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