From 06c5d854748b35f194428e227ae44d7a6a46cd97 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 17 Dec 2013 01:30:36 +0200 Subject: [PATCH] use main header, parse variable types, asm patch comment --- stdc.hlst => stdc.hlist | 0 tools/my_str.h | 2 +- tools/protoparse.h | 56 ++++++++++++++++++++---- tools/translate.c | 97 ++++++++++++++++++++++++++++++++++++----- 4 files changed, 134 insertions(+), 21 deletions(-) rename stdc.hlst => stdc.hlist (100%) diff --git a/stdc.hlst b/stdc.hlist similarity index 100% rename from stdc.hlst rename to stdc.hlist diff --git a/tools/my_str.h b/tools/my_str.h index f541481..60fcc76 100644 --- a/tools/my_str.h +++ b/tools/my_str.h @@ -6,7 +6,7 @@ static int my_isblank(char c) static int my_issep(char c) { return c == '(' || c == ')' || c == '[' || c == ']' - || c == '<' || c == '>' || c == ',' + || c == '<' || c == '>' || c == ',' || c == ';' || c == '+' || c == '-' || c == '*' || c == '/'; } diff --git a/tools/protoparse.h b/tools/protoparse.h index 533dd46..5ef8b4b 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -15,8 +15,10 @@ struct parsed_proto { int argc; int argc_stack; int argc_reg; + unsigned int is_func:1; unsigned int is_stdcall:1; unsigned int is_fptr:1; + unsigned int is_array:1; }; static const char *hdrfn; @@ -26,6 +28,7 @@ static int find_protostr(char *dst, size_t dlen, FILE *fhdr, const char *fname, const char *sym_) { const char *sym = sym_; + const char *finc_name; FILE *finc; int symlen; int line = 0; @@ -41,27 +44,31 @@ static int find_protostr(char *dst, size_t dlen, FILE *fhdr, while (fgets(dst, dlen, fhdr)) { line++; - if (strncmp(dst, "#include ", 9) == 0) { - p = strpbrk(dst + 9, "\r\n "); + if (strncmp(dst, "//#include ", 11) == 0) { + finc_name = dst + 11; + p = strpbrk(finc_name, "\r\n "); if (p != NULL) *p = 0; - finc = fopen(dst + 9, "r"); + finc = fopen(finc_name, "r"); if (finc == NULL) { printf("%s:%d: can't open '%s'\n", - fname, line, dst + 9); + fname, line, finc_name); continue; } ret = find_protostr(dst, dlen, finc, - dst + 9, sym_); + finc_name, sym_); fclose(finc); if (ret == 0) break; continue; } + if (strncmp(sskip(dst), "//", 2) == 0) + continue; p = strstr(dst, sym); - if (p != NULL + if (p != NULL && p > dst + && (my_isblank(p[-1]) || my_issep(p[-1])) && (my_isblank(p[symlen]) || my_issep(p[symlen]))) break; } @@ -180,12 +187,22 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) int ret; int i; - p = protostr; + p = sskip(protostr); if (p[0] == '/' && p[1] == '/') { - //printf("warning: decl for sym '%s' is commented out\n", sym); + printf("%s:%d: commented out?\n", hdrfn, hdrfline); p = sskip(p + 2); } + // strip unneeded stuff + for (p1 = p; p1[0] != 0 && p1[1] != 0; p1++) { + if ((p1[0] == '/' && p1[1] == '*') + || (p1[0] == '*' && p1[1] == '/')) + p1[0] = p1[1] = ' '; + } + + if (strncmp(p, "extern ", 7) == 0) + p = sskip(p + 7); + kt = check_type(p); if (kt == NULL) { printf("%s:%d:%ld: unhandled return in '%s'\n", @@ -196,6 +213,26 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) p += strlen(kt); p = sskip(p); + if (!strchr(p, ')')) { + p = next_idt(buf, sizeof(buf), p); + p = sskip(p); + if (buf[0] == 0) { + printf("%s:%d:%ld: var name missing\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + strcpy(pp->name, buf); + + p1 = strchr(p, ']'); + if (p1 != NULL) { + p = p1 + 1; + pp->is_array = 1; + } + return p - protostr; + } + + pp->is_func = 1; + if (*p == '(') { pp->is_fptr = 1; p = sskip(p + 1); @@ -275,7 +312,8 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) // check for x(void) p = sskip(p); - if (strncmp(p, "void", 4) == 0 && *sskip(p + 4) == ')') + if ((!strncmp(p, "void", 4) || !strncmp(p, "VOID", 4)) + && *sskip(p + 4) == ')') p += 4; while (1) { diff --git a/tools/translate.c b/tools/translate.c index 532c160..e7f4bdd 100644 --- a/tools/translate.c +++ b/tools/translate.c @@ -12,8 +12,9 @@ #include "protoparse.h" -const char *asmfn; +static const char *asmfn; static int asmln; +static FILE *g_fhdr; #define anote(fmt, ...) \ printf("%s:%d: note: " fmt, asmfn, asmln, ##__VA_ARGS__) @@ -112,6 +113,7 @@ enum opr_lenmod { struct parsed_opr { enum opr_type type; enum opr_lenmod lmod; + unsigned int is_ptr:1; // pointer in C int reg; unsigned int val; char name[256]; @@ -391,6 +393,61 @@ static int guess_lmod_from_name(struct parsed_opr *opr) return 0; } +static int guess_lmod_from_c_type(struct parsed_opr *opr, const char *c_type) +{ + static const char *ptr_types[] = { + "LPCSTR", + }; + static const char *dword_types[] = { + "int", "_DWORD", "DWORD", "HANDLE", "HWND", "HMODULE", + }; + static const char *word_types[] = { + "__int16", "unsigned __int16", + }; + static const char *byte_types[] = { + "char", "__int8", "unsigned __int8", "BYTE", + }; + int i; + + if (strchr(c_type, '*')) { + opr->lmod = OPLM_DWORD; + opr->is_ptr = 1; + return 1; + } + + for (i = 0; i < ARRAY_SIZE(dword_types); i++) { + if (IS(c_type, dword_types[i])) { + opr->lmod = OPLM_DWORD; + return 1; + } + } + + for (i = 0; i < ARRAY_SIZE(ptr_types); i++) { + if (IS(c_type, ptr_types[i])) { + opr->lmod = OPLM_DWORD; + opr->is_ptr = 1; + return 1; + } + } + + for (i = 0; i < ARRAY_SIZE(word_types); i++) { + if (IS(c_type, word_types[i])) { + opr->lmod = OPLM_WORD; + return 1; + } + } + + for (i = 0; i < ARRAY_SIZE(byte_types); i++) { + if (IS(c_type, byte_types[i])) { + opr->lmod = OPLM_BYTE; + return 1; + } + } + + anote("unhandled C type '%s' for '%s'\n", c_type, opr->name); + return 0; +} + static void setup_reg_opr(struct parsed_opr *opr, int reg, enum opr_lenmod lmod, int *regmask) { @@ -407,6 +464,7 @@ static int parse_operand(struct parsed_opr *opr, int *regmask, int *regmask_indirect, char words[16][256], int wordc, int w, unsigned int op_flags) { + struct parsed_proto pp; enum opr_lenmod tmplmod; int ret, len; long number; @@ -536,12 +594,19 @@ static int parse_operand(struct parsed_opr *opr, // most likely var in data segment opr->type = OPT_LABEL; + + ret = proto_parse(g_fhdr, opr->name, &pp); + if (ret == 0) { + if (pp.is_fptr) { + opr->lmod = OPLM_DWORD; + opr->is_ptr = 1; + } + else if (opr->lmod == OPLM_UNSPEC) + guess_lmod_from_c_type(opr, pp.ret_type); + } + if (opr->lmod == OPLM_UNSPEC) guess_lmod_from_name(opr); - if (opr->lmod != OPLM_UNSPEC) - return wordc; - - // TODO: scan data seg to determine type? return wordc; } @@ -2105,8 +2170,9 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt) case OP_MOV: assert_operand_cnt(2); propagate_lmod(po, &po->operand[0], &po->operand[1]); - fprintf(fout, " %s = %s;", + fprintf(fout, " %s = %s%s;", out_dst_opr(buf1, sizeof(buf1), po, &po->operand[0]), + po->operand[0].is_ptr ? "(void *)" : "", out_src_opr(buf2, sizeof(buf2), po, &po->operand[1], 0)); break; @@ -2561,7 +2627,7 @@ static int cmpstringp(const void *p1, const void *p2) int main(int argc, char *argv[]) { - FILE *fout, *fasm, *fhdr, *frlist; + FILE *fout, *fasm, *frlist; char line[256]; char words[16][256]; int ida_func_attr = 0; @@ -2598,8 +2664,8 @@ int main(int argc, char *argv[]) my_assert_not(fasm, NULL); hdrfn = argv[arg++]; - fhdr = fopen(hdrfn, "r"); - my_assert_not(fhdr, NULL); + g_fhdr = fopen(hdrfn, "r"); + my_assert_not(g_fhdr, NULL); rlist_alloc = 64; rlist = malloc(rlist_alloc * sizeof(rlist[0])); @@ -2690,6 +2756,7 @@ int main(int argc, char *argv[]) continue; } +parse_words: memset(words, 0, sizeof(words)); for (wordc = 0; wordc < 16; wordc++) { p = sskip(next_word_s(words[wordc], sizeof(words[0]), p)); @@ -2699,6 +2766,14 @@ int main(int argc, char *argv[]) } } + // alow asm patches in comments + if (*p == ';' && IS_START(p, "; sctpatch: ")) { + p = sskip(p + 12); + if (*p == 0 || *p == ';') + continue; + goto parse_words; // lame + } + if (wordc == 0) { // shouldn't happen awarn("wordc == 0?\n"); @@ -2736,7 +2811,7 @@ int main(int argc, char *argv[]) words[0], g_func); if (in_func && !skip_func) - gen_func(fout, fhdr, g_func, pi); + gen_func(fout, g_fhdr, g_func, pi); in_func = 0; skip_warned = 0; @@ -2808,7 +2883,7 @@ int main(int argc, char *argv[]) fclose(fout); fclose(fasm); - fclose(fhdr); + fclose(g_fhdr); return 0; } -- 2.39.5