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