kconfig: improve error messages for bad source statements
[linux-2.6/mini2440.git] / scripts / kconfig / zconf.l
blob21ff69c9ad4e846b3c409216a86434e587b22989
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  */
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
17 #define LKC_DIRECT_LINK
18 #include "lkc.h"
20 #define START_STRSIZE   16
22 static struct {
23         struct file *file;
24         int lineno;
25 } current_pos;
27 static char *text;
28 static int text_size, text_asize;
30 struct buffer {
31         struct buffer *parent;
32         YY_BUFFER_STATE state;
35 struct buffer *current_buf;
37 static int last_ts, first_ts;
39 static void zconf_endhelp(void);
40 static void zconf_endfile(void);
42 void new_string(void)
44         text = malloc(START_STRSIZE);
45         text_asize = START_STRSIZE;
46         text_size = 0;
47         *text = 0;
50 void append_string(const char *str, int size)
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;
64 void alloc_string(const char *str, int size)
66         text = malloc(size + 1);
67         memcpy(text, str, size);
68         text[size] = 0;
72 ws      [ \n\t]
73 n       [A-Za-z0-9_]
76         int str = 0;
77         int ts, i;
79 [ \t]*#.*\n     |
80 [ \t]*\n        {
81         current_file->lineno++;
82         return T_EOL;
84 [ \t]*#.*
87 [ \t]+  {
88         BEGIN(COMMAND);
91 .       {
92         unput(yytext[0]);
93         BEGIN(COMMAND);
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         }
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         }
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         }
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         }
236 <<EOF>> {
237         if (current_file) {
238                 zconf_endfile();
239                 return T_EOL;
240         }
241         fclose(yyin);
242         yyterminate();
246 void zconf_starthelp(void)
248         new_string();
249         last_ts = first_ts = 0;
250         BEGIN(HELP);
253 static void zconf_endhelp(void)
255         zconflval.string = text;
256         BEGIN(INITIAL);
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)
270         char *env, fullname[PATH_MAX+1];
271         FILE *f;
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;
284 void zconf_initscan(const char *name)
286         yyin = zconf_fopen(name);
287         if (!yyin) {
288                 printf("can't find file %s\n", name);
289                 exit(1);
290         }
292         current_buf = malloc(sizeof(*current_buf));
293         memset(current_buf, 0, sizeof(*current_buf));
295         current_file = file_lookup(name);
296         current_file->lineno = 1;
297         current_file->flags = FILE_BUSY;
300 void zconf_nextfile(const char *name)
302         struct file *file = file_lookup(name);
303         struct buffer *buf = malloc(sizeof(*buf));
304         memset(buf, 0, sizeof(*buf));
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;
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;
333 static void zconf_endfile(void)
335         struct buffer *parent;
337         current_file->flags |= FILE_SCANNED;
338         current_file->flags &= ~FILE_BUSY;
339         current_file = current_file->parent;
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;
351 int zconf_lineno(void)
353         return current_pos.lineno;
356 char *zconf_curname(void)
358         return current_pos.file ? current_pos.file->name : "<none>";