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