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