cvt_data: use .hword (consistent 2 bytes), offsets from ;.org
[ia32rtools.git] / tools / protoparse.h
CommitLineData
c36e914d 1
39b168b8 2struct parsed_proto;
3
3ebea2cf 4struct parsed_type {
5 char *name;
6 unsigned int is_array:1;
7 unsigned int is_ptr:1;
a652aa9f 8 unsigned int is_struct:1; // split for args
1f84f6b3 9 unsigned int is_retreg:1; // register to return
3ebea2cf 10};
11
39b168b8 12struct parsed_proto_arg {
13 char *reg;
3ebea2cf 14 struct parsed_type type;
39b168b8 15 struct parsed_proto *fptr;
16 void *datap;
17};
18
c36e914d 19struct parsed_proto {
39b168b8 20 char name[256];
3ebea2cf 21 union {
22 struct parsed_type ret_type;
23 struct parsed_type type;
24 };
39b168b8 25 struct parsed_proto_arg arg[16];
c36e914d 26 int argc;
27 int argc_stack;
28 int argc_reg;
06c5d854 29 unsigned int is_func:1;
39b168b8 30 unsigned int is_stdcall:1;
c0050df6 31 unsigned int is_fastcall:1;
efea2951 32 unsigned int is_vararg:1; // vararg func
39b168b8 33 unsigned int is_fptr:1;
e56ab892 34 unsigned int is_noreturn:1;
89ff3147 35 unsigned int is_unresolved:1;
1f84f6b3 36 unsigned int is_userstack:1;
efea2951 37 unsigned int is_arg:1; // decl in func arg
a652aa9f 38 unsigned int has_structarg:1;
1f84f6b3 39 unsigned int has_retreg:1;
c36e914d 40};
41
42static const char *hdrfn;
43static int hdrfline = 0;
44
a652aa9f 45static void pp_copy_arg(struct parsed_proto_arg *d,
46 const struct parsed_proto_arg *s);
47
bd96f656 48static int b_pp_c_handler(char *proto, const char *fname);
49
50static int do_protostrs(FILE *fhdr, const char *fname)
c36e914d 51{
06c5d854 52 const char *finc_name;
bd96f656 53 const char *hdrfn_saved;
54 char protostr[256];
36595fd2 55 char path[256];
56 char fname_inc[256];
39b168b8 57 FILE *finc;
c36e914d 58 int line = 0;
39b168b8 59 int ret;
c36e914d 60 char *p;
61
bd96f656 62 hdrfn_saved = hdrfn;
63 hdrfn = fname;
39b168b8 64
bd96f656 65 while (fgets(protostr, sizeof(protostr), fhdr))
c36e914d 66 {
67 line++;
bd96f656 68 if (strncmp(protostr, "//#include ", 11) == 0) {
69 finc_name = protostr + 11;
06c5d854 70 p = strpbrk(finc_name, "\r\n ");
39b168b8 71 if (p != NULL)
72 *p = 0;
73
36595fd2 74 path[0] = 0;
75 p = strrchr(hdrfn_saved, '/');
76 if (p) {
77 memcpy(path, hdrfn_saved,
78 p - hdrfn_saved + 1);
79 path[p - hdrfn_saved + 1] = 0;
80 }
81 snprintf(fname_inc, sizeof(fname_inc), "%s%s",
82 path, finc_name);
83 finc = fopen(fname_inc, "r");
39b168b8 84 if (finc == NULL) {
85 printf("%s:%d: can't open '%s'\n",
36595fd2 86 fname_inc, line, finc_name);
39b168b8 87 continue;
88 }
bd96f656 89 ret = do_protostrs(finc, finc_name);
39b168b8 90 fclose(finc);
bd96f656 91 if (ret < 0)
39b168b8 92 break;
93 continue;
94 }
bd96f656 95 if (strncmp(sskip(protostr), "//", 2) == 0)
96 continue;
97
98 p = protostr + strlen(protostr);
99 for (p--; p >= protostr && my_isblank(*p); --p)
100 *p = 0;
101 if (p < protostr)
06c5d854 102 continue;
39b168b8 103
bd96f656 104 hdrfline = line;
105
106 ret = b_pp_c_handler(protostr, hdrfn);
107 if (ret < 0)
c36e914d 108 break;
109 }
c36e914d 110
bd96f656 111 hdrfn = hdrfn_saved;
c36e914d 112
bd96f656 113 if (feof(fhdr))
114 return 0;
c36e914d 115
bd96f656 116 return -1;
c36e914d 117}
118
1f84f6b3 119static int get_regparm(char *dst, size_t dlen, char *p, int *retreg)
c36e914d 120{
1f84f6b3 121 int i = 0, o;
122
123 *retreg = 0;
c36e914d 124
125 if (*p != '<')
126 return 0;
127
1f84f6b3 128 i++;
129 if (p[i] == '*') {
130 *retreg = 1;
131 i++;
132 }
133
134 for (o = 0; o < dlen; i++) {
c36e914d 135 if (p[i] == 0)
136 return 0;
137 if (p[i] == '>')
138 break;
139 dst[o++] = p[i];
140 }
141 dst[o] = 0;
142 return i + 1;
143}
144
145// hmh..
64c59faf 146static const char *known_type_mod[] = {
147 "const",
148 "signed",
149 "unsigned",
3ebea2cf 150 "struct",
151 "enum",
840257f6 152 "CONST",
92804a48 153 "volatile",
64c59faf 154};
155
3ebea2cf 156static const char *known_ptr_types[] = {
da87ae38 157 "FARPROC",
92804a48 158 "WNDPROC",
e56ab892 159 "HACCEL",
c36e914d 160 "HANDLE",
e56ab892 161 "HBITMAP",
162 "HCURSOR",
3ebea2cf 163 "HDC",
a652aa9f 164 "HFONT",
3ebea2cf 165 "HGDIOBJ",
e56ab892 166 "HGLOBAL",
da87ae38 167 "HICON",
e56ab892 168 "HINSTANCE",
c7ed83dd 169 "HIMC", // DWORD in mingw, ptr in wine..
e56ab892 170 "HMODULE",
da87ae38 171 "HPALETTE",
e56ab892 172 "HRGN",
173 "HRSRC",
174 "HKEY",
175 "HMENU",
7aca4698 176 "HWAVEOUT",
e56ab892 177 "HWND",
ef6b315d 178 "PBYTE",
a2c1d768 179 "PCRITICAL_SECTION",
3ebea2cf 180 "PDWORD",
92804a48 181 "PFILETIME",
94d447fb 182 "PHKEY",
183 "PLONG",
a2c1d768 184 "PMEMORY_BASIC_INFORMATION",
46411e6c 185 "PUINT",
3ebea2cf 186 "PVOID",
187 "PCVOID",
ef6b315d 188 "PWORD",
e56ab892 189 "DLGPROC",
cdfaeed7 190 "TIMERPROC",
191 "WNDENUMPROC",
4f12f671 192 "va_list",
193 "__VALIST",
3ebea2cf 194};
195
196static const char *ignored_keywords[] = {
197 "extern",
198 "WINBASEAPI",
199 "WINUSERAPI",
4f12f671 200 "WINGDIAPI",
201 "WINADVAPI",
c36e914d 202};
203
64c59faf 204// returns ptr to char after type ends
3ebea2cf 205static int typecmp(const char *n, const char *t)
39b168b8 206{
207 for (; *t != 0; n++, t++) {
208 while (n[0] == ' ' && (n[1] == ' ' || n[1] == '*'))
209 n++;
210 while (t[0] == ' ' && (t[1] == ' ' || t[1] == '*'))
211 t++;
212 if (*n != *t)
3ebea2cf 213 return *n - *t;
39b168b8 214 }
215
3ebea2cf 216 return 0;
39b168b8 217}
218
3ebea2cf 219static const char *skip_type_mod(const char *n)
c36e914d 220{
64c59faf 221 int len;
39b168b8 222 int i;
c36e914d 223
64c59faf 224 for (i = 0; i < ARRAY_SIZE(known_type_mod); i++) {
225 len = strlen(known_type_mod[i]);
226 if (strncmp(n, known_type_mod[i], len) != 0)
227 continue;
bd96f656 228 if (!my_isblank(n[len]))
229 continue;
64c59faf 230
231 n += len;
232 while (my_isblank(*n))
233 n++;
234 i = 0;
235 }
236
3ebea2cf 237 return n;
238}
239
240static int check_type(const char *name, struct parsed_type *type)
241{
242 const char *n, *n1;
243 int ret = -1;
244 int i;
245
246 n = skip_type_mod(name);
247
248 for (i = 0; i < ARRAY_SIZE(known_ptr_types); i++) {
249 if (typecmp(n, known_ptr_types[i]))
64c59faf 250 continue;
251
3ebea2cf 252 type->is_ptr = 1;
253 break;
c36e914d 254 }
255
a652aa9f 256 if (n[0] == 'L' && n[1] == 'P' && strncmp(n, "LPARAM", 6))
3ebea2cf 257 type->is_ptr = 1;
258
259 // assume single word
260 while (!my_isblank(*n) && !my_issep(*n))
261 n++;
262
263 while (1) {
264 n1 = n;
265 while (my_isblank(*n))
266 n++;
267 if (*n == '*') {
268 type->is_ptr = 1;
269 n++;
270 continue;
271 }
272 break;
273 }
274
275 ret = n1 - name;
276 type->name = strndup(name, ret);
a2c1d768 277 if (IS(type->name, "VOID"))
278 memcpy(type->name, "void", 4);
279
3ebea2cf 280 return ret;
c36e914d 281}
282
283/* args are always expanded to 32bit */
284static const char *map_reg(const char *reg)
285{
286 const char *regs_f[] = { "eax", "ebx", "ecx", "edx", "esi", "edi" };
287 const char *regs_w[] = { "ax", "bx", "cx", "dx", "si", "di" };
288 const char *regs_b[] = { "al", "bl", "cl", "dl" };
289 int i;
290
291 for (i = 0; i < ARRAY_SIZE(regs_w); i++)
292 if (IS(reg, regs_w[i]))
293 return regs_f[i];
294
295 for (i = 0; i < ARRAY_SIZE(regs_b); i++)
296 if (IS(reg, regs_b[i]))
297 return regs_f[i];
298
299 return reg;
300}
301
a652aa9f 302static int check_struct_arg(struct parsed_proto_arg *arg)
303{
304 if (IS(arg->type.name, "POINT"))
305 return 2 - 1;
306
307 return 0;
308}
309
c36e914d 310static int parse_protostr(char *protostr, struct parsed_proto *pp)
311{
39b168b8 312 struct parsed_proto_arg *arg;
c36e914d 313 char regparm[16];
314 char buf[256];
315 char cconv[32];
1f84f6b3 316 int is_retreg;
c36e914d 317 int xarg = 0;
39b168b8 318 char *p, *p1;
3ebea2cf 319 int i, l;
c36e914d 320 int ret;
c36e914d 321
06c5d854 322 p = sskip(protostr);
c36e914d 323 if (p[0] == '/' && p[1] == '/') {
06c5d854 324 printf("%s:%d: commented out?\n", hdrfn, hdrfline);
c36e914d 325 p = sskip(p + 2);
326 }
327
06c5d854 328 // strip unneeded stuff
329 for (p1 = p; p1[0] != 0 && p1[1] != 0; p1++) {
330 if ((p1[0] == '/' && p1[1] == '*')
331 || (p1[0] == '*' && p1[1] == '/'))
332 p1[0] = p1[1] = ' ';
333 }
334
e56ab892 335 if (!strncmp(p, "DECLSPEC_NORETURN ", 18)) {
336 pp->is_noreturn = 1;
337 p = sskip(p + 18);
338 }
339
3ebea2cf 340 for (i = 0; i < ARRAY_SIZE(ignored_keywords); i++) {
341 l = strlen(ignored_keywords[i]);
342 if (!strncmp(p, ignored_keywords[i], l) && my_isblank(p[l]))
343 p = sskip(p + l + 1);
344 }
06c5d854 345
3ebea2cf 346 ret = check_type(p, &pp->ret_type);
347 if (ret <= 0) {
63df67be 348 printf("%s:%d:%zd: unhandled return in '%s'\n",
c36e914d 349 hdrfn, hdrfline, (p - protostr) + 1, protostr);
39b168b8 350 return -1;
c36e914d 351 }
64c59faf 352 p = sskip(p + ret);
c36e914d 353
da87ae38 354 if (!strncmp(p, "noreturn ", 9)) {
355 pp->is_noreturn = 1;
356 p = sskip(p + 9);
357 }
358
06c5d854 359 if (!strchr(p, ')')) {
360 p = next_idt(buf, sizeof(buf), p);
361 p = sskip(p);
362 if (buf[0] == 0) {
63df67be 363 printf("%s:%d:%zd: var name missing\n",
06c5d854 364 hdrfn, hdrfline, (p - protostr) + 1);
365 return -1;
366 }
367 strcpy(pp->name, buf);
368
369 p1 = strchr(p, ']');
370 if (p1 != NULL) {
371 p = p1 + 1;
3ebea2cf 372 pp->ret_type.is_array = 1;
06c5d854 373 }
374 return p - protostr;
375 }
376
377 pp->is_func = 1;
378
39b168b8 379 if (*p == '(') {
380 pp->is_fptr = 1;
381 p = sskip(p + 1);
382 }
383
c36e914d 384 p = next_word(cconv, sizeof(cconv), p);
385 p = sskip(p);
386 if (cconv[0] == 0) {
63df67be 387 printf("%s:%d:%zd: cconv missing\n",
c36e914d 388 hdrfn, hdrfline, (p - protostr) + 1);
39b168b8 389 return -1;
c36e914d 390 }
391 if (IS(cconv, "__cdecl"))
392 pp->is_stdcall = 0;
393 else if (IS(cconv, "__stdcall"))
394 pp->is_stdcall = 1;
c0050df6 395 else if (IS(cconv, "__fastcall")) {
396 pp->is_fastcall = 1;
397 pp->is_stdcall = 1; // sort of..
398 }
c36e914d 399 else if (IS(cconv, "__thiscall"))
400 pp->is_stdcall = 1;
401 else if (IS(cconv, "__userpurge"))
de50b98b 402 pp->is_stdcall = 1; // IDA
c36e914d 403 else if (IS(cconv, "__usercall"))
de50b98b 404 pp->is_stdcall = 0; // IDA
1f84f6b3 405 else if (IS(cconv, "__userstack")) {
406 pp->is_stdcall = 0; // custom
407 pp->is_userstack = 1;
408 }
64c59faf 409 else if (IS(cconv, "WINAPI"))
410 pp->is_stdcall = 1;
c36e914d 411 else {
63df67be 412 printf("%s:%d:%zd: unhandled cconv: '%s'\n",
c36e914d 413 hdrfn, hdrfline, (p - protostr) + 1, cconv);
39b168b8 414 return -1;
415 }
416
417 if (pp->is_fptr) {
418 if (*p != '*') {
63df67be 419 printf("%s:%d:%zd: '*' expected\n",
39b168b8 420 hdrfn, hdrfline, (p - protostr) + 1);
421 return -1;
422 }
bd96f656 423 p++;
424 // XXX: skipping extra asterisks, for now
425 while (*p == '*')
426 p++;
427 p = sskip(p);
c36e914d 428 }
429
430 p = next_idt(buf, sizeof(buf), p);
431 p = sskip(p);
432 if (buf[0] == 0) {
de50b98b 433 //printf("%s:%d:%zd: func name missing\n",
434 // hdrfn, hdrfline, (p - protostr) + 1);
435 //return -1;
c36e914d 436 }
39b168b8 437 strcpy(pp->name, buf);
c36e914d 438
1f84f6b3 439 ret = get_regparm(regparm, sizeof(regparm), p, &is_retreg);
c36e914d 440 if (ret > 0) {
441 if (!IS(regparm, "eax") && !IS(regparm, "ax")
2b43685d 442 && !IS(regparm, "al") && !IS(regparm, "edx:eax"))
c36e914d 443 {
63df67be 444 printf("%s:%d:%zd: bad regparm: %s\n",
c36e914d 445 hdrfn, hdrfline, (p - protostr) + 1, regparm);
39b168b8 446 return -1;
c36e914d 447 }
448 p += ret;
449 p = sskip(p);
450 }
451
39b168b8 452 if (pp->is_fptr) {
bd96f656 453 if (*p == '[') {
454 // not really ret_type is array, but ohwell
455 pp->ret_type.is_array = 1;
456 p = strchr(p + 1, ']');
457 if (p == NULL) {
458 printf("%s:%d:%zd: ']' expected\n",
459 hdrfn, hdrfline, (p - protostr) + 1);
460 return -1;
461 }
462 p = sskip(p + 1);
463 }
39b168b8 464 if (*p != ')') {
63df67be 465 printf("%s:%d:%zd: ')' expected\n",
39b168b8 466 hdrfn, hdrfline, (p - protostr) + 1);
467 return -1;
468 }
469 p = sskip(p + 1);
470 }
471
c36e914d 472 if (*p != '(') {
63df67be 473 printf("%s:%d:%zd: '(' expected, got '%c'\n",
c36e914d 474 hdrfn, hdrfline, (p - protostr) + 1, *p);
39b168b8 475 return -1;
c36e914d 476 }
477 p++;
478
39b168b8 479 // check for x(void)
480 p = sskip(p);
06c5d854 481 if ((!strncmp(p, "void", 4) || !strncmp(p, "VOID", 4))
482 && *sskip(p + 4) == ')')
39b168b8 483 p += 4;
484
c36e914d 485 while (1) {
486 p = sskip(p);
39b168b8 487 if (*p == ')') {
488 p++;
c36e914d 489 break;
39b168b8 490 }
840257f6 491 if (xarg > 0) {
492 if (*p != ',') {
493 printf("%s:%d:%zd: ',' expected\n",
494 hdrfn, hdrfline, (p - protostr) + 1);
495 return -1;
496 }
c36e914d 497 p = sskip(p + 1);
840257f6 498 }
c36e914d 499
7ba45c34 500 if (!strncmp(p, "...", 3)) {
501 pp->is_vararg = 1;
502 p = sskip(p + 3);
503 if (*p == ')') {
504 p++;
505 break;
506 }
63df67be 507 printf("%s:%d:%zd: ')' expected\n",
7ba45c34 508 hdrfn, hdrfline, (p - protostr) + 1);
509 return -1;
510 }
511
39b168b8 512 arg = &pp->arg[xarg];
c36e914d 513 xarg++;
514
39b168b8 515 p1 = p;
3ebea2cf 516 ret = check_type(p, &arg->type);
517 if (ret <= 0) {
63df67be 518 printf("%s:%d:%zd: unhandled type for arg%d\n",
c36e914d 519 hdrfn, hdrfline, (p - protostr) + 1, xarg);
39b168b8 520 return -1;
c36e914d 521 }
64c59faf 522 p = sskip(p + ret);
c36e914d 523
39b168b8 524 if (*p == '(') {
525 // func ptr
526 arg->fptr = calloc(1, sizeof(*arg->fptr));
527 ret = parse_protostr(p1, arg->fptr);
528 if (ret < 0) {
63df67be 529 printf("%s:%d:%zd: funcarg parse failed\n",
39b168b8 530 hdrfn, hdrfline, p1 - protostr);
531 return -1;
532 }
efea2951 533 arg->fptr->is_arg = 1;
534 // we don't use actual names right now..
535 snprintf(arg->fptr->name,
536 sizeof(arg->fptr->name), "a%d", xarg);
39b168b8 537 // we'll treat it as void * for non-calls
a652aa9f 538 arg->type.name = strdup("void *");
3ebea2cf 539 arg->type.is_ptr = 1;
39b168b8 540
541 p = p1 + ret;
542 }
543
c36e914d 544 p = next_idt(buf, sizeof(buf), p);
545 p = sskip(p);
546#if 0
547 if (buf[0] == 0) {
63df67be 548 printf("%s:%d:%zd: idt missing for arg%d\n",
c36e914d 549 hdrfn, hdrfline, (p - protostr) + 1, xarg);
39b168b8 550 return -1;
c36e914d 551 }
552#endif
39b168b8 553 arg->reg = NULL;
c36e914d 554
1f84f6b3 555 ret = get_regparm(regparm, sizeof(regparm), p, &is_retreg);
c36e914d 556 if (ret > 0) {
557 p += ret;
558 p = sskip(p);
559
39b168b8 560 arg->reg = strdup(map_reg(regparm));
1f84f6b3 561 arg->type.is_retreg = is_retreg;
562 pp->has_retreg |= is_retreg;
c36e914d 563 }
a652aa9f 564
7e50b291 565 if (strstr(arg->type.name, "int64")
566 || IS(arg->type.name, "double"))
567 {
568 // hack..
569 free(arg->type.name);
570 arg->type.name = strdup("int");
571 pp_copy_arg(&pp->arg[xarg], arg);
572 xarg++;
573 }
574
a652aa9f 575 ret = check_struct_arg(arg);
576 if (ret > 0) {
577 pp->has_structarg = 1;
578 arg->type.is_struct = 1;
579 free(arg->type.name);
580 arg->type.name = strdup("int");
581 for (l = 0; l < ret; l++) {
582 pp_copy_arg(&pp->arg[xarg], arg);
583 xarg++;
584 }
585 }
c36e914d 586 }
587
588 if (xarg > 0 && (IS(cconv, "__fastcall") || IS(cconv, "__thiscall"))) {
589 if (pp->arg[0].reg != NULL) {
590 printf("%s:%d: %s with arg1 spec %s?\n",
591 hdrfn, hdrfline, cconv, pp->arg[0].reg);
592 }
593 pp->arg[0].reg = strdup("ecx");
594 }
595
596 if (xarg > 1 && IS(cconv, "__fastcall")) {
597 if (pp->arg[1].reg != NULL) {
598 printf("%s:%d: %s with arg2 spec %s?\n",
599 hdrfn, hdrfline, cconv, pp->arg[1].reg);
600 }
601 pp->arg[1].reg = strdup("edx");
602 }
603
604 pp->argc = xarg;
605
606 for (i = 0; i < pp->argc; i++) {
607 if (pp->arg[i].reg == NULL)
608 pp->argc_stack++;
609 else
610 pp->argc_reg++;
611 }
612
c0050df6 613 if (pp->argc == 1 && pp->arg[0].reg != NULL
614 && IS(pp->arg[0].reg, "ecx"))
615 {
616 pp->is_fastcall = 1;
617 }
618 else if (pp->argc_reg == 2
619 && pp->arg[0].reg != NULL && IS(pp->arg[0].reg, "ecx")
620 && pp->arg[1].reg != NULL && IS(pp->arg[1].reg, "edx"))
621 {
622 pp->is_fastcall = 1;
623 }
624
625 if (pp->is_vararg && (pp->is_stdcall || pp->is_fastcall)) {
626 printf("%s:%d: vararg %s?\n", hdrfn, hdrfline, cconv);
627 return -1;
628 }
629
39b168b8 630 return p - protostr;
c36e914d 631}
632
bd96f656 633static int pp_name_cmp(const void *p1, const void *p2)
634{
635 const struct parsed_proto *pp1 = p1, *pp2 = p2;
636 return strcmp(pp1->name, pp2->name);
637}
638
639static struct parsed_proto *pp_cache;
640static int pp_cache_size;
641static int pp_cache_alloc;
642
643static int b_pp_c_handler(char *proto, const char *fname)
644{
645 int ret;
646
647 if (pp_cache_size >= pp_cache_alloc) {
648 pp_cache_alloc = pp_cache_alloc * 2 + 64;
649 pp_cache = realloc(pp_cache, pp_cache_alloc
650 * sizeof(pp_cache[0]));
651 my_assert_not(pp_cache, NULL);
652 memset(pp_cache + pp_cache_size, 0,
653 (pp_cache_alloc - pp_cache_size)
654 * sizeof(pp_cache[0]));
655 }
656
657 ret = parse_protostr(proto, &pp_cache[pp_cache_size]);
658 if (ret < 0)
659 return -1;
660
661 pp_cache_size++;
662 return 0;
663}
664
665static void build_pp_cache(FILE *fhdr)
c36e914d 666{
1f906263 667 long pos;
c36e914d 668 int ret;
669
1f906263 670 pos = ftell(fhdr);
bd96f656 671 rewind(fhdr);
672
673 ret = do_protostrs(fhdr, hdrfn);
674 if (ret < 0)
675 exit(1);
676
677 qsort(pp_cache, pp_cache_size, sizeof(pp_cache[0]), pp_name_cmp);
1f906263 678 fseek(fhdr, pos, SEEK_SET);
bd96f656 679}
680
36595fd2 681static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym,
682 int quiet)
bd96f656 683{
684 const struct parsed_proto *pp_ret;
685 struct parsed_proto pp_search;
7aca4698 686 char *p;
bd96f656 687
688 if (pp_cache == NULL)
689 build_pp_cache(fhdr);
690
691 if (sym[0] == '_') // && strncmp(fname, "stdc", 4) == 0)
692 sym++;
c36e914d 693
bd96f656 694 strcpy(pp_search.name, sym);
7aca4698 695 p = strchr(pp_search.name, '@');
696 if (p != NULL)
697 *p = 0;
698
bd96f656 699 pp_ret = bsearch(&pp_search, pp_cache, pp_cache_size,
700 sizeof(pp_cache[0]), pp_name_cmp);
36595fd2 701 if (pp_ret == NULL && !quiet)
c36e914d 702 printf("%s: sym '%s' is missing\n", hdrfn, sym);
bd96f656 703
704 return pp_ret;
705}
706
a652aa9f 707static void pp_copy_arg(struct parsed_proto_arg *d,
708 const struct parsed_proto_arg *s)
709{
710 memcpy(d, s, sizeof(*d));
711
712 if (s->reg != NULL) {
713 d->reg = strdup(s->reg);
714 my_assert_not(d->reg, NULL);
715 }
716 if (s->type.name != NULL) {
717 d->type.name = strdup(s->type.name);
718 my_assert_not(d->type.name, NULL);
719 }
720 if (s->fptr != NULL) {
721 d->fptr = malloc(sizeof(*d->fptr));
722 my_assert_not(d->fptr, NULL);
723 memcpy(d->fptr, s->fptr, sizeof(*d->fptr));
724 }
725}
726
bd96f656 727struct parsed_proto *proto_clone(const struct parsed_proto *pp_c)
728{
729 struct parsed_proto *pp;
730 int i;
731
732 pp = malloc(sizeof(*pp));
733 my_assert_not(pp, NULL);
734 memcpy(pp, pp_c, sizeof(*pp)); // lazy..
735
736 // do the actual deep copy..
a652aa9f 737 for (i = 0; i < pp_c->argc; i++)
738 pp_copy_arg(&pp->arg[i], &pp_c->arg[i]);
bd96f656 739 if (pp_c->ret_type.name != NULL)
740 pp->ret_type.name = strdup(pp_c->ret_type.name);
c36e914d 741
bd96f656 742 return pp;
c36e914d 743}
744
b74c31e3 745static inline void pp_print(char *buf, size_t buf_size,
746 const struct parsed_proto *pp)
747{
748 size_t l;
749 int i;
750
751 snprintf(buf, buf_size, "%s %s(", pp->ret_type.name, pp->name);
752 l = strlen(buf);
753
754 for (i = 0; i < pp->argc_reg; i++) {
755 snprintf(buf + l, buf_size - l, "%s%s",
756 i == 0 ? "" : ", ", pp->arg[i].reg);
757 l = strlen(buf);
758 }
759 if (pp->argc_stack > 0) {
760 snprintf(buf + l, buf_size - l, "%s{%d stack}",
761 i == 0 ? "" : ", ", pp->argc_stack);
762 l = strlen(buf);
763 }
764 snprintf(buf + l, buf_size - l, ")");
765}
766
bd96f656 767static inline void proto_release(struct parsed_proto *pp)
c36e914d 768{
769 int i;
770
771 for (i = 0; i < pp->argc; i++) {
39b168b8 772 if (pp->arg[i].reg != NULL)
c36e914d 773 free(pp->arg[i].reg);
3ebea2cf 774 if (pp->arg[i].type.name != NULL)
775 free(pp->arg[i].type.name);
39b168b8 776 if (pp->arg[i].fptr != NULL)
777 free(pp->arg[i].fptr);
c36e914d 778 }
3ebea2cf 779 if (pp->ret_type.name != NULL)
780 free(pp->ret_type.name);
bd96f656 781 free(pp);
c36e914d 782}