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