/* This file is part of mhmake.
*
* Copyright (C) 2001-2009 Marc Haesen
*
* Mhmake 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 3 of the License, or
* (at your option) any later version.
*
* Mhmake 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 Mhmake. If not, see .
*/
/* $Rev$ */
/* -------------- declaration section -------------- */
%name mhmakelexer
%header{
#include "mhmakeparser.h"
#include "fileinfo.h"
#include "rule.h"
#include "util.h"
static uint32 LoadMakMd5(refptr &Target)
{
string FileName=Target->GetFullFileName();
FileName+=".md5_32";
FILE *pFile=fopen(FileName.c_str(),"rb");
if (!pFile)
return 0;
uint32 Md5_32=0;
fread(&Md5_32,sizeof(Md5_32),1,pFile);
fclose(pFile);
Target->SetCommandsMd5_32(Md5_32);
return Md5_32;
}
static void SaveMakMd5(refptr &Target)
{
string FileName=Target->GetFullFileName();
FileName+=".md5_32";
FILE *pFile=fopen(FileName.c_str(),"wb");
if (!pFile)
{
throw string("Error creating file ")+FileName;
}
Target->WriteMd5_32(pFile);
fclose(pFile);
}
%}
%define LEX_PARAM TOKENVALUE &theValue
%define MEMBERS public: \
struct INSTACK\
{\
YY_BUFFER_STATE m_BufferState;\
string m_FileName;\
int m_Line;\
INSTACK(YY_BUFFER_STATE BufferState,string FileName,int Line) :\
m_BufferState(BufferState),m_FileName(FileName),m_Line(Line) {}\
};\
int m_Line;\
int m_BraceIndent;\
size_t m_IndentSkip;\
iterstack m_IndentStack;\
bool m_IgnoreIncludeError;\
string m_InputFileName; \
string m_curtoken; \
iterstack m_IncludeStack; \
mhmakeparser *m_pParser;\
mhmakeparser *GetParser()\
{\
return m_pParser;\
}
%define CONSTRUCTOR_INIT : m_Line(1), m_BraceIndent(0)
/* -------------- rules section -------------- */
%x INCLUDE IFDEF IF IFNDEF SKIPUNTILELSEORENDIF QUOTE MAKEEXPRES SINGLEQUOTE COMMANDPARSE
%x IFEQ IFNEQ ERRORMACRO MESSAGEMACRO REPARSEMACRO LOAD_MAKEFILE
%%
/*---------------------------------------------------------------------------*/
[ \t\r]*\n[ ][ \t]* |
[ \t\r]*\n {
PRINTF(("%s %d: NEWLINE:\n",m_InputFileName.c_str(),m_Line));
m_Line++;
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^[s\-]?include {
PRINTF(("%s %d: INCLUDE: ",m_InputFileName.c_str(),m_Line));
BEGIN(INCLUDE);
if (yytext[0]=='-' || yytext[0]=='s')
m_IgnoreIncludeError=true;
else
m_IgnoreIncludeError=false;
return mhmakeparser::INCLUDEMAK; // Return a newline to be sure that the previous line is completely parse by yacc (in case it is a variable definition)
}
/*****************************************************************************/
[ \t]* /* eat the whitespace */
/*---------------------------------------------------------------------------*/
[^\r\n]+ { /* got the include file name */
mhmakeparser *pParser=GetParser();
string IncludeFileNames=pParser->ExpandExpression((const char*)yytext);
PRINTF(("%s -> %s\n",yytext,IncludeFileNames.c_str()));
const char *pTmp=IncludeFileNames.c_str();
while (*pTmp)
{
string IncludeFileName;
pTmp=NextItem(pTmp,IncludeFileName);
if (!IncludeFileName.empty())
{
PRINTF(("%s -> %s\n",yytext,IncludeFileName.c_str()));
refptr pInclude=GetFileInfo(IncludeFileName,pParser->GetMakeDir());
/* Already build the include file, in case we already have a rule for it. */
if (pInclude->GetRule())
{
uint32 Md5_32=LoadMakMd5(pInclude);
pParser->BuildTarget(pInclude);
if (!pInclude->CompareMd5_32(Md5_32))
SaveMakMd5(pInclude);
}
pParser->AddIncludedMakefile(pInclude);
string strToInclude=pInclude->GetFullFileName();
FILE *pTmp = ::fopen(strToInclude.c_str(), "r" );
if ( ! pTmp )
{
if (!m_IgnoreIncludeError)
{
iterstack::reverse_iterator StackIt=m_IncludeStack.rbegin();
while (StackIt!=m_IncludeStack.rend())
{
cout<<" in "<m_FileName<<" ("<m_Line<<")";
StackIt++;
}
cout<IncludeAfterBuild(strToInclude);
}
}
else
{
m_IncludeStack.push(INSTACK(YY_mhmakelexer_CURRENT_BUFFER,m_InputFileName,m_Line));
m_Line=1;
yyin=pTmp;
m_InputFileName=strToInclude;
YY_mhmakelexer_SWITCH_TO_BUFFER(YY_mhmakelexer_CREATE_BUFFER( yyin, YY_BUF_SIZE ) );
}
}
}
BEGIN(INITIAL);
}
/*---------------------------------------------------------------------------*/
load_makefile {
PRINTF(("%s %d: LOAD_MAKEFILE:\n",m_InputFileName.c_str(),m_Line));
BEGIN(LOAD_MAKEFILE);
return mhmakeparser::NEWLINE; // Return a newline to be sure that the previous line is completely parse by yacc (in case it is a variable definition)
}
/*****************************************************************************/
[^\r\n]+ {
string ListOfMakefiles=GetParser()->ExpandExpression((const char*)yytext);
PRINTF(("%s %d: LOAD_MAKEFILE: '%s'\n",m_InputFileName.c_str(),m_Line,ListOfMakefiles.c_str()));
const char *pTmp=ListOfMakefiles.c_str();
while (*pTmp)
{
string Item;
pTmp=NextCharItem(pTmp,Item,';');
if (Item.empty())
{
throw m_InputFileName + "(" + stringify(m_Line) + "): Error in load_makefile statement";
}
GetParser()->AddMakefileToMakefilesToLoad(Item);
}
}
/*---------------------------------------------------------------------------*/
\r?\n {
m_Line++;
BEGIN(INITIAL);
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
[ \t]+ {
PRINTF(("%s %d: SPACE:\n",m_InputFileName.c_str(),m_Line));
return mhmakeparser::SPACE;
}
/*---------------------------------------------------------------------------*/
[ \t]*=[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: EQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
m_Line++;
theValue.theString=(const char *)yytext;
return mhmakeparser::EQUAL;
}
[ \t]*=[ \t]* {
PRINTF(("%s %d: EQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::EQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*:=[ \t]*\\[ \t\r]*\n[ \t]* {
m_Line++;
PRINTF(("%s %d: IMEQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::IMEQUAL;
}
[ \t]*:=[ \t]* {
PRINTF(("%s %d: IMEQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::IMEQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*\?=[ \t]*\\[ \t\r]*\n[ \t]* {
m_Line++;
PRINTF(("%s %d: IMEQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::OPTEQUAL;
}
[ \t]*\?=[ \t]* {
PRINTF(("%s %d: IMEQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::OPTEQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*\+=[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: PEQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
m_Line++;
return mhmakeparser::PEQUAL;
}
[ \t]*\+=[ \t]* {
PRINTF(("%s %d: PEQUAL: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::PEQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*;[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: -SEMICOLON (NEWLINE): %s\n",m_InputFileName.c_str(),m_Line,yytext));
m_curtoken=g_EmptyString;
m_Line++;
BEGIN(COMMANDPARSE);
return mhmakeparser::NEWLINE;
}
[ \t]*;[ \t]* {
PRINTF(("%s %d: -SEMICOLON (NEWLINE): %s\n",m_InputFileName.c_str(),m_Line,yytext));
m_curtoken=g_EmptyString;
BEGIN(COMMANDPARSE);
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
[ \t]*::[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: DOUBLECOLON: %s\n",m_InputFileName.c_str(),m_Line,yytext));
m_Line++;
theValue.theString=(const char *)yytext;
return mhmakeparser::DOUBLECOLON;
}
[ \t]*::[ \t]* {
PRINTF(("%s %d: DOUBLECOLON: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::DOUBLECOLON;
}
/*---------------------------------------------------------------------------*/
[ \t]*:[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: COLON: %s\n",m_InputFileName.c_str(),m_Line,yytext));
m_Line++;
theValue.theString=(const char *)yytext;
return mhmakeparser::COLON;
}
[ \t]*:[ \t]* {
PRINTF(("%s %d: COLON: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::COLON;
}
/*---------------------------------------------------------------------------*/
, {
PRINTF(("%s %d: COMMA: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::COMMA;
}
/*---------------------------------------------------------------------------*/
^[ \t]*endif {
if (m_IndentStack.size())
{
m_IndentStack.pop();
PRINTF(("%s %d: %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext,m_IndentStack.size()));
}
else
{
throw string("Unexpected endif at line ") + stringify(m_Line) + " of " + m_InputFileName;
}
}
/*---------------------------------------------------------------------------*/
^[ \t]*ifdef[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFDEF);
m_Line++;
return mhmakeparser::NEWLINE;
}
^[ \t]*ifdef[ \t]+ {
BEGIN(IFDEF);
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^[ \t]*if[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IF);
m_Line++;
m_curtoken=g_EmptyString;
return mhmakeparser::NEWLINE;
}
^[ \t]*if[ \t]+ {
BEGIN(IF);
m_curtoken=g_EmptyString;
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^[ \t]*ifndef[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFNDEF);
m_Line++;
return mhmakeparser::NEWLINE;
}
^[ \t]*ifndef[ \t]+ {
BEGIN(IFNDEF);
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^[ \t]*ifeq[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFEQ);
m_curtoken=g_EmptyString;
m_Line++;
return mhmakeparser::NEWLINE;
}
^[ \t]*ifeq[ \t]+ {
BEGIN(IFEQ);
m_curtoken=g_EmptyString;
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^[ \t]*ifneq[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFNEQ);
m_curtoken=g_EmptyString;
m_Line++;
return mhmakeparser::NEWLINE;
}
^[ \t]*ifneq[ \t]+ {
BEGIN(IFNEQ);
m_curtoken=g_EmptyString;
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^[ \t]*else[ \t]* {
if (m_IndentStack.size() && (!m_IndentStack.top()))
{
PRINTF(("%s %d: skipping else: depth %d\n",m_InputFileName.c_str(),m_Line,m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
m_IndentStack.top()=1;
BEGIN(SKIPUNTILELSEORENDIF);
}
else
{
throw string("Unexpected else at line ") + stringify(m_Line) + " of file " + m_InputFileName;
}
}
/*****************************************************************************/
\n {
unput( yytext[0] );
m_IndentStack.push(0);
if (GetParser()->IsEqual(m_curtoken))
{
PRINTF(("%s %d: Not Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
[ \t]*\\[ \t\r]*\n[ \t]* { m_Line++; m_curtoken += g_SpaceString;}
\r /* skip */
[^\\\r\n]+ |
\\ { m_curtoken += (const char *)yytext; }
/*****************************************************************************/
\n {
unput( yytext[0] );
m_IndentStack.push(0);
if (!GetParser()->IsEqual(m_curtoken))
{
PRINTF(("%s %d: Not Skipping ifneq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifneq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
/*****************************************************************************/
[ \t\r]*[a-zA-Z0-9_]+[ \t\r]*\n {
unput( '\n' );
m_IndentStack.push(0);
#ifndef WIN32
int lastidx=strlen((const char *)yytext)-1;
if (yytext[lastidx]=='\r')
yytext[lastidx]='\0';
#endif
string Val=GetParser()->ExpandVar((const char *)yytext);
if (Val.empty() || Val=="0")
{
PRINTF(("%s %d: Skipping if %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext,m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
else
{
PRINTF(("%s %d: Not Skipping if %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext,m_IndentStack.size()));
BEGIN(INITIAL);
}
}
/*---------------------------------------------------------------------------*/
\n {
unput( yytext[0] );
m_IndentStack.push(0);
if (GetParser()->IsExprTrue(m_curtoken))
{
PRINTF(("%s %d: Not Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str(),m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
/*****************************************************************************/
[ \t\r]* /* skip */
/*---------------------------------------------------------------------------*/
[a-zA-Z0-9_]+ {
m_IndentStack.push(0);
if (GetParser()->IsDefined((const char *)yytext))
{
PRINTF(("%s %d: Not Skipping ifdef %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext,m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifdef %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext,m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
/*****************************************************************************/
[a-zA-Z0-9_]+ {
m_IndentStack.push(0);
if (!GetParser()->IsDefined((const char *)yytext)) {
PRINTF(("%s %d: Not Skipping ifndef %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext,m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifndef %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext,m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
/*****************************************************************************/
\n[ ]*endif {
m_Line++;
if (!m_IndentStack.size())
{
throw string("Unexpected endif at line ") + stringify(m_Line) + " of " + m_InputFileName;
}
else
{
m_IndentStack.pop();
PRINTF(("%s %d: endif: depth %d\n",m_InputFileName.c_str(),m_Line,m_IndentStack.size()));
if (m_IndentStack.size()==m_IndentSkip-1) BEGIN(INITIAL);
}
}
/*---------------------------------------------------------------------------*/
\n[ ]*else {
m_Line++;
PRINTF(("%s %d: else: depth %d\n",m_InputFileName.c_str(),m_Line,m_IndentStack.size()));
if (m_IndentStack.top())
{
throw string("Unexpected else at line ") + stringify(m_Line) + " of file " + m_InputFileName;
}
m_IndentStack.top()=1;
if (m_IndentStack.size()==m_IndentSkip)
{
BEGIN(INITIAL);
}
}
/*---------------------------------------------------------------------------*/
\n[ ]*if(def|ndef|eq|neq)? {
m_Line++;
m_IndentStack.push(0);
PRINTF(("%s %d: %s: depth %d\n",m_InputFileName.c_str(),m_Line,yytext+1,m_IndentStack.size()));
}
/*---------------------------------------------------------------------------*/
[a-zA-Z]+ /* skip */
/*---------------------------------------------------------------------------*/
[^a-zA-Z\n]+ /* skip */
/*---------------------------------------------------------------------------*/
\n[ ]*[a-zA-Z]+ m_Line++;
/*---------------------------------------------------------------------------*/
\n {
m_Line++;
}
/*---------------------------------------------------------------------------*/
[ \t]*#[^\n]* {
PRINTF(("%s %d: -COMMENT: %s\n",m_InputFileName.c_str(),m_Line,yytext));
}
/*---------------------------------------------------------------------------*/
[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: SPACE:\n",m_InputFileName.c_str(),m_Line));
m_Line++;
return mhmakeparser::SPACE;
}
/*---------------------------------------------------------------------------*/
\.PHONY {
PRINTF(("%s %d: .PHONY: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::PHONY;
}
/*---------------------------------------------------------------------------*/
\.AUTODEPS {
PRINTF(("%s %d: .AUTODEPS: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::AUTODEPS;
}
/*---------------------------------------------------------------------------*/
export {
PRINTF(("%s %d: export: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::EXPORT;
}
/*---------------------------------------------------------------------------*/
[a-zA-Z]:[a-zA-Z0-9\\\._\~\-%\@<&/]+\\[ \t\r]*\n {
size_t EndIndex=::strlen((const char*)yytext);
while (strchr(" \t\r\n\\",yytext[--EndIndex]));
yyless(EndIndex+1);
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::STRING;
}
[a-zA-Z]:[a-zA-Z0-9\\\._\~\-%\@<&/]+ {
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::STRING;
}
/*---------------------------------------------------------------------------*/
([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|]|\\\ |\\#)+\\[ \t\r]*\n {
size_t EndIndex=::strlen((const char*)yytext);
while (strchr(" \t\r\n\\",yytext[--EndIndex]));
yyless(EndIndex+1);
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::STRING;
}
([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|]|\\\ |\\#)+\+= {
size_t Len;
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
Len=strlen((const char *)yytext)-2;
yyless(Len);
theValue.theString=(const char *)yytext;
return mhmakeparser::STRING;
}
([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|]|\\\ |\\#)+ {
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::STRING;
}
/*---------------------------------------------------------------------------*/
\" {
BEGIN(QUOTE);
yymore();
}
/*---------------------------------------------------------------------------*/
\' {
BEGIN(SINGLEQUOTE);
yymore();
}
/*---------------------------------------------------------------------------*/
\$\( {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN MACRO $(: %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
BEGIN(MAKEEXPRES);
yymore();
}
/*---------------------------------------------------------------------------*/
\$\([ \t]*error[ \t]+ {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN ERROR MACRO $(: %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
BEGIN(ERRORMACRO);
m_curtoken=g_EmptyString;
}
/*---------------------------------------------------------------------------*/
\$\([ \t]*message[ \t]+ {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN MESSAGE MACRO $(: %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
BEGIN(MESSAGEMACRO);
m_curtoken=g_EmptyString;
}
/*---------------------------------------------------------------------------*/
\$\([ \t]*reparse[ \t]+ {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN REPARSE MACRO $(: %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
BEGIN(REPARSEMACRO);
m_curtoken=g_EmptyString;
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
\( {
PRINTF(("%s %d: OPENBRACE: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::OPENBRACE;
}
/*---------------------------------------------------------------------------*/
\) {
PRINTF(("%s %d: CLOSEBRACE: %s\n",m_InputFileName.c_str(),m_Line,yytext));
return mhmakeparser::CLOSEBRACE;
}
/*---------------------------------------------------------------------------*/
\$[<@/$] {
PRINTF(("%s %d: DOLLAREXPR: %s\n",m_InputFileName.c_str(),m_Line,yytext));
theValue.theString=(const char *)yytext;
return mhmakeparser::DOLLAREXPR;
}
/*---------------------------------------------------------------------------*/
[ \t\r]*\n\t[ \t]* {
/* token newline */
PRINTF(("%s %d: NEWLINE\n",m_InputFileName.c_str(),m_Line));
m_Line++;
m_curtoken=g_EmptyString;
BEGIN(COMMANDPARSE);
return mhmakeparser::NEWLINE;
}
/*---------------------------------------------------------------------------*/
[^\n] {
PRINTF(("%s %d: ANYCHAR: %d: %s\n",m_InputFileName.c_str(),m_Line,m_Line,yytext));
}
/*****************************************************************************/
[ \t\r]*\n {
PRINTF(("%s %d: COMMAND: %d: %s\n",m_InputFileName.c_str(),m_Line,m_Line,m_curtoken.c_str()));
theValue.theString=m_curtoken;
m_Line++;
BEGIN(INITIAL);
return mhmakeparser::COMMAND;
}
/*---------------------------------------------------------------------------*/
[ \t\r]*\n\t[ \t]* {
PRINTF(("%s %d: COMMAND: %s\n",m_InputFileName.c_str(),m_Line,m_curtoken.c_str()));
theValue.theString=m_curtoken;
m_Line++;
m_curtoken=g_EmptyString;
return mhmakeparser::COMMAND;
}
/*---------------------------------------------------------------------------*/
[ \t]*\\[ \t\r]*\n[ \t]* {
m_Line++;
m_curtoken+=g_SpaceString;
}
/*---------------------------------------------------------------------------*/
[ ]+ {
m_curtoken+=g_SpaceString;
}
/*---------------------------------------------------------------------------*/
[^ \r\n#\\]+ |
\\ {
m_curtoken+=(const char *)yytext;
}
/*---------------------------------------------------------------------------*/
[ \t]*\\#[^\n]* {
char ToAdd[100];
int i=0;
int nChars=(int)((strchr((const char *)yytext,'#')-(char*)yytext))+1;
while (strchr(" \t",yytext[i]))
{
ToAdd[i]=yytext[i];
i++;
}
ToAdd[i++]='#';
ToAdd[i++]=0;
m_curtoken+=ToAdd;
yyless(nChars);
}
/*---------------------------------------------------------------------------*/
[ \t]*#[^\n]* {
PRINTF(("%s %d: -COMMENT: %s\n",m_InputFileName.c_str(),m_Line,yytext));
}
/*****************************************************************************/
\" {
PRINTF(("%s %d: QUOTEDSTRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
BEGIN(INITIAL);
theValue.theString=(const char *)yytext;
return mhmakeparser::STRING;
}
/*---------------------------------------------------------------------------*/
\r /* skip */
[^\\\"\r\n]+ |
\\ |
\\\" |
\\# {
yymore();
}
/*****************************************************************************/
\' {
PRINTF(("%s %d: QUOTEDSTRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
BEGIN(INITIAL);
theValue.theString=(const char *)yytext;
return mhmakeparser::STRING;
}
/*---------------------------------------------------------------------------*/
\r /* skip */
[^\\\'\r\n]+ |
\\ |
\\\' |
\\# {
yymore();
}
/*****************************************************************************/
\) {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE ERROR MACRO ): %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
if (!m_BraceIndent)
{
PRINTF(("%s %d: ERRORMACRO: %s\n",m_InputFileName.c_str(),m_Line,yytext));
yyless(0);
throw GetParser()->ExpandExpression((const char*)yytext);
} else {
yymore();
}
}
/*****************************************************************************/
\) {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE MESSAGE MACRO ): %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
if (!m_BraceIndent)
{
PRINTF(("%s %d: MESSAGEMACRO: %s\n",m_InputFileName.c_str(),m_Line,yytext));
yytext[strlen((const char*)yytext)-1]=0;
cerr<ExpandExpression((const char*)yytext)<\) {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE REPARSE MACRO ): %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
if (!m_BraceIndent)
{
PRINTF(("%s %d: REPARSEMACRO: %s\n",m_InputFileName.c_str(),m_Line,yytext));
string Deps=GetParser()->ExpandExpression((const char*)yytext);
PRINTF(("%s %d: REPARSEMACRO expanded: %s\n",m_InputFileName.c_str(),m_Line,Deps.c_str()));
string::const_reverse_iterator It=Deps.rbegin()+1; // +1 because we don't want the latest brace
string::const_reverse_iterator ItBeg=Deps.rend();
while (It!= ItBeg)
{
char Char=*It++;
if (Char==';') Char='\n';
unput(Char);
}
BEGIN(INITIAL);
}
else
{
yymore();
}
}
/*****************************************************************************/
\) {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE MAKEEXPRES MACRO ): %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
if (!m_BraceIndent)
{
PRINTF(("%s %d: DOLLAREXPR: %s\n",m_InputFileName.c_str(),m_Line,yytext));
BEGIN(INITIAL);
theValue.theString=(const char *)yytext;
return mhmakeparser::DOLLAREXPR;
}
else
{
yymore();
}
}
/*---------------------------------------------------------------------------*/
\$\( {
m_BraceIndent++;
PRINTF(("%s %d: MACRO extra $(: %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
yymore();
}
/*---------------------------------------------------------------------------*/
[^$\(\)\r\n]+ |
\$ |
\( {
yymore();
}
\r?\n {
m_Line++;
}
<> {
throw string("Missing endif or else statement. #else or #endif used?");
}
<> {
if (m_BraceIndent)
{
throw string("Missing closing ) of macro usage in ") + m_InputFileName;
}
if (!m_IncludeStack.size())
{
if (m_IndentStack.size())
{
throw string("Missing endif or else statement in ") + m_InputFileName + ". #else or #endif used";
}
yyterminate();
}
else
{
::fclose(YY_mhmakelexer_CURRENT_BUFFER->yy_input_file);
YY_mhmakelexer_DELETE_BUFFER(YY_mhmakelexer_CURRENT_BUFFER);
INSTACK *pInStack=&m_IncludeStack.top();
YY_mhmakelexer_SWITCH_TO_BUFFER(pInStack->m_BufferState);
m_InputFileName=pInStack->m_FileName;
m_Line=pInStack->m_Line;
m_IncludeStack.pop();
}
}
%%