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