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