xref: /aosp_15_r20/external/ltp/metadata/metaparse.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2019-2021 Cyril Hrubis <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (c) 2020 Petr Vorel <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  */
6*49cdfc7eSAndroid Build Coastguard Worker 
7*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
8*49cdfc7eSAndroid Build Coastguard Worker 
9*49cdfc7eSAndroid Build Coastguard Worker #include <search.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <libgen.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <ctype.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
16*49cdfc7eSAndroid Build Coastguard Worker 
17*49cdfc7eSAndroid Build Coastguard Worker #include "data_storage.h"
18*49cdfc7eSAndroid Build Coastguard Worker 
19*49cdfc7eSAndroid Build Coastguard Worker #define INCLUDE_PATH_MAX 5
20*49cdfc7eSAndroid Build Coastguard Worker 
21*49cdfc7eSAndroid Build Coastguard Worker static int verbose;
22*49cdfc7eSAndroid Build Coastguard Worker static char *cmdline_includepath[INCLUDE_PATH_MAX];
23*49cdfc7eSAndroid Build Coastguard Worker static unsigned int cmdline_includepaths;
24*49cdfc7eSAndroid Build Coastguard Worker static char *includepath;
25*49cdfc7eSAndroid Build Coastguard Worker 
26*49cdfc7eSAndroid Build Coastguard Worker #define WARN(str) fprintf(stderr, "WARNING: " str "\n")
27*49cdfc7eSAndroid Build Coastguard Worker 
oneline_comment(FILE * f)28*49cdfc7eSAndroid Build Coastguard Worker static void oneline_comment(FILE *f)
29*49cdfc7eSAndroid Build Coastguard Worker {
30*49cdfc7eSAndroid Build Coastguard Worker 	int c;
31*49cdfc7eSAndroid Build Coastguard Worker 
32*49cdfc7eSAndroid Build Coastguard Worker 	do {
33*49cdfc7eSAndroid Build Coastguard Worker 		c = getc(f);
34*49cdfc7eSAndroid Build Coastguard Worker 	} while (c != '\n');
35*49cdfc7eSAndroid Build Coastguard Worker }
36*49cdfc7eSAndroid Build Coastguard Worker 
eat_asterisk_space(const char * c)37*49cdfc7eSAndroid Build Coastguard Worker static const char *eat_asterisk_space(const char *c)
38*49cdfc7eSAndroid Build Coastguard Worker {
39*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i = 0;
40*49cdfc7eSAndroid Build Coastguard Worker 
41*49cdfc7eSAndroid Build Coastguard Worker 	while (isspace(c[i]))
42*49cdfc7eSAndroid Build Coastguard Worker 		i++;
43*49cdfc7eSAndroid Build Coastguard Worker 
44*49cdfc7eSAndroid Build Coastguard Worker 	if (c[i] == '*') {
45*49cdfc7eSAndroid Build Coastguard Worker 		if (isspace(c[i+1]))
46*49cdfc7eSAndroid Build Coastguard Worker 			i++;
47*49cdfc7eSAndroid Build Coastguard Worker 		return &c[i+1];
48*49cdfc7eSAndroid Build Coastguard Worker 	}
49*49cdfc7eSAndroid Build Coastguard Worker 
50*49cdfc7eSAndroid Build Coastguard Worker 	return c;
51*49cdfc7eSAndroid Build Coastguard Worker }
52*49cdfc7eSAndroid Build Coastguard Worker 
multiline_comment(FILE * f,struct data_node * doc)53*49cdfc7eSAndroid Build Coastguard Worker static void multiline_comment(FILE *f, struct data_node *doc)
54*49cdfc7eSAndroid Build Coastguard Worker {
55*49cdfc7eSAndroid Build Coastguard Worker 	int c;
56*49cdfc7eSAndroid Build Coastguard Worker 	int state = 0;
57*49cdfc7eSAndroid Build Coastguard Worker 	char buf[4096];
58*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int bufp = 0;
59*49cdfc7eSAndroid Build Coastguard Worker 
60*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
61*49cdfc7eSAndroid Build Coastguard Worker 		c = getc(f);
62*49cdfc7eSAndroid Build Coastguard Worker 
63*49cdfc7eSAndroid Build Coastguard Worker 		if (doc) {
64*49cdfc7eSAndroid Build Coastguard Worker 			if (c == '\n') {
65*49cdfc7eSAndroid Build Coastguard Worker 				struct data_node *line;
66*49cdfc7eSAndroid Build Coastguard Worker 				buf[bufp] = 0;
67*49cdfc7eSAndroid Build Coastguard Worker 				line = data_node_string(eat_asterisk_space(buf));
68*49cdfc7eSAndroid Build Coastguard Worker 				if (data_node_array_add(doc, line))
69*49cdfc7eSAndroid Build Coastguard Worker 					WARN("doc string comment truncated");
70*49cdfc7eSAndroid Build Coastguard Worker 				bufp = 0;
71*49cdfc7eSAndroid Build Coastguard Worker 				continue;
72*49cdfc7eSAndroid Build Coastguard Worker 			}
73*49cdfc7eSAndroid Build Coastguard Worker 
74*49cdfc7eSAndroid Build Coastguard Worker 			if (bufp + 1 >= sizeof(buf))
75*49cdfc7eSAndroid Build Coastguard Worker 				continue;
76*49cdfc7eSAndroid Build Coastguard Worker 
77*49cdfc7eSAndroid Build Coastguard Worker 			buf[bufp++] = c;
78*49cdfc7eSAndroid Build Coastguard Worker 		}
79*49cdfc7eSAndroid Build Coastguard Worker 
80*49cdfc7eSAndroid Build Coastguard Worker 		switch (state) {
81*49cdfc7eSAndroid Build Coastguard Worker 		case 0:
82*49cdfc7eSAndroid Build Coastguard Worker 			if (c == '*')
83*49cdfc7eSAndroid Build Coastguard Worker 				state = 1;
84*49cdfc7eSAndroid Build Coastguard Worker 		break;
85*49cdfc7eSAndroid Build Coastguard Worker 		case 1:
86*49cdfc7eSAndroid Build Coastguard Worker 			switch (c) {
87*49cdfc7eSAndroid Build Coastguard Worker 			case '/':
88*49cdfc7eSAndroid Build Coastguard Worker 				return;
89*49cdfc7eSAndroid Build Coastguard Worker 			case '*':
90*49cdfc7eSAndroid Build Coastguard Worker 				continue;
91*49cdfc7eSAndroid Build Coastguard Worker 			default:
92*49cdfc7eSAndroid Build Coastguard Worker 				state = 0;
93*49cdfc7eSAndroid Build Coastguard Worker 			break;
94*49cdfc7eSAndroid Build Coastguard Worker 			}
95*49cdfc7eSAndroid Build Coastguard Worker 		break;
96*49cdfc7eSAndroid Build Coastguard Worker 		}
97*49cdfc7eSAndroid Build Coastguard Worker 	}
98*49cdfc7eSAndroid Build Coastguard Worker 
99*49cdfc7eSAndroid Build Coastguard Worker }
100*49cdfc7eSAndroid Build Coastguard Worker 
101*49cdfc7eSAndroid Build Coastguard Worker static const char doc_prefix[] = "\\\n";
102*49cdfc7eSAndroid Build Coastguard Worker 
maybe_doc_comment(FILE * f,struct data_node * doc)103*49cdfc7eSAndroid Build Coastguard Worker static void maybe_doc_comment(FILE *f, struct data_node *doc)
104*49cdfc7eSAndroid Build Coastguard Worker {
105*49cdfc7eSAndroid Build Coastguard Worker 	int c, i;
106*49cdfc7eSAndroid Build Coastguard Worker 
107*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; doc_prefix[i]; i++) {
108*49cdfc7eSAndroid Build Coastguard Worker 		c = getc(f);
109*49cdfc7eSAndroid Build Coastguard Worker 
110*49cdfc7eSAndroid Build Coastguard Worker 		if (c == doc_prefix[i])
111*49cdfc7eSAndroid Build Coastguard Worker 			continue;
112*49cdfc7eSAndroid Build Coastguard Worker 
113*49cdfc7eSAndroid Build Coastguard Worker 		if (c == '*')
114*49cdfc7eSAndroid Build Coastguard Worker 			ungetc(c, f);
115*49cdfc7eSAndroid Build Coastguard Worker 
116*49cdfc7eSAndroid Build Coastguard Worker 		multiline_comment(f, NULL);
117*49cdfc7eSAndroid Build Coastguard Worker 		return;
118*49cdfc7eSAndroid Build Coastguard Worker 	}
119*49cdfc7eSAndroid Build Coastguard Worker 
120*49cdfc7eSAndroid Build Coastguard Worker 	multiline_comment(f, doc);
121*49cdfc7eSAndroid Build Coastguard Worker }
122*49cdfc7eSAndroid Build Coastguard Worker 
maybe_comment(FILE * f,struct data_node * doc)123*49cdfc7eSAndroid Build Coastguard Worker static void maybe_comment(FILE *f, struct data_node *doc)
124*49cdfc7eSAndroid Build Coastguard Worker {
125*49cdfc7eSAndroid Build Coastguard Worker 	int c = getc(f);
126*49cdfc7eSAndroid Build Coastguard Worker 
127*49cdfc7eSAndroid Build Coastguard Worker 	switch (c) {
128*49cdfc7eSAndroid Build Coastguard Worker 	case '/':
129*49cdfc7eSAndroid Build Coastguard Worker 		oneline_comment(f);
130*49cdfc7eSAndroid Build Coastguard Worker 	break;
131*49cdfc7eSAndroid Build Coastguard Worker 	case '*':
132*49cdfc7eSAndroid Build Coastguard Worker 		maybe_doc_comment(f, doc);
133*49cdfc7eSAndroid Build Coastguard Worker 	break;
134*49cdfc7eSAndroid Build Coastguard Worker 	default:
135*49cdfc7eSAndroid Build Coastguard Worker 		ungetc(c, f);
136*49cdfc7eSAndroid Build Coastguard Worker 	break;
137*49cdfc7eSAndroid Build Coastguard Worker 	}
138*49cdfc7eSAndroid Build Coastguard Worker }
139*49cdfc7eSAndroid Build Coastguard Worker 
next_token2(FILE * f,char * buf,size_t buf_len,struct data_node * doc)140*49cdfc7eSAndroid Build Coastguard Worker static char *next_token2(FILE *f, char *buf, size_t buf_len, struct data_node *doc)
141*49cdfc7eSAndroid Build Coastguard Worker {
142*49cdfc7eSAndroid Build Coastguard Worker 	size_t i = 0;
143*49cdfc7eSAndroid Build Coastguard Worker 	int c;
144*49cdfc7eSAndroid Build Coastguard Worker 	int in_str = 0;
145*49cdfc7eSAndroid Build Coastguard Worker 
146*49cdfc7eSAndroid Build Coastguard Worker 	buf_len--;
147*49cdfc7eSAndroid Build Coastguard Worker 
148*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
149*49cdfc7eSAndroid Build Coastguard Worker 		c = fgetc(f);
150*49cdfc7eSAndroid Build Coastguard Worker 
151*49cdfc7eSAndroid Build Coastguard Worker 		if (c == EOF)
152*49cdfc7eSAndroid Build Coastguard Worker 			goto exit;
153*49cdfc7eSAndroid Build Coastguard Worker 
154*49cdfc7eSAndroid Build Coastguard Worker 		if (in_str) {
155*49cdfc7eSAndroid Build Coastguard Worker 			if (c == '"') {
156*49cdfc7eSAndroid Build Coastguard Worker 				if (i == 0 || buf[i-1] != '\\')
157*49cdfc7eSAndroid Build Coastguard Worker 					goto exit;
158*49cdfc7eSAndroid Build Coastguard Worker 			}
159*49cdfc7eSAndroid Build Coastguard Worker 
160*49cdfc7eSAndroid Build Coastguard Worker 			if (i < buf_len)
161*49cdfc7eSAndroid Build Coastguard Worker 				buf[i++] = c;
162*49cdfc7eSAndroid Build Coastguard Worker 			continue;
163*49cdfc7eSAndroid Build Coastguard Worker 		}
164*49cdfc7eSAndroid Build Coastguard Worker 
165*49cdfc7eSAndroid Build Coastguard Worker 		switch (c) {
166*49cdfc7eSAndroid Build Coastguard Worker 		case '{':
167*49cdfc7eSAndroid Build Coastguard Worker 		case '}':
168*49cdfc7eSAndroid Build Coastguard Worker 		case ';':
169*49cdfc7eSAndroid Build Coastguard Worker 		case '(':
170*49cdfc7eSAndroid Build Coastguard Worker 		case ')':
171*49cdfc7eSAndroid Build Coastguard Worker 		case '=':
172*49cdfc7eSAndroid Build Coastguard Worker 		case ',':
173*49cdfc7eSAndroid Build Coastguard Worker 		case '[':
174*49cdfc7eSAndroid Build Coastguard Worker 		case ']':
175*49cdfc7eSAndroid Build Coastguard Worker 		case '#':
176*49cdfc7eSAndroid Build Coastguard Worker 			if (i) {
177*49cdfc7eSAndroid Build Coastguard Worker 				ungetc(c, f);
178*49cdfc7eSAndroid Build Coastguard Worker 				goto exit;
179*49cdfc7eSAndroid Build Coastguard Worker 			}
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker 			if (i < buf_len)
182*49cdfc7eSAndroid Build Coastguard Worker 				buf[i++] = c;
183*49cdfc7eSAndroid Build Coastguard Worker 			goto exit;
184*49cdfc7eSAndroid Build Coastguard Worker 		case '0' ... '9':
185*49cdfc7eSAndroid Build Coastguard Worker 		case 'a' ... 'z':
186*49cdfc7eSAndroid Build Coastguard Worker 		case 'A' ... 'Z':
187*49cdfc7eSAndroid Build Coastguard Worker 		case '.':
188*49cdfc7eSAndroid Build Coastguard Worker 		case '_':
189*49cdfc7eSAndroid Build Coastguard Worker 		case '-':
190*49cdfc7eSAndroid Build Coastguard Worker 			buf[i++] = c;
191*49cdfc7eSAndroid Build Coastguard Worker 		break;
192*49cdfc7eSAndroid Build Coastguard Worker 		case '/':
193*49cdfc7eSAndroid Build Coastguard Worker 			maybe_comment(f, doc);
194*49cdfc7eSAndroid Build Coastguard Worker 		break;
195*49cdfc7eSAndroid Build Coastguard Worker 		case '"':
196*49cdfc7eSAndroid Build Coastguard Worker 			in_str = 1;
197*49cdfc7eSAndroid Build Coastguard Worker 		break;
198*49cdfc7eSAndroid Build Coastguard Worker 		case ' ':
199*49cdfc7eSAndroid Build Coastguard Worker 		case '\n':
200*49cdfc7eSAndroid Build Coastguard Worker 		case '\t':
201*49cdfc7eSAndroid Build Coastguard Worker 			if (i)
202*49cdfc7eSAndroid Build Coastguard Worker 				goto exit;
203*49cdfc7eSAndroid Build Coastguard Worker 		break;
204*49cdfc7eSAndroid Build Coastguard Worker 		}
205*49cdfc7eSAndroid Build Coastguard Worker 	}
206*49cdfc7eSAndroid Build Coastguard Worker 
207*49cdfc7eSAndroid Build Coastguard Worker exit:
208*49cdfc7eSAndroid Build Coastguard Worker 	if (i == 0 && !in_str)
209*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
210*49cdfc7eSAndroid Build Coastguard Worker 
211*49cdfc7eSAndroid Build Coastguard Worker 	buf[i] = 0;
212*49cdfc7eSAndroid Build Coastguard Worker 	return buf;
213*49cdfc7eSAndroid Build Coastguard Worker }
214*49cdfc7eSAndroid Build Coastguard Worker 
next_token(FILE * f,struct data_node * doc)215*49cdfc7eSAndroid Build Coastguard Worker static char *next_token(FILE *f, struct data_node *doc)
216*49cdfc7eSAndroid Build Coastguard Worker {
217*49cdfc7eSAndroid Build Coastguard Worker 	static char buf[4096];
218*49cdfc7eSAndroid Build Coastguard Worker 
219*49cdfc7eSAndroid Build Coastguard Worker 	return next_token2(f, buf, sizeof(buf), doc);
220*49cdfc7eSAndroid Build Coastguard Worker }
221*49cdfc7eSAndroid Build Coastguard Worker 
open_file(const char * dir,const char * fname)222*49cdfc7eSAndroid Build Coastguard Worker static FILE *open_file(const char *dir, const char *fname)
223*49cdfc7eSAndroid Build Coastguard Worker {
224*49cdfc7eSAndroid Build Coastguard Worker 	FILE *f;
225*49cdfc7eSAndroid Build Coastguard Worker 	char *path;
226*49cdfc7eSAndroid Build Coastguard Worker 
227*49cdfc7eSAndroid Build Coastguard Worker 	if (asprintf(&path, "%s/%s", dir, fname) < 0)
228*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
229*49cdfc7eSAndroid Build Coastguard Worker 
230*49cdfc7eSAndroid Build Coastguard Worker 	f = fopen(path, "r");
231*49cdfc7eSAndroid Build Coastguard Worker 
232*49cdfc7eSAndroid Build Coastguard Worker 	free(path);
233*49cdfc7eSAndroid Build Coastguard Worker 
234*49cdfc7eSAndroid Build Coastguard Worker 	return f;
235*49cdfc7eSAndroid Build Coastguard Worker }
236*49cdfc7eSAndroid Build Coastguard Worker 
open_include(FILE * f)237*49cdfc7eSAndroid Build Coastguard Worker static FILE *open_include(FILE *f)
238*49cdfc7eSAndroid Build Coastguard Worker {
239*49cdfc7eSAndroid Build Coastguard Worker 	char buf[256], *fname;
240*49cdfc7eSAndroid Build Coastguard Worker 	FILE *inc;
241*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i;
242*49cdfc7eSAndroid Build Coastguard Worker 
243*49cdfc7eSAndroid Build Coastguard Worker 	if (!fscanf(f, "%s\n", buf))
244*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
245*49cdfc7eSAndroid Build Coastguard Worker 
246*49cdfc7eSAndroid Build Coastguard Worker 	if (buf[0] != '"')
247*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
248*49cdfc7eSAndroid Build Coastguard Worker 
249*49cdfc7eSAndroid Build Coastguard Worker 	fname = buf + 1;
250*49cdfc7eSAndroid Build Coastguard Worker 
251*49cdfc7eSAndroid Build Coastguard Worker 	if (!buf[0])
252*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
253*49cdfc7eSAndroid Build Coastguard Worker 
254*49cdfc7eSAndroid Build Coastguard Worker 	fname[strlen(fname)-1] = 0;
255*49cdfc7eSAndroid Build Coastguard Worker 
256*49cdfc7eSAndroid Build Coastguard Worker 	inc = open_file(includepath, fname);
257*49cdfc7eSAndroid Build Coastguard Worker 	if (inc) {
258*49cdfc7eSAndroid Build Coastguard Worker 		if (verbose)
259*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "INCLUDE %s/%s\n", includepath, fname);
260*49cdfc7eSAndroid Build Coastguard Worker 
261*49cdfc7eSAndroid Build Coastguard Worker 		return inc;
262*49cdfc7eSAndroid Build Coastguard Worker 	}
263*49cdfc7eSAndroid Build Coastguard Worker 
264*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < cmdline_includepaths; i++) {
265*49cdfc7eSAndroid Build Coastguard Worker 		inc = open_file(cmdline_includepath[i], fname);
266*49cdfc7eSAndroid Build Coastguard Worker 
267*49cdfc7eSAndroid Build Coastguard Worker 		if (!inc)
268*49cdfc7eSAndroid Build Coastguard Worker 			continue;
269*49cdfc7eSAndroid Build Coastguard Worker 
270*49cdfc7eSAndroid Build Coastguard Worker 		if (verbose) {
271*49cdfc7eSAndroid Build Coastguard Worker 			fprintf(stderr, "INCLUDE %s/%s\n",
272*49cdfc7eSAndroid Build Coastguard Worker 				cmdline_includepath[i], fname);
273*49cdfc7eSAndroid Build Coastguard Worker 		}
274*49cdfc7eSAndroid Build Coastguard Worker 
275*49cdfc7eSAndroid Build Coastguard Worker 		return inc;
276*49cdfc7eSAndroid Build Coastguard Worker 	}
277*49cdfc7eSAndroid Build Coastguard Worker 
278*49cdfc7eSAndroid Build Coastguard Worker 	return NULL;
279*49cdfc7eSAndroid Build Coastguard Worker }
280*49cdfc7eSAndroid Build Coastguard Worker 
close_include(FILE * inc)281*49cdfc7eSAndroid Build Coastguard Worker static void close_include(FILE *inc)
282*49cdfc7eSAndroid Build Coastguard Worker {
283*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
284*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "INCLUDE END\n");
285*49cdfc7eSAndroid Build Coastguard Worker 
286*49cdfc7eSAndroid Build Coastguard Worker 	fclose(inc);
287*49cdfc7eSAndroid Build Coastguard Worker }
288*49cdfc7eSAndroid Build Coastguard Worker 
parse_array(FILE * f,struct data_node * node)289*49cdfc7eSAndroid Build Coastguard Worker static int parse_array(FILE *f, struct data_node *node)
290*49cdfc7eSAndroid Build Coastguard Worker {
291*49cdfc7eSAndroid Build Coastguard Worker 	const char *token;
292*49cdfc7eSAndroid Build Coastguard Worker 
293*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
294*49cdfc7eSAndroid Build Coastguard Worker 		if (!(token = next_token(f, NULL)))
295*49cdfc7eSAndroid Build Coastguard Worker 			return 1;
296*49cdfc7eSAndroid Build Coastguard Worker 
297*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "{")) {
298*49cdfc7eSAndroid Build Coastguard Worker 			struct data_node *ret = data_node_array();
299*49cdfc7eSAndroid Build Coastguard Worker 			parse_array(f, ret);
300*49cdfc7eSAndroid Build Coastguard Worker 
301*49cdfc7eSAndroid Build Coastguard Worker 			if (data_node_array_len(ret))
302*49cdfc7eSAndroid Build Coastguard Worker 				data_node_array_add(node, ret);
303*49cdfc7eSAndroid Build Coastguard Worker 			else
304*49cdfc7eSAndroid Build Coastguard Worker 				data_node_free(ret);
305*49cdfc7eSAndroid Build Coastguard Worker 
306*49cdfc7eSAndroid Build Coastguard Worker 			continue;
307*49cdfc7eSAndroid Build Coastguard Worker 		}
308*49cdfc7eSAndroid Build Coastguard Worker 
309*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "}"))
310*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
311*49cdfc7eSAndroid Build Coastguard Worker 
312*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, ","))
313*49cdfc7eSAndroid Build Coastguard Worker 			continue;
314*49cdfc7eSAndroid Build Coastguard Worker 
315*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "NULL"))
316*49cdfc7eSAndroid Build Coastguard Worker 			continue;
317*49cdfc7eSAndroid Build Coastguard Worker 
318*49cdfc7eSAndroid Build Coastguard Worker 		struct data_node *str = data_node_string(token);
319*49cdfc7eSAndroid Build Coastguard Worker 
320*49cdfc7eSAndroid Build Coastguard Worker 		data_node_array_add(node, str);
321*49cdfc7eSAndroid Build Coastguard Worker 	}
322*49cdfc7eSAndroid Build Coastguard Worker 
323*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
324*49cdfc7eSAndroid Build Coastguard Worker }
325*49cdfc7eSAndroid Build Coastguard Worker 
try_apply_macro(char ** res)326*49cdfc7eSAndroid Build Coastguard Worker static void try_apply_macro(char **res)
327*49cdfc7eSAndroid Build Coastguard Worker {
328*49cdfc7eSAndroid Build Coastguard Worker 	ENTRY macro = {
329*49cdfc7eSAndroid Build Coastguard Worker 		.key = *res,
330*49cdfc7eSAndroid Build Coastguard Worker 	};
331*49cdfc7eSAndroid Build Coastguard Worker 
332*49cdfc7eSAndroid Build Coastguard Worker 	ENTRY *ret;
333*49cdfc7eSAndroid Build Coastguard Worker 
334*49cdfc7eSAndroid Build Coastguard Worker 	ret = hsearch(macro, FIND);
335*49cdfc7eSAndroid Build Coastguard Worker 
336*49cdfc7eSAndroid Build Coastguard Worker 	if (!ret)
337*49cdfc7eSAndroid Build Coastguard Worker 		return;
338*49cdfc7eSAndroid Build Coastguard Worker 
339*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
340*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "APPLYING MACRO %s=%s\n", ret->key, (char*)ret->data);
341*49cdfc7eSAndroid Build Coastguard Worker 
342*49cdfc7eSAndroid Build Coastguard Worker 	*res = ret->data;
343*49cdfc7eSAndroid Build Coastguard Worker }
344*49cdfc7eSAndroid Build Coastguard Worker 
parse_get_array_len(FILE * f)345*49cdfc7eSAndroid Build Coastguard Worker static int parse_get_array_len(FILE *f)
346*49cdfc7eSAndroid Build Coastguard Worker {
347*49cdfc7eSAndroid Build Coastguard Worker 	const char *token;
348*49cdfc7eSAndroid Build Coastguard Worker 	int cnt = 0, depth = 0, prev_comma = 0;
349*49cdfc7eSAndroid Build Coastguard Worker 
350*49cdfc7eSAndroid Build Coastguard Worker 	if (!(token = next_token(f, NULL)))
351*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
352*49cdfc7eSAndroid Build Coastguard Worker 
353*49cdfc7eSAndroid Build Coastguard Worker 	if (strcmp(token, "{"))
354*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
355*49cdfc7eSAndroid Build Coastguard Worker 
356*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
357*49cdfc7eSAndroid Build Coastguard Worker 		if (!(token = next_token(f, NULL)))
358*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
359*49cdfc7eSAndroid Build Coastguard Worker 
360*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "{"))
361*49cdfc7eSAndroid Build Coastguard Worker 			depth++;
362*49cdfc7eSAndroid Build Coastguard Worker 
363*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "}"))
364*49cdfc7eSAndroid Build Coastguard Worker 			depth--;
365*49cdfc7eSAndroid Build Coastguard Worker 		else
366*49cdfc7eSAndroid Build Coastguard Worker 			prev_comma = 0;
367*49cdfc7eSAndroid Build Coastguard Worker 
368*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, ",") && !depth) {
369*49cdfc7eSAndroid Build Coastguard Worker 			prev_comma = 1;
370*49cdfc7eSAndroid Build Coastguard Worker 			cnt++;
371*49cdfc7eSAndroid Build Coastguard Worker 		}
372*49cdfc7eSAndroid Build Coastguard Worker 
373*49cdfc7eSAndroid Build Coastguard Worker 		if (depth < 0)
374*49cdfc7eSAndroid Build Coastguard Worker 			return cnt + !prev_comma;
375*49cdfc7eSAndroid Build Coastguard Worker 	}
376*49cdfc7eSAndroid Build Coastguard Worker }
377*49cdfc7eSAndroid Build Coastguard Worker 
look_for_array_size(FILE * f,const char * arr_id,struct data_node ** res)378*49cdfc7eSAndroid Build Coastguard Worker static void look_for_array_size(FILE *f, const char *arr_id, struct data_node **res)
379*49cdfc7eSAndroid Build Coastguard Worker {
380*49cdfc7eSAndroid Build Coastguard Worker 	const char *token;
381*49cdfc7eSAndroid Build Coastguard Worker 	char buf[2][2048] = {};
382*49cdfc7eSAndroid Build Coastguard Worker 	int cur_buf = 0;
383*49cdfc7eSAndroid Build Coastguard Worker 	int prev_buf = 1;
384*49cdfc7eSAndroid Build Coastguard Worker 
385*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
386*49cdfc7eSAndroid Build Coastguard Worker 		if (!(token = next_token2(f, buf[cur_buf], sizeof(buf[cur_buf]), NULL)))
387*49cdfc7eSAndroid Build Coastguard Worker 			break;
388*49cdfc7eSAndroid Build Coastguard Worker 
389*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "=") && !strcmp(buf[prev_buf], arr_id)) {
390*49cdfc7eSAndroid Build Coastguard Worker 			int arr_len = parse_get_array_len(f);
391*49cdfc7eSAndroid Build Coastguard Worker 
392*49cdfc7eSAndroid Build Coastguard Worker 			if (verbose)
393*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "ARRAY %s LENGTH = %i\n", arr_id, arr_len);
394*49cdfc7eSAndroid Build Coastguard Worker 
395*49cdfc7eSAndroid Build Coastguard Worker 			*res = data_node_int(arr_len);
396*49cdfc7eSAndroid Build Coastguard Worker 
397*49cdfc7eSAndroid Build Coastguard Worker 			break;
398*49cdfc7eSAndroid Build Coastguard Worker 		}
399*49cdfc7eSAndroid Build Coastguard Worker 
400*49cdfc7eSAndroid Build Coastguard Worker 		if (strcmp(buf[cur_buf], "]") && strcmp(buf[cur_buf], "[")) {
401*49cdfc7eSAndroid Build Coastguard Worker 			cur_buf = !cur_buf;
402*49cdfc7eSAndroid Build Coastguard Worker 			prev_buf = !prev_buf;
403*49cdfc7eSAndroid Build Coastguard Worker 		}
404*49cdfc7eSAndroid Build Coastguard Worker 	}
405*49cdfc7eSAndroid Build Coastguard Worker }
406*49cdfc7eSAndroid Build Coastguard Worker 
parse_array_size(FILE * f,struct data_node ** res)407*49cdfc7eSAndroid Build Coastguard Worker static int parse_array_size(FILE *f, struct data_node **res)
408*49cdfc7eSAndroid Build Coastguard Worker {
409*49cdfc7eSAndroid Build Coastguard Worker 	const char *token;
410*49cdfc7eSAndroid Build Coastguard Worker 	char *arr_id;
411*49cdfc7eSAndroid Build Coastguard Worker 	long pos;
412*49cdfc7eSAndroid Build Coastguard Worker 	int hash = 0;
413*49cdfc7eSAndroid Build Coastguard Worker 
414*49cdfc7eSAndroid Build Coastguard Worker 	*res = NULL;
415*49cdfc7eSAndroid Build Coastguard Worker 
416*49cdfc7eSAndroid Build Coastguard Worker 	if (!(token = next_token(f, NULL)))
417*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
418*49cdfc7eSAndroid Build Coastguard Worker 
419*49cdfc7eSAndroid Build Coastguard Worker 	if (strcmp(token, "("))
420*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
421*49cdfc7eSAndroid Build Coastguard Worker 
422*49cdfc7eSAndroid Build Coastguard Worker 	if (!(token = next_token(f, NULL)))
423*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
424*49cdfc7eSAndroid Build Coastguard Worker 
425*49cdfc7eSAndroid Build Coastguard Worker 	arr_id = strdup(token);
426*49cdfc7eSAndroid Build Coastguard Worker 
427*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
428*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "COMPUTING ARRAY '%s' LENGHT\n", arr_id);
429*49cdfc7eSAndroid Build Coastguard Worker 
430*49cdfc7eSAndroid Build Coastguard Worker 	pos = ftell(f);
431*49cdfc7eSAndroid Build Coastguard Worker 
432*49cdfc7eSAndroid Build Coastguard Worker 	rewind(f);
433*49cdfc7eSAndroid Build Coastguard Worker 
434*49cdfc7eSAndroid Build Coastguard Worker 	look_for_array_size(f, arr_id, res);
435*49cdfc7eSAndroid Build Coastguard Worker 
436*49cdfc7eSAndroid Build Coastguard Worker 	if (!*res) {
437*49cdfc7eSAndroid Build Coastguard Worker 		FILE *inc;
438*49cdfc7eSAndroid Build Coastguard Worker 
439*49cdfc7eSAndroid Build Coastguard Worker 		rewind(f);
440*49cdfc7eSAndroid Build Coastguard Worker 
441*49cdfc7eSAndroid Build Coastguard Worker 		for (;;) {
442*49cdfc7eSAndroid Build Coastguard Worker 			if (!(token = next_token(f, NULL)))
443*49cdfc7eSAndroid Build Coastguard Worker 				break;
444*49cdfc7eSAndroid Build Coastguard Worker 
445*49cdfc7eSAndroid Build Coastguard Worker 			if (token[0] == '#') {
446*49cdfc7eSAndroid Build Coastguard Worker 				hash = 1;
447*49cdfc7eSAndroid Build Coastguard Worker 				continue;
448*49cdfc7eSAndroid Build Coastguard Worker 			}
449*49cdfc7eSAndroid Build Coastguard Worker 
450*49cdfc7eSAndroid Build Coastguard Worker 			if (!hash)
451*49cdfc7eSAndroid Build Coastguard Worker 				continue;
452*49cdfc7eSAndroid Build Coastguard Worker 
453*49cdfc7eSAndroid Build Coastguard Worker 			if (!strcmp(token, "include")) {
454*49cdfc7eSAndroid Build Coastguard Worker 				inc = open_include(f);
455*49cdfc7eSAndroid Build Coastguard Worker 
456*49cdfc7eSAndroid Build Coastguard Worker 				if (inc) {
457*49cdfc7eSAndroid Build Coastguard Worker 					look_for_array_size(inc, arr_id, res);
458*49cdfc7eSAndroid Build Coastguard Worker 					close_include(inc);
459*49cdfc7eSAndroid Build Coastguard Worker 				}
460*49cdfc7eSAndroid Build Coastguard Worker 			}
461*49cdfc7eSAndroid Build Coastguard Worker 
462*49cdfc7eSAndroid Build Coastguard Worker 			if (*res)
463*49cdfc7eSAndroid Build Coastguard Worker 				break;
464*49cdfc7eSAndroid Build Coastguard Worker 		}
465*49cdfc7eSAndroid Build Coastguard Worker 	}
466*49cdfc7eSAndroid Build Coastguard Worker 
467*49cdfc7eSAndroid Build Coastguard Worker 	free(arr_id);
468*49cdfc7eSAndroid Build Coastguard Worker 
469*49cdfc7eSAndroid Build Coastguard Worker 	if (fseek(f, pos, SEEK_SET))
470*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
471*49cdfc7eSAndroid Build Coastguard Worker 
472*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
473*49cdfc7eSAndroid Build Coastguard Worker }
474*49cdfc7eSAndroid Build Coastguard Worker 
parse_test_struct(FILE * f,struct data_node * doc,struct data_node * node)475*49cdfc7eSAndroid Build Coastguard Worker static int parse_test_struct(FILE *f, struct data_node *doc, struct data_node *node)
476*49cdfc7eSAndroid Build Coastguard Worker {
477*49cdfc7eSAndroid Build Coastguard Worker 	char *token;
478*49cdfc7eSAndroid Build Coastguard Worker 	char *id = NULL;
479*49cdfc7eSAndroid Build Coastguard Worker 	int state = 0;
480*49cdfc7eSAndroid Build Coastguard Worker 	struct data_node *ret;
481*49cdfc7eSAndroid Build Coastguard Worker 
482*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
483*49cdfc7eSAndroid Build Coastguard Worker 		if (!(token = next_token(f, doc)))
484*49cdfc7eSAndroid Build Coastguard Worker 			return 1;
485*49cdfc7eSAndroid Build Coastguard Worker 
486*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "}"))
487*49cdfc7eSAndroid Build Coastguard Worker 			return 0;
488*49cdfc7eSAndroid Build Coastguard Worker 
489*49cdfc7eSAndroid Build Coastguard Worker 		switch (state) {
490*49cdfc7eSAndroid Build Coastguard Worker 		case 0:
491*49cdfc7eSAndroid Build Coastguard Worker 			id = strdup(token);
492*49cdfc7eSAndroid Build Coastguard Worker 			state = 1;
493*49cdfc7eSAndroid Build Coastguard Worker 			continue;
494*49cdfc7eSAndroid Build Coastguard Worker 		case 1:
495*49cdfc7eSAndroid Build Coastguard Worker 			if (!strcmp(token, "="))
496*49cdfc7eSAndroid Build Coastguard Worker 				state = 2;
497*49cdfc7eSAndroid Build Coastguard Worker 			else
498*49cdfc7eSAndroid Build Coastguard Worker 				WARN("Expected '='");
499*49cdfc7eSAndroid Build Coastguard Worker 			continue;
500*49cdfc7eSAndroid Build Coastguard Worker 		case 2:
501*49cdfc7eSAndroid Build Coastguard Worker 			if (!strcmp(token, "(")) {
502*49cdfc7eSAndroid Build Coastguard Worker 				state = 3;
503*49cdfc7eSAndroid Build Coastguard Worker 				continue;
504*49cdfc7eSAndroid Build Coastguard Worker 			}
505*49cdfc7eSAndroid Build Coastguard Worker 		break;
506*49cdfc7eSAndroid Build Coastguard Worker 		case 3:
507*49cdfc7eSAndroid Build Coastguard Worker 			if (!strcmp(token, ")"))
508*49cdfc7eSAndroid Build Coastguard Worker 				state = 2;
509*49cdfc7eSAndroid Build Coastguard Worker 			continue;
510*49cdfc7eSAndroid Build Coastguard Worker 
511*49cdfc7eSAndroid Build Coastguard Worker 		case 4:
512*49cdfc7eSAndroid Build Coastguard Worker 			if (!strcmp(token, ","))
513*49cdfc7eSAndroid Build Coastguard Worker 				state = 0;
514*49cdfc7eSAndroid Build Coastguard Worker 			continue;
515*49cdfc7eSAndroid Build Coastguard Worker 		}
516*49cdfc7eSAndroid Build Coastguard Worker 
517*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "{")) {
518*49cdfc7eSAndroid Build Coastguard Worker 			ret = data_node_array();
519*49cdfc7eSAndroid Build Coastguard Worker 			parse_array(f, ret);
520*49cdfc7eSAndroid Build Coastguard Worker 		} else if (!strcmp(token, "ARRAY_SIZE")) {
521*49cdfc7eSAndroid Build Coastguard Worker 			if (parse_array_size(f, &ret))
522*49cdfc7eSAndroid Build Coastguard Worker 				return 1;
523*49cdfc7eSAndroid Build Coastguard Worker 		} else {
524*49cdfc7eSAndroid Build Coastguard Worker 			try_apply_macro(&token);
525*49cdfc7eSAndroid Build Coastguard Worker 			ret = data_node_string(token);
526*49cdfc7eSAndroid Build Coastguard Worker 		}
527*49cdfc7eSAndroid Build Coastguard Worker 
528*49cdfc7eSAndroid Build Coastguard Worker 		if (!ret)
529*49cdfc7eSAndroid Build Coastguard Worker 			continue;
530*49cdfc7eSAndroid Build Coastguard Worker 
531*49cdfc7eSAndroid Build Coastguard Worker 		const char *key = id;
532*49cdfc7eSAndroid Build Coastguard Worker 		if (key[0] == '.')
533*49cdfc7eSAndroid Build Coastguard Worker 			key++;
534*49cdfc7eSAndroid Build Coastguard Worker 
535*49cdfc7eSAndroid Build Coastguard Worker 		data_node_hash_add(node, key, ret);
536*49cdfc7eSAndroid Build Coastguard Worker 		free(id);
537*49cdfc7eSAndroid Build Coastguard Worker 		state = 4;
538*49cdfc7eSAndroid Build Coastguard Worker 	}
539*49cdfc7eSAndroid Build Coastguard Worker }
540*49cdfc7eSAndroid Build Coastguard Worker 
541*49cdfc7eSAndroid Build Coastguard Worker static const char *tokens[] = {
542*49cdfc7eSAndroid Build Coastguard Worker 	"static",
543*49cdfc7eSAndroid Build Coastguard Worker 	"struct",
544*49cdfc7eSAndroid Build Coastguard Worker 	"tst_test",
545*49cdfc7eSAndroid Build Coastguard Worker 	"test",
546*49cdfc7eSAndroid Build Coastguard Worker 	"=",
547*49cdfc7eSAndroid Build Coastguard Worker 	"{",
548*49cdfc7eSAndroid Build Coastguard Worker };
549*49cdfc7eSAndroid Build Coastguard Worker 
macro_get_string(FILE * f,char * buf,char * buf_end)550*49cdfc7eSAndroid Build Coastguard Worker static void macro_get_string(FILE *f, char *buf, char *buf_end)
551*49cdfc7eSAndroid Build Coastguard Worker {
552*49cdfc7eSAndroid Build Coastguard Worker 	int c;
553*49cdfc7eSAndroid Build Coastguard Worker 	char *buf_start = buf;
554*49cdfc7eSAndroid Build Coastguard Worker 
555*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
556*49cdfc7eSAndroid Build Coastguard Worker 		c = fgetc(f);
557*49cdfc7eSAndroid Build Coastguard Worker 
558*49cdfc7eSAndroid Build Coastguard Worker 		switch (c) {
559*49cdfc7eSAndroid Build Coastguard Worker 		case EOF:
560*49cdfc7eSAndroid Build Coastguard Worker 			*buf = 0;
561*49cdfc7eSAndroid Build Coastguard Worker 			return;
562*49cdfc7eSAndroid Build Coastguard Worker 		case '"':
563*49cdfc7eSAndroid Build Coastguard Worker 			if (buf == buf_start || buf[-1] != '\\') {
564*49cdfc7eSAndroid Build Coastguard Worker 				*buf = 0;
565*49cdfc7eSAndroid Build Coastguard Worker 				return;
566*49cdfc7eSAndroid Build Coastguard Worker 			}
567*49cdfc7eSAndroid Build Coastguard Worker 			buf[-1] = '"';
568*49cdfc7eSAndroid Build Coastguard Worker 		break;
569*49cdfc7eSAndroid Build Coastguard Worker 		default:
570*49cdfc7eSAndroid Build Coastguard Worker 			if (buf < buf_end)
571*49cdfc7eSAndroid Build Coastguard Worker 				*(buf++) = c;
572*49cdfc7eSAndroid Build Coastguard Worker 		}
573*49cdfc7eSAndroid Build Coastguard Worker 	}
574*49cdfc7eSAndroid Build Coastguard Worker }
575*49cdfc7eSAndroid Build Coastguard Worker 
macro_get_val(FILE * f,char * buf,size_t buf_len)576*49cdfc7eSAndroid Build Coastguard Worker static void macro_get_val(FILE *f, char *buf, size_t buf_len)
577*49cdfc7eSAndroid Build Coastguard Worker {
578*49cdfc7eSAndroid Build Coastguard Worker 	int c, prev = 0;
579*49cdfc7eSAndroid Build Coastguard Worker 	char *buf_end = buf + buf_len - 1;
580*49cdfc7eSAndroid Build Coastguard Worker 
581*49cdfc7eSAndroid Build Coastguard Worker 	while (isspace(c = fgetc(f)));
582*49cdfc7eSAndroid Build Coastguard Worker 
583*49cdfc7eSAndroid Build Coastguard Worker 	if (c == '"') {
584*49cdfc7eSAndroid Build Coastguard Worker 		macro_get_string(f, buf, buf_end);
585*49cdfc7eSAndroid Build Coastguard Worker 		return;
586*49cdfc7eSAndroid Build Coastguard Worker 	}
587*49cdfc7eSAndroid Build Coastguard Worker 
588*49cdfc7eSAndroid Build Coastguard Worker 	for (;;) {
589*49cdfc7eSAndroid Build Coastguard Worker 		switch (c) {
590*49cdfc7eSAndroid Build Coastguard Worker 		case '\n':
591*49cdfc7eSAndroid Build Coastguard Worker 			if (prev == '\\') {
592*49cdfc7eSAndroid Build Coastguard Worker 				buf--;
593*49cdfc7eSAndroid Build Coastguard Worker 			} else {
594*49cdfc7eSAndroid Build Coastguard Worker 				*buf = 0;
595*49cdfc7eSAndroid Build Coastguard Worker 				return;
596*49cdfc7eSAndroid Build Coastguard Worker 			}
597*49cdfc7eSAndroid Build Coastguard Worker 		break;
598*49cdfc7eSAndroid Build Coastguard Worker 		case EOF:
599*49cdfc7eSAndroid Build Coastguard Worker 			*buf = 0;
600*49cdfc7eSAndroid Build Coastguard Worker 			return;
601*49cdfc7eSAndroid Build Coastguard Worker 		case ' ':
602*49cdfc7eSAndroid Build Coastguard Worker 		case '\t':
603*49cdfc7eSAndroid Build Coastguard Worker 		break;
604*49cdfc7eSAndroid Build Coastguard Worker 		default:
605*49cdfc7eSAndroid Build Coastguard Worker 			if (buf < buf_end)
606*49cdfc7eSAndroid Build Coastguard Worker 				*(buf++) = c;
607*49cdfc7eSAndroid Build Coastguard Worker 		}
608*49cdfc7eSAndroid Build Coastguard Worker 
609*49cdfc7eSAndroid Build Coastguard Worker 		prev = c;
610*49cdfc7eSAndroid Build Coastguard Worker 		c = fgetc(f);
611*49cdfc7eSAndroid Build Coastguard Worker 	}
612*49cdfc7eSAndroid Build Coastguard Worker }
613*49cdfc7eSAndroid Build Coastguard Worker 
parse_macro(FILE * f)614*49cdfc7eSAndroid Build Coastguard Worker static void parse_macro(FILE *f)
615*49cdfc7eSAndroid Build Coastguard Worker {
616*49cdfc7eSAndroid Build Coastguard Worker 	char name[128];
617*49cdfc7eSAndroid Build Coastguard Worker 	char val[256];
618*49cdfc7eSAndroid Build Coastguard Worker 
619*49cdfc7eSAndroid Build Coastguard Worker 	if (!fscanf(f, "%s[^\n]", name))
620*49cdfc7eSAndroid Build Coastguard Worker 		return;
621*49cdfc7eSAndroid Build Coastguard Worker 
622*49cdfc7eSAndroid Build Coastguard Worker 	if (fgetc(f) == '\n')
623*49cdfc7eSAndroid Build Coastguard Worker 		return;
624*49cdfc7eSAndroid Build Coastguard Worker 
625*49cdfc7eSAndroid Build Coastguard Worker 	macro_get_val(f, val, sizeof(val));
626*49cdfc7eSAndroid Build Coastguard Worker 
627*49cdfc7eSAndroid Build Coastguard Worker 	if (name[0] == '_')
628*49cdfc7eSAndroid Build Coastguard Worker 		return;
629*49cdfc7eSAndroid Build Coastguard Worker 
630*49cdfc7eSAndroid Build Coastguard Worker 	ENTRY e = {
631*49cdfc7eSAndroid Build Coastguard Worker 		.key = strdup(name),
632*49cdfc7eSAndroid Build Coastguard Worker 		.data = strdup(val),
633*49cdfc7eSAndroid Build Coastguard Worker 	};
634*49cdfc7eSAndroid Build Coastguard Worker 
635*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
636*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, " MACRO %s=%s\n", e.key, (char*)e.data);
637*49cdfc7eSAndroid Build Coastguard Worker 
638*49cdfc7eSAndroid Build Coastguard Worker 	hsearch(e, ENTER);
639*49cdfc7eSAndroid Build Coastguard Worker }
640*49cdfc7eSAndroid Build Coastguard Worker 
parse_include_macros(FILE * f)641*49cdfc7eSAndroid Build Coastguard Worker static void parse_include_macros(FILE *f)
642*49cdfc7eSAndroid Build Coastguard Worker {
643*49cdfc7eSAndroid Build Coastguard Worker 	FILE *inc;
644*49cdfc7eSAndroid Build Coastguard Worker 	const char *token;
645*49cdfc7eSAndroid Build Coastguard Worker 	int hash = 0;
646*49cdfc7eSAndroid Build Coastguard Worker 
647*49cdfc7eSAndroid Build Coastguard Worker 	inc = open_include(f);
648*49cdfc7eSAndroid Build Coastguard Worker 	if (!inc)
649*49cdfc7eSAndroid Build Coastguard Worker 		return;
650*49cdfc7eSAndroid Build Coastguard Worker 
651*49cdfc7eSAndroid Build Coastguard Worker 	while ((token = next_token(inc, NULL))) {
652*49cdfc7eSAndroid Build Coastguard Worker 		if (token[0] == '#') {
653*49cdfc7eSAndroid Build Coastguard Worker 			hash = 1;
654*49cdfc7eSAndroid Build Coastguard Worker 			continue;
655*49cdfc7eSAndroid Build Coastguard Worker 		}
656*49cdfc7eSAndroid Build Coastguard Worker 
657*49cdfc7eSAndroid Build Coastguard Worker 		if (!hash)
658*49cdfc7eSAndroid Build Coastguard Worker 			continue;
659*49cdfc7eSAndroid Build Coastguard Worker 
660*49cdfc7eSAndroid Build Coastguard Worker 		if (!strcmp(token, "define"))
661*49cdfc7eSAndroid Build Coastguard Worker 			parse_macro(inc);
662*49cdfc7eSAndroid Build Coastguard Worker 
663*49cdfc7eSAndroid Build Coastguard Worker 		hash = 0;
664*49cdfc7eSAndroid Build Coastguard Worker 	}
665*49cdfc7eSAndroid Build Coastguard Worker 
666*49cdfc7eSAndroid Build Coastguard Worker 	close_include(inc);
667*49cdfc7eSAndroid Build Coastguard Worker }
668*49cdfc7eSAndroid Build Coastguard Worker 
parse_file(const char * fname)669*49cdfc7eSAndroid Build Coastguard Worker static struct data_node *parse_file(const char *fname)
670*49cdfc7eSAndroid Build Coastguard Worker {
671*49cdfc7eSAndroid Build Coastguard Worker 	int state = 0, found = 0;
672*49cdfc7eSAndroid Build Coastguard Worker 	const char *token;
673*49cdfc7eSAndroid Build Coastguard Worker 
674*49cdfc7eSAndroid Build Coastguard Worker 	if (access(fname, F_OK)) {
675*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "file %s does not exist\n", fname);
676*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
677*49cdfc7eSAndroid Build Coastguard Worker 	}
678*49cdfc7eSAndroid Build Coastguard Worker 
679*49cdfc7eSAndroid Build Coastguard Worker 	FILE *f = fopen(fname, "r");
680*49cdfc7eSAndroid Build Coastguard Worker 
681*49cdfc7eSAndroid Build Coastguard Worker 	includepath = dirname(strdup(fname));
682*49cdfc7eSAndroid Build Coastguard Worker 
683*49cdfc7eSAndroid Build Coastguard Worker 	struct data_node *res = data_node_hash();
684*49cdfc7eSAndroid Build Coastguard Worker 	struct data_node *doc = data_node_array();
685*49cdfc7eSAndroid Build Coastguard Worker 
686*49cdfc7eSAndroid Build Coastguard Worker 	while ((token = next_token(f, doc))) {
687*49cdfc7eSAndroid Build Coastguard Worker 		if (state < 6 && !strcmp(tokens[state], token)) {
688*49cdfc7eSAndroid Build Coastguard Worker 			state++;
689*49cdfc7eSAndroid Build Coastguard Worker 		} else {
690*49cdfc7eSAndroid Build Coastguard Worker 			if (token[0] == '#') {
691*49cdfc7eSAndroid Build Coastguard Worker 				token = next_token(f, doc);
692*49cdfc7eSAndroid Build Coastguard Worker 				if (token) {
693*49cdfc7eSAndroid Build Coastguard Worker 					if (!strcmp(token, "define"))
694*49cdfc7eSAndroid Build Coastguard Worker 						parse_macro(f);
695*49cdfc7eSAndroid Build Coastguard Worker 
696*49cdfc7eSAndroid Build Coastguard Worker 					if (!strcmp(token, "include"))
697*49cdfc7eSAndroid Build Coastguard Worker 						parse_include_macros(f);
698*49cdfc7eSAndroid Build Coastguard Worker 				}
699*49cdfc7eSAndroid Build Coastguard Worker 			}
700*49cdfc7eSAndroid Build Coastguard Worker 
701*49cdfc7eSAndroid Build Coastguard Worker 			state = 0;
702*49cdfc7eSAndroid Build Coastguard Worker 		}
703*49cdfc7eSAndroid Build Coastguard Worker 
704*49cdfc7eSAndroid Build Coastguard Worker 		if (state < 6)
705*49cdfc7eSAndroid Build Coastguard Worker 			continue;
706*49cdfc7eSAndroid Build Coastguard Worker 
707*49cdfc7eSAndroid Build Coastguard Worker 		found = 1;
708*49cdfc7eSAndroid Build Coastguard Worker 		parse_test_struct(f, doc, res);
709*49cdfc7eSAndroid Build Coastguard Worker 	}
710*49cdfc7eSAndroid Build Coastguard Worker 
711*49cdfc7eSAndroid Build Coastguard Worker 	if (data_node_array_len(doc)) {
712*49cdfc7eSAndroid Build Coastguard Worker 		data_node_hash_add(res, "doc", doc);
713*49cdfc7eSAndroid Build Coastguard Worker 		found = 1;
714*49cdfc7eSAndroid Build Coastguard Worker 	} else {
715*49cdfc7eSAndroid Build Coastguard Worker 		data_node_free(doc);
716*49cdfc7eSAndroid Build Coastguard Worker 	}
717*49cdfc7eSAndroid Build Coastguard Worker 
718*49cdfc7eSAndroid Build Coastguard Worker 	fclose(f);
719*49cdfc7eSAndroid Build Coastguard Worker 
720*49cdfc7eSAndroid Build Coastguard Worker 	if (!found) {
721*49cdfc7eSAndroid Build Coastguard Worker 		data_node_free(res);
722*49cdfc7eSAndroid Build Coastguard Worker 		return NULL;
723*49cdfc7eSAndroid Build Coastguard Worker 	}
724*49cdfc7eSAndroid Build Coastguard Worker 
725*49cdfc7eSAndroid Build Coastguard Worker 	return res;
726*49cdfc7eSAndroid Build Coastguard Worker }
727*49cdfc7eSAndroid Build Coastguard Worker 
728*49cdfc7eSAndroid Build Coastguard Worker static struct typemap {
729*49cdfc7eSAndroid Build Coastguard Worker 	const char *id;
730*49cdfc7eSAndroid Build Coastguard Worker 	enum data_type type;
731*49cdfc7eSAndroid Build Coastguard Worker } tst_test_typemap[] = {
732*49cdfc7eSAndroid Build Coastguard Worker 	{.id = "test_variants", .type = DATA_INT},
733*49cdfc7eSAndroid Build Coastguard Worker 	{}
734*49cdfc7eSAndroid Build Coastguard Worker };
735*49cdfc7eSAndroid Build Coastguard Worker 
convert_str2int(struct data_node * res,const char * id,const char * str_val)736*49cdfc7eSAndroid Build Coastguard Worker static void convert_str2int(struct data_node *res, const char *id, const char *str_val)
737*49cdfc7eSAndroid Build Coastguard Worker {
738*49cdfc7eSAndroid Build Coastguard Worker 	long val;
739*49cdfc7eSAndroid Build Coastguard Worker 	char *endptr;
740*49cdfc7eSAndroid Build Coastguard Worker 
741*49cdfc7eSAndroid Build Coastguard Worker 	errno = 0;
742*49cdfc7eSAndroid Build Coastguard Worker 	val = strtol(str_val, &endptr, 10);
743*49cdfc7eSAndroid Build Coastguard Worker 
744*49cdfc7eSAndroid Build Coastguard Worker 	if (errno || *endptr) {
745*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr,	"Cannot convert %s value %s to int!\n", id, str_val);
746*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
747*49cdfc7eSAndroid Build Coastguard Worker 	}
748*49cdfc7eSAndroid Build Coastguard Worker 
749*49cdfc7eSAndroid Build Coastguard Worker 	if (verbose)
750*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "NORMALIZING %s TO INT %li\n", id, val);
751*49cdfc7eSAndroid Build Coastguard Worker 
752*49cdfc7eSAndroid Build Coastguard Worker 	data_node_hash_del(res, id);
753*49cdfc7eSAndroid Build Coastguard Worker 	data_node_hash_add(res, id, data_node_int(val));
754*49cdfc7eSAndroid Build Coastguard Worker }
755*49cdfc7eSAndroid Build Coastguard Worker 
check_normalize_types(struct data_node * res)756*49cdfc7eSAndroid Build Coastguard Worker static void check_normalize_types(struct data_node *res)
757*49cdfc7eSAndroid Build Coastguard Worker {
758*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i;
759*49cdfc7eSAndroid Build Coastguard Worker 
760*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; tst_test_typemap[i].id; i++) {
761*49cdfc7eSAndroid Build Coastguard Worker 		struct data_node *n;
762*49cdfc7eSAndroid Build Coastguard Worker 		struct typemap *typemap = &tst_test_typemap[i];
763*49cdfc7eSAndroid Build Coastguard Worker 
764*49cdfc7eSAndroid Build Coastguard Worker 		n = data_node_hash_get(res, typemap->id);
765*49cdfc7eSAndroid Build Coastguard Worker 		if (!n)
766*49cdfc7eSAndroid Build Coastguard Worker 			continue;
767*49cdfc7eSAndroid Build Coastguard Worker 
768*49cdfc7eSAndroid Build Coastguard Worker 		if (n->type == typemap->type)
769*49cdfc7eSAndroid Build Coastguard Worker 			continue;
770*49cdfc7eSAndroid Build Coastguard Worker 
771*49cdfc7eSAndroid Build Coastguard Worker 		if (n->type == DATA_STRING && typemap->type == DATA_INT) {
772*49cdfc7eSAndroid Build Coastguard Worker 			convert_str2int(res, typemap->id, n->string.val);
773*49cdfc7eSAndroid Build Coastguard Worker 			continue;
774*49cdfc7eSAndroid Build Coastguard Worker 		}
775*49cdfc7eSAndroid Build Coastguard Worker 
776*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot convert %s from %s to %s!\n",
777*49cdfc7eSAndroid Build Coastguard Worker 			typemap->id, data_type_name(n->type),
778*49cdfc7eSAndroid Build Coastguard Worker 			data_type_name(typemap->type));
779*49cdfc7eSAndroid Build Coastguard Worker 		exit(1);
780*49cdfc7eSAndroid Build Coastguard Worker 	}
781*49cdfc7eSAndroid Build Coastguard Worker }
782*49cdfc7eSAndroid Build Coastguard Worker 
783*49cdfc7eSAndroid Build Coastguard Worker static const char *filter_out[] = {
784*49cdfc7eSAndroid Build Coastguard Worker 	"bufs",
785*49cdfc7eSAndroid Build Coastguard Worker 	"cleanup",
786*49cdfc7eSAndroid Build Coastguard Worker 	"mntpoint",
787*49cdfc7eSAndroid Build Coastguard Worker 	"setup",
788*49cdfc7eSAndroid Build Coastguard Worker 	"tcnt",
789*49cdfc7eSAndroid Build Coastguard Worker 	"test",
790*49cdfc7eSAndroid Build Coastguard Worker 	"test_all",
791*49cdfc7eSAndroid Build Coastguard Worker 	NULL
792*49cdfc7eSAndroid Build Coastguard Worker };
793*49cdfc7eSAndroid Build Coastguard Worker 
794*49cdfc7eSAndroid Build Coastguard Worker static struct implies {
795*49cdfc7eSAndroid Build Coastguard Worker 	const char *flag;
796*49cdfc7eSAndroid Build Coastguard Worker 	const char **implies;
797*49cdfc7eSAndroid Build Coastguard Worker } implies[] = {
798*49cdfc7eSAndroid Build Coastguard Worker 	{"mount_device", (const char *[]) {"format_device", "needs_device",
799*49cdfc7eSAndroid Build Coastguard Worker 		"needs_tmpdir", NULL}},
800*49cdfc7eSAndroid Build Coastguard Worker 	{"format_device", (const char *[]) {"needs_device", "needs_tmpdir",
801*49cdfc7eSAndroid Build Coastguard Worker 		NULL}},
802*49cdfc7eSAndroid Build Coastguard Worker 	{"all_filesystems", (const char *[]) {"needs_device", "needs_tmpdir",
803*49cdfc7eSAndroid Build Coastguard Worker 		NULL}},
804*49cdfc7eSAndroid Build Coastguard Worker 	{"needs_device", (const char *[]) {"needs_tmpdir", NULL}},
805*49cdfc7eSAndroid Build Coastguard Worker 	{"needs_checkpoints", (const char *[]) {"needs_tmpdir", NULL}},
806*49cdfc7eSAndroid Build Coastguard Worker 	{"resource_files", (const char *[]) {"needs_tmpdir", NULL}},
807*49cdfc7eSAndroid Build Coastguard Worker 	{NULL, (const char *[]) {NULL}}
808*49cdfc7eSAndroid Build Coastguard Worker };
809*49cdfc7eSAndroid Build Coastguard Worker 
strip_name(char * path)810*49cdfc7eSAndroid Build Coastguard Worker const char *strip_name(char *path)
811*49cdfc7eSAndroid Build Coastguard Worker {
812*49cdfc7eSAndroid Build Coastguard Worker 	char *name = basename(path);
813*49cdfc7eSAndroid Build Coastguard Worker 	size_t len = strlen(name);
814*49cdfc7eSAndroid Build Coastguard Worker 
815*49cdfc7eSAndroid Build Coastguard Worker 	if (len > 2 && name[len-1] == 'c' && name[len-2] == '.')
816*49cdfc7eSAndroid Build Coastguard Worker 		name[len-2] = '\0';
817*49cdfc7eSAndroid Build Coastguard Worker 
818*49cdfc7eSAndroid Build Coastguard Worker 	return name;
819*49cdfc7eSAndroid Build Coastguard Worker }
820*49cdfc7eSAndroid Build Coastguard Worker 
print_help(const char * prgname)821*49cdfc7eSAndroid Build Coastguard Worker static void print_help(const char *prgname)
822*49cdfc7eSAndroid Build Coastguard Worker {
823*49cdfc7eSAndroid Build Coastguard Worker 	printf("usage: %s [-vh] input.c\n\n", prgname);
824*49cdfc7eSAndroid Build Coastguard Worker 	printf("-v sets verbose mode\n");
825*49cdfc7eSAndroid Build Coastguard Worker 	printf("-I add include path\n");
826*49cdfc7eSAndroid Build Coastguard Worker 	printf("-h prints this help\n\n");
827*49cdfc7eSAndroid Build Coastguard Worker 	exit(0);
828*49cdfc7eSAndroid Build Coastguard Worker }
829*49cdfc7eSAndroid Build Coastguard Worker 
main(int argc,char * argv[])830*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char *argv[])
831*49cdfc7eSAndroid Build Coastguard Worker {
832*49cdfc7eSAndroid Build Coastguard Worker 	unsigned int i, j;
833*49cdfc7eSAndroid Build Coastguard Worker 	struct data_node *res;
834*49cdfc7eSAndroid Build Coastguard Worker 	int opt;
835*49cdfc7eSAndroid Build Coastguard Worker 
836*49cdfc7eSAndroid Build Coastguard Worker 	while ((opt = getopt(argc, argv, "hI:v")) != -1) {
837*49cdfc7eSAndroid Build Coastguard Worker 		switch (opt) {
838*49cdfc7eSAndroid Build Coastguard Worker 		case 'h':
839*49cdfc7eSAndroid Build Coastguard Worker 			print_help(argv[0]);
840*49cdfc7eSAndroid Build Coastguard Worker 		break;
841*49cdfc7eSAndroid Build Coastguard Worker 		case 'I':
842*49cdfc7eSAndroid Build Coastguard Worker 			if (cmdline_includepaths >= INCLUDE_PATH_MAX) {
843*49cdfc7eSAndroid Build Coastguard Worker 				fprintf(stderr, "Too much include paths!");
844*49cdfc7eSAndroid Build Coastguard Worker 				exit(1);
845*49cdfc7eSAndroid Build Coastguard Worker 			}
846*49cdfc7eSAndroid Build Coastguard Worker 
847*49cdfc7eSAndroid Build Coastguard Worker 			cmdline_includepath[cmdline_includepaths++] = optarg;
848*49cdfc7eSAndroid Build Coastguard Worker 		break;
849*49cdfc7eSAndroid Build Coastguard Worker 		case 'v':
850*49cdfc7eSAndroid Build Coastguard Worker 			verbose = 1;
851*49cdfc7eSAndroid Build Coastguard Worker 		break;
852*49cdfc7eSAndroid Build Coastguard Worker 		}
853*49cdfc7eSAndroid Build Coastguard Worker 	}
854*49cdfc7eSAndroid Build Coastguard Worker 
855*49cdfc7eSAndroid Build Coastguard Worker 	if (optind >= argc) {
856*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "No input filename.c\n");
857*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
858*49cdfc7eSAndroid Build Coastguard Worker 	}
859*49cdfc7eSAndroid Build Coastguard Worker 
860*49cdfc7eSAndroid Build Coastguard Worker 	if (!hcreate(128)) {
861*49cdfc7eSAndroid Build Coastguard Worker 		fprintf(stderr, "Failed to initialize hash table\n");
862*49cdfc7eSAndroid Build Coastguard Worker 		return 1;
863*49cdfc7eSAndroid Build Coastguard Worker 	}
864*49cdfc7eSAndroid Build Coastguard Worker 
865*49cdfc7eSAndroid Build Coastguard Worker 	res = parse_file(argv[optind]);
866*49cdfc7eSAndroid Build Coastguard Worker 	if (!res)
867*49cdfc7eSAndroid Build Coastguard Worker 		return 0;
868*49cdfc7eSAndroid Build Coastguard Worker 
869*49cdfc7eSAndroid Build Coastguard Worker 	/* Filter out useless data */
870*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; filter_out[i]; i++)
871*49cdfc7eSAndroid Build Coastguard Worker 		data_node_hash_del(res, filter_out[i]);
872*49cdfc7eSAndroid Build Coastguard Worker 
873*49cdfc7eSAndroid Build Coastguard Worker 	/* Normalize the result */
874*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; implies[i].flag; i++) {
875*49cdfc7eSAndroid Build Coastguard Worker 		if (data_node_hash_get(res, implies[i].flag)) {
876*49cdfc7eSAndroid Build Coastguard Worker 			for (j = 0; implies[i].implies[j]; j++) {
877*49cdfc7eSAndroid Build Coastguard Worker 				if (data_node_hash_get(res, implies[i].implies[j]))
878*49cdfc7eSAndroid Build Coastguard Worker 					fprintf(stderr, "%s: useless tag: %s\n",
879*49cdfc7eSAndroid Build Coastguard Worker 						argv[optind], implies[i].implies[j]);
880*49cdfc7eSAndroid Build Coastguard Worker 			}
881*49cdfc7eSAndroid Build Coastguard Worker 		}
882*49cdfc7eSAndroid Build Coastguard Worker 	}
883*49cdfc7eSAndroid Build Coastguard Worker 
884*49cdfc7eSAndroid Build Coastguard Worker 	/* Normalize types */
885*49cdfc7eSAndroid Build Coastguard Worker 	check_normalize_types(res);
886*49cdfc7eSAndroid Build Coastguard Worker 
887*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; implies[i].flag; i++) {
888*49cdfc7eSAndroid Build Coastguard Worker 		if (data_node_hash_get(res, implies[i].flag)) {
889*49cdfc7eSAndroid Build Coastguard Worker 			for (j = 0; implies[i].implies[j]; j++) {
890*49cdfc7eSAndroid Build Coastguard Worker 				if (!data_node_hash_get(res, implies[i].implies[j]))
891*49cdfc7eSAndroid Build Coastguard Worker 					data_node_hash_add(res, implies[i].implies[j],
892*49cdfc7eSAndroid Build Coastguard Worker 							   data_node_string("1"));
893*49cdfc7eSAndroid Build Coastguard Worker 			}
894*49cdfc7eSAndroid Build Coastguard Worker 		}
895*49cdfc7eSAndroid Build Coastguard Worker 	}
896*49cdfc7eSAndroid Build Coastguard Worker 
897*49cdfc7eSAndroid Build Coastguard Worker 	data_node_hash_add(res, "fname", data_node_string(argv[optind]));
898*49cdfc7eSAndroid Build Coastguard Worker 	printf("  \"%s\": ", strip_name(argv[optind]));
899*49cdfc7eSAndroid Build Coastguard Worker 	data_to_json(res, stdout, 2);
900*49cdfc7eSAndroid Build Coastguard Worker 	data_node_free(res);
901*49cdfc7eSAndroid Build Coastguard Worker 
902*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
903*49cdfc7eSAndroid Build Coastguard Worker }
904