55517b2877cdb610c57acaae904647e57cfe5d8f
[linux-2.6.git] / scripts / kconfig / 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
16 #define LKC_DIRECT_LINK
17 #include "lkc.h"
18
19 #define START_STRSIZE   16
20
21 char *text;
22 static char *text_ptr;
23 static int text_size, text_asize;
24
25 struct buffer {
26         struct buffer *parent;
27         YY_BUFFER_STATE state;
28 };
29
30 struct buffer *current_buf;
31
32 static int last_ts, first_ts;
33
34 static void zconf_endhelp(void);
35 static struct buffer *zconf_endfile(void);
36
37 void new_string(void)
38 {
39         text = malloc(START_STRSIZE);
40         text_asize = START_STRSIZE;
41         text_ptr = text;
42         text_size = 0;
43         *text_ptr = 0;
44 }
45
46 void append_string(const char *str, int size)
47 {
48         int new_size = text_size + size + 1;
49         if (new_size > text_asize) {
50                 text = realloc(text, new_size);
51                 text_asize = new_size;
52                 text_ptr = text + text_size;
53         }
54         memcpy(text_ptr, str, size);
55         text_ptr += size;
56         text_size += size;
57         *text_ptr = 0;
58 }
59
60 void alloc_string(const char *str, int size)
61 {
62         text = malloc(size + 1);
63         memcpy(text, str, size);
64         text[size] = 0;
65 }
66 %}
67
68 ws      [ \n\t]
69 n       [A-Za-z0-9_]
70
71 %%
72         int str = 0;
73         int ts, i;
74
75 [ \t]*#.*\n     current_file->lineno++;
76 [ \t]*#.*
77
78 [ \t]*\n        current_file->lineno++; return T_EOL;
79
80 [ \t]+  {
81         BEGIN(COMMAND);
82 }
83
84 .       {
85         unput(yytext[0]);
86         BEGIN(COMMAND);
87 }
88
89
90 <COMMAND>{
91         "mainmenu"              BEGIN(PARAM); return T_MAINMENU;
92         "menu"                  BEGIN(PARAM); return T_MENU;
93         "endmenu"               BEGIN(PARAM); return T_ENDMENU;
94         "source"                BEGIN(PARAM); return T_SOURCE;
95         "choice"                BEGIN(PARAM); return T_CHOICE;
96         "endchoice"             BEGIN(PARAM); return T_ENDCHOICE;
97         "comment"               BEGIN(PARAM); return T_COMMENT;
98         "config"                BEGIN(PARAM); return T_CONFIG;
99         "menuconfig"            BEGIN(PARAM); return T_MENUCONFIG;
100         "help"                  BEGIN(PARAM); return T_HELP;
101         "if"                    BEGIN(PARAM); return T_IF;
102         "endif"                 BEGIN(PARAM); return T_ENDIF;
103         "depends"               BEGIN(PARAM); return T_DEPENDS;
104         "requires"              BEGIN(PARAM); return T_REQUIRES;
105         "optional"              BEGIN(PARAM); return T_OPTIONAL;
106         "default"               BEGIN(PARAM); return T_DEFAULT;
107         "prompt"                BEGIN(PARAM); return T_PROMPT;
108         "tristate"              BEGIN(PARAM); return T_TRISTATE;
109         "def_tristate"          BEGIN(PARAM); return T_DEF_TRISTATE;
110         "bool"                  BEGIN(PARAM); return T_BOOLEAN;
111         "boolean"               BEGIN(PARAM); return T_BOOLEAN;
112         "def_bool"              BEGIN(PARAM); return T_DEF_BOOLEAN;
113         "def_boolean"           BEGIN(PARAM); return T_DEF_BOOLEAN;
114         "int"                   BEGIN(PARAM); return T_INT;
115         "hex"                   BEGIN(PARAM); return T_HEX;
116         "string"                BEGIN(PARAM); return T_STRING;
117         "select"                BEGIN(PARAM); return T_SELECT;
118         "enable"                BEGIN(PARAM); return T_SELECT;
119         "range"                 BEGIN(PARAM); return T_RANGE;
120         {n}+    {
121                 alloc_string(yytext, yyleng);
122                 zconflval.string = text;
123                 return T_WORD;
124         }
125         .
126         \n      current_file->lineno++; BEGIN(INITIAL);
127 }
128
129 <PARAM>{
130         "&&"    return T_AND;
131         "||"    return T_OR;
132         "("     return T_OPEN_PAREN;
133         ")"     return T_CLOSE_PAREN;
134         "!"     return T_NOT;
135         "="     return T_EQUAL;
136         "!="    return T_UNEQUAL;
137         "if"    return T_IF;
138         "on"    return T_ON;
139         \"|\'   {
140                 str = yytext[0];
141                 new_string();
142                 BEGIN(STRING);
143         }
144         \n      BEGIN(INITIAL); current_file->lineno++; return T_EOL;
145         ---     /* ignore */
146         ({n}|[-/.])+    {
147                 alloc_string(yytext, yyleng);
148                 zconflval.string = text;
149                 return T_WORD;
150         }
151         #.*     /* comment */
152         \\\n    current_file->lineno++;
153         .
154         <<EOF>> {
155                 BEGIN(INITIAL);
156         }
157 }
158
159 <STRING>{
160         [^'"\\\n]+/\n   {
161                 append_string(yytext, yyleng);
162                 zconflval.string = text;
163                 return T_WORD_QUOTE;
164         }
165         [^'"\\\n]+      {
166                 append_string(yytext, yyleng);
167         }
168         \\.?/\n {
169                 append_string(yytext + 1, yyleng - 1);
170                 zconflval.string = text;
171                 return T_WORD_QUOTE;
172         }
173         \\.?    {
174                 append_string(yytext + 1, yyleng - 1);
175         }
176         \'|\"   {
177                 if (str == yytext[0]) {
178                         BEGIN(PARAM);
179                         zconflval.string = text;
180                         return T_WORD_QUOTE;
181                 } else
182                         append_string(yytext, 1);
183         }
184         \n      {
185                 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno());
186                 current_file->lineno++;
187                 BEGIN(INITIAL);
188                 return T_EOL;
189         }
190         <<EOF>> {
191                 BEGIN(INITIAL);
192         }
193 }
194
195 <HELP>{
196         [ \t]+  {
197                 ts = 0;
198                 for (i = 0; i < yyleng; i++) {
199                         if (yytext[i] == '\t')
200                                 ts = (ts & ~7) + 8;
201                         else
202                                 ts++;
203                 }
204                 last_ts = ts;
205                 if (first_ts) {
206                         if (ts < first_ts) {
207                                 zconf_endhelp();
208                                 return T_HELPTEXT;
209                         }
210                         ts -= first_ts;
211                         while (ts > 8) {
212                                 append_string("        ", 8);
213                                 ts -= 8;
214                         }
215                         append_string("        ", ts);
216                 }
217         }
218         [ \t]*\n/[^ \t\n] {
219                 current_file->lineno++;
220                 zconf_endhelp();
221                 return T_HELPTEXT;
222         }
223         [ \t]*\n        {
224                 current_file->lineno++;
225                 append_string("\n", 1);
226         }
227         [^ \t\n].* {
228                 append_string(yytext, yyleng);
229                 if (!first_ts)
230                         first_ts = last_ts;
231         }
232         <<EOF>> {
233                 zconf_endhelp();
234                 return T_HELPTEXT;
235         }
236 }
237
238 <<EOF>> {
239         if (current_buf) {
240                 zconf_endfile();
241                 return T_EOF;
242         }
243         fclose(yyin);
244         yyterminate();
245 }
246
247 %%
248 void zconf_starthelp(void)
249 {
250         new_string();
251         last_ts = first_ts = 0;
252         BEGIN(HELP);
253 }
254
255 static void zconf_endhelp(void)
256 {
257         zconflval.string = text;
258         BEGIN(INITIAL);
259 }
260
261
262 /*
263  * Try to open specified file with following names:
264  * ./name
265  * $(srctree)/name
266  * The latter is used when srctree is separate from objtree
267  * when compiling the kernel.
268  * Return NULL if file is not found.
269  */
270 FILE *zconf_fopen(const char *name)
271 {
272         char *env, fullname[PATH_MAX+1];
273         FILE *f;
274
275         f = fopen(name, "r");
276         if (!f && name[0] != '/') {
277                 env = getenv(SRCTREE);
278                 if (env) {
279                         sprintf(fullname, "%s/%s", env, name);
280                         f = fopen(fullname, "r");
281                 }
282         }
283         return f;
284 }
285
286 void zconf_initscan(const char *name)
287 {
288         yyin = zconf_fopen(name);
289         if (!yyin) {
290                 printf("can't find file %s\n", name);
291                 exit(1);
292         }
293
294         current_buf = malloc(sizeof(*current_buf));
295         memset(current_buf, 0, sizeof(*current_buf));
296
297         current_file = file_lookup(name);
298         current_file->lineno = 1;
299         current_file->flags = FILE_BUSY;
300 }
301
302 void zconf_nextfile(const char *name)
303 {
304         struct file *file = file_lookup(name);
305         struct buffer *buf = malloc(sizeof(*buf));
306         memset(buf, 0, sizeof(*buf));
307
308         current_buf->state = YY_CURRENT_BUFFER;
309         yyin = zconf_fopen(name);
310         if (!yyin) {
311                 printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
312                 exit(1);
313         }
314         yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
315         buf->parent = current_buf;
316         current_buf = buf;
317
318         if (file->flags & FILE_BUSY) {
319                 printf("recursive scan (%s)?\n", name);
320                 exit(1);
321         }
322         if (file->flags & FILE_SCANNED) {
323                 printf("file %s already scanned?\n", name);
324                 exit(1);
325         }
326         file->flags |= FILE_BUSY;
327         file->lineno = 1;
328         file->parent = current_file;
329         current_file = file;
330 }
331
332 static struct buffer *zconf_endfile(void)
333 {
334         struct buffer *parent;
335
336         current_file->flags |= FILE_SCANNED;
337         current_file->flags &= ~FILE_BUSY;
338         current_file = current_file->parent;
339
340         parent = current_buf->parent;
341         if (parent) {
342                 fclose(yyin);
343                 yy_delete_buffer(YY_CURRENT_BUFFER);
344                 yy_switch_to_buffer(parent->state);
345         }
346         free(current_buf);
347         current_buf = parent;
348
349         return parent;
350 }
351
352 int zconf_lineno(void)
353 {
354         if (current_buf)
355                 return current_file->lineno - 1;
356         else
357                 return 0;
358 }
359
360 char *zconf_curname(void)
361 {
362         if (current_buf)
363                 return current_file->name;
364         else
365                 return "<none>";
366 }