aboutsummaryrefslogtreecommitdiff
path: root/tools/mhmake/src/mhmakelexer.l
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mhmake/src/mhmakelexer.l')
-rw-r--r--tools/mhmake/src/mhmakelexer.l900
1 files changed, 900 insertions, 0 deletions
diff --git a/tools/mhmake/src/mhmakelexer.l b/tools/mhmake/src/mhmakelexer.l
new file mode 100644
index 000000000..5e73dd812
--- /dev/null
+++ b/tools/mhmake/src/mhmakelexer.l
@@ -0,0 +1,900 @@
+/* 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 <http://www.gnu.org/licenses/>.
+*/
+
+/* $Rev$ */
+
+/* -------------- declaration section -------------- */
+%name mhmakelexer
+%header{
+#include "mhmakeparser.h"
+#include "fileinfo.h"
+#include "rule.h"
+#include "util.h"
+
+static uint32 LoadMakMd5(refptr<fileinfo> &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<fileinfo> &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<int> m_IndentStack;\
+ bool m_IgnoreIncludeError;\
+ string m_InputFileName; \
+ string m_curtoken; \
+ iterstack<INSTACK> 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)
+}
+
+ /*****************************************************************************/
+<INCLUDE>[ \t]* /* eat the whitespace */
+ /*---------------------------------------------------------------------------*/
+<INCLUDE>[^\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<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();
+ FILE *pTmp = ::fopen(strToInclude.c_str(), "r" );
+ if ( ! pTmp )
+ {
+ if (!m_IgnoreIncludeError)
+ {
+ iterstack<INSTACK>::reverse_iterator StackIt=m_IncludeStack.rbegin();
+ while (StackIt!=m_IncludeStack.rend())
+ {
+ cout<<" in "<<StackIt->m_FileName<<" ("<<StackIt->m_Line<<")";
+ StackIt++;
+ }
+ cout<<endl;
+ cout<<"Warning error opening file "<<strToInclude<<" in "<<m_InputFileName<<" ("<<m_Line<<")\n";
+ pParser->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)
+}
+
+ /*****************************************************************************/
+<LOAD_MAKEFILE>[^\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);
+ }
+
+}
+ /*---------------------------------------------------------------------------*/
+<LOAD_MAKEFILE>\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++;
+ return mhmakeparser::NEWLINE;
+}
+
+^[ \t]*if[ \t]+ {
+ BEGIN(IF);
+ 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;
+ }
+}
+
+ /*****************************************************************************/
+<IFEQ>\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);
+ }
+}
+
+<IFEQ,IFNEQ>[ \t]*\\[ \t\r]*\n[ \t]* { m_Line++; m_curtoken += g_SpaceString;}
+
+<IFEQ,IFNEQ>\r /* skip */
+
+<IFEQ,IFNEQ>[^\\\r\n]+ |
+<IFEQ,IFNEQ>\\ { m_curtoken += (const char *)yytext; }
+
+ /*****************************************************************************/
+<IFNEQ>\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);
+ }
+}
+
+ /*****************************************************************************/
+<IF,IFDEF,IFNDEF>[ \t\r]* /* skip */
+
+ /*---------------------------------------------------------------------------*/
+<IF>[a-zA-Z0-9_]+ {
+ m_IndentStack.push(0);
+ 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);
+ }
+}
+
+ /*---------------------------------------------------------------------------*/
+<IFDEF>[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);
+ }
+}
+
+ /*****************************************************************************/
+<IFNDEF>[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);
+ }
+}
+
+ /*****************************************************************************/
+<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);
+ }
+}
+
+ /*---------------------------------------------------------------------------*/
+<SKIPUNTILELSEORENDIF>\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);
+ }
+}
+
+ /*---------------------------------------------------------------------------*/
+<SKIPUNTILELSEORENDIF>\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()));
+}
+
+ /*---------------------------------------------------------------------------*/
+<SKIPUNTILELSEORENDIF>[a-zA-Z]+ /* skip */
+ /*---------------------------------------------------------------------------*/
+<SKIPUNTILELSEORENDIF>[^a-zA-Z\n]+ /* skip */
+ /*---------------------------------------------------------------------------*/
+<SKIPUNTILELSEORENDIF>\n[ ]*[a-zA-Z]+ m_Line++;
+ /*---------------------------------------------------------------------------*/
+<SKIPUNTILELSEORENDIF>\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;
+}
+
+ /*---------------------------------------------------------------------------*/
+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));
+}
+
+ /*****************************************************************************/
+
+<COMMANDPARSE>[ \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;
+}
+
+ /*---------------------------------------------------------------------------*/
+<COMMANDPARSE>[ \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;
+}
+
+ /*---------------------------------------------------------------------------*/
+<COMMANDPARSE>[ \t]*\\[ \t\r]*\n[ \t]* {
+ m_Line++;
+ m_curtoken+=g_SpaceString;
+}
+
+ /*---------------------------------------------------------------------------*/
+<COMMANDPARSE>[ ]+ {
+ m_curtoken+=g_SpaceString;
+}
+
+ /*---------------------------------------------------------------------------*/
+<COMMANDPARSE>[^ \r\n#\\]+ |
+<COMMANDPARSE>\\ {
+ m_curtoken+=(const char *)yytext;
+}
+
+ /*---------------------------------------------------------------------------*/
+<COMMANDPARSE>[ \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);
+}
+
+ /*---------------------------------------------------------------------------*/
+<COMMANDPARSE>[ \t]*#[^\n]* {
+ PRINTF(("%s %d: -COMMENT: %s\n",m_InputFileName.c_str(),m_Line,yytext));
+}
+
+ /*****************************************************************************/
+<QUOTE>\" {
+ PRINTF(("%s %d: QUOTEDSTRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
+ BEGIN(INITIAL);
+ theValue.theString=(const char *)yytext;
+ return mhmakeparser::STRING;
+}
+
+ /*---------------------------------------------------------------------------*/
+<QUOTE>\r /* skip */
+
+<QUOTE>[^\\\"\r\n]+ |
+<QUOTE>\\ |
+<QUOTE>\\\" |
+<QUOTE>\\# {
+ yymore();
+}
+
+ /*****************************************************************************/
+<SINGLEQUOTE>\' {
+ PRINTF(("%s %d: QUOTEDSTRING: %s\n",m_InputFileName.c_str(),m_Line,yytext));
+ BEGIN(INITIAL);
+ theValue.theString=(const char *)yytext;
+ return mhmakeparser::STRING;
+}
+
+ /*---------------------------------------------------------------------------*/
+<SINGLEQUOTE>\r /* skip */
+
+<SINGLEQUOTE>[^\\\'\r\n]+ |
+<SINGLEQUOTE>\\ |
+<SINGLEQUOTE>\\\' |
+<SINGLEQUOTE>\\# {
+ yymore();
+}
+
+ /*****************************************************************************/
+<ERRORMACRO>\) {
+ 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();
+ }
+}
+
+ /*****************************************************************************/
+<MESSAGEMACRO>\) {
+ 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<<GetParser()->ExpandExpression((const char*)yytext)<<endl;
+ BEGIN(INITIAL);
+ } else {
+ yymore();
+ }
+}
+
+ /*****************************************************************************/
+<REPARSEMACRO>\) {
+ 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();
+ }
+}
+
+ /*****************************************************************************/
+<MAKEEXPRES>\) {
+ 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();
+ }
+}
+
+ /*---------------------------------------------------------------------------*/
+<MAKEEXPRES,ERRORMACRO,MESSAGEMACRO,REPARSEMACRO>\$\( {
+ m_BraceIndent++;
+ PRINTF(("%s %d: MACRO extra $(: %d\n",m_InputFileName.c_str(),m_Line,m_BraceIndent));
+ yymore();
+}
+
+ /*---------------------------------------------------------------------------*/
+<MAKEEXPRES,ERRORMACRO,MESSAGEMACRO,REPARSEMACRO>[^$\(\)\r\n]+ |
+<MAKEEXPRES,ERRORMACRO,MESSAGEMACRO,REPARSEMACRO>\$ |
+<MAKEEXPRES,ERRORMACRO,MESSAGEMACRO,REPARSEMACRO>\( {
+ yymore();
+}
+<MAKEEXPRES,ERRORMACRO,MESSAGEMACRO,REPARSEMACRO>\r?\n {
+ m_Line++;
+}
+
+<SKIPUNTILELSEORENDIF><<EOF>> {
+ throw string("Missing endif or else statement. #else or #endif used?");
+}
+
+<<EOF>> {
+ 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();
+ }
+}
+%%
+