1/* 2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 3 * 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the 8 * License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 18 * USA 19 */ 20 21%option noyywrap noinput nounput yylineno 22 23%x INCLUDE 24%x BYTESTRING 25%x PROPNODENAME 26%s V1 27 28PROPNODECHAR [a-zA-Z0-9,._+*#?@-] 29PATHCHAR ({PROPNODECHAR}|[/]) 30LABEL [a-zA-Z_][a-zA-Z0-9_]* 31STRING \"([^\\"]|\\.)*\" 32WS [[:space:]] 33COMMENT "/*"([^*]|\*+[^*/])*\*+"/" 34LINECOMMENT "//".*\n 35 36%{ 37#include "dtc.h" 38#include "srcpos.h" 39#include "dtc-parser.tab.h" 40 41 42/*#define LEXDEBUG 1*/ 43 44#ifdef LEXDEBUG 45#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) 46#else 47#define DPRINT(fmt, ...) do { } while (0) 48#endif 49 50static int dts_version; /* = 0 */ 51 52#define BEGIN_DEFAULT() if (dts_version == 0) { \ 53 DPRINT("<INITIAL>\n"); \ 54 BEGIN(INITIAL); \ 55 } else { \ 56 DPRINT("<V1>\n"); \ 57 BEGIN(V1); \ 58 } 59 60static void push_input_file(const char *filename); 61static int pop_input_file(void); 62%} 63 64%% 65<*>"/include/"{WS}*{STRING} { 66 char *name = strchr(yytext, '\"') + 1; 67 yytext[yyleng-1] = '\0'; 68 push_input_file(name); 69 } 70 71<*><<EOF>> { 72 if (!pop_input_file()) { 73 yyterminate(); 74 } 75 } 76 77<*>{STRING} { 78 yylloc.file = srcpos_file; 79 yylloc.first_line = yylineno; 80 DPRINT("String: %s\n", yytext); 81 yylval.data = data_copy_escape_string(yytext+1, 82 yyleng-2); 83 yylloc.first_line = yylineno; 84 return DT_STRING; 85 } 86 87<*>"/dts-v1/" { 88 yylloc.file = srcpos_file; 89 yylloc.first_line = yylineno; 90 DPRINT("Keyword: /dts-v1/\n"); 91 dts_version = 1; 92 BEGIN_DEFAULT(); 93 return DT_V1; 94 } 95 96<*>"/memreserve/" { 97 yylloc.file = srcpos_file; 98 yylloc.first_line = yylineno; 99 DPRINT("Keyword: /memreserve/\n"); 100 BEGIN_DEFAULT(); 101 return DT_MEMRESERVE; 102 } 103 104<*>{LABEL}: { 105 yylloc.file = srcpos_file; 106 yylloc.first_line = yylineno; 107 DPRINT("Label: %s\n", yytext); 108 yylval.labelref = strdup(yytext); 109 yylval.labelref[yyleng-1] = '\0'; 110 return DT_LABEL; 111 } 112 113<INITIAL>[bodh]# { 114 yylloc.file = srcpos_file; 115 yylloc.first_line = yylineno; 116 if (*yytext == 'b') 117 yylval.cbase = 2; 118 else if (*yytext == 'o') 119 yylval.cbase = 8; 120 else if (*yytext == 'd') 121 yylval.cbase = 10; 122 else 123 yylval.cbase = 16; 124 DPRINT("Base: %d\n", yylval.cbase); 125 return DT_BASE; 126 } 127 128<INITIAL>[0-9a-fA-F]+ { 129 yylloc.file = srcpos_file; 130 yylloc.first_line = yylineno; 131 yylval.literal = strdup(yytext); 132 DPRINT("Literal: '%s'\n", yylval.literal); 133 return DT_LEGACYLITERAL; 134 } 135 136<V1>[0-9]+|0[xX][0-9a-fA-F]+ { 137 yylloc.file = srcpos_file; 138 yylloc.first_line = yylineno; 139 yylval.literal = strdup(yytext); 140 DPRINT("Literal: '%s'\n", yylval.literal); 141 return DT_LITERAL; 142 } 143 144\&{LABEL} { /* label reference */ 145 yylloc.file = srcpos_file; 146 yylloc.first_line = yylineno; 147 DPRINT("Ref: %s\n", yytext+1); 148 yylval.labelref = strdup(yytext+1); 149 return DT_REF; 150 } 151 152"&{/"{PATHCHAR}+\} { /* new-style path reference */ 153 yylloc.file = srcpos_file; 154 yylloc.first_line = yylineno; 155 yytext[yyleng-1] = '\0'; 156 DPRINT("Ref: %s\n", yytext+2); 157 yylval.labelref = strdup(yytext+2); 158 return DT_REF; 159 } 160 161<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */ 162 yylloc.file = srcpos_file; 163 yylloc.first_line = yylineno; 164 DPRINT("Ref: %s\n", yytext+1); 165 yylval.labelref = strdup(yytext+1); 166 return DT_REF; 167 } 168 169<BYTESTRING>[0-9a-fA-F]{2} { 170 yylloc.file = srcpos_file; 171 yylloc.first_line = yylineno; 172 yylval.byte = strtol(yytext, NULL, 16); 173 DPRINT("Byte: %02x\n", (int)yylval.byte); 174 return DT_BYTE; 175 } 176 177<BYTESTRING>"]" { 178 yylloc.file = srcpos_file; 179 yylloc.first_line = yylineno; 180 DPRINT("/BYTESTRING\n"); 181 BEGIN_DEFAULT(); 182 return ']'; 183 } 184 185<PROPNODENAME>{PROPNODECHAR}+ { 186 yylloc.file = srcpos_file; 187 yylloc.first_line = yylineno; 188 DPRINT("PropNodeName: %s\n", yytext); 189 yylval.propnodename = strdup(yytext); 190 BEGIN_DEFAULT(); 191 return DT_PROPNODENAME; 192 } 193 194"/incbin/" { 195 yylloc.file = srcpos_file; 196 yylloc.first_line = yylineno; 197 DPRINT("Binary Include\n"); 198 return DT_INCBIN; 199 } 200 201<*>{WS}+ /* eat whitespace */ 202<*>{COMMENT}+ /* eat C-style comments */ 203<*>{LINECOMMENT}+ /* eat C++-style comments */ 204 205<*>. { 206 yylloc.file = srcpos_file; 207 yylloc.first_line = yylineno; 208 DPRINT("Char: %c (\\x%02x)\n", yytext[0], 209 (unsigned)yytext[0]); 210 if (yytext[0] == '[') { 211 DPRINT("<BYTESTRING>\n"); 212 BEGIN(BYTESTRING); 213 } 214 if ((yytext[0] == '{') 215 || (yytext[0] == ';')) { 216 DPRINT("<PROPNODENAME>\n"); 217 BEGIN(PROPNODENAME); 218 } 219 return yytext[0]; 220 } 221 222%% 223 224 225/* 226 * Stack of nested include file contexts. 227 */ 228 229struct incl_file { 230 struct dtc_file *file; 231 YY_BUFFER_STATE yy_prev_buf; 232 int yy_prev_lineno; 233 struct incl_file *prev; 234}; 235 236static struct incl_file *incl_file_stack; 237 238 239/* 240 * Detect infinite include recursion. 241 */ 242#define MAX_INCLUDE_DEPTH (100) 243 244static int incl_depth = 0; 245 246 247static void push_input_file(const char *filename) 248{ 249 struct incl_file *incl_file; 250 struct dtc_file *newfile; 251 struct search_path search, *searchptr = NULL; 252 253 assert(filename); 254 255 if (incl_depth++ >= MAX_INCLUDE_DEPTH) 256 die("Includes nested too deeply"); 257 258 if (srcpos_file) { 259 search.dir = srcpos_file->dir; 260 search.next = NULL; 261 search.prev = NULL; 262 searchptr = &search; 263 } 264 265 newfile = dtc_open_file(filename, searchptr); 266 267 incl_file = xmalloc(sizeof(struct incl_file)); 268 269 /* 270 * Save current context. 271 */ 272 incl_file->yy_prev_buf = YY_CURRENT_BUFFER; 273 incl_file->yy_prev_lineno = yylineno; 274 incl_file->file = srcpos_file; 275 incl_file->prev = incl_file_stack; 276 277 incl_file_stack = incl_file; 278 279 /* 280 * Establish new context. 281 */ 282 srcpos_file = newfile; 283 yylineno = 1; 284 yyin = newfile->file; 285 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 286} 287 288 289static int pop_input_file(void) 290{ 291 struct incl_file *incl_file; 292 293 if (incl_file_stack == 0) 294 return 0; 295 296 dtc_close_file(srcpos_file); 297 298 /* 299 * Pop. 300 */ 301 --incl_depth; 302 incl_file = incl_file_stack; 303 incl_file_stack = incl_file->prev; 304 305 /* 306 * Recover old context. 307 */ 308 yy_delete_buffer(YY_CURRENT_BUFFER); 309 yy_switch_to_buffer(incl_file->yy_prev_buf); 310 yylineno = incl_file->yy_prev_lineno; 311 srcpos_file = incl_file->file; 312 yyin = incl_file->file ? incl_file->file->file : NULL; 313 314 /* 315 * Free old state. 316 */ 317 free(incl_file); 318 319 return 1; 320} 321