xref: /rk3399_rockchip-uboot/scripts/dtc/dtc-lexer.l (revision e23ffda262942d719738f47025958a7fcb5a9fb6)
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 YYLTYPE yylloc;
42d18719a4STom Rini extern bool treesource_error;
43d18719a4STom Rini 
44d18719a4STom Rini /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
45d18719a4STom Rini #define	YY_USER_ACTION \
46d18719a4STom Rini 	{ \
47d18719a4STom Rini 		srcpos_update(&yylloc, yytext, yyleng); \
48d18719a4STom Rini 	}
49d18719a4STom Rini 
50d18719a4STom Rini /*#define LEXDEBUG	1*/
51d18719a4STom Rini 
52d18719a4STom Rini #ifdef LEXDEBUG
53d18719a4STom Rini #define DPRINT(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
54d18719a4STom Rini #else
55d18719a4STom Rini #define DPRINT(fmt, ...)	do { } while (0)
56d18719a4STom Rini #endif
57d18719a4STom Rini 
58d18719a4STom Rini static int dts_version = 1;
59d18719a4STom Rini 
60d18719a4STom Rini #define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \
61d18719a4STom Rini 				BEGIN(V1); \
62d18719a4STom Rini 
63d18719a4STom Rini static void push_input_file(const char *filename);
64d18719a4STom Rini static bool pop_input_file(void);
65*e23ffda2STom Rini static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
66d18719a4STom Rini 
67d18719a4STom Rini %}
68d18719a4STom Rini 
69d18719a4STom Rini %%
70d18719a4STom Rini <*>"/include/"{WS}*{STRING} {
71d18719a4STom Rini 			char *name = strchr(yytext, '\"') + 1;
72d18719a4STom Rini 			yytext[yyleng-1] = '\0';
73d18719a4STom Rini 			push_input_file(name);
74d18719a4STom Rini 		}
75d18719a4STom Rini 
76d18719a4STom Rini <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
77d18719a4STom Rini 			char *line, *fnstart, *fnend;
78d18719a4STom Rini 			struct data fn;
79d18719a4STom Rini 			/* skip text before line # */
80d18719a4STom Rini 			line = yytext;
81d18719a4STom Rini 			while (!isdigit((unsigned char)*line))
82d18719a4STom Rini 				line++;
83d18719a4STom Rini 
84d18719a4STom Rini 			/* regexp ensures that first and list "
85d18719a4STom Rini 			 * in the whole yytext are those at
86d18719a4STom Rini 			 * beginning and end of the filename string */
87d18719a4STom Rini 			fnstart = memchr(yytext, '"', yyleng);
88d18719a4STom Rini 			for (fnend = yytext + yyleng - 1;
89d18719a4STom Rini 			     *fnend != '"'; fnend--)
90d18719a4STom Rini 				;
91d18719a4STom Rini 			assert(fnstart && fnend && (fnend > fnstart));
92d18719a4STom Rini 
93d18719a4STom Rini 			fn = data_copy_escape_string(fnstart + 1,
94d18719a4STom Rini 						     fnend - fnstart - 1);
95d18719a4STom Rini 
96d18719a4STom Rini 			/* Don't allow nuls in filenames */
97d18719a4STom Rini 			if (memchr(fn.val, '\0', fn.len - 1))
98d18719a4STom Rini 				lexical_error("nul in line number directive");
99d18719a4STom Rini 
100d18719a4STom Rini 			/* -1 since #line is the number of the next line */
101d18719a4STom Rini 			srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
102d18719a4STom Rini 			data_free(fn);
103d18719a4STom Rini 		}
104d18719a4STom Rini 
105d18719a4STom Rini <*><<EOF>>		{
106d18719a4STom Rini 			if (!pop_input_file()) {
107d18719a4STom Rini 				yyterminate();
108d18719a4STom Rini 			}
109d18719a4STom Rini 		}
110d18719a4STom Rini 
111d18719a4STom Rini <*>{STRING}	{
112d18719a4STom Rini 			DPRINT("String: %s\n", yytext);
113d18719a4STom Rini 			yylval.data = data_copy_escape_string(yytext+1,
114d18719a4STom Rini 					yyleng-2);
115d18719a4STom Rini 			return DT_STRING;
116d18719a4STom Rini 		}
117d18719a4STom Rini 
118d18719a4STom Rini <*>"/dts-v1/"	{
119d18719a4STom Rini 			DPRINT("Keyword: /dts-v1/\n");
120d18719a4STom Rini 			dts_version = 1;
121d18719a4STom Rini 			BEGIN_DEFAULT();
122d18719a4STom Rini 			return DT_V1;
123d18719a4STom Rini 		}
124d18719a4STom Rini 
125d18719a4STom Rini <*>"/plugin/"	{
126d18719a4STom Rini 			DPRINT("Keyword: /plugin/\n");
127d18719a4STom Rini 			return DT_PLUGIN;
128d18719a4STom Rini 		}
129d18719a4STom Rini 
130d18719a4STom Rini <*>"/memreserve/"	{
131d18719a4STom Rini 			DPRINT("Keyword: /memreserve/\n");
132d18719a4STom Rini 			BEGIN_DEFAULT();
133d18719a4STom Rini 			return DT_MEMRESERVE;
134d18719a4STom Rini 		}
135d18719a4STom Rini 
136d18719a4STom Rini <*>"/bits/"	{
137d18719a4STom Rini 			DPRINT("Keyword: /bits/\n");
138d18719a4STom Rini 			BEGIN_DEFAULT();
139d18719a4STom Rini 			return DT_BITS;
140d18719a4STom Rini 		}
141d18719a4STom Rini 
142d18719a4STom Rini <*>"/delete-property/"	{
143d18719a4STom Rini 			DPRINT("Keyword: /delete-property/\n");
144d18719a4STom Rini 			DPRINT("<PROPNODENAME>\n");
145d18719a4STom Rini 			BEGIN(PROPNODENAME);
146d18719a4STom Rini 			return DT_DEL_PROP;
147d18719a4STom Rini 		}
148d18719a4STom Rini 
149d18719a4STom Rini <*>"/delete-node/"	{
150d18719a4STom Rini 			DPRINT("Keyword: /delete-node/\n");
151d18719a4STom Rini 			DPRINT("<PROPNODENAME>\n");
152d18719a4STom Rini 			BEGIN(PROPNODENAME);
153d18719a4STom Rini 			return DT_DEL_NODE;
154d18719a4STom Rini 		}
155d18719a4STom Rini 
156d18719a4STom Rini <*>{LABEL}:	{
157d18719a4STom Rini 			DPRINT("Label: %s\n", yytext);
158d18719a4STom Rini 			yylval.labelref = xstrdup(yytext);
159d18719a4STom Rini 			yylval.labelref[yyleng-1] = '\0';
160d18719a4STom Rini 			return DT_LABEL;
161d18719a4STom Rini 		}
162d18719a4STom Rini 
163d18719a4STom Rini <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
164d18719a4STom Rini 			char *e;
165d18719a4STom Rini 			DPRINT("Integer Literal: '%s'\n", yytext);
166d18719a4STom Rini 
167d18719a4STom Rini 			errno = 0;
168d18719a4STom Rini 			yylval.integer = strtoull(yytext, &e, 0);
169d18719a4STom Rini 
170d18719a4STom Rini 			if (*e && e[strspn(e, "UL")]) {
171d18719a4STom Rini 				lexical_error("Bad integer literal '%s'",
172d18719a4STom Rini 					      yytext);
173d18719a4STom Rini 			}
174d18719a4STom Rini 
175d18719a4STom Rini 			if (errno == ERANGE)
176d18719a4STom Rini 				lexical_error("Integer literal '%s' out of range",
177d18719a4STom Rini 					      yytext);
178d18719a4STom Rini 			else
179d18719a4STom Rini 				/* ERANGE is the only strtoull error triggerable
180d18719a4STom Rini 				 *  by strings matching the pattern */
181d18719a4STom Rini 				assert(errno == 0);
182d18719a4STom Rini 			return DT_LITERAL;
183d18719a4STom Rini 		}
184d18719a4STom Rini 
185d18719a4STom Rini <*>{CHAR_LITERAL}	{
186d18719a4STom Rini 			struct data d;
187d18719a4STom Rini 			DPRINT("Character literal: %s\n", yytext);
188d18719a4STom Rini 
189d18719a4STom Rini 			d = data_copy_escape_string(yytext+1, yyleng-2);
190d18719a4STom Rini 			if (d.len == 1) {
191d18719a4STom Rini 				lexical_error("Empty character literal");
192d18719a4STom Rini 				yylval.integer = 0;
193d18719a4STom Rini 			} else {
194d18719a4STom Rini 				yylval.integer = (unsigned char)d.val[0];
195d18719a4STom Rini 
196d18719a4STom Rini 				if (d.len > 2)
197d18719a4STom Rini 					lexical_error("Character literal has %d"
198d18719a4STom Rini 						      " characters instead of 1",
199d18719a4STom Rini 						      d.len - 1);
200d18719a4STom Rini 			}
201d18719a4STom Rini 
202d18719a4STom Rini 			data_free(d);
203d18719a4STom Rini 			return DT_CHAR_LITERAL;
204d18719a4STom Rini 		}
205d18719a4STom Rini 
206d18719a4STom Rini <*>\&{LABEL}	{	/* label reference */
207d18719a4STom Rini 			DPRINT("Ref: %s\n", yytext+1);
208d18719a4STom Rini 			yylval.labelref = xstrdup(yytext+1);
209d18719a4STom Rini 			return DT_REF;
210d18719a4STom Rini 		}
211d18719a4STom Rini 
212d18719a4STom Rini <*>"&{/"{PATHCHAR}*\}	{	/* new-style path reference */
213d18719a4STom Rini 			yytext[yyleng-1] = '\0';
214d18719a4STom Rini 			DPRINT("Ref: %s\n", yytext+2);
215d18719a4STom Rini 			yylval.labelref = xstrdup(yytext+2);
216d18719a4STom Rini 			return DT_REF;
217d18719a4STom Rini 		}
218d18719a4STom Rini 
219d18719a4STom Rini <BYTESTRING>[0-9a-fA-F]{2} {
220d18719a4STom Rini 			yylval.byte = strtol(yytext, NULL, 16);
221d18719a4STom Rini 			DPRINT("Byte: %02x\n", (int)yylval.byte);
222d18719a4STom Rini 			return DT_BYTE;
223d18719a4STom Rini 		}
224d18719a4STom Rini 
225d18719a4STom Rini <BYTESTRING>"]"	{
226d18719a4STom Rini 			DPRINT("/BYTESTRING\n");
227d18719a4STom Rini 			BEGIN_DEFAULT();
228d18719a4STom Rini 			return ']';
229d18719a4STom Rini 		}
230d18719a4STom Rini 
231d18719a4STom Rini <PROPNODENAME>\\?{PROPNODECHAR}+ {
232d18719a4STom Rini 			DPRINT("PropNodeName: %s\n", yytext);
233d18719a4STom Rini 			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
234d18719a4STom Rini 							yytext + 1 : yytext);
235d18719a4STom Rini 			BEGIN_DEFAULT();
236d18719a4STom Rini 			return DT_PROPNODENAME;
237d18719a4STom Rini 		}
238d18719a4STom Rini 
239d18719a4STom Rini "/incbin/"	{
240d18719a4STom Rini 			DPRINT("Binary Include\n");
241d18719a4STom Rini 			return DT_INCBIN;
242d18719a4STom Rini 		}
243d18719a4STom Rini 
244d18719a4STom Rini <*>{WS}+	/* eat whitespace */
245d18719a4STom Rini <*>{COMMENT}+	/* eat C-style comments */
246d18719a4STom Rini <*>{LINECOMMENT}+ /* eat C++-style comments */
247d18719a4STom Rini 
248d18719a4STom Rini <*>"<<"		{ return DT_LSHIFT; };
249d18719a4STom Rini <*>">>"		{ return DT_RSHIFT; };
250d18719a4STom Rini <*>"<="		{ return DT_LE; };
251d18719a4STom Rini <*>">="		{ return DT_GE; };
252d18719a4STom Rini <*>"=="		{ return DT_EQ; };
253d18719a4STom Rini <*>"!="		{ return DT_NE; };
254d18719a4STom Rini <*>"&&"		{ return DT_AND; };
255d18719a4STom Rini <*>"||"		{ return DT_OR; };
256d18719a4STom Rini 
257d18719a4STom Rini <*>.		{
258d18719a4STom Rini 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
259d18719a4STom Rini 				(unsigned)yytext[0]);
260d18719a4STom Rini 			if (yytext[0] == '[') {
261d18719a4STom Rini 				DPRINT("<BYTESTRING>\n");
262d18719a4STom Rini 				BEGIN(BYTESTRING);
263d18719a4STom Rini 			}
264d18719a4STom Rini 			if ((yytext[0] == '{')
265d18719a4STom Rini 			    || (yytext[0] == ';')) {
266d18719a4STom Rini 				DPRINT("<PROPNODENAME>\n");
267d18719a4STom Rini 				BEGIN(PROPNODENAME);
268d18719a4STom Rini 			}
269d18719a4STom Rini 			return yytext[0];
270d18719a4STom Rini 		}
271d18719a4STom Rini 
272d18719a4STom Rini %%
273d18719a4STom Rini 
274d18719a4STom Rini static void push_input_file(const char *filename)
275d18719a4STom Rini {
276d18719a4STom Rini 	assert(filename);
277d18719a4STom Rini 
278d18719a4STom Rini 	srcfile_push(filename);
279d18719a4STom Rini 
280d18719a4STom Rini 	yyin = current_srcfile->f;
281d18719a4STom Rini 
282d18719a4STom Rini 	yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
283d18719a4STom Rini }
284d18719a4STom Rini 
285d18719a4STom Rini 
286d18719a4STom Rini static bool pop_input_file(void)
287d18719a4STom Rini {
288d18719a4STom Rini 	if (srcfile_pop() == 0)
289d18719a4STom Rini 		return false;
290d18719a4STom Rini 
291d18719a4STom Rini 	yypop_buffer_state();
292d18719a4STom Rini 	yyin = current_srcfile->f;
293d18719a4STom Rini 
294d18719a4STom Rini 	return true;
295d18719a4STom Rini }
296d18719a4STom Rini 
297d18719a4STom Rini static void lexical_error(const char *fmt, ...)
298d18719a4STom Rini {
299d18719a4STom Rini 	va_list ap;
300d18719a4STom Rini 
301d18719a4STom Rini 	va_start(ap, fmt);
302d18719a4STom Rini 	srcpos_verror(&yylloc, "Lexical error", fmt, ap);
303d18719a4STom Rini 	va_end(ap);
304d18719a4STom Rini 
305d18719a4STom Rini 	treesource_error = true;
306d18719a4STom Rini }
307