read_config_file.c revision da442f4777454436e02bf0ec170bc9b59fb68546
1/* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 1998,1999,2003,2007,2008,2009 Juan Cespedes 5 * Copyright (C) 2006 Ian Wienand 6 * Copyright (C) 2006 Steve Fink 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 * 02110-1301 USA 22 */ 23 24#include "config.h" 25 26#include <string.h> 27#include <stdlib.h> 28#include <ctype.h> 29#include <errno.h> 30#include <error.h> 31#include <assert.h> 32 33#include "common.h" 34#include "output.h" 35#include "expr.h" 36#include "param.h" 37#include "printf.h" 38#include "zero.h" 39#include "type.h" 40#include "lens.h" 41#include "lens_default.h" 42#include "lens_enum.h" 43 44static int line_no; 45static char *filename; 46 47static struct arg_type_info *parse_nonpointer_type(char **str, 48 struct param **extra_param, 49 size_t param_num, int *ownp); 50static struct arg_type_info *parse_type(char **str, struct param **extra_param, 51 size_t param_num, int *ownp); 52static struct arg_type_info *parse_lens(char **str, struct param **extra_param, 53 size_t param_num, int *ownp); 54static int parse_enum(char **str, struct arg_type_info **retp, int *ownp); 55 56Function *list_of_functions = NULL; 57 58static int 59parse_arg_type(char **name, enum arg_type *ret) 60{ 61 char *rest = NULL; 62 enum arg_type candidate; 63 64#define KEYWORD(KWD, TYPE) \ 65 do { \ 66 if (strncmp(*name, KWD, sizeof(KWD) - 1) == 0) { \ 67 rest = *name + sizeof(KWD) - 1; \ 68 candidate = TYPE; \ 69 goto ok; \ 70 } \ 71 } while (0) 72 73 KEYWORD("void", ARGTYPE_VOID); 74 KEYWORD("int", ARGTYPE_INT); 75 KEYWORD("uint", ARGTYPE_UINT); 76 KEYWORD("long", ARGTYPE_LONG); 77 KEYWORD("ulong", ARGTYPE_ULONG); 78 KEYWORD("char", ARGTYPE_CHAR); 79 KEYWORD("short", ARGTYPE_SHORT); 80 KEYWORD("ushort", ARGTYPE_USHORT); 81 KEYWORD("float", ARGTYPE_FLOAT); 82 KEYWORD("double", ARGTYPE_DOUBLE); 83 KEYWORD("array", ARGTYPE_ARRAY); 84 KEYWORD("struct", ARGTYPE_STRUCT); 85 86 assert(rest == NULL); 87 return -1; 88 89#undef KEYWORD 90 91ok: 92 if (isalnum(*rest)) 93 return -1; 94 95 *name = rest; 96 *ret = candidate; 97 return 0; 98} 99 100static void 101eat_spaces(char **str) { 102 while (**str == ' ') { 103 (*str)++; 104 } 105} 106 107static char * 108xstrndup(char *str, size_t len) { 109 char *ret = (char *) malloc(len + 1); 110 if (ret == NULL) { 111 report_global_error("malloc: %s", strerror(errno)); 112 return NULL; 113 } 114 strncpy(ret, str, len); 115 ret[len] = 0; 116 return ret; 117} 118 119static char * 120parse_ident(char **str) { 121 char *ident = *str; 122 123 if (!isalpha(**str) && **str != '_') { 124 report_error(filename, line_no, "bad identifier"); 125 return NULL; 126 } 127 128 while (**str && (isalnum(**str) || **str == '_')) { 129 ++(*str); 130 } 131 132 return xstrndup(ident, *str - ident); 133} 134 135/* 136 Returns position in string at the left parenthesis which starts the 137 function's argument signature. Returns NULL on error. 138*/ 139static char * 140start_of_arg_sig(char *str) { 141 char *pos; 142 int stacked = 0; 143 144 if (!strlen(str)) 145 return NULL; 146 147 pos = &str[strlen(str)]; 148 do { 149 pos--; 150 if (pos < str) 151 return NULL; 152 while ((pos > str) && (*pos != ')') && (*pos != '(')) 153 pos--; 154 155 if (*pos == ')') 156 stacked++; 157 else if (*pos == '(') 158 stacked--; 159 else 160 return NULL; 161 162 } while (stacked > 0); 163 164 return (stacked == 0) ? pos : NULL; 165} 166 167static int 168parse_int(char **str, long *ret) 169{ 170 char *end; 171 long n = strtol(*str, &end, 0); 172 if (end == *str) { 173 report_error(filename, line_no, "bad number"); 174 return -1; 175 } 176 177 *str = end; 178 if (ret != NULL) 179 *ret = n; 180 return 0; 181} 182 183static int 184check_nonnegative(long l) 185{ 186 if (l < 0) { 187 report_error(filename, line_no, 188 "expected non-negative value, got %ld", l); 189 return -1; 190 } 191 return 0; 192} 193 194static int 195check_int(long l) 196{ 197 int i = l; 198 if ((long)i != l) { 199 report_error(filename, line_no, 200 "Number too large: %ld", l); 201 return -1; 202 } 203 return 0; 204} 205 206static int 207parse_char(char **str, char expected) 208{ 209 if (**str != expected) { 210 report_error(filename, line_no, 211 "expected '%c', got '%c'", expected, **str); 212 return -1; 213 } 214 215 ++*str; 216 return 0; 217} 218 219static struct expr_node *parse_argnum(char **str, int zero); 220 221static struct expr_node * 222parse_zero(char **str, struct expr_node *ret) 223{ 224 eat_spaces(str); 225 if (**str == '(') { 226 ++*str; 227 struct expr_node *arg = parse_argnum(str, 0); 228 if (arg == NULL) 229 return NULL; 230 if (parse_char(str, ')') < 0) { 231 fail: 232 expr_destroy(arg); 233 free(arg); 234 return NULL; 235 } 236 237 struct expr_node *ret = build_zero_w_arg(arg, 1); 238 if (ret == NULL) 239 goto fail; 240 return ret; 241 242 } else { 243 return expr_node_zero(); 244 } 245} 246 247static int 248wrap_in_zero(struct expr_node **nodep) 249{ 250 struct expr_node *n = build_zero_w_arg(*nodep, 1); 251 if (n == NULL) 252 return -1; 253 *nodep = n; 254 return 0; 255} 256 257/* 258 * Input: 259 * argN : The value of argument #N, counting from 1 260 * eltN : The value of element #N of the containing structure 261 * retval : The return value 262 * N : The numeric value N 263 */ 264static struct expr_node * 265parse_argnum(char **str, int zero) 266{ 267 struct expr_node *expr = malloc(sizeof(*expr)); 268 if (expr == NULL) 269 return NULL; 270 271 if (isdigit(**str)) { 272 long l; 273 if (parse_int(str, &l) < 0 274 || check_nonnegative(l) < 0 275 || check_int(l) < 0) 276 goto fail; 277 278 expr_init_const_word(expr, l, type_get_simple(ARGTYPE_LONG), 0); 279 280 if (zero && wrap_in_zero(&expr) < 0) 281 goto fail; 282 283 return expr; 284 285 } else { 286 char *name = parse_ident(str); 287 if (name == NULL) 288 goto fail; 289 290 int is_arg = strncmp(name, "arg", 3) == 0; 291 int is_elt = !is_arg && strncmp(name, "elt", 3) == 0; 292 if (is_arg || is_elt) { 293 long l; 294 name += 3; 295 if (parse_int(&name, &l) < 0 296 || check_int(l) < 0) 297 goto fail; 298 299 if (is_arg) { 300 expr_init_argno(expr, l - 1); 301 } else { 302 struct expr_node *e_up = malloc(sizeof(*e_up)); 303 struct expr_node *e_ix = malloc(sizeof(*e_ix)); 304 if (e_up == NULL || e_ix == NULL) { 305 free(e_up); 306 free(e_ix); 307 goto fail; 308 } 309 310 expr_init_up(e_up, expr_self(), 0); 311 struct arg_type_info *ti 312 = type_get_simple(ARGTYPE_LONG); 313 expr_init_const_word(e_ix, l - 1, ti, 0); 314 expr_init_index(expr, e_up, 1, e_ix, 1); 315 } 316 317 } else if (strcmp(name, "retval") == 0) { 318 expr_init_named(expr, "retval", 0); 319 320 } else if (strcmp(name, "zero") == 0) { 321 struct expr_node *ret = parse_zero(str, expr); 322 if (ret == NULL) 323 goto fail; 324 return ret; 325 326 } else { 327 report_error(filename, line_no, 328 "Unknown length specifier: '%s'", name); 329 goto fail; 330 } 331 332 if (zero && wrap_in_zero(&expr) < 0) 333 goto fail; 334 335 return expr; 336 } 337 338fail: 339 free(expr); 340 return NULL; 341} 342 343struct typedef_node_t { 344 char *name; 345 struct arg_type_info *info; 346 int own_type; 347 struct typedef_node_t *next; 348} *typedefs = NULL; 349 350static struct arg_type_info * 351lookup_typedef(char **str) { 352 struct typedef_node_t *node; 353 char *end = *str; 354 while (*end && (isalnum(*end) || *end == '_')) 355 ++end; 356 if (end == *str) 357 return NULL; 358 359 for (node = typedefs; node != NULL; node = node->next) { 360 if (strncmp(*str, node->name, end - *str) == 0) { 361 (*str) += strlen(node->name); 362 return node->info; 363 } 364 } 365 366 return NULL; 367} 368 369static struct typedef_node_t * 370insert_typedef(char *name, struct arg_type_info *info, int own_type) 371{ 372 struct typedef_node_t *binding = malloc(sizeof(*binding)); 373 binding->name = name; 374 binding->info = info; 375 binding->own_type = own_type; 376 binding->next = typedefs; 377 typedefs = binding; 378 return binding; 379} 380 381static void 382parse_typedef(char **str) { 383 char *name; 384 struct arg_type_info *info; 385 386 (*str) += strlen("typedef"); 387 eat_spaces(str); 388 389 // Grab out the name of the type 390 name = parse_ident(str); 391 392 // Skip = sign 393 eat_spaces(str); 394 if (parse_char(str, '=') < 0) 395 return; 396 eat_spaces(str); 397 398 // Parse the type 399 int own; 400 info = parse_type(str, NULL, 0, &own); 401 402 insert_typedef(name, info, own); 403} 404 405static void 406destroy_fun(Function *fun) 407{ 408 size_t i; 409 if (fun == NULL) 410 return; 411 if (fun->own_return_info) { 412 type_destroy(fun->return_info); 413 free(fun->return_info); 414 } 415 for (i = 0; i < fun->num_params; ++i) 416 param_destroy(&fun->params[i]); 417 free(fun->params); 418} 419 420/* Syntax: struct ( type,type,type,... ) */ 421static int 422parse_struct(char **str, struct arg_type_info *info) 423{ 424 eat_spaces(str); 425 if (parse_char(str, '(') < 0) 426 return -1; 427 428 eat_spaces(str); // Empty arg list with whitespace inside 429 430 type_init_struct(info); 431 432 while (1) { 433 eat_spaces(str); 434 if (**str == 0 || **str == ')') { 435 parse_char(str, ')'); 436 return 0; 437 } 438 439 /* Field delimiter. */ 440 if (type_struct_size(info) > 0) 441 parse_char(str, ','); 442 443 eat_spaces(str); 444 int own; 445 struct arg_type_info *field = parse_lens(str, NULL, 0, &own); 446 if (field == NULL || type_struct_add(info, field, own)) { 447 type_destroy(info); 448 return -1; 449 } 450 } 451} 452 453static int 454parse_string(char **str, struct arg_type_info **retp, int *ownp) 455{ 456 struct arg_type_info *info = malloc(sizeof(*info) * 2); 457 if (info == NULL) { 458 fail: 459 free(info); 460 return -1; 461 } 462 463 struct expr_node *length; 464 int own_length; 465 int with_arg = 0; 466 467 if (isdigit(**str)) { 468 /* string0 is string[retval], length is zero(retval) 469 * stringN is string[argN], length is zero(argN) */ 470 long l; 471 if (parse_int(str, &l) < 0 472 || check_int(l) < 0) 473 goto fail; 474 475 struct expr_node *length_arg = malloc(sizeof(*length_arg)); 476 if (length_arg == NULL) 477 goto fail; 478 479 if (l == 0) 480 expr_init_named(length_arg, "retval", 0); 481 else 482 expr_init_argno(length_arg, l - 1); 483 484 length = build_zero_w_arg(length_arg, 1); 485 if (length == NULL) { 486 expr_destroy(length_arg); 487 free(length_arg); 488 goto fail; 489 } 490 own_length = 1; 491 492 } else { 493 eat_spaces(str); 494 if (**str == '[') { 495 (*str)++; 496 eat_spaces(str); 497 498 length = parse_argnum(str, 1); 499 if (length == NULL) 500 goto fail; 501 own_length = 1; 502 503 eat_spaces(str); 504 parse_char(str, ']'); 505 506 } else if (**str == '(') { 507 /* Usage of "string" as lens. */ 508 ++*str; 509 510 free(info); 511 512 eat_spaces(str); 513 info = parse_type(str, NULL, 0, ownp); 514 if (info == NULL) 515 goto fail; 516 517 eat_spaces(str); 518 parse_char(str, ')'); 519 520 with_arg = 1; 521 522 } else { 523 /* It was just a simple string after all. */ 524 length = expr_node_zero(); 525 own_length = 0; 526 } 527 } 528 529 /* String is a pointer to array of chars. */ 530 if (!with_arg) { 531 type_init_array(&info[1], type_get_simple(ARGTYPE_CHAR), 0, 532 length, own_length); 533 534 type_init_pointer(&info[0], &info[1], 0); 535 *ownp = 1; 536 } 537 538 info->lens = &string_lens; 539 info->own_lens = 0; 540 541 *retp = info; 542 return 0; 543} 544 545static int 546build_printf_pack(struct param **packp, size_t param_num) 547{ 548 if (packp == NULL) { 549 report_error(filename, line_no, 550 "'format' type in unexpected context"); 551 return -1; 552 } 553 if (*packp != NULL) { 554 report_error(filename, line_no, 555 "only one 'format' type per function supported"); 556 return -1; 557 } 558 559 *packp = malloc(sizeof(**packp)); 560 if (*packp == NULL) 561 return -1; 562 563 struct expr_node *node = malloc(sizeof(*node)); 564 if (node == NULL) { 565 free(*packp); 566 return -1; 567 } 568 569 expr_init_argno(node, param_num); 570 571 param_pack_init_printf(*packp, node, 1); 572 573 return 0; 574} 575 576/* Match and consume KWD if it's next in stream, and return 0. 577 * Otherwise return negative number. */ 578static int 579try_parse_kwd(char **str, const char *kwd) 580{ 581 size_t len = strlen(kwd); 582 if (strncmp(*str, kwd, len) == 0 583 && !isalnum((*str)[len])) { 584 (*str) += len; 585 return 0; 586 } 587 return -1; 588} 589 590/* Make a copy of INFO and set the *OWN bit if it's not already 591 * owned. */ 592static int 593unshare_type_info(struct arg_type_info **infop, int *ownp) 594{ 595 if (*ownp) 596 return 0; 597 598 struct arg_type_info *ninfo = malloc(sizeof(*ninfo)); 599 if (ninfo == NULL) { 600 report_error(filename, line_no, 601 "malloc: %s", strerror(errno)); 602 return -1; 603 } 604 *ninfo = **infop; 605 *infop = ninfo; 606 *ownp = 1; 607 return 0; 608} 609 610/* XXX extra_param and param_num are a kludge to get in 611 * backward-compatible support for "format" parameter type. The 612 * latter is only valid if the former is non-NULL, which is only in 613 * top-level context. */ 614static int 615parse_alias(char **str, struct arg_type_info **retp, int *ownp, 616 struct param **extra_param, size_t param_num) 617{ 618 /* For backward compatibility, we need to support things like 619 * stringN (which is like string[argN], string[N], and also 620 * bare string. We might, in theory, replace this by 621 * preprocessing configure file sources with M4, but for now, 622 * "string" is syntax. */ 623 if (strncmp(*str, "string", 6) == 0) { 624 (*str) += 6; 625 return parse_string(str, retp, ownp); 626 627 } else if (try_parse_kwd(str, "format") >= 0 628 && extra_param != NULL) { 629 /* For backward compatibility, format is parsed as 630 * "string", but it smuggles to the parameter list of 631 * a function a "printf" argument pack with this 632 * parameter as argument. */ 633 if (parse_string(str, retp, ownp) < 0) 634 return -1; 635 636 return build_printf_pack(extra_param, param_num); 637 638 } else if (try_parse_kwd(str, "enum") >=0) { 639 640 return parse_enum(str, retp, ownp); 641 642 } else { 643 *retp = NULL; 644 return 0; 645 } 646} 647 648/* Syntax: array ( type, N|argN ) */ 649static int 650parse_array(char **str, struct arg_type_info *info) 651{ 652 eat_spaces(str); 653 if (parse_char(str, '(') < 0) 654 return -1; 655 656 eat_spaces(str); 657 int own; 658 struct arg_type_info *elt_info = parse_lens(str, NULL, 0, &own); 659 if (elt_info == NULL) 660 return -1; 661 662 eat_spaces(str); 663 parse_char(str, ','); 664 665 eat_spaces(str); 666 struct expr_node *length = parse_argnum(str, 0); 667 if (length == NULL) { 668 if (own) { 669 type_destroy(elt_info); 670 free(elt_info); 671 } 672 return -1; 673 } 674 675 type_init_array(info, elt_info, own, length, 1); 676 677 eat_spaces(str); 678 parse_char(str, ')'); 679 return 0; 680} 681 682/* Syntax: 683 * enum (keyname[=value],keyname[=value],... ) 684 * enum<type> (keyname[=value],keyname[=value],... ) 685 */ 686static int 687parse_enum(char **str, struct arg_type_info **retp, int *ownp) 688{ 689 /* Optional type argument. */ 690 eat_spaces(str); 691 if (**str == '[') { 692 parse_char(str, '['); 693 eat_spaces(str); 694 *retp = parse_nonpointer_type(str, NULL, 0, ownp); 695 if (*retp == NULL) 696 return -1; 697 698 if (!type_is_integral((*retp)->type)) { 699 report_error(filename, line_no, 700 "integral type required as enum argument"); 701 fail: 702 if (*ownp) { 703 /* This also releases associated lens 704 * if any was set so far. */ 705 type_destroy(*retp); 706 free(*retp); 707 } 708 return -1; 709 } 710 711 eat_spaces(str); 712 if (parse_char(str, ']') < 0) 713 goto fail; 714 715 } else { 716 *retp = type_get_simple(ARGTYPE_INT); 717 *ownp = 0; 718 } 719 720 /* We'll need to set the lens, so unshare. */ 721 if (unshare_type_info(retp, ownp) < 0) 722 goto fail; 723 724 eat_spaces(str); 725 if (parse_char(str, '(') < 0) 726 goto fail; 727 728 struct enum_lens *lens = malloc(sizeof(*lens)); 729 if (lens == NULL) { 730 report_error(filename, line_no, 731 "malloc enum lens: %s", strerror(errno)); 732 return -1; 733 } 734 735 lens_init_enum(lens); 736 (*retp)->lens = &lens->super; 737 (*retp)->own_lens = 1; 738 739 long last_val = 0; 740 while (1) { 741 eat_spaces(str); 742 if (**str == 0 || **str == ')') { 743 parse_char(str, ')'); 744 return 0; 745 } 746 747 /* Field delimiter. XXX should we support the C 748 * syntax, where the enumeration can end in pending 749 * comma? */ 750 if (lens_enum_size(lens) > 0) 751 parse_char(str, ','); 752 753 eat_spaces(str); 754 char *key = parse_ident(str); 755 if (key == NULL) { 756 err: 757 free(key); 758 goto fail; 759 } 760 761 if (**str == '=') { 762 ++*str; 763 eat_spaces(str); 764 if (parse_int(str, &last_val) < 0) 765 goto err; 766 } 767 768 struct value *value = malloc(sizeof(*value)); 769 if (value == NULL) 770 goto err; 771 value_init_detached(value, NULL, *retp, 0); 772 value_set_word(value, last_val); 773 774 if (lens_enum_add(lens, key, 1, value, 1) < 0) 775 goto err; 776 777 last_val++; 778 } 779 780 return 0; 781} 782 783static struct arg_type_info * 784parse_nonpointer_type(char **str, struct param **extra_param, size_t param_num, 785 int *ownp) 786{ 787 enum arg_type type; 788 if (parse_arg_type(str, &type) < 0) { 789 struct arg_type_info *simple; 790 if (parse_alias(str, &simple, ownp, extra_param, param_num) < 0) 791 return NULL; 792 if (simple == NULL) 793 simple = lookup_typedef(str); 794 if (simple != NULL) { 795 *ownp = 0; 796 return simple; 797 } 798 799 report_error(filename, line_no, 800 "unknown type around '%s'", *str); 801 return NULL; 802 } 803 804 int (*parser) (char **, struct arg_type_info *) = NULL; 805 806 /* For some types that's all we need. */ 807 switch (type) { 808 case ARGTYPE_VOID: 809 case ARGTYPE_INT: 810 case ARGTYPE_UINT: 811 case ARGTYPE_LONG: 812 case ARGTYPE_ULONG: 813 case ARGTYPE_CHAR: 814 case ARGTYPE_SHORT: 815 case ARGTYPE_USHORT: 816 case ARGTYPE_FLOAT: 817 case ARGTYPE_DOUBLE: 818 *ownp = 0; 819 return type_get_simple(type); 820 821 case ARGTYPE_ARRAY: 822 parser = parse_array; 823 break; 824 825 case ARGTYPE_STRUCT: 826 parser = parse_struct; 827 break; 828 829 case ARGTYPE_POINTER: 830 /* Pointer syntax is not based on keyword, so we 831 * should never get this type. */ 832 assert(type != ARGTYPE_POINTER); 833 abort(); 834 } 835 836 struct arg_type_info *info = malloc(sizeof(*info)); 837 if (info == NULL) { 838 report_error(filename, line_no, 839 "malloc: %s", strerror(errno)); 840 return NULL; 841 } 842 *ownp = 1; 843 844 if (parser(str, info) < 0) { 845 free(info); 846 return NULL; 847 } 848 849 return info; 850} 851 852static struct named_lens { 853 const char *name; 854 struct lens *lens; 855} lenses[] = { 856 { "hide", &blind_lens }, 857 { "octal", &octal_lens }, 858 { "hex", &hex_lens }, 859 { "bool", &bool_lens }, 860 { "guess", &guess_lens }, 861}; 862 863static struct lens * 864name2lens(char **str, int *own_lensp) 865{ 866 size_t i; 867 for (i = 0; i < sizeof(lenses)/sizeof(*lenses); ++i) 868 if (try_parse_kwd(str, lenses[i].name) == 0) { 869 *own_lensp = 0; 870 return lenses[i].lens; 871 } 872 873 return NULL; 874} 875 876static struct arg_type_info * 877parse_type(char **str, struct param **extra_param, size_t param_num, int *ownp) 878{ 879 struct arg_type_info *info 880 = parse_nonpointer_type(str, extra_param, param_num, ownp); 881 if (info == NULL) 882 return NULL; 883 884 while (1) { 885 eat_spaces(str); 886 if (**str == '*') { 887 struct arg_type_info *outer = malloc(sizeof(*outer)); 888 if (outer == NULL) { 889 if (*ownp) { 890 type_destroy(info); 891 free(info); 892 } 893 report_error(filename, line_no, 894 "malloc: %s", strerror(errno)); 895 return NULL; 896 } 897 type_init_pointer(outer, info, *ownp); 898 *ownp = 1; 899 (*str)++; 900 info = outer; 901 } else 902 break; 903 } 904 return info; 905} 906 907static struct arg_type_info * 908parse_lens(char **str, struct param **extra_param, size_t param_num, int *ownp) 909{ 910 int own_lens; 911 struct lens *lens = name2lens(str, &own_lens); 912 int has_args = 1; 913 struct arg_type_info *info; 914 if (lens != NULL) { 915 eat_spaces(str); 916 917 /* Octal lens gets special treatment, because of 918 * backward compatibility. */ 919 if (lens == &octal_lens && **str != '(') { 920 has_args = 0; 921 info = type_get_simple(ARGTYPE_INT); 922 *ownp = 0; 923 } else if (parse_char(str, '(') < 0) { 924 report_error(filename, line_no, 925 "expected type argument after the lens"); 926 return NULL; 927 } 928 } 929 930 if (has_args) { 931 eat_spaces(str); 932 info = parse_type(str, extra_param, param_num, ownp); 933 if (info == NULL) { 934 fail: 935 if (own_lens && lens != NULL) 936 lens_destroy(lens); 937 return NULL; 938 } 939 } 940 941 if (lens != NULL && has_args) { 942 eat_spaces(str); 943 parse_char(str, ')'); 944 } 945 946 /* We can't modify shared types. Make a copy if we have a 947 * lens. */ 948 if (lens != NULL && unshare_type_info(&info, ownp) < 0) 949 goto fail; 950 951 if (lens != NULL) { 952 info->lens = lens; 953 info->own_lens = own_lens; 954 } 955 956 return info; 957} 958 959static int 960add_param(Function *fun, size_t *allocdp) 961{ 962 size_t allocd = *allocdp; 963 /* XXX +1 is for the extra_param handling hack. */ 964 if ((fun->num_params + 1) >= allocd) { 965 allocd = allocd > 0 ? 2 * allocd : 8; 966 void *na = realloc(fun->params, sizeof(*fun->params) * allocd); 967 if (na == NULL) 968 return -1; 969 970 fun->params = na; 971 *allocdp = allocd; 972 } 973 return 0; 974} 975 976static Function * 977process_line(char *buf) { 978 char *str = buf; 979 char *tmp; 980 981 line_no++; 982 debug(3, "Reading line %d of `%s'", line_no, filename); 983 eat_spaces(&str); 984 985 /* A comment or empty line. */ 986 if (*str == ';' || *str == 0 || *str == '\n') 987 return NULL; 988 989 if (strncmp(str, "typedef", 7) == 0) { 990 parse_typedef(&str); 991 return NULL; 992 } 993 994 Function *fun = calloc(1, sizeof(*fun)); 995 if (fun == NULL) { 996 report_error(filename, line_no, 997 "alloc function: %s", strerror(errno)); 998 return NULL; 999 } 1000 1001 fun->return_info = parse_lens(&str, NULL, 0, &fun->own_return_info); 1002 if (fun->return_info == NULL) { 1003 err: 1004 debug(3, " Skipping line %d", line_no); 1005 destroy_fun(fun); 1006 return NULL; 1007 } 1008 debug(4, " return_type = %d", fun->return_info->type); 1009 1010 eat_spaces(&str); 1011 tmp = start_of_arg_sig(str); 1012 if (tmp == NULL) { 1013 report_error(filename, line_no, "syntax error"); 1014 goto err; 1015 } 1016 *tmp = '\0'; 1017 fun->name = strdup(str); 1018 str = tmp + 1; 1019 debug(3, " name = %s", fun->name); 1020 1021 size_t allocd = 0; 1022 struct param *extra_param = NULL; 1023 1024 int have_stop = 0; 1025 1026 while (1) { 1027 eat_spaces(&str); 1028 if (*str == ')') 1029 break; 1030 1031 if (str[0] == '+') { 1032 if (have_stop == 0) { 1033 if (add_param(fun, &allocd) < 0) 1034 goto add_err; 1035 param_init_stop 1036 (&fun->params[fun->num_params++]); 1037 have_stop = 1; 1038 } 1039 str++; 1040 } 1041 1042 if (add_param(fun, &allocd) < 0) { 1043 add_err: 1044 report_error(filename, line_no, "(re)alloc params: %s", 1045 strerror(errno)); 1046 goto err; 1047 } 1048 1049 int own; 1050 struct arg_type_info *type = parse_lens(&str, &extra_param, 1051 fun->num_params, &own); 1052 if (type == NULL) { 1053 report_error(filename, line_no, 1054 "unknown argument type"); 1055 goto err; 1056 } 1057 1058 /* XXX We used to allow void parameter as a synonym to 1059 * an argument that shouldn't be displayed. We may 1060 * wish to re-introduce this when lenses are 1061 * implemented, as a synonym, but backends generally 1062 * need to know the type, so disallow bare void for 1063 * now. */ 1064 if (type->type == ARGTYPE_VOID) { 1065 report_warning(filename, line_no, 1066 "void parameter assumed to be 'int'"); 1067 if (own) { 1068 type_destroy(type); 1069 free(type); 1070 } 1071 type = type_get_simple(ARGTYPE_INT); 1072 own = 0; 1073 } 1074 1075 param_init_type(&fun->params[fun->num_params++], type, own); 1076 1077 eat_spaces(&str); 1078 if (*str == ',') { 1079 str++; 1080 continue; 1081 } else if (*str == ')') { 1082 continue; 1083 } else { 1084 if (str[strlen(str) - 1] == '\n') 1085 str[strlen(str) - 1] = '\0'; 1086 report_error(filename, line_no, 1087 "syntax error around \"%s\"", str); 1088 goto err; 1089 } 1090 } 1091 1092 if (extra_param != NULL) { 1093 assert(fun->num_params < allocd); 1094 memcpy(&fun->params[fun->num_params++], extra_param, 1095 sizeof(*extra_param)); 1096 } 1097 1098 return fun; 1099} 1100 1101void 1102init_global_config(void) 1103{ 1104 struct arg_type_info *info = malloc(2 * sizeof(*info)); 1105 if (info == NULL) 1106 error(1, errno, "malloc in init_global_config"); 1107 1108 memset(info, 0, 2 * sizeof(*info)); 1109 info[0].type = ARGTYPE_POINTER; 1110 info[0].u.ptr_info.info = &info[1]; 1111 info[1].type = ARGTYPE_VOID; 1112 1113 insert_typedef(strdup("addr"), info, 0); 1114 insert_typedef(strdup("file"), info, 1); 1115} 1116 1117void 1118read_config_file(char *file) { 1119 FILE *stream; 1120 char buf[1024]; 1121 1122 filename = file; 1123 stream = fopen(filename, "r"); 1124 if (!stream) { 1125 return; 1126 } 1127 1128 debug(1, "Reading config file `%s'...", filename); 1129 1130 line_no = 0; 1131 while (fgets(buf, 1024, stream)) { 1132 Function *tmp; 1133 1134 tmp = process_line(buf); 1135 1136 if (tmp) { 1137 debug(2, "New function: `%s'", tmp->name); 1138 tmp->next = list_of_functions; 1139 list_of_functions = tmp; 1140 } 1141 } 1142 fclose(stream); 1143} 1144