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