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