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 INCLUDE 24204431Sraj%x BYTESTRING 25204431Sraj%x PROPNODENAME 26204431Sraj%s V1 27204431Sraj 28204431SrajPROPNODECHAR [a-zA-Z0-9,._+*#?@-] 29204431SrajPATHCHAR ({PROPNODECHAR}|[/]) 30204431SrajLABEL [a-zA-Z_][a-zA-Z0-9_]* 31204431SrajSTRING \"([^\\"]|\\.)*\" 32238742SimpCHAR_LITERAL '([^']|\\')*' 33204431SrajWS [[:space:]] 34204431SrajCOMMENT "/*"([^*]|\*+[^*/])*\*+"/" 35204431SrajLINECOMMENT "//".*\n 36204431Sraj 37204431Sraj%{ 38204431Sraj#include "dtc.h" 39204431Sraj#include "srcpos.h" 40204431Sraj#include "dtc-parser.tab.h" 41204431Sraj 42238742Simp#define MAX_INCLUDE_NESTING 100 43238742SimpYY_BUFFER_STATE include_stack[MAX_INCLUDE_NESTING]; 44238742Simpint include_stack_pointer = 0; 45238742Simp 46204489SrajYYLTYPE yylloc; 47266130Sianextern bool treesource_error; 48204489Sraj 49238742Simp/* CAUTION: this will stop working if we ever use yyless() or yyunput() */ 50204433Sraj#define YY_USER_ACTION \ 51204433Sraj { \ 52238742Simp srcpos_update(&yylloc, yytext, yyleng); \ 53204433Sraj } 54204431Sraj 55204431Sraj/*#define LEXDEBUG 1*/ 56204431Sraj 57204431Sraj#ifdef LEXDEBUG 58204431Sraj#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) 59204431Sraj#else 60204431Sraj#define DPRINT(fmt, ...) do { } while (0) 61204431Sraj#endif 62204431Sraj 63204433Srajstatic int dts_version = 1; 64204431Sraj 65204433Sraj#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \ 66204431Sraj BEGIN(V1); \ 67204431Sraj 68204431Srajstatic void push_input_file(const char *filename); 69266130Sianstatic bool pop_input_file(void); 70266130Sianstatic void lexical_error(const char *fmt, ...); 71204431Sraj%} 72204431Sraj 73204431Sraj%% 74204431Sraj<*>"/include/"{WS}*{STRING} { 75204431Sraj char *name = strchr(yytext, '\"') + 1; 76204431Sraj yytext[yyleng-1] = '\0'; 77204431Sraj push_input_file(name); 78204431Sraj } 79204431Sraj 80266130Sian<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { 81266130Sian char *line, *tmp, *fn; 82266130Sian /* skip text before line # */ 83266130Sian line = yytext; 84266130Sian while (!isdigit((unsigned char)*line)) 85266130Sian line++; 86266130Sian /* skip digits in line # */ 87266130Sian tmp = line; 88266130Sian while (!isspace((unsigned char)*tmp)) 89266130Sian tmp++; 90266130Sian /* "NULL"-terminate line # */ 91266130Sian *tmp = '\0'; 92266130Sian /* start of filename */ 93266130Sian fn = strchr(tmp + 1, '"') + 1; 94266130Sian /* strip trailing " from filename */ 95266130Sian tmp = strchr(fn, '"'); 96266130Sian *tmp = 0; 97266130Sian /* -1 since #line is the number of the next line */ 98266130Sian srcpos_set_line(xstrdup(fn), atoi(line) - 1); 99266130Sian } 100266130Sian 101204431Sraj<*><<EOF>> { 102204431Sraj if (!pop_input_file()) { 103204431Sraj yyterminate(); 104204431Sraj } 105204431Sraj } 106204431Sraj 107204431Sraj<*>{STRING} { 108204431Sraj DPRINT("String: %s\n", yytext); 109204431Sraj yylval.data = data_copy_escape_string(yytext+1, 110204431Sraj yyleng-2); 111204431Sraj return DT_STRING; 112204431Sraj } 113204431Sraj 114204431Sraj<*>"/dts-v1/" { 115204431Sraj DPRINT("Keyword: /dts-v1/\n"); 116204431Sraj dts_version = 1; 117204431Sraj BEGIN_DEFAULT(); 118204431Sraj return DT_V1; 119204431Sraj } 120204431Sraj 121204431Sraj<*>"/memreserve/" { 122204431Sraj DPRINT("Keyword: /memreserve/\n"); 123204431Sraj BEGIN_DEFAULT(); 124204431Sraj return DT_MEMRESERVE; 125204431Sraj } 126204431Sraj 127238742Simp<*>"/bits/" { 128238742Simp DPRINT("Keyword: /bits/\n"); 129238742Simp BEGIN_DEFAULT(); 130238742Simp return DT_BITS; 131238742Simp } 132238742Simp 133266130Sian<*>"/delete-property/" { 134266130Sian DPRINT("Keyword: /delete-property/\n"); 135266130Sian DPRINT("<PROPNODENAME>\n"); 136266130Sian BEGIN(PROPNODENAME); 137266130Sian return DT_DEL_PROP; 138266130Sian } 139266130Sian 140266130Sian<*>"/delete-node/" { 141266130Sian DPRINT("Keyword: /delete-node/\n"); 142266130Sian DPRINT("<PROPNODENAME>\n"); 143266130Sian BEGIN(PROPNODENAME); 144266130Sian return DT_DEL_NODE; 145266130Sian } 146266130Sian 147204431Sraj<*>{LABEL}: { 148204431Sraj DPRINT("Label: %s\n", yytext); 149204433Sraj yylval.labelref = xstrdup(yytext); 150204431Sraj yylval.labelref[yyleng-1] = '\0'; 151204431Sraj return DT_LABEL; 152204431Sraj } 153204431Sraj 154238742Simp<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { 155266130Sian char *e; 156266130Sian DPRINT("Integer Literal: '%s'\n", yytext); 157266130Sian 158266130Sian errno = 0; 159266130Sian yylval.integer = strtoull(yytext, &e, 0); 160266130Sian 161266130Sian assert(!(*e) || !e[strspn(e, "UL")]); 162266130Sian 163266130Sian if (errno == ERANGE) 164266130Sian lexical_error("Integer literal '%s' out of range", 165266130Sian yytext); 166266130Sian else 167266130Sian /* ERANGE is the only strtoull error triggerable 168266130Sian * by strings matching the pattern */ 169266130Sian assert(errno == 0); 170204431Sraj return DT_LITERAL; 171204431Sraj } 172204431Sraj 173238742Simp<*>{CHAR_LITERAL} { 174266130Sian struct data d; 175266130Sian DPRINT("Character literal: %s\n", yytext); 176266130Sian 177266130Sian d = data_copy_escape_string(yytext+1, yyleng-2); 178266130Sian if (d.len == 1) { 179266130Sian lexical_error("Empty character literal"); 180266130Sian yylval.integer = 0; 181266130Sian return DT_CHAR_LITERAL; 182266130Sian } 183266130Sian 184266130Sian yylval.integer = (unsigned char)d.val[0]; 185266130Sian 186266130Sian if (d.len > 2) 187266130Sian lexical_error("Character literal has %d" 188266130Sian " characters instead of 1", 189266130Sian d.len - 1); 190266130Sian 191238742Simp return DT_CHAR_LITERAL; 192238742Simp } 193238742Simp 194238742Simp<*>\&{LABEL} { /* label reference */ 195204431Sraj DPRINT("Ref: %s\n", yytext+1); 196204433Sraj yylval.labelref = xstrdup(yytext+1); 197204431Sraj return DT_REF; 198204431Sraj } 199204431Sraj 200238742Simp<*>"&{/"{PATHCHAR}+\} { /* new-style path reference */ 201204431Sraj yytext[yyleng-1] = '\0'; 202204431Sraj DPRINT("Ref: %s\n", yytext+2); 203204433Sraj yylval.labelref = xstrdup(yytext+2); 204204431Sraj return DT_REF; 205204431Sraj } 206204431Sraj 207204431Sraj<BYTESTRING>[0-9a-fA-F]{2} { 208204431Sraj yylval.byte = strtol(yytext, NULL, 16); 209204431Sraj DPRINT("Byte: %02x\n", (int)yylval.byte); 210204431Sraj return DT_BYTE; 211204431Sraj } 212204431Sraj 213204431Sraj<BYTESTRING>"]" { 214204431Sraj DPRINT("/BYTESTRING\n"); 215204431Sraj BEGIN_DEFAULT(); 216204431Sraj return ']'; 217204431Sraj } 218204431Sraj 219266130Sian<PROPNODENAME>\\?{PROPNODECHAR}+ { 220204431Sraj DPRINT("PropNodeName: %s\n", yytext); 221266130Sian yylval.propnodename = xstrdup((yytext[0] == '\\') ? 222266130Sian yytext + 1 : yytext); 223204431Sraj BEGIN_DEFAULT(); 224204431Sraj return DT_PROPNODENAME; 225204431Sraj } 226204431Sraj 227204431Sraj"/incbin/" { 228204431Sraj DPRINT("Binary Include\n"); 229204431Sraj return DT_INCBIN; 230204431Sraj } 231204431Sraj 232204431Sraj<*>{WS}+ /* eat whitespace */ 233204431Sraj<*>{COMMENT}+ /* eat C-style comments */ 234204431Sraj<*>{LINECOMMENT}+ /* eat C++-style comments */ 235204431Sraj 236238742Simp<*>"<<" { return DT_LSHIFT; }; 237238742Simp<*>">>" { return DT_RSHIFT; }; 238238742Simp<*>"<=" { return DT_LE; }; 239238742Simp<*>">=" { return DT_GE; }; 240238742Simp<*>"==" { return DT_EQ; }; 241238742Simp<*>"!=" { return DT_NE; }; 242238742Simp<*>"&&" { return DT_AND; }; 243238742Simp<*>"||" { return DT_OR; }; 244238742Simp 245204431Sraj<*>. { 246204431Sraj DPRINT("Char: %c (\\x%02x)\n", yytext[0], 247204431Sraj (unsigned)yytext[0]); 248204431Sraj if (yytext[0] == '[') { 249204431Sraj DPRINT("<BYTESTRING>\n"); 250204431Sraj BEGIN(BYTESTRING); 251204431Sraj } 252204431Sraj if ((yytext[0] == '{') 253204431Sraj || (yytext[0] == ';')) { 254204431Sraj DPRINT("<PROPNODENAME>\n"); 255204431Sraj BEGIN(PROPNODENAME); 256204431Sraj } 257204431Sraj return yytext[0]; 258204431Sraj } 259204431Sraj 260204431Sraj%% 261204431Sraj 262204431Srajstatic void push_input_file(const char *filename) 263204431Sraj{ 264204431Sraj assert(filename); 265204431Sraj 266239998Sandrew assert(include_stack_pointer < MAX_INCLUDE_NESTING); 267204431Sraj 268238742Simp srcfile_push(filename); 269204431Sraj 270238742Simp yyin = current_srcfile->f; 271204431Sraj 272238742Simp include_stack[include_stack_pointer++] = YY_CURRENT_BUFFER; 273204431Sraj 274204431Sraj yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 275204431Sraj} 276204431Sraj 277204431Sraj 278266130Sianstatic bool pop_input_file(void) 279204431Sraj{ 280238742Simp if (srcfile_pop() == 0) 281266130Sian return false; 282204431Sraj 283238742Simp assert(include_stack_pointer > 0); 284204431Sraj 285238742Simp yy_delete_buffer( YY_CURRENT_BUFFER ); 286204431Sraj 287238742Simp yy_switch_to_buffer( include_stack[--include_stack_pointer] ); 288204431Sraj 289238742Simp yyin = current_srcfile->f; 290204431Sraj 291266130Sian return true; 292204431Sraj} 293266130Sian 294266130Sianstatic void lexical_error(const char *fmt, ...) 295266130Sian{ 296266130Sian va_list ap; 297266130Sian 298266130Sian va_start(ap, fmt); 299266130Sian srcpos_verror(&yylloc, "Lexical error", fmt, ap); 300266130Sian va_end(ap); 301266130Sian 302266130Sian treesource_error = true; 303266130Sian} 304