translate: more float stuff
[ia32rtools.git] / tools / protoparse.h
index 308cccd..897171e 100644 (file)
@@ -15,13 +15,15 @@ struct parsed_type {
        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;
 };
 
 struct parsed_proto_arg {
        char *reg;
        struct parsed_type type;
-       struct parsed_proto *fptr;
+       struct parsed_proto *pp; // fptr or struct
        void *datap;
+       unsigned int is_saved:1; // not set here, for tool use
 };
 
 struct parsed_proto {
@@ -191,12 +193,14 @@ static const char *known_ptr_types[] = {
        "HACCEL",
        "HANDLE",
        "HBITMAP",
+       "HBRUSH",
        "HCALL",
        "HCURSOR",
        "HDC",
        "HFONT",
        "HGDIOBJ",
        "HGLOBAL",
+       "HHOOK",
        "HICON",
        "HINSTANCE",
        "HIMC", // DWORD in mingw, ptr in wine..
@@ -216,13 +220,19 @@ static const char *known_ptr_types[] = {
        "PDWORD",
        "PFILETIME",
        "PLARGE_INTEGER",
+       "PHANDLE",
        "PHKEY",
        "PLONG",
        "PMEMORY_BASIC_INFORMATION",
        "PUINT",
+       "PULARGE_INTEGER",
+       "PULONG_PTR",
        "PVOID",
        "PCVOID",
        "PWORD",
+       "REFCLSID",
+       "REFIID",
+       "HOOKPROC",
        "DLGPROC",
        "TIMERPROC",
        "WNDENUMPROC",
@@ -353,6 +363,54 @@ static int check_struct_arg(struct parsed_proto_arg *arg)
        return 0;
 }
 
+static int parse_protostr(char *protostr, struct parsed_proto *pp);
+
+static int parse_arg(char **p_, struct parsed_proto_arg *arg, int xarg)
+{
+       char buf[256];
+       char *p = *p_;
+       char *pe;
+       int ret;
+
+       arg->pp = calloc(1, sizeof(*arg->pp));
+       my_assert_not(arg->pp, NULL);
+       arg->pp->is_arg = 1;
+
+       pe = p;
+       while (1) {
+               pe = strpbrk(pe, ",()");
+               if (pe == NULL)
+                       return -1;
+               if (*pe == ',' || *pe == ')')
+                       break;
+               pe = strchr(pe, ')');
+               if (pe == NULL)
+                       return -1;
+               pe++;
+       }
+
+       if (pe - p > sizeof(buf) - 1)
+               return -1;
+       memcpy(buf, p, pe - p);
+       buf[pe - p] = 0;
+
+       ret = parse_protostr(buf, arg->pp);
+       if (ret < 0)
+               return -1;
+
+       // we don't use actual names right now...
+       snprintf(arg->pp->name, sizeof(arg->pp->name), "a%d", xarg);
+
+       if (!arg->type.is_struct)
+               // we'll treat it as void * for non-calls
+               arg->type.name = strdup("void *");
+       arg->type.is_ptr = 1;
+
+       p += ret;
+       *p_ = p;
+       return 0;
+}
+
 static int parse_protostr(char *protostr, struct parsed_proto *pp)
 {
        struct parsed_proto_arg *arg;
@@ -360,8 +418,8 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp)
        char buf[256];
        char cconv[32];
        int is_retreg;
-       int xarg = 0;
        char *p, *p1;
+       int xarg = 0;
        int i, l;
        int ret;
 
@@ -416,8 +474,8 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp)
        if (!strchr(p, ')')) {
                p = next_idt(buf, sizeof(buf), p);
                p = sskip(p);
-               if (buf[0] == 0) {
-                       printf("%s:%d:%zd: var name missing\n",
+               if (!pp->is_arg && buf[0] == 0) {
+                       printf("%s:%d:%zd: var name is missing\n",
                                hdrfn, hdrfline, (p - protostr) + 1);
                        return -1;
                }
@@ -463,7 +521,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp)
                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",
@@ -578,24 +636,15 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp)
                }
                p = sskip(p + ret);
 
-               if (*p == '(') {
-                       // func ptr
-                       arg->fptr = calloc(1, sizeof(*arg->fptr));
-                       ret = parse_protostr(p1, arg->fptr);
+               if (*p == '(' || arg->type.is_struct) {
+                       // func ptr or struct
+                       ret = parse_arg(&p1, arg, xarg);
                        if (ret < 0) {
                                printf("%s:%d:%zd: funcarg parse failed\n",
                                        hdrfn, hdrfline, p1 - protostr);
                                return -1;
                        }
-                       arg->fptr->is_arg = 1;
-                       // we don't use actual names right now..
-                       snprintf(arg->fptr->name,
-                               sizeof(arg->fptr->name), "a%d", xarg);
-                       // we'll treat it as void * for non-calls
-                       arg->type.name = strdup("void *");
-                       arg->type.is_ptr = 1;
-
-                       p = p1 + ret;
+                       p = p1;
                }
 
                p = next_idt(buf, sizeof(buf), p);
@@ -619,14 +668,16 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp)
                        pp->has_retreg |= is_retreg;
                }
 
-               if (strstr(arg->type.name, "int64")
-                   || IS(arg->type.name, "double"))
+               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);
@@ -821,7 +872,8 @@ static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym,
        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);
@@ -885,10 +937,10 @@ static void pp_copy_arg(struct parsed_proto_arg *d,
                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));
+       if (s->pp != NULL) {
+               d->pp = malloc(sizeof(*d->pp));
+               my_assert_not(d->pp, NULL);
+               memcpy(d->pp, s->pp, sizeof(*d->pp));
        }
 }
 
@@ -965,8 +1017,8 @@ static inline void proto_release(struct parsed_proto *pp)
                        free(pp->arg[i].reg);
                if (pp->arg[i].type.name != NULL)
                        free(pp->arg[i].type.name);
-               if (pp->arg[i].fptr != NULL)
-                       free(pp->arg[i].fptr);
+               if (pp->arg[i].pp != NULL)
+                       free(pp->arg[i].pp);
        }
        if (pp->ret_type.name != NULL)
                free(pp->ret_type.name);