/* * (C) Copyright David Gibson , IBM Corporation. 2005. * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ %option noyywrap nounput yylineno %x INCLUDE %x CELLDATA %x BYTESTRING %x MEMRESERVE PROPCHAR [a-zA-Z0-9,._+*#?-] UNITCHAR [0-9a-f,] WS [[:space:]] REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@]) %{ #include "dtc.h" #include "srcpos.h" #include "dtc-parser.tab.h" /*#define LEXDEBUG 1*/ #ifdef LEXDEBUG #define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) #else #define DPRINT(fmt, ...) do { } while (0) #endif %} %% "/include/" BEGIN(INCLUDE); \"[^"\n]*\" { yytext[strlen(yytext) - 1] = 0; if (!push_input_file(yytext + 1)) { /* Some unrecoverable error.*/ exit(1); } BEGIN(INITIAL); } <> { if (!pop_input_file()) { yyterminate(); } } \"[^"]*\" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("String: %s\n", yytext); yylval.data = data_copy_escape_string(yytext+1, yyleng-2); yylloc.first_line = yylineno; return DT_STRING; } "/memreserve/" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Keyword: /memreserve/\n"); BEGIN(MEMRESERVE); return DT_MEMRESERVE; } [0-9a-fA-F]+ { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; if (yyleng > 2*sizeof(yylval.addr)) { fprintf(stderr, "Address value %s too large\n", yytext); } yylval.addr = (u64) strtoull(yytext, NULL, 16); DPRINT("Addr: %llx\n", (unsigned long long)yylval.addr); return DT_ADDR; } ";" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("/MEMRESERVE\n"); BEGIN(INITIAL); return ';'; } <*>[a-zA-Z_][a-zA-Z0-9_]*: { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Label: %s\n", yytext); yylval.str = strdup(yytext); yylval.str[yyleng-1] = '\0'; return DT_LABEL; } [bodh]# { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; if (*yytext == 'b') yylval.cbase = 2; else if (*yytext == 'o') yylval.cbase = 8; else if (*yytext == 'd') yylval.cbase = 10; else yylval.cbase = 16; DPRINT("Base: %d\n", yylval.cbase); return DT_BASE; } [0-9a-fA-F]+ { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; yylval.str = strdup(yytext); DPRINT("Cell: '%s'\n", yylval.str); return DT_CELL; } ">" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("/CELLDATA\n"); BEGIN(INITIAL); return '>'; } \&{REFCHAR}* { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Ref: %s\n", yytext+1); yylval.str = strdup(yytext+1); return DT_REF; } [0-9a-fA-F]{2} { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; yylval.byte = strtol(yytext, NULL, 16); DPRINT("Byte: %02x\n", (int)yylval.byte); return DT_BYTE; } "]" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("/BYTESTRING\n"); BEGIN(INITIAL); return ']'; } , { /* Technically this is a valid property name, but we'd rather use it as punctuation, so detect it here in preference */ yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Char (propname like): %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); return yytext[0]; } {PROPCHAR}+ { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("PropName: %s\n", yytext); yylval.str = strdup(yytext); return DT_PROPNAME; } {PROPCHAR}+(@{UNITCHAR}+)? { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("NodeName: %s\n", yytext); yylval.str = strdup(yytext); return DT_NODENAME; } <*>{WS}+ /* eat whitespace */ <*>"/*"([^*]|\*+[^*/])*\*+"/" { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; DPRINT("Comment: %s\n", yytext); /* eat comments */ } <*>"//".*\n /* eat line comments */ <*>. { yylloc.filenum = srcpos_filenum; yylloc.first_line = yylineno; switch (yytext[0]) { case '<': DPRINT("CELLDATA\n"); BEGIN(CELLDATA); break; case '[': DPRINT("BYTESTRING\n"); BEGIN(BYTESTRING); break; default: DPRINT("Char: %c (\\x%02x)\n", yytext[0], (unsigned)yytext[0]); break; } return yytext[0]; } %% /* * Stack of nested include file contexts. */ struct incl_file { int filenum; FILE *file; YY_BUFFER_STATE yy_prev_buf; int yy_prev_lineno; struct incl_file *prev; }; struct incl_file *incl_file_stack; /* * Detect infinite include recursion. */ #define MAX_INCLUDE_DEPTH (100) static int incl_depth = 0; int push_input_file(const char *filename) { FILE *f; struct incl_file *incl_file; if (!filename) { yyerror("No include file name given."); return 0; } if (incl_depth++ >= MAX_INCLUDE_DEPTH) { yyerror("Includes nested too deeply"); return 0; } f = dtc_open_file(filename); incl_file = malloc(sizeof(struct incl_file)); if (!incl_file) { yyerror("Can not allocate include file space."); return 0; } /* * Save current context. */ incl_file->yy_prev_buf = YY_CURRENT_BUFFER; incl_file->yy_prev_lineno = yylineno; incl_file->filenum = srcpos_filenum; incl_file->file = yyin; incl_file->prev = incl_file_stack; incl_file_stack = incl_file; /* * Establish new context. */ srcpos_filenum = lookup_file_name(filename, 0); yylineno = 1; yyin = f; yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); return 1; } int pop_input_file(void) { struct incl_file *incl_file; if (incl_file_stack == 0) return 0; fclose(yyin); /* * Pop. */ --incl_depth; incl_file = incl_file_stack; incl_file_stack = incl_file->prev; /* * Recover old context. */ yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(incl_file->yy_prev_buf); yylineno = incl_file->yy_prev_lineno; srcpos_filenum = incl_file->filenum; yyin = incl_file->file; /* * Free old state. */ free(incl_file); if (YY_CURRENT_BUFFER == 0) return 0; return 1; }