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