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