dtc-lexer.l revision 204489
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 noinput 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 41YYLTYPE yylloc; 42 43#define YY_USER_ACTION \ 44 { \ 45 yylloc.file = srcpos_file; \ 46 yylloc.first_line = yylineno; \ 47 } 48 49/*#define LEXDEBUG 1*/ 50 51#ifdef LEXDEBUG 52#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) 53#else 54#define DPRINT(fmt, ...) do { } while (0) 55#endif 56 57static int dts_version = 1; 58 59#define BEGIN_DEFAULT() DPRINT("<V1>\n"); \ 60 BEGIN(V1); \ 61 62static void push_input_file(const char *filename); 63static int pop_input_file(void); 64%} 65 66%% 67<*>"/include/"{WS}*{STRING} { 68 char *name = strchr(yytext, '\"') + 1; 69 yytext[yyleng-1] = '\0'; 70 push_input_file(name); 71 } 72 73<*><<EOF>> { 74 if (!pop_input_file()) { 75 yyterminate(); 76 } 77 } 78 79<*>{STRING} { 80 DPRINT("String: %s\n", yytext); 81 yylval.data = data_copy_escape_string(yytext+1, 82 yyleng-2); 83 return DT_STRING; 84 } 85 86<*>"/dts-v1/" { 87 DPRINT("Keyword: /dts-v1/\n"); 88 dts_version = 1; 89 BEGIN_DEFAULT(); 90 return DT_V1; 91 } 92 93<*>"/memreserve/" { 94 DPRINT("Keyword: /memreserve/\n"); 95 BEGIN_DEFAULT(); 96 return DT_MEMRESERVE; 97 } 98 99<*>{LABEL}: { 100 DPRINT("Label: %s\n", yytext); 101 yylval.labelref = xstrdup(yytext); 102 yylval.labelref[yyleng-1] = '\0'; 103 return DT_LABEL; 104 } 105 106<V1>[0-9]+|0[xX][0-9a-fA-F]+ { 107 yylval.literal = xstrdup(yytext); 108 DPRINT("Literal: '%s'\n", yylval.literal); 109 return DT_LITERAL; 110 } 111 112\&{LABEL} { /* label reference */ 113 DPRINT("Ref: %s\n", yytext+1); 114 yylval.labelref = xstrdup(yytext+1); 115 return DT_REF; 116 } 117 118"&{/"{PATHCHAR}+\} { /* new-style path reference */ 119 yytext[yyleng-1] = '\0'; 120 DPRINT("Ref: %s\n", yytext+2); 121 yylval.labelref = xstrdup(yytext+2); 122 return DT_REF; 123 } 124 125<BYTESTRING>[0-9a-fA-F]{2} { 126 yylval.byte = strtol(yytext, NULL, 16); 127 DPRINT("Byte: %02x\n", (int)yylval.byte); 128 return DT_BYTE; 129 } 130 131<BYTESTRING>"]" { 132 DPRINT("/BYTESTRING\n"); 133 BEGIN_DEFAULT(); 134 return ']'; 135 } 136 137<PROPNODENAME>{PROPNODECHAR}+ { 138 DPRINT("PropNodeName: %s\n", yytext); 139 yylval.propnodename = xstrdup(yytext); 140 BEGIN_DEFAULT(); 141 return DT_PROPNODENAME; 142 } 143 144"/incbin/" { 145 DPRINT("Binary Include\n"); 146 return DT_INCBIN; 147 } 148 149<*>{WS}+ /* eat whitespace */ 150<*>{COMMENT}+ /* eat C-style comments */ 151<*>{LINECOMMENT}+ /* eat C++-style comments */ 152 153<*>. { 154 DPRINT("Char: %c (\\x%02x)\n", yytext[0], 155 (unsigned)yytext[0]); 156 if (yytext[0] == '[') { 157 DPRINT("<BYTESTRING>\n"); 158 BEGIN(BYTESTRING); 159 } 160 if ((yytext[0] == '{') 161 || (yytext[0] == ';')) { 162 DPRINT("<PROPNODENAME>\n"); 163 BEGIN(PROPNODENAME); 164 } 165 return yytext[0]; 166 } 167 168%% 169 170 171/* 172 * Stack of nested include file contexts. 173 */ 174 175struct incl_file { 176 struct dtc_file *file; 177 YY_BUFFER_STATE yy_prev_buf; 178 int yy_prev_lineno; 179 struct incl_file *prev; 180}; 181 182static struct incl_file *incl_file_stack; 183 184 185/* 186 * Detect infinite include recursion. 187 */ 188#define MAX_INCLUDE_DEPTH (100) 189 190static int incl_depth = 0; 191 192 193static void push_input_file(const char *filename) 194{ 195 struct incl_file *incl_file; 196 struct dtc_file *newfile; 197 struct search_path search, *searchptr = NULL; 198 199 assert(filename); 200 201 if (incl_depth++ >= MAX_INCLUDE_DEPTH) 202 die("Includes nested too deeply"); 203 204 if (srcpos_file) { 205 search.dir = srcpos_file->dir; 206 search.next = NULL; 207 search.prev = NULL; 208 searchptr = &search; 209 } 210 211 newfile = dtc_open_file(filename, searchptr); 212 213 incl_file = xmalloc(sizeof(struct incl_file)); 214 215 /* 216 * Save current context. 217 */ 218 incl_file->yy_prev_buf = YY_CURRENT_BUFFER; 219 incl_file->yy_prev_lineno = yylineno; 220 incl_file->file = srcpos_file; 221 incl_file->prev = incl_file_stack; 222 223 incl_file_stack = incl_file; 224 225 /* 226 * Establish new context. 227 */ 228 srcpos_file = newfile; 229 yylineno = 1; 230 yyin = newfile->file; 231 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 232} 233 234 235static int pop_input_file(void) 236{ 237 struct incl_file *incl_file; 238 239 if (incl_file_stack == 0) 240 return 0; 241 242 dtc_close_file(srcpos_file); 243 244 /* 245 * Pop. 246 */ 247 --incl_depth; 248 incl_file = incl_file_stack; 249 incl_file_stack = incl_file->prev; 250 251 /* 252 * Recover old context. 253 */ 254 yy_delete_buffer(YY_CURRENT_BUFFER); 255 yy_switch_to_buffer(incl_file->yy_prev_buf); 256 yylineno = incl_file->yy_prev_lineno; 257 srcpos_file = incl_file->file; 258 yyin = incl_file->file ? incl_file->file->file : NULL; 259 260 /* 261 * Free old state. 262 */ 263 free(incl_file); 264 265 return 1; 266} 267