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