summaryrefslogtreecommitdiff
path: root/lexer.c
diff options
context:
space:
mode:
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);
}