read_config_file.c revision ce034981e2880eecb8a196c78182dfb4ae67850f
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4 * Copyright (C) 1998,1999,2003,2007,2008,2009 Juan Cespedes
5 * Copyright (C) 2006 Ian Wienand
6 * Copyright (C) 2006 Steve Fink
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 */
23
24#include "config.h"
25
26#include <string.h>
27#include <stdlib.h>
28#include <ctype.h>
29#include <errno.h>
30#include <error.h>
31#include <assert.h>
32
33#include "common.h"
34#include "output.h"
35#include "expr.h"
36#include "param.h"
37#include "printf.h"
38#include "zero.h"
39#include "type.h"
40#include "lens.h"
41
42static int line_no;
43static char *filename;
44
45static struct arg_type_info *parse_nonpointer_type(char **str,
46						   struct param **extra_param,
47						   size_t param_num, int *ownp);
48static struct arg_type_info *parse_type(char **str, struct param **extra_param,
49					size_t param_num, int *ownp);
50static struct arg_type_info *parse_lens(char **str, struct param **extra_param,
51					size_t param_num, int *ownp);
52
53Function *list_of_functions = NULL;
54
55static int
56parse_arg_type(char **name, enum arg_type *ret)
57{
58	char *rest = NULL;
59	enum arg_type candidate = ARGTYPE_UNKNOWN;
60
61#define KEYWORD(KWD, TYPE)						\
62	do {								\
63		if (strncmp(*name, KWD, sizeof(KWD) - 1) == 0) {	\
64			rest = *name + sizeof(KWD) - 1;			\
65			candidate = TYPE;				\
66			goto ok;					\
67		}							\
68	} while (0)
69
70	KEYWORD("void", ARGTYPE_VOID);
71	KEYWORD("int", ARGTYPE_INT);
72	KEYWORD("uint", ARGTYPE_UINT);
73	KEYWORD("long", ARGTYPE_LONG);
74	KEYWORD("ulong", ARGTYPE_ULONG);
75	KEYWORD("char", ARGTYPE_CHAR);
76	KEYWORD("short", ARGTYPE_SHORT);
77	KEYWORD("ushort", ARGTYPE_USHORT);
78	KEYWORD("float", ARGTYPE_FLOAT);
79	KEYWORD("double", ARGTYPE_DOUBLE);
80	KEYWORD("array", ARGTYPE_ARRAY);
81	KEYWORD("enum", ARGTYPE_ENUM);
82	KEYWORD("struct", ARGTYPE_STRUCT);
83
84	assert(rest == NULL);
85	return -1;
86
87#undef KEYWORD
88
89ok:
90	if (isalnum(*rest))
91		return -1;
92
93	*name = rest;
94	*ret = candidate;
95	return 0;
96}
97
98static void
99eat_spaces(char **str) {
100	while (**str == ' ') {
101		(*str)++;
102	}
103}
104
105static char *
106xstrndup(char *str, size_t len) {
107	char *ret = (char *) malloc(len + 1);
108	if (ret == NULL) {
109		report_global_error("malloc: %s", strerror(errno));
110		return NULL;
111	}
112	strncpy(ret, str, len);
113	ret[len] = 0;
114	return ret;
115}
116
117static char *
118parse_ident(char **str) {
119	char *ident = *str;
120
121	if (!isalpha(**str) && **str != '_') {
122		report_error(filename, line_no, "bad identifier");
123		return NULL;
124	}
125
126	while (**str && (isalnum(**str) || **str == '_')) {
127		++(*str);
128	}
129
130	return xstrndup(ident, *str - ident);
131}
132
133/*
134  Returns position in string at the left parenthesis which starts the
135  function's argument signature. Returns NULL on error.
136*/
137static char *
138start_of_arg_sig(char *str) {
139	char *pos;
140	int stacked = 0;
141
142	if (!strlen(str))
143		return NULL;
144
145	pos = &str[strlen(str)];
146	do {
147		pos--;
148		if (pos < str)
149			return NULL;
150		while ((pos > str) && (*pos != ')') && (*pos != '('))
151			pos--;
152
153		if (*pos == ')')
154			stacked++;
155		else if (*pos == '(')
156			stacked--;
157		else
158			return NULL;
159
160	} while (stacked > 0);
161
162	return (stacked == 0) ? pos : NULL;
163}
164
165static int
166parse_int(char **str, long *ret)
167{
168	char *end;
169	long n = strtol(*str, &end, 0);
170	if (end == *str) {
171		report_error(filename, line_no, "bad number");
172		return -1;
173	}
174
175	*str = end;
176	if (ret != NULL)
177		*ret = n;
178	return 0;
179}
180
181static int
182check_nonnegative(long l)
183{
184	if (l < 0) {
185		report_error(filename, line_no,
186			     "expected non-negative value, got %ld", l);
187		return -1;
188	}
189	return 0;
190}
191
192static int
193check_int(long l)
194{
195	int i = l;
196	if ((long)i != l) {
197		report_error(filename, line_no,
198			     "Number too large: %ld", l);
199		return -1;
200	}
201	return 0;
202}
203
204static int
205parse_char(char **str, char expected)
206{
207	if (**str != expected) {
208		report_error(filename, line_no,
209			     "expected '%c', got '%c'", expected, **str);
210		return -1;
211	}
212
213	++*str;
214	return 0;
215}
216
217static struct expr_node *parse_argnum(char **str, int zero);
218
219static struct expr_node *
220parse_zero(char **str, struct expr_node *ret)
221{
222	eat_spaces(str);
223	if (**str == '(') {
224		++*str;
225		struct expr_node *arg = parse_argnum(str, 0);
226		if (arg == NULL)
227			return NULL;
228		if (parse_char(str, ')') < 0) {
229		fail:
230			expr_destroy(arg);
231			free(arg);
232			return NULL;
233		}
234
235		struct expr_node *ret = build_zero_w_arg(arg, 1);
236		if (ret == NULL)
237			goto fail;
238		return ret;
239
240	} else {
241		return expr_node_zero();
242	}
243}
244
245static int
246wrap_in_zero(struct expr_node **nodep)
247{
248	struct expr_node *n = build_zero_w_arg(*nodep, 1);
249	if (n == NULL)
250		return -1;
251	*nodep = n;
252	return 0;
253}
254
255/*
256 * Input:
257 *  argN   : The value of argument #N, counting from 1
258 *  eltN   : The value of element #N of the containing structure
259 *  retval : The return value
260 *  N      : The numeric value N
261 */
262static struct expr_node *
263parse_argnum(char **str, int zero)
264{
265	struct expr_node *expr = malloc(sizeof(*expr));
266	if (expr == NULL)
267		return NULL;
268
269	if (isdigit(**str)) {
270		long l;
271		if (parse_int(str, &l) < 0
272		    || check_nonnegative(l) < 0
273		    || check_int(l) < 0)
274			goto fail;
275
276		expr_init_const_word(expr, l, type_get_simple(ARGTYPE_LONG), 0);
277
278		if (zero && wrap_in_zero(&expr) < 0)
279			goto fail;
280
281		return expr;
282
283	} else {
284		char *name = parse_ident(str);
285		if (name == NULL)
286			goto fail;
287
288		int is_arg = strncmp(name, "arg", 3) == 0;
289		int is_elt = !is_arg && strncmp(name, "elt", 3) == 0;
290		if (is_arg || is_elt) {
291			long l;
292			name += 3;
293			if (parse_int(&name, &l) < 0
294			    || check_int(l) < 0)
295				goto fail;
296
297			if (is_arg) {
298				expr_init_argno(expr, l - 1);
299			} else {
300				struct expr_node *e_up = malloc(sizeof(*e_up));
301				struct expr_node *e_ix = malloc(sizeof(*e_ix));
302				if (e_up == NULL || e_ix == NULL) {
303					free(e_up);
304					free(e_ix);
305					goto fail;
306				}
307
308				expr_init_up(e_up, expr_self(), 0);
309				struct arg_type_info *ti
310					= type_get_simple(ARGTYPE_LONG);
311				expr_init_const_word(e_ix, l - 1, ti, 0);
312				expr_init_index(expr, e_up, 1, e_ix, 1);
313			}
314
315		} else if (strcmp(name, "retval") == 0) {
316			expr_init_named(expr, "retval", 0);
317
318		} else if (strcmp(name, "zero") == 0) {
319			struct expr_node *ret = parse_zero(str, expr);
320			if (ret == NULL)
321				goto fail;
322			return ret;
323
324		} else {
325			report_error(filename, line_no,
326				     "Unknown length specifier: '%s'", name);
327			goto fail;
328		}
329
330		if (zero && wrap_in_zero(&expr) < 0)
331			goto fail;
332
333		return expr;
334	}
335
336fail:
337	free(expr);
338	return NULL;
339}
340
341struct typedef_node_t {
342	char *name;
343	struct arg_type_info *info;
344	int own_type;
345	struct typedef_node_t *next;
346} *typedefs = NULL;
347
348static struct arg_type_info *
349lookup_typedef(char **str) {
350	struct typedef_node_t *node;
351	char *end = *str;
352	while (*end && (isalnum(*end) || *end == '_'))
353		++end;
354	if (end == *str)
355		return NULL;
356
357	for (node = typedefs; node != NULL; node = node->next) {
358		if (strncmp(*str, node->name, end - *str) == 0) {
359			(*str) += strlen(node->name);
360			return node->info;
361		}
362	}
363
364	return NULL;
365}
366
367static struct typedef_node_t *
368insert_typedef(char *name, struct arg_type_info *info, int own_type)
369{
370	struct typedef_node_t *binding = malloc(sizeof(*binding));
371	binding->name = name;
372	binding->info = info;
373	binding->own_type = own_type;
374	binding->next = typedefs;
375	typedefs = binding;
376	return binding;
377}
378
379static void
380parse_typedef(char **str) {
381	char *name;
382	struct arg_type_info *info;
383
384	(*str) += strlen("typedef");
385	eat_spaces(str);
386
387	// Grab out the name of the type
388	name = parse_ident(str);
389
390	// Skip = sign
391	eat_spaces(str);
392	if (parse_char(str, '=') < 0)
393		return;
394	eat_spaces(str);
395
396	// Parse the type
397	int own;
398	info = parse_type(str, NULL, 0, &own);
399
400	insert_typedef(name, info, own);
401}
402
403static void
404destroy_fun(Function *fun)
405{
406	size_t i;
407	if (fun == NULL)
408		return;
409	if (fun->own_return_info) {
410		type_destroy(fun->return_info);
411		free(fun->return_info);
412	}
413	for (i = 0; i < fun->num_params; ++i)
414		param_destroy(&fun->params[i]);
415	free(fun->params);
416}
417
418/* Syntax: struct ( type,type,type,... ) */
419static int
420parse_struct(char **str, struct arg_type_info *info)
421{
422	eat_spaces(str);
423	if (parse_char(str, '(') < 0)
424		return -1;
425
426	eat_spaces(str); // Empty arg list with whitespace inside
427
428	type_init_struct(info);
429
430	while (1) {
431		eat_spaces(str);
432		if (**str == 0 || **str == ')') {
433			parse_char(str, ')');
434			return 0;
435		}
436
437		/* Field delimiter.  */
438		if (type_struct_size(info) > 0)
439			parse_char(str, ',');
440
441		eat_spaces(str);
442		int own;
443		struct arg_type_info *field = parse_lens(str, NULL, 0, &own);
444		if (field == NULL || type_struct_add(info, field, own)) {
445			type_destroy(info);
446			return -1;
447		}
448	}
449}
450
451static int
452parse_string(char **str, struct arg_type_info **retp)
453{
454	struct arg_type_info *info = malloc(sizeof(*info));
455	if (info == NULL) {
456	fail:
457		free(info);
458		return -1;
459	}
460
461	struct expr_node *length;
462	int own_length;
463
464	if (isdigit(**str)) {
465		/* string0 is string[retval], length is zero(retval)
466		 * stringN is string[argN], length is zero(argN) */
467		long l;
468		if (parse_int(str, &l) < 0
469		    || check_int(l) < 0)
470			goto fail;
471
472		struct expr_node *length_arg = malloc(sizeof(*length_arg));
473		if (length_arg == NULL)
474			goto fail;
475
476		if (l == 0)
477			expr_init_named(length_arg, "retval", 0);
478		else
479			expr_init_argno(length_arg, l - 1);
480
481		length = build_zero_w_arg(length_arg, 1);
482		if (length == NULL) {
483			expr_destroy(length_arg);
484			free(length_arg);
485			goto fail;
486		}
487		own_length = 1;
488
489	} else {
490		eat_spaces(str);
491		if (**str == '[') {
492			(*str)++;
493			eat_spaces(str);
494
495			length = parse_argnum(str, 1);
496			if (length == NULL)
497				goto fail;
498			own_length = 1;
499
500			eat_spaces(str);
501			parse_char(str, ']');
502
503		} else {
504			/* It was just a simple string after all.  */
505			length = expr_node_zero();
506			own_length = 0;
507		}
508	}
509
510	/* String is a pointer to array of chars.  */
511	type_init_string(info, length, own_length);
512
513	*retp = info;
514	return 0;
515}
516
517static int
518build_printf_pack(struct param **packp, size_t param_num)
519{
520	if (packp == NULL) {
521		report_error(filename, line_no,
522			     "'format' type in unexpected context");
523		return -1;
524	}
525	if (*packp != NULL) {
526		report_error(filename, line_no,
527			     "only one 'format' type per function supported");
528		return -1;
529	}
530
531	*packp = malloc(sizeof(**packp));
532	if (*packp == NULL)
533		return -1;
534
535	struct expr_node *node = malloc(sizeof(*node));
536	if (node == NULL) {
537		free(*packp);
538		return -1;
539	}
540
541	expr_init_argno(node, param_num);
542
543	param_pack_init_printf(*packp, node, 1);
544
545	return 0;
546}
547
548/* Make a copy of INFO and set the *OWN bit if it's not already
549 * owned.  */
550static int
551unshare_type_info(struct arg_type_info **infop, int *ownp)
552{
553	if (*ownp)
554		return 0;
555
556	struct arg_type_info *ninfo = malloc(sizeof(*ninfo));
557	if (ninfo == NULL) {
558		report_error(filename, line_no,
559			     "malloc: %s", strerror(errno));
560		return -1;
561	}
562	*ninfo = **infop;
563	*infop = ninfo;
564	*ownp = 1;
565	return 0;
566}
567
568/* XXX extra_param and param_num are a kludge to get in
569 * backward-compatible support for "format" parameter type.  The
570 * latter is only valid if the former is non-NULL, which is only in
571 * top-level context.  */
572static int
573parse_alias(char **str, struct arg_type_info **retp, int *ownp,
574	    struct param **extra_param, size_t param_num)
575{
576	/* For backward compatibility, we need to support things like
577	 * stringN (which is like string[argN], string[N], and also
578	 * bare string.  We might, in theory, replace this by
579	 * preprocessing configure file sources with M4, but for now,
580	 * "string" is syntax.  */
581	if (strncmp(*str, "string", 6) == 0) {
582		(*str) += 6;
583		return parse_string(str, retp);
584
585	} else if (strncmp(*str, "format", 6) == 0
586		   && !isalnum((*str)[6])
587		   && extra_param != NULL) {
588		/* For backward compatibility, format is parsed as
589		 * "string", but it smuggles to the parameter list of
590		 * a function a "printf" argument pack with this
591		 * parameter as argument.  */
592		(*str) += 6;
593		if (parse_string(str, retp) < 0)
594			return -1;
595
596		return build_printf_pack(extra_param, param_num);
597
598	} else {
599		*retp = NULL;
600		return 0;
601	}
602}
603
604/* Syntax: array ( type, N|argN ) */
605static int
606parse_array(char **str, struct arg_type_info *info)
607{
608	eat_spaces(str);
609	if (parse_char(str, '(') < 0)
610		return -1;
611
612	eat_spaces(str);
613	int own;
614	struct arg_type_info *elt_info = parse_lens(str, NULL, 0, &own);
615	if (elt_info == NULL)
616		return -1;
617
618	eat_spaces(str);
619	parse_char(str, ',');
620
621	eat_spaces(str);
622	struct expr_node *length = parse_argnum(str, 0);
623	if (length == NULL) {
624		if (own) {
625			type_destroy(elt_info);
626			free(elt_info);
627		}
628		return -1;
629	}
630
631	type_init_array(info, elt_info, own, length, 1);
632
633	eat_spaces(str);
634	parse_char(str, ')');
635	return 0;
636}
637
638/* Syntax: enum ( keyname=value,keyname=value,... ) */
639static int
640parse_enum(char **str, struct arg_type_info *info)
641{
642	eat_spaces(str);
643	if (parse_char(str, '(') < 0)
644		return -1;
645
646	type_init_enum(info);
647
648	int last_val = 0;
649	while (1) {
650		eat_spaces(str);
651		if (**str == 0 || **str == ')') {
652			parse_char(str, ')');
653			return 0;
654		}
655
656		/* Field delimiter.  XXX should we support the C
657		 * syntax, where the enumeration can end in pending
658		 * comma?  */
659		if (type_enum_size(info) > 0)
660			parse_char(str, ',');
661
662		eat_spaces(str);
663		char *key = parse_ident(str);
664		if (key == NULL) {
665		err:
666			free(key);
667			return -1;
668		}
669
670		if (**str == '=') {
671			++*str;
672			eat_spaces(str);
673			long l;
674			if (parse_int(str, &l) < 0 || check_int(l) < 0)
675				goto err;
676			last_val = l;
677
678		} else {
679			last_val++;
680		}
681
682		if (type_enum_add(info, key, 1, last_val) < 0)
683			goto err;
684	}
685
686	return 0;
687}
688
689static struct arg_type_info *
690parse_nonpointer_type(char **str, struct param **extra_param, size_t param_num,
691		      int *ownp)
692{
693	enum arg_type type;
694	if (parse_arg_type(str, &type) < 0) {
695		struct arg_type_info *simple;
696		if (parse_alias(str, &simple, ownp, extra_param, param_num) < 0)
697			return NULL;
698		if (simple == NULL)
699			simple = lookup_typedef(str);
700		if (simple != NULL) {
701			*ownp = 0;
702			return simple;
703		}
704
705		report_error(filename, line_no,
706			     "unknown type around '%s'", *str);
707		return NULL;
708	}
709
710	int (*parser) (char **, struct arg_type_info *) = NULL;
711
712	/* For some types that's all we need.  */
713	switch (type) {
714	case ARGTYPE_UNKNOWN:
715	case ARGTYPE_VOID:
716	case ARGTYPE_INT:
717	case ARGTYPE_UINT:
718	case ARGTYPE_LONG:
719	case ARGTYPE_ULONG:
720	case ARGTYPE_CHAR:
721	case ARGTYPE_SHORT:
722	case ARGTYPE_USHORT:
723	case ARGTYPE_FLOAT:
724	case ARGTYPE_DOUBLE:
725		*ownp = 0;
726		return type_get_simple(type);
727
728	case ARGTYPE_ARRAY:
729		parser = parse_array;
730		break;
731
732	case ARGTYPE_ENUM:
733		parser = parse_enum;
734		break;
735
736	case ARGTYPE_STRUCT:
737		parser = parse_struct;
738		break;
739
740	case ARGTYPE_STRING_N:
741		/* Strings are handled in aliases, to support
742		 * "stringN" syntax cleanly.  */
743		assert(type != ARGTYPE_STRING_N);
744		abort();
745
746	case ARGTYPE_POINTER:
747		/* Pointer syntax is not based on keyword, so we
748		 * should never get this type.  */
749		assert(type != ARGTYPE_POINTER);
750		abort();
751	}
752
753	struct arg_type_info *info = malloc(sizeof(*info));
754	if (info == NULL) {
755		report_error(filename, line_no,
756			     "malloc: %s", strerror(errno));
757		return NULL;
758	}
759	*ownp = 1;
760
761	if (parser(str, info) < 0) {
762		free(info);
763		return NULL;
764	}
765
766	return info;
767}
768
769static struct named_lens {
770	const char *name;
771	struct lens *lens;
772} lenses[] = {
773	{ "hide", &blind_lens },
774	{ "octal", &octal_lens },
775	{ "hex", &hex_lens },
776};
777
778static struct lens *
779name2lens(char **str, int *own_lensp)
780{
781	char *str2 = *str;
782	char *ident = parse_ident(&str2);
783	size_t i;
784	for (i = 0; i < sizeof(lenses)/sizeof(*lenses); ++i)
785		if (strcmp(ident, lenses[i].name) == 0) {
786			*str = str2;
787			*own_lensp = 0;
788			return lenses[i].lens;
789		}
790
791	return NULL;
792}
793
794static struct arg_type_info *
795parse_type(char **str, struct param **extra_param, size_t param_num, int *ownp)
796{
797	struct arg_type_info *info
798		= parse_nonpointer_type(str, extra_param, param_num, ownp);
799	if (info == NULL)
800		return NULL;
801
802	while (1) {
803		eat_spaces(str);
804		if (**str == '*') {
805			struct arg_type_info *outer = malloc(sizeof(*outer));
806			if (outer == NULL) {
807				if (*ownp) {
808					type_destroy(info);
809					free(info);
810				}
811				report_error(filename, line_no,
812					     "malloc: %s", strerror(errno));
813				return NULL;
814			}
815			type_init_pointer(outer, info, *ownp);
816			*ownp = 1;
817			(*str)++;
818			info = outer;
819		} else
820			break;
821	}
822	return info;
823}
824
825static struct arg_type_info *
826parse_lens(char **str, struct param **extra_param, size_t param_num, int *ownp)
827{
828	int own_lens;
829	struct lens *lens = name2lens(str, &own_lens);
830	int has_args = 1;
831	struct arg_type_info *info;
832	if (lens != NULL) {
833		eat_spaces(str);
834
835		/* Octal lens gets special treatment, because of
836		 * backward compatibility.  */
837		if (lens == &octal_lens && **str != '(') {
838			has_args = 0;
839			info = type_get_simple(ARGTYPE_INT);
840			*ownp = 0;
841		} else if (parse_char(str, '(') < 0) {
842			report_error(filename, line_no,
843				     "expected type argument after the lens");
844			return NULL;
845		}
846	}
847
848	if (has_args) {
849		eat_spaces(str);
850		info = parse_type(str, extra_param, param_num, ownp);
851		if (info == NULL) {
852		fail:
853			if (own_lens && lens != NULL)
854				lens_destroy(lens);
855			return NULL;
856		}
857	}
858
859	if (lens != NULL && has_args) {
860		eat_spaces(str);
861		parse_char(str, ')');
862	}
863
864	/* We can't modify shared types.  Make a copy if we have a
865	 * lens.  */
866	if (lens != NULL && unshare_type_info(&info, ownp) < 0)
867		goto fail;
868
869	if (lens != NULL) {
870		info->lens = lens;
871		info->own_lens = own_lens;
872	}
873
874	return info;
875}
876
877static int
878add_param(Function *fun, size_t *allocdp)
879{
880	size_t allocd = *allocdp;
881	/* XXX +1 is for the extra_param handling hack.  */
882	if ((fun->num_params + 1) >= allocd) {
883		allocd = allocd > 0 ? 2 * allocd : 8;
884		void *na = realloc(fun->params, sizeof(*fun->params) * allocd);
885		if (na == NULL)
886			return -1;
887
888		fun->params = na;
889		*allocdp = allocd;
890	}
891	return 0;
892}
893
894static Function *
895process_line(char *buf) {
896	char *str = buf;
897	char *tmp;
898
899	line_no++;
900	debug(3, "Reading line %d of `%s'", line_no, filename);
901	eat_spaces(&str);
902
903	/* A comment or empty line.  */
904	if (*str == ';' || *str == 0)
905		return NULL;
906
907	if (strncmp(str, "typedef", 7) == 0) {
908		parse_typedef(&str);
909		return NULL;
910	}
911
912	Function *fun = calloc(1, sizeof(*fun));
913	if (fun == NULL) {
914		report_error(filename, line_no,
915			     "alloc function: %s", strerror(errno));
916		return NULL;
917	}
918
919	fun->return_info = parse_lens(&str, NULL, 0, &fun->own_return_info);
920	if (fun->return_info == NULL
921	    || fun->return_info->type == ARGTYPE_UNKNOWN) {
922	err:
923		debug(3, " Skipping line %d", line_no);
924		destroy_fun(fun);
925		return NULL;
926	}
927	debug(4, " return_type = %d", fun->return_info->type);
928
929	eat_spaces(&str);
930	tmp = start_of_arg_sig(str);
931	if (tmp == NULL) {
932		report_error(filename, line_no, "syntax error");
933		goto err;
934	}
935	*tmp = '\0';
936	fun->name = strdup(str);
937	str = tmp + 1;
938	debug(3, " name = %s", fun->name);
939
940	size_t allocd = 0;
941	fun->num_params = 0;
942	struct param *extra_param = NULL;
943
944	int have_stop = 0;
945
946	while (1) {
947		eat_spaces(&str);
948		if (*str == ')')
949			break;
950
951		if (str[0] == '+') {
952			if (have_stop == 0) {
953				if (add_param(fun, &allocd) < 0)
954					goto add_err;
955				param_init_stop
956					(&fun->params[fun->num_params++]);
957				have_stop = 1;
958			}
959			str++;
960		}
961
962		if (add_param(fun, &allocd) < 0) {
963		add_err:
964			report_error(filename, line_no, "(re)alloc params: %s",
965				     strerror(errno));
966			goto err;
967		}
968
969		int own;
970		struct arg_type_info *type = parse_lens(&str, &extra_param,
971							fun->num_params, &own);
972		if (type == NULL) {
973			report_error(filename, line_no,
974				     "unknown argument type");
975			goto err;
976		}
977
978		/* XXX We used to allow void parameter as a synonym to
979		 * an argument that shouldn't be displayed.  We may
980		 * wish to re-introduce this when lenses are
981		 * implemented, as a synonym, but backends generally
982		 * need to know the type, so disallow bare void for
983		 * now.  */
984		if (type->type == ARGTYPE_VOID) {
985			report_warning(filename, line_no,
986				       "void parameter assumed to be 'int'");
987			if (own) {
988				type_destroy(type);
989				free(type);
990			}
991			type = type_get_simple(ARGTYPE_INT);
992			own = 0;
993		}
994
995		param_init_type(&fun->params[fun->num_params++], type, own);
996
997		eat_spaces(&str);
998		if (*str == ',') {
999			str++;
1000			continue;
1001		} else if (*str == ')') {
1002			continue;
1003		} else {
1004			if (str[strlen(str) - 1] == '\n')
1005				str[strlen(str) - 1] = '\0';
1006			report_error(filename, line_no,
1007				     "syntax error around \"%s\"", str);
1008			goto err;
1009		}
1010	}
1011
1012	if (extra_param != NULL) {
1013		assert(fun->num_params < allocd);
1014		memcpy(&fun->params[fun->num_params++], extra_param,
1015		       sizeof(*extra_param));
1016	}
1017
1018	return fun;
1019}
1020
1021void
1022init_global_config(void)
1023{
1024	struct arg_type_info *info = malloc(2 * sizeof(*info));
1025	if (info == NULL)
1026		error(1, errno, "malloc in init_global_config");
1027
1028	memset(info, 0, 2 * sizeof(*info));
1029	info[0].type = ARGTYPE_POINTER;
1030	info[0].u.ptr_info.info = &info[1];
1031	info[1].type = ARGTYPE_VOID;
1032
1033	insert_typedef(strdup("addr"), info, 0);
1034	insert_typedef(strdup("file"), info, 1);
1035}
1036
1037void
1038read_config_file(char *file) {
1039	FILE *stream;
1040	char buf[1024];
1041
1042	filename = file;
1043	stream = fopen(filename, "r");
1044	if (!stream) {
1045		return;
1046	}
1047
1048	debug(1, "Reading config file `%s'...", filename);
1049
1050	line_no = 0;
1051	while (fgets(buf, 1024, stream)) {
1052		Function *tmp;
1053
1054		tmp = process_line(buf);
1055
1056		if (tmp) {
1057			debug(2, "New function: `%s'", tmp->name);
1058			tmp->next = list_of_functions;
1059			list_of_functions = tmp;
1060		}
1061	}
1062	fclose(stream);
1063}
1064