Makefile: Add atusb to 'all'
[linux-libre-firmware.git] / carl9170fw / config / zconf.l
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
4  */
5 %option nostdinit noyywrap never-interactive full ecs
6 %option 8bit nodefault yylineno
7 %x ASSIGN_VAL HELP STRING
8 %{
9
10 #include <assert.h>
11 #include <limits.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16
17 #include "lkc.h"
18 #include "zconf.tab.h"
19
20 #define YY_DECL         static int yylex1(void)
21
22 #define START_STRSIZE   16
23
24 static struct {
25         struct file *file;
26         int lineno;
27 } current_pos;
28
29 static int prev_prev_token = T_EOL;
30 static int prev_token = T_EOL;
31 static char *text;
32 static int text_size, text_asize;
33
34 struct buffer {
35         struct buffer *parent;
36         YY_BUFFER_STATE state;
37 };
38
39 struct buffer *current_buf;
40
41 static int last_ts, first_ts;
42
43 static char *expand_token(const char *in, size_t n);
44 static void append_expanded_string(const char *in);
45 static void zconf_endhelp(void);
46 static void zconf_endfile(void);
47
48 static void new_string(void)
49 {
50         text = xmalloc(START_STRSIZE);
51         text_asize = START_STRSIZE;
52         text_size = 0;
53         *text = 0;
54 }
55
56 static void append_string(const char *str, int size)
57 {
58         int new_size = text_size + size + 1;
59         if (new_size > text_asize) {
60                 new_size += START_STRSIZE - 1;
61                 new_size &= -START_STRSIZE;
62                 text = xrealloc(text, new_size);
63                 text_asize = new_size;
64         }
65         memcpy(text + text_size, str, size);
66         text_size += size;
67         text[text_size] = 0;
68 }
69
70 static void alloc_string(const char *str, int size)
71 {
72         text = xmalloc(size + 1);
73         memcpy(text, str, size);
74         text[size] = 0;
75 }
76
77 static void warn_ignored_character(char chr)
78 {
79         fprintf(stderr,
80                 "%s:%d:warning: ignoring unsupported character '%c'\n",
81                 current_file->name, yylineno, chr);
82 }
83 %}
84
85 n       [A-Za-z0-9_-]
86
87 %%
88         int str = 0;
89         int ts, i;
90
91 #.*                     /* ignore comment */
92 [ \t]*                  /* whitespaces */
93 \\\n                    /* escaped new line */
94 \n                      return T_EOL;
95 "allnoconfig_y"         return T_ALLNOCONFIG_Y;
96 "bool"                  return T_BOOL;
97 "choice"                return T_CHOICE;
98 "comment"               return T_COMMENT;
99 "config"                return T_CONFIG;
100 "def_bool"              return T_DEF_BOOL;
101 "def_tristate"          return T_DEF_TRISTATE;
102 "default"               return T_DEFAULT;
103 "defconfig_list"        return T_DEFCONFIG_LIST;
104 "depends"               return T_DEPENDS;
105 "endchoice"             return T_ENDCHOICE;
106 "endif"                 return T_ENDIF;
107 "endmenu"               return T_ENDMENU;
108 "help"|"---help---"     return T_HELP;
109 "hex"                   return T_HEX;
110 "if"                    return T_IF;
111 "imply"                 return T_IMPLY;
112 "int"                   return T_INT;
113 "mainmenu"              return T_MAINMENU;
114 "menu"                  return T_MENU;
115 "menuconfig"            return T_MENUCONFIG;
116 "modules"               return T_MODULES;
117 "on"                    return T_ON;
118 "option"                return T_OPTION;
119 "optional"              return T_OPTIONAL;
120 "prompt"                return T_PROMPT;
121 "range"                 return T_RANGE;
122 "select"                return T_SELECT;
123 "source"                return T_SOURCE;
124 "string"                return T_STRING;
125 "tristate"              return T_TRISTATE;
126 "visible"               return T_VISIBLE;
127 "||"                    return T_OR;
128 "&&"                    return T_AND;
129 "="                     return T_EQUAL;
130 "!="                    return T_UNEQUAL;
131 "<"                     return T_LESS;
132 "<="                    return T_LESS_EQUAL;
133 ">"                     return T_GREATER;
134 ">="                    return T_GREATER_EQUAL;
135 "!"                     return T_NOT;
136 "("                     return T_OPEN_PAREN;
137 ")"                     return T_CLOSE_PAREN;
138 ":="                    return T_COLON_EQUAL;
139 "+="                    return T_PLUS_EQUAL;
140 \"|\'                   {
141                                 str = yytext[0];
142                                 new_string();
143                                 BEGIN(STRING);
144                         }
145 {n}+                    {
146                                 alloc_string(yytext, yyleng);
147                                 yylval.string = text;
148                                 return T_WORD;
149                         }
150 ({n}|$)+                {
151                                 /* this token includes at least one '$' */
152                                 yylval.string = expand_token(yytext, yyleng);
153                                 if (strlen(yylval.string))
154                                         return T_WORD;
155                                 free(yylval.string);
156                         }
157 .                       warn_ignored_character(*yytext);
158
159 <ASSIGN_VAL>{
160         [^[:blank:]\n]+.*       {
161                 alloc_string(yytext, yyleng);
162                 yylval.string = text;
163                 return T_ASSIGN_VAL;
164         }
165         \n      { BEGIN(INITIAL); return T_EOL; }
166         .
167 }
168
169 <STRING>{
170         "$".*   append_expanded_string(yytext);
171         [^$'"\\\n]+     {
172                 append_string(yytext, yyleng);
173         }
174         \\.?    {
175                 append_string(yytext + 1, yyleng - 1);
176         }
177         \'|\"   {
178                 if (str == yytext[0]) {
179                         BEGIN(INITIAL);
180                         yylval.string = text;
181                         return T_WORD_QUOTE;
182                 } else
183                         append_string(yytext, 1);
184         }
185         \n      {
186                 fprintf(stderr,
187                         "%s:%d:warning: multi-line strings not supported\n",
188                         zconf_curname(), zconf_lineno());
189                 unput('\n');
190                 BEGIN(INITIAL);
191                 yylval.string = text;
192                 return T_WORD_QUOTE;
193         }
194         <<EOF>> {
195                 BEGIN(INITIAL);
196                 yylval.string = text;
197                 return T_WORD_QUOTE;
198         }
199 }
200
201 <HELP>{
202         [ \t]+  {
203                 ts = 0;
204                 for (i = 0; i < yyleng; i++) {
205                         if (yytext[i] == '\t')
206                                 ts = (ts & ~7) + 8;
207                         else
208                                 ts++;
209                 }
210                 last_ts = ts;
211                 if (first_ts) {
212                         if (ts < first_ts) {
213                                 zconf_endhelp();
214                                 return T_HELPTEXT;
215                         }
216                         ts -= first_ts;
217                         while (ts > 8) {
218                                 append_string("        ", 8);
219                                 ts -= 8;
220                         }
221                         append_string("        ", ts);
222                 }
223         }
224         [ \t]*\n/[^ \t\n] {
225                 zconf_endhelp();
226                 return T_HELPTEXT;
227         }
228         [ \t]*\n        {
229                 append_string("\n", 1);
230         }
231         [^ \t\n].* {
232                 while (yyleng) {
233                         if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t'))
234                                 break;
235                         yyleng--;
236                 }
237                 append_string(yytext, yyleng);
238                 if (!first_ts)
239                         first_ts = last_ts;
240         }
241         <<EOF>> {
242                 zconf_endhelp();
243                 return T_HELPTEXT;
244         }
245 }
246
247 <<EOF>> {
248         BEGIN(INITIAL);
249
250         if (prev_token != T_EOL && prev_token != T_HELPTEXT)
251                 fprintf(stderr, "%s:%d:warning: no new line at end of file\n",
252                         current_file->name, yylineno);
253
254         if (current_file) {
255                 zconf_endfile();
256                 return T_EOL;
257         }
258         fclose(yyin);
259         yyterminate();
260 }
261
262 %%
263
264 /* second stage lexer */
265 int yylex(void)
266 {
267         int token;
268
269 repeat:
270         token = yylex1();
271
272         if (prev_token == T_EOL || prev_token == T_HELPTEXT) {
273                 if (token == T_EOL) {
274                         /* Do not pass unneeded T_EOL to the parser. */
275                         goto repeat;
276                 } else {
277                         /*
278                          * For the parser, update file/lineno at the first token
279                          * of each statement. Generally, \n is a statement
280                          * terminator in Kconfig, but it is not always true
281                          * because \n could be escaped by a backslash.
282                          */
283                         current_pos.file = current_file;
284                         current_pos.lineno = yylineno;
285                 }
286         }
287
288         if (prev_prev_token == T_EOL && prev_token == T_WORD &&
289             (token == T_EQUAL || token == T_COLON_EQUAL || token == T_PLUS_EQUAL))
290                 BEGIN(ASSIGN_VAL);
291
292         prev_prev_token = prev_token;
293         prev_token = token;
294
295         return token;
296 }
297
298 static char *expand_token(const char *in, size_t n)
299 {
300         char *out;
301         int c;
302         char c2;
303         const char *rest, *end;
304
305         new_string();
306         append_string(in, n);
307
308         /* get the whole line because we do not know the end of token. */
309         while ((c = input()) != EOF) {
310                 if (c == '\n') {
311                         unput(c);
312                         break;
313                 }
314                 c2 = c;
315                 append_string(&c2, 1);
316         }
317
318         rest = text;
319         out = expand_one_token(&rest);
320
321         /* push back unused characters to the input stream */
322         end = rest + strlen(rest);
323         while (end > rest)
324                 unput(*--end);
325
326         free(text);
327
328         return out;
329 }
330
331 static void append_expanded_string(const char *str)
332 {
333         const char *end;
334         char *res;
335
336         str++;
337
338         res = expand_dollar(&str);
339
340         /* push back unused characters to the input stream */
341         end = str + strlen(str);
342         while (end > str)
343                 unput(*--end);
344
345         append_string(res, strlen(res));
346
347         free(res);
348 }
349
350 void zconf_starthelp(void)
351 {
352         new_string();
353         last_ts = first_ts = 0;
354         BEGIN(HELP);
355 }
356
357 static void zconf_endhelp(void)
358 {
359         yylval.string = text;
360         BEGIN(INITIAL);
361 }
362
363
364 /*
365  * Try to open specified file with following names:
366  * ./name
367  * $(srctree)/name
368  * The latter is used when srctree is separate from objtree
369  * when compiling the firmware.
370  * Return NULL if file is not found.
371  */
372 FILE *zconf_fopen(const char *name)
373 {
374         char *env, fullname[PATH_MAX+1];
375         FILE *f;
376
377         f = fopen(name, "r");
378         if (!f && name != NULL && name[0] != '/') {
379                 env = getenv(SRCTREE);
380                 if (env) {
381                         sprintf(fullname, "%s/%s", env, name);
382                         f = fopen(fullname, "r");
383                 }
384         }
385         return f;
386 }
387
388 void zconf_initscan(const char *name)
389 {
390         yyin = zconf_fopen(name);
391         if (!yyin) {
392                 fprintf(stderr, "can't find file %s\n", name);
393                 exit(1);
394         }
395
396         current_buf = xmalloc(sizeof(*current_buf));
397         memset(current_buf, 0, sizeof(*current_buf));
398
399         current_file = file_lookup(name);
400         yylineno = 1;
401 }
402
403 void zconf_nextfile(const char *name)
404 {
405         struct file *iter;
406         struct file *file = file_lookup(name);
407         struct buffer *buf = xmalloc(sizeof(*buf));
408         memset(buf, 0, sizeof(*buf));
409
410         current_buf->state = YY_CURRENT_BUFFER;
411         yyin = zconf_fopen(file->name);
412         if (!yyin) {
413                 fprintf(stderr, "%s:%d: can't open file \"%s\"\n",
414                         zconf_curname(), zconf_lineno(), file->name);
415                 exit(1);
416         }
417         yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
418         buf->parent = current_buf;
419         current_buf = buf;
420
421         current_file->lineno = yylineno;
422         file->parent = current_file;
423
424         for (iter = current_file; iter; iter = iter->parent) {
425                 if (!strcmp(iter->name, file->name)) {
426                         fprintf(stderr,
427                                 "Recursive inclusion detected.\n"
428                                 "Inclusion path:\n"
429                                 "  current file : %s\n", file->name);
430                         iter = file;
431                         do {
432                                 iter = iter->parent;
433                                 fprintf(stderr, "  included from: %s:%d\n",
434                                         iter->name, iter->lineno - 1);
435                         } while (strcmp(iter->name, file->name));
436                         exit(1);
437                 }
438         }
439
440         yylineno = 1;
441         current_file = file;
442 }
443
444 static void zconf_endfile(void)
445 {
446         struct buffer *parent;
447
448         current_file = current_file->parent;
449         if (current_file)
450                 yylineno = current_file->lineno;
451
452         parent = current_buf->parent;
453         if (parent) {
454                 fclose(yyin);
455                 yy_delete_buffer(YY_CURRENT_BUFFER);
456                 yy_switch_to_buffer(parent->state);
457         }
458         free(current_buf);
459         current_buf = parent;
460 }
461
462 int zconf_lineno(void)
463 {
464         return current_pos.lineno;
465 }
466
467 const char *zconf_curname(void)
468 {
469         return current_pos.file ? current_pos.file->name : "<none>";
470 }