Replace readdir_r with readdir
[platform/upstream/ltrace.git] / read_config_file.c
1 /*
2  * This file is part of ltrace.
3  * Copyright (C) 2011,2012,2013,2014 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 /* getline is POSIX.1-2008.  It was originally a GNU extension, and
25  * chances are uClibc still needs _GNU_SOURCE, but for now try it this
26  * way.  */
27 #define _POSIX_C_SOURCE 200809L
28
29 #include "config.h"
30
31 #include <string.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <assert.h>
36
37 #include "common.h"
38 #include "output.h"
39 #include "expr.h"
40 #include "param.h"
41 #include "printf.h"
42 #include "prototype.h"
43 #include "zero.h"
44 #include "type.h"
45 #include "lens.h"
46 #include "lens_default.h"
47 #include "lens_enum.h"
48
49 /* Lifted from GCC: The ctype functions are often implemented as
50  * macros which do lookups in arrays using the parameter as the
51  * offset.  If the ctype function parameter is a char, then gcc will
52  * (appropriately) warn that a "subscript has type char".  Using a
53  * (signed) char as a subscript is bad because you may get negative
54  * offsets and thus it is not 8-bit safe.  The CTYPE_CONV macro
55  * ensures that the parameter is cast to an unsigned char when a char
56  * is passed in.  When an int is passed in, the parameter is left
57  * alone so we don't lose EOF.  */
58
59 #define CTYPE_CONV(CH) \
60   (sizeof(CH) == sizeof(unsigned char) ? (int)(unsigned char)(CH) : (int)(CH))
61
62 struct locus
63 {
64         const char *filename;
65         int line_no;
66 };
67
68 static struct arg_type_info *parse_nonpointer_type(struct protolib *plib,
69                                                    struct locus *loc,
70                                                    char **str,
71                                                    struct param **extra_param,
72                                                    size_t param_num,
73                                                    int *ownp, int *forwardp);
74 static struct arg_type_info *parse_type(struct protolib *plib,
75                                         struct locus *loc,
76                                         char **str, struct param **extra_param,
77                                         size_t param_num, int *ownp,
78                                         int *forwardp);
79 static struct arg_type_info *parse_lens(struct protolib *plib,
80                                         struct locus *loc,
81                                         char **str, struct param **extra_param,
82                                         size_t param_num, int *ownp,
83                                         int *forwardp);
84 static int parse_enum(struct protolib *plib, struct locus *loc,
85                       char **str, struct arg_type_info **retp, int *ownp);
86
87 struct prototype *list_of_functions = NULL;
88
89 static int
90 parse_arg_type(char **name, enum arg_type *ret)
91 {
92         char *rest = NULL;
93         enum arg_type candidate;
94
95 #define KEYWORD(KWD, TYPE)                                              \
96         do {                                                            \
97                 if (strncmp(*name, KWD, sizeof(KWD) - 1) == 0) {        \
98                         rest = *name + sizeof(KWD) - 1;                 \
99                         candidate = TYPE;                               \
100                         goto ok;                                        \
101                 }                                                       \
102         } while (0)
103
104         KEYWORD("void", ARGTYPE_VOID);
105         KEYWORD("int", ARGTYPE_INT);
106         KEYWORD("uint", ARGTYPE_UINT);
107         KEYWORD("long", ARGTYPE_LONG);
108         KEYWORD("ulong", ARGTYPE_ULONG);
109         KEYWORD("char", ARGTYPE_CHAR);
110         KEYWORD("short", ARGTYPE_SHORT);
111         KEYWORD("ushort", ARGTYPE_USHORT);
112         KEYWORD("float", ARGTYPE_FLOAT);
113         KEYWORD("double", ARGTYPE_DOUBLE);
114         KEYWORD("array", ARGTYPE_ARRAY);
115         KEYWORD("struct", ARGTYPE_STRUCT);
116
117         /* Misspelling of int used in ltrace.conf that we used to
118          * ship.  */
119         KEYWORD("itn", ARGTYPE_INT);
120
121         assert(rest == NULL);
122         return -1;
123
124 #undef KEYWORD
125
126 ok:
127         if (isalnum(CTYPE_CONV(*rest)) || *rest == '_')
128                 return -1;
129
130         *name = rest;
131         *ret = candidate;
132         return 0;
133 }
134
135 static void
136 eat_spaces(char **str) {
137         while (**str == ' ') {
138                 (*str)++;
139         }
140 }
141
142 static char *
143 xstrndup(char *str, size_t len) {
144         char *ret = (char *) malloc(len + 1);
145         if (ret == NULL) {
146                 report_global_error("malloc: %s", strerror(errno));
147                 return NULL;
148         }
149         strncpy(ret, str, len);
150         ret[len] = 0;
151         return ret;
152 }
153
154 static char *
155 parse_ident(struct locus *loc, char **str)
156 {
157         char *ident = *str;
158
159         if (!isalpha(CTYPE_CONV(**str)) && **str != '_') {
160                 report_error(loc->filename, loc->line_no, "bad identifier");
161                 return NULL;
162         }
163
164         while (**str && (isalnum(CTYPE_CONV(**str)) || **str == '_')) {
165                 ++(*str);
166         }
167
168         return xstrndup(ident, *str - ident);
169 }
170
171 static int
172 parse_int(struct locus *loc, char **str, long *ret)
173 {
174         char *end;
175         long n = strtol(*str, &end, 0);
176         if (end == *str) {
177                 report_error(loc->filename, loc->line_no, "bad number");
178                 return -1;
179         }
180
181         *str = end;
182         if (ret != NULL)
183                 *ret = n;
184         return 0;
185 }
186
187 static int
188 check_nonnegative(struct locus *loc, long l)
189 {
190         if (l < 0) {
191                 report_error(loc->filename, loc->line_no,
192                              "expected non-negative value, got %ld", l);
193                 return -1;
194         }
195         return 0;
196 }
197
198 static int
199 check_int(struct locus *loc, long l)
200 {
201         int i = l;
202         if ((long)i != l) {
203                 report_error(loc->filename, loc->line_no,
204                              "Number too large: %ld", l);
205                 return -1;
206         }
207         return 0;
208 }
209
210 static int
211 parse_char(struct locus *loc, char **str, char expected)
212 {
213         if (**str != expected) {
214                 report_error(loc->filename, loc->line_no,
215                              "expected '%c', got '%c'", expected, **str);
216                 return -1;
217         }
218
219         ++*str;
220         return 0;
221 }
222
223 static struct expr_node *parse_argnum(struct locus *loc,
224                                       char **str, int *ownp, int zero);
225
226 static struct expr_node *
227 parse_zero(struct locus *loc, char **str, int *ownp)
228 {
229         eat_spaces(str);
230         if (**str == '(') {
231                 ++*str;
232                 int own;
233                 struct expr_node *arg = parse_argnum(loc, str, &own, 0);
234                 if (arg == NULL)
235                         return NULL;
236                 if (parse_char(loc, str, ')') < 0) {
237                 fail:
238                         expr_destroy(arg);
239                         free(arg);
240                         return NULL;
241                 }
242
243                 struct expr_node *ret = build_zero_w_arg(arg, own);
244                 if (ret == NULL)
245                         goto fail;
246                 *ownp = 1;
247                 return ret;
248
249         } else {
250                 *ownp = 0;
251                 return expr_node_zero();
252         }
253 }
254
255 static int
256 wrap_in_zero(struct expr_node **nodep)
257 {
258         struct expr_node *n = build_zero_w_arg(*nodep, 1);
259         if (n == NULL)
260                 return -1;
261         *nodep = n;
262         return 0;
263 }
264
265 /*
266  * Input:
267  *  argN   : The value of argument #N, counting from 1
268  *  eltN   : The value of element #N of the containing structure
269  *  retval : The return value
270  *  N      : The numeric value N
271  */
272 static struct expr_node *
273 parse_argnum(struct locus *loc, char **str, int *ownp, int zero)
274 {
275         struct expr_node *expr = malloc(sizeof(*expr));
276         if (expr == NULL)
277                 return NULL;
278
279         if (isdigit(CTYPE_CONV(**str))) {
280                 long l;
281                 if (parse_int(loc, str, &l) < 0
282                     || check_nonnegative(loc, l) < 0
283                     || check_int(loc, l) < 0)
284                         goto fail;
285
286                 expr_init_const_word(expr, l, type_get_simple(ARGTYPE_LONG), 0);
287
288                 if (zero && wrap_in_zero(&expr) < 0)
289                         goto fail;
290
291                 *ownp = 1;
292                 return expr;
293
294         } else {
295                 char *const name = parse_ident(loc, str);
296                 if (name == NULL) {
297                 fail_ident:
298                         free(name);
299                         goto fail;
300                 }
301
302                 int is_arg = strncmp(name, "arg", 3) == 0;
303                 if (is_arg || strncmp(name, "elt", 3) == 0) {
304                         long l;
305                         char *num = name + 3;
306                         if (parse_int(loc, &num, &l) < 0
307                             || check_int(loc, l) < 0)
308                                 goto fail_ident;
309
310                         if (is_arg) {
311                                 if (l == 0)
312                                         expr_init_named(expr, "retval", 0);
313                                 else
314                                         expr_init_argno(expr, l - 1);
315                         } else {
316                                 struct expr_node *e_up = malloc(sizeof(*e_up));
317                                 struct expr_node *e_ix = malloc(sizeof(*e_ix));
318                                 if (e_up == NULL || e_ix == NULL) {
319                                         free(e_up);
320                                         free(e_ix);
321                                         goto fail_ident;
322                                 }
323
324                                 expr_init_up(e_up, expr_self(), 0);
325                                 struct arg_type_info *ti
326                                         = type_get_simple(ARGTYPE_LONG);
327                                 expr_init_const_word(e_ix, l - 1, ti, 0);
328                                 expr_init_index(expr, e_up, 1, e_ix, 1);
329                         }
330
331                 } else if (strcmp(name, "retval") == 0) {
332                         expr_init_named(expr, "retval", 0);
333
334                 } else if (strcmp(name, "zero") == 0) {
335                         struct expr_node *ret
336                                 = parse_zero(loc, str, ownp);
337                         if (ret == NULL)
338                                 goto fail_ident;
339                         free(expr);
340                         free(name);
341                         return ret;
342
343                 } else {
344                         report_error(loc->filename, loc->line_no,
345                                      "Unknown length specifier: '%s'", name);
346                         goto fail_ident;
347                 }
348
349                 if (zero && wrap_in_zero(&expr) < 0)
350                         goto fail_ident;
351
352                 free(name);
353                 *ownp = 1;
354                 return expr;
355         }
356
357 fail:
358         free(expr);
359         return NULL;
360 }
361
362 static struct arg_type_info *
363 parse_typedef_name(struct protolib *plib, char **str)
364 {
365         char *end = *str;
366         while (*end && (isalnum(CTYPE_CONV(*end)) || *end == '_'))
367                 ++end;
368         if (end == *str)
369                 return NULL;
370
371         size_t len = end - *str;
372         char buf[len + 1];
373         memcpy(buf, *str, len);
374         *str += len;
375         buf[len] = 0;
376
377         struct named_type *nt = protolib_lookup_type(plib, buf, true);
378         if (nt == NULL)
379                 return NULL;
380         return nt->info;
381 }
382
383 static int
384 parse_typedef(struct protolib *plib, struct locus *loc, char **str)
385 {
386         (*str) += strlen("typedef");
387         eat_spaces(str);
388         char *name = parse_ident(loc, str);
389
390         /* Look through the typedef list whether we already have a
391          * forward of this type.  If we do, it must be forward
392          * structure.  */
393         struct named_type *forward = protolib_lookup_type(plib, name, true);
394         if (forward != NULL
395             && (forward->info->type != ARGTYPE_STRUCT
396                 || !forward->forward)) {
397                 report_error(loc->filename, loc->line_no,
398                              "Redefinition of typedef '%s'", name);
399         err:
400                 free(name);
401                 return -1;
402         }
403
404         // Skip = sign
405         eat_spaces(str);
406         if (parse_char(loc, str, '=') < 0)
407                 goto err;
408         eat_spaces(str);
409
410         int fwd = 0;
411         int own = 0;
412         struct arg_type_info *info
413                 = parse_lens(plib, loc, str, NULL, 0, &own, &fwd);
414         if (info == NULL)
415                 goto err;
416
417         struct named_type this_nt;
418         named_type_init(&this_nt, info, own);
419         this_nt.forward = fwd;
420
421         if (forward == NULL) {
422                 if (protolib_add_named_type(plib, name, 1, &this_nt) < 0) {
423                         named_type_destroy(&this_nt);
424                         goto err;
425                 }
426                 return 0;
427         }
428
429         /* If we are defining a forward, make sure the definition is a
430          * structure as well.  */
431         if (this_nt.info->type != ARGTYPE_STRUCT) {
432                 report_error(loc->filename, loc->line_no,
433                              "Definition of forward '%s' must be a structure.",
434                              name);
435                 named_type_destroy(&this_nt);
436                 goto err;
437         }
438
439         /* Now move guts of the actual type over to the forward type.
440          * We can't just move pointers around, because references to
441          * forward must stay intact.  */
442         assert(this_nt.own_type);
443         type_destroy(forward->info);
444         *forward->info = *this_nt.info;
445         forward->forward = 0;
446         free(this_nt.info);
447         free(name);
448         return 0;
449 }
450
451 /* Syntax: struct ( type,type,type,... ) */
452 static int
453 parse_struct(struct protolib *plib, struct locus *loc,
454              char **str, struct arg_type_info *info,
455              int *forwardp)
456 {
457         eat_spaces(str);
458
459         if (**str == ';') {
460                 if (forwardp == NULL) {
461                         report_error(loc->filename, loc->line_no,
462                                      "Forward struct can be declared only "
463                                      "directly after a typedef.");
464                         return -1;
465                 }
466
467                 /* Forward declaration is currently handled as an
468                  * empty struct.  */
469                 type_init_struct(info);
470                 *forwardp = 1;
471                 return 0;
472         }
473
474         if (parse_char(loc, str, '(') < 0)
475                 return -1;
476
477         eat_spaces(str); // Empty arg list with whitespace inside
478
479         type_init_struct(info);
480
481         while (1) {
482                 eat_spaces(str);
483                 if (**str == 0 || **str == ')') {
484                         parse_char(loc, str, ')');
485                         return 0;
486                 }
487
488                 /* Field delimiter.  */
489                 if (type_struct_size(info) > 0)
490                         parse_char(loc, str, ',');
491
492                 eat_spaces(str);
493                 int own;
494                 struct arg_type_info *field
495                         = parse_lens(plib, loc, str, NULL, 0, &own, NULL);
496                 if (field == NULL || type_struct_add(info, field, own)) {
497                         type_destroy(info);
498                         return -1;
499                 }
500         }
501 }
502
503 /* Make a copy of INFO and set the *OWN bit if it's not already
504  * owned.  */
505 static int
506 unshare_type_info(struct locus *loc, struct arg_type_info **infop, int *ownp)
507 {
508         if (*ownp)
509                 return 0;
510
511         struct arg_type_info *ninfo = malloc(sizeof(*ninfo));
512         if (ninfo == NULL || type_clone(ninfo, *infop) < 0) {
513                 report_error(loc->filename, loc->line_no,
514                              "malloc: %s", strerror(errno));
515                 free(ninfo);
516                 return -1;
517         }
518         *infop = ninfo;
519         *ownp = 1;
520         return 0;
521 }
522
523 static int
524 parse_string(struct protolib *plib, struct locus *loc,
525              char **str, struct arg_type_info **retp, int *ownp)
526 {
527         struct arg_type_info *info = NULL;
528         struct expr_node *length;
529         int own_length;
530
531         if (isdigit(CTYPE_CONV(**str))) {
532                 /* string0 is string[retval], length is zero(retval)
533                  * stringN is string[argN], length is zero(argN) */
534                 long l;
535                 if (parse_int(loc, str, &l) < 0
536                     || check_int(loc, l) < 0)
537                         return -1;
538
539                 struct expr_node *length_arg = malloc(sizeof(*length_arg));
540                 if (length_arg == NULL)
541                         return -1;
542
543                 if (l == 0)
544                         expr_init_named(length_arg, "retval", 0);
545                 else
546                         expr_init_argno(length_arg, l - 1);
547
548                 length = build_zero_w_arg(length_arg, 1);
549                 if (length == NULL) {
550                         expr_destroy(length_arg);
551                         free(length_arg);
552                         return -1;
553                 }
554                 own_length = 1;
555
556         } else {
557                 eat_spaces(str);
558                 if (**str == '[') {
559                         (*str)++;
560                         eat_spaces(str);
561
562                         length = parse_argnum(loc, str, &own_length, 1);
563                         if (length == NULL)
564                                 return -1;
565
566                         eat_spaces(str);
567                         parse_char(loc, str, ']');
568
569                 } else if (**str == '(') {
570                         /* Usage of "string" as lens.  */
571                         ++*str;
572
573                         eat_spaces(str);
574                         info = parse_type(plib, loc, str, NULL, 0, ownp, NULL);
575                         if (info == NULL)
576                                 return -1;
577
578                         length = NULL;
579                         own_length = 0;
580
581                         eat_spaces(str);
582                         parse_char(loc, str, ')');
583
584                 } else {
585                         /* It was just a simple string after all.  */
586                         length = expr_node_zero();
587                         own_length = 0;
588                 }
589         }
590
591         /* String is a pointer to array of chars.  */
592         if (info == NULL) {
593                 struct arg_type_info *info1 = malloc(sizeof(*info1));
594                 struct arg_type_info *info2 = malloc(sizeof(*info2));
595                 if (info1 == NULL || info2 == NULL) {
596                         free(info1);
597                         free(info2);
598                 fail:
599                         if (own_length) {
600                                 assert(length != NULL);
601                                 expr_destroy(length);
602                                 free(length);
603                         }
604                         return -1;
605                 }
606                 type_init_array(info2, type_get_simple(ARGTYPE_CHAR), 0,
607                                 length, own_length);
608                 type_init_pointer(info1, info2, 1);
609
610                 info = info1;
611                 *ownp = 1;
612         }
613
614         /* We'll need to set the lens, so unshare.  */
615         if (unshare_type_info(loc, &info, ownp) < 0)
616                 /* If unshare_type_info failed, it must have been as a
617                  * result of cloning attempt because *OWNP was 0.
618                  * Thus we don't need to destroy INFO.  */
619                 goto fail;
620
621         info->lens = &string_lens;
622         info->own_lens = 0;
623
624         *retp = info;
625         return 0;
626 }
627
628 static int
629 build_printf_pack(struct locus *loc, struct param **packp, size_t param_num)
630 {
631         if (packp == NULL) {
632                 report_error(loc->filename, loc->line_no,
633                              "'format' type in unexpected context");
634                 return -1;
635         }
636         if (*packp != NULL) {
637                 report_error(loc->filename, loc->line_no,
638                              "only one 'format' type per function supported");
639                 return -1;
640         }
641
642         *packp = malloc(sizeof(**packp));
643         if (*packp == NULL)
644                 return -1;
645
646         struct expr_node *node = malloc(sizeof(*node));
647         if (node == NULL) {
648                 free(*packp);
649                 *packp = NULL;
650                 return -1;
651         }
652
653         expr_init_argno(node, param_num);
654
655         param_pack_init_printf(*packp, node, 1);
656
657         return 0;
658 }
659
660 /* Match and consume KWD if it's next in stream, and return 0.
661  * Otherwise return negative number.  */
662 static int
663 try_parse_kwd(char **str, const char *kwd)
664 {
665         size_t len = strlen(kwd);
666         if (strncmp(*str, kwd, len) == 0
667             && !isalnum(CTYPE_CONV((*str)[len]))
668             && (*str)[len] != '_') {
669                 (*str) += len;
670                 return 0;
671         }
672         return -1;
673 }
674
675 /* XXX EXTRA_PARAM and PARAM_NUM are a kludge to get in
676  * backward-compatible support for "format" parameter type.  The
677  * latter is only valid if the former is non-NULL, which is only in
678  * top-level context.  */
679 static int
680 parse_alias(struct protolib *plib, struct locus *loc,
681             char **str, struct arg_type_info **retp, int *ownp,
682             struct param **extra_param, size_t param_num)
683 {
684         /* For backward compatibility, we need to support things like
685          * stringN (which is like string[argN], string[N], and also
686          * bare string.  We might, in theory, replace this by
687          * preprocessing configure file sources with M4, but for now,
688          * "string" is syntax.  */
689         if (strncmp(*str, "string", 6) == 0) {
690                 (*str) += 6;
691                 return parse_string(plib, loc, str, retp, ownp);
692
693         } else if (try_parse_kwd(str, "format") >= 0
694                    && extra_param != NULL) {
695                 /* For backward compatibility, format is parsed as
696                  * "string", but it smuggles to the parameter list of
697                  * a function a "printf" argument pack with this
698                  * parameter as argument.  */
699                 if (parse_string(plib, loc, str, retp, ownp) < 0)
700                         return -1;
701
702                 return build_printf_pack(loc, extra_param, param_num);
703
704         } else if (try_parse_kwd(str, "enum") >=0) {
705
706                 return parse_enum(plib, loc, str, retp, ownp);
707
708         } else {
709                 *retp = NULL;
710                 return 0;
711         }
712 }
713
714 /* Syntax: array ( type, N|argN ) */
715 static int
716 parse_array(struct protolib *plib, struct locus *loc,
717             char **str, struct arg_type_info *info)
718 {
719         eat_spaces(str);
720         if (parse_char(loc, str, '(') < 0)
721                 return -1;
722
723         eat_spaces(str);
724         int own;
725         struct arg_type_info *elt_info
726                 = parse_lens(plib, loc, str, NULL, 0, &own, NULL);
727         if (elt_info == NULL)
728                 return -1;
729
730         eat_spaces(str);
731         parse_char(loc, str, ',');
732
733         eat_spaces(str);
734         int own_length;
735         struct expr_node *length = parse_argnum(loc, str, &own_length, 0);
736         if (length == NULL) {
737                 if (own) {
738                         type_destroy(elt_info);
739                         free(elt_info);
740                 }
741                 return -1;
742         }
743
744         type_init_array(info, elt_info, own, length, own_length);
745
746         eat_spaces(str);
747         parse_char(loc, str, ')');
748         return 0;
749 }
750
751 /* Syntax:
752  *   enum (keyname[=value],keyname[=value],... )
753  *   enum<type> (keyname[=value],keyname[=value],... )
754  */
755 static int
756 parse_enum(struct protolib *plib, struct locus *loc, char **str,
757            struct arg_type_info **retp, int *ownp)
758 {
759         /* Optional type argument.  */
760         eat_spaces(str);
761         if (**str == '[') {
762                 parse_char(loc, str, '[');
763                 eat_spaces(str);
764                 *retp = parse_nonpointer_type(plib, loc, str, NULL, 0, ownp, 0);
765                 if (*retp == NULL)
766                         return -1;
767
768                 if (!type_is_integral((*retp)->type)) {
769                         report_error(loc->filename, loc->line_no,
770                                      "integral type required as enum argument");
771                 fail:
772                         if (*ownp) {
773                                 /* This also releases associated lens
774                                  * if any was set so far.  */
775                                 type_destroy(*retp);
776                                 free(*retp);
777                         }
778                         return -1;
779                 }
780
781                 eat_spaces(str);
782                 if (parse_char(loc, str, ']') < 0)
783                         goto fail;
784
785         } else {
786                 *retp = type_get_simple(ARGTYPE_INT);
787                 *ownp = 0;
788         }
789
790         /* We'll need to set the lens, so unshare.  */
791         if (unshare_type_info(loc, retp, ownp) < 0)
792                 goto fail;
793
794         eat_spaces(str);
795         if (parse_char(loc, str, '(') < 0)
796                 goto fail;
797
798         struct enum_lens *lens = malloc(sizeof(*lens));
799         if (lens == NULL) {
800                 report_error(loc->filename, loc->line_no,
801                              "malloc enum lens: %s", strerror(errno));
802                 return -1;
803         }
804
805         lens_init_enum(lens);
806         (*retp)->lens = &lens->super;
807         (*retp)->own_lens = 1;
808
809         long last_val = 0;
810         while (1) {
811                 eat_spaces(str);
812                 if (**str == 0 || **str == ')') {
813                         parse_char(loc, str, ')');
814                         return 0;
815                 }
816
817                 /* Field delimiter.  XXX should we support the C
818                  * syntax, where the enumeration can end in pending
819                  * comma?  */
820                 if (lens_enum_size(lens) > 0)
821                         parse_char(loc, str, ',');
822
823                 eat_spaces(str);
824                 char *key = parse_ident(loc, str);
825                 if (key == NULL) {
826                 err:
827                         free(key);
828                         goto fail;
829                 }
830
831                 if (**str == '=') {
832                         ++*str;
833                         eat_spaces(str);
834                         if (parse_int(loc, str, &last_val) < 0)
835                                 goto err;
836                 }
837
838                 struct value *value = malloc(sizeof(*value));
839                 if (value == NULL)
840                         goto err;
841                 value_init_detached(value, NULL, *retp, 0);
842                 value_set_word(value, last_val);
843
844                 if (lens_enum_add(lens, key, 1, value, 1) < 0)
845                         goto err;
846
847                 last_val++;
848         }
849
850         return 0;
851 }
852
853 static struct arg_type_info *
854 parse_nonpointer_type(struct protolib *plib, struct locus *loc,
855                       char **str, struct param **extra_param, size_t param_num,
856                       int *ownp, int *forwardp)
857 {
858         const char *orig_str = *str;
859         enum arg_type type;
860         if (parse_arg_type(str, &type) < 0) {
861                 struct arg_type_info *type;
862                 if (parse_alias(plib, loc, str, &type,
863                                 ownp, extra_param, param_num) < 0)
864                         return NULL;
865                 else if (type != NULL)
866                         return type;
867
868                 *ownp = 0;
869                 if ((type = parse_typedef_name(plib, str)) == NULL)
870                         report_error(loc->filename, loc->line_no,
871                                      "unknown type around '%s'", orig_str);
872                 return type;
873         }
874
875         /* For some types that's all we need.  */
876         switch (type) {
877         case ARGTYPE_VOID:
878         case ARGTYPE_INT:
879         case ARGTYPE_UINT:
880         case ARGTYPE_LONG:
881         case ARGTYPE_ULONG:
882         case ARGTYPE_CHAR:
883         case ARGTYPE_SHORT:
884         case ARGTYPE_USHORT:
885         case ARGTYPE_FLOAT:
886         case ARGTYPE_DOUBLE:
887                 *ownp = 0;
888                 return type_get_simple(type);
889
890         case ARGTYPE_ARRAY:
891         case ARGTYPE_STRUCT:
892                 break;
893
894         case ARGTYPE_POINTER:
895                 /* Pointer syntax is not based on keyword, so we
896                  * should never get this type.  */
897                 assert(type != ARGTYPE_POINTER);
898                 abort();
899         }
900
901         struct arg_type_info *info = malloc(sizeof(*info));
902         if (info == NULL) {
903                 report_error(loc->filename, loc->line_no,
904                              "malloc: %s", strerror(errno));
905                 return NULL;
906         }
907         *ownp = 1;
908
909         if (type == ARGTYPE_ARRAY) {
910                 if (parse_array(plib, loc, str, info) < 0) {
911                 fail:
912                         free(info);
913                         return NULL;
914                 }
915         } else {
916                 assert(type == ARGTYPE_STRUCT);
917                 if (parse_struct(plib, loc, str, info, forwardp) < 0)
918                         goto fail;
919         }
920
921         return info;
922 }
923
924 static struct named_lens {
925         const char *name;
926         struct lens *lens;
927 } lenses[] = {
928         { "hide", &blind_lens },
929         { "octal", &octal_lens },
930         { "oct", &octal_lens },
931         { "bitvec", &bitvect_lens },
932         { "hex", &hex_lens },
933         { "bool", &bool_lens },
934         { "guess", &guess_lens },
935 };
936
937 static struct lens *
938 name2lens(char **str, int *own_lensp)
939 {
940         size_t i;
941         for (i = 0; i < sizeof(lenses)/sizeof(*lenses); ++i)
942                 if (try_parse_kwd(str, lenses[i].name) == 0) {
943                         *own_lensp = 0;
944                         return lenses[i].lens;
945                 }
946
947         return NULL;
948 }
949
950 static struct arg_type_info *
951 parse_type(struct protolib *plib, struct locus *loc, char **str,
952            struct param **extra_param, size_t param_num,
953            int *ownp, int *forwardp)
954 {
955         struct arg_type_info *info
956                 = parse_nonpointer_type(plib, loc, str, extra_param,
957                                         param_num, ownp, forwardp);
958         if (info == NULL)
959                 return NULL;
960
961         while (1) {
962                 eat_spaces(str);
963                 if (**str == '*') {
964                         struct arg_type_info *outer = malloc(sizeof(*outer));
965                         if (outer == NULL) {
966                                 if (*ownp) {
967                                         type_destroy(info);
968                                         free(info);
969                                 }
970                                 report_error(loc->filename, loc->line_no,
971                                              "malloc: %s", strerror(errno));
972                                 return NULL;
973                         }
974                         type_init_pointer(outer, info, *ownp);
975                         *ownp = 1;
976                         (*str)++;
977                         info = outer;
978                 } else
979                         break;
980         }
981         return info;
982 }
983
984 static struct arg_type_info *
985 parse_lens(struct protolib *plib, struct locus *loc,
986            char **str, struct param **extra_param,
987            size_t param_num, int *ownp, int *forwardp)
988 {
989         int own_lens;
990         struct lens *lens = name2lens(str, &own_lens);
991         int has_args = 1;
992         struct arg_type_info *info;
993         if (lens != NULL) {
994                 eat_spaces(str);
995
996                 /* Octal lens gets special treatment, because of
997                  * backward compatibility.  */
998                 if (lens == &octal_lens && **str != '(') {
999                         has_args = 0;
1000                         info = type_get_simple(ARGTYPE_INT);
1001                         *ownp = 0;
1002                 } else if (parse_char(loc, str, '(') < 0) {
1003                         report_error(loc->filename, loc->line_no,
1004                                      "expected type argument after the lens");
1005                         return NULL;
1006                 }
1007         }
1008
1009         if (has_args) {
1010                 eat_spaces(str);
1011                 info = parse_type(plib, loc, str, extra_param, param_num,
1012                                   ownp, forwardp);
1013                 if (info == NULL) {
1014                 fail:
1015                         if (own_lens && lens != NULL)
1016                                 lens_destroy(lens);
1017                         return NULL;
1018                 }
1019         }
1020
1021         if (lens != NULL && has_args) {
1022                 eat_spaces(str);
1023                 parse_char(loc, str, ')');
1024         }
1025
1026         /* We can't modify shared types.  Make a copy if we have a
1027          * lens.  */
1028         if (lens != NULL && unshare_type_info(loc, &info, ownp) < 0)
1029                 goto fail;
1030
1031         if (lens != NULL) {
1032                 info->lens = lens;
1033                 info->own_lens = own_lens;
1034         }
1035
1036         return info;
1037 }
1038
1039 static int
1040 param_is_void(struct param *param)
1041 {
1042         return param->flavor == PARAM_FLAVOR_TYPE
1043                 && param->u.type.type->type == ARGTYPE_VOID;
1044 }
1045
1046 static struct arg_type_info *
1047 get_hidden_int(void)
1048 {
1049         static struct arg_type_info info, *pinfo = NULL;
1050         if (pinfo != NULL)
1051                 return pinfo;
1052
1053         info = *type_get_simple(ARGTYPE_INT);
1054         info.lens = &blind_lens;
1055         pinfo = &info;
1056
1057         return pinfo;
1058 }
1059
1060 static enum callback_status
1061 void_to_hidden_int(struct prototype *proto, struct param *param, void *data)
1062 {
1063         struct locus *loc = data;
1064         if (param_is_void(param)) {
1065                 report_warning(loc->filename, loc->line_no,
1066                                "void parameter assumed to be 'hide(int)'");
1067
1068                 static struct arg_type_info *type = NULL;
1069                 if (type == NULL)
1070                         type = get_hidden_int();
1071                 param_destroy(param);
1072                 param_init_type(param, type, 0);
1073         }
1074         return CBS_CONT;
1075 }
1076
1077 static int
1078 process_line(struct protolib *plib, struct locus *loc, char *buf)
1079 {
1080         char *str = buf;
1081
1082         debug(3, "Reading line %d of `%s'", loc->line_no, loc->filename);
1083         eat_spaces(&str);
1084
1085         /* A comment or empty line.  */
1086         if (*str == ';' || *str == 0 || *str == '\n' || *str == '#')
1087                 return 0;
1088
1089         if (strncmp(str, "typedef", 7) == 0) {
1090                 parse_typedef(plib, loc, &str);
1091                 return 0;
1092         }
1093
1094         struct prototype fun;
1095         prototype_init(&fun);
1096
1097         struct param *extra_param = NULL;
1098         char *proto_name = NULL;
1099         int own;
1100         fun.return_info = parse_lens(plib, loc, &str, NULL, 0, &own, NULL);
1101         if (fun.return_info == NULL) {
1102         err:
1103                 debug(3, " Skipping line %d", loc->line_no);
1104
1105                 if (extra_param != NULL) {
1106                         param_destroy(extra_param);
1107                         free(extra_param);
1108                 }
1109
1110                 prototype_destroy(&fun);
1111                 free(proto_name);
1112                 return -1;
1113         }
1114         fun.own_return_info = own;
1115         debug(4, " return_type = %d", fun.return_info->type);
1116
1117         eat_spaces(&str);
1118         proto_name = parse_ident(loc, &str);
1119         if (proto_name == NULL)
1120                 goto err;
1121
1122         eat_spaces(&str);
1123         if (parse_char(loc, &str, '(') < 0)
1124                 goto err;
1125         debug(3, " name = %s", proto_name);
1126
1127         int have_stop = 0;
1128
1129         while (1) {
1130                 eat_spaces(&str);
1131                 if (*str == ')')
1132                         break;
1133
1134                 if (str[0] == '+') {
1135                         if (have_stop == 0) {
1136                                 struct param param;
1137                                 param_init_stop(&param);
1138                                 if (prototype_push_param(&fun, &param) < 0) {
1139                                 oom:
1140                                         report_error(loc->filename,
1141                                                      loc->line_no,
1142                                                      "%s", strerror(errno));
1143                                         goto err;
1144                                 }
1145                                 have_stop = 1;
1146                         }
1147                         str++;
1148                 }
1149
1150                 int own;
1151                 size_t param_num = prototype_num_params(&fun) - have_stop;
1152                 struct arg_type_info *type
1153                         = parse_lens(plib, loc, &str, &extra_param,
1154                                      param_num, &own, NULL);
1155                 if (type == NULL) {
1156                         report_error(loc->filename, loc->line_no,
1157                                      "unknown argument type");
1158                         goto err;
1159                 }
1160
1161                 struct param param;
1162                 param_init_type(&param, type, own);
1163                 if (prototype_push_param(&fun, &param) < 0)
1164                         goto oom;
1165
1166                 eat_spaces(&str);
1167                 if (*str == ',') {
1168                         str++;
1169                         continue;
1170                 } else if (*str == ')') {
1171                         continue;
1172                 } else {
1173                         if (str[strlen(str) - 1] == '\n')
1174                                 str[strlen(str) - 1] = '\0';
1175                         report_error(loc->filename, loc->line_no,
1176                                      "syntax error around \"%s\"", str);
1177                         goto err;
1178                 }
1179         }
1180
1181         /* We used to allow void parameter as a synonym to an argument
1182          * that shouldn't be displayed.  But backends really need to
1183          * know the exact type that they are dealing with.  The proper
1184          * way to do this these days is to use the hide lens.
1185          *
1186          * So if there are any voids in the parameter list, show a
1187          * warning and assume that they are ints.  If there's a sole
1188          * void, assume the function doesn't take any arguments.  The
1189          * latter is conservative, we can drop the argument
1190          * altogether, instead of fetching and then not showing it,
1191          * without breaking any observable behavior.  */
1192         if (prototype_num_params(&fun) == 1
1193             && param_is_void(prototype_get_nth_param(&fun, 0))) {
1194                 if (0)
1195                         /* Don't show this warning.  Pre-0.7.0
1196                          * ltrace.conf often used this idiom.  This
1197                          * should be postponed until much later, when
1198                          * extant uses are likely gone.  */
1199                         report_warning(loc->filename, loc->line_no,
1200                                        "sole void parameter ignored");
1201                 prototype_destroy_nth_param(&fun, 0);
1202         } else {
1203                 prototype_each_param(&fun, NULL, void_to_hidden_int, loc);
1204         }
1205
1206         if (extra_param != NULL) {
1207                 prototype_push_param(&fun, extra_param);
1208                 free(extra_param);
1209                 extra_param = NULL;
1210         }
1211
1212         if (protolib_add_prototype(plib, proto_name, 1, &fun) < 0) {
1213                 report_error(loc->filename, loc->line_no,
1214                              "couldn't add prototype: %s",
1215                              strerror(errno));
1216                 goto err;
1217         }
1218
1219         return 0;
1220 }
1221
1222 int
1223 read_config_file(FILE *stream, const char *path, struct protolib *plib)
1224 {
1225         debug(DEBUG_FUNCTION, "Reading config file `%s'...", path);
1226
1227         struct locus loc = { path, 0 };
1228         char *line = NULL;
1229         size_t len = 0;
1230         while (getline(&line, &len, stream) >= 0) {
1231                 loc.line_no++;
1232                 process_line(plib, &loc, line);
1233         }
1234
1235         free(line);
1236         return 0;
1237 }