xref: /rk3399_rockchip-uboot/scripts/dtc/dtc-lexer.l (revision d02db1fd3842d09259fc50461d901cf2569f10cf)
1d18719a4STom Rini /*
2d18719a4STom Rini  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3d18719a4STom Rini  *
4d18719a4STom Rini  *
5d18719a4STom Rini  * This program is free software; you can redistribute it and/or
6d18719a4STom Rini  * modify it under the terms of the GNU General Public License as
7d18719a4STom Rini  * published by the Free Software Foundation; either version 2 of the
8d18719a4STom Rini  * License, or (at your option) any later version.
9d18719a4STom Rini  *
10d18719a4STom Rini  *  This program is distributed in the hope that it will be useful,
11d18719a4STom Rini  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12d18719a4STom Rini  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13d18719a4STom Rini  *  General Public License for more details.
14d18719a4STom Rini  *
15d18719a4STom Rini  *  You should have received a copy of the GNU General Public License
16d18719a4STom Rini  *  along with this program; if not, write to the Free Software
17d18719a4STom Rini  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18d18719a4STom Rini  *                                                                   USA
19d18719a4STom Rini  */
20d18719a4STom Rini 
21d18719a4STom Rini %option noyywrap nounput noinput never-interactive
22d18719a4STom Rini 
23d18719a4STom Rini %x BYTESTRING
24d18719a4STom Rini %x PROPNODENAME
25d18719a4STom Rini %s V1
26d18719a4STom Rini 
27d18719a4STom Rini PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
28d18719a4STom Rini PATHCHAR	({PROPNODECHAR}|[/])
29d18719a4STom Rini LABEL		[a-zA-Z_][a-zA-Z0-9_]*
30d18719a4STom Rini STRING		\"([^\\"]|\\.)*\"
31d18719a4STom Rini CHAR_LITERAL	'([^']|\\')*'
32d18719a4STom Rini WS		[[:space:]]
33d18719a4STom Rini COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
34d18719a4STom Rini LINECOMMENT	"//".*\n
35d18719a4STom Rini 
36d18719a4STom Rini %{
37d18719a4STom Rini #include "dtc.h"
38d18719a4STom Rini #include "srcpos.h"
39d18719a4STom Rini #include "dtc-parser.tab.h"
40d18719a4STom Rini 
41d18719a4STom Rini extern bool treesource_error;
42d18719a4STom Rini 
43d18719a4STom Rini /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
44d18719a4STom Rini #define	YY_USER_ACTION \
45d18719a4STom Rini 	{ \
46d18719a4STom Rini 		srcpos_update(&yylloc, yytext, yyleng); \
47d18719a4STom Rini 	}
48d18719a4STom Rini 
49d18719a4STom Rini /*#define LEXDEBUG	1*/
50d18719a4STom Rini 
51d18719a4STom Rini #ifdef LEXDEBUG
52d18719a4STom Rini #define DPRINT(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
53d18719a4STom Rini #else
54d18719a4STom Rini #define DPRINT(fmt, ...)	do { } while (0)
55d18719a4STom Rini #endif
56d18719a4STom Rini 
57d18719a4STom Rini static int dts_version = 1;
58d18719a4STom Rini 
59d18719a4STom Rini #define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \
60d18719a4STom Rini 				BEGIN(V1); \
61d18719a4STom Rini 
62d18719a4STom Rini static void push_input_file(const char *filename);
63d18719a4STom Rini static bool pop_input_file(void);
64*e23ffda2STom Rini static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
65d18719a4STom Rini 
66d18719a4STom Rini %}
67d18719a4STom Rini 
68d18719a4STom Rini %%
69d18719a4STom Rini <*>"/include/"{WS}*{STRING} {
70d18719a4STom Rini 			char *name = strchr(yytext, '\"') + 1;
71d18719a4STom Rini 			yytext[yyleng-1] = '\0';
72d18719a4STom Rini 			push_input_file(name);
73d18719a4STom Rini 		}
74d18719a4STom Rini 
75d18719a4STom Rini <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
76d18719a4STom Rini 			char *line, *fnstart, *fnend;
77d18719a4STom Rini 			struct data fn;
78d18719a4STom Rini 			/* skip text before line # */
79d18719a4STom Rini 			line = yytext;
80d18719a4STom Rini 			while (!isdigit((unsigned char)*line))
81d18719a4STom Rini 				line++;
82d18719a4STom Rini 
83d18719a4STom Rini 			/* regexp ensures that first and list "
84d18719a4STom Rini 			 * in the whole yytext are those at
85d18719a4STom Rini 			 * beginning and end of the filename string */
86d18719a4STom Rini 			fnstart = memchr(yytext, '"', yyleng);
87d18719a4STom Rini 			for (fnend = yytext + yyleng - 1;
88d18719a4STom Rini 			     *fnend != '"'; fnend--)
89d18719a4STom Rini 				;
90d18719a4STom Rini 			assert(fnstart && fnend && (fnend > fnstart));
91d18719a4STom Rini 
92d18719a4STom Rini 			fn = data_copy_escape_string(fnstart + 1,
93d18719a4STom Rini 						     fnend - fnstart - 1);
94d18719a4STom Rini 
95d18719a4STom Rini 			/* Don't allow nuls in filenames */
96d18719a4STom Rini 			if (memchr(fn.val, '\0', fn.len - 1))
97d18719a4STom Rini 				lexical_error("nul in line number directive");
98d18719a4STom Rini 
99d18719a4STom Rini 			/* -1 since #line is the number of the next line */
100d18719a4STom Rini 			srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
101d18719a4STom Rini 			data_free(fn);
102d18719a4STom Rini 		}
103d18719a4STom Rini 
104d18719a4STom Rini <*><<EOF>>		{
105d18719a4STom Rini 			if (!pop_input_file()) {
106d18719a4STom Rini 				yyterminate();
107d18719a4STom Rini 			}
108d18719a4STom Rini 		}
109d18719a4STom Rini 
110d18719a4STom Rini <*>{STRING}	{
111d18719a4STom Rini 			DPRINT("String: %s\n", yytext);
112d18719a4STom Rini 			yylval.data = data_copy_escape_string(yytext+1,
113d18719a4STom Rini 					yyleng-2);
114d18719a4STom Rini 			return DT_STRING;
115d18719a4STom Rini 		}
116d18719a4STom Rini 
117d18719a4STom Rini <*>"/dts-v1/"	{
118d18719a4STom Rini 			DPRINT("Keyword: /dts-v1/\n");
119d18719a4STom Rini 			dts_version = 1;
120d18719a4STom Rini 			BEGIN_DEFAULT();
121d18719a4STom Rini 			return DT_V1;
122d18719a4STom Rini 		}
123d18719a4STom Rini 
124d18719a4STom Rini <*>"/plugin/"	{
125d18719a4STom Rini 			DPRINT("Keyword: /plugin/\n");
126d18719a4STom Rini 			return DT_PLUGIN;
127d18719a4STom Rini 		}
128d18719a4STom Rini 
129d18719a4STom Rini <*>"/memreserve/"	{
130d18719a4STom Rini 			DPRINT("Keyword: /memreserve/\n");
131d18719a4STom Rini 			BEGIN_DEFAULT();
132d18719a4STom Rini 			return DT_MEMRESERVE;
133d18719a4STom Rini 		}
134d18719a4STom Rini 
135d18719a4STom Rini <*>"/bits/"	{
136d18719a4STom Rini 			DPRINT("Keyword: /bits/\n");
137d18719a4STom Rini 			BEGIN_DEFAULT();
138d18719a4STom Rini 			return DT_BITS;
139d18719a4STom Rini 		}
140d18719a4STom Rini 
141d18719a4STom Rini <*>"/delete-property/"	{
142d18719a4STom Rini 			DPRINT("Keyword: /delete-property/\n");
143d18719a4STom Rini 			DPRINT("<PROPNODENAME>\n");
144d18719a4STom Rini 			BEGIN(PROPNODENAME);
145d18719a4STom Rini 			return DT_DEL_PROP;
146d18719a4STom Rini 		}
147d18719a4STom Rini 
148d18719a4STom Rini <*>"/delete-node/"	{
149d18719a4STom Rini 			DPRINT("Keyword: /delete-node/\n");
150d18719a4STom Rini 			DPRINT("<PROPNODENAME>\n");
151d18719a4STom Rini 			BEGIN(PROPNODENAME);
152d18719a4STom Rini 			return DT_DEL_NODE;
153d18719a4STom Rini 		}
154d18719a4STom Rini 
155d18719a4STom Rini <*>{LABEL}:	{
156d18719a4STom Rini 			DPRINT("Label: %s\n", yytext);
157d18719a4STom Rini 			yylval.labelref = xstrdup(yytext);
158d18719a4STom Rini 			yylval.labelref[yyleng-1] = '\0';
159d18719a4STom Rini 			return DT_LABEL;
160d18719a4STom Rini 		}
161d18719a4STom Rini 
162d18719a4STom Rini <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
163d18719a4STom Rini 			char *e;
164d18719a4STom Rini 			DPRINT("Integer Literal: '%s'\n", yytext);
165d18719a4STom Rini 
166d18719a4STom Rini 			errno = 0;
167d18719a4STom Rini 			yylval.integer = strtoull(yytext, &e, 0);
168d18719a4STom Rini 
169d18719a4STom Rini 			if (*e && e[strspn(e, "UL")]) {
170d18719a4STom Rini 				lexical_error("Bad integer literal '%s'",
171d18719a4STom Rini 					      yytext);
172d18719a4STom Rini 			}
173d18719a4STom Rini 
174d18719a4STom Rini 			if (errno == ERANGE)
175d18719a4STom Rini 				lexical_error("Integer literal '%s' out of range",
176d18719a4STom Rini 					      yytext);
177d18719a4STom Rini 			else
178d18719a4STom Rini 				/* ERANGE is the only strtoull error triggerable
179d18719a4STom Rini 				 *  by strings matching the pattern */
180d18719a4STom Rini 				assert(errno == 0);
181d18719a4STom Rini 			return DT_LITERAL;
182d18719a4STom Rini 		}
183d18719a4STom Rini 
184d18719a4STom Rini <*>{CHAR_LITERAL}	{
185d18719a4STom Rini 			struct data d;
186d18719a4STom Rini 			DPRINT("Character literal: %s\n", yytext);
187d18719a4STom Rini 
188d18719a4STom Rini 			d = data_copy_escape_string(yytext+1, yyleng-2);
189d18719a4STom Rini 			if (d.len == 1) {
190d18719a4STom Rini 				lexical_error("Empty character literal");
191d18719a4STom Rini 				yylval.integer = 0;
192d18719a4STom Rini 			} else {
193d18719a4STom Rini 				yylval.integer = (unsigned char)d.val[0];
194d18719a4STom Rini 
195d18719a4STom Rini 				if (d.len > 2)
196d18719a4STom Rini 					lexical_error("Character literal has %d"
197d18719a4STom Rini 						      " characters instead of 1",
198d18719a4STom Rini 						      d.len - 1);
199d18719a4STom Rini 			}
200d18719a4STom Rini 
201d18719a4STom Rini 			data_free(d);
202d18719a4STom Rini 			return DT_CHAR_LITERAL;
203d18719a4STom Rini 		}
204d18719a4STom Rini 
205d18719a4STom Rini <*>\&{LABEL}	{	/* label reference */
206d18719a4STom Rini 			DPRINT("Ref: %s\n", yytext+1);
207d18719a4STom Rini 			yylval.labelref = xstrdup(yytext+1);
208d18719a4STom Rini 			return DT_REF;
209d18719a4STom Rini 		}
210d18719a4STom Rini 
211d18719a4STom Rini <*>"&{/"{PATHCHAR}*\}	{	/* new-style path reference */
212d18719a4STom Rini 			yytext[yyleng-1] = '\0';
213d18719a4STom Rini 			DPRINT("Ref: %s\n", yytext+2);
214d18719a4STom Rini 			yylval.labelref = xstrdup(yytext+2);
215d18719a4STom Rini 			return DT_REF;
216d18719a4STom Rini 		}
217d18719a4STom Rini 
218d18719a4STom Rini <BYTESTRING>[0-9a-fA-F]{2} {
219d18719a4STom Rini 			yylval.byte = strtol(yytext, NULL, 16);
220d18719a4STom Rini 			DPRINT("Byte: %02x\n", (int)yylval.byte);
221d18719a4STom Rini 			return DT_BYTE;
222d18719a4STom Rini 		}
223d18719a4STom Rini 
224d18719a4STom Rini <BYTESTRING>"]"	{
225d18719a4STom Rini 			DPRINT("/BYTESTRING\n");
226d18719a4STom Rini 			BEGIN_DEFAULT();
227d18719a4STom Rini 			return ']';
228d18719a4STom Rini 		}
229d18719a4STom Rini 
230d18719a4STom Rini <PROPNODENAME>\\?{PROPNODECHAR}+ {
231d18719a4STom Rini 			DPRINT("PropNodeName: %s\n", yytext);
232d18719a4STom Rini 			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
233d18719a4STom Rini 							yytext + 1 : yytext);
234d18719a4STom Rini 			BEGIN_DEFAULT();
235d18719a4STom Rini 			return DT_PROPNODENAME;
236d18719a4STom Rini 		}
237d18719a4STom Rini 
238d18719a4STom Rini "/incbin/"	{
239d18719a4STom Rini 			DPRINT("Binary Include\n");
240d18719a4STom Rini 			return DT_INCBIN;
241d18719a4STom Rini 		}
242d18719a4STom Rini 
243d18719a4STom Rini <*>{WS}+	/* eat whitespace */
244d18719a4STom Rini <*>{COMMENT}+	/* eat C-style comments */
245d18719a4STom Rini <*>{LINECOMMENT}+ /* eat C++-style comments */
246d18719a4STom Rini 
247d18719a4STom Rini <*>"<<"		{ return DT_LSHIFT; };
248d18719a4STom Rini <*>">>"		{ return DT_RSHIFT; };
249d18719a4STom Rini <*>"<="		{ return DT_LE; };
250d18719a4STom Rini <*>">="		{ return DT_GE; };
251d18719a4STom Rini <*>"=="		{ return DT_EQ; };
252d18719a4STom Rini <*>"!="		{ return DT_NE; };
253d18719a4STom Rini <*>"&&"		{ return DT_AND; };
254d18719a4STom Rini <*>"||"		{ return DT_OR; };
255d18719a4STom Rini 
256d18719a4STom Rini <*>.		{
257d18719a4STom Rini 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
258d18719a4STom Rini 				(unsigned)yytext[0]);
259d18719a4STom Rini 			if (yytext[0] == '[') {
260d18719a4STom Rini 				DPRINT("<BYTESTRING>\n");
261d18719a4STom Rini 				BEGIN(BYTESTRING);
262d18719a4STom Rini 			}
263d18719a4STom Rini 			if ((yytext[0] == '{')
264d18719a4STom Rini 			    || (yytext[0] == ';')) {
265d18719a4STom Rini 				DPRINT("<PROPNODENAME>\n");
266d18719a4STom Rini 				BEGIN(PROPNODENAME);
267d18719a4STom Rini 			}
268d18719a4STom Rini 			return yytext[0];
269d18719a4STom Rini 		}
270d18719a4STom Rini 
271d18719a4STom Rini %%
272d18719a4STom Rini 
273d18719a4STom Rini static void push_input_file(const char *filename)
274d18719a4STom Rini {
275d18719a4STom Rini 	assert(filename);
276d18719a4STom Rini 
277d18719a4STom Rini 	srcfile_push(filename);
278d18719a4STom Rini 
279d18719a4STom Rini 	yyin = current_srcfile->f;
280d18719a4STom Rini 
281d18719a4STom Rini 	yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
282d18719a4STom Rini }
283d18719a4STom Rini 
284d18719a4STom Rini 
285d18719a4STom Rini static bool pop_input_file(void)
286d18719a4STom Rini {
287d18719a4STom Rini 	if (srcfile_pop() == 0)
288d18719a4STom Rini 		return false;
289d18719a4STom Rini 
290d18719a4STom Rini 	yypop_buffer_state();
291d18719a4STom Rini 	yyin = current_srcfile->f;
292d18719a4STom Rini 
293d18719a4STom Rini 	return true;
294d18719a4STom Rini }
295d18719a4STom Rini 
296d18719a4STom Rini static void lexical_error(const char *fmt, ...)
297d18719a4STom Rini {
298d18719a4STom Rini 	va_list ap;
299d18719a4STom Rini 
300d18719a4STom Rini 	va_start(ap, fmt);
301d18719a4STom Rini 	srcpos_verror(&yylloc, "Lexical error", fmt, ap);
302d18719a4STom Rini 	va_end(ap);
303d18719a4STom Rini 
304d18719a4STom Rini 	treesource_error = true;
305d18719a4STom Rini }
306