Merge branch 'master' into for-next
[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 %option noinput
4 %x COMMAND HELP STRING PARAM
5 %{
6 /*
7  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
8  * Released under the terms of the GNU GPL v2.0.
9  */
10
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.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 static 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 static 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 static 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                 while (yyleng) {
222                         if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
223                                 break;
224                         yyleng--;
225                 }
226                 append_string(yytext, yyleng);
227                 if (!first_ts)
228                         first_ts = last_ts;
229         }
230         <<EOF>> {
231                 zconf_endhelp();
232                 return T_HELPTEXT;
233         }
234 }
235
236 <<EOF>> {
237         if (current_file) {
238                 zconf_endfile();
239                 return T_EOL;
240         }
241         fclose(yyin);
242         yyterminate();
243 }
244
245 %%
246 void zconf_starthelp(void)
247 {
248         new_string();
249         last_ts = first_ts = 0;
250         BEGIN(HELP);
251 }
252
253 static void zconf_endhelp(void)
254 {
255         zconflval.string = text;
256         BEGIN(INITIAL);
257 }
258
259
260 /*
261  * Try to open specified file with following names:
262  * ./name
263  * $(srctree)/name
264  * The latter is used when srctree is separate from objtree
265  * when compiling the kernel.
266  * Return NULL if file is not found.
267  */
268 FILE *zconf_fopen(const char *name)
269 {
270         char *env, fullname[PATH_MAX+1];
271         FILE *f;
272
273         f = fopen(name, "r");
274         if (!f && name != NULL && name[0] != '/') {
275                 env = getenv(SRCTREE);
276                 if (env) {
277                         sprintf(fullname, "%s/%s", env, name);
278                         f = fopen(fullname, "r");
279                 }
280         }
281         return f;
282 }
283
284 void zconf_initscan(const char *name)
285 {
286         yyin = zconf_fopen(name);
287         if (!yyin) {
288                 printf("can't find file %s\n", name);
289                 exit(1);
290         }
291
292         current_buf = malloc(sizeof(*current_buf));
293         memset(current_buf, 0, sizeof(*current_buf));
294
295         current_file = file_lookup(name);
296         current_file->lineno = 1;
297         current_file->flags = FILE_BUSY;
298 }
299
300 void zconf_nextfile(const char *name)
301 {
302         struct file *file = file_lookup(name);
303         struct buffer *buf = malloc(sizeof(*buf));
304         memset(buf, 0, sizeof(*buf));
305
306         current_buf->state = YY_CURRENT_BUFFER;
307         yyin = zconf_fopen(name);
308         if (!yyin) {
309                 printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
310                 exit(1);
311         }
312         yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
313         buf->parent = current_buf;
314         current_buf = buf;
315
316         if (file->flags & FILE_BUSY) {
317                 printf("%s:%d: do not source '%s' from itself\n",
318                        zconf_curname(), zconf_lineno(), name);
319                 exit(1);
320         }
321         if (file->flags & FILE_SCANNED) {
322                 printf("%s:%d: file '%s' is already sourced from '%s'\n",
323                        zconf_curname(), zconf_lineno(), name,
324                        file->parent->name);
325                 exit(1);
326         }
327         file->flags |= FILE_BUSY;
328         file->lineno = 1;
329         file->parent = current_file;
330         current_file = file;
331 }
332
333 static void zconf_endfile(void)
334 {
335         struct buffer *parent;
336
337         current_file->flags |= FILE_SCANNED;
338         current_file->flags &= ~FILE_BUSY;
339         current_file = current_file->parent;
340
341         parent = current_buf->parent;
342         if (parent) {
343                 fclose(yyin);
344                 yy_delete_buffer(YY_CURRENT_BUFFER);
345                 yy_switch_to_buffer(parent->state);
346         }
347         free(current_buf);
348         current_buf = parent;
349 }
350
351 int zconf_lineno(void)
352 {
353         return current_pos.lineno;
354 }
355
356 char *zconf_curname(void)
357 {
358         return current_pos.file ? current_pos.file->name : "<none>";
359 }