From 71c3c523aacb0f6986d50f4a7a2e5d604728a4c4 Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 6 Aug 2006 19:42:22 +0000 Subject: A load of updates, most of these made me realize that I probably could do this whole thing a lot better. We'll see how that works out later, once I figure out how to do it better. --- src/action.cpp | 15 +++ src/action.h | 2 + src/build.l | 24 ++++- src/build.y | 77 ++++++++++----- src/builder.cpp | 263 +++++++++++++++++++++++++++++++++++++++++++++++++--- src/builder.h | 28 ++++++ src/main.cpp | 14 ++- src/regexp.cpp | 13 ++- src/viewerplain.cpp | 5 + src/viewerplain.h | 1 + 10 files changed, 399 insertions(+), 43 deletions(-) diff --git a/src/action.cpp b/src/action.cpp index 8907816..51868eb 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -23,6 +23,11 @@ void Action::add( Command *pCmd ) lCommand.push_back( pCmd ); } +void Action::add( int nType, const char *sCmd ) +{ + lRegExCommand.push_back( std::pair( nType, sCmd ) ); +} + void Action::debug() { if( bDefault ) @@ -39,6 +44,16 @@ void Action::debug() void Action::execute( Builder &bld ) { + for( std::list >::iterator i = + lRegExCommand.begin(); i != lRegExCommand.end(); i++ ) + { + std::list lTmp = bld.findTargets( (*i).second.c_str() ); + for( std::list::iterator j = lTmp.begin(); + j != lTmp.end(); j++ ) + { + add( new Command( (Command::CmdType)(*i).first, (*j).c_str() ) ); + } + } for( std::list::iterator i = lCommand.begin(); i != lCommand.end(); i++ ) { diff --git a/src/action.h b/src/action.h index ea92efa..a5555a3 100644 --- a/src/action.h +++ b/src/action.h @@ -15,6 +15,7 @@ public: virtual ~Action(); void add( Command *pCmd ); + void add( int nType, const char *sCmd ); const char *getName() { @@ -38,6 +39,7 @@ private: bool bDefault; StaticString sName; std::list lCommand; + std::list > lRegExCommand; }; #endif diff --git a/src/build.l b/src/build.l index 540af46..723991b 100644 --- a/src/build.l +++ b/src/build.l @@ -14,7 +14,7 @@ std::string strbuf; %option noyywrap nounput batch debug %{ -//# define YY_USER_ACTION yylloc->columns (yyleng); +# define YY_USER_ACTION yylloc->last_column += yyleng; %} %% @@ -34,6 +34,7 @@ std::string strbuf; "for" return TOK_FOR; "set" return TOK_SET; "matches" return TOK_MATCHES; +"matching" return TOK_MATCHING; "all" return TOK_ALL; "one" return TOK_ONE; "perform" return TOK_PERFORM; @@ -41,10 +42,25 @@ std::string strbuf; "command" return TOK_COMMAND; "check" return TOK_CHECK; "clean" return TOK_CLEAN; +"directories" return TOK_DIRECTORIES; +"targets" return TOK_TARGETS; -"..."\n /* elipsis line continuation */ -\n+ return TOK_EOL; -[ \t\r]* /* whitespace */ +"..."\n { + yylloc->last_line += yyleng; + yylloc->first_line = yylloc->last_line; + yylloc->first_column = yylloc->last_column = 0; +} +\n+ { + yylloc->last_line += yyleng; + yylloc->first_line = yylloc->last_line; + yylloc->first_column = yylloc->last_column = 0; + return TOK_EOL; +} + +[ \t\r]* { + yylloc->first_line = yylloc->last_line; + yylloc->first_column = yylloc->last_column+1; +} "/" { BEGIN( regexp ); diff --git a/src/build.y b/src/build.y index bf565fb..d8cba53 100644 --- a/src/build.y +++ b/src/build.y @@ -15,10 +15,6 @@ void yyerror( YYLTYPE *locp, Builder &bld, char const *msg ); %pure-parser %locations -%initial-action -{ - //@$.begin.filename = @$.end.filename = &bld.file; -} %debug %error-verbose @@ -43,6 +39,7 @@ void yyerror( YYLTYPE *locp, Builder &bld, char const *msg ); %token TOK_FOR "for" %token TOK_SET "set" %token TOK_MATCHES "matches" +%token TOK_MATCHING "matching" %token TOK_ALL "all" %token TOK_ONE "one" %token TOK_PERFORM "perform" @@ -50,6 +47,8 @@ void yyerror( YYLTYPE *locp, Builder &bld, char const *msg ); %token TOK_COMMAND "command" %token TOK_CHECK "check" %token TOK_CLEAN "clean" +%token TOK_DIRECTORIES "directories" +%token TOK_TARGETS "targets" %token TOK_EOL "end of line" %token ',' ':' '=' @@ -75,7 +74,15 @@ line: TOK_DEFAULT TOK_ACTION ':' bld.add( new Action( $1 ) ); } actionlst - | TOK_CREATE createwhat TOK_FROM createfrom TOK_USING createusing + | TOK_FOR fortypes TOK_MATCHING REGEXP + { + bld.setFilter( $4 ); + } + augments + { + bld.endList(); + } + listcmds | STRING TOK_REQUIRES { bld.setTmp( $1 ); @@ -91,15 +98,37 @@ line: TOK_DEFAULT TOK_ACTION ':' | listcmds | TOK_FOR STRING { - bld.setContext( $2 ); + bld.startList( STRING ); + bld.addListItem( $2 ); } listcmds { - bld.setContext(); + } | rule ; +fortypes: TOK_DIRECTORIES + { + bld.startList( TOK_DIRECTORIES ); + } + | TOK_TARGETS + { + bld.startList( TOK_TARGETS ); + } + | TOK_FILES + { + bld.startList( TOK_FILES ); + } + ; + +augments: + | TOK_IN STRING + { + bld.augmentList( $2 ); + } + ; + reqcompletion: reqlst | TOK_FROM TOK_COMMAND STRING { @@ -118,15 +147,23 @@ reqlst: STRING ; listcmds: TOK_SET setexpr + | TOK_CREATE createwhat TOK_FROM createfrom TOK_USING createusing + { + bld.endTarget(); + } ; createwhat: TOK_FILE STRING { - bld.add( new FileTarget( $2 ) ); + bld.addTarget( TOK_FILE, $2 ); } ; -createfrom: TOK_FILES TOK_IN createfromdirlst +createfrom: TOK_FILES TOK_IN + { + bld.setTargetInputType( TOK_FILES ); + } + createfromdirlst ; createfromdirlst: createfromdir @@ -135,23 +172,13 @@ createfromdirlst: createfromdir 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() ); - } + bld.addTargetInput( $1 ); } ; createusing: TOK_RULE STRING { - bld.lastTarget()->setRule( $2 ); + bld.setTargetRule( $2 ); } ; @@ -163,10 +190,18 @@ action: TOK_CHECK STRING { bld.add( new Command( Command::cmdCheck, $2 ) ); } + | TOK_CHECK REGEXP + { + bld.addRegexCommand( Command::cmdCheck, $2 ); + } | TOK_CLEAN STRING { bld.add( new Command( Command::cmdClean, $2 ) ); } + | TOK_CLEAN REGEXP + { + bld.addRegexCommand( Command::cmdClean, $2 ); + } ; setexpr: STRING '=' STRING diff --git a/src/builder.cpp b/src/builder.cpp index a21bc99..8fd72bb 100644 --- a/src/builder.cpp +++ b/src/builder.cpp @@ -1,9 +1,13 @@ #include +#include +#include +#include #include "builder.h" #include "action.h" #include "command.h" #include "target.h" +#include "filetarget.h" #include "build.tab.h" #include "rule.h" #include "viewer.h" @@ -17,7 +21,8 @@ Builder::Builder( Viewer &rView ) : pLastAddedAction( NULL ), sTmp(""), sContext(""), - rView( rView ) + rView( rView ), + bUsingList( false ) { } @@ -110,6 +115,14 @@ void Builder::add( Command *pCmd ) } } +void Builder::addRegexCommand( int nType, const char *sReg ) +{ + if( pLastAddedAction ) + { + pLastAddedAction->add( nType, sReg ); + } +} + void Builder::add( Rule *pRule ) { pLastAddedRule = pRule; @@ -122,6 +135,87 @@ void Builder::add( Target *pTarg ) mTarget[pTarg->getName()] = pTarg; } +void Builder::addTarget( int tokType, const char *sName ) +{ + nTargetType = tokType; + sTargetName = sName; +} + +void Builder::setTargetInputType( int tokType ) +{ + nTargetInputType = tokType; +} + +void Builder::addTargetInput( const char *sInput ) +{ + lsTargetInput.push_back( sInput ); +} + +void Builder::setTargetRule( const char *sRule ) +{ + sTargetRule = sRule; +} + +void Builder::endTarget() +{ + if( bUsingList == false ) + { + switch( nTargetType ) + { + case TOK_FILE: + add( new FileTarget( sTargetName.c_str() ) ); + switch( nTargetInputType ) + { + case TOK_FILES: + for( std::list::iterator + i = lsTargetInput.begin(); + i != lsTargetInput.end(); i++ ) + { + ((FileTarget *)lastTarget())->addInputDir( + (*i).c_str() + ); + } + break; + } + lastTarget()->setRule( sTargetRule.c_str() ); + break; + } + } + else + { + switch( nTargetType ) + { + case TOK_FILE: + for( std::list > >::iterator j = lTok.begin(); j != lTok.end(); j++ ) + { + std::string sName = varRepl( sTargetName.c_str(), "", &(*j).second ); + add( new FileTarget( sName.c_str() ) ); + switch( nTargetInputType ) + { + case TOK_FILES: + for( std::list::iterator + i = lsTargetInput.begin(); + i != lsTargetInput.end(); i++ ) + { + std::string sInput = varRepl( + (*i).c_str(), "", + &(*j).second + ); + ((FileTarget *)lastTarget())->addInputDir( + sInput.c_str() + ); + } + break; + } + lastTarget()->setRule( sTargetRule.c_str() ); + } + break; + } + } + + clearList(); +} + void Builder::debug() { printf("Actions:\n"); @@ -214,17 +308,31 @@ void Builder::checkVar( const char *cont, const char *sName ) void Builder::varSet( const char *sName, const char *sValue ) { - checkVar( sContext, sName ); + if( bUsingList ) + { + for( std::list > >::iterator i = lTok.begin(); i != lTok.end(); i++ ) + { + checkVar( (*i).first.c_str(), sName ); - std::string newVal = varRepl( sValue, sContext, NULL ); + std::string newVal = varRepl( sValue, (*i).first.c_str(), &(*i).second ); - if( sContext[0] == '\0' ) - { - mVar[sName] = newVal; + mContVar[(*i).first.c_str()][sName] = newVal; + } } else { - mContVar[sContext.getString()][sName] = newVal; + checkVar( sContext, sName ); + + std::string newVal = varRepl( sValue, sContext, NULL ); + + if( sContext[0] == '\0' ) + { + mVar[sName] = newVal; + } + else + { + mContVar[sContext.getString()][sName] = newVal; + } } } @@ -383,6 +491,17 @@ std::map *Builder::regexVars( RegExp *re ) return map; } +void Builder::regexVars( RegExp *re, varmap &map ) +{ + int jmax = re->getNumSubStrings(); + for( int j = 0; j < jmax; j++ ) + { + char buf[8]; + sprintf( buf, "re:%d", j ); + map[buf] = re->getSubString( j ); + } +} + void Builder::requires( const char *sBase, const char *sReq ) { if( bReqRegexp ) @@ -507,6 +626,7 @@ Rule *Builder::getRule( const char *sName ) if( mRule.find( sName ) != mRule.end() ) return mRule[sName]; + throw BuildException("No rule named %s registered.", sName ); return NULL; } @@ -554,11 +674,128 @@ void Builder::error( const std::string &err ) void Builder::error( YYLTYPE *locp, const std::string &err ) { - fprintf( stderr, "%s:%d-%d:%d-%d: %s\n", - file.c_str(), - locp->first_line, locp->last_line, - locp->first_column, locp->last_column, - err.c_str() - ); + std::stringstream s; + s << file << ":" << locp->first_line << "." << locp->first_column; + if( locp->first_line != locp->last_line ) + s << "-" << locp->last_line << "." << locp->last_column; + else if( locp->first_column != locp->last_column ) + s << "-" << locp->last_column; + s << ": " << err; + throw BuildException( s.str().c_str() ); +} + +void Builder::startList( int tokType ) +{ + bUsingList = true; + lTok.clear(); + bTokFiltered = false; + nTokType = tokType; +} + +void Builder::setFilter( const char *sRegExp ) +{ + rTok.compile( sRegExp ); + bTokFiltered = true; +} + +void Builder::augmentList( const char *sFrom ) +{ + switch( nTokType ) + { + case TOK_DIRECTORIES: + { + DIR *dir = opendir( sFrom ); + if( dir == NULL ) + { + printf("dir: %s\n", sFrom ); + throw BuildException( strerror( errno ) ); + } + + std::string base; + base += sFrom; + base += "/"; + + struct dirent *de; + + while( (de = readdir( dir )) ) + { + if( de->d_type != DT_DIR ) + continue; + if( de->d_name[0] == '.' || de->d_name[0] == '\0' ) + continue; + + std::string s( base ); + s += de->d_name; + addListItem( s.c_str() ); + } + + closedir( dir ); + } + break; + + default: + break; + } +} + +void Builder::endList() +{ + switch( nTokType ) + { + case TOK_TARGETS: + for( std::map::iterator i = + mTarget.begin(); i != mTarget.end(); i++ ) + { + addListItem( (*i).first ); + } + break; + } +} + +void Builder::addListItem( const char *sItem ) +{ + std::map mVars; + mVars["match"] = sItem; + if( bTokFiltered ) + { + if( rTok.execute( sItem ) ) + { + regexVars( &rTok, mVars ); + } + else + { + return; + } + } + lTok.push_back( + std::pair >( + sItem, mVars + ) + ); +} + +void Builder::clearList() +{ + lTok.clear(); + lsTargetInput.clear(); + bUsingList = false; +} + +std::list Builder::findTargets( const char *sRegex ) +{ + RegExp r( sRegex ); + + std::list lTmp; + + for( std::map::iterator i = mTarget.begin(); + i != mTarget.end(); i++ ) + { + if( r.execute( (*i).first ) ) + { + lTmp.push_back( (*i).first ); + } + } + + return lTmp; } diff --git a/src/builder.h b/src/builder.h index 56a7b07..195296a 100644 --- a/src/builder.h +++ b/src/builder.h @@ -51,9 +51,23 @@ public: return rView; } + void startList( int tokType ); + void setFilter( const char *sRegExp ); + void augmentList( const char *sFrom ); + void addListItem( const char *sItem ); + void clearList(); + void endList(); + + void addTarget( int tokType, const char *sName ); + void setTargetInputType( int tokType ); + void addTargetInput( const char *sInput ); + void setTargetRule( const char *sRule ); + void endTarget(); + void setCache( const std::string &sFile ); void add( Action *pAct ); void add( Command *pCmd ); + void addRegexCommand( int nType, const char *sReg ); void add( Rule *pRule ); void add( Target *pTarg ); void varSet( const char *sName, const char *sValue ); @@ -64,6 +78,7 @@ public: void requires( const char *sBase, const char *sReq ); void requiresFromCommand( const char *sBase, const char *sReq ); void genRequiresFor( const char *sName, time_t tNewTime ); + std::list findTargets( const char *sRegex ); void requiresRegexp( bool on ) { bReqRegexp = on; @@ -119,6 +134,7 @@ public: typedef std::map varmap; varmap *regexVars( RegExp *re ); + void regexVars( RegExp *re, varmap &map ); std::string varRepl( const char *sSrc, const char *cont, varmap *mExtra ); private: @@ -159,6 +175,18 @@ private: StaticString sCacheFile; class Cache cRequires; + + std::list > > lTok; + bool bTokFiltered; + int nTokType; + RegExp rTok; + + int nTargetType; + int nTargetInputType; + std::string sTargetName; + std::list lsTargetInput; + std::string sTargetRule; + bool bUsingList; }; void cleanList( std::list &lst ); diff --git a/src/main.cpp b/src/main.cpp index 009aac5..3ea4411 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,8 @@ class Param : public ParamProc public: Param() : sFile("build.conf"), - sCache("build.cache") + sCache("build.cache"), + bDebug( false ) { addHelpBanner("Build r?\n\n"); addParam("file", 'f', &sFile, @@ -64,7 +65,16 @@ int main( int argc, char *argv[] ) Builder bld( *prm.pViewer ); bld.setCache( prm.sCache ); - bld.load( prm.sFile.c_str() ); + try + { + bld.load( prm.sFile.c_str() ); + } + catch( BuildException &e ) + { + fputs( e.what(), stderr ); + fputs( "\n", stderr ); + return 1; + } if( prm.bDebug ) { diff --git a/src/regexp.cpp b/src/regexp.cpp index ff2d09a..e5a3535 100644 --- a/src/regexp.cpp +++ b/src/regexp.cpp @@ -17,14 +17,21 @@ RegExp::RegExp( const char *sSrc ) : RegExp::~RegExp() { - regfree( &re ); - delete[] aSubStr; + if( bCompiled ) + { + regfree( &re ); + delete[] aSubStr; + } } void RegExp::compile( const char *sSrc ) { if( bCompiled ) - throw BuildException("Already compiled."); + { + regfree( &re ); + delete[] aSubStr; + bCompiled = false; + } int nErr = regcomp( &re, sSrc, REG_EXTENDED|REG_NEWLINE ); if( nErr ) diff --git a/src/viewerplain.cpp b/src/viewerplain.cpp index 5d95d19..52b798b 100644 --- a/src/viewerplain.cpp +++ b/src/viewerplain.cpp @@ -54,3 +54,8 @@ void ViewerPlain::beginExecute() printf(" build: %s\n", sTarget.getString() ); } +void ViewerPlain::executeCmd( const char *sCmd ) +{ + //printf("--> %s\n", sCmd ); +} + diff --git a/src/viewerplain.h b/src/viewerplain.h index 1ec2b64..4c88a0f 100644 --- a/src/viewerplain.h +++ b/src/viewerplain.h @@ -19,6 +19,7 @@ public: virtual void beginExtraRequiresCheck( const char *sCommand ); void printHead(); virtual void beginExecute(); + virtual void executeCmd( const char *sCmd ); private: class StaticString sAction; -- cgit v1.2.3