xref: /openbmc/linux/scripts/dtc/dtc-lexer.l (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
112869ecdSRob Herring /* SPDX-License-Identifier: GPL-2.0-or-later */
29fffb55fSDavid Gibson /*
39fffb55fSDavid Gibson  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
49fffb55fSDavid Gibson  */
59fffb55fSDavid Gibson 
6658f29a5SJohn Bonesio %option noyywrap nounput noinput never-interactive
79fffb55fSDavid Gibson 
89fffb55fSDavid Gibson %x BYTESTRING
99fffb55fSDavid Gibson %x PROPNODENAME
109fffb55fSDavid Gibson %s V1
119fffb55fSDavid Gibson 
129fffb55fSDavid Gibson PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
139fffb55fSDavid Gibson PATHCHAR	({PROPNODECHAR}|[/])
149fffb55fSDavid Gibson LABEL		[a-zA-Z_][a-zA-Z0-9_]*
159fffb55fSDavid Gibson STRING		\"([^\\"]|\\.)*\"
16cd296721SStephen Warren CHAR_LITERAL	'([^']|\\')*'
179fffb55fSDavid Gibson WS		[[:space:]]
189fffb55fSDavid Gibson COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
199fffb55fSDavid Gibson LINECOMMENT	"//".*\n
209fffb55fSDavid Gibson 
219fffb55fSDavid Gibson %{
229fffb55fSDavid Gibson #include "dtc.h"
239fffb55fSDavid Gibson #include "srcpos.h"
249fffb55fSDavid Gibson #include "dtc-parser.tab.h"
259fffb55fSDavid Gibson 
2647605971SRob Herring extern bool treesource_error;
27658f29a5SJohn Bonesio 
28658f29a5SJohn Bonesio /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
29658f29a5SJohn Bonesio #define	YY_USER_ACTION \
30658f29a5SJohn Bonesio 	{ \
31658f29a5SJohn Bonesio 		srcpos_update(&yylloc, yytext, yyleng); \
32658f29a5SJohn Bonesio 	}
339fffb55fSDavid Gibson 
349fffb55fSDavid Gibson /*#define LEXDEBUG	1*/
359fffb55fSDavid Gibson 
369fffb55fSDavid Gibson #ifdef LEXDEBUG
379fffb55fSDavid Gibson #define DPRINT(fmt, ...)	fprintf(stderr, fmt, ##__VA_ARGS__)
389fffb55fSDavid Gibson #else
399fffb55fSDavid Gibson #define DPRINT(fmt, ...)	do { } while (0)
409fffb55fSDavid Gibson #endif
419fffb55fSDavid Gibson 
42658f29a5SJohn Bonesio static int dts_version = 1;
439fffb55fSDavid Gibson 
44658f29a5SJohn Bonesio #define BEGIN_DEFAULT()		DPRINT("<V1>\n"); \
459fffb55fSDavid Gibson 				BEGIN(V1); \
469fffb55fSDavid Gibson 
479fffb55fSDavid Gibson static void push_input_file(const char *filename);
4847605971SRob Herring static bool pop_input_file(void);
4989d12310SRob Herring static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
5089d12310SRob Herring 
519fffb55fSDavid Gibson %}
529fffb55fSDavid Gibson 
539fffb55fSDavid Gibson %%
549fffb55fSDavid Gibson <*>"/include/"{WS}*{STRING} {
559fffb55fSDavid Gibson 			char *name = strchr(yytext, '\"') + 1;
569fffb55fSDavid Gibson 			yytext[yyleng-1] = '\0';
579fffb55fSDavid Gibson 			push_input_file(name);
589fffb55fSDavid Gibson 		}
599fffb55fSDavid Gibson 
60a77725a9SRob Herring <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
6191feabc2SRob Herring 			char *line, *fnstart, *fnend;
6291feabc2SRob Herring 			struct data fn;
63cd296721SStephen Warren 			/* skip text before line # */
64cd296721SStephen Warren 			line = yytext;
6547605971SRob Herring 			while (!isdigit((unsigned char)*line))
66cd296721SStephen Warren 				line++;
6791feabc2SRob Herring 
6891feabc2SRob Herring 			/* regexp ensures that first and list "
6991feabc2SRob Herring 			 * in the whole yytext are those at
7091feabc2SRob Herring 			 * beginning and end of the filename string */
7191feabc2SRob Herring 			fnstart = memchr(yytext, '"', yyleng);
7291feabc2SRob Herring 			for (fnend = yytext + yyleng - 1;
7391feabc2SRob Herring 			     *fnend != '"'; fnend--)
7491feabc2SRob Herring 				;
7591feabc2SRob Herring 			assert(fnstart && fnend && (fnend > fnstart));
7691feabc2SRob Herring 
7791feabc2SRob Herring 			fn = data_copy_escape_string(fnstart + 1,
7891feabc2SRob Herring 						     fnend - fnstart - 1);
7991feabc2SRob Herring 
8091feabc2SRob Herring 			/* Don't allow nuls in filenames */
8191feabc2SRob Herring 			if (memchr(fn.val, '\0', fn.len - 1))
8291feabc2SRob Herring 				lexical_error("nul in line number directive");
8391feabc2SRob Herring 
84cd296721SStephen Warren 			/* -1 since #line is the number of the next line */
8591feabc2SRob Herring 			srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
8691feabc2SRob Herring 			data_free(fn);
87cd296721SStephen Warren 		}
88cd296721SStephen Warren 
899fffb55fSDavid Gibson <*><<EOF>>		{
909fffb55fSDavid Gibson 			if (!pop_input_file()) {
919fffb55fSDavid Gibson 				yyterminate();
929fffb55fSDavid Gibson 			}
939fffb55fSDavid Gibson 		}
949fffb55fSDavid Gibson 
959fffb55fSDavid Gibson <*>{STRING}	{
969fffb55fSDavid Gibson 			DPRINT("String: %s\n", yytext);
979fffb55fSDavid Gibson 			yylval.data = data_copy_escape_string(yytext+1,
989fffb55fSDavid Gibson 					yyleng-2);
999fffb55fSDavid Gibson 			return DT_STRING;
1009fffb55fSDavid Gibson 		}
1019fffb55fSDavid Gibson 
1029fffb55fSDavid Gibson <*>"/dts-v1/"	{
1039fffb55fSDavid Gibson 			DPRINT("Keyword: /dts-v1/\n");
1049fffb55fSDavid Gibson 			dts_version = 1;
1059fffb55fSDavid Gibson 			BEGIN_DEFAULT();
1069fffb55fSDavid Gibson 			return DT_V1;
1079fffb55fSDavid Gibson 		}
1089fffb55fSDavid Gibson 
1096f05afcbSRob Herring <*>"/plugin/"	{
1106f05afcbSRob Herring 			DPRINT("Keyword: /plugin/\n");
1116f05afcbSRob Herring 			return DT_PLUGIN;
1126f05afcbSRob Herring 		}
1136f05afcbSRob Herring 
1149fffb55fSDavid Gibson <*>"/memreserve/"	{
1159fffb55fSDavid Gibson 			DPRINT("Keyword: /memreserve/\n");
1169fffb55fSDavid Gibson 			BEGIN_DEFAULT();
1179fffb55fSDavid Gibson 			return DT_MEMRESERVE;
1189fffb55fSDavid Gibson 		}
1199fffb55fSDavid Gibson 
120cd296721SStephen Warren <*>"/bits/"	{
121cd296721SStephen Warren 			DPRINT("Keyword: /bits/\n");
122cd296721SStephen Warren 			BEGIN_DEFAULT();
123cd296721SStephen Warren 			return DT_BITS;
124cd296721SStephen Warren 		}
125cd296721SStephen Warren 
126cd296721SStephen Warren <*>"/delete-property/"	{
127cd296721SStephen Warren 			DPRINT("Keyword: /delete-property/\n");
128cd296721SStephen Warren 			DPRINT("<PROPNODENAME>\n");
129cd296721SStephen Warren 			BEGIN(PROPNODENAME);
130cd296721SStephen Warren 			return DT_DEL_PROP;
131cd296721SStephen Warren 		}
132cd296721SStephen Warren 
133cd296721SStephen Warren <*>"/delete-node/"	{
134cd296721SStephen Warren 			DPRINT("Keyword: /delete-node/\n");
135cd296721SStephen Warren 			DPRINT("<PROPNODENAME>\n");
136cd296721SStephen Warren 			BEGIN(PROPNODENAME);
137cd296721SStephen Warren 			return DT_DEL_NODE;
138cd296721SStephen Warren 		}
139cd296721SStephen Warren 
14050aafd60SRob Herring <*>"/omit-if-no-ref/"	{
14150aafd60SRob Herring 			DPRINT("Keyword: /omit-if-no-ref/\n");
14250aafd60SRob Herring 			DPRINT("<PROPNODENAME>\n");
14350aafd60SRob Herring 			BEGIN(PROPNODENAME);
14450aafd60SRob Herring 			return DT_OMIT_NO_REF;
14550aafd60SRob Herring 		}
14650aafd60SRob Herring 
1479fffb55fSDavid Gibson <*>{LABEL}:	{
1489fffb55fSDavid Gibson 			DPRINT("Label: %s\n", yytext);
149658f29a5SJohn Bonesio 			yylval.labelref = xstrdup(yytext);
1509fffb55fSDavid Gibson 			yylval.labelref[yyleng-1] = '\0';
1519fffb55fSDavid Gibson 			return DT_LABEL;
1529fffb55fSDavid Gibson 		}
1539fffb55fSDavid Gibson 
154cd296721SStephen Warren <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
15547605971SRob Herring 			char *e;
15647605971SRob Herring 			DPRINT("Integer Literal: '%s'\n", yytext);
15747605971SRob Herring 
15847605971SRob Herring 			errno = 0;
15947605971SRob Herring 			yylval.integer = strtoull(yytext, &e, 0);
16047605971SRob Herring 
16191feabc2SRob Herring 			if (*e && e[strspn(e, "UL")]) {
16291feabc2SRob Herring 				lexical_error("Bad integer literal '%s'",
16391feabc2SRob Herring 					      yytext);
16491feabc2SRob Herring 			}
16547605971SRob Herring 
16647605971SRob Herring 			if (errno == ERANGE)
16747605971SRob Herring 				lexical_error("Integer literal '%s' out of range",
16847605971SRob Herring 					      yytext);
16947605971SRob Herring 			else
17047605971SRob Herring 				/* ERANGE is the only strtoull error triggerable
17147605971SRob Herring 				 *  by strings matching the pattern */
17247605971SRob Herring 				assert(errno == 0);
1739fffb55fSDavid Gibson 			return DT_LITERAL;
1749fffb55fSDavid Gibson 		}
1759fffb55fSDavid Gibson 
176cd296721SStephen Warren <*>{CHAR_LITERAL}	{
17747605971SRob Herring 			struct data d;
17847605971SRob Herring 			DPRINT("Character literal: %s\n", yytext);
17947605971SRob Herring 
18047605971SRob Herring 			d = data_copy_escape_string(yytext+1, yyleng-2);
18147605971SRob Herring 			if (d.len == 1) {
18247605971SRob Herring 				lexical_error("Empty character literal");
18347605971SRob Herring 				yylval.integer = 0;
1846f05afcbSRob Herring 			} else {
18547605971SRob Herring 				yylval.integer = (unsigned char)d.val[0];
18647605971SRob Herring 
18747605971SRob Herring 				if (d.len > 2)
18847605971SRob Herring 					lexical_error("Character literal has %d"
18947605971SRob Herring 						      " characters instead of 1",
19047605971SRob Herring 						      d.len - 1);
1916f05afcbSRob Herring 			}
19247605971SRob Herring 
1936f05afcbSRob Herring 			data_free(d);
194cd296721SStephen Warren 			return DT_CHAR_LITERAL;
195cd296721SStephen Warren 		}
196cd296721SStephen Warren 
197658f29a5SJohn Bonesio <*>\&{LABEL}	{	/* label reference */
1989fffb55fSDavid Gibson 			DPRINT("Ref: %s\n", yytext+1);
199658f29a5SJohn Bonesio 			yylval.labelref = xstrdup(yytext+1);
200c2e7075cSRob Herring 			return DT_LABEL_REF;
2019fffb55fSDavid Gibson 		}
2029fffb55fSDavid Gibson 
203*ea3723a5SRob Herring <*>"&{"{PATHCHAR}*\}	{	/* new-style path reference */
2049fffb55fSDavid Gibson 			yytext[yyleng-1] = '\0';
2059fffb55fSDavid Gibson 			DPRINT("Ref: %s\n", yytext+2);
206658f29a5SJohn Bonesio 			yylval.labelref = xstrdup(yytext+2);
207c2e7075cSRob Herring 			return DT_PATH_REF;
2089fffb55fSDavid Gibson 		}
2099fffb55fSDavid Gibson 
2109fffb55fSDavid Gibson <BYTESTRING>[0-9a-fA-F]{2} {
2119fffb55fSDavid Gibson 			yylval.byte = strtol(yytext, NULL, 16);
2129fffb55fSDavid Gibson 			DPRINT("Byte: %02x\n", (int)yylval.byte);
2139fffb55fSDavid Gibson 			return DT_BYTE;
2149fffb55fSDavid Gibson 		}
2159fffb55fSDavid Gibson 
2169fffb55fSDavid Gibson <BYTESTRING>"]"	{
2179fffb55fSDavid Gibson 			DPRINT("/BYTESTRING\n");
2189fffb55fSDavid Gibson 			BEGIN_DEFAULT();
2199fffb55fSDavid Gibson 			return ']';
2209fffb55fSDavid Gibson 		}
2219fffb55fSDavid Gibson 
222cd296721SStephen Warren <PROPNODENAME>\\?{PROPNODECHAR}+ {
2239fffb55fSDavid Gibson 			DPRINT("PropNodeName: %s\n", yytext);
224cd296721SStephen Warren 			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
225cd296721SStephen Warren 							yytext + 1 : yytext);
2269fffb55fSDavid Gibson 			BEGIN_DEFAULT();
2279fffb55fSDavid Gibson 			return DT_PROPNODENAME;
2289fffb55fSDavid Gibson 		}
2299fffb55fSDavid Gibson 
2309fffb55fSDavid Gibson "/incbin/"	{
2319fffb55fSDavid Gibson 			DPRINT("Binary Include\n");
2329fffb55fSDavid Gibson 			return DT_INCBIN;
2339fffb55fSDavid Gibson 		}
2349fffb55fSDavid Gibson 
2359fffb55fSDavid Gibson <*>{WS}+	/* eat whitespace */
2369fffb55fSDavid Gibson <*>{COMMENT}+	/* eat C-style comments */
2379fffb55fSDavid Gibson <*>{LINECOMMENT}+ /* eat C++-style comments */
2389fffb55fSDavid Gibson 
239cd296721SStephen Warren <*>"<<"		{ return DT_LSHIFT; };
240cd296721SStephen Warren <*>">>"		{ return DT_RSHIFT; };
241cd296721SStephen Warren <*>"<="		{ return DT_LE; };
242cd296721SStephen Warren <*>">="		{ return DT_GE; };
243cd296721SStephen Warren <*>"=="		{ return DT_EQ; };
244cd296721SStephen Warren <*>"!="		{ return DT_NE; };
245cd296721SStephen Warren <*>"&&"		{ return DT_AND; };
246cd296721SStephen Warren <*>"||"		{ return DT_OR; };
247cd296721SStephen Warren 
2489fffb55fSDavid Gibson <*>.		{
2499fffb55fSDavid Gibson 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
2509fffb55fSDavid Gibson 				(unsigned)yytext[0]);
2519fffb55fSDavid Gibson 			if (yytext[0] == '[') {
2529fffb55fSDavid Gibson 				DPRINT("<BYTESTRING>\n");
2539fffb55fSDavid Gibson 				BEGIN(BYTESTRING);
2549fffb55fSDavid Gibson 			}
2559fffb55fSDavid Gibson 			if ((yytext[0] == '{')
2569fffb55fSDavid Gibson 			    || (yytext[0] == ';')) {
2579fffb55fSDavid Gibson 				DPRINT("<PROPNODENAME>\n");
2589fffb55fSDavid Gibson 				BEGIN(PROPNODENAME);
2599fffb55fSDavid Gibson 			}
2609fffb55fSDavid Gibson 			return yytext[0];
2619fffb55fSDavid Gibson 		}
2629fffb55fSDavid Gibson 
2639fffb55fSDavid Gibson %%
2649fffb55fSDavid Gibson 
2659fffb55fSDavid Gibson static void push_input_file(const char *filename)
2669fffb55fSDavid Gibson {
2679fffb55fSDavid Gibson 	assert(filename);
2689fffb55fSDavid Gibson 
269658f29a5SJohn Bonesio 	srcfile_push(filename);
2709fffb55fSDavid Gibson 
271658f29a5SJohn Bonesio 	yyin = current_srcfile->f;
2729fffb55fSDavid Gibson 
273658f29a5SJohn Bonesio 	yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
2749fffb55fSDavid Gibson }
2759fffb55fSDavid Gibson 
2769fffb55fSDavid Gibson 
27747605971SRob Herring static bool pop_input_file(void)
2789fffb55fSDavid Gibson {
279658f29a5SJohn Bonesio 	if (srcfile_pop() == 0)
28047605971SRob Herring 		return false;
2819fffb55fSDavid Gibson 
282658f29a5SJohn Bonesio 	yypop_buffer_state();
283658f29a5SJohn Bonesio 	yyin = current_srcfile->f;
2849fffb55fSDavid Gibson 
28547605971SRob Herring 	return true;
28647605971SRob Herring }
28747605971SRob Herring 
28847605971SRob Herring static void lexical_error(const char *fmt, ...)
28947605971SRob Herring {
29047605971SRob Herring 	va_list ap;
29147605971SRob Herring 
29247605971SRob Herring 	va_start(ap, fmt);
29347605971SRob Herring 	srcpos_verror(&yylloc, "Lexical error", fmt, ap);
29447605971SRob Herring 	va_end(ap);
29547605971SRob Herring 
29647605971SRob Herring 	treesource_error = true;
2979fffb55fSDavid Gibson }
298