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