#define STB_DS_IMPLEMENTATION #include "stb_ds.h" #include #include #include #include #include #define STREQ(s1, s2) (strcmp((s1), (s2)) == 0) #define STRMT(s) ((s)[0] == '\0') #define LINE_LEN 100 typedef struct { char lab[10]; char opc[4]; char opr[10]; bool ind; int psu; } token_t; token_t tokenize(char *); int split(char *, char [4][10]); void extfname(char *, char *); int main(int argc, char** argv) { struct { char *key; uint16_t value; } *hopc = NULL; struct { char *key; uint16_t value; } *hlab = NULL; struct { uint8_t key; uint16_t value; } *hopr = NULL; token_t tkn; FILE *inpf, *outf; char *lines, *tlines; char line[LINE_LEN], opc[4], out[10], ofname[10]; uint16_t lc, ins, addr; uint8_t opr, i; bool unknown, end; if (argc < 2) { puts("no input file"); return 1; } sh_new_strdup(hopc); sh_new_strdup(hlab); shdefault(hopc, -1); shdefault(hlab, -1); inpf = fopen("opcodes", "r"); for (i = 25; i > 0; --i) { fscanf(inpf, "%s %x", opc, &addr); shput(hopc, opc, addr); } lines = (char *)malloc(LINE_LEN*100*sizeof(char)); inpf = fopen(argv[1], "r"); lc = 0, opr = 0, end = false; while (fgets(line, LINE_LEN, inpf) != NULL) { tkn = tokenize(line); if (STRMT(tkn.opc) && tkn.psu == 0) continue; if (!STRMT(tkn.lab)) { hmput(hopr, shget(hlab, tkn.lab), lc); shput(hlab, tkn.lab, lc); } switch (tkn.psu) { case 1: lc = strtol(tkn.opr, NULL, 16); continue; case 2: ins = strtol(tkn.opr, NULL, 10); break; case 3: ins = strtol(tkn.opr, NULL, 16); break; case 4: end = true; } if (end) break; if (!STRMT(tkn.opc)) { ins = shget(hopc, tkn.opc); if (tkn.ind) ins += 8; if (!STRMT(tkn.opr)) { ins = ins << 12; addr = shget(hlab, tkn.opr); if (addr == 0xffff) { unknown = true; addr = opr; shput(hlab, tkn.opr, opr++); } ins = ins | addr; } } sprintf(out, "%03x %04x\n", lc, ins); if (unknown) { out[5] = '?'; unknown = false; } strcat(lines, out); lc++; } fclose(inpf); shfree(hopc); shfree(hlab); tlines = lines; while ((tlines = strchr(tlines, '?')) != NULL) { opr = strtol(++tlines, NULL, 16); addr = hmget(hopr, opr); sprintf(out, "%03x", addr); strncpy(--tlines, out, 3); } puts(lines); extfname(argv[1], ofname); outf = fopen(ofname, "w"); fputs(lines, outf); fclose(outf); hmfree(hopr); free(lines); return 0; } token_t tokenize(char *start) { const char pseudo[][4] = { "ORG", "DEC", "HEX", "END" }; token_t tkn = { '\0', '\0', '\0', false, 0 }; char parts[4][10]; int n, pi = 0, i; n = split(start, parts); if (n == 0) return tkn; if (parts[0][strlen(parts[0])-1] == ',') { parts[0][strlen(parts[0])-1] = '\0'; strcpy(tkn.lab, parts[0]); pi++; n--; if (n <= 0) return tkn; } for (i = 3; i >= 0; --i) { if (STREQ(parts[pi], pseudo[i])) { tkn.psu = i + 1; pi++; if (n-- > 0) strcpy(tkn.opr, parts[pi]); return tkn; } } if (parts[pi][0] != '\0') { strcpy(tkn.opc, parts[pi++]); n--; if (n > 0) { strcpy(tkn.opr, parts[pi++]); n--; } } if (STREQ(parts[pi], "I")) if (n-- > 0) tkn.ind = true; return tkn; } int split(char *start, char list[4][10]) { int si = 0, wi = 0, li = 0; char c; do { c = start[si++]; if (c == '\n' || c == '/') { if (wi) list[li++][wi] = '\0'; break; } if (c == ' ' || c == '\t') { if (wi) { list[li++][wi] = '\0'; wi = 0; } continue; } list[li][wi++] = c; } while (c != '\0'); return li; } void extfname(char *path, char *fname) { int si = 0, i; char c; for (i = 0; path[i] != '\0'; ++i) { c = path[i]; fname[si++] = c; if (c == '/') si = 0; if (c == '.') { si--; break; } } fname[si] = '\0'; }