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