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