/* This file is part of mhmake.
*
* Copyright (C) 2001-2010 marha@sourceforge.net
*
* 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 -------------- */
%{
#include "fileinfo.h"
#include "rule.h"
#include "util.h"
static uint32 LoadMakMd5(fileinfo *pTarget)
{
uint32 Md5_32=0;
string FileName=pTarget->GetFullFileName();
FileName+=".md5_32";
FILE *pFile=fopen(FileName.c_str(),"rb");
if (!pFile)
return Md5_32;
if (1!=fread(&Md5_32,sizeof(Md5_32),1,pFile))
{
fclose(pFile);
return Md5_32;
}
pTarget->SetCommandsMd5_32(Md5_32);
fclose(pFile);
return Md5_32;
}
static void SaveMakMd5(fileinfo *pTarget)
{
string FileName=pTarget->GetFullFileName();
FileName+=".md5_32";
FILE *pFile=fopen(FileName.c_str(),"wb");
if (!pFile)
{
throw string("Error creating file ")+FileName;
}
pTarget->WriteMd5_32(pFile);
fclose(pFile);
}
static void ReplaceCurlyBraces(string &String)
{
int Pos=String.find_first_of('{',0);
if (Pos!=string::npos)
{
/* if not { found, } will not be there eather (or it is a valid syntax, so it may generate an error) */
do
{
String.replace(Pos,1,1,'(');
Pos=String.find_first_of('{',Pos);
}
while (Pos!=string::npos);
Pos=0;
while ((Pos=String.find_first_of('}',Pos))!=string::npos)
String.replace(Pos,1,1,')');
}
}
#include "mhmakeparser.hpp"
#define YY_DECL int mhmakeFlexLexer::yylex(yy::mhmakeparser::semantic_type* yylval, yy::mhmakeparser::location_type* yylloc)
/* By default yylex returns int, we use token_type.
Unfortunately yyterminate by default returns 0, which is
not of token_type. */
#define yyterminate() return yy::mhmakeparser::token::END
%}
%option prefix="mhmake"
%option never-interactive
%option 8bit
%option c++
%option full
%option noyywrap
%option warn
/* -------------- rules section -------------- */
%x INCLUDE IFDEF IF IFNDEF SKIPUNTILELSEORENDIF QUOTE MAKEEXPRES SINGLEQUOTE COMMANDPARSE
%x IFEQ IFNEQ ERRORMACRO MESSAGEMACRO REPARSEMACRO LOAD_MAKEFILE
%x DEFINE
%{
# define YY_USER_ACTION yylloc->columns (yyleng);
#define inclineno() yylloc->incline()
#define lineno() yylloc->end.line
#define colno() yylloc->end.column
%}
%%
%{
yylloc->step ();
%}
/*---------------------------------------------------------------------------*/
[ \t\r]*\n[ ][ \t]* {
yy_set_bol(1); // Make sure the next rule also matches the ^
inclineno();
return yy::mhmakeparser::token::NEWLINE;
}
[ \t\r]*\n {
PRINTF(("%s %d: NEWLINE:\n",m_InputFileName.c_str(),lineno()));
inclineno();
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^[s\-]?include {
PRINTF(("%s %d: INCLUDE: ",m_InputFileName.c_str(),lineno()));
BEGIN(INCLUDE);
unsigned i=0;
while (strchr(" \t",yytext[i])) i++;
if (strchr("-s",yytext[i]))
m_IgnoreIncludeError=true;
else
m_IgnoreIncludeError=false;
return yy::mhmakeparser::token::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 */
mhmakefileparser *pParser=GetParser();
/* replace the {} by () before expanding */
string IncludeFileNames(yytext);
ReplaceCurlyBraces(IncludeFileNames);
IncludeFileNames=pParser->ExpandExpression(IncludeFileNames);
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()));
fileinfo *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();
INSTACK *pStackElem=new INSTACK(YY_CURRENT_BUFFER, strToInclude, m_InputFileName, yylloc);
if ( pStackElem->fail() )
{
delete pStackElem;
if (!m_IgnoreIncludeError)
{
mystack::reverse_iterator StackIt=m_IncludeStack.rbegin();
while (StackIt!=m_IncludeStack.rend())
{
cout<<" in "<<(*StackIt)->m_FileName<<" ("<<(*StackIt)->yylloc<<")";
StackIt++;
}
cout<IncludeAfterBuild(strToInclude);
}
else
pInclude->SetPhony(); /* To be sure that no message is printed when mhmake is trying to build the file later */
}
else
{
m_IncludeStack.push(pStackElem);
m_InputFileName=strToInclude;
yylloc->initialize(&m_InputFileName);
yypush_buffer_state(yy_create_buffer( pStackElem->GetStream(), YY_BUF_SIZE ));
yyrestart(pStackElem->GetStream());
}
}
}
BEGIN(INITIAL);
}
/*---------------------------------------------------------------------------*/
load_makefile {
PRINTF(("%s %d: LOAD_MAKEFILE:\n",m_InputFileName.c_str(),lineno()));
BEGIN(LOAD_MAKEFILE);
return yy::mhmakeparser::token::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((const char*)yytext);
ReplaceCurlyBraces(ListOfMakefiles);
ListOfMakefiles=GetParser()->ExpandExpression(ListOfMakefiles);
PRINTF(("%s %d: LOAD_MAKEFILE: '%s'\n",m_InputFileName.c_str(),lineno(),ListOfMakefiles.c_str()));
const char *pTmp=ListOfMakefiles.c_str();
while (*pTmp)
{
string Item;
pTmp=NextCharItem(pTmp,Item,';');
if (Item.empty())
{
throw m_InputFileName + "(" + stringify(lineno()) + "): Error in load_makefile statement";
}
GetParser()->AddMakefileToMakefilesToLoad(Item);
}
}
/*---------------------------------------------------------------------------*/
\r?\n {
inclineno();
BEGIN(INITIAL);
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
[ \t]+ {
PRINTF(("%s %d: SPACE:\n",m_InputFileName.c_str(),lineno()));
return yy::mhmakeparser::token::SPACE;
}
/*---------------------------------------------------------------------------*/
[ \t]*=[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: EQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
inclineno();
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::EQUAL;
}
[ \t]*=[ \t]* {
PRINTF(("%s %d: EQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::EQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*:=[ \t]*\\[ \t\r]*\n[ \t]* {
inclineno();
PRINTF(("%s %d: IMEQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::IMEQUAL;
}
[ \t]*:=[ \t]* {
PRINTF(("%s %d: IMEQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::IMEQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*\?=[ \t]*\\[ \t\r]*\n[ \t]* {
inclineno();
PRINTF(("%s %d: OPTEQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::OPTEQUAL;
}
[ \t]*\?=[ \t]* {
PRINTF(("%s %d: OPTEQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::OPTEQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*\+=[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: PEQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
inclineno();
return yy::mhmakeparser::token::PEQUAL;
}
[ \t]*\+=[ \t]* {
PRINTF(("%s %d: PEQUAL: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::PEQUAL;
}
/*---------------------------------------------------------------------------*/
[ \t]*;[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: -SEMICOLON (NEWLINE): %s\n",m_InputFileName.c_str(),lineno(),yytext));
m_curtoken=g_EmptyString;
inclineno();
BEGIN(COMMANDPARSE);
return yy::mhmakeparser::token::NEWLINE;
}
[ \t]*;[ \t]* {
PRINTF(("%s %d: -SEMICOLON (NEWLINE): %s\n",m_InputFileName.c_str(),lineno(),yytext));
m_curtoken=g_EmptyString;
BEGIN(COMMANDPARSE);
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
[ \t]*::[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: DOUBLECOLON: %s\n",m_InputFileName.c_str(),lineno(),yytext));
inclineno();
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::DOUBLECOLON;
}
[ \t]*::[ \t]* {
PRINTF(("%s %d: DOUBLECOLON: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::DOUBLECOLON;
}
/*---------------------------------------------------------------------------*/
[ \t]*:[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: COLON: %s\n",m_InputFileName.c_str(),lineno(),yytext));
inclineno();
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::COLON;
}
[ \t]*:[ \t]* {
PRINTF(("%s %d: COLON: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::COLON;
}
/*---------------------------------------------------------------------------*/
, {
PRINTF(("%s %d: COMMA: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::COMMA;
}
/*---------------------------------------------------------------------------*/
^endif {
if (m_IndentStack.size())
{
m_IndentStack.pop();
PRINTF(("%s %d: %s: depth %d\n",m_InputFileName.c_str(),lineno(),yytext,m_IndentStack.size()));
}
else
{
throw string("Unexpected endif at line ") + stringify(lineno()) + " of " + m_InputFileName;
}
}
/*---------------------------------------------------------------------------*/
^ifdef[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFDEF);
inclineno();
return yy::mhmakeparser::token::NEWLINE;
}
^ifdef[ \t]+ {
BEGIN(IFDEF);
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^if[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IF);
inclineno();
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::NEWLINE;
}
^if[ \t]+ {
BEGIN(IF);
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^ifndef[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFNDEF);
inclineno();
return yy::mhmakeparser::token::NEWLINE;
}
^ifndef[ \t]+ {
BEGIN(IFNDEF);
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^ifeq[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFEQ);
m_curtoken=g_EmptyString;
inclineno();
return yy::mhmakeparser::token::NEWLINE;
}
^ifeq[ \t]+ {
BEGIN(IFEQ);
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^ifneq[ \t]*\\[ \t\r]*\n[ \t]* {
BEGIN(IFNEQ);
m_curtoken=g_EmptyString;
inclineno();
return yy::mhmakeparser::token::NEWLINE;
}
^ifneq[ \t]+ {
BEGIN(IFNEQ);
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
^else[ \t]* {
if (m_IndentStack.size() && (!m_IndentStack.top()))
{
PRINTF(("%s %d: skipping else: depth %d\n",m_InputFileName.c_str(),lineno(),m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
m_IndentStack.top()=1;
BEGIN(SKIPUNTILELSEORENDIF);
}
else
{
throw string("Unexpected else at line ") + stringify(lineno()) + " of file " + m_InputFileName;
}
}
/*****************************************************************************/
\n {
yyless(0);
m_IndentStack.push(0);
if (GetParser()->IsEqual(m_curtoken))
{
PRINTF(("%s %d: Not Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str(),m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str(),m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
[ \t]*\\[ \t\r]*\n[ \t]* { inclineno(); m_curtoken += g_SpaceString;}
\r /* skip */
[^\\\r\n\$]+ |
[\\\$] { m_curtoken += (const char *)yytext; }
/*****************************************************************************/
\n {
yyless(0);
m_IndentStack.push(0);
if (!GetParser()->IsEqual(m_curtoken))
{
PRINTF(("%s %d: Not Skipping ifneq %s: depth %d\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str(),m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifneq %s: depth %d\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str(),m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
/*****************************************************************************/
[ \t\r]*[a-zA-Z0-9_]+[ \t\r]*\n {
yyless(yyleng-1);
m_IndentStack.push(0);
#ifndef WIN32
int lastidx=yyleng-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(),lineno(),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(),lineno(),yytext,m_IndentStack.size()));
BEGIN(INITIAL);
}
}
/*---------------------------------------------------------------------------*/
\n {
yyless(0);
m_IndentStack.push(0);
if (GetParser()->IsExprTrue(m_curtoken))
{
PRINTF(("%s %d: Not Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str(),m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifeq %s: depth %d\n",m_InputFileName.c_str(),lineno(),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(),lineno(),yytext,m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifdef %s: depth %d\n",m_InputFileName.c_str(),lineno(),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(),lineno(),yytext,m_IndentStack.size()));
BEGIN(INITIAL);
}
else
{
PRINTF(("%s %d: Skipping ifndef %s: depth %d\n",m_InputFileName.c_str(),lineno(),yytext,m_IndentStack.size()));
m_IndentSkip=m_IndentStack.size();
BEGIN(SKIPUNTILELSEORENDIF);
}
}
/*****************************************************************************/
\n[ ]*endif {
inclineno();
if (!m_IndentStack.size())
{
throw string("Unexpected endif at line ") + stringify(lineno()) + " of " + m_InputFileName;
}
else
{
m_IndentStack.pop();
PRINTF(("%s %d: endif: depth %d\n",m_InputFileName.c_str(),lineno(),m_IndentStack.size()));
if (m_IndentStack.size()==m_IndentSkip-1) BEGIN(INITIAL);
}
}
/*---------------------------------------------------------------------------*/
\n[ ]*else {
inclineno();
PRINTF(("%s %d: else: depth %d\n",m_InputFileName.c_str(),lineno(),m_IndentStack.size()));
if (m_IndentStack.top())
{
throw string("Unexpected else at line ") + stringify(lineno()) + " of file " + m_InputFileName;
}
m_IndentStack.top()=1;
if (m_IndentStack.size()==m_IndentSkip)
{
BEGIN(INITIAL);
}
}
/*---------------------------------------------------------------------------*/
\n[ ]*if(def|ndef|eq|neq)? {
inclineno();
m_IndentStack.push(0);
PRINTF(("%s %d: %s: depth %d\n",m_InputFileName.c_str(),lineno(),yytext+1,m_IndentStack.size()));
}
/*---------------------------------------------------------------------------*/
[a-zA-Z]+ /* skip */
/*---------------------------------------------------------------------------*/
[^a-zA-Z\n]+ /* skip */
/*---------------------------------------------------------------------------*/
\n[ ]*[a-zA-Z]+ {
inclineno();
}
/*---------------------------------------------------------------------------*/
\n {
inclineno();
}
/*---------------------------------------------------------------------------*/
[ \t]*#[^\n]* {
PRINTF(("%s %d: -COMMENT: %s\n",m_InputFileName.c_str(),lineno(),yytext));
}
/*---------------------------------------------------------------------------*/
[ \t]*\\[ \t\r]*\n[ \t]* {
PRINTF(("%s %d: SPACE:\n",m_InputFileName.c_str(),lineno()));
inclineno();
return yy::mhmakeparser::token::SPACE;
}
/*---------------------------------------------------------------------------*/
\.PHONY {
PRINTF(("%s %d: .PHONY: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::PHONY;
}
/*---------------------------------------------------------------------------*/
\.AUTODEPS {
PRINTF(("%s %d: .AUTODEPS: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::AUTODEPS;
}
/*---------------------------------------------------------------------------*/
export {
PRINTF(("%s %d: export: %s\n",m_InputFileName.c_str(),lineno(),yytext));
return yy::mhmakeparser::token::EXPORT;
}
/*---------------------------------------------------------------------------*/
^vpath {
PRINTF(("%s %d: vpath\n",m_InputFileName.c_str(),lineno()));
return yy::mhmakeparser::token::VPATH;
}
/*---------------------------------------------------------------------------*/
[a-zA-Z]:[a-zA-Z0-9\\\._\~\-%\@<&/]+\\[ \t\r]*\n {
size_t EndIndex=yyleng;
while (strchr(" \t\r\n\\",yytext[--EndIndex]));
yyless(EndIndex+1);
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
[a-zA-Z]:[a-zA-Z0-9\\\._\~\-%\@<&/]+ {
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
/*---------------------------------------------------------------------------*/
([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|]|\\\ |\\#)+\\[ \t\r]*\n {
size_t EndIndex=yyleng;
while (strchr(" \t\r\n\\",yytext[--EndIndex]));
yyless(EndIndex+1);
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|]|\\\ |\\#)+\+= {
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yyless(yyleng-2);
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
([a-zA-Z0-9\\\._\~\-\+%\@<&;/\*\|]|\\\ |\\#)+ {
PRINTF(("%s %d: STRING: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
^define[ \t]+[a-zA-Z0-9_\.]+[ \t]*\n {
const char *pVar=(const char *)yytext;
while (strchr(" \t",*pVar)) pVar++;
pVar+=6;
yylval->theString=pVar;
BEGIN(DEFINE);
m_curtoken=g_EmptyString;
PRINTF(("%s %d: VARDEF: %s\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str()));
inclineno();
return yy::mhmakeparser::token::VARDEF;
}
[ \t]*\\[ \t\r]*\n[ \t]* {
inclineno();
m_curtoken+=g_SpaceString;
}
. {
m_curtoken+=(const char *)yytext;
}
[ \t]*\n[ \t]*endef {
inclineno();
yylval->theString=m_curtoken;
PRINTF(("%s %d: VARVAL: %s\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str()));
BEGIN(INITIAL);
return yy::mhmakeparser::token::VARVAL;
}
/*---------------------------------------------------------------------------*/
\" {
BEGIN(QUOTE);
yymore();
}
/*---------------------------------------------------------------------------*/
\' {
BEGIN(SINGLEQUOTE);
yymore();
}
/*---------------------------------------------------------------------------*/
\$[\(\{] {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN MACRO $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
BEGIN(MAKEEXPRES);
m_curtoken=(const char *)yytext;
}
/*---------------------------------------------------------------------------*/
\$[\(\{][ \t]*error[ \t]+ {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN ERROR MACRO $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
BEGIN(ERRORMACRO);
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::NEWLINE; // Make sure that the previous lines are matched by the bison parser (so that all variables until here are defined)
}
/*---------------------------------------------------------------------------*/
\$[\(\{][ \t]*(message|info)[ \t]+ {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN MESSAGE MACRO $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
BEGIN(MESSAGEMACRO);
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::NEWLINE; // Make sure that the previous lines are matched by the bison parser (so that all variables until here are defined)
}
/*---------------------------------------------------------------------------*/
\$[\(\{][ \t]*reparse[ \t]+ {
m_BraceIndent++;
PRINTF(("%s %d: BEGIN REPARSE MACRO $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
BEGIN(REPARSEMACRO);
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
\$[<@/$] {
PRINTF(("%s %d: DOLLAREXPR: %s\n",m_InputFileName.c_str(),lineno(),yytext));
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::DOLLAREXPR;
}
/*---------------------------------------------------------------------------*/
[ \t\r]*\n\t[ \t]* {
/* token newline */
PRINTF(("%s %d: NEWLINE\n",m_InputFileName.c_str(),lineno()));
inclineno();
m_curtoken=g_EmptyString;
BEGIN(COMMANDPARSE);
return yy::mhmakeparser::token::NEWLINE;
}
/*---------------------------------------------------------------------------*/
[\(\)\{\}] {
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
/*---------------------------------------------------------------------------*/
[^\n] {
PRINTF(("%s %d: ANYCHAR: %d: %s\n",m_InputFileName.c_str(),lineno(),lineno(),yytext));
throw string("Unexpected character '")+yytext+"' in makefile '" + m_InputFileName + "' at line "+stringify(lineno()) + ", column " + stringify(colno()-1);
}
/*****************************************************************************/
[ \t\r]*\n {
PRINTF(("%s %d: COMMAND: %d: %s\n",m_InputFileName.c_str(),lineno(),lineno(),m_curtoken.c_str()));
yylval->theString=m_curtoken;
inclineno();
BEGIN(INITIAL);
return yy::mhmakeparser::token::COMMAND;
}
/*---------------------------------------------------------------------------*/
[ \t\r]*\n\t[ \t]* {
PRINTF(("%s %d: COMMAND: %s\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str()));
yylval->theString=m_curtoken;
inclineno();
m_curtoken=g_EmptyString;
return yy::mhmakeparser::token::COMMAND;
}
/*---------------------------------------------------------------------------*/
[ \t]*\\[ \t\r]*\n[ \t]* {
inclineno();
m_curtoken+=g_SpaceString;
}
/*---------------------------------------------------------------------------*/
[ ]+ {
m_curtoken+=g_SpaceString;
}
/*---------------------------------------------------------------------------*/
[^ \r\n#\\$]+ |
[\\\$] {
m_curtoken+=(const char *)yytext;
}
/*---------------------------------------------------------------------------*/
[ \t]*\\#[^\n]* {
int nChars=(int)((strchr((const char *)yytext,'#')-(char*)yytext))+1;
yyless(nChars);
m_curtoken+=string(yytext,nChars-2);
m_curtoken+='#';
}
/*---------------------------------------------------------------------------*/
[ \t]*#[^\n]* {
PRINTF(("%s %d: -COMMENT: %s\n",m_InputFileName.c_str(),lineno(),yytext));
}
/*****************************************************************************/
\" {
PRINTF(("%s %d: QUOTEDSTRING: %s\n",m_InputFileName.c_str(),lineno(),yytext));
BEGIN(INITIAL);
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
/*---------------------------------------------------------------------------*/
\r /* skip */
[^\\\"\r\n$]+ |
[\\\$] |
\\\" |
\\# {
yymore();
}
/*****************************************************************************/
\' {
PRINTF(("%s %d: QUOTEDSTRING: %s\n",m_InputFileName.c_str(),lineno(),yytext));
BEGIN(INITIAL);
yylval->theString=(const char *)yytext;
return yy::mhmakeparser::token::STRING;
}
/*---------------------------------------------------------------------------*/
\r /* skip */
[^\\\'\r\n$]+ |
[\\\$] |
\\\' |
\\# {
yymore();
}
/*****************************************************************************/
[\)\}] {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE ERROR MACRO ): %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
if (!m_BraceIndent)
{
PRINTF(("%s %d: ERRORMACRO: %s\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str()));
throw string("\n-> ")+m_InputFileName.c_str()+"("+stringify(lineno())+") : "+GetParser()->ExpandExpression(m_curtoken);
} else {
m_curtoken+=(const char *)yytext;
}
}
/*****************************************************************************/
[\)\}] {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE MESSAGE MACRO ): %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
if (!m_BraceIndent)
{
PRINTF(("%s %d: MESSAGEMACRO: %s\n",m_InputFileName.c_str(),lineno(),yytext));
cerr<ExpandExpression(m_curtoken)<[\)\}] {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE REPARSE MACRO ): %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
if (!m_BraceIndent)
{
PRINTF(("%s %d: REPARSEMACRO: %s\n",m_InputFileName.c_str(),lineno(),yytext));
string Deps=GetParser()->ExpandExpression(m_curtoken);
PRINTF(("%s %d: REPARSEMACRO expanded: %s\n",m_InputFileName.c_str(),lineno(),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
{
m_curtoken+=(const char *)yytext;
}
}
/*****************************************************************************/
[\)\}] {
m_BraceIndent--;
PRINTF(("%s %d: CLOSE BRACE MAKEEXPRES MACRO ): %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
if (!m_BraceIndent)
{
BEGIN(INITIAL);
m_curtoken+=(const char *)yytext;
yylval->theString=m_curtoken;
PRINTF(("%s %d: DOLLAREXPR: %s\n",m_InputFileName.c_str(),lineno(),m_curtoken.c_str()));
return yy::mhmakeparser::token::DOLLAREXPR;
}
else
{
m_curtoken+=(const char *)yytext;
}
}
/*---------------------------------------------------------------------------*/
\$[\(\{] {
m_BraceIndent++;
PRINTF(("%s %d: MACRO extra $(: %d\n",m_InputFileName.c_str(),lineno(),m_BraceIndent));
m_curtoken+=(const char *)yytext;
}
/*---------------------------------------------------------------------------*/
[^$\(\)\{\}\r\n\\]+ |
[\(\$\\\{] {
m_curtoken+=(const char *)yytext;
}
[ \t\r]*\\[ \t\r]*\n[ \t\r]* {
inclineno();
m_curtoken+=g_SpaceString;
}
<> {
throw string("Missing endif or else statement. #else or #endif used?");
}
<> {
if (m_BraceIndent)
{
throw string("Missing closing ) or } 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
{
INSTACK *pInStack=m_IncludeStack.top();
yypop_buffer_state();
m_InputFileName=pInStack->m_FileName;
*yylloc=pInStack->yylloc;
m_IncludeStack.pop();
}
}
%%