X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tools%2Fprotoparse.h;h=39bbd2c6921ffeab58ef4d57cd6cc075a35af72b;hb=e56ab892c4ff9eef34f85fab010d7084b9c59e81;hp=533dd467b8b88e4917893fcd3532b9fa62868580;hpb=39b168b8949dfc08ec521a70cdc4440dce1ef207;p=ia32rtools.git diff --git a/tools/protoparse.h b/tools/protoparse.h index 533dd46..39bbd2c 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -1,22 +1,34 @@ struct parsed_proto; +struct parsed_type { + char *name; + unsigned int is_array:1; + unsigned int is_ptr:1; +}; + struct parsed_proto_arg { char *reg; - const char *type; + struct parsed_type type; struct parsed_proto *fptr; void *datap; }; struct parsed_proto { char name[256]; - const char *ret_type; + union { + struct parsed_type ret_type; + struct parsed_type type; + }; struct parsed_proto_arg arg[16]; int argc; int argc_stack; int argc_reg; + unsigned int is_func:1; unsigned int is_stdcall:1; + unsigned int is_vararg:1; unsigned int is_fptr:1; + unsigned int is_noreturn:1; }; static const char *hdrfn; @@ -26,6 +38,7 @@ static int find_protostr(char *dst, size_t dlen, FILE *fhdr, const char *fname, const char *sym_) { const char *sym = sym_; + const char *finc_name; FILE *finc; int symlen; int line = 0; @@ -41,27 +54,31 @@ static int find_protostr(char *dst, size_t dlen, FILE *fhdr, while (fgets(dst, dlen, fhdr)) { line++; - if (strncmp(dst, "#include ", 9) == 0) { - p = strpbrk(dst + 9, "\r\n "); + if (strncmp(dst, "//#include ", 11) == 0) { + finc_name = dst + 11; + p = strpbrk(finc_name, "\r\n "); if (p != NULL) *p = 0; - finc = fopen(dst + 9, "r"); + finc = fopen(finc_name, "r"); if (finc == NULL) { printf("%s:%d: can't open '%s'\n", - fname, line, dst + 9); + fname, line, finc_name); continue; } ret = find_protostr(dst, dlen, finc, - dst + 9, sym_); + finc_name, sym_); fclose(finc); if (ret == 0) break; continue; } + if (strncmp(sskip(dst), "//", 2) == 0) + continue; p = strstr(dst, sym); - if (p != NULL + if (p != NULL && p > dst + && (my_isblank(p[-1]) || my_issep(p[-1])) && (my_isblank(p[symlen]) || my_issep(p[symlen]))) break; } @@ -96,33 +113,47 @@ static int get_regparm(char *dst, size_t dlen, char *p) } // hmh.. -static const char *known_types[] = { - "const void *", - "void *", - "char *", - "FILE *", - "int *", - "unsigned __int8", - "unsigned __int16", - "unsigned int", - "signed int", - "char", - "__int8", - "__int16", - "int", - "bool", - "void", - "BYTE", - "WORD", - "DWORD", - "_DWORD", - "HMODULE", +static const char *known_type_mod[] = { + "const", + "signed", + "unsigned", + "struct", + "enum", +}; + +static const char *known_ptr_types[] = { + "HACCEL", "HANDLE", + "HBITMAP", + "HCURSOR", + "HDC", + "HGDIOBJ", + "HGLOBAL", + "HINSTANCE", + "HMODULE", + "HRGN", + "HRSRC", + "HKEY", + "HMENU", "HWND", - "LPCSTR", - "size_t", + "PLONG", + "PDWORD", + "PVOID", + "PCVOID", + "DLGPROC", + "va_list", + "__VALIST", +}; + +static const char *ignored_keywords[] = { + "extern", + "WINBASEAPI", + "WINUSERAPI", + "WINGDIAPI", + "WINADVAPI", }; +// returns ptr to char after type ends static int typecmp(const char *n, const char *t) { for (; *t != 0; n++, t++) { @@ -137,16 +168,63 @@ static int typecmp(const char *n, const char *t) return 0; } -static const char *check_type(const char *name) +static const char *skip_type_mod(const char *n) { + int len; int i; - for (i = 0; i < ARRAY_SIZE(known_types); i++) { - if (typecmp(name, known_types[i]) == 0) - return known_types[i]; + for (i = 0; i < ARRAY_SIZE(known_type_mod); i++) { + len = strlen(known_type_mod[i]); + if (strncmp(n, known_type_mod[i], len) != 0) + continue; + + n += len; + while (my_isblank(*n)) + n++; + i = 0; + } + + return n; +} + +static int check_type(const char *name, struct parsed_type *type) +{ + const char *n, *n1; + int ret = -1; + int i; + + n = skip_type_mod(name); + + for (i = 0; i < ARRAY_SIZE(known_ptr_types); i++) { + if (typecmp(n, known_ptr_types[i])) + continue; + + type->is_ptr = 1; + break; + } + + if (n[0] == 'L' && n[1] == 'P') + type->is_ptr = 1; + + // assume single word + while (!my_isblank(*n) && !my_issep(*n)) + n++; + + while (1) { + n1 = n; + while (my_isblank(*n)) + n++; + if (*n == '*') { + type->is_ptr = 1; + n++; + continue; + } + break; } - return NULL; + ret = n1 - name; + type->name = strndup(name, ret); + return ret; } /* args are always expanded to 32bit */ @@ -174,27 +252,62 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) char regparm[16]; char buf[256]; char cconv[32]; - const char *kt; int xarg = 0; char *p, *p1; + int i, l; int ret; - int i; - p = protostr; + p = sskip(protostr); if (p[0] == '/' && p[1] == '/') { - //printf("warning: decl for sym '%s' is commented out\n", sym); + printf("%s:%d: commented out?\n", hdrfn, hdrfline); p = sskip(p + 2); } - kt = check_type(p); - if (kt == NULL) { - printf("%s:%d:%ld: unhandled return in '%s'\n", + // strip unneeded stuff + for (p1 = p; p1[0] != 0 && p1[1] != 0; p1++) { + if ((p1[0] == '/' && p1[1] == '*') + || (p1[0] == '*' && p1[1] == '/')) + p1[0] = p1[1] = ' '; + } + + if (!strncmp(p, "DECLSPEC_NORETURN ", 18)) { + pp->is_noreturn = 1; + p = sskip(p + 18); + } + + for (i = 0; i < ARRAY_SIZE(ignored_keywords); i++) { + l = strlen(ignored_keywords[i]); + if (!strncmp(p, ignored_keywords[i], l) && my_isblank(p[l])) + p = sskip(p + l + 1); + } + + ret = check_type(p, &pp->ret_type); + if (ret <= 0) { + printf("%s:%d:%zd: unhandled return in '%s'\n", hdrfn, hdrfline, (p - protostr) + 1, protostr); return -1; } - pp->ret_type = kt; - p += strlen(kt); - p = sskip(p); + p = sskip(p + ret); + + 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", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + strcpy(pp->name, buf); + + p1 = strchr(p, ']'); + if (p1 != NULL) { + p = p1 + 1; + pp->ret_type.is_array = 1; + } + return p - protostr; + } + + pp->is_func = 1; if (*p == '(') { pp->is_fptr = 1; @@ -204,7 +317,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) p = next_word(cconv, sizeof(cconv), p); p = sskip(p); if (cconv[0] == 0) { - printf("%s:%d:%ld: cconv missing\n", + printf("%s:%d:%zd: cconv missing\n", hdrfn, hdrfline, (p - protostr) + 1); return -1; } @@ -220,15 +333,17 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) pp->is_stdcall = 1; // in all cases seen.. else if (IS(cconv, "__usercall")) pp->is_stdcall = 0; // ..or is it? + else if (IS(cconv, "WINAPI")) + pp->is_stdcall = 1; else { - printf("%s:%d:%ld: unhandled cconv: '%s'\n", + printf("%s:%d:%zd: unhandled cconv: '%s'\n", hdrfn, hdrfline, (p - protostr) + 1, cconv); return -1; } if (pp->is_fptr) { if (*p != '*') { - printf("%s:%d:%ld: '*' expected\n", + printf("%s:%d:%zd: '*' expected\n", hdrfn, hdrfline, (p - protostr) + 1); return -1; } @@ -238,7 +353,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) p = next_idt(buf, sizeof(buf), p); p = sskip(p); if (buf[0] == 0) { - printf("%s:%d:%ld: func name missing\n", + printf("%s:%d:%zd: func name missing\n", hdrfn, hdrfline, (p - protostr) + 1); return -1; } @@ -249,7 +364,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) if (!IS(regparm, "eax") && !IS(regparm, "ax") && !IS(regparm, "al")) { - printf("%s:%d:%ld: bad regparm: %s\n", + printf("%s:%d:%zd: bad regparm: %s\n", hdrfn, hdrfline, (p - protostr) + 1, regparm); return -1; } @@ -259,7 +374,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) if (pp->is_fptr) { if (*p != ')') { - printf("%s:%d:%ld: ')' expected\n", + printf("%s:%d:%zd: ')' expected\n", hdrfn, hdrfline, (p - protostr) + 1); return -1; } @@ -267,7 +382,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) } if (*p != '(') { - printf("%s:%d:%ld: '(' expected, got '%c'\n", + printf("%s:%d:%zd: '(' expected, got '%c'\n", hdrfn, hdrfline, (p - protostr) + 1, *p); return -1; } @@ -275,7 +390,8 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) // check for x(void) p = sskip(p); - if (strncmp(p, "void", 4) == 0 && *sskip(p + 4) == ')') + if ((!strncmp(p, "void", 4) || !strncmp(p, "VOID", 4)) + && *sskip(p + 4) == ')') p += 4; while (1) { @@ -287,31 +403,42 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) if (*p == ',') p = sskip(p + 1); + if (!strncmp(p, "...", 3)) { + pp->is_vararg = 1; + p = sskip(p + 3); + if (*p == ')') { + p++; + break; + } + printf("%s:%d:%zd: ')' expected\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + arg = &pp->arg[xarg]; xarg++; p1 = p; - kt = check_type(p); - if (kt == NULL) { - printf("%s:%d:%ld: unhandled type for arg%d\n", + ret = check_type(p, &arg->type); + if (ret <= 0) { + printf("%s:%d:%zd: unhandled type for arg%d\n", hdrfn, hdrfline, (p - protostr) + 1, xarg); return -1; } - arg->type = kt; - p += strlen(kt); - p = sskip(p); + p = sskip(p + ret); if (*p == '(') { // func ptr arg->fptr = calloc(1, sizeof(*arg->fptr)); ret = parse_protostr(p1, arg->fptr); if (ret < 0) { - printf("%s:%d:%ld: funcarg parse failed\n", + printf("%s:%d:%zd: funcarg parse failed\n", hdrfn, hdrfline, p1 - protostr); return -1; } // we'll treat it as void * for non-calls - arg->type = "void *"; + arg->type.name = "void *"; + arg->type.is_ptr = 1; p = p1 + ret; } @@ -320,7 +447,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) p = sskip(p); #if 0 if (buf[0] == 0) { - printf("%s:%d:%ld: idt missing for arg%d\n", + printf("%s:%d:%zd: idt missing for arg%d\n", hdrfn, hdrfline, (p - protostr) + 1, xarg); return -1; } @@ -352,6 +479,11 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) pp->arg[1].reg = strdup("edx"); } + if (pp->is_vararg && pp->is_stdcall) { + printf("%s:%d: vararg stdcall?\n", hdrfn, hdrfline); + return -1; + } + pp->argc = xarg; for (i = 0; i < pp->argc; i++) { @@ -387,7 +519,11 @@ static void proto_release(struct parsed_proto *pp) 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].fptr != NULL) free(pp->arg[i].fptr); } + if (pp->ret_type.name != NULL) + free(pp->ret_type.name); }