4 struct parsed_proto_arg {
7 struct parsed_proto *fptr;
14 struct parsed_proto_arg arg[16];
18 unsigned int is_stdcall:1;
19 unsigned int is_fptr:1;
22 static const char *hdrfn;
23 static int hdrfline = 0;
25 static int find_protostr(char *dst, size_t dlen, FILE *fhdr,
26 const char *fname, const char *sym_)
28 const char *sym = sym_;
35 if (sym[0] == '_' && strncmp(fname, "stdc", 4) == 0)
41 while (fgets(dst, dlen, fhdr))
44 if (strncmp(dst, "#include ", 9) == 0) {
45 p = strpbrk(dst + 9, "\r\n ");
49 finc = fopen(dst + 9, "r");
51 printf("%s:%d: can't open '%s'\n",
52 fname, line, dst + 9);
55 ret = find_protostr(dst, dlen, finc,
65 && (my_isblank(p[symlen]) || my_issep(p[symlen])))
73 p = dst + strlen(dst);
74 for (p--; p > dst && my_isblank(*p); --p)
80 static int get_regparm(char *dst, size_t dlen, char *p)
87 for (o = 0, i = 1; o < dlen; i++) {
99 static const char *known_types[] = {
126 static int typecmp(const char *n, const char *t)
128 for (; *t != 0; n++, t++) {
129 while (n[0] == ' ' && (n[1] == ' ' || n[1] == '*'))
131 while (t[0] == ' ' && (t[1] == ' ' || t[1] == '*'))
140 static const char *check_type(const char *name)
144 for (i = 0; i < ARRAY_SIZE(known_types); i++) {
145 if (typecmp(name, known_types[i]) == 0)
146 return known_types[i];
152 /* args are always expanded to 32bit */
153 static const char *map_reg(const char *reg)
155 const char *regs_f[] = { "eax", "ebx", "ecx", "edx", "esi", "edi" };
156 const char *regs_w[] = { "ax", "bx", "cx", "dx", "si", "di" };
157 const char *regs_b[] = { "al", "bl", "cl", "dl" };
160 for (i = 0; i < ARRAY_SIZE(regs_w); i++)
161 if (IS(reg, regs_w[i]))
164 for (i = 0; i < ARRAY_SIZE(regs_b); i++)
165 if (IS(reg, regs_b[i]))
171 static int parse_protostr(char *protostr, struct parsed_proto *pp)
173 struct parsed_proto_arg *arg;
184 if (p[0] == '/' && p[1] == '/') {
185 //printf("warning: decl for sym '%s' is commented out\n", sym);
191 printf("%s:%d:%ld: unhandled return in '%s'\n",
192 hdrfn, hdrfline, (p - protostr) + 1, protostr);
204 p = next_word(cconv, sizeof(cconv), p);
207 printf("%s:%d:%ld: cconv missing\n",
208 hdrfn, hdrfline, (p - protostr) + 1);
211 if (IS(cconv, "__cdecl"))
213 else if (IS(cconv, "__stdcall"))
215 else if (IS(cconv, "__fastcall"))
217 else if (IS(cconv, "__thiscall"))
219 else if (IS(cconv, "__userpurge"))
220 pp->is_stdcall = 1; // in all cases seen..
221 else if (IS(cconv, "__usercall"))
222 pp->is_stdcall = 0; // ..or is it?
224 printf("%s:%d:%ld: unhandled cconv: '%s'\n",
225 hdrfn, hdrfline, (p - protostr) + 1, cconv);
231 printf("%s:%d:%ld: '*' expected\n",
232 hdrfn, hdrfline, (p - protostr) + 1);
238 p = next_idt(buf, sizeof(buf), p);
241 printf("%s:%d:%ld: func name missing\n",
242 hdrfn, hdrfline, (p - protostr) + 1);
245 strcpy(pp->name, buf);
247 ret = get_regparm(regparm, sizeof(regparm), p);
249 if (!IS(regparm, "eax") && !IS(regparm, "ax")
250 && !IS(regparm, "al"))
252 printf("%s:%d:%ld: bad regparm: %s\n",
253 hdrfn, hdrfline, (p - protostr) + 1, regparm);
262 printf("%s:%d:%ld: ')' expected\n",
263 hdrfn, hdrfline, (p - protostr) + 1);
270 printf("%s:%d:%ld: '(' expected, got '%c'\n",
271 hdrfn, hdrfline, (p - protostr) + 1, *p);
278 if (strncmp(p, "void", 4) == 0 && *sskip(p + 4) == ')')
290 arg = &pp->arg[xarg];
296 printf("%s:%d:%ld: unhandled type for arg%d\n",
297 hdrfn, hdrfline, (p - protostr) + 1, xarg);
306 arg->fptr = calloc(1, sizeof(*arg->fptr));
307 ret = parse_protostr(p1, arg->fptr);
309 printf("%s:%d:%ld: funcarg parse failed\n",
310 hdrfn, hdrfline, p1 - protostr);
313 // we'll treat it as void * for non-calls
314 arg->type = "void *";
319 p = next_idt(buf, sizeof(buf), p);
323 printf("%s:%d:%ld: idt missing for arg%d\n",
324 hdrfn, hdrfline, (p - protostr) + 1, xarg);
330 ret = get_regparm(regparm, sizeof(regparm), p);
335 arg->reg = strdup(map_reg(regparm));
339 if (xarg > 0 && (IS(cconv, "__fastcall") || IS(cconv, "__thiscall"))) {
340 if (pp->arg[0].reg != NULL) {
341 printf("%s:%d: %s with arg1 spec %s?\n",
342 hdrfn, hdrfline, cconv, pp->arg[0].reg);
344 pp->arg[0].reg = strdup("ecx");
347 if (xarg > 1 && IS(cconv, "__fastcall")) {
348 if (pp->arg[1].reg != NULL) {
349 printf("%s:%d: %s with arg2 spec %s?\n",
350 hdrfn, hdrfline, cconv, pp->arg[1].reg);
352 pp->arg[1].reg = strdup("edx");
357 for (i = 0; i < pp->argc; i++) {
358 if (pp->arg[i].reg == NULL)
367 static int proto_parse(FILE *fhdr, const char *sym, struct parsed_proto *pp)
372 memset(pp, 0, sizeof(*pp));
374 ret = find_protostr(protostr, sizeof(protostr), fhdr, hdrfn, sym);
376 printf("%s: sym '%s' is missing\n", hdrfn, sym);
380 return parse_protostr(protostr, pp) < 0 ? -1 : 0;
383 static void proto_release(struct parsed_proto *pp)
387 for (i = 0; i < pp->argc; i++) {
388 if (pp->arg[i].reg != NULL)
389 free(pp->arg[i].reg);
390 if (pp->arg[i].fptr != NULL)
391 free(pp->arg[i].fptr);