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