includes work
This commit is contained in:
parent
c351139f4d
commit
ad2baf22d2
233
asm/main.c
233
asm/main.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
84
asm/parse.c
84
asm/parse.c
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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
26
kern/arch.asm
Normal 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
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user