Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[pandora-kernel.git] / arch / powerpc / boot / dtc-src / 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 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
32 %{
33 #include "dtc.h"
34 #include "srcpos.h"
35 #include "dtc-parser.tab.h"
36
37
38 /*#define LEXDEBUG      1*/
39
40 #ifdef LEXDEBUG
41 #define DPRINT(fmt, ...)        fprintf(stderr, fmt, ##__VA_ARGS__)
42 #else
43 #define DPRINT(fmt, ...)        do { } while (0)
44 #endif
45
46 static int dts_version; /* = 0 */
47
48 #define BEGIN_DEFAULT() if (dts_version == 0) { \
49                                 DPRINT("<INITIAL>\n"); \
50                                 BEGIN(INITIAL); \
51                         } else { \
52                                 DPRINT("<V1>\n"); \
53                                 BEGIN(V1); \
54                         }
55 %}
56
57 %%
58 <*>"/include/"          BEGIN(INCLUDE);
59
60 <INCLUDE>\"[^"\n]*\"    {
61                         yytext[strlen(yytext) - 1] = 0;
62                         if (!push_input_file(yytext + 1)) {
63                                 /* Some unrecoverable error.*/
64                                 exit(1);
65                         }
66                         BEGIN_DEFAULT();
67                 }
68
69
70 <*><<EOF>>              {
71                         if (!pop_input_file()) {
72                                 yyterminate();
73                         }
74                 }
75
76 <*>\"([^\\"]|\\.)*\"    {
77                         yylloc.filenum = srcpos_filenum;
78                         yylloc.first_line = yylineno;
79                         DPRINT("String: %s\n", yytext);
80                         yylval.data = data_copy_escape_string(yytext+1,
81                                         yyleng-2);
82                         yylloc.first_line = yylineno;
83                         return DT_STRING;
84                 }
85
86 <*>"/dts-v1/"   {
87                         yylloc.filenum = srcpos_filenum;
88                         yylloc.first_line = yylineno;
89                         DPRINT("Keyword: /dts-v1/\n");
90                         dts_version = 1;
91                         BEGIN_DEFAULT();
92                         return DT_V1;
93                 }
94
95 <*>"/memreserve/"       {
96                         yylloc.filenum = srcpos_filenum;
97                         yylloc.first_line = yylineno;
98                         DPRINT("Keyword: /memreserve/\n");
99                         BEGIN_DEFAULT();
100                         return DT_MEMRESERVE;
101                 }
102
103 <*>{LABEL}:     {
104                         yylloc.filenum = srcpos_filenum;
105                         yylloc.first_line = yylineno;
106                         DPRINT("Label: %s\n", yytext);
107                         yylval.labelref = strdup(yytext);
108                         yylval.labelref[yyleng-1] = '\0';
109                         return DT_LABEL;
110                 }
111
112 <INITIAL>[bodh]# {
113                         yylloc.filenum = srcpos_filenum;
114                         yylloc.first_line = yylineno;
115                         if (*yytext == 'b')
116                                 yylval.cbase = 2;
117                         else if (*yytext == 'o')
118                                 yylval.cbase = 8;
119                         else if (*yytext == 'd')
120                                 yylval.cbase = 10;
121                         else
122                                 yylval.cbase = 16;
123                         DPRINT("Base: %d\n", yylval.cbase);
124                         return DT_BASE;
125                 }
126
127 <INITIAL>[0-9a-fA-F]+   {
128                         yylloc.filenum = srcpos_filenum;
129                         yylloc.first_line = yylineno;
130                         yylval.literal = strdup(yytext);
131                         DPRINT("Literal: '%s'\n", yylval.literal);
132                         return DT_LEGACYLITERAL;
133                 }
134
135 <V1>[0-9]+|0[xX][0-9a-fA-F]+      {
136                         yylloc.filenum = srcpos_filenum;
137                         yylloc.first_line = yylineno;
138                         yylval.literal = strdup(yytext);
139                         DPRINT("Literal: '%s'\n", yylval.literal);
140                         return DT_LITERAL;
141                 }
142
143 \&{LABEL}       {       /* label reference */
144                         yylloc.filenum = srcpos_filenum;
145                         yylloc.first_line = yylineno;
146                         DPRINT("Ref: %s\n", yytext+1);
147                         yylval.labelref = strdup(yytext+1);
148                         return DT_REF;
149                 }
150
151 "&{/"{PATHCHAR}+\}      {       /* new-style path reference */
152                         yylloc.filenum = srcpos_filenum;
153                         yylloc.first_line = yylineno;
154                         yytext[yyleng-1] = '\0';
155                         DPRINT("Ref: %s\n", yytext+2);
156                         yylval.labelref = strdup(yytext+2);
157                         return DT_REF;
158                 }
159
160 <INITIAL>"&/"{PATHCHAR}+ {      /* old-style path reference */
161                         yylloc.filenum = srcpos_filenum;
162                         yylloc.first_line = yylineno;
163                         DPRINT("Ref: %s\n", yytext+1);
164                         yylval.labelref = strdup(yytext+1);
165                         return DT_REF;
166                 }
167
168 <BYTESTRING>[0-9a-fA-F]{2} {
169                         yylloc.filenum = srcpos_filenum;
170                         yylloc.first_line = yylineno;
171                         yylval.byte = strtol(yytext, NULL, 16);
172                         DPRINT("Byte: %02x\n", (int)yylval.byte);
173                         return DT_BYTE;
174                 }
175
176 <BYTESTRING>"]" {
177                         yylloc.filenum = srcpos_filenum;
178                         yylloc.first_line = yylineno;
179                         DPRINT("/BYTESTRING\n");
180                         BEGIN_DEFAULT();
181                         return ']';
182                 }
183
184 <PROPNODENAME>{PROPNODECHAR}+ {
185                         yylloc.filenum = srcpos_filenum;
186                         yylloc.first_line = yylineno;
187                         DPRINT("PropNodeName: %s\n", yytext);
188                         yylval.propnodename = strdup(yytext);
189                         BEGIN_DEFAULT();
190                         return DT_PROPNODENAME;
191                 }
192
193
194 <*>[[:space:]]+ /* eat whitespace */
195
196 <*>"/*"([^*]|\*+[^*/])*\*+"/"   {
197                         yylloc.filenum = srcpos_filenum;
198                         yylloc.first_line = yylineno;
199                         DPRINT("Comment: %s\n", yytext);
200                         /* eat comments */
201                 }
202
203 <*>"//".*\n     /* eat line comments */
204
205 <*>.            {
206                         yylloc.filenum = srcpos_filenum;
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         int filenum;
231         FILE *file;
232         YY_BUFFER_STATE yy_prev_buf;
233         int yy_prev_lineno;
234         struct incl_file *prev;
235 };
236
237 struct incl_file *incl_file_stack;
238
239
240 /*
241  * Detect infinite include recursion.
242  */
243 #define MAX_INCLUDE_DEPTH       (100)
244
245 static int incl_depth = 0;
246
247
248 int push_input_file(const char *filename)
249 {
250         FILE *f;
251         struct incl_file *incl_file;
252
253         if (!filename) {
254                 yyerror("No include file name given.");
255                 return 0;
256         }
257
258         if (incl_depth++ >= MAX_INCLUDE_DEPTH) {
259                 yyerror("Includes nested too deeply");
260                 return 0;
261         }
262
263         f = dtc_open_file(filename);
264
265         incl_file = malloc(sizeof(struct incl_file));
266         if (!incl_file) {
267                 yyerror("Can not allocate include file space.");
268                 return 0;
269         }
270
271         /*
272          * Save current context.
273          */
274         incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
275         incl_file->yy_prev_lineno = yylineno;
276         incl_file->filenum = srcpos_filenum;
277         incl_file->file = yyin;
278         incl_file->prev = incl_file_stack;
279
280         incl_file_stack = incl_file;
281
282         /*
283          * Establish new context.
284          */
285         srcpos_filenum = lookup_file_name(filename, 0);
286         yylineno = 1;
287         yyin = f;
288         yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
289
290         return 1;
291 }
292
293
294 int pop_input_file(void)
295 {
296         struct incl_file *incl_file;
297
298         if (incl_file_stack == 0)
299                 return 0;
300
301         fclose(yyin);
302
303         /*
304          * Pop.
305          */
306         --incl_depth;
307         incl_file = incl_file_stack;
308         incl_file_stack = incl_file->prev;
309
310         /*
311          * Recover old context.
312          */
313         yy_delete_buffer(YY_CURRENT_BUFFER);
314         yy_switch_to_buffer(incl_file->yy_prev_buf);
315         yylineno = incl_file->yy_prev_lineno;
316         srcpos_filenum = incl_file->filenum;
317         yyin = incl_file->file;
318
319         /*
320          * Free old state.
321          */
322         free(incl_file);
323
324         if (YY_CURRENT_BUFFER == 0)
325                 return 0;
326
327         return 1;
328 }