4 struct parsed_proto_arg {
7 struct parsed_proto *fptr;
14 struct parsed_proto_arg arg[16];
18 unsigned int is_func:1;
19 unsigned int is_stdcall:1;
20 unsigned int is_vararg:1;
21 unsigned int is_fptr:1;
22 unsigned int is_array:1;
25 static const char *hdrfn;
26 static int hdrfline = 0;
28 static int find_protostr(char *dst, size_t dlen, FILE *fhdr,
29 const char *fname, const char *sym_)
31 const char *sym = sym_;
32 const char *finc_name;
39 if (sym[0] == '_' && strncmp(fname, "stdc", 4) == 0)
45 while (fgets(dst, dlen, fhdr))
48 if (strncmp(dst, "//#include ", 11) == 0) {
50 p = strpbrk(finc_name, "\r\n ");
54 finc = fopen(finc_name, "r");
56 printf("%s:%d: can't open '%s'\n",
57 fname, line, finc_name);
60 ret = find_protostr(dst, dlen, finc,
67 if (strncmp(sskip(dst), "//", 2) == 0)
71 if (p != NULL && p > dst
72 && (my_isblank(p[-1]) || my_issep(p[-1]))
73 && (my_isblank(p[symlen]) || my_issep(p[symlen])))
81 p = dst + strlen(dst);
82 for (p--; p > dst && my_isblank(*p); --p)
88 static int get_regparm(char *dst, size_t dlen, char *p)
95 for (o = 0, i = 1; o < dlen; i++) {
107 static const char *known_type_mod[] = {
113 static const char *known_types[] = {
140 // returns ptr to char after type ends
141 static const char *typecmp(const char *n, const char *t)
143 for (; *t != 0; n++, t++) {
144 while (n[0] == ' ' && (n[1] == ' ' || n[1] == '*'))
146 while (t[0] == ' ' && (t[1] == ' ' || t[1] == '*'))
155 static char *check_type(const char *name, int *len_out)
157 const char *n = name, *n1;
163 for (i = 0; i < ARRAY_SIZE(known_type_mod); i++) {
164 len = strlen(known_type_mod[i]);
165 if (strncmp(n, known_type_mod[i], len) != 0)
169 while (my_isblank(*n))
174 for (i = 0; i < ARRAY_SIZE(known_types); i++) {
175 n1 = typecmp(n, known_types[i]);
179 *len_out = n1 - name;
180 return strndup(name, *len_out);
186 /* args are always expanded to 32bit */
187 static const char *map_reg(const char *reg)
189 const char *regs_f[] = { "eax", "ebx", "ecx", "edx", "esi", "edi" };
190 const char *regs_w[] = { "ax", "bx", "cx", "dx", "si", "di" };
191 const char *regs_b[] = { "al", "bl", "cl", "dl" };
194 for (i = 0; i < ARRAY_SIZE(regs_w); i++)
195 if (IS(reg, regs_w[i]))
198 for (i = 0; i < ARRAY_SIZE(regs_b); i++)
199 if (IS(reg, regs_b[i]))
205 static int parse_protostr(char *protostr, struct parsed_proto *pp)
207 struct parsed_proto_arg *arg;
218 if (p[0] == '/' && p[1] == '/') {
219 printf("%s:%d: commented out?\n", hdrfn, hdrfline);
223 // strip unneeded stuff
224 for (p1 = p; p1[0] != 0 && p1[1] != 0; p1++) {
225 if ((p1[0] == '/' && p1[1] == '*')
226 || (p1[0] == '*' && p1[1] == '/'))
230 if (strncmp(p, "extern ", 7) == 0)
232 if (strncmp(p, "WINBASEAPI ", 11) == 0)
235 kt = check_type(p, &ret);
237 printf("%s:%d:%zd: unhandled return in '%s'\n",
238 hdrfn, hdrfline, (p - protostr) + 1, protostr);
244 if (!strchr(p, ')')) {
245 p = next_idt(buf, sizeof(buf), p);
248 printf("%s:%d:%zd: var name missing\n",
249 hdrfn, hdrfline, (p - protostr) + 1);
252 strcpy(pp->name, buf);
269 p = next_word(cconv, sizeof(cconv), p);
272 printf("%s:%d:%zd: cconv missing\n",
273 hdrfn, hdrfline, (p - protostr) + 1);
276 if (IS(cconv, "__cdecl"))
278 else if (IS(cconv, "__stdcall"))
280 else if (IS(cconv, "__fastcall"))
282 else if (IS(cconv, "__thiscall"))
284 else if (IS(cconv, "__userpurge"))
285 pp->is_stdcall = 1; // in all cases seen..
286 else if (IS(cconv, "__usercall"))
287 pp->is_stdcall = 0; // ..or is it?
288 else if (IS(cconv, "WINAPI"))
291 printf("%s:%d:%zd: unhandled cconv: '%s'\n",
292 hdrfn, hdrfline, (p - protostr) + 1, cconv);
298 printf("%s:%d:%zd: '*' expected\n",
299 hdrfn, hdrfline, (p - protostr) + 1);
305 p = next_idt(buf, sizeof(buf), p);
308 printf("%s:%d:%zd: func name missing\n",
309 hdrfn, hdrfline, (p - protostr) + 1);
312 strcpy(pp->name, buf);
314 ret = get_regparm(regparm, sizeof(regparm), p);
316 if (!IS(regparm, "eax") && !IS(regparm, "ax")
317 && !IS(regparm, "al"))
319 printf("%s:%d:%zd: bad regparm: %s\n",
320 hdrfn, hdrfline, (p - protostr) + 1, regparm);
329 printf("%s:%d:%zd: ')' expected\n",
330 hdrfn, hdrfline, (p - protostr) + 1);
337 printf("%s:%d:%zd: '(' expected, got '%c'\n",
338 hdrfn, hdrfline, (p - protostr) + 1, *p);
345 if ((!strncmp(p, "void", 4) || !strncmp(p, "VOID", 4))
346 && *sskip(p + 4) == ')')
358 if (!strncmp(p, "...", 3)) {
365 printf("%s:%d:%zd: ')' expected\n",
366 hdrfn, hdrfline, (p - protostr) + 1);
370 arg = &pp->arg[xarg];
374 kt = check_type(p, &ret);
376 printf("%s:%d:%zd: unhandled type for arg%d\n",
377 hdrfn, hdrfline, (p - protostr) + 1, xarg);
385 arg->fptr = calloc(1, sizeof(*arg->fptr));
386 ret = parse_protostr(p1, arg->fptr);
388 printf("%s:%d:%zd: funcarg parse failed\n",
389 hdrfn, hdrfline, p1 - protostr);
392 // we'll treat it as void * for non-calls
393 arg->type = "void *";
398 p = next_idt(buf, sizeof(buf), p);
402 printf("%s:%d:%zd: idt missing for arg%d\n",
403 hdrfn, hdrfline, (p - protostr) + 1, xarg);
409 ret = get_regparm(regparm, sizeof(regparm), p);
414 arg->reg = strdup(map_reg(regparm));
418 if (xarg > 0 && (IS(cconv, "__fastcall") || IS(cconv, "__thiscall"))) {
419 if (pp->arg[0].reg != NULL) {
420 printf("%s:%d: %s with arg1 spec %s?\n",
421 hdrfn, hdrfline, cconv, pp->arg[0].reg);
423 pp->arg[0].reg = strdup("ecx");
426 if (xarg > 1 && IS(cconv, "__fastcall")) {
427 if (pp->arg[1].reg != NULL) {
428 printf("%s:%d: %s with arg2 spec %s?\n",
429 hdrfn, hdrfline, cconv, pp->arg[1].reg);
431 pp->arg[1].reg = strdup("edx");
434 if (pp->is_vararg && pp->is_stdcall) {
435 printf("%s:%d: vararg stdcall?\n", hdrfn, hdrfline);
441 for (i = 0; i < pp->argc; i++) {
442 if (pp->arg[i].reg == NULL)
451 static int proto_parse(FILE *fhdr, const char *sym, struct parsed_proto *pp)
456 memset(pp, 0, sizeof(*pp));
458 ret = find_protostr(protostr, sizeof(protostr), fhdr, hdrfn, sym);
460 printf("%s: sym '%s' is missing\n", hdrfn, sym);
464 return parse_protostr(protostr, pp) < 0 ? -1 : 0;
467 static void proto_release(struct parsed_proto *pp)
471 for (i = 0; i < pp->argc; i++) {
472 if (pp->arg[i].reg != NULL)
473 free(pp->arg[i].reg);
474 if (pp->arg[i].type != NULL)
475 free(pp->arg[i].type);
476 if (pp->arg[i].fptr != NULL)
477 free(pp->arg[i].fptr);
479 if (pp->ret_type != NULL)