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