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 never-interactive 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 CHAR_LITERAL '([^']|\\')*' 33 WS [[:space:]] 34 COMMENT "/*"([^*]|\*+[^*/])*\*+"/" 35 LINECOMMENT "//".*\n 36 37 %{ 38 #include "dtc.h" 39 #include "srcpos.h" 40 #include "dtc-parser.tab.h" 41 42 #define MAX_INCLUDE_NESTING 100 43 YY_BUFFER_STATE include_stack[MAX_INCLUDE_NESTING]; 44 int include_stack_pointer = 0; 45 46 YYLTYPE yylloc; 47 extern bool treesource_error; 48 49 /* CAUTION: this will stop working if we ever use yyless() or yyunput() */ 50 #define YY_USER_ACTION \ 51 { \ 52 srcpos_update(&yylloc, yytext, yyleng); \ 53 } 54 55 /*#define LEXDEBUG 1*/ 56 57 #ifdef LEXDEBUG 58 #define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) 59 #else 60 #define DPRINT(fmt, ...) do { } while (0) 61 #endif 62 63 static int dts_version = 1; 64 65 #define BEGIN_DEFAULT() DPRINT("<V1>\n"); \ 66 BEGIN(V1); \ 67 68 static void push_input_file(const char *filename); 69 static bool pop_input_file(void); 70 static void lexical_error(const char *fmt, ...); 71 %} 72 73 %% 74 <*>"/include/"{WS}*{STRING} { 75 char *name = strchr(yytext, '\"') + 1; 76 yytext[yyleng-1] = '\0'; 77 push_input_file(name); 78 } 79 80 <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? { 81 char *line, *tmp, *fn; 82 /* skip text before line # */ 83 line = yytext; 84 while (!isdigit((unsigned char)*line)) 85 line++; 86 /* skip digits in line # */ 87 tmp = line; 88 while (!isspace((unsigned char)*tmp)) 89 tmp++; 90 /* "NULL"-terminate line # */ 91 *tmp = '\0'; 92 /* start of filename */ 93 fn = strchr(tmp + 1, '"') + 1; 94 /* strip trailing " from filename */ 95 tmp = strchr(fn, '"'); 96 *tmp = 0; 97 /* -1 since #line is the number of the next line */ 98 srcpos_set_line(xstrdup(fn), atoi(line) - 1); 99 } 100 101 <*><<EOF>> { 102 if (!pop_input_file()) { 103 yyterminate(); 104 } 105 } 106 107 <*>{STRING} { 108 DPRINT("String: %s\n", yytext); 109 yylval.data = data_copy_escape_string(yytext+1, 110 yyleng-2); 111 return DT_STRING; 112 } 113 114 <*>"/dts-v1/" { 115 DPRINT("Keyword: /dts-v1/\n"); 116 dts_version = 1; 117 BEGIN_DEFAULT(); 118 return DT_V1; 119 } 120 121 <*>"/memreserve/" { 122 DPRINT("Keyword: /memreserve/\n"); 123 BEGIN_DEFAULT(); 124 return DT_MEMRESERVE; 125 } 126 127 <*>"/bits/" { 128 DPRINT("Keyword: /bits/\n"); 129 BEGIN_DEFAULT(); 130 return DT_BITS; 131 } 132 133 <*>"/delete-property/" { 134 DPRINT("Keyword: /delete-property/\n"); 135 DPRINT("<PROPNODENAME>\n"); 136 BEGIN(PROPNODENAME); 137 return DT_DEL_PROP; 138 } 139 140 <*>"/delete-node/" { 141 DPRINT("Keyword: /delete-node/\n"); 142 DPRINT("<PROPNODENAME>\n"); 143 BEGIN(PROPNODENAME); 144 return DT_DEL_NODE; 145 } 146 147 <*>{LABEL}: { 148 DPRINT("Label: %s\n", yytext); 149 yylval.labelref = xstrdup(yytext); 150 yylval.labelref[yyleng-1] = '\0'; 151 return DT_LABEL; 152 } 153 154 <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? { 155 char *e; 156 DPRINT("Integer Literal: '%s'\n", yytext); 157 158 errno = 0; 159 yylval.integer = strtoull(yytext, &e, 0); 160 161 assert(!(*e) || !e[strspn(e, "UL")]); 162 163 if (errno == ERANGE) 164 lexical_error("Integer literal '%s' out of range", 165 yytext); 166 else 167 /* ERANGE is the only strtoull error triggerable 168 * by strings matching the pattern */ 169 assert(errno == 0); 170 return DT_LITERAL; 171 } 172 173 <*>{CHAR_LITERAL} { 174 struct data d; 175 DPRINT("Character literal: %s\n", yytext); 176 177 d = data_copy_escape_string(yytext+1, yyleng-2); 178 if (d.len == 1) { 179 lexical_error("Empty character literal"); 180 yylval.integer = 0; 181 return DT_CHAR_LITERAL; 182 } 183 184 yylval.integer = (unsigned char)d.val[0]; 185 186 if (d.len > 2) 187 lexical_error("Character literal has %d" 188 " characters instead of 1", 189 d.len - 1); 190 191 return DT_CHAR_LITERAL; 192 } 193 194 <*>\&{LABEL} { /* label reference */ 195 DPRINT("Ref: %s\n", yytext+1); 196 yylval.labelref = xstrdup(yytext+1); 197 return DT_REF; 198 } 199 200 <*>"&{/"{PATHCHAR}+\} { /* new-style path reference */ 201 yytext[yyleng-1] = '\0'; 202 DPRINT("Ref: %s\n", yytext+2); 203 yylval.labelref = xstrdup(yytext+2); 204 return DT_REF; 205 } 206 207 <BYTESTRING>[0-9a-fA-F]{2} { 208 yylval.byte = strtol(yytext, NULL, 16); 209 DPRINT("Byte: %02x\n", (int)yylval.byte); 210 return DT_BYTE; 211 } 212 213 <BYTESTRING>"]" { 214 DPRINT("/BYTESTRING\n"); 215 BEGIN_DEFAULT(); 216 return ']'; 217 } 218 219 <PROPNODENAME>\\?{PROPNODECHAR}+ { 220 DPRINT("PropNodeName: %s\n", yytext); 221 yylval.propnodename = xstrdup((yytext[0] == '\\') ? 222 yytext + 1 : yytext); 223 BEGIN_DEFAULT(); 224 return DT_PROPNODENAME; 225 } 226 227 "/incbin/" { 228 DPRINT("Binary Include\n"); 229 return DT_INCBIN; 230 } 231 232 <*>{WS}+ /* eat whitespace */ 233 <*>{COMMENT}+ /* eat C-style comments */ 234 <*>{LINECOMMENT}+ /* eat C++-style comments */ 235 236 <*>"<<" { return DT_LSHIFT; }; 237 <*>">>" { return DT_RSHIFT; }; 238 <*>"<=" { return DT_LE; }; 239 <*>">=" { return DT_GE; }; 240 <*>"==" { return DT_EQ; }; 241 <*>"!=" { return DT_NE; }; 242 <*>"&&" { return DT_AND; }; 243 <*>"||" { return DT_OR; }; 244 245 <*>. { 246 DPRINT("Char: %c (\\x%02x)\n", yytext[0], 247 (unsigned)yytext[0]); 248 if (yytext[0] == '[') { 249 DPRINT("<BYTESTRING>\n"); 250 BEGIN(BYTESTRING); 251 } 252 if ((yytext[0] == '{') 253 || (yytext[0] == ';')) { 254 DPRINT("<PROPNODENAME>\n"); 255 BEGIN(PROPNODENAME); 256 } 257 return yytext[0]; 258 } 259 260 %% 261 262 static void push_input_file(const char *filename) 263 { 264 assert(filename); 265 266 assert(include_stack_pointer < MAX_INCLUDE_NESTING); 267 268 srcfile_push(filename); 269 270 yyin = current_srcfile->f; 271 272 include_stack[include_stack_pointer++] = YY_CURRENT_BUFFER; 273 274 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 275 } 276 277 278 static bool pop_input_file(void) 279 { 280 if (srcfile_pop() == 0) 281 return false; 282 283 assert(include_stack_pointer > 0); 284 285 yy_delete_buffer( YY_CURRENT_BUFFER ); 286 287 yy_switch_to_buffer( include_stack[--include_stack_pointer] ); 288 289 yyin = current_srcfile->f; 290 291 return true; 292 } 293 294 static void lexical_error(const char *fmt, ...) 295 { 296 va_list ap; 297 298 va_start(ap, fmt); 299 srcpos_verror(&yylloc, "Lexical error", fmt, ap); 300 va_end(ap); 301 302 treesource_error = true; 303 } 304