minor fixes
[ia32rtools.git] / tools / protoparse.h
index 6ea6387..8e88ba0 100644 (file)
@@ -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,6 +216,7 @@ static const char *known_ptr_types[] = {
        "HRGN",
        "HRSRC",
        "HKEY",
+       "HKL",
        "HMENU",
        "HMONITOR",
        "HWAVEOUT",
@@ -239,6 +241,8 @@ static const char *known_ptr_types[] = {
        "REFCLSID",
        "REFGUID",
        "REFIID",
+       "SC_HANDLE",
+       "SERVICE_STATUS_HANDLE",
        "HOOKPROC",
        "DLGPROC",
        "TIMERPROC",
@@ -249,6 +253,7 @@ static const char *known_ptr_types[] = {
 
 static const char *ignored_keywords[] = {
        "extern",
+       "static",
        "WINBASEAPI",
        "WINUSERAPI",
        "WINGDIAPI",
@@ -639,6 +644,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++;
 
@@ -991,22 +1002,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)
 {
@@ -1034,12 +1066,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);