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