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