diff options
Diffstat (limited to 'scripts/dtc/dtc-lexer.l')
-rw-r--r-- | scripts/dtc/dtc-lexer.l | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l new file mode 100644 index 000000000000..44dbfd3f0976 --- /dev/null +++ b/scripts/dtc/dtc-lexer.l | |||
@@ -0,0 +1,320 @@ | |||
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.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 | } | ||