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