dtc-lexer.l revision 204489
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 noinput yylineno
22
23%x INCLUDE
24%x BYTESTRING
25%x PROPNODENAME
26%s V1
27
28PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
29PATHCHAR	({PROPNODECHAR}|[/])
30LABEL		[a-zA-Z_][a-zA-Z0-9_]*
31STRING		\"([^\\"]|\\.)*\"
32WS		[[:space:]]
33COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
34LINECOMMENT	"//".*\n
35
36%{
37#include "dtc.h"
38#include "srcpos.h"
39#include "dtc-parser.tab.h"
40
41YYLTYPE yylloc;
42
43#define	YY_USER_ACTION \
44	{ \
45		yylloc.file = srcpos_file; \
46		yylloc.first_line = yylineno; \
47	}
48
49/*#define LEXDEBUG	1*/
50
51#ifdef LEXDEBUG
52#define DPRINT(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
53#else
54#define DPRINT(fmt, ...)	do { } while (0)
55#endif
56
57static int dts_version = 1;
58
59#define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \
60				BEGIN(V1); \
61
62static void push_input_file(const char *filename);
63static int pop_input_file(void);
64%}
65
66%%
67<*>"/include/"{WS}*{STRING} {
68			char *name = strchr(yytext, '\"') + 1;
69			yytext[yyleng-1] = '\0';
70			push_input_file(name);
71		}
72
73<*><<EOF>>		{
74			if (!pop_input_file()) {
75				yyterminate();
76			}
77		}
78
79<*>{STRING}	{
80			DPRINT("String: %s\n", yytext);
81			yylval.data = data_copy_escape_string(yytext+1,
82					yyleng-2);
83			return DT_STRING;
84		}
85
86<*>"/dts-v1/"	{
87			DPRINT("Keyword: /dts-v1/\n");
88			dts_version = 1;
89			BEGIN_DEFAULT();
90			return DT_V1;
91		}
92
93<*>"/memreserve/"	{
94			DPRINT("Keyword: /memreserve/\n");
95			BEGIN_DEFAULT();
96			return DT_MEMRESERVE;
97		}
98
99<*>{LABEL}:	{
100			DPRINT("Label: %s\n", yytext);
101			yylval.labelref = xstrdup(yytext);
102			yylval.labelref[yyleng-1] = '\0';
103			return DT_LABEL;
104		}
105
106<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
107			yylval.literal = xstrdup(yytext);
108			DPRINT("Literal: '%s'\n", yylval.literal);
109			return DT_LITERAL;
110		}
111
112\&{LABEL}	{	/* label reference */
113			DPRINT("Ref: %s\n", yytext+1);
114			yylval.labelref = xstrdup(yytext+1);
115			return DT_REF;
116		}
117
118"&{/"{PATHCHAR}+\}	{	/* new-style path reference */
119			yytext[yyleng-1] = '\0';
120			DPRINT("Ref: %s\n", yytext+2);
121			yylval.labelref = xstrdup(yytext+2);
122			return DT_REF;
123		}
124
125<BYTESTRING>[0-9a-fA-F]{2} {
126			yylval.byte = strtol(yytext, NULL, 16);
127			DPRINT("Byte: %02x\n", (int)yylval.byte);
128			return DT_BYTE;
129		}
130
131<BYTESTRING>"]"	{
132			DPRINT("/BYTESTRING\n");
133			BEGIN_DEFAULT();
134			return ']';
135		}
136
137<PROPNODENAME>{PROPNODECHAR}+ {
138			DPRINT("PropNodeName: %s\n", yytext);
139			yylval.propnodename = xstrdup(yytext);
140			BEGIN_DEFAULT();
141			return DT_PROPNODENAME;
142		}
143
144"/incbin/"	{
145			DPRINT("Binary Include\n");
146			return DT_INCBIN;
147		}
148
149<*>{WS}+	/* eat whitespace */
150<*>{COMMENT}+	/* eat C-style comments */
151<*>{LINECOMMENT}+ /* eat C++-style comments */
152
153<*>.		{
154			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
155				(unsigned)yytext[0]);
156			if (yytext[0] == '[') {
157				DPRINT("<BYTESTRING>\n");
158				BEGIN(BYTESTRING);
159			}
160			if ((yytext[0] == '{')
161			    || (yytext[0] == ';')) {
162				DPRINT("<PROPNODENAME>\n");
163				BEGIN(PROPNODENAME);
164			}
165			return yytext[0];
166		}
167
168%%
169
170
171/*
172 * Stack of nested include file contexts.
173 */
174
175struct incl_file {
176	struct dtc_file *file;
177	YY_BUFFER_STATE yy_prev_buf;
178	int yy_prev_lineno;
179	struct incl_file *prev;
180};
181
182static struct incl_file *incl_file_stack;
183
184
185/*
186 * Detect infinite include recursion.
187 */
188#define MAX_INCLUDE_DEPTH	(100)
189
190static int incl_depth = 0;
191
192
193static void push_input_file(const char *filename)
194{
195	struct incl_file *incl_file;
196	struct dtc_file *newfile;
197	struct search_path search, *searchptr = NULL;
198
199	assert(filename);
200
201	if (incl_depth++ >= MAX_INCLUDE_DEPTH)
202		die("Includes nested too deeply");
203
204	if (srcpos_file) {
205		search.dir = srcpos_file->dir;
206		search.next = NULL;
207		search.prev = NULL;
208		searchptr = &search;
209	}
210
211	newfile = dtc_open_file(filename, searchptr);
212
213	incl_file = xmalloc(sizeof(struct incl_file));
214
215	/*
216	 * Save current context.
217	 */
218	incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
219	incl_file->yy_prev_lineno = yylineno;
220	incl_file->file = srcpos_file;
221	incl_file->prev = incl_file_stack;
222
223	incl_file_stack = incl_file;
224
225	/*
226	 * Establish new context.
227	 */
228	srcpos_file = newfile;
229	yylineno = 1;
230	yyin = newfile->file;
231	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
232}
233
234
235static int pop_input_file(void)
236{
237	struct incl_file *incl_file;
238
239	if (incl_file_stack == 0)
240		return 0;
241
242	dtc_close_file(srcpos_file);
243
244	/*
245	 * Pop.
246	 */
247	--incl_depth;
248	incl_file = incl_file_stack;
249	incl_file_stack = incl_file->prev;
250
251	/*
252	 * Recover old context.
253	 */
254	yy_delete_buffer(YY_CURRENT_BUFFER);
255	yy_switch_to_buffer(incl_file->yy_prev_buf);
256	yylineno = incl_file->yy_prev_lineno;
257	srcpos_file = incl_file->file;
258	yyin = incl_file->file ? incl_file->file->file : NULL;
259
260	/*
261	 * Free old state.
262	 */
263	free(incl_file);
264
265	return 1;
266}
267