X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tools%2Fprotoparse.h;h=d9f6ef8b2c7cfae3b41392e5474bc6eacc565ca3;hb=36595fd27d06b03f1abf320bd511aec325845ed5;hp=0197214a2578d6272779950bd4b237ee716fdd2e;hpb=de50b98baf577c2ab9b9f680ea102c1dad14eb7c;p=ia32rtools.git diff --git a/tools/protoparse.h b/tools/protoparse.h index 0197214..d9f6ef8 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 { @@ -29,69 +30,84 @@ struct parsed_proto { unsigned int is_vararg:1; unsigned int is_fptr:1; unsigned int is_noreturn:1; + unsigned int has_structarg:1; }; static const char *hdrfn; static int hdrfline = 0; -static int find_protostr(char *dst, size_t dlen, FILE *fhdr, - const char *fname, const char *sym_) +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) { - const char *sym = sym_; const char *finc_name; + const char *hdrfn_saved; + char protostr[256]; + char path[256]; + char fname_inc[256]; FILE *finc; - int symlen; int line = 0; int ret; char *p; - if (sym[0] == '_' && strncmp(fname, "stdc", 4) == 0) - sym++; - symlen = strlen(sym); - - rewind(fhdr); + hdrfn_saved = hdrfn; + hdrfn = fname; - while (fgets(dst, dlen, fhdr)) + while (fgets(protostr, sizeof(protostr), fhdr)) { line++; - if (strncmp(dst, "//#include ", 11) == 0) { - finc_name = dst + 11; + if (strncmp(protostr, "//#include ", 11) == 0) { + finc_name = protostr + 11; p = strpbrk(finc_name, "\r\n "); 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 = find_protostr(dst, dlen, finc, - finc_name, sym_); + ret = do_protostrs(finc, finc_name); fclose(finc); - if (ret == 0) + if (ret < 0) break; continue; } - if (strncmp(sskip(dst), "//", 2) == 0) + if (strncmp(sskip(protostr), "//", 2) == 0) continue; - p = strstr(dst, sym); - if (p != NULL && p > dst - && (my_isblank(p[-1]) || my_issep(p[-1])) - && (my_isblank(p[symlen]) || my_issep(p[symlen]))) + p = protostr + strlen(protostr); + for (p--; p >= protostr && my_isblank(*p); --p) + *p = 0; + if (p < protostr) + continue; + + hdrfline = line; + + ret = b_pp_c_handler(protostr, hdrfn); + if (ret < 0) break; } - hdrfline = line; - if (feof(fhdr)) - return -1; + hdrfn = hdrfn_saved; - p = dst + strlen(dst); - for (p--; p > dst && my_isblank(*p); --p) - *p = 0; + if (feof(fhdr)) + return 0; - return 0; + return -1; } static int get_regparm(char *dst, size_t dlen, char *p) @@ -119,6 +135,7 @@ static const char *known_type_mod[] = { "unsigned", "struct", "enum", + "CONST", }; static const char *known_ptr_types[] = { @@ -127,20 +144,28 @@ static const char *known_ptr_types[] = { "HBITMAP", "HCURSOR", "HDC", + "HFONT", "HGDIOBJ", "HGLOBAL", "HINSTANCE", + "HIMC", "HMODULE", "HRGN", "HRSRC", "HKEY", "HMENU", "HWND", - "PLONG", + "PCRITICAL_SECTION", "PDWORD", + "PHKEY", + "PLONG", + "PMEMORY_BASIC_INFORMATION", + "PUINT", "PVOID", "PCVOID", "DLGPROC", + "TIMERPROC", + "WNDENUMPROC", "va_list", "__VALIST", }; @@ -177,6 +202,8 @@ static const char *skip_type_mod(const char *n) len = strlen(known_type_mod[i]); if (strncmp(n, known_type_mod[i], len) != 0) continue; + if (!my_isblank(n[len])) + continue; n += len; while (my_isblank(*n)) @@ -203,7 +230,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 @@ -224,6 +251,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; } @@ -246,6 +276,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; @@ -347,7 +385,11 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) hdrfn, hdrfline, (p - protostr) + 1); return -1; } - p = sskip(p + 1); + p++; + // XXX: skipping extra asterisks, for now + while (*p == '*') + p++; + p = sskip(p); } p = next_idt(buf, sizeof(buf), p); @@ -362,7 +404,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) ret = get_regparm(regparm, sizeof(regparm), p); if (ret > 0) { if (!IS(regparm, "eax") && !IS(regparm, "ax") - && !IS(regparm, "al")) + && !IS(regparm, "al") && !IS(regparm, "edx:eax")) { printf("%s:%d:%zd: bad regparm: %s\n", hdrfn, hdrfline, (p - protostr) + 1, regparm); @@ -373,6 +415,17 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) } if (pp->is_fptr) { + if (*p == '[') { + // not really ret_type is array, but ohwell + pp->ret_type.is_array = 1; + p = strchr(p + 1, ']'); + if (p == NULL) { + printf("%s:%d:%zd: ']' expected\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + p = sskip(p + 1); + } if (*p != ')') { printf("%s:%d:%zd: ')' expected\n", hdrfn, hdrfline, (p - protostr) + 1); @@ -400,8 +453,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; @@ -437,7 +496,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; @@ -461,6 +520,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,23 +567,111 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) return p - protostr; } -static int proto_parse(FILE *fhdr, const char *sym, struct parsed_proto *pp) +static int pp_name_cmp(const void *p1, const void *p2) +{ + const struct parsed_proto *pp1 = p1, *pp2 = p2; + return strcmp(pp1->name, pp2->name); +} + +static struct parsed_proto *pp_cache; +static int pp_cache_size; +static int pp_cache_alloc; + +static int b_pp_c_handler(char *proto, const char *fname) { - char protostr[256]; int ret; - memset(pp, 0, sizeof(*pp)); + if (pp_cache_size >= pp_cache_alloc) { + pp_cache_alloc = pp_cache_alloc * 2 + 64; + pp_cache = realloc(pp_cache, pp_cache_alloc + * sizeof(pp_cache[0])); + my_assert_not(pp_cache, NULL); + memset(pp_cache + pp_cache_size, 0, + (pp_cache_alloc - pp_cache_size) + * sizeof(pp_cache[0])); + } + + ret = parse_protostr(proto, &pp_cache[pp_cache_size]); + if (ret < 0) + return -1; + + pp_cache_size++; + return 0; +} + +static void build_pp_cache(FILE *fhdr) +{ + int ret; + + rewind(fhdr); + + ret = do_protostrs(fhdr, hdrfn); + if (ret < 0) + exit(1); + + 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, + int quiet) +{ + const struct parsed_proto *pp_ret; + struct parsed_proto pp_search; + + if (pp_cache == NULL) + build_pp_cache(fhdr); + + if (sym[0] == '_') // && strncmp(fname, "stdc", 4) == 0) + sym++; - ret = find_protostr(protostr, sizeof(protostr), fhdr, hdrfn, sym); - if (ret != 0) { + 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 && !quiet) printf("%s: sym '%s' is missing\n", hdrfn, sym); - return ret; + + 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; + int i; + + pp = malloc(sizeof(*pp)); + my_assert_not(pp, NULL); + memcpy(pp, pp_c, sizeof(*pp)); // lazy.. + + // do the actual deep copy.. + 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 parse_protostr(protostr, pp) < 0 ? -1 : 0; + return pp; } -static void proto_release(struct parsed_proto *pp) +static inline void proto_release(struct parsed_proto *pp) { int i; @@ -526,4 +685,5 @@ static void proto_release(struct parsed_proto *pp) } if (pp->ret_type.name != NULL) free(pp->ret_type.name); + free(pp); }