unsigned int is_struct:1; // split for args
unsigned int is_retreg:1; // register to return to caller
unsigned int is_va_list:1;
+ unsigned int is_64bit:1;
+ unsigned int is_float:1; // float, double
};
struct parsed_proto_arg {
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;
unsigned int is_fastcall:1;
unsigned int is_vararg:1; // vararg func
unsigned int is_fptr:1;
+ unsigned int is_import:1; // data import
unsigned int is_noreturn:1;
unsigned int is_unresolved:1;
+ unsigned int is_guessed:1; // for extra checking
unsigned int is_userstack:1;
unsigned int is_include:1; // not from top-level header
unsigned int is_osinc:1; // OS/system library func
"HACCEL",
"HANDLE",
"HBITMAP",
+ "HBRUSH",
"HCALL",
"HCURSOR",
"HDC",
"HFONT",
"HGDIOBJ",
"HGLOBAL",
+ "HHOOK",
"HICON",
"HINSTANCE",
"HIMC", // DWORD in mingw, ptr in wine..
"HRSRC",
"HKEY",
"HMENU",
+ "HMONITOR",
"HWAVEOUT",
"HWND",
+ "PAPPBARDATA",
"PBYTE",
"PCRITICAL_SECTION",
+ "PDEVMODEA",
"PDWORD",
"PFILETIME",
"PLARGE_INTEGER",
+ "PHANDLE",
"PHKEY",
"PLONG",
"PMEMORY_BASIC_INFORMATION",
"PUINT",
+ "PULARGE_INTEGER",
+ "PULONG_PTR",
"PVOID",
"PCVOID",
"PWORD",
+ "REFCLSID",
+ "REFGUID",
+ "REFIID",
+ "SC_HANDLE",
+ "SERVICE_STATUS_HANDLE",
+ "HOOKPROC",
"DLGPROC",
"TIMERPROC",
"WNDENUMPROC",
if (ret < 0)
return -1;
+ if (IS_START(arg->pp->name, "guess"))
+ arg->pp->is_guessed = 1;
+
// we don't use actual names right now...
snprintf(arg->pp->name, sizeof(arg->pp->name), "a%d", xarg);
p = sskip(p + l + 1);
}
+ if (IS_START(p, "DECL_IMPORT ")) {
+ pp->is_import = 1;
+ p = sskip(p + 12);
+ }
+
ret = check_type(p, &pp->ret_type);
if (ret <= 0) {
printf("%s:%d:%zd: unhandled return in '%s'\n",
pp->is_stdcall = 0; // custom
pp->is_userstack = 1;
}
- else if (IS(cconv, "WINAPI"))
+ else if (IS(cconv, "WINAPI") || IS(cconv, "PASCAL"))
pp->is_stdcall = 1;
else {
printf("%s:%d:%zd: unhandled cconv: '%s'\n",
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++;
pp->has_retreg |= is_retreg;
}
- if (strstr(arg->type.name, "int64")
- || IS(arg->type.name, "double"))
+ if (IS(arg->type.name, "float")
+ || IS(arg->type.name, "double"))
{
+ arg->type.is_float = 1;
+ }
+
+ if (!arg->type.is_ptr && (strstr(arg->type.name, "int64")
+ || IS(arg->type.name, "double")))
+ {
+ arg->type.is_64bit = 1;
// hack..
- free(arg->type.name);
- arg->type.name = strdup("int");
pp_copy_arg(&pp->arg[xarg], arg);
+ arg = &pp->arg[xarg];
xarg++;
+ free(arg->type.name);
+ arg->type.name = strdup("dummy");
}
ret = check_struct_arg(arg);
if (pp_cache == NULL)
build_caches(fhdr);
- if (sym[0] == '_') // && strncmp(fname, "stdc", 4) == 0)
+ // ugh...
+ if (sym[0] == '_' && !IS_START(sym, "__W"))
sym++;
strcpy(pp_search.name, sym);
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)
{