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