|
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 STRING \"([^\\"]|\\.)*\" |
|
32 WS [[:space:]] |
|
33 COMMENT "/*"([^*]|\*+[^*/])*\*+"/" |
|
34 LINECOMMENT "//".*\n |
|
35 |
|
36 %{ |
|
37 #include "dtc.h" |
|
38 #include "srcpos.h" |
|
39 #include "dtc-parser.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 } |