X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=tools%2Fprotoparse.h;h=5ef8b4bcd890e43d0345b1306402d11af38b9901;hb=06c5d854748b35f194428e227ae44d7a6a46cd97;hp=a42f38e8ab9aef23ef724f95ba9f316eb79eeb1f;hpb=c36e914d6c0dd787c146395192fa14a7a2bd4218;p=ia32rtools.git diff --git a/tools/protoparse.h b/tools/protoparse.h index a42f38e..5ef8b4b 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -1,30 +1,75 @@ +struct parsed_proto; + +struct parsed_proto_arg { + char *reg; + const char *type; + struct parsed_proto *fptr; + void *datap; +}; + struct parsed_proto { - struct { - char *reg; - const char *type; - } arg[16]; + char name[256]; const char *ret_type; - int is_stdcall; + 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_fptr:1; + unsigned int is_array:1; }; static const char *hdrfn; static int hdrfline = 0; -static int find_protostr(char *dst, size_t dlen, FILE *fhdr, const char *sym) +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; + int ret; char *p; + if (sym[0] == '_' && strncmp(fname, "stdc", 4) == 0) + sym++; + symlen = strlen(sym); + rewind(fhdr); while (fgets(dst, dlen, fhdr)) { line++; - if (strstr(dst, sym) != NULL) + if (strncmp(dst, "//#include ", 11) == 0) { + finc_name = dst + 11; + p = strpbrk(finc_name, "\r\n "); + if (p != NULL) + *p = 0; + + finc = fopen(finc_name, "r"); + if (finc == NULL) { + printf("%s:%d: can't open '%s'\n", + fname, line, finc_name); + continue; + } + ret = find_protostr(dst, dlen, finc, + finc_name, sym_); + fclose(finc); + if (ret == 0) + break; + continue; + } + if (strncmp(sskip(dst), "//", 2) == 0) + continue; + + p = strstr(dst, sym); + if (p != NULL && p > dst + && (my_isblank(p[-1]) || my_issep(p[-1])) + && (my_isblank(p[symlen]) || my_issep(p[symlen]))) break; } hdrfline = line; @@ -63,6 +108,7 @@ static const char *known_types[] = { "void *", "char *", "FILE *", + "int *", "unsigned __int8", "unsigned __int16", "unsigned int", @@ -76,6 +122,7 @@ static const char *known_types[] = { "BYTE", "WORD", "DWORD", + "_DWORD", "HMODULE", "HANDLE", "HWND", @@ -83,13 +130,26 @@ static const char *known_types[] = { "size_t", }; +static int typecmp(const char *n, const char *t) +{ + for (; *t != 0; n++, t++) { + while (n[0] == ' ' && (n[1] == ' ' || n[1] == '*')) + n++; + while (t[0] == ' ' && (t[1] == ' ' || t[1] == '*')) + t++; + if (*n != *t) + return *n - *t; + } + + return 0; +} + static const char *check_type(const char *name) { - int i, l; + int i; for (i = 0; i < ARRAY_SIZE(known_types); i++) { - l = strlen(known_types[i]); - if (strncmp(known_types[i], name, l) == 0) + if (typecmp(name, known_types[i]) == 0) return known_types[i]; } @@ -117,37 +177,73 @@ static const char *map_reg(const char *reg) static int parse_protostr(char *protostr, struct parsed_proto *pp) { + struct parsed_proto_arg *arg; char regparm[16]; char buf[256]; char cconv[32]; const char *kt; int xarg = 0; + char *p, *p1; int ret; - char *p; 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); } + // 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, "extern ", 7) == 0) + p = sskip(p + 7); + kt = check_type(p); if (kt == NULL) { printf("%s:%d:%ld: unhandled return in '%s'\n", hdrfn, hdrfline, (p - protostr) + 1, protostr); - return 1; + return -1; } pp->ret_type = kt; p += strlen(kt); p = sskip(p); + if (!strchr(p, ')')) { + p = next_idt(buf, sizeof(buf), p); + p = sskip(p); + if (buf[0] == 0) { + printf("%s:%d:%ld: 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->is_array = 1; + } + return p - protostr; + } + + pp->is_func = 1; + + if (*p == '(') { + pp->is_fptr = 1; + p = sskip(p + 1); + } + p = next_word(cconv, sizeof(cconv), p); p = sskip(p); if (cconv[0] == 0) { printf("%s:%d:%ld: cconv missing\n", hdrfn, hdrfline, (p - protostr) + 1); - return 1; + return -1; } if (IS(cconv, "__cdecl")) pp->is_stdcall = 0; @@ -164,16 +260,26 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) else { printf("%s:%d:%ld: unhandled cconv: '%s'\n", hdrfn, hdrfline, (p - protostr) + 1, cconv); - return 1; + return -1; + } + + if (pp->is_fptr) { + if (*p != '*') { + printf("%s:%d:%ld: '*' expected\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + p = sskip(p + 1); } p = next_idt(buf, sizeof(buf), p); p = sskip(p); if (buf[0] == 0) { printf("%s:%d:%ld: func name missing\n", - hdrfn, hdrfline, (p - protostr) + 1); - return 1; + hdrfn, hdrfline, (p - protostr) + 1); + return -1; } + strcpy(pp->name, buf); ret = get_regparm(regparm, sizeof(regparm), p); if (ret > 0) { @@ -182,55 +288,89 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) { printf("%s:%d:%ld: bad regparm: %s\n", hdrfn, hdrfline, (p - protostr) + 1, regparm); - return 1; + return -1; } p += ret; p = sskip(p); } + if (pp->is_fptr) { + if (*p != ')') { + printf("%s:%d:%ld: ')' expected\n", + hdrfn, hdrfline, (p - protostr) + 1); + return -1; + } + p = sskip(p + 1); + } + if (*p != '(') { printf("%s:%d:%ld: '(' expected, got '%c'\n", hdrfn, hdrfline, (p - protostr) + 1, *p); - return 1; + return -1; } p++; + // check for x(void) + p = sskip(p); + if ((!strncmp(p, "void", 4) || !strncmp(p, "VOID", 4)) + && *sskip(p + 4) == ')') + p += 4; + while (1) { p = sskip(p); - if (*p == ')') + if (*p == ')') { + p++; break; + } if (*p == ',') p = sskip(p + 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", hdrfn, hdrfline, (p - protostr) + 1, xarg); - return 1; + return -1; } - pp->arg[xarg - 1].type = kt; + arg->type = kt; p += strlen(kt); p = sskip(p); + 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", + hdrfn, hdrfline, p1 - protostr); + return -1; + } + // we'll treat it as void * for non-calls + arg->type = "void *"; + + p = p1 + ret; + } + p = next_idt(buf, sizeof(buf), p); p = sskip(p); #if 0 if (buf[0] == 0) { printf("%s:%d:%ld: idt missing for arg%d\n", hdrfn, hdrfline, (p - protostr) + 1, xarg); - return 1; + return -1; } #endif - pp->arg[xarg - 1].reg = NULL; + arg->reg = NULL; ret = get_regparm(regparm, sizeof(regparm), p); if (ret > 0) { p += ret; p = sskip(p); - pp->arg[xarg - 1].reg = strdup(map_reg(regparm)); + arg->reg = strdup(map_reg(regparm)); } } @@ -259,7 +399,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) pp->argc_reg++; } - return 0; + return p - protostr; } static int proto_parse(FILE *fhdr, const char *sym, struct parsed_proto *pp) @@ -269,13 +409,13 @@ static int proto_parse(FILE *fhdr, const char *sym, struct parsed_proto *pp) memset(pp, 0, sizeof(*pp)); - ret = find_protostr(protostr, sizeof(protostr), fhdr, sym); + ret = find_protostr(protostr, sizeof(protostr), fhdr, hdrfn, sym); if (ret != 0) { printf("%s: sym '%s' is missing\n", hdrfn, sym); return ret; } - return parse_protostr(protostr, pp); + return parse_protostr(protostr, pp) < 0 ? -1 : 0; } static void proto_release(struct parsed_proto *pp) @@ -283,7 +423,9 @@ static void proto_release(struct parsed_proto *pp) int i; for (i = 0; i < pp->argc; i++) { - if (pp->arg[i].reg == NULL) + if (pp->arg[i].reg != NULL) free(pp->arg[i].reg); + if (pp->arg[i].fptr != NULL) + free(pp->arg[i].fptr); } }