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