diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 208 |
1 files changed, 208 insertions, 0 deletions
@@ -0,0 +1,208 @@ +#define STB_DS_IMPLEMENTATION +#include "stb_ds.h" + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdint.h> +#include <stdbool.h> + +#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'; +} + |