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