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