| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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_]* | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 31 | STRING		\"([^\\"]|\\.)*\" | 
|  | 32 | WS		[[:space:]] | 
|  | 33 | COMMENT		"/*"([^*]|\*+[^*/])*\*+"/" | 
|  | 34 | LINECOMMENT	"//".*\n | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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 | } | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 59 |  | 
|  | 60 | static void push_input_file(const char *filename); | 
|  | 61 | static int pop_input_file(void); | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 62 | %} | 
|  | 63 |  | 
|  | 64 | %% | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 65 | <*>"/include/"{WS}*{STRING} { | 
|  | 66 | char *name = strchr(yytext, '\"') + 1; | 
|  | 67 | yytext[yyleng-1] = '\0'; | 
|  | 68 | push_input_file(name); | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 69 | } | 
|  | 70 |  | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 71 | <*><<EOF>>		{ | 
|  | 72 | if (!pop_input_file()) { | 
|  | 73 | yyterminate(); | 
|  | 74 | } | 
|  | 75 | } | 
|  | 76 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 77 | <*>{STRING}	{ | 
|  | 78 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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/"	{ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 88 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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/"	{ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 97 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 98 | yylloc.first_line = yylineno; | 
|  | 99 | DPRINT("Keyword: /memreserve/\n"); | 
|  | 100 | BEGIN_DEFAULT(); | 
|  | 101 | return DT_MEMRESERVE; | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | <*>{LABEL}:	{ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 105 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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]# { | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 114 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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]+	{ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 129 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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]+      { | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 137 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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 */ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 145 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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 */ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 153 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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 */ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 162 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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} { | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 170 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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>"]"	{ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 178 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 179 | yylloc.first_line = yylineno; | 
|  | 180 | DPRINT("/BYTESTRING\n"); | 
|  | 181 | BEGIN_DEFAULT(); | 
|  | 182 | return ']'; | 
|  | 183 | } | 
|  | 184 |  | 
|  | 185 | <PROPNODENAME>{PROPNODECHAR}+ { | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 186 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 194 | "/incbin/"	{ | 
|  | 195 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 196 | yylloc.first_line = yylineno; | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 197 | DPRINT("Binary Include\n"); | 
|  | 198 | return DT_INCBIN; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 199 | } | 
|  | 200 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 201 | <*>{WS}+	/* eat whitespace */ | 
|  | 202 | <*>{COMMENT}+	/* eat C-style comments */ | 
|  | 203 | <*>{LINECOMMENT}+ /* eat C++-style comments */ | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 204 |  | 
|  | 205 | <*>.		{ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 206 | yylloc.file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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 { | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 230 | struct dtc_file *file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 231 | YY_BUFFER_STATE yy_prev_buf; | 
|  | 232 | int yy_prev_lineno; | 
|  | 233 | struct incl_file *prev; | 
|  | 234 | }; | 
|  | 235 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 236 | static struct incl_file *incl_file_stack; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 237 |  | 
|  | 238 |  | 
|  | 239 | /* | 
|  | 240 | * Detect infinite include recursion. | 
|  | 241 | */ | 
|  | 242 | #define MAX_INCLUDE_DEPTH	(100) | 
|  | 243 |  | 
|  | 244 | static int incl_depth = 0; | 
|  | 245 |  | 
|  | 246 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 247 | static void push_input_file(const char *filename) | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 248 | { | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 249 | struct incl_file *incl_file; | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 250 | struct dtc_file *newfile; | 
|  | 251 | struct search_path search, *searchptr = NULL; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 252 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 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; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 263 | } | 
|  | 264 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 265 | newfile = dtc_open_file(filename, searchptr); | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 266 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 267 | incl_file = xmalloc(sizeof(struct incl_file)); | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 268 |  | 
|  | 269 | /* | 
|  | 270 | * Save current context. | 
|  | 271 | */ | 
|  | 272 | incl_file->yy_prev_buf = YY_CURRENT_BUFFER; | 
|  | 273 | incl_file->yy_prev_lineno = yylineno; | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 274 | incl_file->file = srcpos_file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 275 | incl_file->prev = incl_file_stack; | 
|  | 276 |  | 
|  | 277 | incl_file_stack = incl_file; | 
|  | 278 |  | 
|  | 279 | /* | 
|  | 280 | * Establish new context. | 
|  | 281 | */ | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 282 | srcpos_file = newfile; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 283 | yylineno = 1; | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 284 | yyin = newfile->file; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 285 | yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 286 | } | 
|  | 287 |  | 
|  | 288 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 289 | static int pop_input_file(void) | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 290 | { | 
|  | 291 | struct incl_file *incl_file; | 
|  | 292 |  | 
|  | 293 | if (incl_file_stack == 0) | 
|  | 294 | return 0; | 
|  | 295 |  | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 296 | dtc_close_file(srcpos_file); | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 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; | 
| David Gibson | ed95d74 | 2008-08-07 12:24:17 +1000 | [diff] [blame] | 311 | srcpos_file = incl_file->file; | 
|  | 312 | yyin = incl_file->file ? incl_file->file->file : NULL; | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 313 |  | 
|  | 314 | /* | 
|  | 315 | * Free old state. | 
|  | 316 | */ | 
|  | 317 | free(incl_file); | 
|  | 318 |  | 
| David Gibson | a4da2e3 | 2007-12-18 15:06:42 +1100 | [diff] [blame] | 319 | return 1; | 
|  | 320 | } |