From 36595fd27d06b03f1abf320bd511aec325845ed5 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 10 Jan 2014 03:32:06 +0200 Subject: [PATCH] more work on cvt_data, works mostly --- tools/cvt_data.c | 185 +++++++++++++++++++++++++++++++++++++++------ tools/mkbridge.c | 4 +- tools/protoparse.h | 20 ++++- tools/translate.c | 10 +-- 4 files changed, 184 insertions(+), 35 deletions(-) diff --git a/tools/cvt_data.c b/tools/cvt_data.c index 32166f8..6bb2730 100644 --- a/tools/cvt_data.c +++ b/tools/cvt_data.c @@ -14,8 +14,8 @@ static const char *asmfn; static int asmln; -static FILE *g_fhdr; +// note: must be in ascending order enum dx_type { DXT_UNSPEC, DXT_BYTE, @@ -25,6 +25,8 @@ enum dx_type { DXT_TEN, }; +#define anote(fmt, ...) \ + printf("%s:%d: note: " fmt, asmfn, asmln, ##__VA_ARGS__) #define aerr(fmt, ...) do { \ printf("%s:%d: error: " fmt, asmfn, asmln, ##__VA_ARGS__); \ fcloseall(); \ @@ -136,6 +138,21 @@ static const char *type_name(enum dx_type type) return ""; } +static const char *type_name_float(enum dx_type type) +{ + switch (type) { + case DXT_DWORD: + return ".float"; + case DXT_QUAD: + return ".double"; + case DXT_TEN: + return ".tfloat"; + default: + break; + } + return ""; +} + static int type_size(enum dx_type type) { switch (type) { @@ -177,11 +194,61 @@ static char *escape_string(char *s) return strcpy(s, buf); } +static void check_sym(FILE *fhdr, const char *name) +{ + const struct parsed_proto *pp; + char buf[256]; + int i, l; + + pp = proto_parse(fhdr, name, 1); + if (pp == NULL) { + if (IS_START(name, "sub_")) + aerr("sub_ sym missing proto: '%s'\n", name); + return; + } + + if (!pp->is_func && !pp->is_fptr) + return; + if (pp->argc_reg == 0) + return; + if (pp->argc_reg == 1 && pp->argc_stack == 0 + && IS(pp->arg[0].reg, "ecx")) + { + return; + } + if (pp->argc_reg == 2 + && IS(pp->arg[0].reg, "ecx") + && IS(pp->arg[1].reg, "edx")) + { + return; + } + snprintf(buf, sizeof(buf), "%s %s(", + pp->ret_type.name, name); + l = strlen(buf); + + for (i = 0; i < pp->argc_reg; i++) { + snprintf(buf + l, sizeof(buf) - l, "%s%s", + i == 0 ? "" : ", ", pp->arg[i].reg); + l = strlen(buf); + } + if (pp->argc_stack > 0) { + snprintf(buf + l, sizeof(buf) - l, ", {%d stack}", pp->argc_stack); + l = strlen(buf); + } + snprintf(buf + l, sizeof(buf) - l, ")"); + + aerr("unhandled reg call: %s\n", buf); +} + +static int cmpstringp(const void *p1, const void *p2) +{ + return strcmp(*(char * const *)p1, *(char * const *)p2); +} + int main(int argc, char *argv[]) { - FILE *fout, *fasm; + FILE *fout, *fasm, *fhdr, *frlist; char words[20][256]; - //int sep_after[20]; char word[256]; char line[256]; char comment[256]; @@ -189,18 +256,25 @@ int main(int argc, char *argv[]) unsigned long cnt; const char *sym; enum dx_type type; + char **pub_syms; + int pub_sym_cnt = 0; + int pub_sym_alloc; + char **rlist; + int rlist_cnt = 0; + int rlist_alloc; int is_label; + int is_bss; int wordc; int first; int arg_out; int arg = 1; int len; - int w; + int w, i; char *p; char *p2; - if (argc != 4) { - printf("usage:\n%s <.s> <.asm> \n", + if (argc < 4) { + printf("usage:\n%s <.s> <.asm> [rlist]*\n", argv[0]); return 1; } @@ -212,16 +286,54 @@ int main(int argc, char *argv[]) my_assert_not(fasm, NULL); hdrfn = argv[arg++]; - g_fhdr = fopen(hdrfn, "r"); - my_assert_not(g_fhdr, NULL); + fhdr = fopen(hdrfn, "r"); + my_assert_not(fhdr, NULL); fout = fopen(argv[arg_out], "w"); my_assert_not(fout, NULL); comment[0] = 0; - while (!feof(fasm)) { + pub_sym_alloc = 64; + pub_syms = malloc(pub_sym_alloc * sizeof(pub_syms[0])); + my_assert_not(pub_syms, NULL); + + rlist_alloc = 64; + rlist = malloc(rlist_alloc * sizeof(rlist[0])); + my_assert_not(rlist, NULL); + + for (; arg < argc; arg++) { + frlist = fopen(argv[arg], "r"); + my_assert_not(frlist, NULL); + + while (fgets(line, sizeof(line), frlist)) { + p = sskip(line); + if (*p == 0 || *p == ';') + continue; + + p = next_word(words[0], sizeof(words[0]), p); + if (words[0][0] == 0) + continue; + + if (rlist_cnt >= rlist_alloc) { + rlist_alloc = rlist_alloc * 2 + 64; + rlist = realloc(rlist, rlist_alloc * sizeof(rlist[0])); + my_assert_not(rlist, NULL); + } + rlist[rlist_cnt++] = strdup(words[0]); + } + + fclose(frlist); + frlist = NULL; + } + + if (rlist_cnt > 0) + qsort(rlist, rlist_cnt, sizeof(rlist[0]), cmpstringp); + + while (1) { next_section(fasm, line); + if (feof(fasm)) + break; if (IS(line + 1, "text")) continue; @@ -244,20 +356,20 @@ int main(int argc, char *argv[]) continue; for (wordc = 0; wordc < ARRAY_SIZE(words); wordc++) { - //sep_after[wordc] = 0; p = sskip(next_word_s(words[wordc], sizeof(words[0]), p)); if (*p == 0 || *p == ';') { wordc++; break; } if (*p == ',') { - //sep_after[wordc] = 1; p = sskip(p + 1); } } if (wordc == 2 && IS(words[1], "ends")) break; + if (wordc <= 2 && IS(words[0], "end")) + break; if (wordc < 2) aerr("unhandled: '%s'\n", words[0]); @@ -282,6 +394,14 @@ int main(int argc, char *argv[]) aerr("unhandled decl: '%s %s'\n", words[0], words[1]); if (sym != NULL) { + // public/global name + if (pub_sym_cnt >= pub_sym_alloc) { + pub_sym_alloc *= 2; + pub_syms = realloc(pub_syms, pub_sym_alloc * sizeof(pub_syms[0])); + my_assert_not(pub_syms, NULL); + } + pub_syms[pub_sym_cnt++] = strdup(sym); + len = strlen(sym); fprintf(fout, "_%s:", sym); @@ -338,7 +458,10 @@ int main(int argc, char *argv[]) aerr("bad dup?\n"); memmove(word, p, p2 - p); word[p2 - p] = 0; - val = parse_number(word); + + val = 0; + if (!IS(word, "?")) + val = parse_number(word); fprintf(fout, ".fill 0x%02lx,%d,0x%02lx", cnt, type_size(type), val); @@ -359,14 +482,12 @@ int main(int argc, char *argv[]) goto fin; } - if ((type == DXT_QUAD || type == DXT_TEN) - && strchr(words[w], '.')) + if (type >= DXT_DWORD && strchr(words[w], '.')) { if (w != wordc - 1) aerr("TODO\n"); - fprintf(fout, type == DXT_TEN ? ".tfloat " : ".double "); - fprintf(fout, "%s", words[w]); + fprintf(fout, "%s %s", type_name_float(type), words[w]); goto fin; } @@ -377,11 +498,14 @@ int main(int argc, char *argv[]) if (!first) fprintf(fout, ", "); - is_label = 0; - if (w >= wordc - 2 && IS(words[w], "offset")) { + is_label = is_bss = 0; + if (w <= wordc - 2 && IS(words[w], "offset")) { is_label = 1; w++; } + else if (IS(words[w], "?")) { + is_bss = 1; + } else if (type == DXT_DWORD && !('0' <= words[w][0] && words[w][0] <= '9')) { @@ -389,15 +513,22 @@ int main(int argc, char *argv[]) is_label = 1; } - if (is_label) { + if (is_bss) { + fprintf(fout, "0"); + } + else if (is_label) { p = words[w]; - if (IS_START(p, "loc_") || strchr(p, '?') || strchr(p, '@')) + if (IS_START(p, "loc_") || strchr(p, '?') || strchr(p, '@') + || bsearch(&p, rlist, rlist_cnt, sizeof(rlist[0]), + cmpstringp)) { fprintf(fout, "0"); - snprintf(comment, sizeof(comment), "%s", words[w + 1]); - goto fin; + snprintf(comment, sizeof(comment), "%s", p); + } + else { + check_sym(fhdr, p); + fprintf(fout, "_%s", p); } - fprintf(fout, "_%s", p); } else { val = parse_number(words[w]); @@ -420,9 +551,15 @@ fin: } } + fprintf(fout, "\n"); + + // dump public syms + for (i = 0; i < pub_sym_cnt; i++) + fprintf(fout, ".global _%s\n", pub_syms[i]); + fclose(fout); fclose(fasm); - fclose(g_fhdr); + fclose(fhdr); return 0; } diff --git a/tools/mkbridge.c b/tools/mkbridge.c index 4b3a458..705567f 100644 --- a/tools/mkbridge.c +++ b/tools/mkbridge.c @@ -230,7 +230,7 @@ int main(int argc, char *argv[]) if (p != NULL) *p = 0; - pp = proto_parse(fhdr, sym_noat); + pp = proto_parse(fhdr, sym_noat, 0); if (pp == NULL) goto out; @@ -245,7 +245,7 @@ int main(int argc, char *argv[]) if (sym[0] == 0 || sym[0] == ';' || sym[0] == '#') continue; - pp = proto_parse(fhdr, sym); + pp = proto_parse(fhdr, sym, 0); if (pp == NULL) goto out; diff --git a/tools/protoparse.h b/tools/protoparse.h index b49c216..d9f6ef8 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -46,6 +46,8 @@ static int do_protostrs(FILE *fhdr, const char *fname) const char *finc_name; const char *hdrfn_saved; char protostr[256]; + char path[256]; + char fname_inc[256]; FILE *finc; int line = 0; int ret; @@ -63,10 +65,19 @@ static int do_protostrs(FILE *fhdr, const char *fname) if (p != NULL) *p = 0; - finc = fopen(finc_name, "r"); + path[0] = 0; + p = strrchr(hdrfn_saved, '/'); + if (p) { + memcpy(path, hdrfn_saved, + p - hdrfn_saved + 1); + path[p - hdrfn_saved + 1] = 0; + } + snprintf(fname_inc, sizeof(fname_inc), "%s%s", + path, finc_name); + finc = fopen(fname_inc, "r"); if (finc == NULL) { printf("%s:%d: can't open '%s'\n", - fname, line, finc_name); + fname_inc, line, finc_name); continue; } ret = do_protostrs(finc, finc_name); @@ -601,7 +612,8 @@ static void build_pp_cache(FILE *fhdr) qsort(pp_cache, pp_cache_size, sizeof(pp_cache[0]), pp_name_cmp); } -static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym) +static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym, + int quiet) { const struct parsed_proto *pp_ret; struct parsed_proto pp_search; @@ -615,7 +627,7 @@ static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym) strcpy(pp_search.name, sym); pp_ret = bsearch(&pp_search, pp_cache, pp_cache_size, sizeof(pp_cache[0]), pp_name_cmp); - if (pp_ret == NULL) + if (pp_ret == NULL && !quiet) printf("%s: sym '%s' is missing\n", hdrfn, sym); return pp_ret; diff --git a/tools/translate.c b/tools/translate.c index 2c52f78..f9ac8a8 100644 --- a/tools/translate.c +++ b/tools/translate.c @@ -650,7 +650,7 @@ static int parse_operand(struct parsed_opr *opr, // most likely var in data segment opr->type = OPT_LABEL; - pp = proto_parse(g_fhdr, opr->name); + pp = proto_parse(g_fhdr, opr->name, 0); if (pp != NULL) { if (pp->is_fptr || pp->is_func) { opr->lmod = OPLM_DWORD; @@ -1437,7 +1437,7 @@ static void check_label_read_ref(struct parsed_op *po, const char *name) { const struct parsed_proto *pp; - pp = proto_parse(g_fhdr, name); + pp = proto_parse(g_fhdr, name, 0); if (pp == NULL) ferr(po, "proto_parse failed for ref '%s'\n", name); @@ -2293,7 +2293,7 @@ static const struct parsed_proto *try_recover_pp( ferr(po, "icall sa: reg arg in arg-call unhandled yet\n"); } else if (opr->type == OPT_OFFSET || opr->type == OPT_LABEL) { - pp = proto_parse(g_fhdr, opr->name); + pp = proto_parse(g_fhdr, opr->name, 0); if (pp == NULL) ferr(po, "proto_parse failed for icall from '%s'\n", opr->name); if (pp->argc_reg != 0) @@ -2586,7 +2586,7 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt) g_bp_frame = g_sp_frame = g_stack_fsz = 0; g_stack_frame_used = 0; - g_func_pp = proto_parse(fhdr, funcn); + g_func_pp = proto_parse(fhdr, funcn, 0); if (g_func_pp == NULL) ferr(ops, "proto_parse failed for '%s'\n", funcn); @@ -2755,7 +2755,7 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt) tmpname = opr_name(po, 0); if (IS_START(tmpname, "loc_")) ferr(po, "call to loc_*\n"); - pp_c = proto_parse(fhdr, tmpname); + pp_c = proto_parse(fhdr, tmpname, 0); if (pp_c == NULL) ferr(po, "proto_parse failed for call '%s'\n", tmpname); if (pp_c->is_fptr && pp_c->argc_reg != 0) -- 2.39.2