xref: /openbmc/linux/scripts/dtc/dtc-lexer.l (revision 82ced6fd)
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 }
321