summaryrefslogtreecommitdiff
path: root/lexer.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-09-18 14:49:07 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-09-18 14:49:07 -0400
commiteea04e3327972f052dcfb8ae0854b77f87d3d52f (patch)
treee6c65aad43cb65eb152dc55fba1eb13efffdf7f2 /lexer.c
parent385a621b9487456c3167f204b02cb0ea0752191d (diff)
- Added support for structs, and unions to the
emulator's assembler. - Make the symbol table a doublely linked list, in both ways. - Optimized the memcopy() function. - Changed the benchmark timing, to now use a timer, and stops once the timer reaches zero. When the timer hits zero, it sends SIGALRM to the main function, which tells the emulator that the benchmark is done.
Diffstat (limited to 'lexer.c')
-rw-r--r--lexer.c148
1 files changed, 134 insertions, 14 deletions
diff --git a/lexer.c b/lexer.c
index 2b7c8e7..1c9456e 100644
--- a/lexer.c
+++ b/lexer.c
@@ -9,6 +9,8 @@ symbol *locals = NULL;
symbol *last_loc = NULL;
symbol *cur_sym = NULL;
+line *tmp_line = NULL;
+
symbol *mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t islocal, uint8_t useid, uint16_t id, uint8_t dbg) {
uint16_t i = 0;
symbol *s = (!islocal) ? symbols : locals;
@@ -41,22 +43,40 @@ symbol *mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t islocal, u
}
size_t str_size = strlen(name)+1;
s = malloc(sizeof(symbol));
- s->local = NULL;
+ s->down = NULL;
if (!islocal) {
(last_sym) ? (last_sym->next = s) : (symbols = s);
+ if (last_sym) {
+ last_sym->next->prev = last_sym;
+ last_sym->next->up = last_sym->up;
+ last_sym->next->down = NULL;
+ } else {
+ symbols->prev = NULL;
+ symbols->up = NULL;
+ symbols->down = NULL;
+ }
} else {
(last_loc) ? (last_loc->next = s) : (locals = s);
+ if (last_loc) {
+ last_loc->next->prev = last_loc;
+ last_loc->next->up = last_loc->up;
+ last_loc->next->down = NULL;
+ } else {
+ locals->prev = NULL;
+ locals->down = NULL;
+ }
}
s->name = malloc(str_size);
s->def = def;
s->val = val;
s->count = 0;
+ s->isstruct = 0;
memcpy(s->name, name, str_size);
s->next = NULL;
s->id = sym_count++;
(!islocal) ? (last_sym = s) : (last_loc = s);
if (!islocal) {
- s->local = NULL;
+ s->down = NULL;
/*if (def) {
locals = NULL;
last_loc = NULL;
@@ -95,6 +115,26 @@ symbol *get_sym(const char *name, uint64_t val, token *t, uint8_t islocal, uint8
}
}
+symbol *find_member(char *name, symbol* root, uint8_t dbg) {
+ /*for (; root->up; root = root->up);*/
+ symbol *s = root;
+ if (s->down == NULL && s->up != NULL) {
+ s = s->up;
+ }
+ do {
+ s = s->down;
+ for (symbol *m = s; m; m = m->next) {
+ size_t len1 = strlen(name);
+ size_t len2 = strlen(m->name);
+ if (len1 == len2 && name[0] == m->name[0] && !strcmp(name, m->name)) {
+ return m;
+ }
+ }
+ for (; s->next && !s->down; s = s->next);
+ } while (s->down);
+ return NULL;
+}
+
uint16_t reslv_fixups(uint8_t dbg) {
fixup *f = fixups;
symbol *ls;
@@ -187,6 +227,8 @@ line *find_line(uint32_t ln, uint8_t dbg) {
return l;
}
+uint8_t is_struct = 0;
+
uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
char sym[0x100];
uint16_t i = 0;
@@ -227,6 +269,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
token *st = NULL;
token *t = NULL;
token *lt = NULL;
+ symbol *tmp_sym = NULL;
while (isdigit(str[i]) && isdelm(str[i], dbg) != 16) {
lnum[j++] = str[i++];
@@ -292,19 +335,48 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
switch (ptok) {
case PTOK_DOT:
i++;
- for (; isdelm(str[i+j], dbg) != 16; j++);
+ for (; !(isdelm(str[i+j], dbg) & 17); j++);
memcpy(lexeme, str+i, j);
lexeme[j] = '\0';
i += j;
if (!isop) {
- for (k = 0; k < 7; k++) {
+ for (k = 0; k < 11; k++) {
if (tolower(lexeme[0]) == dir_t[k][0] && !strcasecmp(lexeme, dir_t[k])) {
lex_type = TOK_DIR;
+ is_struct += (k == DIR_STRUCT || k == DIR_UNION);
+ is_struct -= (k == DIR_ENDSTRUCT || k == DIR_ENDUNION);
+ if ((k == DIR_ENDSTRUCT || k == DIR_ENDUNION)) {
+ if (is_struct) {
+ symbol *s = cur_sym;
+ for (; s->prev; s = s->prev) {
+ if (s->up == NULL) {
+ s->up = cur_sym->up;
+ }
+ printf("s: %p, last_loc: %p\n", s, last_loc);
+ }
+ for (s = locals; s; s = s->next) {
+ if (s->up == NULL) {
+ s->up = cur_sym;
+ }
+ }
+ if (cur_sym->down == NULL) {
+ cur_sym->down = locals;
+ }
+ cur_sym = cur_sym->up;
+ for (locals = cur_sym->down; locals->prev; locals = locals->prev);
+ for (last_loc = locals; last_loc->next; last_loc = last_loc->next);
+ }
+ }
break;
}
}
l->count++;
- t = make_token(lex_type, k, space, tab, 0, "", NULL);
+ if (lex_type != TOK_DIR && lt && lt->id == TOK_SYM) {
+ lex_type = TOK_MEMBER;
+ i -= j;
+ } else {
+ t = make_token(lex_type, k, space, tab, 0, "", NULL);
+ }
} else {
lex_type = TOK_RS;
switch (tolower(lexeme[j-1])) {
@@ -535,11 +607,11 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
}
if (!islocal) {
cur_sym = last_sym;
- cur_sym->local = NULL;
locals = NULL;
last_loc = NULL;
- } else if (cur_sym->local == NULL) {
- cur_sym->local = locals;
+ } else if (cur_sym->down == NULL && cur_sym == last_sym) {
+ cur_sym->down = locals;
+ cur_sym->down->up = cur_sym;
}
islocal = 0;
if (dbg) {
@@ -590,7 +662,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
i += j;
isch = 0;
isop = 0;
- if (j == 3 && str[i] != ':') {
+ if (j == 3 && str[i] != ':' && !is_struct) {
for (k = 0; k < OPNUM; k++) {
if (toupper(lexeme[0]) == mne[k][0]) {
if (!strcasecmp(lexeme, mne[k])) {
@@ -616,14 +688,56 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
if (dbg) {
printf("lex(): spaces: %u\n", spaces);
}
- if (str[i+spaces] != ':' && str[i+spaces] != '=') {
- t->sym = get_sym(lexeme, address, t, islocal, dbg);
- islocal = 0;
+ if (is_struct) {
+ islocal = !(is_struct == 1 && lt && lt->id == TOK_DIR);
+ mksymbol(sym, 0, 1, islocal, 0, 0, dbg);
+ if (isfixup) {
+ isfixup = reslv_fixups(dbg);
+ }
+ t->sym = get_sym(sym, 0, t, islocal, dbg);
+ if (lt && lt->id == TOK_DIR) {
+ t->sym->isstruct = 1;
+ t->id = (lt->type == DIR_STRUCT) ? TOK_STRUCT : TOK_UNION;
+ tmp_line = l;
+ } else {
+ t->id = TOK_MEMBER;
+ }
isfixup += (t->sym == NULL);
+ cur_sym = (!islocal && !cur_sym) ? last_sym : cur_sym;
+ if (!islocal) {
+ cur_sym->down = locals;
+ } else {
+ if (lt && lt->id == TOK_DIR) {
+ if (lt->type == DIR_UNION || lt->type == DIR_STRUCT) {
+ cur_sym->down = locals;
+ cur_sym->down->up = cur_sym;
+ last_loc->up = cur_sym;
+ cur_sym = last_loc;
+ locals = NULL;
+ last_loc = NULL;
+ }
+ }
+ }
+ islocal = 0;
+ } else if ((str[i+spaces] != ':' && str[i+spaces] != '=')) {
+ uint8_t sym_struct = 0;
+ symbol *s;
+ /*tmp_sym = (s && s->isstruct) ? NULL : tmp_sym;*/
+ if (tmp_sym) {
+ t->sym = find_member(lexeme, tmp_sym, dbg);
+ tmp_sym = NULL;
+ } else {
+ t->sym = get_sym(lexeme, address, t, islocal, dbg);
+ }
+ isfixup += (t && t->sym == NULL);
+ islocal = 0;
if (dbg) {
printf("lex(): isfixup: %u\n", isfixup);
}
}
+ if (!is_struct && t && t->sym && t->sym->isstruct) {
+ tmp_sym = t->sym;
+ }
}
break;
}
@@ -636,7 +750,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
j = 0;
if (lex_type == TOK_OPCODE && !isop) {
j = 0;
- } else if (lex_type == TOK_EXPR || !isdelm2(str[i], dbg)) {
+ } else if (lex_type == TOK_EXPR || (lex_type != TOK_MEMBER && !isdelm2(str[i], dbg))) {
i++;
}
switch (lex_type) {
@@ -675,7 +789,13 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
tokens = NULL;
last_tok = NULL;
bytecount dummy;
- address = parse_tokens(l->tok, &dummy, 0, address, dbg);
+ if (!is_struct) {
+ l = (tmp_line) ? tmp_line : l;
+ address = parse_tokens(l->tok, &l, &dummy, 0, address, dbg);
+ if (tmp_line) {
+ tmp_line = NULL;
+ }
+ }
if (dbg) {
printf("lex(): Next address: $%"PRIX64"\n", address);
}