dtc/dtc-lexer.l
David Gibson 2b67c632df dtc: Trivial lexer cleanups
This patch applies a couple of tiny cleanups to the lexer.  The
not-very-useful 'WS' named pattern is removed, and the debugging
printf() for single character tokens is moved to the top of the
action, which results in less confusing output when LEXDEBUG is
switched on (because it goes before the printf()s for possible
resulting lexer state changes).

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2007-12-05 08:27:37 -06:00

329 lines
6.8 KiB
Text

/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, 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 BYTESTRING
%x PROPNODENAME
%s V1
PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
PATHCHAR ({PROPNODECHAR}|[/])
LEGACYPATHCHAR [a-zA-Z0-9_@/]
LABEL [a-zA-Z_][a-zA-Z0-9_]*
%{
#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
static int dts_version; /* = 0 */
#define BEGIN_DEFAULT() if (dts_version == 0) { \
DPRINT("<INITIAL>\n"); \
BEGIN(INITIAL); \
} else { \
DPRINT("<V1>\n"); \
BEGIN(V1); \
}
%}
%%
<*>"/include/" BEGIN(INCLUDE);
<INCLUDE>\"[^"\n]*\" {
yytext[strlen(yytext) - 1] = 0;
if (!push_input_file(yytext + 1)) {
/* Some unrecoverable error.*/
exit(1);
}
BEGIN_DEFAULT();
}
<*><<EOF>> {
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;
}
<*>"/dts-v1/" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
BEGIN_DEFAULT();
return DT_V1;
}
<*>"/memreserve/" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
<*>{LABEL}: {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Label: %s\n", yytext);
yylval.labelref = strdup(yytext);
yylval.labelref[yyleng-1] = '\0';
return DT_LABEL;
}
<INITIAL>[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;
}
<INITIAL>[0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
yylval.literal = strdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LEGACYLITERAL;
}
<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
yylval.literal = strdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LITERAL;
}
\&{LABEL} { /* label reference */
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = strdup(yytext+1);
return DT_REF;
}
"&{/"{PATHCHAR}+\} { /* new-style path reference */
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = strdup(yytext+2);
return DT_REF;
}
<INITIAL>"&/"{LEGACYPATHCHAR}+ { /* old-style path reference */
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = strdup(yytext+1);
return DT_REF;
}
<BYTESTRING>[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;
}
<BYTESTRING>"]" {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
return ']';
}
<PROPNODENAME>{PROPNODECHAR}+ {
yylloc.filenum = srcpos_filenum;
yylloc.first_line = yylineno;
DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = strdup(yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
<*>[[:space:]]+ /* 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;
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
if (yytext[0] == '[') {
DPRINT("<BYTESTRING>\n");
BEGIN(BYTESTRING);
}
if ((yytext[0] == '{')
|| (yytext[0] == ';')) {
DPRINT("<PROPNODENAME>\n");
BEGIN(PROPNODENAME);
}
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;
}