X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tools%2Fprotoparse.h;h=0aa8ed885a40a84c733e098456135bf05e8b2000;hb=cb6623274360357225526abaf285e5b500dbef97;hp=673fcb794d4cd4ea929f645a15828a04a2bf64ac;hpb=bd96f6564765a72d647fbf31de3120ad7f363653;p=ia32rtools.git diff --git a/tools/protoparse.h b/tools/protoparse.h index 673fcb7..0aa8ed8 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -5,6 +5,7 @@ struct parsed_type { char *name; unsigned int is_array:1; unsigned int is_ptr:1; + unsigned int is_struct:1; // split for args }; struct parsed_proto_arg { @@ -26,14 +27,20 @@ struct parsed_proto { int argc_reg; unsigned int is_func:1; unsigned int is_stdcall:1; + unsigned int is_fastcall:1; unsigned int is_vararg:1; unsigned int is_fptr:1; unsigned int is_noreturn:1; + unsigned int is_unresolved:1; + unsigned int has_structarg:1; }; static const char *hdrfn; static int hdrfline = 0; +static void pp_copy_arg(struct parsed_proto_arg *d, + const struct parsed_proto_arg *s); + static int b_pp_c_handler(char *proto, const char *fname); static int do_protostrs(FILE *fhdr, const char *fname) @@ -41,6 +48,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; @@ -58,10 +67,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); @@ -119,28 +137,40 @@ static const char *known_type_mod[] = { "unsigned", "struct", "enum", + "CONST", }; static const char *known_ptr_types[] = { + "FARPROC", "HACCEL", "HANDLE", "HBITMAP", "HCURSOR", "HDC", + "HFONT", "HGDIOBJ", "HGLOBAL", + "HICON", "HINSTANCE", + //"HIMC", // DWORD "HMODULE", + "HPALETTE", "HRGN", "HRSRC", "HKEY", "HMENU", "HWND", - "PLONG", + "PCRITICAL_SECTION", "PDWORD", + "PHKEY", + "PLONG", + "PMEMORY_BASIC_INFORMATION", + "PUINT", "PVOID", "PCVOID", "DLGPROC", + "TIMERPROC", + "WNDENUMPROC", "va_list", "__VALIST", }; @@ -205,7 +235,7 @@ static int check_type(const char *name, struct parsed_type *type) break; } - if (n[0] == 'L' && n[1] == 'P') + if (n[0] == 'L' && n[1] == 'P' && strncmp(n, "LPARAM", 6)) type->is_ptr = 1; // assume single word @@ -226,6 +256,9 @@ static int check_type(const char *name, struct parsed_type *type) ret = n1 - name; type->name = strndup(name, ret); + if (IS(type->name, "VOID")) + memcpy(type->name, "void", 4); + return ret; } @@ -248,6 +281,14 @@ static const char *map_reg(const char *reg) return reg; } +static int check_struct_arg(struct parsed_proto_arg *arg) +{ + if (IS(arg->type.name, "POINT")) + return 2 - 1; + + return 0; +} + static int parse_protostr(char *protostr, struct parsed_proto *pp) { struct parsed_proto_arg *arg; @@ -291,6 +332,11 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) } p = sskip(p + ret); + if (!strncmp(p, "noreturn ", 9)) { + pp->is_noreturn = 1; + p = sskip(p + 9); + } + if (!strchr(p, ')')) { p = next_idt(buf, sizeof(buf), p); p = sskip(p); @@ -327,8 +373,10 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) pp->is_stdcall = 0; else if (IS(cconv, "__stdcall")) pp->is_stdcall = 1; - else if (IS(cconv, "__fastcall")) - pp->is_stdcall = 1; + else if (IS(cconv, "__fastcall")) { + pp->is_fastcall = 1; + pp->is_stdcall = 1; // sort of.. + } else if (IS(cconv, "__thiscall")) pp->is_stdcall = 1; else if (IS(cconv, "__userpurge")) @@ -417,8 +465,14 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) p++; break; } - if (*p == ',') + if (xarg > 0) { + if (*p != ',') { + printf("%s:%d:%zd: ',' expected\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } p = sskip(p + 1); + } if (!strncmp(p, "...", 3)) { pp->is_vararg = 1; @@ -454,7 +508,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) return -1; } // we'll treat it as void * for non-calls - arg->type.name = "void *"; + arg->type.name = strdup("void *"); arg->type.is_ptr = 1; p = p1 + ret; @@ -478,6 +532,18 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) arg->reg = strdup(map_reg(regparm)); } + + ret = check_struct_arg(arg); + if (ret > 0) { + pp->has_structarg = 1; + arg->type.is_struct = 1; + free(arg->type.name); + arg->type.name = strdup("int"); + for (l = 0; l < ret; l++) { + pp_copy_arg(&pp->arg[xarg], arg); + xarg++; + } + } } if (xarg > 0 && (IS(cconv, "__fastcall") || IS(cconv, "__thiscall"))) { @@ -496,11 +562,6 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) pp->arg[1].reg = strdup("edx"); } - if (pp->is_vararg && pp->is_stdcall) { - printf("%s:%d: vararg stdcall?\n", hdrfn, hdrfline); - return -1; - } - pp->argc = xarg; for (i = 0; i < pp->argc; i++) { @@ -510,6 +571,23 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) pp->argc_reg++; } + if (pp->argc == 1 && pp->arg[0].reg != NULL + && IS(pp->arg[0].reg, "ecx")) + { + pp->is_fastcall = 1; + } + else if (pp->argc_reg == 2 + && pp->arg[0].reg != NULL && IS(pp->arg[0].reg, "ecx") + && pp->arg[1].reg != NULL && IS(pp->arg[1].reg, "edx")) + { + pp->is_fastcall = 1; + } + + if (pp->is_vararg && (pp->is_stdcall || pp->is_fastcall)) { + printf("%s:%d: vararg %s?\n", hdrfn, hdrfline, cconv); + return -1; + } + return p - protostr; } @@ -547,8 +625,10 @@ static int b_pp_c_handler(char *proto, const char *fname) static void build_pp_cache(FILE *fhdr) { + long pos; int ret; + pos = ftell(fhdr); rewind(fhdr); ret = do_protostrs(fhdr, hdrfn); @@ -556,9 +636,11 @@ static void build_pp_cache(FILE *fhdr) exit(1); qsort(pp_cache, pp_cache_size, sizeof(pp_cache[0]), pp_name_cmp); + fseek(fhdr, pos, SEEK_SET); } -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; @@ -572,12 +654,32 @@ 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; } +static void pp_copy_arg(struct parsed_proto_arg *d, + const struct parsed_proto_arg *s) +{ + memcpy(d, s, sizeof(*d)); + + if (s->reg != NULL) { + d->reg = strdup(s->reg); + my_assert_not(d->reg, NULL); + } + if (s->type.name != NULL) { + d->type.name = strdup(s->type.name); + my_assert_not(d->type.name, NULL); + } + if (s->fptr != NULL) { + d->fptr = malloc(sizeof(*d->fptr)); + my_assert_not(d->fptr, NULL); + memcpy(d->fptr, s->fptr, sizeof(*d->fptr)); + } +} + struct parsed_proto *proto_clone(const struct parsed_proto *pp_c) { struct parsed_proto *pp; @@ -588,28 +690,36 @@ struct parsed_proto *proto_clone(const struct parsed_proto *pp_c) memcpy(pp, pp_c, sizeof(*pp)); // lazy.. // do the actual deep copy.. - for (i = 0; i < pp_c->argc; i++) { - if (pp_c->arg[i].reg != NULL) { - pp->arg[i].reg = strdup(pp_c->arg[i].reg); - my_assert_not(pp->arg[i].reg, NULL); - } - if (pp_c->arg[i].type.name != NULL) { - pp->arg[i].type.name = strdup(pp_c->arg[i].type.name); - my_assert_not(pp->arg[i].type.name, NULL); - } - if (pp_c->arg[i].fptr != NULL) { - pp->arg[i].fptr = malloc(sizeof(*pp->arg[i].fptr)); - my_assert_not(pp->arg[i].fptr, NULL); - memcpy(pp->arg[i].fptr, pp_c->arg[i].fptr, - sizeof(*pp->arg[i].fptr)); - } - } + for (i = 0; i < pp_c->argc; i++) + pp_copy_arg(&pp->arg[i], &pp_c->arg[i]); if (pp_c->ret_type.name != NULL) pp->ret_type.name = strdup(pp_c->ret_type.name); return pp; } +static inline void pp_print(char *buf, size_t buf_size, + const struct parsed_proto *pp) +{ + size_t l; + int i; + + snprintf(buf, buf_size, "%s %s(", pp->ret_type.name, pp->name); + l = strlen(buf); + + for (i = 0; i < pp->argc_reg; i++) { + snprintf(buf + l, buf_size - l, "%s%s", + i == 0 ? "" : ", ", pp->arg[i].reg); + l = strlen(buf); + } + if (pp->argc_stack > 0) { + snprintf(buf + l, buf_size - l, "%s{%d stack}", + i == 0 ? "" : ", ", pp->argc_stack); + l = strlen(buf); + } + snprintf(buf + l, buf_size - l, ")"); +} + static inline void proto_release(struct parsed_proto *pp) { int i;