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