read_config_file.c revision 1b9cfd6ad305ad909e8ff17139111a7c78f01464
1#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <string.h>
6#include <stdlib.h>
7#include <ctype.h>
8
9#include "ltrace.h"
10#include "read_config_file.h"
11#include "options.h"
12#include "output.h"
13
14/*
15 *	"void"		ARGTYPE_VOID
16 *	"int"		ARGTYPE_INT
17 *	"uint"		ARGTYPE_UINT
18 *	"octal"		ARGTYPE_OCTAL
19 *	"char"		ARGTYPE_CHAR
20 *	"string"	ARGTYPE_STRING
21 *	"format"	ARGTYPE_FORMAT
22 *	"addr"		ARGTYPE_ADDR
23 */
24
25struct function * list_of_functions = NULL;
26
27static struct list_of_pt_t {
28	char * name;
29	enum arg_type pt;
30} list_of_pt[] = {
31	{ "void",   ARGTYPE_VOID },
32	{ "int",    ARGTYPE_INT },
33	{ "uint",   ARGTYPE_UINT },
34	{ "octal",  ARGTYPE_OCTAL },
35	{ "char",   ARGTYPE_CHAR },
36	{ "addr",   ARGTYPE_ADDR },
37	{ "file",   ARGTYPE_FILE },
38	{ "format", ARGTYPE_FORMAT },
39	{ "string", ARGTYPE_STRING },
40	{ "string0",ARGTYPE_STRING0 },
41	{ "string1",ARGTYPE_STRING1 },
42	{ "string2",ARGTYPE_STRING2 },
43	{ "string3",ARGTYPE_STRING3 },
44	{ NULL,     ARGTYPE_UNKNOWN }		/* Must finish with NULL */
45};
46
47static enum arg_type str2type(char ** str)
48{
49	struct list_of_pt_t * tmp = &list_of_pt[0];
50
51	while(tmp->name) {
52		if (!strncmp(*str, tmp->name, strlen(tmp->name))
53			&& index(" ,)#", *(*str+strlen(tmp->name)))) {
54				*str += strlen(tmp->name);
55				return tmp->pt;
56		}
57		tmp++;
58	}
59	return ARGTYPE_UNKNOWN;
60}
61
62static void eat_spaces(char ** str)
63{
64	while(**str==' ') {
65		(*str)++;
66	}
67}
68
69/*
70  Returns position in string at the left parenthesis which starts the
71  function's argument signature. Returns NULL on error.
72  FIXME: this routine incorrectly returns the beginning of the string in
73         things like "hello)" (cespedes)
74*/
75static char * start_of_arg_sig(char * str)
76{
77	char * pos;
78	int stacked = 0;
79
80	if (!strlen(str)) return NULL;
81
82	pos = &str[strlen(str)];
83	do {
84		pos--;
85		while ((pos > str) && (*pos != ')') && (*pos != '(')) pos--;
86
87		if (pos < str) return NULL;
88		else if (*pos == ')') stacked++;
89		else stacked--;
90
91	} while (stacked > 0);
92
93	return (stacked == 0) ? pos : NULL;
94}
95
96static int line_no;
97static char * filename;
98
99struct function * process_line (char * buf) {
100	struct function fun;
101	struct function * fun_p;
102	char * str = buf;
103	char * tmp;
104	int i;
105
106	line_no++;
107	if (opt_d>2) {
108		output_line(0, "Reading line %d of `%s'", line_no, filename);
109	}
110	eat_spaces(&str);
111	fun.return_type = str2type(&str);
112	if (fun.return_type==ARGTYPE_UNKNOWN) {
113		if (opt_d>2) {
114			output_line(0, " Skipping line %d", line_no);
115		}
116		return NULL;
117	}
118	if (opt_d>3) {
119		output_line(0, " return_type = %d", fun.return_type);
120	}
121	eat_spaces(&str);
122#if 0  /* Obsoleted code. 19990702 mortene. */
123       /* FIXME: why the space? 19990702 mortene. */
124	tmp = strpbrk(str, " (");
125#else
126	tmp = start_of_arg_sig(str);
127#endif
128	if (!tmp) {
129		output_line(0, "Syntax error in `%s', line %d", filename, line_no);
130		return NULL;
131	}
132	*tmp = '\0';
133	fun.name = strdup(str);
134	str = tmp+1;
135	if (opt_d>2) {
136		output_line(0, " name = %s", fun.name);
137	}
138	fun.params_right = 0;
139	for(i=0; i<MAX_ARGS; i++) {
140		eat_spaces(&str);
141		if (*str == ')') {
142			break;
143		}
144		if (str[0]=='+') {
145			fun.params_right++;
146			str++;
147		} else if (fun.params_right) {
148			fun.params_right++;
149		}
150		fun.arg_types[i] = str2type(&str);
151		if (fun.return_type==ARGTYPE_UNKNOWN) {
152			output_line(0, "Syntax error in `%s', line %d", filename, line_no);
153			return NULL;
154		}
155		eat_spaces(&str);
156		if (*str==',') {
157			str++;
158			continue;
159		} else if (*str==')') {
160			continue;
161		} else {
162			output_line(0, "Syntax error in `%s', line %d", filename, line_no);
163			return NULL;
164		}
165	}
166	fun.num_params = i;
167	fun_p = malloc(sizeof(struct function));
168	memcpy(fun_p, &fun, sizeof(struct function));
169	return fun_p;
170}
171
172void read_config_file(char * file)
173{
174	FILE * stream;
175	char buf[1024];
176
177	filename = file;
178
179	if (opt_d) {
180		output_line(0, "Reading config file `%s'...", filename);
181	}
182
183	stream = fopen(filename, "r");
184	if (!stream) {
185		return;
186	}
187	line_no=0;
188	while (fgets(buf, 1024, stream)) {
189		struct function * tmp = process_line(buf);
190
191		if (tmp) {
192			if (opt_d > 1) {
193				output_line(0, "New function: `%s'", tmp->name);
194			}
195			tmp->next = list_of_functions;
196			list_of_functions = tmp;
197		}
198	}
199	fclose(stream);
200}
201