1204431Sraj/* 2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3204431Sraj * 4204431Sraj * 5204431Sraj * This program is free software; you can redistribute it and/or 6204431Sraj * modify it under the terms of the GNU General Public License as 7204431Sraj * published by the Free Software Foundation; either version 2 of the 8204431Sraj * License, or (at your option) any later version. 9204431Sraj * 10204431Sraj * This program is distributed in the hope that it will be useful, 11204431Sraj * but WITHOUT ANY WARRANTY; without even the implied warranty of 12204431Sraj * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13204431Sraj * General Public License for more details. 14204431Sraj * 15204431Sraj * You should have received a copy of the GNU General Public License 16204431Sraj * along with this program; if not, write to the Free Software 17204431Sraj * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18204431Sraj * USA 19204431Sraj */ 20204431Sraj 21238742Simp%option noyywrap nounput noinput never-interactive 22204431Sraj 23204431Sraj%x BYTESTRING 24204431Sraj%x PROPNODENAME 25204431Sraj%s V1 26204431Sraj 27204431SrajPROPNODECHAR [a-zA-Z0-9,._+*#?@-] 28204431SrajPATHCHAR ({PROPNODECHAR}|[/]) 29204431SrajLABEL [a-zA-Z_][a-zA-Z0-9_]* 30204431SrajSTRING \"([^\\"]|\\.)*\" 31238742SimpCHAR_LITERAL '([^']|\\')*' 32204431SrajWS [[:space:]] 33204431SrajCOMMENT "/*"([^*]|\*+[^*/])*\*+"/" 34204431SrajLINECOMMENT "//".*\n 35204431Sraj 36204431Sraj%{ 37204431Sraj#include "dtc.h" 38204431Sraj#include "srcpos.h" 39204431Sraj#include "dtc-parser.tab.h" 40204431Sraj 41238742Simp#define MAX_INCLUDE_NESTING 100 42238742SimpYY_BUFFER_STATE include_stack[MAX_INCLUDE_NESTING]; 43238742Simpint include_stack_pointer = 0; 44238742Simp 45366135Skevansextern YYLTYPE yylloc; 46261215Simpextern bool treesource_error; 47204489Sraj 48238742Simp/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ 49204433Sraj#define YY_USER_ACTION \ 50204433Sraj { \ 51238742Simp srcpos_update(&yylloc, yytext, yyleng); \ 52204433Sraj } 53204431Sraj 54204431Sraj/*#define LEXDEBUG 1*/ 55204431Sraj 56204431Sraj#ifdef LEXDEBUG 57204431Sraj#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) 58204431Sraj#else 59204431Sraj#define DPRINT(fmt, ...) do { } while (0) 60204431Sraj#endif 61204431Sraj 62204433Srajstatic int dts_version = 1; 63204431Sraj 64204433Sraj#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \ 65204431Sraj BEGIN(V1); \ 66204431Sraj 67204431Srajstatic void push_input_file(const char *filename); 68261215Simpstatic bool pop_input_file(void); 69318102Sgonzo#ifdef __GNUC__ 70318102Sgonzostatic void lexical_error(const char *fmt, ...) 71318102Sgonzo __attribute__((format (printf, 1, 2))); 72318102Sgonzo#else 73261215Simpstatic void lexical_error(const char *fmt, ...); 74318102Sgonzo#endif 75318102Sgonzo 76204431Sraj%} 77204431Sraj 78204431Sraj%% 79204431Sraj<*>"/include/"{WS}*{STRING} { 80204431Sraj char *name = strchr(yytext, '\"') + 1; 81204431Sraj yytext[yyleng-1] = '\0'; 82204431Sraj push_input_file(name); 83204431Sraj } 84204431Sraj 85261215Simp<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { 86318102Sgonzo char *line, *fnstart, *fnend; 87318102Sgonzo struct data fn; 88261215Simp /* skip text before line # */ 89261215Simp line = yytext; 90261215Simp while (!isdigit((unsigned char)*line)) 91261215Simp line++; 92318102Sgonzo 93318102Sgonzo /* regexp ensures that first and list " 94318102Sgonzo * in the whole yytext are those at 95318102Sgonzo * beginning and end of the filename string */ 96318102Sgonzo fnstart = memchr(yytext, '"', yyleng); 97318102Sgonzo for (fnend = yytext + yyleng - 1; 98318102Sgonzo *fnend != '"'; fnend--) 99318102Sgonzo ; 100318102Sgonzo assert(fnstart && fnend && (fnend > fnstart)); 101318102Sgonzo 102318102Sgonzo fn = data_copy_escape_string(fnstart + 1, 103318102Sgonzo fnend - fnstart - 1); 104318102Sgonzo 105318102Sgonzo /* Don't allow nuls in filenames */ 106318102Sgonzo if (memchr(fn.val, '\0', fn.len - 1)) 107318102Sgonzo lexical_error("nul in line number directive"); 108318102Sgonzo 109261215Simp /* -1 since #line is the number of the next line */ 110318102Sgonzo srcpos_set_line(xstrdup(fn.val), atoi(line) - 1); 111318102Sgonzo data_free(fn); 112261215Simp } 113261215Simp 114204431Sraj<*><<EOF>> { 115204431Sraj if (!pop_input_file()) { 116204431Sraj yyterminate(); 117204431Sraj } 118204431Sraj } 119204431Sraj 120204431Sraj<*>{STRING} { 121204431Sraj DPRINT("String: %s\n", yytext); 122204431Sraj yylval.data = data_copy_escape_string(yytext+1, 123204431Sraj yyleng-2); 124204431Sraj return DT_STRING; 125204431Sraj } 126204431Sraj 127204431Sraj<*>"/dts-v1/" { 128204431Sraj DPRINT("Keyword: /dts-v1/\n"); 129204431Sraj dts_version = 1; 130204431Sraj BEGIN_DEFAULT(); 131204431Sraj return DT_V1; 132204431Sraj } 133204431Sraj 134318102Sgonzo<*>"/plugin/" { 135318102Sgonzo DPRINT("Keyword: /plugin/\n"); 136318102Sgonzo return DT_PLUGIN; 137318102Sgonzo } 138318102Sgonzo 139204431Sraj<*>"/memreserve/" { 140204431Sraj DPRINT("Keyword: /memreserve/\n"); 141204431Sraj BEGIN_DEFAULT(); 142204431Sraj return DT_MEMRESERVE; 143204431Sraj } 144204431Sraj 145238742Simp<*>"/bits/" { 146238742Simp DPRINT("Keyword: /bits/\n"); 147238742Simp BEGIN_DEFAULT(); 148238742Simp return DT_BITS; 149238742Simp } 150238742Simp 151261215Simp<*>"/delete-property/" { 152261215Simp DPRINT("Keyword: /delete-property/\n"); 153261215Simp DPRINT("<PROPNODENAME>\n"); 154261215Simp BEGIN(PROPNODENAME); 155261215Simp return DT_DEL_PROP; 156261215Simp } 157261215Simp 158261215Simp<*>"/delete-node/" { 159261215Simp DPRINT("Keyword: /delete-node/\n"); 160261215Simp DPRINT("<PROPNODENAME>\n"); 161261215Simp BEGIN(PROPNODENAME); 162261215Simp return DT_DEL_NODE; 163261215Simp } 164261215Simp 165204431Sraj<*>{LABEL}: { 166204431Sraj DPRINT("Label: %s\n", yytext); 167204433Sraj yylval.labelref = xstrdup(yytext); 168204431Sraj yylval.labelref[yyleng-1] = '\0'; 169204431Sraj return DT_LABEL; 170204431Sraj } 171204431Sraj 172238742Simp<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { 173261215Simp char *e; 174261215Simp DPRINT("Integer Literal: '%s'\n", yytext); 175261215Simp 176261215Simp errno = 0; 177261215Simp yylval.integer = strtoull(yytext, &e, 0); 178261215Simp 179318102Sgonzo if (*e && e[strspn(e, "UL")]) { 180318102Sgonzo lexical_error("Bad integer literal '%s'", 181318102Sgonzo yytext); 182318102Sgonzo } 183261215Simp 184261215Simp if (errno == ERANGE) 185261215Simp lexical_error("Integer literal '%s' out of range", 186261215Simp yytext); 187261215Simp else 188261215Simp /* ERANGE is the only strtoull error triggerable 189261215Simp * by strings matching the pattern */ 190261215Simp assert(errno == 0); 191204431Sraj return DT_LITERAL; 192204431Sraj } 193204431Sraj 194238742Simp<*>{CHAR_LITERAL} { 195261215Simp struct data d; 196261215Simp DPRINT("Character literal: %s\n", yytext); 197261215Simp 198261215Simp d = data_copy_escape_string(yytext+1, yyleng-2); 199261215Simp if (d.len == 1) { 200261215Simp lexical_error("Empty character literal"); 201261215Simp yylval.integer = 0; 202318102Sgonzo } else { 203318102Sgonzo yylval.integer = (unsigned char)d.val[0]; 204318102Sgonzo 205318102Sgonzo if (d.len > 2) 206318102Sgonzo lexical_error("Character literal has %d" 207318102Sgonzo " characters instead of 1", 208318102Sgonzo d.len - 1); 209261215Simp } 210261215Simp 211318102Sgonzo data_free(d); 212238742Simp return DT_CHAR_LITERAL; 213238742Simp } 214238742Simp 215238742Simp<*>\&{LABEL} { /* label reference */ 216204431Sraj DPRINT("Ref: %s\n", yytext+1); 217204433Sraj yylval.labelref = xstrdup(yytext+1); 218204431Sraj return DT_REF; 219204431Sraj } 220204431Sraj 221318102Sgonzo<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ 222204431Sraj yytext[yyleng-1] = '\0'; 223204431Sraj DPRINT("Ref: %s\n", yytext+2); 224204433Sraj yylval.labelref = xstrdup(yytext+2); 225204431Sraj return DT_REF; 226204431Sraj } 227204431Sraj 228204431Sraj<BYTESTRING>[0-9a-fA-F]{2} { 229204431Sraj yylval.byte = strtol(yytext, NULL, 16); 230204431Sraj DPRINT("Byte: %02x\n", (int)yylval.byte); 231204431Sraj return DT_BYTE; 232204431Sraj } 233204431Sraj 234204431Sraj<BYTESTRING>"]" { 235204431Sraj DPRINT("/BYTESTRING\n"); 236204431Sraj BEGIN_DEFAULT(); 237204431Sraj return ']'; 238204431Sraj } 239204431Sraj 240261215Simp<PROPNODENAME>\\?{PROPNODECHAR}+ { 241204431Sraj DPRINT("PropNodeName: %s\n", yytext); 242261215Simp yylval.propnodename = xstrdup((yytext[0] == '\\') ? 243261215Simp yytext + 1 : yytext); 244204431Sraj BEGIN_DEFAULT(); 245204431Sraj return DT_PROPNODENAME; 246204431Sraj } 247204431Sraj 248204431Sraj"/incbin/" { 249204431Sraj DPRINT("Binary Include\n"); 250204431Sraj return DT_INCBIN; 251204431Sraj } 252204431Sraj 253204431Sraj<*>{WS}+ /* eat whitespace */ 254204431Sraj<*>{COMMENT}+ /* eat C-style comments */ 255204431Sraj<*>{LINECOMMENT}+ /* eat C++-style comments */ 256204431Sraj 257238742Simp<*>"<<" { return DT_LSHIFT; }; 258238742Simp<*>">>" { return DT_RSHIFT; }; 259238742Simp<*>"<=" { return DT_LE; }; 260238742Simp<*>">=" { return DT_GE; }; 261238742Simp<*>"==" { return DT_EQ; }; 262238742Simp<*>"!=" { return DT_NE; }; 263238742Simp<*>"&&" { return DT_AND; }; 264238742Simp<*>"||" { return DT_OR; }; 265238742Simp 266204431Sraj<*>. { 267204431Sraj DPRINT("Char: %c (\\x%02x)\n", yytext[0], 268204431Sraj (unsigned)yytext[0]); 269204431Sraj if (yytext[0] == '[') { 270204431Sraj DPRINT("<BYTESTRING>\n"); 271204431Sraj BEGIN(BYTESTRING); 272204431Sraj } 273204431Sraj if ((yytext[0] == '{') 274204431Sraj || (yytext[0] == ';')) { 275204431Sraj DPRINT("<PROPNODENAME>\n"); 276204431Sraj BEGIN(PROPNODENAME); 277204431Sraj } 278204431Sraj return yytext[0]; 279204431Sraj } 280204431Sraj 281204431Sraj%% 282204431Sraj 283204431Srajstatic void push_input_file(const char *filename) 284204431Sraj{ 285204431Sraj assert(filename); 286204431Sraj 287239998Sandrew assert(include_stack_pointer < MAX_INCLUDE_NESTING); 288204431Sraj 289238742Simp srcfile_push(filename); 290204431Sraj 291238742Simp yyin = current_srcfile->f; 292204431Sraj 293238742Simp include_stack[include_stack_pointer++] = YY_CURRENT_BUFFER; 294204431Sraj 295204431Sraj yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 296204431Sraj} 297204431Sraj 298204431Sraj 299261215Simpstatic bool pop_input_file(void) 300204431Sraj{ 301238742Simp if (srcfile_pop() == 0) 302261215Simp return false; 303204431Sraj 304238742Simp assert(include_stack_pointer > 0); 305204431Sraj 306238742Simp yy_delete_buffer( YY_CURRENT_BUFFER ); 307204431Sraj 308238742Simp yy_switch_to_buffer( include_stack[--include_stack_pointer] ); 309204431Sraj 310238742Simp yyin = current_srcfile->f; 311204431Sraj 312261215Simp return true; 313204431Sraj} 314261215Simp 315261215Simpstatic void lexical_error(const char *fmt, ...) 316261215Simp{ 317261215Simp va_list ap; 318261215Simp 319261215Simp va_start(ap, fmt); 320261215Simp srcpos_verror(&yylloc, "Lexical error", fmt, ap); 321261215Simp va_end(ap); 322261215Simp 323261215Simp treesource_error = true; 324261215Simp} 325