1204431Sraj/*
2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3204431Sraj *
4204431Sraj *
5204431Sraj * This program is free software; you can redistribute it and/or
6204431Sraj * modify it under the terms of the GNU General Public License as
7204431Sraj * published by the Free Software Foundation; either version 2 of the
8204431Sraj * License, or (at your option) any later version.
9204431Sraj *
10204431Sraj *  This program is distributed in the hope that it will be useful,
11204431Sraj *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12204431Sraj *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13204431Sraj *  General Public License for more details.
14204431Sraj *
15204431Sraj *  You should have received a copy of the GNU General Public License
16204431Sraj *  along with this program; if not, write to the Free Software
17204431Sraj *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18204431Sraj *                                                                   USA
19204431Sraj */
20204431Sraj
21238742Simp%option noyywrap nounput noinput never-interactive
22204431Sraj
23204431Sraj%x INCLUDE
24204431Sraj%x BYTESTRING
25204431Sraj%x PROPNODENAME
26204431Sraj%s V1
27204431Sraj
28204431SrajPROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
29204431SrajPATHCHAR	({PROPNODECHAR}|[/])
30204431SrajLABEL		[a-zA-Z_][a-zA-Z0-9_]*
31204431SrajSTRING		\"([^\\"]|\\.)*\"
32238742SimpCHAR_LITERAL	'([^']|\\')*'
33204431SrajWS		[[:space:]]
34204431SrajCOMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
35204431SrajLINECOMMENT	"//".*\n
36204431Sraj
37204431Sraj%{
38204431Sraj#include "dtc.h"
39204431Sraj#include "srcpos.h"
40204431Sraj#include "dtc-parser.tab.h"
41204431Sraj
42238742Simp#define MAX_INCLUDE_NESTING 100
43238742SimpYY_BUFFER_STATE include_stack[MAX_INCLUDE_NESTING];
44238742Simpint include_stack_pointer = 0;
45238742Simp
46204489SrajYYLTYPE yylloc;
47266130Sianextern bool treesource_error;
48204489Sraj
49238742Simp/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
50204433Sraj#define	YY_USER_ACTION \
51204433Sraj	{ \
52238742Simp		srcpos_update(&yylloc, yytext, yyleng); \
53204433Sraj	}
54204431Sraj
55204431Sraj/*#define LEXDEBUG	1*/
56204431Sraj
57204431Sraj#ifdef LEXDEBUG
58204431Sraj#define DPRINT(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
59204431Sraj#else
60204431Sraj#define DPRINT(fmt, ...)	do { } while (0)
61204431Sraj#endif
62204431Sraj
63204433Srajstatic int dts_version = 1;
64204431Sraj
65204433Sraj#define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \
66204431Sraj				BEGIN(V1); \
67204431Sraj
68204431Srajstatic void push_input_file(const char *filename);
69266130Sianstatic bool pop_input_file(void);
70266130Sianstatic void lexical_error(const char *fmt, ...);
71204431Sraj%}
72204431Sraj
73204431Sraj%%
74204431Sraj<*>"/include/"{WS}*{STRING} {
75204431Sraj			char *name = strchr(yytext, '\"') + 1;
76204431Sraj			yytext[yyleng-1] = '\0';
77204431Sraj			push_input_file(name);
78204431Sraj		}
79204431Sraj
80266130Sian<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
81266130Sian			char *line, *tmp, *fn;
82266130Sian			/* skip text before line # */
83266130Sian			line = yytext;
84266130Sian			while (!isdigit((unsigned char)*line))
85266130Sian				line++;
86266130Sian			/* skip digits in line # */
87266130Sian			tmp = line;
88266130Sian			while (!isspace((unsigned char)*tmp))
89266130Sian				tmp++;
90266130Sian			/* "NULL"-terminate line # */
91266130Sian			*tmp = '\0';
92266130Sian			/* start of filename */
93266130Sian			fn = strchr(tmp + 1, '"') + 1;
94266130Sian			/* strip trailing " from filename */
95266130Sian			tmp = strchr(fn, '"');
96266130Sian			*tmp = 0;
97266130Sian			/* -1 since #line is the number of the next line */
98266130Sian			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
99266130Sian		}
100266130Sian
101204431Sraj<*><<EOF>>		{
102204431Sraj			if (!pop_input_file()) {
103204431Sraj				yyterminate();
104204431Sraj			}
105204431Sraj		}
106204431Sraj
107204431Sraj<*>{STRING}	{
108204431Sraj			DPRINT("String: %s\n", yytext);
109204431Sraj			yylval.data = data_copy_escape_string(yytext+1,
110204431Sraj					yyleng-2);
111204431Sraj			return DT_STRING;
112204431Sraj		}
113204431Sraj
114204431Sraj<*>"/dts-v1/"	{
115204431Sraj			DPRINT("Keyword: /dts-v1/\n");
116204431Sraj			dts_version = 1;
117204431Sraj			BEGIN_DEFAULT();
118204431Sraj			return DT_V1;
119204431Sraj		}
120204431Sraj
121204431Sraj<*>"/memreserve/"	{
122204431Sraj			DPRINT("Keyword: /memreserve/\n");
123204431Sraj			BEGIN_DEFAULT();
124204431Sraj			return DT_MEMRESERVE;
125204431Sraj		}
126204431Sraj
127238742Simp<*>"/bits/"	{
128238742Simp			DPRINT("Keyword: /bits/\n");
129238742Simp			BEGIN_DEFAULT();
130238742Simp			return DT_BITS;
131238742Simp		}
132238742Simp
133266130Sian<*>"/delete-property/"	{
134266130Sian			DPRINT("Keyword: /delete-property/\n");
135266130Sian			DPRINT("<PROPNODENAME>\n");
136266130Sian			BEGIN(PROPNODENAME);
137266130Sian			return DT_DEL_PROP;
138266130Sian		}
139266130Sian
140266130Sian<*>"/delete-node/"	{
141266130Sian			DPRINT("Keyword: /delete-node/\n");
142266130Sian			DPRINT("<PROPNODENAME>\n");
143266130Sian			BEGIN(PROPNODENAME);
144266130Sian			return DT_DEL_NODE;
145266130Sian		}
146266130Sian
147204431Sraj<*>{LABEL}:	{
148204431Sraj			DPRINT("Label: %s\n", yytext);
149204433Sraj			yylval.labelref = xstrdup(yytext);
150204431Sraj			yylval.labelref[yyleng-1] = '\0';
151204431Sraj			return DT_LABEL;
152204431Sraj		}
153204431Sraj
154238742Simp<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
155266130Sian			char *e;
156266130Sian			DPRINT("Integer Literal: '%s'\n", yytext);
157266130Sian
158266130Sian			errno = 0;
159266130Sian			yylval.integer = strtoull(yytext, &e, 0);
160266130Sian
161266130Sian			assert(!(*e) || !e[strspn(e, "UL")]);
162266130Sian
163266130Sian			if (errno == ERANGE)
164266130Sian				lexical_error("Integer literal '%s' out of range",
165266130Sian					      yytext);
166266130Sian			else
167266130Sian				/* ERANGE is the only strtoull error triggerable
168266130Sian				 *  by strings matching the pattern */
169266130Sian				assert(errno == 0);
170204431Sraj			return DT_LITERAL;
171204431Sraj		}
172204431Sraj
173238742Simp<*>{CHAR_LITERAL}	{
174266130Sian			struct data d;
175266130Sian			DPRINT("Character literal: %s\n", yytext);
176266130Sian
177266130Sian			d = data_copy_escape_string(yytext+1, yyleng-2);
178266130Sian			if (d.len == 1) {
179266130Sian				lexical_error("Empty character literal");
180266130Sian				yylval.integer = 0;
181266130Sian				return DT_CHAR_LITERAL;
182266130Sian			}
183266130Sian
184266130Sian			yylval.integer = (unsigned char)d.val[0];
185266130Sian
186266130Sian			if (d.len > 2)
187266130Sian				lexical_error("Character literal has %d"
188266130Sian					      " characters instead of 1",
189266130Sian					      d.len - 1);
190266130Sian
191238742Simp			return DT_CHAR_LITERAL;
192238742Simp		}
193238742Simp
194238742Simp<*>\&{LABEL}	{	/* label reference */
195204431Sraj			DPRINT("Ref: %s\n", yytext+1);
196204433Sraj			yylval.labelref = xstrdup(yytext+1);
197204431Sraj			return DT_REF;
198204431Sraj		}
199204431Sraj
200238742Simp<*>"&{/"{PATHCHAR}+\}	{	/* new-style path reference */
201204431Sraj			yytext[yyleng-1] = '\0';
202204431Sraj			DPRINT("Ref: %s\n", yytext+2);
203204433Sraj			yylval.labelref = xstrdup(yytext+2);
204204431Sraj			return DT_REF;
205204431Sraj		}
206204431Sraj
207204431Sraj<BYTESTRING>[0-9a-fA-F]{2} {
208204431Sraj			yylval.byte = strtol(yytext, NULL, 16);
209204431Sraj			DPRINT("Byte: %02x\n", (int)yylval.byte);
210204431Sraj			return DT_BYTE;
211204431Sraj		}
212204431Sraj
213204431Sraj<BYTESTRING>"]"	{
214204431Sraj			DPRINT("/BYTESTRING\n");
215204431Sraj			BEGIN_DEFAULT();
216204431Sraj			return ']';
217204431Sraj		}
218204431Sraj
219266130Sian<PROPNODENAME>\\?{PROPNODECHAR}+ {
220204431Sraj			DPRINT("PropNodeName: %s\n", yytext);
221266130Sian			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
222266130Sian							yytext + 1 : yytext);
223204431Sraj			BEGIN_DEFAULT();
224204431Sraj			return DT_PROPNODENAME;
225204431Sraj		}
226204431Sraj
227204431Sraj"/incbin/"	{
228204431Sraj			DPRINT("Binary Include\n");
229204431Sraj			return DT_INCBIN;
230204431Sraj		}
231204431Sraj
232204431Sraj<*>{WS}+	/* eat whitespace */
233204431Sraj<*>{COMMENT}+	/* eat C-style comments */
234204431Sraj<*>{LINECOMMENT}+ /* eat C++-style comments */
235204431Sraj
236238742Simp<*>"<<"		{ return DT_LSHIFT; };
237238742Simp<*>">>"		{ return DT_RSHIFT; };
238238742Simp<*>"<="		{ return DT_LE; };
239238742Simp<*>">="		{ return DT_GE; };
240238742Simp<*>"=="		{ return DT_EQ; };
241238742Simp<*>"!="		{ return DT_NE; };
242238742Simp<*>"&&"		{ return DT_AND; };
243238742Simp<*>"||"		{ return DT_OR; };
244238742Simp
245204431Sraj<*>.		{
246204431Sraj			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
247204431Sraj				(unsigned)yytext[0]);
248204431Sraj			if (yytext[0] == '[') {
249204431Sraj				DPRINT("<BYTESTRING>\n");
250204431Sraj				BEGIN(BYTESTRING);
251204431Sraj			}
252204431Sraj			if ((yytext[0] == '{')
253204431Sraj			    || (yytext[0] == ';')) {
254204431Sraj				DPRINT("<PROPNODENAME>\n");
255204431Sraj				BEGIN(PROPNODENAME);
256204431Sraj			}
257204431Sraj			return yytext[0];
258204431Sraj		}
259204431Sraj
260204431Sraj%%
261204431Sraj
262204431Srajstatic void push_input_file(const char *filename)
263204431Sraj{
264204431Sraj	assert(filename);
265204431Sraj
266239998Sandrew	assert(include_stack_pointer < MAX_INCLUDE_NESTING);
267204431Sraj
268238742Simp	srcfile_push(filename);
269204431Sraj
270238742Simp	yyin = current_srcfile->f;
271204431Sraj
272238742Simp	include_stack[include_stack_pointer++] = YY_CURRENT_BUFFER;
273204431Sraj
274204431Sraj	yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
275204431Sraj}
276204431Sraj
277204431Sraj
278266130Sianstatic bool pop_input_file(void)
279204431Sraj{
280238742Simp	if (srcfile_pop() == 0)
281266130Sian		return false;
282204431Sraj
283238742Simp	assert(include_stack_pointer > 0);
284204431Sraj
285238742Simp	yy_delete_buffer( YY_CURRENT_BUFFER );
286204431Sraj
287238742Simp	yy_switch_to_buffer( include_stack[--include_stack_pointer] );
288204431Sraj
289238742Simp	yyin = current_srcfile->f;
290204431Sraj
291266130Sian	return true;
292204431Sraj}
293266130Sian
294266130Sianstatic void lexical_error(const char *fmt, ...)
295266130Sian{
296266130Sian	va_list ap;
297266130Sian
298266130Sian	va_start(ap, fmt);
299266130Sian	srcpos_verror(&yylloc, "Lexical error", fmt, ap);
300266130Sian	va_end(ap);
301266130Sian
302266130Sian	treesource_error = true;
303266130Sian}
304