X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tools%2Fprotoparse.h;h=ced1a546d242221084fcfa3dd877c7635f3fc645;hb=360cca21a7b27400c4953c49e0afc8628e003a0c;hp=7acd63a82858ab0ac7adc04760bbb117411d83ab;hpb=1fe8d40ebdb232ab6be27af1a3b94a2869cc3779;p=ia32rtools.git diff --git a/tools/protoparse.h b/tools/protoparse.h index 7acd63a..ced1a54 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -23,8 +23,9 @@ struct parsed_proto_arg { char *reg; struct parsed_type type; struct parsed_proto *pp; // fptr or struct - void *datap; unsigned int is_saved:1; // not set here, for tool use + void **push_refs; + int push_ref_cnt; }; struct parsed_proto { @@ -33,7 +34,7 @@ struct parsed_proto { struct parsed_type ret_type; struct parsed_type type; }; - struct parsed_proto_arg arg[16]; + struct parsed_proto_arg arg[32]; int argc; int argc_stack; int argc_reg; @@ -215,7 +216,9 @@ static const char *known_ptr_types[] = { "HRGN", "HRSRC", "HKEY", + "HKL", "HMENU", + "HMONITOR", "HWAVEOUT", "HWND", "PAPPBARDATA", @@ -238,6 +241,8 @@ static const char *known_ptr_types[] = { "REFCLSID", "REFGUID", "REFIID", + "SC_HANDLE", + "SERVICE_STATUS_HANDLE", "HOOKPROC", "DLGPROC", "TIMERPROC", @@ -638,6 +643,12 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) return -1; } + if (xarg >= ARRAY_SIZE(pp->arg)) { + printf("%s:%d:%zd: too many args\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + arg = &pp->arg[xarg]; xarg++; @@ -990,22 +1001,43 @@ static inline int pp_cmp_func(const struct parsed_proto *pp1, if (pp1->argc != pp2->argc || pp1->argc_reg != pp2->argc_reg) return 1; - else { - for (i = 0; i < pp1->argc; i++) { - if ((pp1->arg[i].reg != NULL) != (pp2->arg[i].reg != NULL)) - return 1; - - if ((pp1->arg[i].reg != NULL) - && !IS(pp1->arg[i].reg, pp2->arg[i].reg)) - { - return 1; - } + if (pp1->is_stdcall != pp2->is_stdcall) + return 1; + + // because of poor void return detection, return is not + // checked for now to avoid heaps of false positives + + for (i = 0; i < pp1->argc; i++) { + if ((pp1->arg[i].reg != NULL) != (pp2->arg[i].reg != NULL)) + return 1; + + if ((pp1->arg[i].reg != NULL) + && !IS(pp1->arg[i].reg, pp2->arg[i].reg)) + { + return 1; } } return 0; } +static inline int pp_compatible_func( + const struct parsed_proto *pp_site, + const struct parsed_proto *pp_callee) +{ + if (pp_cmp_func(pp_site, pp_callee) == 0) + return 1; + + if (pp_site->argc_stack == 0 && pp_site->is_fastcall + && pp_callee->argc_stack == 0 + && (pp_callee->is_fastcall || pp_callee->argc_reg == 0) + && pp_site->argc_reg > pp_callee->argc_reg) + /* fascall compatible callee doesn't use all args -> ok */ + return 1; + + return 0; +} + static inline void pp_print(char *buf, size_t buf_size, const struct parsed_proto *pp) { @@ -1033,12 +1065,10 @@ static inline void proto_release(struct parsed_proto *pp) int i; for (i = 0; i < pp->argc; i++) { - if (pp->arg[i].reg != NULL) - free(pp->arg[i].reg); - if (pp->arg[i].type.name != NULL) - free(pp->arg[i].type.name); - if (pp->arg[i].pp != NULL) - free(pp->arg[i].pp); + free(pp->arg[i].reg); + free(pp->arg[i].type.name); + free(pp->arg[i].pp); + free(pp->arg[i].push_refs); } if (pp->ret_type.name != NULL) free(pp->ret_type.name);