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 nounput yylineno 22 23 %x INCLUDE 24 %x BYTESTRING 25 %x PROPNODENAME 26 %s V1 27 28 PROPNODECHAR [a-zA-Z0-9,._+*#?@-] 29 PATHCHAR ({PROPNODECHAR}|[/]) 30 LABEL [a-zA-Z_][a-zA-Z0-9_]* 31 STRING \"([^\\"]|\\.)*\" 32 WS [[:space:]] 33 COMMENT "/*"([^*]|\*+[^*/])*\*+"/" 34 LINECOMMENT "//".*\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 50 static 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 60 static void push_input_file(const char *filename); 61 static 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 229 struct 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 236 static struct incl_file *incl_file_stack; 237 238 239 /* 240 * Detect infinite include recursion. 241 */ 242 #define MAX_INCLUDE_DEPTH (100) 243 244 static int incl_depth = 0; 245 246 247 static 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 289 static 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