0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
0004 */
0005
0006 %option noyywrap nounput noinput never-interactive
0007
0008 %x BYTESTRING
0009 %x PROPNODENAME
0010 %s V1
0011
0012 PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
0013 PATHCHAR ({PROPNODECHAR}|[/])
0014 LABEL [a-zA-Z_][a-zA-Z0-9_]*
0015 STRING \"([^\\"]|\\.)*\"
0016 CHAR_LITERAL '([^']|\\')*'
0017 WS [[:space:]]
0018 COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
0019 LINECOMMENT "//".*\n
0020
0021 %{
0022 #include "dtc.h"
0023 #include "srcpos.h"
0024 #include "dtc-parser.tab.h"
0025
0026 extern bool treesource_error;
0027
0028 /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
0029 #define YY_USER_ACTION \
0030 { \
0031 srcpos_update(&yylloc, yytext, yyleng); \
0032 }
0033
0034 /*#define LEXDEBUG 1*/
0035
0036 #ifdef LEXDEBUG
0037 #define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
0038 #else
0039 #define DPRINT(fmt, ...) do { } while (0)
0040 #endif
0041
0042 static int dts_version = 1;
0043
0044 #define BEGIN_DEFAULT() DPRINT("<V1>\n"); \
0045 BEGIN(V1); \
0046
0047 static void push_input_file(const char *filename);
0048 static bool pop_input_file(void);
0049 static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
0050
0051 %}
0052
0053 %%
0054 <*>"/include/"{WS}*{STRING} {
0055 char *name = strchr(yytext, '\"') + 1;
0056 yytext[yyleng-1] = '\0';
0057 push_input_file(name);
0058 }
0059
0060 <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
0061 char *line, *fnstart, *fnend;
0062 struct data fn;
0063 /* skip text before line # */
0064 line = yytext;
0065 while (!isdigit((unsigned char)*line))
0066 line++;
0067
0068 /* regexp ensures that first and list "
0069 * in the whole yytext are those at
0070 * beginning and end of the filename string */
0071 fnstart = memchr(yytext, '"', yyleng);
0072 for (fnend = yytext + yyleng - 1;
0073 *fnend != '"'; fnend--)
0074 ;
0075 assert(fnstart && fnend && (fnend > fnstart));
0076
0077 fn = data_copy_escape_string(fnstart + 1,
0078 fnend - fnstart - 1);
0079
0080 /* Don't allow nuls in filenames */
0081 if (memchr(fn.val, '\0', fn.len - 1))
0082 lexical_error("nul in line number directive");
0083
0084 /* -1 since #line is the number of the next line */
0085 srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
0086 data_free(fn);
0087 }
0088
0089 <*><<EOF>> {
0090 if (!pop_input_file()) {
0091 yyterminate();
0092 }
0093 }
0094
0095 <*>{STRING} {
0096 DPRINT("String: %s\n", yytext);
0097 yylval.data = data_copy_escape_string(yytext+1,
0098 yyleng-2);
0099 return DT_STRING;
0100 }
0101
0102 <*>"/dts-v1/" {
0103 DPRINT("Keyword: /dts-v1/\n");
0104 dts_version = 1;
0105 BEGIN_DEFAULT();
0106 return DT_V1;
0107 }
0108
0109 <*>"/plugin/" {
0110 DPRINT("Keyword: /plugin/\n");
0111 return DT_PLUGIN;
0112 }
0113
0114 <*>"/memreserve/" {
0115 DPRINT("Keyword: /memreserve/\n");
0116 BEGIN_DEFAULT();
0117 return DT_MEMRESERVE;
0118 }
0119
0120 <*>"/bits/" {
0121 DPRINT("Keyword: /bits/\n");
0122 BEGIN_DEFAULT();
0123 return DT_BITS;
0124 }
0125
0126 <*>"/delete-property/" {
0127 DPRINT("Keyword: /delete-property/\n");
0128 DPRINT("<PROPNODENAME>\n");
0129 BEGIN(PROPNODENAME);
0130 return DT_DEL_PROP;
0131 }
0132
0133 <*>"/delete-node/" {
0134 DPRINT("Keyword: /delete-node/\n");
0135 DPRINT("<PROPNODENAME>\n");
0136 BEGIN(PROPNODENAME);
0137 return DT_DEL_NODE;
0138 }
0139
0140 <*>"/omit-if-no-ref/" {
0141 DPRINT("Keyword: /omit-if-no-ref/\n");
0142 DPRINT("<PROPNODENAME>\n");
0143 BEGIN(PROPNODENAME);
0144 return DT_OMIT_NO_REF;
0145 }
0146
0147 <*>{LABEL}: {
0148 DPRINT("Label: %s\n", yytext);
0149 yylval.labelref = xstrdup(yytext);
0150 yylval.labelref[yyleng-1] = '\0';
0151 return DT_LABEL;
0152 }
0153
0154 <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
0155 char *e;
0156 DPRINT("Integer Literal: '%s'\n", yytext);
0157
0158 errno = 0;
0159 yylval.integer = strtoull(yytext, &e, 0);
0160
0161 if (*e && e[strspn(e, "UL")]) {
0162 lexical_error("Bad integer literal '%s'",
0163 yytext);
0164 }
0165
0166 if (errno == ERANGE)
0167 lexical_error("Integer literal '%s' out of range",
0168 yytext);
0169 else
0170 /* ERANGE is the only strtoull error triggerable
0171 * by strings matching the pattern */
0172 assert(errno == 0);
0173 return DT_LITERAL;
0174 }
0175
0176 <*>{CHAR_LITERAL} {
0177 struct data d;
0178 DPRINT("Character literal: %s\n", yytext);
0179
0180 d = data_copy_escape_string(yytext+1, yyleng-2);
0181 if (d.len == 1) {
0182 lexical_error("Empty character literal");
0183 yylval.integer = 0;
0184 } else {
0185 yylval.integer = (unsigned char)d.val[0];
0186
0187 if (d.len > 2)
0188 lexical_error("Character literal has %d"
0189 " characters instead of 1",
0190 d.len - 1);
0191 }
0192
0193 data_free(d);
0194 return DT_CHAR_LITERAL;
0195 }
0196
0197 <*>\&{LABEL} { /* label reference */
0198 DPRINT("Ref: %s\n", yytext+1);
0199 yylval.labelref = xstrdup(yytext+1);
0200 return DT_LABEL_REF;
0201 }
0202
0203 <*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
0204 yytext[yyleng-1] = '\0';
0205 DPRINT("Ref: %s\n", yytext+2);
0206 yylval.labelref = xstrdup(yytext+2);
0207 return DT_PATH_REF;
0208 }
0209
0210 <BYTESTRING>[0-9a-fA-F]{2} {
0211 yylval.byte = strtol(yytext, NULL, 16);
0212 DPRINT("Byte: %02x\n", (int)yylval.byte);
0213 return DT_BYTE;
0214 }
0215
0216 <BYTESTRING>"]" {
0217 DPRINT("/BYTESTRING\n");
0218 BEGIN_DEFAULT();
0219 return ']';
0220 }
0221
0222 <PROPNODENAME>\\?{PROPNODECHAR}+ {
0223 DPRINT("PropNodeName: %s\n", yytext);
0224 yylval.propnodename = xstrdup((yytext[0] == '\\') ?
0225 yytext + 1 : yytext);
0226 BEGIN_DEFAULT();
0227 return DT_PROPNODENAME;
0228 }
0229
0230 "/incbin/" {
0231 DPRINT("Binary Include\n");
0232 return DT_INCBIN;
0233 }
0234
0235 <*>{WS}+ /* eat whitespace */
0236 <*>{COMMENT}+ /* eat C-style comments */
0237 <*>{LINECOMMENT}+ /* eat C++-style comments */
0238
0239 <*>"<<" { return DT_LSHIFT; };
0240 <*>">>" { return DT_RSHIFT; };
0241 <*>"<=" { return DT_LE; };
0242 <*>">=" { return DT_GE; };
0243 <*>"==" { return DT_EQ; };
0244 <*>"!=" { return DT_NE; };
0245 <*>"&&" { return DT_AND; };
0246 <*>"||" { return DT_OR; };
0247
0248 <*>. {
0249 DPRINT("Char: %c (\\x%02x)\n", yytext[0],
0250 (unsigned)yytext[0]);
0251 if (yytext[0] == '[') {
0252 DPRINT("<BYTESTRING>\n");
0253 BEGIN(BYTESTRING);
0254 }
0255 if ((yytext[0] == '{')
0256 || (yytext[0] == ';')) {
0257 DPRINT("<PROPNODENAME>\n");
0258 BEGIN(PROPNODENAME);
0259 }
0260 return yytext[0];
0261 }
0262
0263 %%
0264
0265 static void push_input_file(const char *filename)
0266 {
0267 assert(filename);
0268
0269 srcfile_push(filename);
0270
0271 yyin = current_srcfile->f;
0272
0273 yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
0274 }
0275
0276
0277 static bool pop_input_file(void)
0278 {
0279 if (srcfile_pop() == 0)
0280 return false;
0281
0282 yypop_buffer_state();
0283 yyin = current_srcfile->f;
0284
0285 return true;
0286 }
0287
0288 static void lexical_error(const char *fmt, ...)
0289 {
0290 va_list ap;
0291
0292 va_start(ap, fmt);
0293 srcpos_verror(&yylloc, "Lexical error", fmt, ap);
0294 va_end(ap);
0295
0296 treesource_error = true;
0297 }