From b672fa69c4c98509f8ee251b87300e3fcbe6bdc8 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Mon, 31 Jul 2006 17:23:04 +0000 Subject: We're almost to rule/command generation, then only a couple of steps before it will do it all! --- src/action.cpp | 10 +++ src/action.h | 3 + src/build.y | 46 +++++++++-- src/builder.cpp | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/builder.h | 39 ++++++++- src/command.cpp | 16 ++++ src/command.h | 4 + src/filetarget.cpp | 65 +++++++++++++++ src/filetarget.h | 5 ++ src/main.cpp | 5 +- src/regexp.cpp | 71 ++++++++++++++++ src/regexp.h | 36 ++++++++ src/rule.cpp | 37 +++++++-- src/rule.h | 8 +- src/target.cpp | 16 ++++ src/target.h | 13 ++- 16 files changed, 589 insertions(+), 20 deletions(-) create mode 100644 src/regexp.cpp create mode 100644 src/regexp.h (limited to 'src') diff --git a/src/action.cpp b/src/action.cpp index c594792..8907816 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -1,5 +1,6 @@ #include "action.h" #include "command.h" +#include "builder.h" Action::Action() : bDefault( true ), @@ -36,3 +37,12 @@ void Action::debug() } } +void Action::execute( Builder &bld ) +{ + for( std::list::iterator i = lCommand.begin(); + i != lCommand.end(); i++ ) + { + (*i)->execute( bld ); + } +} + diff --git a/src/action.h b/src/action.h index 12c2cc4..7518ed2 100644 --- a/src/action.h +++ b/src/action.h @@ -5,6 +5,7 @@ #include "staticstring.h" class Command; +class Builder; class Action { @@ -26,6 +27,8 @@ public: void debug(); + void execute( class Builder &bld ); + private: bool bDefault; StaticString sName; diff --git a/src/build.y b/src/build.y index 8345b1f..ecc5d59 100644 --- a/src/build.y +++ b/src/build.y @@ -78,8 +78,15 @@ line: TOK_DEFAULT TOK_ACTION ':' | STRING TOK_REQUIRES { bld.setTmp( $1 ); + bld.requiresRegexp( false ); } - reqlst + reqcompletion + | REGEXP TOK_REQUIRES + { + bld.setTmp( $1 ); + bld.requiresRegexp( true ); + } + reqcompletion | listcmds | TOK_FOR STRING { @@ -92,6 +99,13 @@ line: TOK_DEFAULT TOK_ACTION ':' | rule ; +reqcompletion: reqlst + | TOK_FROM TOK_COMMAND STRING + { + bld.requiresFromCommand( bld.getTmp(), $3 ); + } + ; + reqlst: STRING { bld.requires( bld.getTmp(), $1 ); @@ -118,7 +132,20 @@ createfromdirlst: createfromdir | createfromdirlst ',' createfromdir ; -createfromdir: STRING { printf(" srcdir: %s\n", $1 ); } +createfromdir: STRING + { + try + { + ((FileTarget *)bld.lastTarget())->addInputDir( $1 ); + } + catch( BuildException &e ) + { + std::string s( $1 ); + s +=": "; + s += e.what(); + yyerror( &yyloc, bld, s.c_str() ); + } + } ; createusing: TOK_RULE STRING @@ -159,12 +186,19 @@ rulesublst: rulesub ; rulesub: TOK_MATCHES rulematches - | TOK_PRODUCES STRING - { - bld.lastRule()->setProduces( $2 ); - } + | TOK_PRODUCES produceslst ; +produceslst: STRING + { + bld.lastRule()->addProduces( $1 ); + } + | produceslst ',' STRING + { + bld.lastRule()->addProduces( $3 ); + } + ; + rulematches: TOK_ALL REGEXP { try diff --git a/src/builder.cpp b/src/builder.cpp index e5017e2..8e29c81 100644 --- a/src/builder.cpp +++ b/src/builder.cpp @@ -32,6 +32,28 @@ void Builder::load( const char *sFN ) scanEnd(); } +void Builder::build( const char *sAct ) +{ + Action *pAct; + if( sAct == NULL ) + pAct = pDefaultAction; + else + { + if( mAction.find( sAct ) == mAction.end() ) + throw BuildException("No action matches '%s'.", sAct ); + pAct = mAction[sAct]; + } + + printf("--- %s ---\n", pAct->getName() ); + + pAct->execute( *this ); +} + +void Builder::execute( Action *pAct ) +{ + pAct->execute( *this ); +} + void Builder::add( Action *pAct ) { if( pAct->isDefault() ) @@ -185,7 +207,124 @@ void Builder::varAddSet( const char *sName, const char *sValue ) } } +void Builder::processRequires( std::list &lInput ) +{ + for( regreqlist::iterator i = lRequiresRegexp.begin(); + i != lRequiresRegexp.end(); i++ ) + { + RegExp *re = (*i).first; + for( std::list::iterator j = lInput.begin(); + j != lInput.end(); j++ ) + { + if( re->execute( (*j).c_str() ) ) + { + varmap *revars = regexVars( re ); + requiresNormal( + (*j).c_str(), + varRepl( + (*i).second.c_str(), + "", + revars + ).c_str() + ); + delete revars; + } + } + } + + for( regreqlist::iterator i = lRequiresRegexpCommand.begin(); + i != lRequiresRegexpCommand.end(); i++ ) + { + RegExp *re = (*i).first; + for( std::list::iterator j = lInput.begin(); + j != lInput.end(); j++ ) + { + if( re->execute( (*j).c_str() ) ) + { + varmap *revars = regexVars( re ); + FILE *fcmd = popen( + varRepl( (*i).second.c_str(), "", revars ).c_str(), + "r" ); + std::string rhs; + bool bHeader = true; + for(;;) + { + if( feof( fcmd ) ) + break; + int cc = fgetc( fcmd ); + if( cc == EOF ) + break; + unsigned char c = cc; + if( bHeader ) + { + if( c == ':' ) + bHeader = false; + } + else + { + if( c == ' ' || c == '\t' ) + { + if( rhs != "" ) + { + requiresNormal( + (*j).c_str(), + rhs.c_str() + ); + rhs = ""; + } + } + else + { + if( c == '\\' ) + c = fgetc( fcmd ); + if( c != '\n' ) + rhs += c; + } + } + } + if( rhs != "" ) + { + requiresNormal( + (*j).c_str(), + rhs.c_str() + ); + rhs = ""; + } + fclose( fcmd ); + delete revars; + } + } + } +} + +std::map *Builder::regexVars( RegExp *re ) +{ + varmap *map = new varmap; + + int jmax = re->getNumSubStrings(); + for( int j = 0; j < jmax; j++ ) + { + char buf[8]; + sprintf( buf, "re:%d", j ); + (*map)[buf] = re->getSubString( j ); + } + + return map; +} + void Builder::requires( const char *sBase, const char *sReq ) +{ + if( bReqRegexp ) + { + requiresRegexp( sBase, sReq ); + } + else + { + requiresNormal( sBase, sReq ); + } +} + +void Builder::requiresNormal( const char *sBase, const char *sReq ) { std::list *pList = NULL; if( mRequires.find(sBase) == mRequires.end() ) @@ -201,6 +340,26 @@ void Builder::requires( const char *sBase, const char *sReq ) pList->push_back( sReq ); } +void Builder::requiresRegexp( const char *sBase, const char *sReq ) +{ + lRequiresRegexp.push_back( + std::pair( + new RegExp( sBase ), + sReq + ) + ); +} + +void Builder::requiresFromCommand( const char *sBase, const char *sCmd ) +{ + lRequiresRegexpCommand.push_back( + std::pair( + new RegExp( sBase ), + sCmd + ) + ); +} + void Builder::setContext( const char *sCont ) { sContext = sCont; @@ -211,3 +370,79 @@ void Builder::setContext() setContext(""); } +bool Builder::hasVar( varmap *pMap, std::string &var ) +{ + if( pMap == NULL ) + return false; + if( pMap->find( var ) == pMap->end() ) + return false; + return true; +} + +std::string Builder::varRepl( const char *sSrc, const char *cont, varmap *mExtra ) +{ + varmap *mCont = NULL; + if( cont[0] != '\0' ) + { + if( mContVar.find( cont ) != mContVar.end() ) + mCont = &mContVar[cont]; + } + + std::string out; + std::string var; + bool bVar = false; + + for( const char *s = sSrc; *s; s++ ) + { + if( *s == '{' ) + { + bVar = true; + continue; + } + else if( *s == '}' && bVar ) + { + if( hasVar( &mVar, var ) ) + { + out += mVar[var]; + } + else if( hasVar( mCont, var ) ) + { + out += (*mCont)[var]; + } + else if( hasVar( mExtra, var ) ) + { + out += (*mExtra)[var]; + } + var = ""; + bVar = false; + continue; + } + + if( bVar == true ) + { + var += *s; + } + else + { + out += *s; + } + } + + return out; +} + +Rule *Builder::getRule( const char *sName ) +{ + if( mRule.find( sName ) != mRule.end() ) + return mRule[sName]; + + return NULL; +} + +std::list Builder::findRuleChain( Rule *pRule ) +{ + std::list ret; + + return ret; +} + diff --git a/src/builder.h b/src/builder.h index 89810c0..d7c0891 100644 --- a/src/builder.h +++ b/src/builder.h @@ -7,6 +7,7 @@ #include "build.tab.h" #include "exceptionbase.h" #include "staticstring.h" +#include "regexp.h" subExceptionDecl( BuildException ) @@ -34,6 +35,8 @@ public: virtual ~Builder(); void load( const char *sFN ); + void build( const char *sAct=NULL ); + void execute( Action *pAct ); //void error( const yy::location &l, const std::string &m ); //void error( const std::string &m ); @@ -46,7 +49,19 @@ public: void add( Target *pTarg ); void varSet( const char *sName, const char *sValue ); void varAddSet( const char *sName, const char *sValue ); + Rule *getRule( const char *sName ); + std::list findRuleChain( Rule *pRule ); + void processRequires( std::list &lInput ); void requires( const char *sBase, const char *sReq ); + void requiresFromCommand( const char *sBase, const char *sReq ); + void requiresRegexp( bool on ) + { + bReqRegexp = on; + } + bool isRequiresRegexp() + { + return bReqRegexp; + } void setContext( const char *sCont ); void setContext(); @@ -77,10 +92,26 @@ public: return sTmp; } + Target *getTarget( const char *sName ) + { + if( mTarget.find( sName ) == mTarget.end() ) + throw BuildException("Target %s not found.", sName ); + + return mTarget[sName]; + } + private: + typedef std::map varmap; + + void requiresNormal( const char *sBase, const char *sReq ); + void requiresRegexp( const char *sBase, const char *sReq ); void checkVar( const char *cont, const char *sName ); void scanBegin(); void scanEnd(); + varmap *regexVars( RegExp *re ); + + bool hasVar( varmap *pMap, std::string &var ); + std::string varRepl( const char *sSrc, const char *cont, varmap *mExtra ); Action *pDefaultAction; Action *pLastAddedAction; @@ -92,14 +123,20 @@ private: Target *pLastAddedTarget; std::map mTarget; - typedef std::map varmap; varmap mVar; + std::map *> mRequires; + typedef std::list > regreqlist; + regreqlist lRequiresRegexp; + regreqlist lRequiresRegexpCommand; + std::map mContVar; StaticString sContext; StaticString sTmp; + + bool bReqRegexp; }; #endif diff --git a/src/command.cpp b/src/command.cpp index 72f9a4c..ea5ade3 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -1,4 +1,6 @@ #include "command.h" +#include "builder.h" +#include "target.h" Command::Command( CmdType cmd, const char *sTarget ) : nType( cmd ), @@ -16,3 +18,17 @@ void Command::debug() printf(" command: %s %s\n", cmdt[ nType ], sTarget.getString() ); } +void Command::execute( Builder &bld ) +{ + switch( nType ) + { + case cmdCheck: + bld.getTarget( sTarget )->check( bld ); + break; + + case cmdClean: + bld.getTarget( sTarget )->clean( bld ); + break; + } +} + diff --git a/src/command.h b/src/command.h index aa00eae..495c749 100644 --- a/src/command.h +++ b/src/command.h @@ -4,6 +4,8 @@ #include #include "staticstring.h" +class Builder; + class Command { public: @@ -29,6 +31,8 @@ public: void debug(); + void execute( class Builder &bld ); + private: CmdType nType; StaticString sTarget; diff --git a/src/filetarget.cpp b/src/filetarget.cpp index b9d7946..65f9d70 100644 --- a/src/filetarget.cpp +++ b/src/filetarget.cpp @@ -1,4 +1,9 @@ +#include +#include + +#include "rule.h" #include "filetarget.h" +#include "builder.h" // for BuildException FileTarget::FileTarget( const char *sName ) : Target( sName ) @@ -15,3 +20,63 @@ void FileTarget::debug() printf(" type: FileTarget\n"); } +char *gnu_getcwd() +{ + size_t size = 1024; + + while (1) + { + char *buffer = new char[size]; + if (getcwd (buffer, size) == buffer) + return buffer; + delete[] buffer; + if (errno != ERANGE) + return 0; + size *= 2; + } +} + +void FileTarget::addInputDir( const char *sDir ) +{ + DIR *dir = opendir( sDir ); + if( dir == NULL ) + { + throw BuildException( strerror( errno ) ); + } + + char *cwd = gnu_getcwd(); + std::string base( cwd ); + base += "/"; + base += sDir; + delete[] cwd; + + struct dirent *de; + + while( (de = readdir( dir )) ) + { + if( de->d_name[0] == '.' || de->d_name[0] == '\0' ) + continue; + + std::string s( base ); + s += "/"; + s += de->d_name; + addInput( s.c_str() ); + } + + closedir( dir ); +} + +void FileTarget::check( Builder &bld ) +{ + Rule *pRule = bld.getRule( sRule ); + + std::list tmp = pRule->execute( bld, lInput ); + lOutput.insert( lOutput.end(), tmp.begin(), tmp.end() ); + + bld.processRequires( lInput ); +} + +void FileTarget::clean( Builder &bld ) +{ +} + diff --git a/src/filetarget.h b/src/filetarget.h index cf4b3d6..11dc180 100644 --- a/src/filetarget.h +++ b/src/filetarget.h @@ -11,6 +11,11 @@ public: virtual ~FileTarget(); virtual void debug(); + + void addInputDir( const char *sDir ); + + virtual void check( class Builder &bld ); + virtual void clean( class Builder &bld ); private: diff --git a/src/main.cpp b/src/main.cpp index 995009d..2e13b16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,10 +4,11 @@ int main() { Builder bld; - bld.load("congo"); + bld.load("build.conf"); - printf("\n\n----------\nDebug dump\n----------\n"); + bld.build(); + printf("\n\n----------\nDebug dump\n----------\n"); bld.debug(); } diff --git a/src/regexp.cpp b/src/regexp.cpp new file mode 100644 index 0000000..ff2d09a --- /dev/null +++ b/src/regexp.cpp @@ -0,0 +1,71 @@ +#include "regexp.h" +#include "builder.h" // For BuildException +#include "staticstring.h" + +RegExp::RegExp() : + bCompiled( false ), + aSubStr( NULL ) +{ +} + +RegExp::RegExp( const char *sSrc ) : + bCompiled( false ), + aSubStr( NULL ) +{ + compile( sSrc ); +} + +RegExp::~RegExp() +{ + regfree( &re ); + delete[] aSubStr; +} + +void RegExp::compile( const char *sSrc ) +{ + if( bCompiled ) + throw BuildException("Already compiled."); + + int nErr = regcomp( &re, sSrc, REG_EXTENDED|REG_NEWLINE ); + if( nErr ) + { + size_t length = regerror( nErr, &re, NULL, 0 ); + char *buffer = new char[length]; + (void) regerror( nErr, &re, buffer, length ); + StaticString s( buffer ); + delete[] buffer; + throw BuildException( s.getString() ); + } + bCompiled = true; + this->sSrc = sSrc; + + nSubStr = re.re_nsub+1; + aSubStr = new regmatch_t[nSubStr]; +} + +int RegExp::getNumSubStrings() +{ + return nSubStr; +} + +bool RegExp::execute( const char *sSrc ) +{ + sTest = sSrc; + if( regexec( &re, sSrc, nSubStr, aSubStr, 0 ) ) + return false; + return true; +} + +std::pair RegExp::getSubStringRange( int nIndex ) +{ + return std::pair( aSubStr[nIndex].rm_so, aSubStr[nIndex].rm_eo ); +} + +std::string RegExp::getSubString( int nIndex ) +{ + return std::string( + sTest.getString()+aSubStr[nIndex].rm_so, + aSubStr[nIndex].rm_eo - aSubStr[nIndex].rm_so + ); +} + diff --git a/src/regexp.h b/src/regexp.h new file mode 100644 index 0000000..96f3747 --- /dev/null +++ b/src/regexp.h @@ -0,0 +1,36 @@ +#ifndef REG_EXP_H +#define REG_EXP_H + +#include +#include +#include +#include +#include "staticstring.h" + +class RegExp +{ +public: + RegExp(); + RegExp( const char *sSrc ); + virtual ~RegExp(); + + void compile( const char *sSrc ); + int getNumSubStrings(); + bool execute( const char *sSrc ); + std::pair getSubStringRange( int nIndex ); + std::string getSubString( int nIndex ); + const char *getSource() + { + return sSrc; + } + +private: + StaticString sSrc; + StaticString sTest; + regex_t re; + bool bCompiled; + int nSubStr; + regmatch_t *aSubStr; +}; + +#endif diff --git a/src/rule.cpp b/src/rule.cpp index a7ebf9b..a240855 100644 --- a/src/rule.cpp +++ b/src/rule.cpp @@ -2,8 +2,7 @@ #include "builder.h" // for BuildException Rule::Rule( const char *sName ) : - sName( sName ), - sProduces("{target}") + sName( sName ) { } @@ -14,11 +13,23 @@ Rule::~Rule() void Rule::debug() { - printf(" Rule %s produces %s:\n", - sName.getString(), - sProduces.getString() + printf(" Rule %s:\n", + sName.getString() ); - printf(" Matches "); + printf(" Produces: "); + if( lProduces.empty() ) + printf("{target}"); + else + { + for( std::list::iterator i = lProduces.begin(); + i != lProduces.end(); i++ ) + { + if( i != lProduces.begin() ) + printf(", "); + printf("%s", (*i).c_str() ); + } + } + printf("\n Matches "); if( mHow == matchOne ) printf("one "); else if( mHow == matchAll ) @@ -31,9 +42,9 @@ void Rule::debug() printf("\"%s\"\n", sPerfCmd.getString() ); } -void Rule::setProduces( const char *sP ) +void Rule::addProduces( const char *sP ) { - sProduces = sP; + lProduces.push_back( sP ); } void Rule::setMatches( Matches how, const char *sW ) @@ -59,3 +70,13 @@ void Rule::setPerforms( Perform pwhat, const char *sperfcmd ) sPerfCmd = sperfcmd; } +std::list Rule::execute( Builder &bld, std::list lInput ) +{ + std::list lRule = bld.findRuleChain( this ); + + std::list ret; + + return ret; + +} + diff --git a/src/rule.h b/src/rule.h index 64cdc9d..8371649 100644 --- a/src/rule.h +++ b/src/rule.h @@ -1,6 +1,8 @@ #ifndef RULE_H #define RULE_H +#include +#include #include #include #include "staticstring.h" @@ -30,13 +32,15 @@ public: void debug(); - void setProduces( const char *sProduces ); + void addProduces( const char *sProduces ); void setMatches( Matches how, const char *sWhat ); void setPerforms( Perform pwhat, const char *sPerfCmd ); + std::list execute( class Builder &bld, std::list lInput ); + private: StaticString sName; - StaticString sProduces; + std::list lProduces; Matches mHow; StaticString sWhat; diff --git a/src/target.cpp b/src/target.cpp index b0967bf..00d16b4 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -20,5 +20,21 @@ void Target::debug() sName.getString(), sRule.getString() ); + printf(" Input list:\n"); + for( std::list::iterator i = lInput.begin(); + i != lInput.end(); i++ ) + { + printf(" %s\n", (*i).c_str() ); + } +} + +void Target::addInput( const char *sInput ) +{ + lInput.push_back( sInput ); +} + +void Target::addOutput( const char *sOutput ) +{ + lOutput.push_back( sOutput ); } diff --git a/src/target.h b/src/target.h index 667c467..59c5d7e 100644 --- a/src/target.h +++ b/src/target.h @@ -1,6 +1,8 @@ #ifndef TARGET_H #define TARGET_H +#include +#include #include #include "staticstring.h" @@ -19,10 +21,19 @@ public: virtual void debug(); -private: + void addInput( const char *sInput ); + void addOutput( const char *sOutput ); + + virtual void check( class Builder &bld ) = 0; + virtual void clean( class Builder &bld ) = 0; + +protected: StaticString sName; StaticString sRule; + std::list lInput; + std::list lOutput; + }; #endif -- cgit v1.2.3