blob: d1390777850d7dcdc4d94348d98a74810042fa97 [file] [log] [blame]
/*
* YAPP lexer
*
* Copyright (C) 2001 Michael Urman
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
%{
#include <util.h>
#define YASM_LIB_INTERNAL
#include <libyasm.h>
#include <errno.h>
#include "modules/preprocs/yapp/yapp-preproc.h"
#include "modules/preprocs/yapp/yapp-token.h"
#define yylval yapp_preproc_lval
#define malloc yasm_xmalloc
#define realloc yasm_xrealloc
/* starting size of string buffer */
#define STRBUF_ALLOC_SIZE 128
/* string buffer used when parsing strings/character constants */
static char *strbuf = (char *)NULL;
/* length of strbuf (including terminating NULL character) */
static size_t strbuf_size = 0;
/* include file mumbo jumbo */
static SLIST_HEAD(include_head, include_s) includes_head;
struct include_s {
SLIST_ENTRY(include_s) next;
YY_BUFFER_STATE include_state;
char *filename;
int line_number;
};
typedef struct include_s include;
char *yapp_preproc_current_file;
int yapp_preproc_line_number;
%}
%option noyywrap
%option nounput
%option case-insensitive
%option prefix="yapp_preproc_"
%option outfile="lex.yy.c"
%x D
%x incl
%x line
%x inhibit
DIGIT [0-9]
BINDIGIT [01]
OCTDIGIT [0-7]
HEXDIGIT [0-9a-f]
WS [ \t]
DIR %[ \t]*
%%
/* standard decimal integer */
{DIGIT}+ {
yylval.int_str_val.val = strtoul(yytext, (char **)NULL, 10);
yylval.int_str_val.str = yytext;
return INTNUM;
}
/* 10010011b - binary number */
{BINDIGIT}+b {
yylval.int_str_val.val = strtoul(yytext, (char **)NULL, 2);
yylval.int_str_val.str = yytext;
return INTNUM;
}
/* 777q - octal number */
{OCTDIGIT}+q {
yylval.int_str_val.val = strtoul(yytext, (char **)NULL, 8);
yylval.int_str_val.str = yytext;
return INTNUM;
}
/* 0AAh form of hexidecimal number */
0{HEXDIGIT}+h {
yylval.int_str_val.val = strtoul(yytext+1, (char **)NULL, 16);
yylval.int_str_val.str = yytext;
return INTNUM;
}
/* $0AA and 0xAA forms of hexidecimal number */
(\$0|0x){HEXDIGIT}+ {
yylval.int_str_val.val = strtoul(yytext+2, (char **)NULL, 16);
yylval.int_str_val.str = yytext;
return INTNUM;
}
/* floating point value */
{DIGIT}+\.{DIGIT}*(e[-+]?{DIGIT}+)? {
yylval.double_str_val.val = strtod(yytext, (char **)NULL);
yylval.double_str_val.str = yytext;
return FLTNUM;
}
/* string/character constant values */
["'] {
int inch;
size_t count;
char endch = yytext[0];
strbuf = yasm_xmalloc(STRBUF_ALLOC_SIZE);
strbuf_size = STRBUF_ALLOC_SIZE;
inch = input();
count = 0;
while(inch != EOF && inch != endch && inch != '\n') {
strbuf[count++] = inch;
if(count >= strbuf_size) {
strbuf = yasm_xrealloc(strbuf, strbuf_size + STRBUF_ALLOC_SIZE);
strbuf_size += STRBUF_ALLOC_SIZE;
}
inch = input();
}
if(inch == '\n')
yasm_error_set(YASM_ERROR_VALUE, N_("unterminated string"));
else if(inch == EOF)
yasm_error_set(YASM_ERROR_VALUE, N_("unexpected end of file in string"));
strbuf[count] = '\0';
yylval.str_val = strbuf;
return STRING;
}
/* identifiers */
\.\.[a-z0-9_$#@~.?]+ |
\.[a-z0-9_$#@~?][a-z0-9_$#@~.?]* |
[a-z_?][a-z0-9_$#@~.?]* {
yylval.str_val = yasm__xstrdup(yytext);
return IDENT;
}
/* includes - based on flex manual handling of include files */
<inhibit>{DIR}include[^\n]* ;
{DIR}include BEGIN(incl);
/* note the " handling here is a hack that doesn't accept useful
* things (like spaces, or quotes). fix it later */
<incl>[ \t"]* /* eat whitespace */
<incl>[^ \t\n"]* { /* have the filename */
include *inc;
FILE *incfile;
inc = yasm_xmalloc(sizeof(include));
inc->include_state = YY_CURRENT_BUFFER;
/* FIXME: handle includes that aren't relative */
incfile = fopen (yytext, "r");
if(!incfile) {
yasm_error_set(YASM_ERROR_VALUE, N_("include file `%s': %s"),
yytext, strerror(errno));
yasm_xfree(inc);
}
else {
yyin = incfile;
inc->filename = yapp_preproc_current_file;
inc->line_number = yapp_preproc_line_number;
SLIST_INSERT_HEAD(&includes_head, inc, next);
yapp_preproc_line_number = 1;
yapp_preproc_current_file = yasm__xstrdup(yytext);
BEGIN(INITIAL);
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
}
return INCLUDE;
}
/* end includes - note that it's not in <incl> at the time */
<<EOF>> {
if(SLIST_EMPTY(&includes_head)) {
yyterminate();
}
else {
include *inc;
inc = SLIST_FIRST(&includes_head);
yy_delete_buffer (YY_CURRENT_BUFFER);
yy_switch_to_buffer (inc->include_state);
yasm_xfree(yapp_preproc_current_file);
yapp_preproc_current_file = inc->filename;
yapp_preproc_line_number = inc->line_number + 1;
SLIST_REMOVE_HEAD(&includes_head, next);
yasm_xfree(inc);
BEGIN(incl);
return INCLUDE;
}
}
<incl>["]{WS}*\n BEGIN(INITIAL);
/* directive: % directive [args] */
<inhibit>{DIR}clear[^\n] ;
{DIR}clear return CLEAR;
<inhibit>{DIR}line[^\n] ;
{DIR}line BEGIN(line);
<line>{DIGIT}+ yapp_preproc_line_number = strtoul(yytext, (char **)NULL, 10);
<line>{DIGIT}+{WS}*\n {
yapp_preproc_line_number = strtoul(yytext, (char **)NULL, 10);
BEGIN(INITIAL);
return LINE;
}
<line>{WS}+["] ; /* eat space before file */
<line>[^ \t\n"]* { /* have the filename */
yasm_xfree(yapp_preproc_current_file);
yapp_preproc_current_file = yasm__xstrdup(yytext);
}
<line>["]{WS}*\n {
BEGIN(INITIAL);
return LINE;
}
{DIR}define return DEFINE;
{DIR}undef return UNDEF;
{DIR}assign return ASSIGN;
{DIR}macro return MACRO;
{DIR}endmacro return ENDMACRO;
{DIR}rotate return ROTATE;
<inhibit>{DIR}define[^\n]* ;
<inhibit>{DIR}undef[^\n]* ;
<inhibit>{DIR}assign[^\n]* ;
<inhibit>{DIR}macro[^\n]* ;
<inhibit>{DIR}endmacro[^\n]* ;
<inhibit>{DIR}rotate[^\n]* ;
/* preprocessor loops */
{DIR}rep return REP;
{DIR}exitrep return EXITREP;
{DIR}endrep return ENDREP;
<inhibit>{DIR}rep[^\n]* ;
<inhibit>{DIR}exitrep[^\n]* ;
<inhibit>{DIR}endrep[^\n]* ;
{DIR}if return IF;
{DIR}elif return ELIF;
{DIR}else return ELSE;
{DIR}endif return ENDIF;
<inhibit>{DIR}if { BEGIN(INITIAL); return IF; }
<inhibit>{DIR}elif { BEGIN(INITIAL); return ELIF; }
<inhibit>{DIR}else { BEGIN(INITIAL); return ELSE; }
<inhibit>{DIR}endif { BEGIN(INITIAL); return ENDIF; }
/* test defines */
{DIR}ifdef return IFDEF;
{DIR}elifdef return ELIFDEF;
{DIR}ifndef return IFNDEF;
{DIR}elifndef return ELIFNDEF;
<inhibit>{DIR}ifdef { BEGIN(INITIAL); return IFDEF; }
<inhibit>{DIR}elifdef { BEGIN(INITIAL); return ELIFDEF; }
<inhibit>{DIR}ifndef { BEGIN(INITIAL); return IFNDEF; }
<inhibit>{DIR}elifndef { BEGIN(INITIAL); return ELIFNDEF; }
/* test context stack */
{DIR}ifctx return IFCTX;
{DIR}elifctx return ELIFCTX;
<inhibit>{DIR}ifctx { BEGIN(INITIAL); return IFCTX; }
<inhibit>{DIR}elifctx { BEGIN(INITIAL); return ELIFCTX; }
/* test exact identity */
{DIR}ifidn return IFIDN;
{DIR}elifidn return ELIFIDN;
{DIR}ifidni return IFIDNI;
{DIR}elifidni return ELIFIDNI;
<inhibit>{DIR}ifidn { BEGIN(INITIAL); return IFIDN; }
<inhibit>{DIR}elifidn { BEGIN(INITIAL); return ELIFIDN; }
<inhibit>{DIR}ifidni { BEGIN(INITIAL); return IFIDNI; }
<inhibit>{DIR}elifidni { BEGIN(INITIAL); return ELIFIDNI; }
/* test token types */
{DIR}ifid return IFID;
{DIR}elifid return ELIFID;
{DIR}ifnum return IFNUM;
{DIR}elifnum return ELIFNUM;
{DIR}ifstr return IFSTR;
{DIR}elifstr return ELIFSTR;
<inhibit>{DIR}ifid { BEGIN(INITIAL); return IFID; }
<inhibit>{DIR}elifid { BEGIN(INITIAL); return ELIFID; }
<inhibit>{DIR}ifnum { BEGIN(INITIAL); return IFNUM; }
<inhibit>{DIR}elifnum { BEGIN(INITIAL); return ELIFNUM; }
<inhibit>{DIR}ifstr { BEGIN(INITIAL); return IFSTR; }
<inhibit>{DIR}elifstr { BEGIN(INITIAL); return ELIFSTR; }
/* error reporting */
<inhibit>{DIR}error[^\n]* ;
{DIR}error[ ]+.* { yylval.str_val = yytext; return ERROR; }
/* context stack management */
{DIR}push return PUSH;
{DIR}pop return POP;
{DIR}repl return REPL;
<inhibit>{DIR}push[^\n]* ;
<inhibit>{DIR}pop[^\n]* ;
<inhibit>{DIR}repl[^\n]* ;
<inhibit>[^%\n]*\n { yapp_preproc_line_number++; return '\n'; }
;.*\n { yapp_preproc_line_number++; return '\n'; }
{WS}+ { yylval.str_val = yytext; return WHITESPACE; }
{WS}*\n { yapp_preproc_line_number++; return '\n'; }
[][+*/,()-] { return yytext[0]; }
<inhibit>. {
yasm_warn_set(YASM_WARN_PREPROC, N_("Unhandled character in <inhibit> `%s'"), yasm__conv_unprint(yytext[0]));
}
. {
yasm_warn_set(YASM_WARN_PREPROC, N_("ignoring unrecognized character `%s'"),
yasm__conv_unprint(yytext[0]));
}
%%
void
yapp_lex_initialize(FILE *f)
{
SLIST_INIT(&includes_head);
yyin = f;
}
void set_inhibit(void)
{
BEGIN(inhibit);
}