diff options
Diffstat (limited to 'lexer.c')
-rw-r--r-- | lexer.c | 148 |
1 files changed, 134 insertions, 14 deletions
@@ -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); } |