From 9139f1df4cda80b91ab68e5de27e85eaa4c54682 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 31 Jul 2006 08:07:12 +0000 Subject: I still can't get the pymake file to auto-make the bison and flex .c files, but besides that everything is looking great. There's only one thing left to parse and interpret before we can try actually building something. --- src/action.cpp | 4 +- src/build.l | 2 +- src/build.y | 142 +++++++++++++++++++++++++++++++++++++++++-------- src/builder.cpp | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/builder.h | 46 ++++++++++++++++ src/command.cpp | 3 +- src/filetarget.cpp | 17 ++++++ src/filetarget.h | 19 +++++++ src/main.cpp | 2 + src/rule.cpp | 61 +++++++++++++++++++++ src/rule.h | 49 +++++++++++++++++ src/target.cpp | 24 +++++++++ src/target.h | 28 ++++++++++ 13 files changed, 522 insertions(+), 27 deletions(-) create mode 100644 src/filetarget.cpp create mode 100644 src/filetarget.h create mode 100644 src/rule.cpp create mode 100644 src/rule.h create mode 100644 src/target.cpp create mode 100644 src/target.h (limited to 'src') diff --git a/src/action.cpp b/src/action.cpp index 7a7bbb8..c594792 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -25,9 +25,9 @@ void Action::add( Command *pCmd ) void Action::debug() { if( bDefault ) - printf("action default:\n"); + printf(" action default:\n"); else - printf("action \"%s\":\n", sName.getString() ); + printf(" action \"%s\":\n", sName.getString() ); for( std::list::iterator i = lCommand.begin(); i != lCommand.end(); i++ ) diff --git a/src/build.l b/src/build.l index 3a457b1..a88f90d 100644 --- a/src/build.l +++ b/src/build.l @@ -58,7 +58,7 @@ std::string strbuf; "#".* /* single line comment */ -[^ \t\r\n\'\":=,.]+ { +[^ \t\r\n\'\":=,/][^ \t\r\n\'\":=,]* { yylval->strval = stringdup( yytext ); return STRING; } diff --git a/src/build.y b/src/build.y index 45a84f1..8345b1f 100644 --- a/src/build.y +++ b/src/build.y @@ -4,6 +4,8 @@ # include "builder.h" # include "action.h" # include "command.h" +# include "rule.h" +# include "filetarget.h" # include "build.tab.h" void yyerror( YYLTYPE *locp, Builder &bld, char const *msg ); %} @@ -28,25 +30,25 @@ void yyerror( YYLTYPE *locp, Builder &bld, char const *msg ); %token REGEXP "regular expression" %token TOK_ADDSET "+=" -%token TOK_DEFAULT "keyword 'default'" -%token TOK_ACTION "keyword 'action'" -%token TOK_CREATE "keyword 'create'" -%token TOK_FILE "keyword 'file'" -%token TOK_FROM "keyword 'from'" -%token TOK_FILES "keyword 'files'" -%token TOK_IN "keyword 'in'" -%token TOK_USING "keyword 'using'" -%token TOK_RULE "keyword 'rule'" -%token TOK_REQUIRES "keyword 'requires'" -%token TOK_FOR "keyword 'for'" -%token TOK_SET "keyword 'set'" -%token TOK_MATCHES "keyword 'matches'" -%token TOK_ALL "keyword 'all'" -%token TOK_ONE "keyword 'one'" -%token TOK_PERFORM "keyword 'perform'" -%token TOK_PRODUCES "keyword 'produces'" -%token TOK_COMMAND "keyword 'command'" -%token TOK_CHECK "keyword 'check'" +%token TOK_DEFAULT "default" +%token TOK_ACTION "action" +%token TOK_CREATE "create" +%token TOK_FILE "file" +%token TOK_FROM "from" +%token TOK_FILES "files" +%token TOK_IN "in" +%token TOK_USING "using" +%token TOK_RULE "rule" +%token TOK_REQUIRES "requires" +%token TOK_FOR "for" +%token TOK_SET "set" +%token TOK_MATCHES "matches" +%token TOK_ALL "all" +%token TOK_ONE "one" +%token TOK_PERFORM "perform" +%token TOK_PRODUCES "produces" +%token TOK_COMMAND "command" +%token TOK_CHECK "check" %token TOK_EOL "end of line" %token ',' ':' '=' @@ -73,9 +75,40 @@ line: TOK_DEFAULT TOK_ACTION ':' } actionlst | TOK_CREATE createwhat TOK_FROM createfrom TOK_USING createusing + | STRING TOK_REQUIRES + { + bld.setTmp( $1 ); + } + reqlst + | listcmds + | TOK_FOR STRING + { + bld.setContext( $2 ); + } + listcmds + { + bld.setContext(); + } + | rule ; -createwhat: TOK_FILE STRING { printf("target: %s\n", $2 ); } +reqlst: STRING + { + bld.requires( bld.getTmp(), $1 ); + } + | reqlst ',' STRING + { + bld.requires( bld.getTmp(), $3 ); + } + ; + +listcmds: TOK_SET setexpr + ; + +createwhat: TOK_FILE STRING + { + bld.add( new FileTarget( $2 ) ); + } ; createfrom: TOK_FILES TOK_IN createfromdirlst @@ -88,7 +121,10 @@ createfromdirlst: createfromdir createfromdir: STRING { printf(" srcdir: %s\n", $1 ); } ; -createusing: TOK_RULE STRING { printf(" rule: %s\n", $2 ); } +createusing: TOK_RULE STRING + { + bld.lastTarget()->setRule( $2 ); + } ; actionlst: action @@ -101,6 +137,70 @@ action: TOK_CHECK STRING } ; +setexpr: STRING '=' STRING + { + bld.varSet( $1, $3 ); + } + | STRING TOK_ADDSET STRING + { + bld.varAddSet( $1, $3 ); + } + ; + +rule: TOK_RULE STRING + { + bld.add( new Rule( $2 ) ); + } + rulesublst TOK_PERFORM rulecompletion + ; + +rulesublst: rulesub + | rulesublst rulesub + ; + +rulesub: TOK_MATCHES rulematches + | TOK_PRODUCES STRING + { + bld.lastRule()->setProduces( $2 ); + } + ; + +rulematches: TOK_ALL REGEXP + { + try + { + bld.lastRule()->setMatches( Rule::matchAll, $2 ); + } + catch( BuildException &e ) + { + std::string s("RegExp compile error: "); + s += e.what(); + yyerror( &yyloc, bld, s.c_str() ); + return 1; + } + } + | TOK_ONE REGEXP + { + try + { + bld.lastRule()->setMatches( Rule::matchOne, $2 ); + } + catch( BuildException &e ) + { + std::string s("RegExp compile error: "); + s += e.what(); + yyerror( &yyloc, bld, s.c_str() ); + return 1; + } + } + ; + +rulecompletion: TOK_COMMAND STRING + { + bld.lastRule()->setPerforms( Rule::perfCommand, $2 ); + } + ; + %% void yyerror( YYLTYPE *locp, Builder &bld, char const *msg ) diff --git a/src/builder.cpp b/src/builder.cpp index 2de6f5c..e5017e2 100644 --- a/src/builder.cpp +++ b/src/builder.cpp @@ -3,13 +3,17 @@ #include "builder.h" #include "action.h" #include "command.h" +#include "target.h" #include "build.tab.h" +#include "rule.h" subExceptionDef( BuildException ) Builder::Builder() : pDefaultAction( NULL ), - pLastAddedAction( NULL ) + pLastAddedAction( NULL ), + sTmp(""), + sContext("") { } @@ -51,13 +55,159 @@ void Builder::add( Command *pCmd ) } } +void Builder::add( Rule *pRule ) +{ + pLastAddedRule = pRule; + mRule[pRule->getName()] = pRule; +} + +void Builder::add( Target *pTarg ) +{ + pLastAddedTarget = pTarg; + mTarget[pTarg->getName()] = pTarg; +} + void Builder::debug() { + printf("Actions:\n"); pDefaultAction->debug(); for( std::map::iterator i = mAction.begin(); i != mAction.end(); i++ ) { (*i).second->debug(); } + + printf("Targets:\n"); + for( std::map::iterator i = mTarget.begin(); + i != mTarget.end(); i++ ) + { + (*i).second->debug(); + } + + printf("Rules:\n"); + for( std::map::iterator i = mRule.begin(); + i != mRule.end(); i++ ) + { + (*i).second->debug(); + } + + printf("Variables:\n"); + for( varmap::iterator i = mVar.begin(); i != mVar.end(); i++ ) + { + printf(" %s = \"%s\"\n", (*i).first.c_str(), (*i).second.c_str() ); + } + + printf("Variables (by context):\n"); + for( std::map::iterator j = mContVar.begin(); + j != mContVar.end(); j++ ) + { + printf(" %s:\n", (*j).first.c_str() ); + for( varmap::iterator i = (*j).second.begin(); + i != (*j).second.end(); i++ ) + { + printf(" %s = \"%s\"\n", + (*i).first.c_str(), (*i).second.c_str() ); + } + } + + printf("Additional dependancies:\n"); + for( std::map *>::iterator i = + mRequires.begin(); i != mRequires.end(); i++ ) + { + printf(" %s: ", (*i).first.c_str() ); + std::list *pList = (*i).second; + for( std::list::iterator j = pList->begin(); + j != pList->end(); j++ ) + { + if( j != pList->begin() ) + printf(", "); + printf("%s", (*j).c_str() ); + } + printf("\n"); + } +} + +void Builder::checkVar( const char *cont, const char *sName ) +{ + if( cont[0] != '\0' ) + { + varmap &mmVar = mContVar[cont]; + if( mmVar.find( sName ) == mmVar.end() ) + { + checkVar( "", sName ); + mmVar[sName] = mVar[sName]; + } + } + else + { + if( mVar.find( sName ) == mVar.end() ) + { + char *env = getenv( sName ); + if( env ) + mVar[sName] = env; + else + mVar[sName] = ""; + } + } +} + +void Builder::varSet( const char *sName, const char *sValue ) +{ + checkVar( sContext, sName ); + + if( sContext[0] == '\0' ) + { + mVar[sName] = sValue; + } + else + { + mContVar[sContext.getString()][sName] = sValue; + } +} + +void Builder::varAddSet( const char *sName, const char *sValue ) +{ + checkVar( sContext, sName ); + + if( sContext[0] == '\0' ) + { + std::string s = mVar[sName]; + s += " "; + s += sValue; + mVar[sName] = s; + } + else + { + std::string s = mContVar[sContext.getString()][sName]; + s += " "; + s += sValue; + mContVar[sContext.getString()][sName] = s; + } +} + +void Builder::requires( const char *sBase, const char *sReq ) +{ + std::list *pList = NULL; + if( mRequires.find(sBase) == mRequires.end() ) + { + pList = new std::list; + mRequires[sBase] = pList; + } + else + { + pList = mRequires[sBase]; + } + + pList->push_back( sReq ); +} + +void Builder::setContext( const char *sCont ) +{ + sContext = sCont; +} + +void Builder::setContext() +{ + setContext(""); } diff --git a/src/builder.h b/src/builder.h index 58afaf5..89810c0 100644 --- a/src/builder.h +++ b/src/builder.h @@ -6,12 +6,15 @@ #include #include "build.tab.h" #include "exceptionbase.h" +#include "staticstring.h" subExceptionDecl( BuildException ) class Builder; class Action; class Command; +class Rule; +class Target; #define YY_DECL int yylex( YYSTYPE *yylval_param, YYLTYPE *yylloc_param, Builder &bld ) YY_DECL; @@ -39,6 +42,13 @@ public: void add( Action *pAct ); void add( Command *pCmd ); + void add( Rule *pRule ); + void add( Target *pTarg ); + void varSet( const char *sName, const char *sValue ); + void varAddSet( const char *sName, const char *sValue ); + void requires( const char *sBase, const char *sReq ); + void setContext( const char *sCont ); + void setContext(); bool hasDefaultAction() { @@ -47,13 +57,49 @@ public: void debug(); + Rule *lastRule() + { + return pLastAddedRule; + } + + Target *lastTarget() + { + return pLastAddedTarget; + } + + void setTmp( const char *s ) + { + sTmp = s; + } + + const char *getTmp() + { + return sTmp; + } + private: + void checkVar( const char *cont, const char *sName ); void scanBegin(); void scanEnd(); Action *pDefaultAction; Action *pLastAddedAction; std::map mAction; + + Rule *pLastAddedRule; + std::map mRule; + + Target *pLastAddedTarget; + std::map mTarget; + + typedef std::map varmap; + varmap mVar; + std::map *> mRequires; + + std::map mContVar; + StaticString sContext; + + StaticString sTmp; }; #endif diff --git a/src/command.cpp b/src/command.cpp index 4a1fa6c..72f9a4c 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -13,7 +13,6 @@ Command::~Command() void Command::debug() { static const char *cmdt[]={"Check", "Clean"}; - printf(" command: %s %s\n", cmdt[ nType ], sTarget.getString() ); - + printf(" command: %s %s\n", cmdt[ nType ], sTarget.getString() ); } diff --git a/src/filetarget.cpp b/src/filetarget.cpp new file mode 100644 index 0000000..b9d7946 --- /dev/null +++ b/src/filetarget.cpp @@ -0,0 +1,17 @@ +#include "filetarget.h" + +FileTarget::FileTarget( const char *sName ) : + Target( sName ) +{ +} + +FileTarget::~FileTarget() +{ +} + +void FileTarget::debug() +{ + Target::debug(); + printf(" type: FileTarget\n"); +} + diff --git a/src/filetarget.h b/src/filetarget.h new file mode 100644 index 0000000..cf4b3d6 --- /dev/null +++ b/src/filetarget.h @@ -0,0 +1,19 @@ +#ifndef FILE_TARGET_H +#define FILE_TARGET_H + +#include +#include "target.h" + +class FileTarget : public Target +{ +public: + FileTarget( const char *sName ); + virtual ~FileTarget(); + + virtual void debug(); + +private: + +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp index 598a97f..995009d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,8 @@ int main() bld.load("congo"); + printf("\n\n----------\nDebug dump\n----------\n"); + bld.debug(); } diff --git a/src/rule.cpp b/src/rule.cpp new file mode 100644 index 0000000..a7ebf9b --- /dev/null +++ b/src/rule.cpp @@ -0,0 +1,61 @@ +#include "rule.h" +#include "builder.h" // for BuildException + +Rule::Rule( const char *sName ) : + sName( sName ), + sProduces("{target}") +{ +} + +Rule::~Rule() +{ + regfree( &rWhat ); +} + +void Rule::debug() +{ + printf(" Rule %s produces %s:\n", + sName.getString(), + sProduces.getString() + ); + printf(" Matches "); + if( mHow == matchOne ) + printf("one "); + else if( mHow == matchAll ) + printf("all "); + printf("/%s/\n", sWhat.getString() ); + + printf(" Performs "); + if( pHow == perfCommand ) + printf("command "); + printf("\"%s\"\n", sPerfCmd.getString() ); +} + +void Rule::setProduces( const char *sP ) +{ + sProduces = sP; +} + +void Rule::setMatches( Matches how, const char *sW ) +{ + sWhat = sW; + mHow = how; + + int nErr = regcomp( &rWhat, sW, REG_EXTENDED|REG_NEWLINE ); + if( nErr ) + { + size_t length = regerror( nErr, &rWhat, NULL, 0 ); + char *buffer = new char[length]; + (void) regerror( nErr, &rWhat, buffer, length ); + StaticString s( buffer ); + delete[] buffer; + throw BuildException( s.getString() ); + } +} + +void Rule::setPerforms( Perform pwhat, const char *sperfcmd ) +{ + pHow = pwhat; + sPerfCmd = sperfcmd; +} + diff --git a/src/rule.h b/src/rule.h new file mode 100644 index 0000000..64cdc9d --- /dev/null +++ b/src/rule.h @@ -0,0 +1,49 @@ +#ifndef RULE_H +#define RULE_H + +#include +#include +#include "staticstring.h" + +class Rule +{ +public: + enum Matches + { + matchOne, + matchAll + }; + + enum Perform + { + perfCommand + }; + +public: + Rule( const char *sName ); + virtual ~Rule(); + + const char *getName() + { + return sName; + } + + void debug(); + + void setProduces( const char *sProduces ); + void setMatches( Matches how, const char *sWhat ); + void setPerforms( Perform pwhat, const char *sPerfCmd ); + +private: + StaticString sName; + StaticString sProduces; + + Matches mHow; + StaticString sWhat; + regex_t rWhat; + + Perform pHow; + StaticString sPerfCmd; +}; + +#endif diff --git a/src/target.cpp b/src/target.cpp new file mode 100644 index 0000000..b0967bf --- /dev/null +++ b/src/target.cpp @@ -0,0 +1,24 @@ +#include "target.h" + +Target::Target( const char *sName ) : + sName( sName ) +{ +} + +Target::~Target() +{ +} + +void Target::setRule( const char *sRule ) +{ + this->sRule = sRule; +} + +void Target::debug() +{ + printf(" %s:\n Rule: %s\n", + sName.getString(), + sRule.getString() + ); +} + diff --git a/src/target.h b/src/target.h new file mode 100644 index 0000000..667c467 --- /dev/null +++ b/src/target.h @@ -0,0 +1,28 @@ +#ifndef TARGET_H +#define TARGET_H + +#include +#include "staticstring.h" + +class Target +{ +public: + Target( const char *sName ); + virtual ~Target(); + + const char *getName() + { + return sName; + } + + void setRule( const char *sRule ); + + virtual void debug(); + +private: + StaticString sName; + StaticString sRule; + +}; + +#endif -- cgit v1.2.3