Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6.git] / scripts / dtc / dtc-lexer.l
1 /*
2  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3  *
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18  *                                                                   USA
19  */
20
21 %option noyywrap noinput nounput yylineno
22
23 %x INCLUDE
24 %x BYTESTRING
25 %x PROPNODENAME
26 %s V1
27
28 PROPNODECHAR    [a-zA-Z0-9,._+*#?@-]
29 PATHCHAR        ({PROPNODECHAR}|[/])
30 LABEL           [a-zA-Z_][a-zA-Z0-9_]*
31 STRING          \"([^\\"]|\\.)*\"
32 WS              [[:space:]]
33 COMMENT         "/*"([^*]|\*+[^*/])*\*+"/"
34 LINECOMMENT     "//".*\n
35
36 %{
37 #include "dtc.h"
38 #include "srcpos.h"
39 #include "dtc-parser.tab.h"
40
41
42 /*#define LEXDEBUG      1*/
43
44 #ifdef LEXDEBUG
45 #define DPRINT(fmt, ...)        fprintf(stderr, fmt, ##__VA_ARGS__)
46 #else
47 #define DPRINT(fmt, ...)        do { } while (0)
48 #endif
49
50 static int dts_version; /* = 0 */
51
52 #define BEGIN_DEFAULT() if (dts_version == 0) { \
53                                 DPRINT("<INITIAL>\n"); \
54                                 BEGIN(INITIAL); \
55                         } else { \
56                                 DPRINT("<V1>\n"); \
57                                 BEGIN(V1); \
58                         }
59
60 static void push_input_file(const char *filename);
61 static int pop_input_file(void);
62 %}
63
64 %%
65 <*>"/include/"{WS}*{STRING} {
66                         char *name = strchr(yytext, '\"') + 1;
67                         yytext[yyleng-1] = '\0';
68                         push_input_file(name);
69                 }
70
71 <*><<EOF>>              {
72                         if (!pop_input_file()) {
73                                 yyterminate();
74                         }
75                 }
76
77 <*>{STRING}     {
78                         yylloc.file = srcpos_file;
79                         yylloc.first_line = yylineno;
80                         DPRINT("String: %s\n", yytext);
81                         yylval.data = data_copy_escape_string(yytext+1,
82                                         yyleng-2);
83                         yylloc.first_line = yylineno;
84                         return DT_STRING;
85                 }
86
87 <*>"/dts-v1/"   {
88                         yylloc.file = srcpos_file;
89                         yylloc.first_line = yylineno;
90                         DPRINT("Keyword: /dts-v1/\n");
91                         dts_version = 1;
92                         BEGIN_DEFAULT();
93                         return DT_V1;
94                 }
95
96 <*>"/memreserve/"       {
97                         yylloc.file = srcpos_file;
98                         yylloc.first_line = yylineno;
99                         DPRINT("Keyword: /memreserve/\n");
100                         BEGIN_DEFAULT();
101                         return DT_MEMRESERVE;
102                 }
103
104 <*>{LABEL}:     {
105                         yylloc.file = srcpos_file;
106                         yylloc.first_line = yylineno;
107                         DPRINT("Label: %s\n", yytext);
108                         yylval.labelref = strdup(yytext);
109                         yylval.labelref[yyleng-1] = '\0';
110                         return DT_LABEL;
111                 }
112
113 <INITIAL>[bodh]# {
114                         yylloc.file = srcpos_file;
115                         yylloc.first_line = yylineno;
116                         if (*yytext == 'b')
117                                 yylval.cbase = 2;
118                         else if (*yytext == 'o')
119                                 yylval.cbase = 8;
120                         else if (*yytext == 'd')
121                                 yylval.cbase = 10;
122                         else
123                                 yylval.cbase = 16;
124                         DPRINT("Base: %d\n", yylval.cbase);
125                         return DT_BASE;
126                 }
127
128 <INITIAL>[0-9a-fA-F]+   {
129                         yylloc.file = srcpos_file;
130                         yylloc.first_line = yylineno;
131                         yylval.literal = strdup(yytext);
132                         DPRINT("Literal: '%s'\n", yylval.literal);
133                         return DT_LEGACYLITERAL;
134                 }
135
136 <V1>[0-9]+|0[xX][0-9a-fA-F]+      {
137                         yylloc.file = srcpos_file;
138                         yylloc.first_line = yylineno;
139                         yylval.literal = strdup(yytext);
140                         DPRINT("Literal: '%s'\n", yylval.literal);
141                         return DT_LITERAL;
142                 }
143
144 \&{LABEL}       {       /* label reference */
145                         yylloc.file = srcpos_file;
146                         yylloc.first_line = yylineno;
147                         DPRINT("Ref: %s\n", yytext+1);
148                         yylval.labelref = strdup(yytext+1);
149                         return DT_REF;
150                 }
151
152 "&{/"{PATHCHAR}+\}      {       /* new-style path reference */
153                         yylloc.file = srcpos_file;
154                         yylloc.first_line = yylineno;
155                         yytext[yyleng-1] = '\0';
156                         DPRINT("Ref: %s\n", yytext+2);
157                         yylval.labelref = strdup(yytext+2);
158                         return DT_REF;
159                 }
160
161 <INITIAL>"&/"{PATHCHAR}+ {      /* old-style path reference */
162                         yylloc.file = srcpos_file;
163                         yylloc.first_line = yylineno;
164                         DPRINT("Ref: %s\n", yytext+1);
165                         yylval.labelref = strdup(yytext+1);
166                         return DT_REF;
167                 }
168
169 <BYTESTRING>[0-9a-fA-F]{2} {
170                         yylloc.file = srcpos_file;
171                         yylloc.first_line = yylineno;
172                         yylval.byte = strtol(yytext, NULL, 16);
173                         DPRINT("Byte: %02x\n", (int)yylval.byte);
174                         return DT_BYTE;
175                 }
176
177 <BYTESTRING>"]" {
178                         yylloc.file = srcpos_file;
179                         yylloc.first_line = yylineno;
180                         DPRINT("/BYTESTRING\n");
181                         BEGIN_DEFAULT();
182                         return ']';
183                 }
184
185 <PROPNODENAME>{PROPNODECHAR}+ {
186                         yylloc.file = srcpos_file;
187                         yylloc.first_line = yylineno;
188                         DPRINT("PropNodeName: %s\n", yytext);
189                         yylval.propnodename = strdup(yytext);
190                         BEGIN_DEFAULT();
191                         return DT_PROPNODENAME;
192                 }
193
194 "/incbin/"      {
195                         yylloc.file = srcpos_file;
196                         yylloc.first_line = yylineno;
197                         DPRINT("Binary Include\n");
198                         return DT_INCBIN;
199                 }
200
201 <*>{WS}+        /* eat whitespace */
202 <*>{COMMENT}+   /* eat C-style comments */
203 <*>{LINECOMMENT}+ /* eat C++-style comments */
204
205 <*>.            {
206                         yylloc.file = srcpos_file;
207                         yylloc.first_line = yylineno;
208                         DPRINT("Char: %c (\\x%02x)\n", yytext[0],
209                                 (unsigned)yytext[0]);
210                         if (yytext[0] == '[') {
211                                 DPRINT("<BYTESTRING>\n");
212                                 BEGIN(BYTESTRING);
213                         }
214                         if ((yytext[0] == '{')
215                             || (yytext[0] == ';')) {
216                                 DPRINT("<PROPNODENAME>\n");
217                                 BEGIN(PROPNODENAME);
218                         }
219                         return yytext[0];
220                 }
221
222 %%
223
224
225 /*
226  * Stack of nested include file contexts.
227  */
228
229 struct incl_file {
230         struct dtc_file *file;
231         YY_BUFFER_STATE yy_prev_buf;
232         int yy_prev_lineno;
233         struct incl_file *prev;
234 };
235
236 static struct incl_file *incl_file_stack;
237
238
239 /*
240  * Detect infinite include recursion.
241  */
242 #define MAX_INCLUDE_DEPTH       (100)
243
244 static int incl_depth = 0;
245
246
247 static void push_input_file(const char *filename)
248 {
249         struct incl_file *incl_file;
250         struct dtc_file *newfile;
251         struct search_path search, *searchptr = NULL;
252
253         assert(filename);
254
255         if (incl_depth++ >= MAX_INCLUDE_DEPTH)
256                 die("Includes nested too deeply");
257
258         if (srcpos_file) {
259                 search.dir = srcpos_file->dir;
260                 search.next = NULL;
261                 search.prev = NULL;
262                 searchptr = &search;
263         }
264
265         newfile = dtc_open_file(filename, searchptr);
266
267         incl_file = xmalloc(sizeof(struct incl_file));
268
269         /*
270          * Save current context.
271          */
272         incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
273         incl_file->yy_prev_lineno = yylineno;
274         incl_file->file = srcpos_file;
275         incl_file->prev = incl_file_stack;
276
277         incl_file_stack = incl_file;
278
279         /*
280          * Establish new context.
281          */
282         srcpos_file = newfile;
283         yylineno = 1;
284         yyin = newfile->file;
285         yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
286 }
287
288
289 static int pop_input_file(void)
290 {
291         struct incl_file *incl_file;
292
293         if (incl_file_stack == 0)
294                 return 0;
295
296         dtc_close_file(srcpos_file);
297
298         /*
299          * Pop.
300          */
301         --incl_depth;
302         incl_file = incl_file_stack;
303         incl_file_stack = incl_file->prev;
304
305         /*
306          * Recover old context.
307          */
308         yy_delete_buffer(YY_CURRENT_BUFFER);
309         yy_switch_to_buffer(incl_file->yy_prev_buf);
310         yylineno = incl_file->yy_prev_lineno;
311         srcpos_file = incl_file->file;
312         yyin = incl_file->file ? incl_file->file->file : NULL;
313
314         /*
315          * Free old state.
316          */
317         free(incl_file);
318
319         return 1;
320 }