includes work

This commit is contained in:
sfja 2025-04-02 20:46:35 +02:00
parent c351139f4d
commit ad2baf22d2
7 changed files with 282 additions and 111 deletions

View File

@ -6,53 +6,27 @@
#include "str.h"
#include <assert.h>
#include <errno.h>
#include <libgen.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static inline int define_labels(
IdentResolver* resolver, PLabel* label, uint16_t asm_ip, Reporter* rep)
{
if (label == NULL)
return 0;
int res = define_labels(resolver, label->next, asm_ip, rep);
const IdentResol* existing = ident_resolver_resolve(resolver, label->ident);
if (existing != NULL) {
REPORTF_ERROR("redefinition of identifier '%s'", label->ident);
reporter_print_loc(rep, label->loc);
REPORTF_INFO("original definition of '%s'", label->ident);
reporter_print_loc(rep, existing->loc);
return 1;
}
if (label->sub_label) {
ident_resolver_define_sublabel(
resolver, asm_strdup(label->ident), label->loc, asm_ip);
} else {
ident_resolver_define_label(
resolver, asm_strdup(label->ident), label->loc, asm_ip);
}
return res;
}
static inline void use_labels(IdentResolver* resolver, PLabel* label)
{
if (label == NULL)
return;
use_labels(resolver, label->next);
const IdentResol* existing = ident_resolver_resolve(resolver, label->ident);
if (existing->ty == IdentResolTy_Label) {
resolver->current_parent = existing;
}
}
typedef struct {
const char* input_file;
const char* output_file;
} Args;
static inline Args parse_args(int argc, char** argv);
static inline char* read_text_file(const char* filename);
static inline int include_file(IdentResolver* resolver,
OperandEvaluator* evaluator,
const char* origin,
const char* filename);
static inline int define_labels(
IdentResolver* resolver, PLabel* label, uint16_t asm_ip, Reporter* rep);
static inline void use_labels(IdentResolver* resolver, PLabel* label);
int main(int argc, char** argv)
{
@ -60,26 +34,7 @@ int main(int argc, char** argv)
Args args = parse_args(argc, argv);
FILE* input_fp = fopen(args.input_file, "r");
if (!input_fp) {
REPORTF_ERROR("could not open input file '%s': %s",
args.input_file,
strerror(errno));
return -1;
}
fseek(input_fp, 0L, SEEK_END);
size_t file_size = (size_t)ftell(input_fp);
rewind(input_fp);
char* input_text = calloc(file_size + 1, sizeof(char));
size_t bytes_read = fread(input_text, sizeof(char), file_size, input_fp);
fclose(input_fp);
if (bytes_read != file_size) {
REPORTF_ERROR("could not read input file '%s': %s",
args.input_file,
strerror(errno));
return -1;
}
char* input_text = read_text_file(args.input_file);
bool errors_occured = false;
@ -132,6 +87,7 @@ int main(int argc, char** argv)
if (existing != NULL) {
REPORTF_ERROR("redefinition of constant '%s'", stmt->ident);
reporter_print_loc(&rep, stmt->loc);
errors_occured = true;
pstmt_free(stmt);
continue;
}
@ -139,13 +95,26 @@ int main(int argc, char** argv)
= eval_operand_to_imm(&evaluator, stmt->value);
if (evaled.ty == EoTy_Err) {
pstmt_free(stmt);
errors_occured = true;
continue;
}
ident_resolver_define_const(
&resolver, asm_strdup(stmt->ident), stmt->loc, evaled.imm);
ident_resolver_define_const(&resolver,
asm_strdup(stmt->ident),
stmt->loc,
evaled.imm,
asm_strdup(args.input_file));
pstmt_free(stmt);
break;
}
case PStmtTy_Include: {
int include_res = include_file(
&resolver, &evaluator, args.input_file, stmt->str);
pstmt_free(stmt);
if (include_res != 0) {
errors_occured = true;
}
break;
}
}
}
@ -257,3 +226,153 @@ static inline Args parse_args(int argc, char** argv)
output_file,
};
}
static inline int include_file(IdentResolver* resolver,
OperandEvaluator* evaluator,
const char* origin_filename,
const char* include_filename)
{
char* origin_dir_buf = asm_strdup(origin_filename);
const char* origin_dir = dirname(origin_dir_buf);
char* filepath = calloc(
strlen(origin_dir) + strlen(include_filename) + 2, sizeof(char));
strcat(filepath, origin_dir);
free(origin_dir_buf);
strcat(filepath, "/");
strcat(filepath, include_filename);
char* text = read_text_file(filepath);
if (!text)
return -1;
Parser parser;
parser_construct(&parser, filepath, text);
Reporter rep = {
.filename = parser.lexer.filename,
.text = parser.lexer.text,
.text_len = parser.lexer.text_len,
};
bool errors_occured = false;
while (!parser_done(&parser)) {
PStmt* stmt = parser_next_stmt(&parser);
if (!stmt) {
continue;
}
switch (stmt->ty) {
case PStmtTy_Const: {
const IdentResol* existing
= ident_resolver_resolve(resolver, stmt->ident);
if (existing != NULL) {
REPORTF_ERROR("redefinition of constant '%s'", stmt->ident);
reporter_print_loc(&rep, stmt->loc);
errors_occured = true;
pstmt_free(stmt);
continue;
}
EvaledOperand evaled
= eval_operand_to_imm(evaluator, stmt->value);
if (evaled.ty == EoTy_Err) {
pstmt_free(stmt);
errors_occured = true;
continue;
}
ident_resolver_define_const(resolver,
asm_strdup(stmt->ident),
stmt->loc,
evaled.imm,
asm_strdup(filepath));
break;
}
case PStmtTy_Include: {
int include_res
= include_file(resolver, evaluator, filepath, stmt->str);
pstmt_free(stmt);
if (include_res != 0) {
errors_occured = true;
}
break;
}
default:
break;
}
pstmt_free(stmt);
}
errors_occured &= parser_error_occured(&parser);
free(filepath);
free(text);
return errors_occured;
}
static inline char* read_text_file(const char* filename)
{
FILE* fp = fopen(filename, "r");
if (!fp) {
REPORTF_ERROR("could not open file '%s' for reading: %s",
filename,
strerror(errno));
return NULL;
}
fseek(fp, 0L, SEEK_END);
size_t file_size = (size_t)ftell(fp);
rewind(fp);
char* text = calloc(file_size + 1, sizeof(char));
size_t bytes_read = fread(text, sizeof(char), file_size, fp);
fclose(fp);
if (bytes_read != file_size) {
REPORTF_ERROR(
"could not read input file '%s': %s", filename, strerror(errno));
return NULL;
}
return text;
}
static inline int define_labels(
IdentResolver* resolver, PLabel* label, uint16_t asm_ip, Reporter* rep)
{
if (label == NULL)
return 0;
int res = define_labels(resolver, label->next, asm_ip, rep);
const IdentResol* existing = ident_resolver_resolve(resolver, label->ident);
if (existing != NULL) {
REPORTF_ERROR("redefinition of identifier '%s'", label->ident);
reporter_print_loc(rep, label->loc);
const char* filename = rep->filename;
if (existing->ty == IdentResolTy_Const) {
rep->filename = existing->src_filename;
}
REPORTF_INFO("original definition of '%s'", existing->ident);
reporter_print_loc(rep, existing->loc);
rep->filename = filename;
return 1;
}
if (label->sub_label) {
ident_resolver_define_sublabel(
resolver, asm_strdup(label->ident), label->loc, asm_ip);
} else {
ident_resolver_define_label(
resolver, asm_strdup(label->ident), label->loc, asm_ip);
}
return res;
}
static inline void use_labels(IdentResolver* resolver, PLabel* label)
{
if (label == NULL)
return;
use_labels(resolver, label->next);
const IdentResol* existing = ident_resolver_resolve(resolver, label->ident);
if (existing->ty == IdentResolTy_Label) {
resolver->current_parent = existing;
}
}

View File

@ -139,6 +139,7 @@ PStmt* pstmt_new_ident(PStmtTy ty, Loc loc, char* ident)
*stmt = (PStmt) { .ty = ty, .loc = loc, .ident = ident, .value = NULL };
return stmt;
}
PStmt* pstmt_new_const(PStmtTy ty, Loc loc, char* ident, POperand* value)
{
PStmt* stmt = malloc(sizeof(PStmt));
@ -146,6 +147,13 @@ PStmt* pstmt_new_const(PStmtTy ty, Loc loc, char* ident, POperand* value)
return stmt;
}
PStmt* pstmt_new_include(Loc loc, char* str)
{
PStmt* stmt = malloc(sizeof(PStmt));
*stmt = (PStmt) { .ty = PStmtTy_Include, .loc = loc, .str = str };
return stmt;
}
void pstmt_free(PStmt* stmt)
{
switch (stmt->ty) {
@ -160,6 +168,9 @@ void pstmt_free(PStmt* stmt)
free(stmt->ident);
poperand_free(stmt->value);
break;
case PStmtTy_Include:
free(stmt->str);
break;
}
free(stmt);
}
@ -212,6 +223,38 @@ static inline char* parser_text_val(const Parser* parser, Tok tok)
return asm_strndup(&parser->lexer.text[tok.loc.idx], tok.len);
}
static inline char literal_char_val(const char* str)
{
if (str[0] == '\\') {
switch (str[1]) {
case '0':
return 0;
case 't':
return '\t';
case 'n':
return '\n';
default:
return str[1];
}
} else {
return str[0];
}
}
static inline char* parser_str_val(
const Parser* parser, size_t* str_len, Tok tok)
{
char* lit = parser_text_val(parser, tok);
char* str = calloc(tok.len - 1, sizeof(char));
*str_len = 0;
for (size_t i = 1; i < tok.len - 1; ++i) {
str[*str_len] = literal_char_val(&lit[i]);
*str_len += 1;
}
free(lit);
return str;
}
static inline void parser_report(Parser* parser, const char* msg, Loc loc)
{
parser->error_occured = true;
@ -267,24 +310,6 @@ static inline PLabel* parser_parse_labels(
return labels;
}
static inline char literal_char_val(const char* str)
{
if (str[0] == '\\') {
switch (str[1]) {
case '0':
return 0;
case 't':
return '\t';
case 'n':
return '\n';
default:
return str[1];
}
} else {
return str[0];
}
}
static const int parser_binary_prec = 6;
static inline POperand* parser_parse_operand_2(Parser* parser, int prec);
@ -346,14 +371,8 @@ static inline POperand* parser_parse_operand_0(Parser* parser)
free(str);
return poperand_new_imm(imm, loc);
} else if (parser_eat(parser, TT_Str)) {
char* lit = parser_text_val(parser, parser->eaten);
size_t lit_len = strlen(lit);
char* str = calloc(lit_len - 1, sizeof(char));
size_t str_len = 0;
for (size_t i = 1; i < lit_len - 2; ++i) {
str[i] = literal_char_val(&lit[i]);
}
free(lit);
size_t str_len;
char* str = parser_str_val(parser, &str_len, parser->eaten);
return poperand_new_str(PoTy_Str, str, str_len, loc);
} else if (parser_eat(parser, '.')) {
if (!parser_eat(parser, TT_Ident)) {
@ -559,11 +578,13 @@ static inline PStmtTy pstmt_keyword_ty(const char* ident)
PStmtTy_Global,
PStmtTy_Extern,
PStmtTy_Const,
PStmtTy_Include,
};
const char* keywords[] = {
"global",
"extern",
"const",
"include",
};
static_assert(
sizeof(keywords) / sizeof(keywords[0]) == sizeof(tys) / sizeof(tys[0]),
@ -608,6 +629,17 @@ PStmt* parser_next_stmt(Parser* parser)
return pstmt_new_const(ty, loc, ident, value);
break;
}
case PStmtTy_Include: {
parser_step(parser);
if (!parser_eat(parser, TT_Str)) {
parser_report(parser, "expected string", parser->tok.loc);
return NULL;
}
size_t str_len;
char* str = parser_str_val(parser, &str_len, parser->eaten);
return pstmt_new_include(loc, str);
break;
}
default:
break;
}

View File

@ -85,6 +85,7 @@ typedef enum {
PStmtTy_Global,
PStmtTy_Extern,
PStmtTy_Const,
PStmtTy_Include,
} PStmtTy;
typedef struct {
@ -96,12 +97,14 @@ typedef struct {
char* ident;
POperand* value;
};
char* str;
};
} PStmt;
PStmt* pstmt_new_line(Loc loc, PLine* line);
PStmt* pstmt_new_ident(PStmtTy ty, Loc loc, char* ident);
PStmt* pstmt_new_const(PStmtTy ty, Loc loc, char* ident, POperand* value);
PStmt* pstmt_new_include(Loc loc, char* str);
void pstmt_free(PStmt* stmt);
typedef struct {

View File

@ -9,8 +9,11 @@ void ident_resol_destroy(IdentResol* resol)
break;
case IdentResolTy_Label:
case IdentResolTy_SubLabel:
free(resol->ident);
break;
case IdentResolTy_Const:
free(resol->ident);
free(resol->src_filename);
break;
}
}
@ -78,8 +81,11 @@ void ident_resolver_define_sublabel(
};
}
void ident_resolver_define_const(
IdentResolver* resolver, char* ident, Loc loc, uint16_t value)
void ident_resolver_define_const(IdentResolver* resolver,
char* ident,
Loc loc,
uint16_t value,
char* src_filename)
{
size_t i = ident_resolver_first_empty(resolver);
resolver->resols[i] = (IdentResol) {
@ -87,6 +93,7 @@ void ident_resolver_define_const(
.loc = loc,
.ty = IdentResolTy_Const,
.value = value,
.src_filename = src_filename,
};
}

View File

@ -18,7 +18,10 @@ struct IdentResol {
IdentResolTy ty;
union {
uint16_t ip;
struct {
uint16_t value;
char* src_filename;
};
};
};
@ -38,7 +41,10 @@ void ident_resolver_define_label(
IdentResolver* resolver, char* ident, Loc loc, uint16_t asm_ip);
void ident_resolver_define_sublabel(
IdentResolver* resolver, char* ident, Loc loc, uint16_t asm_ip);
void ident_resolver_define_const(
IdentResolver* resolver, char* ident, Loc loc, uint16_t value);
void ident_resolver_define_const(IdentResolver* resolver,
char* ident,
Loc loc,
uint16_t value,
char* src_filename);
const IdentResol* ident_resolver_resolve(
const IdentResolver* resolver, const char* ident);

26
kern/arch.asm Normal file
View File

@ -0,0 +1,26 @@
const Fl_Zero 0
const Fl_Eq 1
const Fl_Be 2
const Fl_Lt 3
const Fl_Err 4
const Fl_Int 5
const Fl_Vcd 6
const Int_DiskRead 0
const Int_DiskWrite 1
const Int_Key 32
const Device_Keyboard 0
const vcd_ch_width 8
const vcd_ch_height 8
const vcd_width_in_ch 40
const vcd_height_in_ch 12
const vcd_px_width 4
const vcd_px_height 8
const vcd_width_in_px vcd_width_in_ch * vcd_ch_width * vcd_px_width
const vcd_height_in_px vcd_height_in_ch * vcd_ch_height * vcd_px_height
; vim: syntax=nasm

View File

@ -1,27 +1,5 @@
const Fl_Zero 0
const Fl_Eq 1
const Fl_Be 2
const Fl_Lt 3
const Fl_Err 4
const Fl_Int 5
const Fl_Vcd 6
const Int_DiskRead 0
const Int_DiskWrite 1
const Int_Key 32
const Device_Keyboard 0
const vcd_ch_width 8
const vcd_ch_height 8
const vcd_width_in_ch 40
const vcd_height_in_ch 12
const vcd_px_width 4
const vcd_px_height 8
const vcd_width_in_px vcd_width_in_ch * vcd_ch_width * vcd_px_width
const vcd_height_in_px vcd_height_in_ch * vcd_ch_height * vcd_px_height
include "arch.asm"
start:
; rsp points *at* the top element