Skip to content

Commit d985549

Browse files
pixelherodevNoam Preil
authored andcommitted
Implement explicit imports (closes #44, closes KnightOS/KnightOS#179)
1 parent a6045d4 commit d985549

File tree

7 files changed

+153
-7
lines changed

7 files changed

+153
-7
lines changed

assembler/assembler.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ int try_add_label(struct assembler_state *state, char **line) {
310310
sym->defined_address = state->current_area->data_length;
311311
sym->exported = 1; /* TODO: Support explicit export */
312312
list_add(state->current_area->symbols, sym);
313+
list_add(state->object->imports, sym->name);
313314
scas_log(L_DEBUG, "Added label '%s' (pre-linking value 0x%08X) from %s:%d", sym->name, sym->value,
314315
(char *)stack_peek(state->file_name_stack), *(int *)stack_peek(state->line_number_stack));
315316
/* Modify this line so that processing may continue */
@@ -354,7 +355,19 @@ int try_match_instruction(struct assembler_state *state, char **_line) {
354355
result = evaluate_expression(expression, state->equates, &error, &symbol);
355356
}
356357
if (error == EXPRESSION_BAD_SYMBOL) {
357-
/* TODO: Throw error if using explicit import */
358+
if (scas_runtime.options.explicit_import) {
359+
unresolved_symbol_t *unresolved_sym = malloc(sizeof(unresolved_symbol_t));
360+
unresolved_sym->name = malloc(strlen(symbol)+1);
361+
strcpy(unresolved_sym->name,symbol);
362+
unresolved_sym->column = state->column;
363+
unresolved_sym->line_number = *(int*)stack_peek(state->line_number_stack);
364+
unresolved_sym->line = malloc(strlen(state->line) + 1);
365+
strcpy(unresolved_sym->line,state->line);
366+
const char *file_name = stack_peek(state->file_name_stack);
367+
unresolved_sym->file_name = malloc(sizeof(file_name)+1);
368+
strcpy(unresolved_sym->file_name,file_name);
369+
list_add(state->object->unresolved,unresolved_sym);
370+
}
358371
scas_log(L_DEBUG, "Postponing evaluation of '%s' to linker", ref->value_provided);
359372
late_immediate_t *late_imm = malloc(sizeof(late_immediate_t));
360373
late_imm->instruction_address = state->current_area->data_length;
@@ -569,8 +582,25 @@ object_t *assemble(FILE *file, const char *file_name, assembler_settings_t *sett
569582
fclose(cur);
570583
stack_pop(state.file_stack);
571584
stack_pop(state.source_map_stack);
572-
scas_log(L_INFO, "Returning to file '%s'", (char *)stack_peek(state.file_name_stack));
585+
scas_log(L_INFO, "Returning to file '%s'",
586+
(char *)stack_peek(state.file_name_stack));
573587
} else {
588+
for (int i = 0; i < state.object->unresolved->length; i++) {
589+
unresolved_symbol_t *sym = (unresolved_symbol_t*)
590+
state.object->unresolved->items[i];
591+
bool imported = false;
592+
for (int j = 0; j < state.object->imports->length; j++) {
593+
if (strcmp(sym->name, state.object->imports->items[j]) == 0) {
594+
imported = true;
595+
break;
596+
}
597+
}
598+
if (!imported) {
599+
add_error(state.errors, ERROR_UNKNOWN_SYMBOL,
600+
sym->line_number, sym->line, sym->column,
601+
sym->file_name, sym->name);
602+
}
603+
}
574604
break;
575605
}
576606
}

assembler/directives.c

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "directives.h"
2+
#include "assembler.h"
23
#include "errors.h"
34
#include "functions.h"
45
#include "expression.h"
@@ -22,6 +23,10 @@
2223
*(int*)stack_peek(state->line_number_stack), \
2324
state->line, COLUMN, stack_peek(state->file_name_stack) , ##__VA_ARGS__);
2425

26+
#define WARN(WARN_CODE, COLUMN, ...) add_warning(state->warnings, WARN_CODE, \
27+
*(int*)stack_peek(state->line_number_stack), \
28+
state->line, COLUMN, stack_peek(state->file_name_stack) , ##__VA_ARGS__);
29+
2530
#define MAP_SOURCE(LENGTH) if (!state->expanding_macro && state->auto_source_maps) { \
2631
add_source_map((source_map_t *)stack_peek(state->source_map_stack), \
2732
*(int*)stack_peek(state->line_number_stack), state->line, \
@@ -226,7 +231,27 @@ int handle_db(struct assembler_state *state, char **argv, int argc) {
226231
}
227232

228233
if (error == EXPRESSION_BAD_SYMBOL) {
229-
/* TODO: Throw error if using explicit import */
234+
235+
if (scas_runtime.options.explicit_import) {
236+
tokenized_expression_t *changed_expression = malloc(sizeof(tokenized_expression_t));
237+
memcpy(changed_expression, expression, sizeof(tokenized_expression_t));
238+
int ignored_error;
239+
char *fixed_symbol;
240+
transform_local_labels(changed_expression, state->last_global_label);
241+
evaluate_expression(expression, state->equates, &ignored_error, &fixed_symbol);
242+
unresolved_symbol_t *unresolved_sym = malloc(sizeof(unresolved_symbol_t));
243+
unresolved_sym->name = malloc(strlen(fixed_symbol) + 1);
244+
strcpy(unresolved_sym->name, fixed_symbol);
245+
unresolved_sym->column = state->column;
246+
unresolved_sym->line_number = *(int*)stack_peek(state->line_number_stack);
247+
unresolved_sym->line = malloc(strlen(state->line) + 1);
248+
strcpy(unresolved_sym->line, state->line);
249+
const char *file_name=stack_peek(state->file_name_stack);
250+
unresolved_sym->file_name = malloc(sizeof(file_name) + 1);
251+
strcpy(unresolved_sym->file_name, file_name);
252+
list_add(state->object->unresolved, unresolved_sym);
253+
}
254+
230255
scas_log(L_DEBUG, "Postponing evaluation of '%s' to linker", argv[i]);
231256
late_immediate_t *late_imm = malloc(sizeof(late_immediate_t));
232257
late_imm->address = state->current_area->data_length;
@@ -408,7 +433,26 @@ int handle_dw(struct assembler_state *state, char **argv, int argc) {
408433
}
409434

410435
if (error == EXPRESSION_BAD_SYMBOL) {
411-
/* TODO: Throw error if using explicit import */
436+
if (scas_runtime.options.explicit_import) {
437+
tokenized_expression_t *changed_expression = malloc(sizeof(tokenized_expression_t));
438+
memcpy(changed_expression, expression, sizeof(tokenized_expression_t));
439+
int ignored_error;
440+
char *fixed_symbol;
441+
transform_local_labels(changed_expression, state->last_global_label);
442+
evaluate_expression(expression, state->equates, &ignored_error, &fixed_symbol);
443+
unresolved_symbol_t *unresolved_sym = malloc(sizeof(unresolved_symbol_t));
444+
unresolved_sym->name = malloc(strlen(fixed_symbol) + 1);
445+
strcpy(unresolved_sym->name,fixed_symbol);
446+
unresolved_sym->column = state->column;
447+
unresolved_sym->line_number = *(int*)stack_peek(state->line_number_stack);
448+
unresolved_sym->line = malloc(strlen(state->line) + 1);
449+
strcpy(unresolved_sym->line, state->line);
450+
const char *file_name = stack_peek(state->file_name_stack);
451+
unresolved_sym->file_name = malloc(sizeof(file_name) + 1);
452+
strcpy(unresolved_sym->file_name, file_name);
453+
list_add(state->object->unresolved, unresolved_sym);
454+
}
455+
412456
scas_log(L_DEBUG, "Postponing evaluation of '%s' to linker", argv[i]);
413457
late_immediate_t *late_imm = malloc(sizeof(late_immediate_t));
414458
late_imm->address = state->current_area->data_length;
@@ -750,6 +794,22 @@ int handle_export(struct assembler_state *state, char **argv, int argc) {
750794
return 1;
751795
}
752796

797+
int handle_import(struct assembler_state *state, char **argv, int argc) {
798+
if (!scas_runtime.options.explicit_import) {
799+
WARN(WARNING_NO_EFFECT, state->column,
800+
".import", "explicit_import is not enabled");
801+
}
802+
else {
803+
for (int i = 0; i < argc; ++i) {
804+
scas_log(L_DEBUG, "Importing '%s'",argv[i]);
805+
char *imported = malloc(strlen(argv[i]) + 1);
806+
strcpy(imported, argv[i]);
807+
list_add(state->object->imports, imported);
808+
}
809+
}
810+
return 1;
811+
}
812+
753813
int handle_if(struct assembler_state *state, char **argv, int argc) {
754814
if (state->if_stack->length != 0 && !*(int *)stack_peek(state->if_stack)) {
755815
/* Push up another falsy if if we're already in a falsy if */
@@ -971,7 +1031,10 @@ int handle_list(struct assembler_state *state, char **argv, int argc) {
9711031
int handle_map(struct assembler_state *state, char **argv, int argc) {
9721032
// .map filename, lineno, code
9731033
free(((source_map_t *)stack_peek(state->source_map_stack))->file_name);
974-
((source_map_t*)stack_peek(state->source_map_stack))->file_name = strdup(argv[0]);
1034+
((source_map_t*)stack_peek(state->source_map_stack))->file_name =
1035+
malloc(strlen(argv[0]) + 1);
1036+
strcpy(((source_map_t*)stack_peek(state->source_map_stack))->file_name,
1037+
argv[0]);
9751038
add_source_map((source_map_t *)stack_peek(state->source_map_stack),
9761039
atoi(argv[1]), argv[2], state->PC, 1); // TODO: figure out actual length
9771040
return 1;
@@ -1123,7 +1186,7 @@ struct directive directives[] = {
11231186
{ "if", handle_if, 0 },
11241187
{ "ifdef", handle_ifdef, 0 },
11251188
{ "ifndef", handle_ifndef, 0 },
1126-
{ "import", handle_nop, DELIM_COMMAS | DELIM_WHITESPACE }, /* TODO */
1189+
{ "import", handle_import, DELIM_COMMAS | DELIM_WHITESPACE },
11271190
{ "incbin", handle_incbin, DELIM_COMMAS | DELIM_WHITESPACE },
11281191
{ "include", handle_include, DELIM_COMMAS | DELIM_WHITESPACE },
11291192
{ "lclequ", handle_equ, DELIM_COMMAS | DELIM_WHITESPACE },

common/errors.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const char *get_error_string(error_t *error) {
3232

3333
const char *get_warning_string(warning_t *warning) {
3434
switch (warning->code) {
35+
case WARNING_NO_EFFECT:
36+
return "'%s' has no effect %s";
3537
default:
3638
return NULL;
3739
}
@@ -67,6 +69,36 @@ void add_error(list_t *errors, int code, size_t line_number, const char *line,
6769
line_number, column);
6870
}
6971

72+
void add_warning(list_t *warnings, int code, size_t line_number,
73+
const char *line, int column, const char *file_name, ...) {
74+
warning_t *warning = malloc(sizeof(warning_t));
75+
warning->code = code;
76+
warning->line_number = line_number;
77+
warning->file_name = malloc(strlen(file_name) + 1);
78+
strcpy(warning->file_name, file_name);
79+
warning->line = malloc(strlen(line) + 1);
80+
strcpy(warning->line, line);
81+
warning->column = column;
82+
83+
const char *fmt = get_warning_string(warning);
84+
85+
va_list args;
86+
va_start(args, file_name);
87+
int len = vsnprintf(NULL, 0, fmt, args);
88+
va_end(args);
89+
90+
char *buf = malloc(len + 1);
91+
va_start(args, file_name);
92+
vsnprintf(buf, len + 1, fmt, args);
93+
va_end(args);
94+
95+
warning->message = buf;
96+
97+
list_add(warnings, warning);
98+
scas_log(L_ERROR, "Added warning '%s' at %s:%d:%d", buf, file_name,
99+
line_number, column);
100+
}
101+
70102
/* Locates the address in the source maps provided to get the file name and line number */
71103
void add_error_from_map(list_t *errors, int code, list_t *maps, uint64_t address, ...) {
72104
source_map_t *map;

common/objects.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@ object_t *create_object() {
1414
object_t *o = malloc(sizeof(object_t));
1515
o->areas = create_list();
1616
o->exports = create_list();
17+
o->imports = create_list();
18+
o->unresolved = create_list();
1719
return o;
1820
}
1921

2022
void object_free(object_t *o) {
2123
list_free(o->areas);
24+
list_free(o->unresolved);
25+
list_free(o->imports);
2226
}
2327

2428
area_t *create_area(const char *name) {

include/assembler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,6 @@ struct assembler_state {
4848
};
4949

5050
object_t *assemble(FILE *file, const char *file_name, assembler_settings_t *settings);
51-
51+
void transform_local_labels(tokenized_expression_t *expression, const char *last_global_label);
52+
5253
#endif

include/errors.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ enum {
1515
ERROR_DUPLICATE_SYMBOL,
1616
};
1717

18+
enum {
19+
WARNING_NO_EFFECT = 1,
20+
};
21+
1822
typedef struct {
1923
int code;
2024
size_t line_number;
@@ -39,5 +43,7 @@ void add_error(list_t *errors, int code, size_t line_number, const char *line,
3943
int column, const char *file_name, ...);
4044
void add_error_from_map(list_t *errors, int code, list_t *maps, uint64_t
4145
address, ...);
46+
void add_warning(list_t *warnings, int code, size_t line_number,
47+
const char *line, int column, const char *file_name, ...);
4248

4349
#endif

include/objects.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ typedef struct {
2525
int exported;
2626
} symbol_t;
2727

28+
typedef struct {
29+
char *name;
30+
size_t line_number;
31+
char *line;
32+
int column;
33+
char *file_name;
34+
} unresolved_symbol_t;
35+
2836
typedef struct {
2937
tokenized_expression_t *expression;
3038
uint64_t width;
@@ -63,6 +71,8 @@ typedef struct {
6371
list_t *areas;
6472
/* Only used for assembly */
6573
list_t *exports;
74+
list_t *imports;
75+
list_t *unresolved;
6676
} object_t;
6777

6878
object_t *create_object();

0 commit comments

Comments
 (0)