finally move buildroot-ng to trunk
[openwrt.git] / scripts / config / zconf.l
1 %option backup nostdinit noyywrap never-interactive full ecs
2 %option 8bit backup nodefault perf-report perf-report
3 %x COMMAND HELP STRING PARAM
4 %{
5 /*
6  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
7  * Released under the terms of the GNU GPL v2.0.
8  */
9
10 #include <limits.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <glob.h>
16
17 #define LKC_DIRECT_LINK
18 #include "lkc.h"
19
20 #define START_STRSIZE   16
21
22 static struct {
23         struct file *file;
24         int lineno;
25 } current_pos;
26
27 static char *text;
28 static int text_size, text_asize;
29
30 struct buffer {
31         struct buffer *parent;
32         YY_BUFFER_STATE state;
33 };
34
35 struct buffer *current_buf;
36
37 static int last_ts, first_ts;
38
39 static void zconf_endhelp(void);
40 static void zconf_endfile(void);
41
42 void new_string(void)
43 {
44         text = malloc(START_STRSIZE);
45         text_asize = START_STRSIZE;
46         text_size = 0;
47         *text = 0;
48 }
49
50 void append_string(const char *str, int size)
51 {
52         int new_size = text_size + size + 1;
53         if (new_size > text_asize) {
54                 new_size += START_STRSIZE - 1;
55                 new_size &= -START_STRSIZE;
56                 text = realloc(text, new_size);
57                 text_asize = new_size;
58         }
59         memcpy(text + text_size, str, size);
60         text_size += size;
61         text[text_size] = 0;
62 }
63
64 void alloc_string(const char *str, int size)
65 {
66         text = malloc(size + 1);
67         memcpy(text, str, size);
68         text[size] = 0;
69 }
70 %}
71
72 ws      [ \n\t]
73 n       [A-Za-z0-9_]
74
75 %%
76         int str = 0;
77         int ts, i;
78
79 [ \t]*#.*\n     |
80 [ \t]*\n        {
81         current_file->lineno++;
82         return T_EOL;
83 }
84 [ \t]*#.*
85
86
87 [ \t]+  {
88         BEGIN(COMMAND);
89 }
90
91 .       {
92         unput(yytext[0]);
93         BEGIN(COMMAND);
94 }
95
96
97 <COMMAND>{
98         {n}+    {
99                 struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
100                 BEGIN(PARAM);
101                 current_pos.file = current_file;
102                 current_pos.lineno = current_file->lineno;
103                 if (id && id->flags & TF_COMMAND) {
104                         zconflval.id = id;
105                         return id->token;
106                 }
107                 alloc_string(yytext, yyleng);
108                 zconflval.string = text;
109                 return T_WORD;
110         }
111         .
112         \n      {
113                 BEGIN(INITIAL);
114                 current_file->lineno++;
115                 return T_EOL;
116         }
117 }
118
119 <PARAM>{
120         "&&"    return T_AND;
121         "||"    return T_OR;
122         "("     return T_OPEN_PAREN;
123         ")"     return T_CLOSE_PAREN;
124         "!"     return T_NOT;
125         "="     return T_EQUAL;
126         "!="    return T_UNEQUAL;
127         \"|\'   {
128                 str = yytext[0];
129                 new_string();
130                 BEGIN(STRING);
131         }
132         \n      BEGIN(INITIAL); current_file->lineno++; return T_EOL;
133         ---     /* ignore */
134         ({n}|[-/.])+    {
135                 struct kconf_id *id = kconf_id_lookup(yytext, yyleng);
136                 if (id && id->flags & TF_PARAM) {
137                         zconflval.id = id;
138                         return id->token;
139                 }
140                 alloc_string(yytext, yyleng);
141                 zconflval.string = text;
142                 return T_WORD;
143         }
144         #.*     /* comment */
145         \\\n    current_file->lineno++;
146         .
147         <<EOF>> {
148                 BEGIN(INITIAL);
149         }
150 }
151
152 <STRING>{
153         [^'"\\\n]+/\n   {
154                 append_string(yytext, yyleng);
155                 zconflval.string = text;
156                 return T_WORD_QUOTE;
157         }
158         [^'"\\\n]+      {
159                 append_string(yytext, yyleng);
160         }
161         \\.?/\n {
162                 append_string(yytext + 1, yyleng - 1);
163                 zconflval.string = text;
164                 return T_WORD_QUOTE;
165         }
166         \\.?    {
167                 append_string(yytext + 1, yyleng - 1);
168         }
169         \'|\"   {
170                 if (str == yytext[0]) {
171                         BEGIN(PARAM);
172                         zconflval.string = text;
173                         return T_WORD_QUOTE;
174                 } else
175                         append_string(yytext, 1);
176         }
177         \n      {
178                 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
179                 current_file->lineno++;
180                 BEGIN(INITIAL);
181                 return T_EOL;
182         }
183         <<EOF>> {
184                 BEGIN(INITIAL);
185         }
186 }
187
188 <HELP>{
189         [ \t]+  {
190                 ts = 0;
191                 for (i = 0; i < yyleng; i++) {
192                         if (yytext[i] == '\t')
193                                 ts = (ts & ~7) + 8;
194                         else
195                                 ts++;
196                 }
197                 last_ts = ts;
198                 if (first_ts) {
199                         if (ts < first_ts) {
200                                 zconf_endhelp();
201                                 return T_HELPTEXT;
202                         }
203                         ts -= first_ts;
204                         while (ts > 8) {
205                                 append_string("        ", 8);
206                                 ts -= 8;
207                         }
208                         append_string("        ", ts);
209                 }
210         }
211         [ \t]*\n/[^ \t\n] {
212                 current_file->lineno++;
213                 zconf_endhelp();
214                 return T_HELPTEXT;
215         }
216         [ \t]*\n        {
217                 current_file->lineno++;
218                 append_string("\n", 1);
219         }
220         [^ \t\n].* {
221                 append_string(yytext, yyleng);
222                 if (!first_ts)
223                         first_ts = last_ts;
224         }
225         <<EOF>> {
226                 zconf_endhelp();
227                 return T_HELPTEXT;
228         }
229 }
230
231 <<EOF>> {
232         if (current_file) {
233                 zconf_endfile();
234                 return T_EOL;
235         }
236         fclose(yyin);
237         yyterminate();
238 }
239
240 %%
241 void zconf_starthelp(void)
242 {
243         new_string();
244         last_ts = first_ts = 0;
245         BEGIN(HELP);
246 }
247
248 static void zconf_endhelp(void)
249 {
250         zconflval.string = text;
251         BEGIN(INITIAL);
252 }
253
254
255 /*
256  * Try to open specified file with following names:
257  * ./name
258  * $(srctree)/name
259  * The latter is used when srctree is separate from objtree
260  * when compiling the kernel.
261  * Return NULL if file is not found.
262  */
263 FILE *zconf_fopen(const char *name)
264 {
265         char *env, fullname[PATH_MAX+1];
266         FILE *f;
267
268         f = fopen(name, "r");
269         if (!f && name[0] != '/') {
270                 env = getenv(SRCTREE);
271                 if (env) {
272                         sprintf(fullname, "%s/%s", env, name);
273                         f = fopen(fullname, "r");
274                 }
275         }
276         return f;
277 }
278
279 void zconf_initscan(const char *name)
280 {
281         yyin = zconf_fopen(name);
282         if (!yyin) {
283                 printf("can't find file %s\n", name);
284                 exit(1);
285         }
286
287         current_buf = malloc(sizeof(*current_buf));
288         memset(current_buf, 0, sizeof(*current_buf));
289
290         current_file = file_lookup(name);
291         current_file->lineno = 1;
292         current_file->flags = FILE_BUSY;
293 }
294
295 void zconf_nextfile(const char *name)
296 {
297         size_t i;
298         int retval;
299         glob_t files;
300         char *filename;
301         struct file *file;
302         struct buffer *buf;
303
304         retval = glob(name, GLOB_ERR | GLOB_MARK, NULL, &files);
305         if (retval == GLOB_NOSPACE || retval == GLOB_ABORTED || retval == GLOB_NOMATCH) {
306                 printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(),
307                         retval == GLOB_NOSPACE ? "failed to allocate memory" :
308                                 retval == GLOB_ABORTED ? "read error" : "no match",
309                         name);
310                 exit(1);
311         }
312
313         for (i = files.gl_pathc-1; i != (size_t)-1; --i) {
314                 filename = files.gl_pathv[i];
315
316                 file = file_lookup(filename);
317                 buf = malloc(sizeof(*buf));
318                 memset(buf, 0, sizeof(*buf));
319                 current_buf->state = YY_CURRENT_BUFFER;
320                 zconfin = zconf_fopen(filename);
321                 if (!zconfin) {
322                         printf("%s:%d: can't open file \"%s\"\n",
323                                 zconf_curname(), zconf_lineno(), filename);
324                         exit(1);
325                 }
326                 zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
327                 buf->parent = current_buf;
328                 current_buf = buf;
329
330                 if (file->flags & FILE_BUSY) {
331                         printf("recursive scan (%s)?\n", filename);
332                         exit(1);
333                 }
334                 if (file->flags & FILE_SCANNED) {
335                         printf("file %s already scanned?\n", filename);
336                         exit(1);
337                 }
338                 file->flags |= FILE_BUSY;
339                 file->lineno = 1;
340                 file->parent = current_file;
341                 current_file = file;
342         }
343 }
344
345 static void zconf_endfile(void)
346 {
347         struct buffer *parent;
348
349         current_file->flags |= FILE_SCANNED;
350         current_file->flags &= ~FILE_BUSY;
351         current_file = current_file->parent;
352
353         parent = current_buf->parent;
354         if (parent) {
355                 fclose(yyin);
356                 yy_delete_buffer(YY_CURRENT_BUFFER);
357                 yy_switch_to_buffer(parent->state);
358         }
359         free(current_buf);
360         current_buf = parent;
361 }
362
363 int zconf_lineno(void)
364 {
365         return current_pos.lineno;
366 }
367
368 char *zconf_curname(void)
369 {
370         return current_pos.file ? current_pos.file->name : "<none>";
371 }