diff options
Diffstat (limited to '')
72 files changed, 7199 insertions, 0 deletions
diff --git a/src/action.cpp b/src/action.cpp new file mode 100644 index 0000000..23c24cd --- /dev/null +++ b/src/action.cpp | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | #include "action.h" | ||
| 2 | #include "ast.h" | ||
| 3 | #include "astbranch.h" | ||
| 4 | #include "astleaf.h" | ||
| 5 | #include "runner.h" | ||
| 6 | #include "variable.h" | ||
| 7 | |||
| 8 | Action::Action( const class AstBranch *pRoot ) : | ||
| 9 | pRoot( pRoot ), | ||
| 10 | pAst( NULL ) | ||
| 11 | { | ||
| 12 | sName = dynamic_cast<AstLeaf *>( | ||
| 13 | *(*pRoot->getBranchBegin()).begin() | ||
| 14 | )->getStrValue(); | ||
| 15 | } | ||
| 16 | |||
| 17 | Action::~Action() | ||
| 18 | { | ||
| 19 | delete pAst; | ||
| 20 | pAst = NULL; | ||
| 21 | } | ||
| 22 | |||
| 23 | const Bu::FString &Action::getName() const | ||
| 24 | { | ||
| 25 | return sName; | ||
| 26 | } | ||
| 27 | |||
| 28 | void Action::call( class Runner *pRunner ) | ||
| 29 | { | ||
| 30 | pRunner->run( (*(pRoot->getBranchBegin()+1)).begin() ); | ||
| 31 | } | ||
| 32 | |||
| 33 | Action *Action::genDefaultAll() | ||
| 34 | { | ||
| 35 | Ast *pAst = new Ast(); | ||
| 36 | pAst->addNode( AstNode::typeActionDef ); | ||
| 37 | pAst->openBranch(); | ||
| 38 | pAst->addNode( AstNode::typeString, "all" ); | ||
| 39 | pAst->openBranch(); | ||
| 40 | pAst->addNode( AstNode::typeProcessTarget ); | ||
| 41 | pAst->openBranch(); | ||
| 42 | pAst->addNode( AstNode::typeString, "build" ); | ||
| 43 | pAst->openBranch(); | ||
| 44 | pAst->addNode( AstNode::typeFunction ); | ||
| 45 | pAst->openBranch(); | ||
| 46 | pAst->addNode( AstNode::typeString, "targets" ); | ||
| 47 | pAst->closeNode(); | ||
| 48 | pAst->closeNode(); | ||
| 49 | pAst->closeNode(); | ||
| 50 | Action *pRet = new Action( | ||
| 51 | dynamic_cast<const AstBranch *>( *pAst->getNodeBegin() ) | ||
| 52 | ); | ||
| 53 | pRet->pAst = pAst; | ||
| 54 | |||
| 55 | return pRet; | ||
| 56 | } | ||
| 57 | |||
| 58 | Action *Action::genDefaultClean() | ||
| 59 | { | ||
| 60 | Ast *pAst = new Ast(); | ||
| 61 | pAst->addNode( AstNode::typeActionDef ); | ||
| 62 | pAst->openBranch(); | ||
| 63 | pAst->addNode( AstNode::typeString, "clean" ); | ||
| 64 | pAst->openBranch(); | ||
| 65 | pAst->addNode( AstNode::typeProcessTarget ); | ||
| 66 | pAst->openBranch(); | ||
| 67 | pAst->addNode( AstNode::typeString, "clean" ); | ||
| 68 | pAst->openBranch(); | ||
| 69 | pAst->addNode( AstNode::typeFunction ); | ||
| 70 | pAst->openBranch(); | ||
| 71 | pAst->addNode( AstNode::typeString, "targets" ); | ||
| 72 | pAst->closeNode(); | ||
| 73 | pAst->closeNode(); | ||
| 74 | pAst->closeNode(); | ||
| 75 | Action *pRet = new Action( | ||
| 76 | dynamic_cast<const AstBranch *>( *pAst->getNodeBegin() ) | ||
| 77 | ); | ||
| 78 | pRet->pAst = pAst; | ||
| 79 | |||
| 80 | return pRet; | ||
| 81 | } | ||
| 82 | |||
| 83 | Action *Action::genDefaultDefault() | ||
| 84 | { | ||
| 85 | Ast *pAst = new Ast(); | ||
| 86 | pAst->addNode( AstNode::typeActionDef ); | ||
| 87 | pAst->openBranch(); | ||
| 88 | pAst->addNode( AstNode::typeString, "default" ); | ||
| 89 | pAst->openBranch(); | ||
| 90 | pAst->addNode( AstNode::typeProcessTarget ); | ||
| 91 | pAst->openBranch(); | ||
| 92 | pAst->addNode( AstNode::typeString, "build" ); | ||
| 93 | pAst->openBranch(); | ||
| 94 | pAst->addNode( AstNode::typeFunction ); | ||
| 95 | pAst->openBranch(); | ||
| 96 | pAst->addNode( AstNode::typeString, "targets" ); | ||
| 97 | pAst->closeNode(); | ||
| 98 | pAst->closeNode(); | ||
| 99 | pAst->closeNode(); | ||
| 100 | Action *pRet = new Action( | ||
| 101 | dynamic_cast<const AstBranch *>( *pAst->getNodeBegin() ) | ||
| 102 | ); | ||
| 103 | pRet->pAst = pAst; | ||
| 104 | |||
| 105 | return pRet; | ||
| 106 | } | ||
| 107 | |||
diff --git a/src/action.h b/src/action.h new file mode 100644 index 0000000..520f2f1 --- /dev/null +++ b/src/action.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | #ifndef ACTION_H | ||
| 2 | #define ACTION_H | ||
| 3 | |||
| 4 | #include <bu/fstring.h> | ||
| 5 | |||
| 6 | class Action | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | Action( const class AstBranch *pRoot ); | ||
| 10 | virtual ~Action(); | ||
| 11 | |||
| 12 | const Bu::FString &getName() const; | ||
| 13 | |||
| 14 | void call( class Runner *pRunner ); | ||
| 15 | |||
| 16 | static Action *genDefaultAll(); | ||
| 17 | static Action *genDefaultClean(); | ||
| 18 | static Action *genDefaultDefault(); | ||
| 19 | |||
| 20 | private: | ||
| 21 | Bu::FString sName; | ||
| 22 | const class AstBranch *pRoot; | ||
| 23 | class Ast *pAst; | ||
| 24 | }; | ||
| 25 | |||
| 26 | #endif | ||
diff --git a/src/ast.cpp b/src/ast.cpp new file mode 100644 index 0000000..03ed4b6 --- /dev/null +++ b/src/ast.cpp | |||
| @@ -0,0 +1,98 @@ | |||
| 1 | #include "ast.h" | ||
| 2 | |||
| 3 | #include "astleaf.h" | ||
| 4 | #include "astbranch.h" | ||
| 5 | |||
| 6 | Ast::Ast() | ||
| 7 | { | ||
| 8 | } | ||
| 9 | |||
| 10 | Ast::~Ast() | ||
| 11 | { | ||
| 12 | } | ||
| 13 | |||
| 14 | void Ast::addNode( AstNode::Type eType ) | ||
| 15 | { | ||
| 16 | switch( eType&AstNode::typeClassMask ) | ||
| 17 | { | ||
| 18 | case AstNode::typeBranch: | ||
| 19 | { | ||
| 20 | AstBranch *pNode = new AstBranch( eType ); | ||
| 21 | addNode( pNode ); | ||
| 22 | sBranch.push( pNode ); | ||
| 23 | } | ||
| 24 | break; | ||
| 25 | |||
| 26 | case AstNode::typeLeaf: | ||
| 27 | { | ||
| 28 | AstLeaf *pNode = new AstLeaf( eType ); | ||
| 29 | addNode( pNode ); | ||
| 30 | } | ||
| 31 | break; | ||
| 32 | |||
| 33 | default: | ||
| 34 | throw Bu::ExceptionBase("You got it wrong."); | ||
| 35 | break; | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | void Ast::addNode( AstNode::Type eType, int iVal ) | ||
| 40 | { | ||
| 41 | addNode( new AstLeaf( eType, iVal ) ); | ||
| 42 | } | ||
| 43 | |||
| 44 | void Ast::addNode( AstNode::Type eType, float fVal ) | ||
| 45 | { | ||
| 46 | addNode( new AstLeaf( eType, fVal ) ); | ||
| 47 | } | ||
| 48 | |||
| 49 | void Ast::addNode( AstNode::Type eType, bool bVal ) | ||
| 50 | { | ||
| 51 | addNode( new AstLeaf( eType, bVal ) ); | ||
| 52 | } | ||
| 53 | |||
| 54 | void Ast::addNode( AstNode::Type eType, const Bu::FString &sVal ) | ||
| 55 | { | ||
| 56 | addNode( new AstLeaf( eType, sVal ) ); | ||
| 57 | } | ||
| 58 | |||
| 59 | void Ast::addNode( AstNode::Type eType, const char *sVal ) | ||
| 60 | { | ||
| 61 | addNode( new AstLeaf( eType, sVal ) ); | ||
| 62 | } | ||
| 63 | |||
| 64 | void Ast::addNode( AstNode *pNode ) | ||
| 65 | { | ||
| 66 | if( sBranch.isEmpty() ) | ||
| 67 | lNode.append( pNode ); | ||
| 68 | else | ||
| 69 | sBranch.peek()->addNode( pNode ); | ||
| 70 | } | ||
| 71 | |||
| 72 | void Ast::openBranch() | ||
| 73 | { | ||
| 74 | sBranch.peek()->addBranch(); | ||
| 75 | } | ||
| 76 | |||
| 77 | void Ast::closeNode() | ||
| 78 | { | ||
| 79 | sBranch.pop(); | ||
| 80 | } | ||
| 81 | |||
| 82 | Ast::NodeList::const_iterator Ast::getNodeBegin() const | ||
| 83 | { | ||
| 84 | return lNode.begin(); | ||
| 85 | } | ||
| 86 | |||
| 87 | Bu::Formatter &operator<<( Bu::Formatter &f, const Ast &a ) | ||
| 88 | { | ||
| 89 | f << "Abstract Syntax Tree:"; | ||
| 90 | f.incIndent(); | ||
| 91 | f << f.nl; | ||
| 92 | for( Ast::NodeList::const_iterator i = a.getNodeBegin(); i; i++ ) | ||
| 93 | f << **i << f.nl; | ||
| 94 | f << f.nl; | ||
| 95 | f.decIndent(); | ||
| 96 | return f; | ||
| 97 | } | ||
| 98 | |||
diff --git a/src/ast.h b/src/ast.h new file mode 100644 index 0000000..a4f9361 --- /dev/null +++ b/src/ast.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | #ifndef AST_H | ||
| 2 | #define AST_H | ||
| 3 | |||
| 4 | #include "bu/list.h" | ||
| 5 | #include "bu/stack.h" | ||
| 6 | #include "bu/fstring.h" | ||
| 7 | #include "bu/formatter.h" | ||
| 8 | |||
| 9 | #include "astnode.h" | ||
| 10 | |||
| 11 | /** | ||
| 12 | * Abstract Symbol Tree. This is the thing that the parser builds for us. In | ||
| 13 | * the end, this is also what we "run" when we run build files. | ||
| 14 | */ | ||
| 15 | class Ast | ||
| 16 | { | ||
| 17 | public: | ||
| 18 | typedef Bu::List<AstNode *> NodeList; | ||
| 19 | Ast(); | ||
| 20 | virtual ~Ast(); | ||
| 21 | |||
| 22 | void addNode( AstNode::Type eType ); | ||
| 23 | void addNode( AstNode::Type eType, int iVal ); | ||
| 24 | void addNode( AstNode::Type eType, float fVal ); | ||
| 25 | void addNode( AstNode::Type eType, bool bVal ); | ||
| 26 | void addNode( AstNode::Type eType, const Bu::FString &sVal ); | ||
| 27 | void addNode( AstNode::Type eType, const char *sVal ); | ||
| 28 | void addNode( AstNode *pNode ); | ||
| 29 | |||
| 30 | void openBranch(); | ||
| 31 | |||
| 32 | void closeNode(); | ||
| 33 | |||
| 34 | NodeList::const_iterator getNodeBegin() const; | ||
| 35 | |||
| 36 | private: | ||
| 37 | NodeList lNode; | ||
| 38 | typedef Bu::Stack<class AstBranch *> BranchStack; | ||
| 39 | BranchStack sBranch; | ||
| 40 | }; | ||
| 41 | |||
| 42 | Bu::Formatter &operator<<( Bu::Formatter &f, const Ast &a ); | ||
| 43 | |||
| 44 | #endif | ||
diff --git a/src/astbranch.cpp b/src/astbranch.cpp new file mode 100644 index 0000000..a6aa21c --- /dev/null +++ b/src/astbranch.cpp | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | #include "astbranch.h" | ||
| 2 | |||
| 3 | AstBranch::AstBranch( Type eType ) : | ||
| 4 | AstNode( eType ) | ||
| 5 | { | ||
| 6 | } | ||
| 7 | |||
| 8 | AstBranch::~AstBranch() | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | void AstBranch::addBranch() | ||
| 13 | { | ||
| 14 | lBranch.append( NodeList() ); | ||
| 15 | } | ||
| 16 | |||
| 17 | void AstBranch::addNode( AstNode *pNode ) | ||
| 18 | { | ||
| 19 | lBranch.last().append( pNode ); | ||
| 20 | } | ||
| 21 | |||
| 22 | AstBranch::BranchList::const_iterator AstBranch::getBranchBegin() const | ||
| 23 | { | ||
| 24 | return lBranch.begin(); | ||
| 25 | } | ||
| 26 | |||
| 27 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstBranch &l ) | ||
| 28 | { | ||
| 29 | f.incIndent(); | ||
| 30 | f << ":"; | ||
| 31 | for( AstBranch::BranchList::const_iterator i = l.getBranchBegin(); i; i++ ) | ||
| 32 | { | ||
| 33 | f << f.nl << "Branch:"; | ||
| 34 | f.incIndent(); | ||
| 35 | for( AstBranch::NodeList::const_iterator j = i->begin(); j; j++ ) | ||
| 36 | { | ||
| 37 | f << f.nl << **j; | ||
| 38 | } | ||
| 39 | f.decIndent(); | ||
| 40 | } | ||
| 41 | f.decIndent(); | ||
| 42 | return f; | ||
| 43 | } | ||
| 44 | |||
diff --git a/src/astbranch.h b/src/astbranch.h new file mode 100644 index 0000000..5ff8606 --- /dev/null +++ b/src/astbranch.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef AST_BRANCH_H | ||
| 2 | #define AST_BRANCH_H | ||
| 3 | |||
| 4 | #include "bu/list.h" | ||
| 5 | #include "astnode.h" | ||
| 6 | #include "bu/formatter.h" | ||
| 7 | |||
| 8 | class AstBranch : public AstNode | ||
| 9 | { | ||
| 10 | public: | ||
| 11 | typedef Bu::List<AstNode *> NodeList; | ||
| 12 | typedef Bu::List<NodeList> BranchList; | ||
| 13 | AstBranch( Type eType ); | ||
| 14 | virtual ~AstBranch(); | ||
| 15 | |||
| 16 | void addBranch(); | ||
| 17 | void addNode( AstNode *pNode ); | ||
| 18 | |||
| 19 | BranchList::const_iterator getBranchBegin() const; | ||
| 20 | |||
| 21 | private: | ||
| 22 | BranchList lBranch; | ||
| 23 | }; | ||
| 24 | |||
| 25 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstBranch &l ); | ||
| 26 | |||
| 27 | #endif | ||
diff --git a/src/astleaf.cpp b/src/astleaf.cpp new file mode 100644 index 0000000..62773ce --- /dev/null +++ b/src/astleaf.cpp | |||
| @@ -0,0 +1,137 @@ | |||
| 1 | #include "astleaf.h" | ||
| 2 | |||
| 3 | AstLeaf::AstLeaf( Type eType ) : | ||
| 4 | AstNode( eType ), | ||
| 5 | sVal( NULL ) | ||
| 6 | { | ||
| 7 | } | ||
| 8 | |||
| 9 | AstLeaf::AstLeaf( Type eType, int iNew ) : | ||
| 10 | AstNode( eType ), | ||
| 11 | sVal( NULL ) | ||
| 12 | { | ||
| 13 | setIntValue( iNew ); | ||
| 14 | } | ||
| 15 | |||
| 16 | AstLeaf::AstLeaf( Type eType, float fNew ) : | ||
| 17 | AstNode( eType ), | ||
| 18 | sVal( NULL ) | ||
| 19 | { | ||
| 20 | setFloatValue( fNew ); | ||
| 21 | } | ||
| 22 | |||
| 23 | AstLeaf::AstLeaf( Type eType, bool bNew ) : | ||
| 24 | AstNode( eType ), | ||
| 25 | sVal( NULL ) | ||
| 26 | { | ||
| 27 | setBoolValue( bNew ); | ||
| 28 | } | ||
| 29 | |||
| 30 | AstLeaf::AstLeaf( Type eType, const Bu::FString &sNew ) : | ||
| 31 | AstNode( eType ), | ||
| 32 | sVal( NULL ) | ||
| 33 | { | ||
| 34 | setStrValue( sNew ); | ||
| 35 | } | ||
| 36 | |||
| 37 | AstLeaf::AstLeaf( Type eType, const char *sNew ) : | ||
| 38 | AstNode( eType ), | ||
| 39 | sVal( NULL ) | ||
| 40 | { | ||
| 41 | setStrValue( sNew ); | ||
| 42 | } | ||
| 43 | |||
| 44 | AstLeaf::~AstLeaf() | ||
| 45 | { | ||
| 46 | if( getDataType() == typeDataString ) | ||
| 47 | delete sVal; | ||
| 48 | } | ||
| 49 | |||
| 50 | void AstLeaf::setIntValue( int iNew ) | ||
| 51 | { | ||
| 52 | if( getDataType() != typeDataInt ) | ||
| 53 | throw Bu::ExceptionBase("Type is not int."); | ||
| 54 | iVal = iNew; | ||
| 55 | } | ||
| 56 | |||
| 57 | void AstLeaf::setFloatValue( float fNew ) | ||
| 58 | { | ||
| 59 | if( getDataType() != typeDataFloat ) | ||
| 60 | throw Bu::ExceptionBase("Type is not float."); | ||
| 61 | fVal = fNew; | ||
| 62 | } | ||
| 63 | |||
| 64 | void AstLeaf::setBoolValue( bool bNew ) | ||
| 65 | { | ||
| 66 | if( getDataType() != typeDataBool ) | ||
| 67 | throw Bu::ExceptionBase("Type is not bool."); | ||
| 68 | bVal = bNew; | ||
| 69 | } | ||
| 70 | |||
| 71 | void AstLeaf::setStrValue( const Bu::FString &sNew ) | ||
| 72 | { | ||
| 73 | if( getDataType() != typeDataString ) | ||
| 74 | throw Bu::ExceptionBase("Type is not string."); | ||
| 75 | if( sVal == NULL ) | ||
| 76 | sVal = new Bu::FString( sNew ); | ||
| 77 | else | ||
| 78 | *sVal = sNew; | ||
| 79 | } | ||
| 80 | |||
| 81 | int AstLeaf::getIntValue() const | ||
| 82 | { | ||
| 83 | if( getDataType() != typeDataInt ) | ||
| 84 | throw Bu::ExceptionBase("Type is not int."); | ||
| 85 | return iVal; | ||
| 86 | } | ||
| 87 | |||
| 88 | float AstLeaf::getFloatValue() const | ||
| 89 | { | ||
| 90 | if( getDataType() != typeDataFloat ) | ||
| 91 | throw Bu::ExceptionBase("Type is not float."); | ||
| 92 | return fVal; | ||
| 93 | } | ||
| 94 | |||
| 95 | bool AstLeaf::getBoolValue() const | ||
| 96 | { | ||
| 97 | if( getDataType() != typeDataBool ) | ||
| 98 | throw Bu::ExceptionBase("Type is not bool."); | ||
| 99 | return bVal; | ||
| 100 | } | ||
| 101 | |||
| 102 | Bu::FString &AstLeaf::getStrValue() const | ||
| 103 | { | ||
| 104 | if( getDataType() != typeDataString ) | ||
| 105 | throw Bu::ExceptionBase("Type is not string."); | ||
| 106 | return *sVal; | ||
| 107 | } | ||
| 108 | |||
| 109 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstLeaf &l ) | ||
| 110 | { | ||
| 111 | switch( l.getDataType() ) | ||
| 112 | { | ||
| 113 | case AstNode::typeDataInt: | ||
| 114 | f << ": " << l.getIntValue(); | ||
| 115 | break; | ||
| 116 | |||
| 117 | case AstNode::typeDataFloat: | ||
| 118 | f << ": " << l.getFloatValue(); | ||
| 119 | break; | ||
| 120 | |||
| 121 | case AstNode::typeDataBool: | ||
| 122 | f << ": " << l.getBoolValue(); | ||
| 123 | break; | ||
| 124 | |||
| 125 | case AstNode::typeDataString: | ||
| 126 | f << ": '" << l.getStrValue() << "'"; | ||
| 127 | break; | ||
| 128 | |||
| 129 | case AstNode::typeDataNone: | ||
| 130 | break; | ||
| 131 | |||
| 132 | default: | ||
| 133 | f << ": " << "!! Invalid Type !!"; | ||
| 134 | } | ||
| 135 | return f; | ||
| 136 | } | ||
| 137 | |||
diff --git a/src/astleaf.h b/src/astleaf.h new file mode 100644 index 0000000..0c8911b --- /dev/null +++ b/src/astleaf.h | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | #ifndef AST_LEAF_H | ||
| 2 | #define AST_LEAF_H | ||
| 3 | |||
| 4 | #include "astnode.h" | ||
| 5 | #include "bu/fstring.h" | ||
| 6 | #include "bu/formatter.h" | ||
| 7 | |||
| 8 | class AstLeaf : public AstNode | ||
| 9 | { | ||
| 10 | public: | ||
| 11 | AstLeaf( Type eType ); | ||
| 12 | AstLeaf( Type eType, int iNew ); | ||
| 13 | AstLeaf( Type eType, float fNew ); | ||
| 14 | AstLeaf( Type eType, bool bNew ); | ||
| 15 | AstLeaf( Type eType, const Bu::FString &sNew ); | ||
| 16 | AstLeaf( Type eType, const char *sNew ); | ||
| 17 | virtual ~AstLeaf(); | ||
| 18 | |||
| 19 | void setIntValue( int iNew ); | ||
| 20 | void setFloatValue( float fNew ); | ||
| 21 | void setBoolValue( bool bNew ); | ||
| 22 | void setStrValue( const Bu::FString &sNew ); | ||
| 23 | |||
| 24 | int getIntValue() const; | ||
| 25 | float getFloatValue() const; | ||
| 26 | bool getBoolValue() const; | ||
| 27 | Bu::FString &getStrValue() const; | ||
| 28 | |||
| 29 | private: | ||
| 30 | union | ||
| 31 | { | ||
| 32 | int iVal; | ||
| 33 | float fVal; | ||
| 34 | bool bVal; | ||
| 35 | Bu::FString *sVal; | ||
| 36 | }; | ||
| 37 | }; | ||
| 38 | |||
| 39 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstLeaf &l ); | ||
| 40 | |||
| 41 | #endif | ||
diff --git a/src/astnode.cpp b/src/astnode.cpp new file mode 100644 index 0000000..5adb3ee --- /dev/null +++ b/src/astnode.cpp | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | #include "astnode.h" | ||
| 2 | #include "astleaf.h" | ||
| 3 | #include "astbranch.h" | ||
| 4 | |||
| 5 | AstNode::AstNode( Type eType ) : | ||
| 6 | eType( eType ) | ||
| 7 | { | ||
| 8 | } | ||
| 9 | |||
| 10 | AstNode::~AstNode() | ||
| 11 | { | ||
| 12 | } | ||
| 13 | |||
| 14 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstNode &n ) | ||
| 15 | { | ||
| 16 | f << n.getType(); | ||
| 17 | if( n.getClass() == AstNode::typeBranch ) | ||
| 18 | { | ||
| 19 | f << *dynamic_cast<const AstBranch *>(&n); | ||
| 20 | } | ||
| 21 | else | ||
| 22 | { | ||
| 23 | f << *dynamic_cast<const AstLeaf *>(&n); | ||
| 24 | } | ||
| 25 | return f; | ||
| 26 | } | ||
| 27 | |||
| 28 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstNode::Type &t ) | ||
| 29 | { | ||
| 30 | switch( t ) | ||
| 31 | { | ||
| 32 | case AstNode::typeFunction: f << "Function"; break; | ||
| 33 | case AstNode::typeSet: f << "Set"; break; | ||
| 34 | case AstNode::typeUnset: f << "Unset"; break; | ||
| 35 | case AstNode::typeIf: f << "If"; break; | ||
| 36 | case AstNode::typeInclude: f << "Include"; break; | ||
| 37 | case AstNode::typeTarget: f << "Target"; break; | ||
| 38 | case AstNode::typeRule: f << "Rule"; break; | ||
| 39 | case AstNode::typeConfig: f << "Config"; break; | ||
| 40 | case AstNode::typeList: f << "List"; break; | ||
| 41 | case AstNode::typeInlineFunc: f << "InlineFunc"; break; | ||
| 42 | case AstNode::typeRequires: f << "Requires"; break; | ||
| 43 | case AstNode::typeFor: f << "For"; break; | ||
| 44 | case AstNode::typeFunctionDef: f << "FunctionDef"; break; | ||
| 45 | case AstNode::typeReturn: f << "Return"; break; | ||
| 46 | case AstNode::typeProfile: f << "Profile"; break; | ||
| 47 | case AstNode::typeInput: f << "Input"; break; | ||
| 48 | case AstNode::typeRuleDef: f << "RuleDef"; break; | ||
| 49 | case AstNode::typeOutput: f << "Output"; break; | ||
| 50 | case AstNode::typeAutoConfig: f << "AutoConfig"; break; | ||
| 51 | case AstNode::typeGlobalConfig: f << "GlobalConfig"; break; | ||
| 52 | case AstNode::typeType: f << "Type"; break; | ||
| 53 | case AstNode::typeValue: f << "Value"; break; | ||
| 54 | case AstNode::typeAllow: f << "Allow"; break; | ||
| 55 | case AstNode::typeDefault: f << "Default"; break; | ||
| 56 | case AstNode::typeExport: f << "Export"; break; | ||
| 57 | case AstNode::typeExpr: f << "Expr"; break; | ||
| 58 | case AstNode::typeActionDef: f << "ActionDef"; break; | ||
| 59 | case AstNode::typeProcessTarget:f << "ProcessTarget"; break; | ||
| 60 | case AstNode::typeTag: f << "Tag"; break; | ||
| 61 | |||
| 62 | case AstNode::typeVariable: f << "Variable"; break; | ||
| 63 | case AstNode::typeString: f << "String"; break; | ||
| 64 | case AstNode::typeInt: f << "Int"; break; | ||
| 65 | case AstNode::typeFloat: f << "Float"; break; | ||
| 66 | case AstNode::typeBool: f << "Bool"; break; | ||
| 67 | case AstNode::typeVersion: f << "Version"; break; | ||
| 68 | case AstNode::typeOpEq: f << "Operator ="; break; | ||
| 69 | case AstNode::typeOpPlusEq: f << "Operator +="; break; | ||
| 70 | case AstNode::typeOpPlusEqRaw: f << "Operator <<"; break; | ||
| 71 | case AstNode::typeError: f << "Error"; break; | ||
| 72 | case AstNode::typeWarning: f << "Warning"; break; | ||
| 73 | case AstNode::typeNotice: f << "Notice"; break; | ||
| 74 | case AstNode::typeTypeString: f << "Type String"; break; | ||
| 75 | case AstNode::typeTypeInt: f << "Type Int"; break; | ||
| 76 | case AstNode::typeTypeFloat: f << "Type Float"; break; | ||
| 77 | case AstNode::typeTypeBool: f << "Type Bool"; break; | ||
| 78 | case AstNode::typeTypeVersion: f << "Type Version"; break; | ||
| 79 | case AstNode::typeCmpEq: f << "Compare ="; break; | ||
| 80 | case AstNode::typeCmpLt: f << "Compare <"; break; | ||
| 81 | case AstNode::typeCmpGt: f << "Compare >"; break; | ||
| 82 | case AstNode::typeCmpNe: f << "Compare !="; break; | ||
| 83 | case AstNode::typeCmpLtEq: f << "Compare <="; break; | ||
| 84 | case AstNode::typeCmpGtEq: f << "Compare >="; break; | ||
| 85 | case AstNode::typeCondition: f << "Condition"; break; | ||
| 86 | case AstNode::typeDisplay: f << "Display"; break; | ||
| 87 | case AstNode::typeCache: f << "Cache"; break; | ||
| 88 | case AstNode::typePushPrefix: f << "Push Prefix"; break; | ||
| 89 | case AstNode::typePopPrefix: f << "Pop Prefix"; break; | ||
| 90 | case AstNode::typeNull: f << "Null"; break; | ||
| 91 | case AstNode::typeVariableRef: f << "VariableRef"; break; | ||
| 92 | case AstNode::typeOpPlus: f << "Operator +"; break; | ||
| 93 | case AstNode::typeOpMinus: f << "Operator -"; break; | ||
| 94 | case AstNode::typeOpMultiply: f << "Operator *"; break; | ||
| 95 | case AstNode::typeOpDivide: f << "Operator /"; break; | ||
| 96 | case AstNode::typeOpNegate: f << "Operator negate"; break; | ||
| 97 | case AstNode::typeOpNot: f << "Operator not"; break; | ||
| 98 | |||
| 99 | case AstNode::typeBranch: f << "Branch"; break; | ||
| 100 | case AstNode::typeLeaf: f << "Leaf"; break; | ||
| 101 | case AstNode::typeClassMask: f << "ClassMask"; break; | ||
| 102 | |||
| 103 | case AstNode::typeDataNone: f << "<Data None>"; break; | ||
| 104 | case AstNode::typeDataString: f << "<Data String>"; break; | ||
| 105 | case AstNode::typeDataInt: f << "<Data Int>"; break; | ||
| 106 | case AstNode::typeDataFloat: f << "<Data Float>"; break; | ||
| 107 | case AstNode::typeDataBool: f << "<Data Bool>"; break; | ||
| 108 | case AstNode::typeDataVersion: f << "<Data Version>"; break; | ||
| 109 | case AstNode::typeDataMask: f << "<Data Mask>"; break; | ||
| 110 | } | ||
| 111 | return f; | ||
| 112 | } | ||
| 113 | |||
diff --git a/src/astnode.h b/src/astnode.h new file mode 100644 index 0000000..6ade25b --- /dev/null +++ b/src/astnode.h | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | #ifndef AST_NODE_H | ||
| 2 | #define AST_NODE_H | ||
| 3 | |||
| 4 | #include "bu/formatter.h" | ||
| 5 | |||
| 6 | class AstNode | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | enum Type | ||
| 10 | { | ||
| 11 | // Branching types | ||
| 12 | typeFunction = 0x100001, | ||
| 13 | typeSet = 0x100002, | ||
| 14 | typeUnset = 0x100003, | ||
| 15 | typeIf = 0x100004, | ||
| 16 | typeInclude = 0x100005, | ||
| 17 | typeTarget = 0x100006, | ||
| 18 | typeRule = 0x100007, | ||
| 19 | typeConfig = 0x100008, | ||
| 20 | typeList = 0x100009, | ||
| 21 | typeInlineFunc = 0x10000A, | ||
| 22 | typeRequires = 0x10000B, | ||
| 23 | typeFor = 0x10000C, | ||
| 24 | typeFunctionDef = 0x10000D, | ||
| 25 | typeReturn = 0x10000E, | ||
| 26 | typeProfile = 0x10000F, | ||
| 27 | typeInput = 0x100010, | ||
| 28 | typeRuleDef = 0x100011, | ||
| 29 | typeOutput = 0x100012, | ||
| 30 | typeAutoConfig = 0x100013, | ||
| 31 | typeGlobalConfig = 0x100014, | ||
| 32 | typeType = 0x100015, | ||
| 33 | typeValue = 0x100016, | ||
| 34 | typeAllow = 0x100017, | ||
| 35 | typeDefault = 0x100018, | ||
| 36 | typeExport = 0x100019, | ||
| 37 | typeExpr = 0x10001A, /***< Stack based compound expression.*/ | ||
| 38 | typeActionDef = 0x10001B, | ||
| 39 | typeProcessTarget = 0x10001C, | ||
| 40 | typeTag = 0x10001D, | ||
| 41 | |||
| 42 | // Leaf types | ||
| 43 | typeVariable = 0x210001, | ||
| 44 | typeString = 0x210002, | ||
| 45 | typeInt = 0x220003, | ||
| 46 | typeFloat = 0x230004, | ||
| 47 | typeBool = 0x240005, | ||
| 48 | typeVersion = 0x250006, | ||
| 49 | typeOpEq = 0x200007, | ||
| 50 | typeOpPlusEq = 0x200008, | ||
| 51 | typeOpPlusEqRaw = 0x200009, | ||
| 52 | typeError = 0x21000A, | ||
| 53 | typeWarning = 0x21000B, | ||
| 54 | typeNotice = 0x21000C, | ||
| 55 | typeTypeString = 0x20000D, | ||
| 56 | typeTypeInt = 0x20000E, | ||
| 57 | typeTypeFloat = 0x20000F, | ||
| 58 | typeTypeBool = 0x200010, | ||
| 59 | typeTypeVersion = 0x200011, | ||
| 60 | typeCmpEq = 0x200012, | ||
| 61 | typeCmpLt = 0x200013, | ||
| 62 | typeCmpGt = 0x200014, | ||
| 63 | typeCmpNe = 0x200015, | ||
| 64 | typeCmpLtEq = 0x200016, | ||
| 65 | typeCmpGtEq = 0x200017, | ||
| 66 | typeCondition = 0x210018, | ||
| 67 | typeDisplay = 0x210019, | ||
| 68 | typeCache = 0x24001A, | ||
| 69 | typePushPrefix = 0x21001B, | ||
| 70 | typePopPrefix = 0x20001C, | ||
| 71 | typeNull = 0x20001D, | ||
| 72 | typeVariableRef = 0x21001E, | ||
| 73 | typeOpPlus = 0x20001F, | ||
| 74 | typeOpMinus = 0x200020, | ||
| 75 | typeOpMultiply = 0x200021, | ||
| 76 | typeOpDivide = 0x200022, | ||
| 77 | typeOpNegate = 0x200023, | ||
| 78 | typeOpNot = 0x200024, | ||
| 79 | |||
| 80 | typeBranch = 0x100000, | ||
| 81 | typeLeaf = 0x200000, | ||
| 82 | typeClassMask = 0x300000, | ||
| 83 | |||
| 84 | typeDataNone = 0x000000, | ||
| 85 | typeDataString = 0x010000, | ||
| 86 | typeDataInt = 0x020000, | ||
| 87 | typeDataFloat = 0x030000, | ||
| 88 | typeDataBool = 0x040000, | ||
| 89 | typeDataVersion = 0x050000, | ||
| 90 | |||
| 91 | typeDataMask = 0x0F0000 | ||
| 92 | }; | ||
| 93 | public: | ||
| 94 | AstNode( Type eType ); | ||
| 95 | virtual ~AstNode(); | ||
| 96 | |||
| 97 | Type getType() const { return eType; } | ||
| 98 | Type getClass() const { return (Type)(eType&typeClassMask); } | ||
| 99 | Type getDataType() const { return (Type)(eType&typeDataMask); } | ||
| 100 | |||
| 101 | private: | ||
| 102 | Type eType; | ||
| 103 | }; | ||
| 104 | |||
| 105 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstNode &n ); | ||
| 106 | Bu::Formatter &operator<<( Bu::Formatter &f, const AstNode::Type &t ); | ||
| 107 | |||
| 108 | #endif | ||
diff --git a/src/build.l b/src/build.l new file mode 100644 index 0000000..dc4ddda --- /dev/null +++ b/src/build.l | |||
| @@ -0,0 +1,216 @@ | |||
| 1 | %{ | ||
| 2 | #include "buildparser.h" | ||
| 3 | #include "bu/fstring.h" | ||
| 4 | |||
| 5 | char *fstrdup( const Bu::FString &s ) | ||
| 6 | { | ||
| 7 | char *sRet = new char[s.getSize()+1]; | ||
| 8 | memcpy( sRet, s.getStr(), s.getSize()+1 ); | ||
| 9 | return sRet; | ||
| 10 | } | ||
| 11 | |||
| 12 | char *rstrdup( const char *sIn ) | ||
| 13 | { | ||
| 14 | char *sRet = new char[strlen(sIn)+1]; | ||
| 15 | strcpy( sRet, sIn ); | ||
| 16 | return sRet; | ||
| 17 | } | ||
| 18 | void build_error( YYLTYPE *locp, yyscan_t yyscanner, BuildParser &bld, const char *msg ); | ||
| 19 | |||
| 20 | Bu::FString sBuf; | ||
| 21 | int iStrDepth = 0; | ||
| 22 | %} | ||
| 23 | |||
| 24 | %{ | ||
| 25 | #define YY_USER_ACTION yylloc->last_column += yyleng; | ||
| 26 | %} | ||
| 27 | |||
| 28 | %x strdq | ||
| 29 | %x BlockComment | ||
| 30 | %option noyywrap nounput batch debug bison-bridge bison-locations reentrant | ||
| 31 | %option prefix="build_" | ||
| 32 | %option outfile="src/build.yy.c" | ||
| 33 | %option header-file="src/build.yy.h" | ||
| 34 | %% | ||
| 35 | \n+ { | ||
| 36 | yylloc->last_line += yyleng; | ||
| 37 | yylloc->first_line = yylloc->last_line; | ||
| 38 | yylloc->first_column = yylloc->last_column = 0; | ||
| 39 | } | ||
| 40 | [ \t\r]+ { | ||
| 41 | yylloc->first_line = yylloc->last_line; | ||
| 42 | yylloc->first_column = yylloc->last_column+1; | ||
| 43 | } | ||
| 44 | "#".* /* eol comment */ | ||
| 45 | "//".* /* eol comment */ | ||
| 46 | |||
| 47 | "/*" { | ||
| 48 | BEGIN( BlockComment ); | ||
| 49 | } | ||
| 50 | |||
| 51 | <BlockComment>"*/" { | ||
| 52 | BEGIN( INITIAL ); | ||
| 53 | } | ||
| 54 | |||
| 55 | <BlockComment>\n+ { | ||
| 56 | yylloc->last_column = -yyleng; | ||
| 57 | yylloc->last_line += yyleng; | ||
| 58 | } | ||
| 59 | <BlockComment>. { } | ||
| 60 | /* | ||
| 61 | <BlockComment>[^*\n/]+ { } | ||
| 62 | <BlockComment>"*"[^/\n]+ { } | ||
| 63 | <BlockComment>"*"|"/" { } | ||
| 64 | */ | ||
| 65 | |||
| 66 | [(){}[\],.;=<>!+*/-] return yytext[0]; | ||
| 67 | "+=" return OP_ADDSETP; | ||
| 68 | "<<" return OP_ADDSETR; | ||
| 69 | "==" return OP_CMPEQUAL; | ||
| 70 | "!=" return OP_INEQUAL; | ||
| 71 | "<=" return OP_LTEQUAL; | ||
| 72 | ">=" return OP_GTEQUAL; | ||
| 73 | "target" return TOK_TARGET; | ||
| 74 | "input" return TOK_INPUT; | ||
| 75 | "output" return TOK_OUTPUT; | ||
| 76 | "unset" return TOK_UNSET; | ||
| 77 | "set" return TOK_SET; | ||
| 78 | "condition" return TOK_CONDITION; | ||
| 79 | "requires" return TOK_REQUIRES; | ||
| 80 | "auto" return TOK_AUTO; | ||
| 81 | "config" return TOK_CONFIG; | ||
| 82 | "display" return TOK_DISPLAY; | ||
| 83 | "type" return TOK_TYPE; | ||
| 84 | "int" return TOK_INT; | ||
| 85 | "float" return TOK_FLOAT; | ||
| 86 | "bool" return TOK_BOOL; | ||
| 87 | "version" return TOK_VERSION; | ||
| 88 | "string" return TOK_STRING; | ||
| 89 | "default" return TOK_DEFAULT; | ||
| 90 | "allow" return TOK_ALLOW; | ||
| 91 | "rule" return TOK_RULE; | ||
| 92 | "action" return TOK_ACTION; | ||
| 93 | "profile" return TOK_PROFILE; | ||
| 94 | "if" return TOK_IF; | ||
| 95 | "then" return TOK_THEN; | ||
| 96 | "else" return TOK_ELSE; | ||
| 97 | "include" return TOK_INCLUDE; | ||
| 98 | "warning" return TOK_WARNING; | ||
| 99 | "error" return TOK_ERROR; | ||
| 100 | "notice" return TOK_NOTICE; | ||
| 101 | "cache" return TOK_CACHE; | ||
| 102 | "always" return TOK_ALWAYS; | ||
| 103 | "never" return TOK_NEVER; | ||
| 104 | "global" return TOK_GLOBAL; | ||
| 105 | "local" return TOK_LOCAL; | ||
| 106 | "for" return TOK_FOR; | ||
| 107 | "in" return TOK_IN; | ||
| 108 | "do" return TOK_DO; | ||
| 109 | "return" return TOK_RETURN; | ||
| 110 | "function" return TOK_FUNCTION; | ||
| 111 | "continue" return TOK_CONTINUE; | ||
| 112 | "break" return TOK_BREAK; | ||
| 113 | "value" return TOK_VALUE; | ||
| 114 | "all" return TOK_ALL; | ||
| 115 | "export" return TOK_EXPORT; | ||
| 116 | "tag" return TOK_TAG; | ||
| 117 | "null" return TOK_NULL; | ||
| 118 | |||
| 119 | "true" { | ||
| 120 | yylval->bVal = true; | ||
| 121 | return BOOL; | ||
| 122 | } | ||
| 123 | "false" { | ||
| 124 | yylval->bVal = false; | ||
| 125 | return BOOL; | ||
| 126 | } | ||
| 127 | |||
| 128 | [a-zA-Z_][a-zA-Z0-9_]*: { | ||
| 129 | yytext[yyleng-1] = '\0'; | ||
| 130 | yylval->sVal = rstrdup( yytext ); | ||
| 131 | return PROFILE; | ||
| 132 | } | ||
| 133 | |||
| 134 | [a-zA-Z_][a-zA-Z0-9_]* { | ||
| 135 | yylval->sVal = rstrdup( yytext ); | ||
| 136 | if( b.isKeyword( yylval->sVal ) ) | ||
| 137 | return KEYWORD; | ||
| 138 | else if( b.isCond( yylval->sVal ) ) | ||
| 139 | return CONDITION; | ||
| 140 | return UNDEF; | ||
| 141 | } | ||
| 142 | |||
| 143 | -?([1-9][0-9]*)|(0) { | ||
| 144 | yylval->iVal = strtol( yytext, NULL, 10 ); | ||
| 145 | return INT; | ||
| 146 | } | ||
| 147 | |||
| 148 | (0\.0+)|(-?(([1-9][0-9]*)|(0))\.[0-9]*) { | ||
| 149 | yylval->fVal = strtof( yytext, NULL ); | ||
| 150 | return FLOAT; | ||
| 151 | } | ||
| 152 | |||
| 153 | \" { | ||
| 154 | BEGIN( strdq ); | ||
| 155 | sBuf.clear(); | ||
| 156 | iStrDepth = 0; | ||
| 157 | } | ||
| 158 | <strdq>[^\\\n\"$()]+ { | ||
| 159 | sBuf += yytext; | ||
| 160 | } | ||
| 161 | <strdq>\$\$ { | ||
| 162 | sBuf += "$$"; | ||
| 163 | } | ||
| 164 | <strdq>\$\( { | ||
| 165 | iStrDepth++; // TODO: Should this really count depth? I dunno... | ||
| 166 | sBuf += "$("; | ||
| 167 | } | ||
| 168 | <strdq>\\\) sBuf += "\\)"; | ||
| 169 | <strdq>\) { | ||
| 170 | if( iStrDepth > 0 ) | ||
| 171 | iStrDepth--; | ||
| 172 | sBuf += ")"; | ||
| 173 | } | ||
| 174 | <strdq>[$(] { | ||
| 175 | sBuf += yytext; | ||
| 176 | } | ||
| 177 | <strdq>\n { | ||
| 178 | build_error( yylloc, yyscanner, b, "newline encountered in string"); | ||
| 179 | } | ||
| 180 | <strdq>\\n sBuf += "\n"; | ||
| 181 | <strdq>\\t sBuf += "\t"; | ||
| 182 | <strdq>\\r sBuf += "\r"; | ||
| 183 | <strdq>\\b sBuf += "\b"; | ||
| 184 | <strdq>\\f sBuf += "\f"; | ||
| 185 | <strdq>\\\\ sBuf += "\\"; | ||
| 186 | <strdq>\\\" sBuf += "\""; | ||
| 187 | <strdq>\\\' sBuf += "\'"; | ||
| 188 | <strdq>\\\( sBuf += "("; | ||
| 189 | <strdq>\\\` sBuf += "`"; | ||
| 190 | <strdq>\\. printf("Invalid escape sequence.\n"); | ||
| 191 | <strdq>\"[ \t\r\n]*\" {/* Ignore spaces between strings. */} | ||
| 192 | <strdq>\" { | ||
| 193 | if( iStrDepth > 0 ) | ||
| 194 | { | ||
| 195 | sBuf += "\""; | ||
| 196 | } | ||
| 197 | else | ||
| 198 | { | ||
| 199 | BEGIN( INITIAL ); | ||
| 200 | yylval->sVal = fstrdup( sBuf ); | ||
| 201 | return STRING; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | <<EOF>> { | ||
| 206 | build_pop_buffer_state( yyscanner ); | ||
| 207 | if( !YY_CURRENT_BUFFER ) | ||
| 208 | yyterminate(); | ||
| 209 | else | ||
| 210 | b.endInclude( yylloc ); | ||
| 211 | } | ||
| 212 | |||
| 213 | . { | ||
| 214 | build_error( yylloc, yyscanner, b, "invalid character"); | ||
| 215 | } | ||
| 216 | %% | ||
diff --git a/src/build.y b/src/build.y new file mode 100644 index 0000000..a6618e4 --- /dev/null +++ b/src/build.y | |||
| @@ -0,0 +1,741 @@ | |||
| 1 | %defines | ||
| 2 | %{ /* Prologue -- decls and stuff */ | ||
| 3 | #include "buildparser.h" | ||
| 4 | #include "ast.h" | ||
| 5 | void yyerror( YYLTYPE *locp, yyscan_t yyscanner, BuildParser &bld, const char *msg ); | ||
| 6 | %} | ||
| 7 | /* Bison declerations */ | ||
| 8 | |||
| 9 | %parse-param { yyscan_t yyscanner } | ||
| 10 | %parse-param { BuildParser &bld } | ||
| 11 | %lex-param { yyscan_t yyscanner } | ||
| 12 | %lex-param { BuildParser &bld } | ||
| 13 | %pure-parser | ||
| 14 | |||
| 15 | %locations | ||
| 16 | |||
| 17 | %debug | ||
| 18 | %error-verbose | ||
| 19 | %name-prefix="build_" | ||
| 20 | |||
| 21 | %union { | ||
| 22 | int iVal; | ||
| 23 | char *sVal; | ||
| 24 | float fVal; | ||
| 25 | bool bVal; | ||
| 26 | } | ||
| 27 | |||
| 28 | %token <sVal> STRING "string literal" | ||
| 29 | %token <sVal> KEYWORD "keyword" | ||
| 30 | %token <sVal> CONDITION "condition term" | ||
| 31 | %token <sVal> VARIABLE "variable name" | ||
| 32 | %token <sVal> FUNCTION "function name" | ||
| 33 | %token <sVal> UNDEF "undefined identifier" | ||
| 34 | %token <sVal> PROFILE "profile execute" | ||
| 35 | %token <iVal> INT "integer literal" | ||
| 36 | %token <fVal> FLOAT "floating point literal" | ||
| 37 | %token <bVal> BOOL "boolean literal" | ||
| 38 | |||
| 39 | %token TOK_TARGET "target" | ||
| 40 | %token TOK_INPUT "input" | ||
| 41 | %token TOK_OUTPUT "output" | ||
| 42 | %token TOK_UNSET "unset" | ||
| 43 | %token TOK_SET "set" | ||
| 44 | %token TOK_CONDITION "condition" | ||
| 45 | %token TOK_REQUIRES "requires" | ||
| 46 | %token TOK_AUTO "auto" | ||
| 47 | %token TOK_CONFIG "config" | ||
| 48 | %token TOK_DISPLAY "display" | ||
| 49 | %token TOK_TYPE "type" | ||
| 50 | %token TOK_INT "int" | ||
| 51 | %token TOK_FLOAT "float" | ||
| 52 | %token TOK_BOOL "boolean" | ||
| 53 | %token TOK_VERSION "version" | ||
| 54 | %token TOK_STRING "string" | ||
| 55 | %token TOK_DEFAULT "default" | ||
| 56 | %token TOK_ALLOW "allow" | ||
| 57 | %token TOK_RULE "rule" | ||
| 58 | %token TOK_ACTION "action" | ||
| 59 | %token TOK_PROFILE "profile" | ||
| 60 | %token TOK_IF "if" | ||
| 61 | %token TOK_THEN "then" | ||
| 62 | %token TOK_ELSE "else" | ||
| 63 | %token TOK_INCLUDE "include" | ||
| 64 | %token TOK_ERROR "error" | ||
| 65 | %token TOK_WARNING "warning" | ||
| 66 | %token TOK_NOTICE "notice" | ||
| 67 | %token TOK_CACHE "cache" | ||
| 68 | %token TOK_ALWAYS "always" | ||
| 69 | %token TOK_NEVER "never" | ||
| 70 | %token TOK_GLOBAL "global" | ||
| 71 | %token TOK_LOCAL "local" | ||
| 72 | %token TOK_FOR "for" | ||
| 73 | %token TOK_IN "in" | ||
| 74 | %token TOK_DO "do" | ||
| 75 | %token TOK_RETURN "return" | ||
| 76 | %token TOK_FUNCTION "function" | ||
| 77 | %token TOK_CONTINUE "continue" | ||
| 78 | %token TOK_BREAK "break" | ||
| 79 | %token TOK_VALUE "value" | ||
| 80 | %token TOK_ALL "all" | ||
| 81 | %token TOK_EXPORT "export" | ||
| 82 | %token TOK_TAG "tag" | ||
| 83 | %token TOK_NULL "null" | ||
| 84 | |||
| 85 | %token OP_ADDSETP "+=" | ||
| 86 | %token OP_ADDSETR "<<" | ||
| 87 | %token OP_CMPEQUAL "==" | ||
| 88 | %token OP_INEQUAL "!=" | ||
| 89 | %token OP_LTEQUAL "<=" | ||
| 90 | %token OP_GTEQUAL ">=" | ||
| 91 | |||
| 92 | %token '(' ')' '{' '}' '[' ']' ',' ';' '=' '.' '<' '>' '+' '-' '*' '/' | ||
| 93 | |||
| 94 | %right '=' OP_ADDSETP OPADDSETR | ||
| 95 | %left OP_CMPEQUAL '<' '>' OP_INEQUAL OP_LTEQUAL OP_GTEQUAL '+' '-' '*' '/' | ||
| 96 | %left '(' ')' '{' '}' '[' ']' | ||
| 97 | %left IINEG IINOT | ||
| 98 | |||
| 99 | %destructor { delete[] $$; } STRING | ||
| 100 | %destructor { delete[] $$; } KEYWORD | ||
| 101 | %destructor { delete[] $$; } CONDITION | ||
| 102 | %destructor { delete[] $$; } VARIABLE | ||
| 103 | %destructor { delete[] $$; } FUNCTION | ||
| 104 | %destructor { delete[] $$; } UNDEF | ||
| 105 | %destructor { delete[] $$; } PROFILE | ||
| 106 | |||
| 107 | %% /* Grammar rules */ | ||
| 108 | |||
| 109 | /* | ||
| 110 | * root stuff | ||
| 111 | */ | ||
| 112 | |||
| 113 | root: | ||
| 114 | // | root set | ||
| 115 | | root line_expr | ||
| 116 | | root unset | ||
| 117 | | root target | ||
| 118 | | root rule | ||
| 119 | | root config | ||
| 120 | | root root_if | ||
| 121 | | root root_for | ||
| 122 | | root include | ||
| 123 | | root notify | ||
| 124 | | root export | ||
| 125 | | root function_def | ||
| 126 | | root action_def | ||
| 127 | ; | ||
| 128 | |||
| 129 | root_sub_exprs: | ||
| 130 | // | root set | ||
| 131 | | root line_expr | ||
| 132 | | root unset | ||
| 133 | | root target | ||
| 134 | | root rule | ||
| 135 | | root config | ||
| 136 | | root root_if | ||
| 137 | | root root_for | ||
| 138 | | root include | ||
| 139 | | root notify | ||
| 140 | | root export | ||
| 141 | ; | ||
| 142 | |||
| 143 | include: TOK_INCLUDE STRING ';' { bld.include( $2, yyscanner, &yylloc ); } | ||
| 144 | ; | ||
| 145 | |||
| 146 | /* | ||
| 147 | * data related | ||
| 148 | */ | ||
| 149 | |||
| 150 | string: STRING { bld.xAst.addNode( AstNode::typeString, $1 ); } | ||
| 151 | ; | ||
| 152 | |||
| 153 | int: INT { bld.xAst.addNode( AstNode::typeInt, $1 ); } | ||
| 154 | ; | ||
| 155 | |||
| 156 | float: FLOAT { bld.xAst.addNode( AstNode::typeFloat, $1 ); } | ||
| 157 | ; | ||
| 158 | |||
| 159 | bool: BOOL { bld.xAst.addNode( AstNode::typeBool, (bool)$1 ); } | ||
| 160 | ; | ||
| 161 | |||
| 162 | null: TOK_NULL { bld.xAst.addNode( AstNode::typeNull ); } | ||
| 163 | |||
| 164 | literal: string | ||
| 165 | | int | ||
| 166 | | float | ||
| 167 | | bool | ||
| 168 | | null | ||
| 169 | ; | ||
| 170 | |||
| 171 | variable: UNDEF /*VARIABLE*/ { bld.xAst.addNode( AstNode::typeVariable, $1 ); } | ||
| 172 | |||
| 173 | list_core: | ||
| 174 | | { bld.xAst.openBranch(); } expr | ||
| 175 | | list_core ',' { bld.xAst.openBranch(); } expr | ||
| 176 | ; | ||
| 177 | |||
| 178 | list: '[' { | ||
| 179 | bld.xAst.addNode( AstNode::typeList ); | ||
| 180 | } list_core ']' { | ||
| 181 | bld.xAst.closeNode(); | ||
| 182 | } | ||
| 183 | ; | ||
| 184 | |||
| 185 | value_mods: | ||
| 186 | | value_mods '.' function | ||
| 187 | ; | ||
| 188 | |||
| 189 | value_core: variable | ||
| 190 | | literal | ||
| 191 | | function | ||
| 192 | | list | ||
| 193 | ; | ||
| 194 | |||
| 195 | value: value_core value_mods | ||
| 196 | ; | ||
| 197 | |||
| 198 | /* | ||
| 199 | * misc global things | ||
| 200 | */ | ||
| 201 | |||
| 202 | notify: TOK_ERROR STRING ';' { bld.xAst.addNode( AstNode::typeError, $2 ); } | ||
| 203 | | TOK_WARNING STRING ';' { bld.xAst.addNode( AstNode::typeWarning, $2 ); } | ||
| 204 | | TOK_NOTICE STRING ';' { bld.xAst.addNode( AstNode::typeNotice, $2 ); } | ||
| 205 | ; | ||
| 206 | /* | ||
| 207 | set_rhs: '=' { bld.xAst.addNode( AstNode::typeOpEq ); } value | ||
| 208 | | OP_ADDSETP { bld.xAst.addNode( AstNode::typeOpPlusEq ); } value | ||
| 209 | | OP_ADDSETR { bld.xAst.addNode( AstNode::typeOpPlusEqRaw ); } string | ||
| 210 | ; | ||
| 211 | |||
| 212 | set: TOK_SET { | ||
| 213 | bld.xAst.addNode( AstNode::typeSet ); | ||
| 214 | bld.xAst.openBranch(); | ||
| 215 | } variable set_rhs ';' { | ||
| 216 | bld.xAst.closeNode(); | ||
| 217 | } | ||
| 218 | ;*/ | ||
| 219 | |||
| 220 | unset: TOK_UNSET { | ||
| 221 | bld.xAst.addNode( AstNode::typeUnset ); | ||
| 222 | bld.xAst.openBranch(); | ||
| 223 | } variable ';' { | ||
| 224 | bld.xAst.closeNode(); | ||
| 225 | } | ||
| 226 | ; | ||
| 227 | |||
| 228 | export_rhs: '=' value | ||
| 229 | | | ||
| 230 | ; | ||
| 231 | |||
| 232 | export: TOK_EXPORT { | ||
| 233 | bld.xAst.addNode( AstNode::typeExport ); | ||
| 234 | bld.xAst.openBranch(); | ||
| 235 | } variable export_rhs ';' { | ||
| 236 | bld.xAst.closeNode(); | ||
| 237 | } | ||
| 238 | ; | ||
| 239 | |||
| 240 | func_params: | ||
| 241 | | func_param_list | ||
| 242 | ; | ||
| 243 | |||
| 244 | func_param_list: { bld.xAst.openBranch(); } value | ||
| 245 | | func_param_list ',' { bld.xAst.openBranch(); } value | ||
| 246 | ; | ||
| 247 | |||
| 248 | function: UNDEF '(' { | ||
| 249 | bld.xAst.addNode( AstNode::typeFunction ); | ||
| 250 | bld.xAst.openBranch(); | ||
| 251 | bld.xAst.addNode( AstNode::typeString, $1 ); | ||
| 252 | } func_params ')' { | ||
| 253 | bld.xAst.closeNode(); | ||
| 254 | } | ||
| 255 | ; | ||
| 256 | |||
| 257 | requires: TOK_REQUIRES { | ||
| 258 | bld.xAst.addNode( AstNode::typeRequires ); | ||
| 259 | bld.xAst.openBranch(); | ||
| 260 | } value ';' { | ||
| 261 | bld.xAst.closeNode(); | ||
| 262 | } | ||
| 263 | ; | ||
| 264 | |||
| 265 | type: TOK_STRING { bld.xAst.addNode( AstNode::typeTypeString ); } | ||
| 266 | | TOK_INT { bld.xAst.addNode( AstNode::typeTypeInt ); } | ||
| 267 | | TOK_FLOAT { bld.xAst.addNode( AstNode::typeTypeFloat ); } | ||
| 268 | | TOK_BOOL { bld.xAst.addNode( AstNode::typeTypeBool ); } | ||
| 269 | | TOK_VERSION { bld.xAst.addNode( AstNode::typeTypeVersion ); } | ||
| 270 | ; | ||
| 271 | |||
| 272 | /* | ||
| 273 | * comparisons | ||
| 274 | */ | ||
| 275 | |||
| 276 | expr: value | ||
| 277 | | '(' expr ')' | ||
| 278 | | UNDEF '=' { | ||
| 279 | bld.xAst.addNode( AstNode::typeVariableRef, $1 ); | ||
| 280 | } expr { | ||
| 281 | bld.xAst.addNode( AstNode::typeOpEq ); | ||
| 282 | } | ||
| 283 | | UNDEF OP_ADDSETP { | ||
| 284 | bld.xAst.addNode( AstNode::typeVariableRef, $1 ); | ||
| 285 | } expr { | ||
| 286 | bld.xAst.addNode( AstNode::typeOpPlusEq ); | ||
| 287 | } | ||
| 288 | | expr OP_CMPEQUAL expr | ||
| 289 | { | ||
| 290 | bld.xAst.addNode( AstNode::typeCmpEq ); | ||
| 291 | } | ||
| 292 | | expr '<' expr | ||
| 293 | { | ||
| 294 | bld.xAst.addNode( AstNode::typeCmpLt ); | ||
| 295 | } | ||
| 296 | | expr '>' expr | ||
| 297 | { | ||
| 298 | bld.xAst.addNode( AstNode::typeCmpGt ); | ||
| 299 | } | ||
| 300 | | expr OP_INEQUAL expr | ||
| 301 | { | ||
| 302 | bld.xAst.addNode( AstNode::typeCmpNe ); | ||
| 303 | } | ||
| 304 | | expr OP_LTEQUAL expr | ||
| 305 | { | ||
| 306 | bld.xAst.addNode( AstNode::typeCmpLtEq ); | ||
| 307 | } | ||
| 308 | | expr OP_GTEQUAL expr | ||
| 309 | { | ||
| 310 | bld.xAst.addNode( AstNode::typeCmpGtEq ); | ||
| 311 | } | ||
| 312 | | expr '+' expr | ||
| 313 | { | ||
| 314 | bld.xAst.addNode( AstNode::typeOpPlus ); | ||
| 315 | } | ||
| 316 | | expr '-' expr | ||
| 317 | { | ||
| 318 | bld.xAst.addNode( AstNode::typeOpMinus ); | ||
| 319 | } | ||
| 320 | | expr '*' expr | ||
| 321 | { | ||
| 322 | bld.xAst.addNode( AstNode::typeOpMultiply ); | ||
| 323 | } | ||
| 324 | | expr '/' expr | ||
| 325 | { | ||
| 326 | bld.xAst.addNode( AstNode::typeOpDivide ); | ||
| 327 | } | ||
| 328 | | '-' expr %prec IINEG | ||
| 329 | { | ||
| 330 | bld.xAst.addNode( AstNode::typeOpNegate ); | ||
| 331 | } | ||
| 332 | | '!' expr %prec IINOT | ||
| 333 | { | ||
| 334 | bld.xAst.addNode( AstNode::typeOpNot ); | ||
| 335 | } | ||
| 336 | ; | ||
| 337 | |||
| 338 | line_expr: { | ||
| 339 | bld.xAst.addNode( AstNode::typeExpr ); | ||
| 340 | bld.xAst.openBranch(); | ||
| 341 | } expr ';' | ||
| 342 | { | ||
| 343 | bld.xAst.closeNode(); | ||
| 344 | } | ||
| 345 | ; | ||
| 346 | |||
| 347 | if_core: TOK_IF { | ||
| 348 | bld.xAst.addNode( AstNode::typeIf ); | ||
| 349 | bld.xAst.openBranch(); | ||
| 350 | // bld.xAst.addNode( AstNode::typeExpr ); | ||
| 351 | // bld.xAst.openBranch(); | ||
| 352 | } expr TOK_THEN { | ||
| 353 | // bld.xAst.closeNode(); | ||
| 354 | bld.xAst.openBranch(); | ||
| 355 | } | ||
| 356 | ; | ||
| 357 | |||
| 358 | else: TOK_ELSE { bld.xAst.openBranch(); } | ||
| 359 | ; | ||
| 360 | |||
| 361 | root_if: if_core '{' root_sub_exprs '}' root_else { bld.xAst.closeNode(); } | ||
| 362 | ; | ||
| 363 | |||
| 364 | root_else: | ||
| 365 | | else '{' root_sub_exprs '}' | ||
| 366 | | else root_if | ||
| 367 | ; | ||
| 368 | |||
| 369 | target_if: if_core '{' target_exprs '}' target_else { bld.xAst.closeNode(); } | ||
| 370 | ; | ||
| 371 | |||
| 372 | target_else: | ||
| 373 | | else '{' target_exprs '}' | ||
| 374 | | else target_if | ||
| 375 | ; | ||
| 376 | |||
| 377 | rule_if: if_core '{' rule_exprs '}' rule_else { bld.xAst.closeNode(); } | ||
| 378 | ; | ||
| 379 | |||
| 380 | rule_else: | ||
| 381 | | else '{' rule_exprs '}' | ||
| 382 | | else rule_if | ||
| 383 | ; | ||
| 384 | |||
| 385 | function_if: if_core '{' function_exprs '}' function_else | ||
| 386 | { bld.xAst.closeNode(); } | ||
| 387 | ; | ||
| 388 | |||
| 389 | function_else: | ||
| 390 | | else '{' function_exprs '}' | ||
| 391 | | else function_if | ||
| 392 | ; | ||
| 393 | |||
| 394 | /* | ||
| 395 | * loops | ||
| 396 | */ | ||
| 397 | |||
| 398 | for_base: TOK_FOR { | ||
| 399 | bld.xAst.addNode( AstNode::typeFor ); | ||
| 400 | bld.xAst.openBranch(); | ||
| 401 | } variable TOK_IN { | ||
| 402 | bld.xAst.openBranch(); | ||
| 403 | } value TOK_DO { | ||
| 404 | bld.xAst.openBranch(); | ||
| 405 | } | ||
| 406 | ; | ||
| 407 | |||
| 408 | root_for: for_base '{' root_sub_exprs '}' { bld.xAst.closeNode(); } | ||
| 409 | ; | ||
| 410 | |||
| 411 | target_for: for_base '{' target_exprs '}' { bld.xAst.closeNode(); } | ||
| 412 | ; | ||
| 413 | |||
| 414 | rule_for: for_base '{' rule_exprs '}' { bld.xAst.closeNode(); } | ||
| 415 | ; | ||
| 416 | |||
| 417 | function_for: for_base '{' function_exprs '}' { bld.xAst.closeNode(); } | ||
| 418 | ; | ||
| 419 | |||
| 420 | /* | ||
| 421 | * functions | ||
| 422 | */ | ||
| 423 | |||
| 424 | function_def: TOK_FUNCTION UNDEF { | ||
| 425 | bld.xAst.addNode( AstNode::typeFunctionDef ); | ||
| 426 | bld.xAst.openBranch(); | ||
| 427 | bld.xAst.addNode( AstNode::typeString, $2 ); | ||
| 428 | bld.xAst.openBranch(); | ||
| 429 | } '(' param_defs ')' { | ||
| 430 | bld.xAst.openBranch(); | ||
| 431 | } '{' function_exprs '}' { | ||
| 432 | bld.xAst.closeNode(); | ||
| 433 | } | ||
| 434 | ; | ||
| 435 | |||
| 436 | param_defs: | ||
| 437 | | param_def_list | ||
| 438 | ; | ||
| 439 | |||
| 440 | param_def_list: variable | ||
| 441 | | param_def_list ',' variable | ||
| 442 | ; | ||
| 443 | |||
| 444 | function_exprs: | ||
| 445 | // | function_exprs function ';' | ||
| 446 | // | function_exprs set | ||
| 447 | | function_exprs unset | ||
| 448 | | function_exprs line_expr | ||
| 449 | | function_exprs export | ||
| 450 | | function_exprs notify | ||
| 451 | | function_exprs function_if | ||
| 452 | | function_exprs function_for | ||
| 453 | | function_exprs return | ||
| 454 | | function_exprs process_target | ||
| 455 | ; | ||
| 456 | |||
| 457 | return: TOK_RETURN { | ||
| 458 | bld.xAst.addNode( AstNode::typeReturn ); | ||
| 459 | bld.xAst.openBranch(); | ||
| 460 | } expr { | ||
| 461 | bld.xAst.closeNode(); | ||
| 462 | } ';' | ||
| 463 | ; | ||
| 464 | |||
| 465 | /* | ||
| 466 | * Actions, they're basically functions, no parameters | ||
| 467 | */ | ||
| 468 | |||
| 469 | action_def: TOK_ACTION STRING { | ||
| 470 | bld.xAst.addNode( AstNode::typeActionDef ); | ||
| 471 | bld.xAst.openBranch(); | ||
| 472 | bld.xAst.addNode( AstNode::typeString, $2 ); | ||
| 473 | bld.xAst.openBranch(); | ||
| 474 | } '{' function_exprs '}' { | ||
| 475 | bld.xAst.closeNode(); | ||
| 476 | } | ||
| 477 | ; | ||
| 478 | |||
| 479 | /* | ||
| 480 | * profiles | ||
| 481 | */ | ||
| 482 | |||
| 483 | profile: TOK_PROFILE { | ||
| 484 | bld.xAst.addNode( AstNode::typeProfile ); | ||
| 485 | bld.xAst.openBranch(); | ||
| 486 | } string { | ||
| 487 | bld.xAst.openBranch(); | ||
| 488 | } '{' profile_exprs '}' { | ||
| 489 | bld.xAst.closeNode(); | ||
| 490 | } /* in-line function */ | ||
| 491 | ; | ||
| 492 | |||
| 493 | profile_exprs: | ||
| 494 | // | profile_exprs function ';' | ||
| 495 | // | profile_exprs set | ||
| 496 | | profile_exprs unset | ||
| 497 | | profile_exprs line_expr | ||
| 498 | | profile_exprs export | ||
| 499 | | profile_exprs notify | ||
| 500 | | profile_exprs function_if | ||
| 501 | | profile_exprs function_for | ||
| 502 | | profile_exprs return | ||
| 503 | | profile_exprs process_target | ||
| 504 | | profile_exprs condition | ||
| 505 | ; | ||
| 506 | /* | ||
| 507 | * targets | ||
| 508 | */ | ||
| 509 | |||
| 510 | target: TOK_TARGET { | ||
| 511 | bld.xAst.addNode( AstNode::typeTarget ); | ||
| 512 | bld.xAst.openBranch(); | ||
| 513 | } expr { | ||
| 514 | bld.xAst.openBranch(); | ||
| 515 | } '{' target_exprs '}' { | ||
| 516 | bld.xAst.closeNode(); | ||
| 517 | } | ||
| 518 | ; | ||
| 519 | |||
| 520 | target_exprs: | ||
| 521 | // | target_exprs set | ||
| 522 | | target_exprs unset | ||
| 523 | | target_exprs line_expr | ||
| 524 | | target_exprs export | ||
| 525 | | target_exprs target_input | ||
| 526 | | target_exprs requires | ||
| 527 | | target_exprs profile | ||
| 528 | | target_exprs target_if | ||
| 529 | | target_exprs target_for | ||
| 530 | | target_exprs notify | ||
| 531 | | target_exprs target_rule | ||
| 532 | | target_exprs tag | ||
| 533 | | target_exprs display | ||
| 534 | ; | ||
| 535 | |||
| 536 | target_input: TOK_INPUT { | ||
| 537 | bld.xAst.addNode( AstNode::typeInput ); | ||
| 538 | bld.xAst.openBranch(); | ||
| 539 | } expr ';' { | ||
| 540 | bld.xAst.closeNode(); | ||
| 541 | } | ||
| 542 | ; | ||
| 543 | |||
| 544 | target_rule: TOK_RULE { | ||
| 545 | bld.xAst.addNode( AstNode::typeRule ); | ||
| 546 | bld.xAst.openBranch(); | ||
| 547 | } string ';' { | ||
| 548 | bld.xAst.closeNode(); | ||
| 549 | } | ||
| 550 | ; | ||
| 551 | |||
| 552 | condition: TOK_CONDITION CONDITION ';' { | ||
| 553 | bld.xAst.addNode( AstNode::typeCondition, $2 ); | ||
| 554 | } | ||
| 555 | | TOK_CONDITION TOK_ALWAYS ';'{ | ||
| 556 | bld.xAst.addNode( AstNode::typeCondition, "always" ); | ||
| 557 | } | ||
| 558 | | TOK_CONDITION TOK_NEVER ';'{ | ||
| 559 | bld.xAst.addNode( AstNode::typeCondition, "never" ); | ||
| 560 | } | ||
| 561 | ; | ||
| 562 | |||
| 563 | /* | ||
| 564 | * rules | ||
| 565 | */ | ||
| 566 | |||
| 567 | rule: TOK_RULE { | ||
| 568 | bld.xAst.addNode( AstNode::typeRuleDef ); | ||
| 569 | bld.xAst.openBranch(); | ||
| 570 | } string { | ||
| 571 | bld.xAst.openBranch(); | ||
| 572 | } '{' rule_exprs '}' { | ||
| 573 | bld.xAst.closeNode(); | ||
| 574 | } | ||
| 575 | ; | ||
| 576 | |||
| 577 | rule_exprs: | ||
| 578 | | rule_exprs rule_input | ||
| 579 | | rule_exprs output | ||
| 580 | | rule_exprs requires | ||
| 581 | | rule_exprs profile | ||
| 582 | | rule_exprs rule_if | ||
| 583 | | rule_exprs rule_for | ||
| 584 | | rule_exprs notify | ||
| 585 | | rule_exprs display | ||
| 586 | | rule_exprs tag | ||
| 587 | // | rule_exprs set | ||
| 588 | ; | ||
| 589 | |||
| 590 | rule_input_func: function | ||
| 591 | | STRING { | ||
| 592 | /* In this case, when the input is just a string, | ||
| 593 | lets actually turn it into a call to the matches function. | ||
| 594 | */ | ||
| 595 | bld.xAst.addNode( AstNode::typeFunction ); | ||
| 596 | bld.xAst.openBranch(); | ||
| 597 | bld.xAst.addNode( AstNode::typeString, "matches" ); | ||
| 598 | bld.xAst.openBranch(); | ||
| 599 | bld.xAst.addNode( AstNode::typeString, $1 ); | ||
| 600 | bld.xAst.closeNode(); | ||
| 601 | } | ||
| 602 | /* | string */ | ||
| 603 | ; | ||
| 604 | |||
| 605 | rule_input: TOK_INPUT { | ||
| 606 | bld.xAst.addNode( AstNode::typeInput ); | ||
| 607 | bld.xAst.openBranch(); | ||
| 608 | } rule_input_func ';' { | ||
| 609 | bld.xAst.closeNode(); | ||
| 610 | } | ||
| 611 | ; | ||
| 612 | |||
| 613 | output: TOK_OUTPUT { | ||
| 614 | bld.xAst.addNode( AstNode::typeOutput ); | ||
| 615 | bld.xAst.openBranch(); | ||
| 616 | } value ';' { | ||
| 617 | bld.xAst.closeNode(); | ||
| 618 | } | ||
| 619 | ; | ||
| 620 | |||
| 621 | /* | ||
| 622 | * config | ||
| 623 | */ | ||
| 624 | config: TOK_CONFIG { | ||
| 625 | bld.xAst.addNode( AstNode::typeConfig ); | ||
| 626 | bld.xAst.openBranch(); | ||
| 627 | } string { | ||
| 628 | bld.xAst.openBranch(); | ||
| 629 | } '{' config_exprs '}' { | ||
| 630 | bld.xAst.closeNode(); | ||
| 631 | } | ||
| 632 | | TOK_AUTO TOK_CONFIG { | ||
| 633 | bld.xAst.addNode( AstNode::typeAutoConfig ); | ||
| 634 | bld.xAst.openBranch(); | ||
| 635 | } string { | ||
| 636 | bld.xAst.openBranch(); | ||
| 637 | } '{' config_exprs '}' { | ||
| 638 | bld.xAst.closeNode(); | ||
| 639 | } | ||
| 640 | | TOK_GLOBAL TOK_CONFIG { | ||
| 641 | bld.xAst.addNode( AstNode::typeGlobalConfig ); | ||
| 642 | bld.xAst.openBranch(); | ||
| 643 | } string { | ||
| 644 | bld.xAst.openBranch(); | ||
| 645 | } '{' config_exprs '}' { | ||
| 646 | bld.xAst.closeNode(); | ||
| 647 | } | ||
| 648 | ; | ||
| 649 | |||
| 650 | config_exprs: | ||
| 651 | | config_exprs display | ||
| 652 | | config_exprs config_type | ||
| 653 | | config_exprs default | ||
| 654 | | config_exprs value_key | ||
| 655 | | config_exprs allow | ||
| 656 | | config_exprs cache | ||
| 657 | ; | ||
| 658 | |||
| 659 | display: TOK_DISPLAY STRING ';' { | ||
| 660 | bld.xAst.addNode( AstNode::typeDisplay, $2 ); | ||
| 661 | } | ||
| 662 | ; | ||
| 663 | |||
| 664 | config_type: TOK_TYPE { | ||
| 665 | bld.xAst.addNode( AstNode::typeType ); | ||
| 666 | bld.xAst.openBranch(); | ||
| 667 | } type ';' { | ||
| 668 | bld.xAst.closeNode(); | ||
| 669 | } | ||
| 670 | ; | ||
| 671 | |||
| 672 | default: TOK_DEFAULT { | ||
| 673 | bld.xAst.addNode( AstNode::typeDefault ); | ||
| 674 | bld.xAst.openBranch(); | ||
| 675 | } literal ';' { | ||
| 676 | bld.xAst.closeNode(); | ||
| 677 | } | ||
| 678 | ; | ||
| 679 | |||
| 680 | value_key_val: value ';' | ||
| 681 | | '{' function_exprs '}' /* inline function */ | ||
| 682 | |||
| 683 | value_key: TOK_VALUE { | ||
| 684 | bld.xAst.addNode( AstNode::typeValue ); | ||
| 685 | bld.xAst.openBranch(); | ||
| 686 | } value_key_val { | ||
| 687 | bld.xAst.closeNode(); | ||
| 688 | } | ||
| 689 | ; | ||
| 690 | |||
| 691 | allow: TOK_ALLOW { | ||
| 692 | bld.xAst.addNode( AstNode::typeAllow ); | ||
| 693 | bld.xAst.openBranch(); | ||
| 694 | } value ';' { | ||
| 695 | bld.xAst.closeNode(); | ||
| 696 | } | ||
| 697 | ; | ||
| 698 | |||
| 699 | cache: TOK_CACHE TOK_ALWAYS ';' | ||
| 700 | { bld.xAst.addNode( AstNode::typeCache, true ); } | ||
| 701 | | TOK_CACHE TOK_NEVER ';' | ||
| 702 | { bld.xAst.addNode( AstNode::typeCache, false ); } | ||
| 703 | ; | ||
| 704 | |||
| 705 | /* | ||
| 706 | * target/profile execute | ||
| 707 | */ | ||
| 708 | process_target: PROFILE | ||
| 709 | { | ||
| 710 | bld.xAst.addNode( AstNode::typeProcessTarget ); | ||
| 711 | bld.xAst.openBranch(); | ||
| 712 | bld.xAst.addNode( AstNode::typeString, $1 ); | ||
| 713 | bld.xAst.openBranch(); | ||
| 714 | } value ';' { | ||
| 715 | bld.xAst.closeNode(); | ||
| 716 | } | ||
| 717 | ; | ||
| 718 | |||
| 719 | tag: TOK_TAG | ||
| 720 | { | ||
| 721 | bld.xAst.addNode( AstNode::typeTag ); | ||
| 722 | bld.xAst.openBranch(); | ||
| 723 | } value ';' { | ||
| 724 | bld.xAst.closeNode(); | ||
| 725 | } | ||
| 726 | ; | ||
| 727 | |||
| 728 | |||
| 729 | %% | ||
| 730 | |||
| 731 | /* Epilogue -- whatever you want, functions mainly */ | ||
| 732 | |||
| 733 | void build_error( YYLTYPE *locp, yyscan_t, BuildParser &bld, const char *msg ) | ||
| 734 | { | ||
| 735 | bld.error( | ||
| 736 | locp->first_line, locp->last_line, | ||
| 737 | locp->first_column, locp->last_column, | ||
| 738 | msg | ||
| 739 | ); | ||
| 740 | } | ||
| 741 | |||
diff --git a/src/buildparser.cpp b/src/buildparser.cpp new file mode 100644 index 0000000..e391523 --- /dev/null +++ b/src/buildparser.cpp | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | #include "buildparser.h" | ||
| 2 | #include "ast.h" | ||
| 3 | #include "build.yy.h" | ||
| 4 | |||
| 5 | #include "bu/sio.h" | ||
| 6 | using Bu::sio; | ||
| 7 | |||
| 8 | BuildParser::BuildParser( Ast &rAst ) : | ||
| 9 | xAst( rAst ) | ||
| 10 | { | ||
| 11 | lIncludePaths.append("./"); | ||
| 12 | } | ||
| 13 | |||
| 14 | BuildParser::~BuildParser() | ||
| 15 | { | ||
| 16 | } | ||
| 17 | |||
| 18 | int build_parse( yyscan_t yyscanner, BuildParser &bld ); | ||
| 19 | |||
| 20 | void BuildParser::load( const Bu::FString &sFile ) | ||
| 21 | { | ||
| 22 | yyscan_t scanner; | ||
| 23 | |||
| 24 | sFilename.push( sFile ); | ||
| 25 | FILE *fIn = fopen( sFile.getStr(), "rt" ); | ||
| 26 | build_lex_init( &scanner ); | ||
| 27 | // build_set_debug( true, scanner ); | ||
| 28 | build_set_in( fIn, scanner ); | ||
| 29 | |||
| 30 | build_parse( scanner, *this ); | ||
| 31 | |||
| 32 | build_lex_destroy( scanner ); | ||
| 33 | fclose( fIn ); | ||
| 34 | |||
| 35 | // Bu::sio << xAst; | ||
| 36 | } | ||
| 37 | |||
| 38 | bool BuildParser::isKeyword( const Bu::FString &sStr ) | ||
| 39 | { | ||
| 40 | if( sStr == "important" ) | ||
| 41 | return true; | ||
| 42 | if( sStr == "normal" ) | ||
| 43 | return true; | ||
| 44 | if( sStr == "hidden" ) | ||
| 45 | return true; | ||
| 46 | if( sStr == "autogenerated" ) | ||
| 47 | return true; | ||
| 48 | return false; | ||
| 49 | } | ||
| 50 | |||
| 51 | bool BuildParser::isCond( const Bu::FString &sStr ) | ||
| 52 | { | ||
| 53 | if( sStr == "filetime" ) | ||
| 54 | return true; | ||
| 55 | if( sStr == "always" ) | ||
| 56 | return true; | ||
| 57 | if( sStr == "never" ) | ||
| 58 | return true; | ||
| 59 | return false; | ||
| 60 | } | ||
| 61 | |||
| 62 | void BuildParser::include( const Bu::FString &sStr, void *scanner, YYLTYPE *loc ) | ||
| 63 | { | ||
| 64 | for( StrList::iterator pi = lIncludePaths.begin(); pi; pi++ ) | ||
| 65 | { | ||
| 66 | FILE *fIn = fopen( (*pi + sStr).getStr(), "rt" ); | ||
| 67 | if( fIn == NULL ) | ||
| 68 | { | ||
| 69 | continue; | ||
| 70 | } | ||
| 71 | sFilename.push( sStr ); | ||
| 72 | sLocation.push( *loc ); | ||
| 73 | loc->first_line = loc->last_line = 1; | ||
| 74 | loc->first_column = loc->last_column = 0; | ||
| 75 | build_push_buffer_state( | ||
| 76 | build__create_buffer( fIn, YY_READ_BUF_SIZE, scanner ), | ||
| 77 | scanner | ||
| 78 | ); | ||
| 79 | Bu::FString::const_iterator i = sStr.find('/'); | ||
| 80 | if( i ) | ||
| 81 | { | ||
| 82 | for(;;) | ||
| 83 | { | ||
| 84 | Bu::FString::const_iterator j = i.find('/'); | ||
| 85 | if( !j ) | ||
| 86 | break; | ||
| 87 | i = j+1; | ||
| 88 | } | ||
| 89 | sio << "Hey, found it from here: " << sStr.getSubStr( sStr.begin(), i ) << sio.nl; | ||
| 90 | xAst.addNode( AstNode::typePushPrefix, sStr.getSubStr( sStr.begin(), i ) ); | ||
| 91 | } | ||
| 92 | else | ||
| 93 | { | ||
| 94 | xAst.addNode( AstNode::typePushPrefix, "" ); | ||
| 95 | } | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | Bu::FString msg("Could not open include file: "); | ||
| 99 | msg += sStr; | ||
| 100 | error( | ||
| 101 | loc->first_line, loc->last_line, | ||
| 102 | loc->first_column, loc->last_column, | ||
| 103 | msg | ||
| 104 | ); | ||
| 105 | } | ||
| 106 | |||
| 107 | void BuildParser::endInclude( YYLTYPE *loc ) | ||
| 108 | { | ||
| 109 | sFilename.pop(); | ||
| 110 | memcpy( loc, &sLocation.peek(), sizeof(YYLTYPE) ); | ||
| 111 | sLocation.pop(); | ||
| 112 | xAst.addNode( AstNode::typePopPrefix ); | ||
| 113 | } | ||
| 114 | |||
| 115 | void BuildParser::error( int iLine1, int iLine2, int iCol1, int iCol2, | ||
| 116 | const Bu::FString &sMsg ) | ||
| 117 | { | ||
| 118 | throw Bu::ExceptionBase("%s: %d-%d:%d-%d: %s", | ||
| 119 | sFilename.peek().getStr(), iLine1, iLine2, iCol1, iCol2, sMsg.getStr() | ||
| 120 | ); | ||
| 121 | } | ||
| 122 | |||
| 123 | void BuildParser::addIncludePath( const Bu::FString &sPath ) | ||
| 124 | { | ||
| 125 | lIncludePaths.append( sPath + "/" ); | ||
| 126 | } | ||
| 127 | |||
diff --git a/src/buildparser.h b/src/buildparser.h new file mode 100644 index 0000000..8e2af6c --- /dev/null +++ b/src/buildparser.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | #ifndef BUILD_PARSER_H | ||
| 2 | #define BUILD_PARSER_H | ||
| 3 | |||
| 4 | #include "build.tab.h" | ||
| 5 | |||
| 6 | #include "bu/stack.h" | ||
| 7 | #include "bu/fstring.h" | ||
| 8 | #include "types.h" | ||
| 9 | |||
| 10 | class BuildParser | ||
| 11 | { | ||
| 12 | public: | ||
| 13 | BuildParser( class Ast &rAst ); | ||
| 14 | virtual ~BuildParser(); | ||
| 15 | |||
| 16 | void load( const Bu::FString &sFile ); | ||
| 17 | |||
| 18 | bool isKeyword( const Bu::FString &sStr ); | ||
| 19 | bool isCond( const Bu::FString &sStr ); | ||
| 20 | void include( const Bu::FString &sStr, void *scanner, YYLTYPE *loc ); | ||
| 21 | void endInclude( YYLTYPE *loc ); | ||
| 22 | |||
| 23 | void error( int iLine1, int iLine2, int iCol1, int iCol2, | ||
| 24 | const Bu::FString &sMsg ); | ||
| 25 | |||
| 26 | class Ast &xAst; | ||
| 27 | |||
| 28 | void addIncludePath( const Bu::FString &sPath ); | ||
| 29 | |||
| 30 | private: | ||
| 31 | Bu::Stack<Bu::FString> sFilename; | ||
| 32 | Bu::Stack<YYLTYPE> sLocation; | ||
| 33 | StrList lIncludePaths; | ||
| 34 | }; | ||
| 35 | |||
| 36 | typedef void * yyscan_t; | ||
| 37 | #define YY_DECL int build_lex( YYSTYPE *yylval_param, YYLTYPE *yylloc_param, yyscan_t yyscanner, BuildParser &b ) | ||
| 38 | YY_DECL; | ||
| 39 | |||
| 40 | #endif | ||
diff --git a/src/condition.cpp b/src/condition.cpp new file mode 100644 index 0000000..ec87c0e --- /dev/null +++ b/src/condition.cpp | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #include "condition.h" | ||
| 2 | |||
| 3 | Condition::Condition() | ||
| 4 | { | ||
| 5 | } | ||
| 6 | |||
| 7 | Condition::~Condition() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
diff --git a/src/condition.h b/src/condition.h new file mode 100644 index 0000000..2e9b26a --- /dev/null +++ b/src/condition.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef CONDITION_H | ||
| 2 | #define CONDITION_H | ||
| 3 | |||
| 4 | class Condition | ||
| 5 | { | ||
| 6 | public: | ||
| 7 | Condition(); | ||
| 8 | virtual ~Condition(); | ||
| 9 | |||
| 10 | virtual bool shouldExec( class Runner &r, class Target &rTarget )=0; | ||
| 11 | virtual Condition *clone()=0; | ||
| 12 | |||
| 13 | private: | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/conditionalways.cpp b/src/conditionalways.cpp new file mode 100644 index 0000000..077b5b5 --- /dev/null +++ b/src/conditionalways.cpp | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #include "conditionalways.h" | ||
| 2 | #include "target.h" | ||
| 3 | |||
| 4 | ConditionAlways::ConditionAlways() | ||
| 5 | { | ||
| 6 | } | ||
| 7 | |||
| 8 | ConditionAlways::~ConditionAlways() | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | bool ConditionAlways::shouldExec( class Runner &/*r*/, Target &/*rTarget*/ ) | ||
| 13 | { | ||
| 14 | return true; | ||
| 15 | } | ||
| 16 | |||
| 17 | Condition *ConditionAlways::clone() | ||
| 18 | { | ||
| 19 | return new ConditionAlways(); | ||
| 20 | } | ||
| 21 | |||
diff --git a/src/conditionalways.h b/src/conditionalways.h new file mode 100644 index 0000000..1eeeb71 --- /dev/null +++ b/src/conditionalways.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef CONDITION_ALWAYS_H | ||
| 2 | #define CONDITION_ALWAYS_H | ||
| 3 | |||
| 4 | #include "condition.h" | ||
| 5 | |||
| 6 | class ConditionAlways : public Condition | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | ConditionAlways(); | ||
| 10 | virtual ~ConditionAlways(); | ||
| 11 | |||
| 12 | virtual bool shouldExec( class Runner &r, class Target &rTarget ); | ||
| 13 | virtual Condition *clone(); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/conditionfiletime.cpp b/src/conditionfiletime.cpp new file mode 100644 index 0000000..224caf1 --- /dev/null +++ b/src/conditionfiletime.cpp | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | #include "conditionfiletime.h" | ||
| 2 | #include "target.h" | ||
| 3 | |||
| 4 | #include <sys/types.h> | ||
| 5 | #include <sys/stat.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | |||
| 8 | #include <bu/sio.h> | ||
| 9 | using namespace Bu; | ||
| 10 | |||
| 11 | ConditionFileTime::ConditionFileTime() | ||
| 12 | { | ||
| 13 | } | ||
| 14 | |||
| 15 | ConditionFileTime::~ConditionFileTime() | ||
| 16 | { | ||
| 17 | } | ||
| 18 | |||
| 19 | bool ConditionFileTime::shouldExec( class Runner &r, Target &rTarget ) | ||
| 20 | { | ||
| 21 | for( StrList::const_iterator j = rTarget.getOutputList().begin(); j; j++ ) | ||
| 22 | { | ||
| 23 | if( access( (*j).getStr(), F_OK ) ) | ||
| 24 | { | ||
| 25 | //sio << "-- Target processed because '" << *j << "' doesn't exist." | ||
| 26 | // << sio.nl; | ||
| 27 | // Output doesn't exist | ||
| 28 | return true; | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | time_t tOut = 0; | ||
| 33 | struct stat s; | ||
| 34 | for( StrList::const_iterator j = rTarget.getOutputList().begin(); | ||
| 35 | j; j++ ) | ||
| 36 | { | ||
| 37 | stat( (*j).getStr(), &s ); | ||
| 38 | if( tOut == 0 || tOut > s.st_mtime ) | ||
| 39 | { | ||
| 40 | tOut = s.st_mtime; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | for( StrList::const_iterator j = rTarget.getInputList().begin(); | ||
| 44 | j; j++ ) | ||
| 45 | { | ||
| 46 | stat( (*j).getStr(), &s ); | ||
| 47 | if( tOut < s.st_mtime ) | ||
| 48 | { | ||
| 49 | //sio << "-- Target processed because '" << *j | ||
| 50 | // << "' is newer than output." << sio.nl; | ||
| 51 | return true; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | rTarget.buildRequires( r ); | ||
| 55 | for( StrList::const_iterator j = rTarget.getRequiresList().begin(); | ||
| 56 | j; j++ ) | ||
| 57 | { | ||
| 58 | stat( (*j).getStr(), &s ); | ||
| 59 | if( tOut < s.st_mtime ) | ||
| 60 | { | ||
| 61 | //sio << "-- Target processed because '" << *j | ||
| 62 | // << "' is newer than output." << sio.nl; | ||
| 63 | return true; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | return false; | ||
| 67 | } | ||
| 68 | |||
| 69 | Condition *ConditionFileTime::clone() | ||
| 70 | { | ||
| 71 | return new ConditionFileTime(); | ||
| 72 | } | ||
| 73 | |||
diff --git a/src/conditionfiletime.h b/src/conditionfiletime.h new file mode 100644 index 0000000..6fb2e9d --- /dev/null +++ b/src/conditionfiletime.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef CONDITION_FILE_TIME_H | ||
| 2 | #define CONDITION_FILE_TIME_H | ||
| 3 | |||
| 4 | #include "condition.h" | ||
| 5 | |||
| 6 | class ConditionFileTime : public Condition | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | ConditionFileTime(); | ||
| 10 | virtual ~ConditionFileTime(); | ||
| 11 | |||
| 12 | virtual bool shouldExec( class Runner &r, class Target &rTarget ); | ||
| 13 | virtual Condition *clone(); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/conditionnever.cpp b/src/conditionnever.cpp new file mode 100644 index 0000000..1ab4375 --- /dev/null +++ b/src/conditionnever.cpp | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #include "conditionnever.h" | ||
| 2 | #include "target.h" | ||
| 3 | |||
| 4 | ConditionNever::ConditionNever() | ||
| 5 | { | ||
| 6 | } | ||
| 7 | |||
| 8 | ConditionNever::~ConditionNever() | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | bool ConditionNever::shouldExec( class Runner &/*r*/, Target &/*rTarget*/ ) | ||
| 13 | { | ||
| 14 | return false; | ||
| 15 | } | ||
| 16 | |||
| 17 | Condition *ConditionNever::clone() | ||
| 18 | { | ||
| 19 | return new ConditionNever(); | ||
| 20 | } | ||
| 21 | |||
diff --git a/src/conditionnever.h b/src/conditionnever.h new file mode 100644 index 0000000..b7e5e92 --- /dev/null +++ b/src/conditionnever.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef CONDITION_NEVER_H | ||
| 2 | #define CONDITION_NEVER_H | ||
| 3 | |||
| 4 | #include "condition.h" | ||
| 5 | |||
| 6 | class ConditionNever : public Condition | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | ConditionNever(); | ||
| 10 | virtual ~ConditionNever(); | ||
| 11 | |||
| 12 | virtual bool shouldExec( class Runner &r, class Target &rTarget ); | ||
| 13 | virtual Condition *clone(); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/context.cpp b/src/context.cpp new file mode 100644 index 0000000..c257a75 --- /dev/null +++ b/src/context.cpp | |||
| @@ -0,0 +1,524 @@ | |||
| 1 | #include "context.h" | ||
| 2 | #include "target.h" | ||
| 3 | #include "rule.h" | ||
| 4 | #include "function.h" | ||
| 5 | #include "runner.h" | ||
| 6 | #include "action.h" | ||
| 7 | #include "profile.h" | ||
| 8 | #include "view.h" | ||
| 9 | |||
| 10 | #include "functionreplace.h" | ||
| 11 | #include "functionexists.h" | ||
| 12 | #include "functionfiles.h" | ||
| 13 | #include "functionexecute.h" | ||
| 14 | #include "functionmatches.h" | ||
| 15 | #include "functiontostring.h" | ||
| 16 | #include "functionunlink.h" | ||
| 17 | #include "functiontargets.h" | ||
| 18 | #include "functiondirs.h" | ||
| 19 | #include "functiongetmakedeps.h" | ||
| 20 | #include "functionfilename.h" | ||
| 21 | #include "functiondirname.h" | ||
| 22 | |||
| 23 | #include <bu/process.h> | ||
| 24 | #include <bu/sio.h> | ||
| 25 | using namespace Bu; | ||
| 26 | |||
| 27 | Context::Context() : | ||
| 28 | pView( NULL ) | ||
| 29 | { | ||
| 30 | addFunction( new FunctionReplace() ); | ||
| 31 | addFunction( new FunctionExists() ); | ||
| 32 | addFunction( new FunctionFiles() ); | ||
| 33 | addFunction( new FunctionExecute() ); | ||
| 34 | addFunction( new FunctionMatches() ); | ||
| 35 | addFunction( new FunctionToString() ); | ||
| 36 | addFunction( new FunctionUnlink() ); | ||
| 37 | addFunction( new FunctionTargets() ); | ||
| 38 | addFunction( new FunctionDirs() ); | ||
| 39 | addFunction( new FunctionGetMakeDeps() ); | ||
| 40 | addFunction( new FunctionFileName() ); | ||
| 41 | addFunction( new FunctionDirName() ); | ||
| 42 | pushScope(); | ||
| 43 | } | ||
| 44 | |||
| 45 | Context::~Context() | ||
| 46 | { | ||
| 47 | } | ||
| 48 | |||
| 49 | void Context::addTarget( Target *pTarget ) | ||
| 50 | { | ||
| 51 | for( StrList::const_iterator i = pTarget->getOutputList().begin(); i; i++ ) | ||
| 52 | { | ||
| 53 | hTarget.insert( (*i).getStr(), pTarget ); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | void Context::addRule( Rule *pRule ) | ||
| 58 | { | ||
| 59 | hRule.insert( pRule->getName(), pRule ); | ||
| 60 | } | ||
| 61 | |||
| 62 | void Context::addFunction( Function *pFunction ) | ||
| 63 | { | ||
| 64 | pFunction->setContext( this ); | ||
| 65 | hFunction.insert( pFunction->getName(), pFunction ); | ||
| 66 | } | ||
| 67 | |||
| 68 | void Context::addVariable( const Bu::FString &sName, const Variable &vValue ) | ||
| 69 | { | ||
| 70 | for( ScopeStack::iterator i = sVars.begin(); i; i++ ) | ||
| 71 | { | ||
| 72 | if( (*i).has( sName ) ) | ||
| 73 | { | ||
| 74 | // sio << "Replacing higher scope variable \"" << sName << "\" with value \"" << (*i).get( sName ) << "\" with new value \"" << vValue << "\"" << sio.nl; | ||
| 75 | (*i).insert( sName, vValue ); | ||
| 76 | return; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | sVars.first().insert( sName, vValue ); | ||
| 80 | } | ||
| 81 | |||
| 82 | void Context::addAction( Action *pAction ) | ||
| 83 | { | ||
| 84 | hAction.insert( pAction->getName(), pAction ); | ||
| 85 | } | ||
| 86 | |||
| 87 | Action *Context::getAction( const Bu::FString &sName ) | ||
| 88 | { | ||
| 89 | return hAction.get( sName ); | ||
| 90 | } | ||
| 91 | |||
| 92 | void Context::addTargetToTag( Target *pTarget, const Bu::FString &sTag ) | ||
| 93 | { | ||
| 94 | if( !hTag.has( sTag ) ) | ||
| 95 | { | ||
| 96 | hTag.insert( sTag, TargetList() ); | ||
| 97 | } | ||
| 98 | hTag.get( sTag ).append( pTarget ); | ||
| 99 | } | ||
| 100 | |||
| 101 | void Context::addTargetToTags( Target *pTarget, const StrList &sTags ) | ||
| 102 | { | ||
| 103 | for( StrList::const_iterator i = sTags.begin(); i; i++ ) | ||
| 104 | { | ||
| 105 | addTargetToTag( pTarget, *i ); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | TargetList &Context::getTag( const Bu::FString &sTag ) | ||
| 110 | { | ||
| 111 | return hTag.get( sTag ); | ||
| 112 | } | ||
| 113 | |||
| 114 | Variable &Context::getVariable( const Bu::FString &sName ) | ||
| 115 | { | ||
| 116 | for( ScopeStack::iterator i = sVars.begin(); i; i++ ) | ||
| 117 | { | ||
| 118 | if( (*i).has( sName ) ) | ||
| 119 | { | ||
| 120 | return (*i).get( sName ); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | throw Bu::ExceptionBase("No such variable."); | ||
| 124 | } | ||
| 125 | |||
| 126 | void Context::delVariable( const Bu::FString &sName ) | ||
| 127 | { | ||
| 128 | for( ScopeStack::iterator i = sVars.begin(); i; i++ ) | ||
| 129 | { | ||
| 130 | if( (*i).has( sName ) ) | ||
| 131 | { | ||
| 132 | (*i).erase( sName ); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | void Context::pushScope() | ||
| 138 | { | ||
| 139 | VarHash h; | ||
| 140 | if( !sVars.isEmpty() ) | ||
| 141 | h = sVars.peek(); | ||
| 142 | sVars.push( h ); | ||
| 143 | } | ||
| 144 | |||
| 145 | void Context::pushScope( const VarHash &hNewVars ) | ||
| 146 | { | ||
| 147 | VarHash h = hNewVars; | ||
| 148 | if( !sVars.isEmpty() ) | ||
| 149 | { | ||
| 150 | for( VarHash::iterator i = sVars.peek().begin(); i; i++ ) | ||
| 151 | { | ||
| 152 | if( !h.has( i.getKey() ) ) | ||
| 153 | h.insert( i.getKey(), i.getValue() ); | ||
| 154 | } | ||
| 155 | } | ||
| 156 | sVars.push( h ); | ||
| 157 | } | ||
| 158 | |||
| 159 | VarHash &Context::getScope() | ||
| 160 | { | ||
| 161 | return sVars.first(); | ||
| 162 | } | ||
| 163 | |||
| 164 | void Context::popScope() | ||
| 165 | { | ||
| 166 | sVars.pop(); | ||
| 167 | } | ||
| 168 | |||
| 169 | Variable Context::call( const Bu::FString &sName, Variable &input, | ||
| 170 | VarList lParams ) | ||
| 171 | { | ||
| 172 | if( !hFunction.has( sName ) ) | ||
| 173 | { | ||
| 174 | throw Bu::ExceptionBase("Unknown function called: %s", sName.getStr() ); | ||
| 175 | } | ||
| 176 | return hFunction.get( sName )->call( input, lParams ); | ||
| 177 | } | ||
| 178 | |||
| 179 | #include <bu/sio.h> | ||
| 180 | using namespace Bu; | ||
| 181 | Bu::FString Context::expand( const Bu::FString &sInS ) | ||
| 182 | { | ||
| 183 | Bu::FString sRet; | ||
| 184 | Bu::FString sIn = sInS; | ||
| 185 | |||
| 186 | for( int iPass = 0; iPass < 2; iPass++ ) | ||
| 187 | { | ||
| 188 | Bu::FString::const_iterator b = sIn.begin(); | ||
| 189 | sRet.clear(); | ||
| 190 | for(;;) | ||
| 191 | { | ||
| 192 | Bu::FString::const_iterator e = b.find('$'); | ||
| 193 | if( !e ) | ||
| 194 | { | ||
| 195 | sRet.append( b ); | ||
| 196 | break; | ||
| 197 | } | ||
| 198 | sRet.append( b, e ); | ||
| 199 | b = e+1; | ||
| 200 | if( !b ) | ||
| 201 | { | ||
| 202 | sRet.append('$'); | ||
| 203 | } | ||
| 204 | else if( *b == '{' ) | ||
| 205 | { | ||
| 206 | b++; | ||
| 207 | e = b.find('}'); | ||
| 208 | Bu::FString sVar( b, e ); | ||
| 209 | try | ||
| 210 | { | ||
| 211 | sRet.append( getVariable( sVar ).toString() ); | ||
| 212 | } catch(...) | ||
| 213 | { | ||
| 214 | // TODO: This may be handy debugging later... | ||
| 215 | //sio << "No variable named " << sVar << sio.nl; | ||
| 216 | //sio << "Vars: " << sVars << sio.nl << sio.nl; | ||
| 217 | } | ||
| 218 | b = e+1; | ||
| 219 | } | ||
| 220 | else if( *b == '(' && iPass == 1 ) | ||
| 221 | { | ||
| 222 | b++; | ||
| 223 | e = b.find(')'); | ||
| 224 | Bu::FString sCmd( b, e ); | ||
| 225 | Bu::FString sBuf; | ||
| 226 | try | ||
| 227 | { | ||
| 228 | //sio << "Executing command: >>>" << sCmd << "<<<" << sio.nl; | ||
| 229 | Process p( Process::StdOut, "/bin/bash", "/bin/bash", "-c", sCmd.getStr(), NULL ); | ||
| 230 | while( p.isRunning() ) | ||
| 231 | { | ||
| 232 | char buf[4096]; | ||
| 233 | sBuf.append( buf, p.read( buf, 4096 ) ); | ||
| 234 | } | ||
| 235 | sRet.append( sBuf ); | ||
| 236 | } catch(...) | ||
| 237 | { | ||
| 238 | // TODO: This may be handy debugging later... | ||
| 239 | //sio << "No variable named " << sVar << sio.nl; | ||
| 240 | //sio << "Vars: " << sVars << sio.nl << sio.nl; | ||
| 241 | } | ||
| 242 | b = e+1; | ||
| 243 | } | ||
| 244 | else | ||
| 245 | { | ||
| 246 | // Not a match, uh, just output the $ for now... | ||
| 247 | sRet.append('$'); | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | sIn = sRet; | ||
| 252 | } | ||
| 253 | return sRet; | ||
| 254 | } | ||
| 255 | |||
| 256 | Target *Context::getTarget( const Bu::FString &sOutput ) | ||
| 257 | { | ||
| 258 | return hTarget.get( sOutput ); | ||
| 259 | } | ||
| 260 | |||
| 261 | TargetList Context::getExplicitTargets() | ||
| 262 | { | ||
| 263 | TargetList lRet; | ||
| 264 | for( TargetHash::iterator i = hTarget.begin(); i; i++ ) | ||
| 265 | { | ||
| 266 | if( (*i)->isExplicit() ) | ||
| 267 | lRet.append( *i ); | ||
| 268 | } | ||
| 269 | return lRet; | ||
| 270 | } | ||
| 271 | |||
| 272 | void Context::buildTargetTree( Runner &r ) | ||
| 273 | { | ||
| 274 | TargetList lTargets = hTarget.getValues(); | ||
| 275 | |||
| 276 | for( TargetList::iterator i = lTargets.begin(); i; i++ ) | ||
| 277 | { | ||
| 278 | // I believe we only want to autogenerate targets for explicit targets | ||
| 279 | // that have rules defined. | ||
| 280 | if( !(*i)->isExplicit() || !(*i)->hasRule() ) | ||
| 281 | continue; | ||
| 282 | |||
| 283 | StrList lNewIns; // The new "changed" inputs for this target | ||
| 284 | |||
| 285 | Rule *pMaster = hRule.get( (*i)->getRule() ); | ||
| 286 | |||
| 287 | for( StrList::const_iterator j = (*i)->getInputList().begin(); j; j++ ) | ||
| 288 | { | ||
| 289 | if( pMaster->ruleMatches( r, *j ) ) | ||
| 290 | { | ||
| 291 | lNewIns.append( *j ); | ||
| 292 | } | ||
| 293 | |||
| 294 | if( hTarget.has( *j ) ) | ||
| 295 | { | ||
| 296 | // Find the existing dependancy | ||
| 297 | lNewIns.append( *j ); | ||
| 298 | } | ||
| 299 | //else | ||
| 300 | //{ | ||
| 301 | buildTargetTree( r, *i, *j, pMaster, lNewIns ); | ||
| 302 | //} | ||
| 303 | } | ||
| 304 | |||
| 305 | pMaster->prepTarget( *i ); | ||
| 306 | (*i)->resetInputList( lNewIns ); | ||
| 307 | } | ||
| 308 | //sio << "Building dependancies: " << Fmt(3) << 0 << "%\r" << sio.flush; | ||
| 309 | //int iSize = hTarget.getSize(), iCur = 0; | ||
| 310 | for( TargetHash::iterator i = hTarget.begin(); i; i++ ) | ||
| 311 | { | ||
| 312 | // Before we can take a look at the requirements, we need to build | ||
| 313 | // them... | ||
| 314 | // (*i)->buildRequires( r ); | ||
| 315 | |||
| 316 | // For every target we have to examine both it's inputs and it's | ||
| 317 | // additional requirements. Inputs first | ||
| 318 | StrList lDeps( (*i)->getInputList() ); | ||
| 319 | lDeps += (*i)->getRequiresList(); | ||
| 320 | for( StrList::const_iterator j = lDeps.begin(); j; j++ ) | ||
| 321 | { | ||
| 322 | try | ||
| 323 | { | ||
| 324 | (*i)->addDep( hTarget.get( *j ) ); | ||
| 325 | } | ||
| 326 | catch(...) | ||
| 327 | { | ||
| 328 | } | ||
| 329 | } | ||
| 330 | //iCur++; | ||
| 331 | // sio << "Building dependancies: " << Fmt(3) << (iCur*100/iSize) << "%\r" << sio.flush; | ||
| 332 | (*i)->collapseDeps(); | ||
| 333 | } | ||
| 334 | // sio << sio.nl; | ||
| 335 | |||
| 336 | for( TargetHash::iterator i = hTarget.begin(); i; i++ ) | ||
| 337 | { | ||
| 338 | if( !(*i)->isExplicit() ) | ||
| 339 | continue; | ||
| 340 | (*i)->setDepCount(); | ||
| 341 | (*i)->resetRun( false ); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | void Context::buildTargetTree( class Runner &r, class Target * /*pTarget*/, const Bu::FString &sInput, Rule *pMaster, StrList &lNewIns ) | ||
| 346 | { | ||
| 347 | Target *pNewTarget = NULL; | ||
| 348 | for( RuleHash::iterator i = hRule.begin(); i; i++ ) | ||
| 349 | { | ||
| 350 | if( (*i)->hasOutputs() && (*i)->ruleMatches( r, sInput ) ) | ||
| 351 | { | ||
| 352 | pNewTarget = (*i)->createTarget( r, sInput ); | ||
| 353 | |||
| 354 | Bu::Hash<ptrdiff_t, bool> hDone; | ||
| 355 | for( StrList::const_iterator oi = | ||
| 356 | pNewTarget->getOutputList().begin(); oi; oi++ ) | ||
| 357 | { | ||
| 358 | try | ||
| 359 | { | ||
| 360 | Target *pOver = hTarget.get( *oi ); | ||
| 361 | if( hDone.has( (ptrdiff_t)pOver ) ) | ||
| 362 | continue; | ||
| 363 | hDone.insert( (ptrdiff_t)pOver, true ); | ||
| 364 | if( !pOver->isExplicit() ) | ||
| 365 | { | ||
| 366 | delete pNewTarget; | ||
| 367 | pNewTarget = pOver; | ||
| 368 | break; | ||
| 369 | } | ||
| 370 | pOver->mergeUnder( pNewTarget ); | ||
| 371 | delete pNewTarget; | ||
| 372 | // sio << "Delete: " << Fmt::ptr() << (ptrdiff_t)pNewTarget << sio.nl; | ||
| 373 | pNewTarget = pOver; | ||
| 374 | break; | ||
| 375 | } | ||
| 376 | catch(...) | ||
| 377 | { | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | // We actually want to add this either way, if the merge added new | ||
| 382 | // outputs, then we need to take them into account. | ||
| 383 | addTarget( pNewTarget ); | ||
| 384 | addTargetToTags( pNewTarget, (*i)->getTagList() ); | ||
| 385 | |||
| 386 | // We have created a new target (or not, either way, we need to | ||
| 387 | // check if it matches.) | ||
| 388 | for( StrList::const_iterator m = | ||
| 389 | pNewTarget->getOutputList().begin(); m; m++ ) | ||
| 390 | { | ||
| 391 | // Does the new output match the master rule? | ||
| 392 | if( pMaster->ruleMatches( r, (*m) ) ) | ||
| 393 | { | ||
| 394 | lNewIns.append( (*m) ); | ||
| 395 | |||
| 396 | // sio << "What?" << sio.nl; | ||
| 397 | // These relationships are difficult to pick up on except | ||
| 398 | // that one target was created by the other, I suppose. | ||
| 399 | // Anyway, that means that we need to add this while we | ||
| 400 | // can. | ||
| 401 | // pTarget->addDep( pNewTarget ); | ||
| 402 | } | ||
| 403 | // else | ||
| 404 | // { | ||
| 405 | buildTargetTree( r, pNewTarget, *m, pMaster, lNewIns ); | ||
| 406 | // } | ||
| 407 | } | ||
| 408 | |||
| 409 | return; | ||
| 410 | } | ||
| 411 | } | ||
| 412 | if( !pNewTarget ) | ||
| 413 | { | ||
| 414 | //sio << "Incomplete tree created, trying to find purpose for \"" | ||
| 415 | // << sInput << "\"." << sio.nl; | ||
| 416 | return; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | void Context::attachDefaults() | ||
| 421 | { | ||
| 422 | for( TargetHash::iterator i = hTarget.begin(); i; i++ ) | ||
| 423 | { | ||
| 424 | if( !(*i)->hasProfile("clean") ) | ||
| 425 | { | ||
| 426 | (*i)->addProfile( Profile::genDefaultClean() ); | ||
| 427 | } | ||
| 428 | } | ||
| 429 | } | ||
| 430 | |||
| 431 | void Context::genDefaultActions() | ||
| 432 | { | ||
| 433 | if( !hAction.has("all") ) | ||
| 434 | { | ||
| 435 | addAction( Action::genDefaultAll() ); | ||
| 436 | } | ||
| 437 | if( !hAction.has("clean") ) | ||
| 438 | { | ||
| 439 | addAction( Action::genDefaultClean() ); | ||
| 440 | } | ||
| 441 | if( !hAction.has("default") ) | ||
| 442 | { | ||
| 443 | addAction( Action::genDefaultDefault() ); | ||
| 444 | } | ||
| 445 | } | ||
| 446 | |||
| 447 | void Context::writeTargetDot() | ||
| 448 | { | ||
| 449 | Bu::Hash<ptrdiff_t, bool> hDone; | ||
| 450 | sio << "digraph {" << sio.nl | ||
| 451 | << "\trankdir=LR;" << sio.nl; | ||
| 452 | for( TargetHash::iterator i = hTarget.begin(); i; i++ ) | ||
| 453 | { | ||
| 454 | if( hDone.has( (ptrdiff_t)*i ) ) | ||
| 455 | continue; | ||
| 456 | hDone.insert( (ptrdiff_t)*i, true ); | ||
| 457 | for( StrList::const_iterator l = (*i)->getOutputList().begin(); | ||
| 458 | l; l++ ) | ||
| 459 | { | ||
| 460 | for( StrList::const_iterator k = (*i)->getInputList().begin(); | ||
| 461 | k; k++ ) | ||
| 462 | { | ||
| 463 | sio << "\t\"" << *k << "\" -> \"" | ||
| 464 | << *l << "\";" << sio.nl; | ||
| 465 | } | ||
| 466 | for( StrList::const_iterator k = (*i)->getRequiresList().begin(); | ||
| 467 | k; k++ ) | ||
| 468 | { | ||
| 469 | sio << "\t\"" << *k << "\" -> \"" | ||
| 470 | << *l << "\" [color=red];" << sio.nl; | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 | } | ||
| 475 | sio << "}" << sio.nl; | ||
| 476 | } | ||
| 477 | |||
| 478 | void Context::setView( View *pNewView ) | ||
| 479 | { | ||
| 480 | delete pView; | ||
| 481 | pView = pNewView; | ||
| 482 | } | ||
| 483 | |||
| 484 | View *Context::getView() | ||
| 485 | { | ||
| 486 | return pView; | ||
| 487 | } | ||
| 488 | |||
| 489 | Bu::Formatter &operator<<( Bu::Formatter &f, const Context &c ) | ||
| 490 | { | ||
| 491 | f << "Variables: " << c.sVars << f.nl; | ||
| 492 | f << "Targets: " << c.hTarget << f.nl; | ||
| 493 | f << "Rules: " << c.hRule << f.nl; | ||
| 494 | |||
| 495 | return f; | ||
| 496 | } | ||
| 497 | |||
| 498 | void Context::printBasicInfo() | ||
| 499 | { | ||
| 500 | sio << "Available actions:" << sio.nl << "\t"; | ||
| 501 | for( ActionHash::iterator i = hAction.begin(); i; i++ ) | ||
| 502 | { | ||
| 503 | if( i != hAction.begin() ) | ||
| 504 | sio << ", "; | ||
| 505 | sio << i.getKey(); | ||
| 506 | } | ||
| 507 | |||
| 508 | TargetList lTargets = getExplicitTargets(); | ||
| 509 | sio << sio.nl << sio.nl << "Available targets:" << sio.nl << "\t"; | ||
| 510 | for( TargetList::iterator i = lTargets.begin(); i; i++ ) | ||
| 511 | { | ||
| 512 | if( i != lTargets.begin() ) | ||
| 513 | sio << ", "; | ||
| 514 | for( StrList::const_iterator j = (*i)->getOutputList().begin(); j; j++ ) | ||
| 515 | { | ||
| 516 | if( j != (*i)->getOutputList().begin() ) | ||
| 517 | sio << ", "; | ||
| 518 | sio << (*j); | ||
| 519 | } | ||
| 520 | } | ||
| 521 | |||
| 522 | sio << sio.nl << sio.nl; | ||
| 523 | } | ||
| 524 | |||
diff --git a/src/context.h b/src/context.h new file mode 100644 index 0000000..0d9aaff --- /dev/null +++ b/src/context.h | |||
| @@ -0,0 +1,101 @@ | |||
| 1 | #ifndef CONTEXT_H | ||
| 2 | #define CONTEXT_H | ||
| 3 | |||
| 4 | #include "bu/hash.h" | ||
| 5 | #include "bu/fstring.h" | ||
| 6 | |||
| 7 | #include "variable.h" | ||
| 8 | |||
| 9 | class Target; | ||
| 10 | class Rule; | ||
| 11 | class Function; | ||
| 12 | class Action; | ||
| 13 | class View; | ||
| 14 | |||
| 15 | class Context | ||
| 16 | { | ||
| 17 | friend Bu::Formatter &operator<<( Bu::Formatter &f, const Context &c ); | ||
| 18 | public: | ||
| 19 | Context(); | ||
| 20 | virtual ~Context(); | ||
| 21 | |||
| 22 | void addTarget( Target *pTarget ); | ||
| 23 | void addRule( Rule *pRule ); | ||
| 24 | void addFunction( Function *pFunction ); | ||
| 25 | void addVariable( const Bu::FString &sName, const Variable &vValue ); | ||
| 26 | void addAction( Action *pAction ); | ||
| 27 | Action *getAction( const Bu::FString &sName ); | ||
| 28 | |||
| 29 | void addTargetToTag( Target *pTarget, const Bu::FString &sTag ); | ||
| 30 | void addTargetToTags( Target *pTarget, const StrList &sTags ); | ||
| 31 | TargetList &getTag( const Bu::FString &sTag ); | ||
| 32 | |||
| 33 | Variable &getVariable( const Bu::FString &sName ); | ||
| 34 | void delVariable( const Bu::FString &sName ); | ||
| 35 | |||
| 36 | void pushScope(); | ||
| 37 | void pushScope( const VarHash &hNewVars ); | ||
| 38 | VarHash &getScope(); | ||
| 39 | void popScope(); | ||
| 40 | |||
| 41 | Variable call( const Bu::FString &sName, Variable &input, VarList lParams ); | ||
| 42 | |||
| 43 | Bu::FString expand( const Bu::FString &sIn ); | ||
| 44 | |||
| 45 | Target *getTarget( const Bu::FString &sOutput ); | ||
| 46 | TargetList getExplicitTargets(); | ||
| 47 | |||
| 48 | /** | ||
| 49 | * This function actually builds the dependancy tree, and is responsible | ||
| 50 | * for creating all of the auto-generated targets that are required by the | ||
| 51 | * explicitly created targets. | ||
| 52 | */ | ||
| 53 | void buildTargetTree( class Runner &r ); | ||
| 54 | |||
| 55 | /** | ||
| 56 | * This is done as a final step, it goes through all targets and | ||
| 57 | * attaches things that they should have even if they haven't defined them, | ||
| 58 | * like a clean profile, they'll get that even if they haven't added one of | ||
| 59 | * their own. The defaults in this routine are added only if they aren't | ||
| 60 | * already defined in the target. It should be excetued after | ||
| 61 | * buildTargetTree, which means it doesn't need to affect rules. | ||
| 62 | */ | ||
| 63 | void attachDefaults(); | ||
| 64 | |||
| 65 | /** | ||
| 66 | * This function generates some default actions if they don't already | ||
| 67 | * exist, pretty straight forward, it will create all, clean, and default | ||
| 68 | * (default is the same as all). | ||
| 69 | */ | ||
| 70 | void genDefaultActions(); | ||
| 71 | |||
| 72 | void writeTargetDot(); | ||
| 73 | |||
| 74 | void setView( View *pNewView ); | ||
| 75 | View *getView(); | ||
| 76 | |||
| 77 | void printBasicInfo(); | ||
| 78 | |||
| 79 | private: | ||
| 80 | void buildTargetTree( class Runner &r, class Target *pTarget, const Bu::FString &sInput, class Rule *pMaster, StrList &lNewIns ); | ||
| 81 | |||
| 82 | private: | ||
| 83 | typedef Bu::Hash<Bu::FString, Target *> TargetHash; | ||
| 84 | typedef Bu::Hash<Bu::FString, Rule *> RuleHash; | ||
| 85 | typedef Bu::Hash<Bu::FString, Function *> FunctionHash; | ||
| 86 | typedef Bu::Hash<Bu::FString, Action *> ActionHash; | ||
| 87 | typedef Bu::List<VarHash> ScopeStack; | ||
| 88 | typedef Bu::Hash<Bu::FString, TargetList> TagHash; | ||
| 89 | |||
| 90 | TargetHash hTarget; | ||
| 91 | RuleHash hRule; | ||
| 92 | FunctionHash hFunction; | ||
| 93 | ScopeStack sVars; | ||
| 94 | ActionHash hAction; | ||
| 95 | TagHash hTag; | ||
| 96 | View *pView; | ||
| 97 | }; | ||
| 98 | |||
| 99 | Bu::Formatter &operator<<( Bu::Formatter &f, const Context &c ); | ||
| 100 | |||
| 101 | #endif | ||
diff --git a/src/function.cpp b/src/function.cpp new file mode 100644 index 0000000..f73f576 --- /dev/null +++ b/src/function.cpp | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #include "function.h" | ||
| 2 | |||
| 3 | Function::Function() : | ||
| 4 | pContext( NULL ) | ||
| 5 | { | ||
| 6 | } | ||
| 7 | |||
| 8 | Function::~Function() | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | void Function::setContext( class Context *p ) | ||
| 13 | { | ||
| 14 | pContext = p; | ||
| 15 | } | ||
| 16 | |||
diff --git a/src/function.h b/src/function.h new file mode 100644 index 0000000..9573bd3 --- /dev/null +++ b/src/function.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef FUNCTION_H | ||
| 2 | #define FUNCTION_H | ||
| 3 | |||
| 4 | #include "bu/fstring.h" | ||
| 5 | #include "variable.h" | ||
| 6 | |||
| 7 | class Function | ||
| 8 | { | ||
| 9 | public: | ||
| 10 | Function(); | ||
| 11 | virtual ~Function(); | ||
| 12 | |||
| 13 | virtual Bu::FString getName() const=0; | ||
| 14 | |||
| 15 | virtual Variable call( Variable &input, VarList lParams )=0; | ||
| 16 | |||
| 17 | void setContext( class Context *p ); | ||
| 18 | |||
| 19 | protected: | ||
| 20 | class Context *pContext; | ||
| 21 | }; | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/src/functionast.cpp b/src/functionast.cpp new file mode 100644 index 0000000..0d9a938 --- /dev/null +++ b/src/functionast.cpp | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | #include "functionast.h" | ||
| 2 | #include "astbranch.h" | ||
| 3 | #include "astleaf.h" | ||
| 4 | #include "runner.h" | ||
| 5 | #include "context.h" | ||
| 6 | |||
| 7 | FunctionAst::FunctionAst( const AstBranch *pRoot, class Runner *pRunner ) : | ||
| 8 | pRoot( pRoot ), | ||
| 9 | pRunner( pRunner ) | ||
| 10 | { | ||
| 11 | sName = dynamic_cast<AstLeaf *>( | ||
| 12 | *(*pRoot->getBranchBegin()).begin() | ||
| 13 | )->getStrValue(); | ||
| 14 | } | ||
| 15 | |||
| 16 | FunctionAst::~FunctionAst() | ||
| 17 | { | ||
| 18 | } | ||
| 19 | |||
| 20 | Bu::FString FunctionAst::getName() const | ||
| 21 | { | ||
| 22 | return sName; | ||
| 23 | } | ||
| 24 | |||
| 25 | Variable FunctionAst::call( Variable &input, VarList /*lParams*/ ) | ||
| 26 | { | ||
| 27 | pContext->pushScope(); | ||
| 28 | pContext->addVariable("INPUT", input ); | ||
| 29 | Variable vRet = pRunner->run( (*(pRoot->getBranchBegin()+2)).begin() ); | ||
| 30 | pContext->popScope(); | ||
| 31 | return vRet; | ||
| 32 | } | ||
| 33 | |||
diff --git a/src/functionast.h b/src/functionast.h new file mode 100644 index 0000000..b971683 --- /dev/null +++ b/src/functionast.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #ifndef FUNCTION_AST_H | ||
| 2 | #define FUNCTION_AST_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionAst : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionAst( const class AstBranch *pRoot, class Runner *pRunner ); | ||
| 10 | virtual ~FunctionAst(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | |||
| 15 | private: | ||
| 16 | Bu::FString sName; | ||
| 17 | const class AstBranch *pRoot; | ||
| 18 | class Runner *pRunner; | ||
| 19 | }; | ||
| 20 | |||
| 21 | #endif | ||
diff --git a/src/functiondirname.cpp b/src/functiondirname.cpp new file mode 100644 index 0000000..e8b728b --- /dev/null +++ b/src/functiondirname.cpp | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | #include "functiondirname.h" | ||
| 2 | |||
| 3 | FunctionDirName::FunctionDirName() | ||
| 4 | { | ||
| 5 | } | ||
| 6 | |||
| 7 | FunctionDirName::~FunctionDirName() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
| 11 | Bu::FString FunctionDirName::getName() const | ||
| 12 | { | ||
| 13 | return "dirName"; | ||
| 14 | } | ||
| 15 | |||
| 16 | Variable FunctionDirName::call( Variable &input, VarList /*lParams*/ ) | ||
| 17 | { | ||
| 18 | Bu::FString sFile; | ||
| 19 | sFile = input.getString(); | ||
| 20 | |||
| 21 | Bu::FString::const_iterator i = sFile.begin(); | ||
| 22 | Bu::FString::const_iterator io; | ||
| 23 | for(;;) | ||
| 24 | { | ||
| 25 | Bu::FString::const_iterator b = i.find('/'); | ||
| 26 | if( !b ) | ||
| 27 | { | ||
| 28 | return Variable( Bu::FString( sFile.begin(), io ) ); | ||
| 29 | } | ||
| 30 | io = b; | ||
| 31 | i = b+1; | ||
| 32 | if( !i ) | ||
| 33 | { | ||
| 34 | return Variable( Bu::FString( sFile.begin(), io ) ); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
diff --git a/src/functiondirname.h b/src/functiondirname.h new file mode 100644 index 0000000..830a992 --- /dev/null +++ b/src/functiondirname.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef FUNCTION_DIR_NAME_H | ||
| 2 | #define FUNCTION_DIR_NAME_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionDirName : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionDirName(); | ||
| 10 | virtual ~FunctionDirName(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | |||
| 15 | }; | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/src/functiondirs.cpp b/src/functiondirs.cpp new file mode 100644 index 0000000..fb64ef3 --- /dev/null +++ b/src/functiondirs.cpp | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | #include "functiondirs.h" | ||
| 2 | |||
| 3 | #include <sys/types.h> | ||
| 4 | #include <sys/stat.h> | ||
| 5 | #include <glob.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | |||
| 8 | FunctionDirs::FunctionDirs() | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | FunctionDirs::~FunctionDirs() | ||
| 13 | { | ||
| 14 | } | ||
| 15 | |||
| 16 | Bu::FString FunctionDirs::getName() const | ||
| 17 | { | ||
| 18 | return "dirs"; | ||
| 19 | } | ||
| 20 | |||
| 21 | Variable FunctionDirs::call( Variable &/*input*/, VarList lParams ) | ||
| 22 | { | ||
| 23 | glob_t globbuf; | ||
| 24 | |||
| 25 | int flags = 0; | ||
| 26 | |||
| 27 | for( VarList::const_iterator i = lParams.begin(); i; i++ ) | ||
| 28 | { | ||
| 29 | switch( (*i).getType() ) | ||
| 30 | { | ||
| 31 | case Variable::typeString: | ||
| 32 | glob( (*i).getString().getStr(), flags, NULL, &globbuf ); | ||
| 33 | flags |= GLOB_APPEND; | ||
| 34 | break; | ||
| 35 | |||
| 36 | case Variable::typeList: | ||
| 37 | throw Bu::ExceptionBase("Lists not supported in glob yet."); | ||
| 38 | break; | ||
| 39 | |||
| 40 | default: | ||
| 41 | throw Bu::ExceptionBase( | ||
| 42 | "Cannot use a non-string or non-list as a parameter to glob" | ||
| 43 | ); | ||
| 44 | break; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | Variable vRet( Variable::typeList ); | ||
| 49 | struct stat s; | ||
| 50 | for( size_t j = 0; j < globbuf.gl_pathc; j++ ) | ||
| 51 | { | ||
| 52 | stat( globbuf.gl_pathv[j], &s ); | ||
| 53 | if( S_ISDIR( s.st_mode ) ) | ||
| 54 | vRet.append( globbuf.gl_pathv[j] ); | ||
| 55 | } | ||
| 56 | |||
| 57 | globfree( &globbuf ); | ||
| 58 | |||
| 59 | return vRet; | ||
| 60 | } | ||
| 61 | |||
diff --git a/src/functiondirs.h b/src/functiondirs.h new file mode 100644 index 0000000..5edfaf9 --- /dev/null +++ b/src/functiondirs.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef FUNCTION_DIRS_H | ||
| 2 | #define FUNCTION_DIRS_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionDirs : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionDirs(); | ||
| 10 | virtual ~FunctionDirs(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | |||
| 15 | }; | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/src/functionexecute.cpp b/src/functionexecute.cpp new file mode 100644 index 0000000..619d2c2 --- /dev/null +++ b/src/functionexecute.cpp | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | #include "functionexecute.h" | ||
| 2 | #include "context.h" | ||
| 3 | #include "view.h" | ||
| 4 | |||
| 5 | #include <bu/sio.h> | ||
| 6 | #include <bu/process.h> | ||
| 7 | using namespace Bu; | ||
| 8 | |||
| 9 | FunctionExecute::FunctionExecute() | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | FunctionExecute::~FunctionExecute() | ||
| 14 | { | ||
| 15 | } | ||
| 16 | |||
| 17 | Bu::FString FunctionExecute::getName() const | ||
| 18 | { | ||
| 19 | return "execute"; | ||
| 20 | } | ||
| 21 | |||
| 22 | Variable FunctionExecute::call( Variable &/*input*/, VarList lParams ) | ||
| 23 | { | ||
| 24 | // TODO This is lame, really lame, we need to exec on our own and process | ||
| 25 | // output appropriately. | ||
| 26 | pContext->getView()->cmdStarted( lParams.first().getString() ); | ||
| 27 | Process pCmd( Process::Both, "/bin/bash", "/bin/bash", "-c", | ||
| 28 | lParams.first().getString().getStr(), NULL ); | ||
| 29 | FString sStdOut, sStdErr; | ||
| 30 | while( pCmd.isRunning() ) | ||
| 31 | { | ||
| 32 | char buf[4096]; | ||
| 33 | bool out, err; | ||
| 34 | pCmd.select( out, err ); | ||
| 35 | if( err ) | ||
| 36 | { | ||
| 37 | int iRead = pCmd.readErr( buf, 4096 ); | ||
| 38 | sStdErr.append( buf, iRead ); | ||
| 39 | //sio << "Read " << iRead << " bytes of stderr." << sio.nl; | ||
| 40 | } | ||
| 41 | if( out ) | ||
| 42 | { | ||
| 43 | int iRead = pCmd.read( buf, 4096 ); | ||
| 44 | sStdOut.append( buf, iRead ); | ||
| 45 | //sio << "Read " << iRead << " bytes of stdout." << sio.nl; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | pContext->getView()->cmdFinished( | ||
| 50 | sStdOut, sStdErr, pCmd.childExitStatus() | ||
| 51 | ); | ||
| 52 | if( pCmd.childExited() ) | ||
| 53 | { | ||
| 54 | if( pCmd.childExitStatus() != 0 ) | ||
| 55 | { | ||
| 56 | throw Bu::ExceptionBase("Command exited with errorcode %d.", pCmd.childExitStatus() ); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | else | ||
| 60 | { | ||
| 61 | pContext->getView()->cmdFinished( | ||
| 62 | sStdOut, sStdErr, pCmd.childExitStatus() | ||
| 63 | ); | ||
| 64 | throw Bu::ExceptionBase("Command Failed"); | ||
| 65 | } | ||
| 66 | return Variable( pCmd.childExitStatus() ); | ||
| 67 | } | ||
| 68 | |||
diff --git a/src/functionexecute.h b/src/functionexecute.h new file mode 100644 index 0000000..ebeaa7f --- /dev/null +++ b/src/functionexecute.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef FUNCTION_EXECUTE_H | ||
| 2 | #define FUNCTION_EXECUTE_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionExecute : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionExecute(); | ||
| 10 | virtual ~FunctionExecute(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/functionexists.cpp b/src/functionexists.cpp new file mode 100644 index 0000000..d2aa9e9 --- /dev/null +++ b/src/functionexists.cpp | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | #include "functionexists.h" | ||
| 2 | |||
| 3 | #include <unistd.h> | ||
| 4 | |||
| 5 | FunctionExists::FunctionExists() | ||
| 6 | { | ||
| 7 | } | ||
| 8 | |||
| 9 | FunctionExists::~FunctionExists() | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | Bu::FString FunctionExists::getName() const | ||
| 14 | { | ||
| 15 | return "exists"; | ||
| 16 | } | ||
| 17 | |||
| 18 | Variable FunctionExists::call( Variable &input, VarList lParams ) | ||
| 19 | { | ||
| 20 | Bu::FString sFile; | ||
| 21 | if( input.getType() != Variable::typeNone ) | ||
| 22 | { | ||
| 23 | sFile = input.toString(); | ||
| 24 | } | ||
| 25 | else | ||
| 26 | { | ||
| 27 | sFile = lParams.first().toString(); | ||
| 28 | } | ||
| 29 | if( access( sFile.getStr(), F_OK ) == 0 ) | ||
| 30 | return Variable( true ); | ||
| 31 | else | ||
| 32 | return Variable( false ); | ||
| 33 | } | ||
| 34 | |||
diff --git a/src/functionexists.h b/src/functionexists.h new file mode 100644 index 0000000..8a3001a --- /dev/null +++ b/src/functionexists.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef FUNCTION_EXISTS_H | ||
| 2 | #define FUNCTION_EXISTS_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionExists : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionExists(); | ||
| 10 | virtual ~FunctionExists(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | |||
| 15 | }; | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/src/functionfilename.cpp b/src/functionfilename.cpp new file mode 100644 index 0000000..21a4655 --- /dev/null +++ b/src/functionfilename.cpp | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #include "functionfilename.h" | ||
| 2 | |||
| 3 | FunctionFileName::FunctionFileName() | ||
| 4 | { | ||
| 5 | } | ||
| 6 | |||
| 7 | FunctionFileName::~FunctionFileName() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
| 11 | Bu::FString FunctionFileName::getName() const | ||
| 12 | { | ||
| 13 | return "fileName"; | ||
| 14 | } | ||
| 15 | |||
| 16 | Variable FunctionFileName::call( Variable &input, VarList /*lParams*/ ) | ||
| 17 | { | ||
| 18 | Bu::FString sFile; | ||
| 19 | sFile = input.getString(); | ||
| 20 | |||
| 21 | Bu::FString::const_iterator i = sFile.begin(); | ||
| 22 | for(;;) | ||
| 23 | { | ||
| 24 | Bu::FString::const_iterator b = i.find('/'); | ||
| 25 | if( !b ) | ||
| 26 | { | ||
| 27 | return Variable( Bu::FString( i ) ); | ||
| 28 | } | ||
| 29 | i = b+1; | ||
| 30 | if( !i ) | ||
| 31 | { | ||
| 32 | return Variable( Bu::FString( i ) ); | ||
| 33 | } | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
diff --git a/src/functionfilename.h b/src/functionfilename.h new file mode 100644 index 0000000..1401fc7 --- /dev/null +++ b/src/functionfilename.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef FUNCTION_FILE_NAME_H | ||
| 2 | #define FUNCTION_FILE_NAME_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionFileName : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionFileName(); | ||
| 10 | virtual ~FunctionFileName(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | |||
| 15 | }; | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/src/functionfiles.cpp b/src/functionfiles.cpp new file mode 100644 index 0000000..e708d45 --- /dev/null +++ b/src/functionfiles.cpp | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | #include "functionfiles.h" | ||
| 2 | |||
| 3 | #include <sys/types.h> | ||
| 4 | #include <sys/stat.h> | ||
| 5 | #include <glob.h> | ||
| 6 | #include <unistd.h> | ||
| 7 | |||
| 8 | FunctionFiles::FunctionFiles() | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | FunctionFiles::~FunctionFiles() | ||
| 13 | { | ||
| 14 | } | ||
| 15 | |||
| 16 | Bu::FString FunctionFiles::getName() const | ||
| 17 | { | ||
| 18 | return "files"; | ||
| 19 | } | ||
| 20 | |||
| 21 | Variable FunctionFiles::call( Variable &/*input*/, VarList lParams ) | ||
| 22 | { | ||
| 23 | glob_t globbuf; | ||
| 24 | |||
| 25 | int flags = 0; | ||
| 26 | |||
| 27 | for( VarList::const_iterator i = lParams.begin(); i; i++ ) | ||
| 28 | { | ||
| 29 | switch( (*i).getType() ) | ||
| 30 | { | ||
| 31 | case Variable::typeString: | ||
| 32 | glob( (*i).getString().getStr(), flags, NULL, &globbuf ); | ||
| 33 | flags |= GLOB_APPEND; | ||
| 34 | break; | ||
| 35 | |||
| 36 | case Variable::typeList: | ||
| 37 | throw Bu::ExceptionBase("Lists not supported in glob yet."); | ||
| 38 | break; | ||
| 39 | |||
| 40 | default: | ||
| 41 | throw Bu::ExceptionBase( | ||
| 42 | "Cannot use a non-string or non-list as a parameter to glob" | ||
| 43 | ); | ||
| 44 | break; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | Variable vRet( Variable::typeList ); | ||
| 49 | struct stat s; | ||
| 50 | for( size_t j = 0; j < globbuf.gl_pathc; j++ ) | ||
| 51 | { | ||
| 52 | stat( globbuf.gl_pathv[j], &s ); | ||
| 53 | if( S_ISREG( s.st_mode ) ) | ||
| 54 | vRet.append( globbuf.gl_pathv[j] ); | ||
| 55 | } | ||
| 56 | |||
| 57 | globfree( &globbuf ); | ||
| 58 | |||
| 59 | return vRet; | ||
| 60 | } | ||
| 61 | |||
diff --git a/src/functionfiles.h b/src/functionfiles.h new file mode 100644 index 0000000..711288a --- /dev/null +++ b/src/functionfiles.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #ifndef FUNCTION_FILES_H | ||
| 2 | #define FUNCTION_FILES_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionFiles : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionFiles(); | ||
| 10 | virtual ~FunctionFiles(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | |||
| 15 | }; | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/src/functiongetmakedeps.cpp b/src/functiongetmakedeps.cpp new file mode 100644 index 0000000..1aded15 --- /dev/null +++ b/src/functiongetmakedeps.cpp | |||
| @@ -0,0 +1,59 @@ | |||
| 1 | #include "functiongetmakedeps.h" | ||
| 2 | |||
| 3 | #include <bu/process.h> | ||
| 4 | #include <bu/sio.h> | ||
| 5 | using namespace Bu; | ||
| 6 | |||
| 7 | FunctionGetMakeDeps::FunctionGetMakeDeps() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
| 11 | FunctionGetMakeDeps::~FunctionGetMakeDeps() | ||
| 12 | { | ||
| 13 | } | ||
| 14 | |||
| 15 | Bu::FString FunctionGetMakeDeps::getName() const | ||
| 16 | { | ||
| 17 | return "getMakeDeps"; | ||
| 18 | } | ||
| 19 | |||
| 20 | Variable FunctionGetMakeDeps::call( Variable &/*input*/, VarList lParams ) | ||
| 21 | { | ||
| 22 | Process p( Process::StdOut, "/bin/bash", "/bin/bash", "-c", | ||
| 23 | lParams.first().getString().getStr(), NULL ); | ||
| 24 | |||
| 25 | // Gather all data from the command. | ||
| 26 | Bu::FString sBuf; | ||
| 27 | while( !p.isEos() ) | ||
| 28 | { | ||
| 29 | char buf[4096]; | ||
| 30 | int iRead = p.read( buf, 4096 ); | ||
| 31 | sBuf.append( buf, iRead ); | ||
| 32 | } | ||
| 33 | |||
| 34 | Variable vRet( Variable::typeList ); | ||
| 35 | |||
| 36 | Bu::FString::iterator i, j; | ||
| 37 | i = sBuf.find(':')+2; | ||
| 38 | while( i ) | ||
| 39 | { | ||
| 40 | // Find whitespace at the end of the word, this one is easy, there's | ||
| 41 | // always a space after a word | ||
| 42 | for( j = i; j && *j != ' ' && *j != '\n' && *j != '\r'; j++ ) { } | ||
| 43 | |||
| 44 | Bu::FString sTmp( i, j ); | ||
| 45 | vRet.append( sTmp ); | ||
| 46 | |||
| 47 | // Find the begining of the next word, trickier, we don't want to go | ||
| 48 | // off the end, and we need to skip \ chars at the ends of lines, right | ||
| 49 | // now this is too stupid to do that, so it may not work on windows. | ||
| 50 | // TODO: perhaps make this only skip \ chars at the ends of lines, | ||
| 51 | // we'll see if it matters. | ||
| 52 | for( i = j+1; | ||
| 53 | i && (*i == ' ' || *i == '\\' || *i == '\n' || *i == '\r'); i++ ) | ||
| 54 | { } | ||
| 55 | } | ||
| 56 | |||
| 57 | return vRet; | ||
| 58 | } | ||
| 59 | |||
diff --git a/src/functiongetmakedeps.h b/src/functiongetmakedeps.h new file mode 100644 index 0000000..b8f20d5 --- /dev/null +++ b/src/functiongetmakedeps.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef FUNCTION_GET_MAKE_DEPS_H | ||
| 2 | #define FUNCTION_GET_MAKE_DEPS_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionGetMakeDeps : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionGetMakeDeps(); | ||
| 10 | virtual ~FunctionGetMakeDeps(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/functionmatches.cpp b/src/functionmatches.cpp new file mode 100644 index 0000000..4e4b7ff --- /dev/null +++ b/src/functionmatches.cpp | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | #include "functionmatches.h" | ||
| 2 | |||
| 3 | #include <unistd.h> | ||
| 4 | |||
| 5 | FunctionMatches::FunctionMatches() | ||
| 6 | { | ||
| 7 | } | ||
| 8 | |||
| 9 | FunctionMatches::~FunctionMatches() | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | Bu::FString FunctionMatches::getName() const | ||
| 14 | { | ||
| 15 | return "matches"; | ||
| 16 | } | ||
| 17 | |||
| 18 | bool FunctionMatches::globcmp( const Bu::FString &sTxt, const Bu::FString &sMatches ) | ||
| 19 | { | ||
| 20 | Bu::FString::const_iterator t, g; | ||
| 21 | t = sTxt.begin(); | ||
| 22 | g = sMatches.begin(); | ||
| 23 | |||
| 24 | while( g && t ) | ||
| 25 | { | ||
| 26 | switch( *g ) | ||
| 27 | { | ||
| 28 | case '*': | ||
| 29 | // First, if the * is at the end, then we do match, it doesn't | ||
| 30 | // matter what is in sTxt | ||
| 31 | if( !(g+1) ) | ||
| 32 | return true; | ||
| 33 | // Now attempt to scan for the remainder as a matched set | ||
| 34 | { | ||
| 35 | Bu::FString::const_iterator tn = t+1, gn = g+1, gi=g+1; | ||
| 36 | bool bFoundMatch = false; | ||
| 37 | while( tn && gn ) | ||
| 38 | { | ||
| 39 | if( *gn == '*' ) | ||
| 40 | { | ||
| 41 | g = gn; | ||
| 42 | t = tn; | ||
| 43 | break; | ||
| 44 | } | ||
| 45 | if( *tn == *gn ) | ||
| 46 | { | ||
| 47 | g = gn; | ||
| 48 | t = tn; | ||
| 49 | tn++; | ||
| 50 | gn++; | ||
| 51 | bFoundMatch = true; | ||
| 52 | } | ||
| 53 | else | ||
| 54 | { | ||
| 55 | gn = gi; | ||
| 56 | tn++; | ||
| 57 | bFoundMatch = false; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | if( bFoundMatch == false ) | ||
| 61 | return false; | ||
| 62 | if( !tn && !gn && bFoundMatch ) | ||
| 63 | return true; | ||
| 64 | } | ||
| 65 | break; | ||
| 66 | |||
| 67 | case '?': | ||
| 68 | // Don't bother checking. | ||
| 69 | t++; | ||
| 70 | g++; | ||
| 71 | break; | ||
| 72 | |||
| 73 | default: | ||
| 74 | if( *t != *g ) | ||
| 75 | return false; | ||
| 76 | t++; | ||
| 77 | g++; | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | if( t || (g && *g != '*') ) | ||
| 82 | return false; | ||
| 83 | return true; | ||
| 84 | } | ||
| 85 | |||
| 86 | bool FunctionMatches::matchlist( const Bu::FString &sTxt, VarList &lParams ) | ||
| 87 | { | ||
| 88 | for( VarList::iterator i = lParams.begin(); i; i++ ) | ||
| 89 | { | ||
| 90 | if( (*i).getType() == Variable::typeList ) | ||
| 91 | { | ||
| 92 | for( VarList::iterator j = (*i).begin(); j; j++ ) | ||
| 93 | { | ||
| 94 | if( globcmp( sTxt, (*j).toString() ) ) | ||
| 95 | return true; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | else | ||
| 99 | { | ||
| 100 | if( globcmp( sTxt, (*i).toString() ) ) | ||
| 101 | return true; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | return false; | ||
| 105 | } | ||
| 106 | |||
| 107 | Variable FunctionMatches::call( Variable &input, VarList lParams ) | ||
| 108 | { | ||
| 109 | switch( input.getType() ) | ||
| 110 | { | ||
| 111 | case Variable::typeString: | ||
| 112 | { | ||
| 113 | Bu::FString sTxt = input.getString(); | ||
| 114 | return Variable( matchlist( sTxt, lParams ) ); | ||
| 115 | } | ||
| 116 | break; | ||
| 117 | |||
| 118 | case Variable::typeList: | ||
| 119 | { | ||
| 120 | Variable vRet( Variable::typeList ); | ||
| 121 | for( VarList::iterator i = input.begin(); i; i++ ) | ||
| 122 | { | ||
| 123 | if( (*i).getType() != Variable::typeString ) | ||
| 124 | continue; | ||
| 125 | Bu::FString sTxt = (*i).getString(); | ||
| 126 | if( matchlist( sTxt, lParams ) ) | ||
| 127 | vRet.append( *i ); | ||
| 128 | } | ||
| 129 | return vRet; | ||
| 130 | } | ||
| 131 | break; | ||
| 132 | |||
| 133 | default: | ||
| 134 | throw Bu::ExceptionBase("You can only use a string or list as the " | ||
| 135 | "input to matches."); | ||
| 136 | break; | ||
| 137 | } | ||
| 138 | |||
| 139 | return Variable(); | ||
| 140 | } | ||
| 141 | |||
diff --git a/src/functionmatches.h b/src/functionmatches.h new file mode 100644 index 0000000..7757a44 --- /dev/null +++ b/src/functionmatches.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef FUNCTION_MATCHES_H | ||
| 2 | #define FUNCTION_MATCHES_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionMatches : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionMatches(); | ||
| 10 | virtual ~FunctionMatches(); | ||
| 11 | |||
| 12 | /** | ||
| 13 | * Really basic globbing function, it doesn't handle character classes, | ||
| 14 | * just * and ?. We can expand on it later, it may be handy. | ||
| 15 | */ | ||
| 16 | bool globcmp( const Bu::FString &sTxt, const Bu::FString &sMatches ); | ||
| 17 | bool matchlist( const Bu::FString &sTxt, VarList &lParams ); | ||
| 18 | virtual Bu::FString getName() const; | ||
| 19 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 20 | |||
| 21 | }; | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/src/functionreplace.cpp b/src/functionreplace.cpp new file mode 100644 index 0000000..d269083 --- /dev/null +++ b/src/functionreplace.cpp | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | #include "functionreplace.h" | ||
| 2 | |||
| 3 | FunctionReplace::FunctionReplace() | ||
| 4 | { | ||
| 5 | } | ||
| 6 | |||
| 7 | FunctionReplace::~FunctionReplace() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
| 11 | Bu::FString FunctionReplace::getName() const | ||
| 12 | { | ||
| 13 | return "replace"; | ||
| 14 | } | ||
| 15 | |||
| 16 | Variable FunctionReplace::call( Variable &input, VarList lParams ) | ||
| 17 | { | ||
| 18 | Bu::FString sA, sB; | ||
| 19 | sA = lParams.first().getString(); | ||
| 20 | sB = lParams.last().getString(); | ||
| 21 | switch( input.getType() ) | ||
| 22 | { | ||
| 23 | case Variable::typeString: | ||
| 24 | { | ||
| 25 | Variable vOut( input.getString().replace( sA, sB ) ); | ||
| 26 | return vOut; | ||
| 27 | } | ||
| 28 | break; | ||
| 29 | |||
| 30 | case Variable::typeList: | ||
| 31 | { | ||
| 32 | Variable vOut( Variable::typeList ); | ||
| 33 | for( VarList::iterator i = input.begin(); i; i++ ) | ||
| 34 | { | ||
| 35 | vOut.append( (*i).getString().replace( sA, sB ) ); | ||
| 36 | } | ||
| 37 | return vOut; | ||
| 38 | } | ||
| 39 | break; | ||
| 40 | |||
| 41 | default: | ||
| 42 | break; | ||
| 43 | } | ||
| 44 | throw Bu::ExceptionBase( | ||
| 45 | "replace does not work on non-string or non-list types."); | ||
| 46 | } | ||
| 47 | |||
diff --git a/src/functionreplace.h b/src/functionreplace.h new file mode 100644 index 0000000..1bf4dae --- /dev/null +++ b/src/functionreplace.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef FUNCTION_REPLACE_H | ||
| 2 | #define FUNCTION_REPLACE_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionReplace : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionReplace(); | ||
| 10 | virtual ~FunctionReplace(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/functiontargets.cpp b/src/functiontargets.cpp new file mode 100644 index 0000000..93fbb96 --- /dev/null +++ b/src/functiontargets.cpp | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #include "functiontargets.h" | ||
| 2 | #include "context.h" | ||
| 3 | #include "target.h" | ||
| 4 | |||
| 5 | FunctionTargets::FunctionTargets() | ||
| 6 | { | ||
| 7 | } | ||
| 8 | |||
| 9 | FunctionTargets::~FunctionTargets() | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | Bu::FString FunctionTargets::getName() const | ||
| 14 | { | ||
| 15 | return "targets"; | ||
| 16 | } | ||
| 17 | |||
| 18 | Variable FunctionTargets::call( Variable &/*input*/, VarList lParams ) | ||
| 19 | { | ||
| 20 | Variable vRet( Variable::typeList ); | ||
| 21 | TargetList lTrg; | ||
| 22 | if( lParams.getSize() == 0 ) | ||
| 23 | { | ||
| 24 | lTrg = pContext->getExplicitTargets(); | ||
| 25 | } | ||
| 26 | else | ||
| 27 | { | ||
| 28 | lTrg = pContext->getTag( lParams.first().toString() ); | ||
| 29 | } | ||
| 30 | for( TargetList::const_iterator i = lTrg.begin(); i; i++ ) | ||
| 31 | { | ||
| 32 | for( StrList::const_iterator j = (*i)->getOutputList().begin(); j; j++ ) | ||
| 33 | { | ||
| 34 | vRet.append( *j ); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | return vRet; | ||
| 38 | } | ||
| 39 | |||
diff --git a/src/functiontargets.h b/src/functiontargets.h new file mode 100644 index 0000000..9b65d30 --- /dev/null +++ b/src/functiontargets.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef FUNCTION_TARGETS_H | ||
| 2 | #define FUNCTION_TARGETS_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionTargets : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionTargets(); | ||
| 10 | virtual ~FunctionTargets(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/functiontostring.cpp b/src/functiontostring.cpp new file mode 100644 index 0000000..0c04091 --- /dev/null +++ b/src/functiontostring.cpp | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | #include "functiontostring.h" | ||
| 2 | |||
| 3 | #include <stdlib.h> | ||
| 4 | #include <bu/sio.h> | ||
| 5 | using namespace Bu; | ||
| 6 | |||
| 7 | FunctionToString::FunctionToString() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
| 11 | FunctionToString::~FunctionToString() | ||
| 12 | { | ||
| 13 | } | ||
| 14 | |||
| 15 | Bu::FString FunctionToString::getName() const | ||
| 16 | { | ||
| 17 | return "toString"; | ||
| 18 | } | ||
| 19 | |||
| 20 | Variable FunctionToString::call( Variable &input, VarList lParams ) | ||
| 21 | { | ||
| 22 | Bu::FString sStr; | ||
| 23 | Bu::FString sSep; | ||
| 24 | if( lParams.getSize() == 0 ) | ||
| 25 | { | ||
| 26 | sSep = " "; | ||
| 27 | } | ||
| 28 | else | ||
| 29 | { | ||
| 30 | sSep = lParams.first().getString(); | ||
| 31 | } | ||
| 32 | switch( input.getType() ) | ||
| 33 | { | ||
| 34 | case Variable::typeString: | ||
| 35 | return input; | ||
| 36 | |||
| 37 | case Variable::typeList: | ||
| 38 | for( VarList::iterator i = input.begin(); i; i++ ) | ||
| 39 | { | ||
| 40 | if( i != input.begin() ) | ||
| 41 | sStr += sSep; | ||
| 42 | sStr += (*i).getString(); | ||
| 43 | } | ||
| 44 | return Variable( sStr ); | ||
| 45 | |||
| 46 | default: | ||
| 47 | return Variable( input.getString() ); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
diff --git a/src/functiontostring.h b/src/functiontostring.h new file mode 100644 index 0000000..3c3ecc7 --- /dev/null +++ b/src/functiontostring.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef FUNCTION_TO_STRING_H | ||
| 2 | #define FUNCTION_TO_STRING_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionToString : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionToString(); | ||
| 10 | virtual ~FunctionToString(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/functionunlink.cpp b/src/functionunlink.cpp new file mode 100644 index 0000000..addcfd9 --- /dev/null +++ b/src/functionunlink.cpp | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #include "functionunlink.h" | ||
| 2 | |||
| 3 | #include <unistd.h> | ||
| 4 | #include <stdlib.h> | ||
| 5 | #include <bu/sio.h> | ||
| 6 | using namespace Bu; | ||
| 7 | |||
| 8 | FunctionUnlink::FunctionUnlink() | ||
| 9 | { | ||
| 10 | } | ||
| 11 | |||
| 12 | FunctionUnlink::~FunctionUnlink() | ||
| 13 | { | ||
| 14 | } | ||
| 15 | |||
| 16 | Bu::FString FunctionUnlink::getName() const | ||
| 17 | { | ||
| 18 | return "unlink"; | ||
| 19 | } | ||
| 20 | |||
| 21 | Variable FunctionUnlink::call( Variable &/*input*/, VarList lParams ) | ||
| 22 | { | ||
| 23 | //sio << "Unlink called: " << lParams << sio.nl; | ||
| 24 | for( VarList::iterator p = lParams.begin(); p; p++ ) | ||
| 25 | { | ||
| 26 | switch( (*p).getType() ) | ||
| 27 | { | ||
| 28 | case Variable::typeString: | ||
| 29 | //sio << " xx> " << (*p).getString() << sio.nl; | ||
| 30 | unlink( (*p).getString().getStr() ); | ||
| 31 | break; | ||
| 32 | |||
| 33 | case Variable::typeList: | ||
| 34 | //sio << " xx>"; | ||
| 35 | for( VarList::iterator i = (*p).begin(); i; i++ ) | ||
| 36 | { | ||
| 37 | //sio << " " << (*i).getString(); | ||
| 38 | unlink( (*i).getString().getStr() ); | ||
| 39 | } | ||
| 40 | //sio << sio.nl; | ||
| 41 | break; | ||
| 42 | |||
| 43 | default: | ||
| 44 | throw Bu::ExceptionBase("Hey, wrong type passed."); | ||
| 45 | break; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | return Variable(); | ||
| 50 | } | ||
| 51 | |||
diff --git a/src/functionunlink.h b/src/functionunlink.h new file mode 100644 index 0000000..ac3f21e --- /dev/null +++ b/src/functionunlink.h | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | #ifndef FUNCTION_UNLINK_H | ||
| 2 | #define FUNCTION_UNLINK_H | ||
| 3 | |||
| 4 | #include "function.h" | ||
| 5 | |||
| 6 | class FunctionUnlink : public Function | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | FunctionUnlink(); | ||
| 10 | virtual ~FunctionUnlink(); | ||
| 11 | |||
| 12 | virtual Bu::FString getName() const; | ||
| 13 | virtual Variable call( Variable &input, VarList lParams ); | ||
| 14 | }; | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..142927d --- /dev/null +++ b/src/main.cpp | |||
| @@ -0,0 +1,255 @@ | |||
| 1 | #include "buildparser.h" | ||
| 2 | #include "context.h" | ||
| 3 | #include "ast.h" | ||
| 4 | #include "runner.h" | ||
| 5 | #include "target.h" | ||
| 6 | |||
| 7 | #include "viewplugger.h" | ||
| 8 | |||
| 9 | #include <bu/optparser.h> | ||
| 10 | #include <bu/sio.h> | ||
| 11 | #include <sys/types.h> | ||
| 12 | #include <dirent.h> | ||
| 13 | #include <stdlib.h> | ||
| 14 | #include <unistd.h> | ||
| 15 | |||
| 16 | extern char **environ; | ||
| 17 | |||
| 18 | using namespace Bu; | ||
| 19 | |||
| 20 | class Options : public Bu::OptParser | ||
| 21 | { | ||
| 22 | public: | ||
| 23 | Options( int argc, char *argv[] ) : | ||
| 24 | sView("default"), | ||
| 25 | sAction("default"), | ||
| 26 | sConfig("default.bld"), | ||
| 27 | bDot( false ), | ||
| 28 | bDebug( false ), | ||
| 29 | bAutoInclude( true ), | ||
| 30 | bAstDump( false ), | ||
| 31 | bEnviron( true ), | ||
| 32 | iInfoLevel( 0 ) | ||
| 33 | { | ||
| 34 | bool bClean = false; | ||
| 35 | addHelpBanner("build mark 3\n"); | ||
| 36 | |||
| 37 | Bu::FString sViews("Select a view from: "); | ||
| 38 | StrList lViews = ViewPlugger::getInstance().getPluginList(); | ||
| 39 | for( StrList::iterator i = lViews.begin(); i; i++ ) | ||
| 40 | { | ||
| 41 | if( i != lViews.begin() ) | ||
| 42 | sViews += ", "; | ||
| 43 | sViews += *i; | ||
| 44 | } | ||
| 45 | |||
| 46 | addHelpBanner("The following options do things other than build:"); | ||
| 47 | addOption( iInfoLevel, 'i', "info", "Display some basic info about the " | ||
| 48 | "loaded build config, including available targets."); | ||
| 49 | |||
| 50 | addHelpBanner("The following options control general execution:"); | ||
| 51 | addOption( sView, 'v', "view", sViews ); | ||
| 52 | addOption( sConfig, 'f', "file", "Select a different config file." ); | ||
| 53 | addOption( bClean, 'c', "Shorthand for running action 'clean'. If an " | ||
| 54 | "action is specified, this will modify it to run 'clean-action'."); | ||
| 55 | addOption( slot(this, &Options::onChdir), 'C', "chdir", | ||
| 56 | "Change to directory before doing anything else."); | ||
| 57 | |||
| 58 | addHelpBanner("\nThe following options control debugging:"); | ||
| 59 | addOption( bEnviron, "no-env", "Do not import environment variables."); | ||
| 60 | addOption( bDot, "dot", "Generate a dot chart after execution." ); | ||
| 61 | addOption( bDebug, "debug", | ||
| 62 | "Dump massive amounts of hard to read debugging data." ); | ||
| 63 | addOption( bAstDump, "debug-ast", | ||
| 64 | "Display the raw AST that is computed from parsing the input. " | ||
| 65 | "You should probably never ever use this, it'll scare you." | ||
| 66 | ); | ||
| 67 | |||
| 68 | setOverride( "no-env", "false" ); | ||
| 69 | setOverride( "dot", "true" ); | ||
| 70 | setOverride( "debug", "true" ); | ||
| 71 | setOverride( "debug-ast", "true" ); | ||
| 72 | setOverride( "info", "1" ); | ||
| 73 | setOverride( 'c', "true" ); | ||
| 74 | |||
| 75 | addHelpOption(); | ||
| 76 | |||
| 77 | setNonOption( slot( this, &Options::onNonOption ) ); | ||
| 78 | |||
| 79 | parse( argc, argv ); | ||
| 80 | |||
| 81 | if( bClean ) | ||
| 82 | { | ||
| 83 | if( sAction == "default" ) | ||
| 84 | sAction = "clean"; | ||
| 85 | else | ||
| 86 | sAction.prepend("clean-"); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | |||
| 90 | virtual ~Options() | ||
| 91 | { | ||
| 92 | } | ||
| 93 | |||
| 94 | int onChdir( StrArray sParams ) | ||
| 95 | { | ||
| 96 | if( sParams.getSize() == 0 ) | ||
| 97 | { | ||
| 98 | sio << "You must specify a directory name!" << sio.nl << sio.nl; | ||
| 99 | exit(2); | ||
| 100 | } | ||
| 101 | chdir( sParams[1].getStr() ); | ||
| 102 | return 1; | ||
| 103 | } | ||
| 104 | |||
| 105 | int onNonOption( StrArray sParams ) | ||
| 106 | { | ||
| 107 | sAction = sParams[0]; | ||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | Bu::FString sView; | ||
| 112 | Bu::FString sAction; | ||
| 113 | Bu::FString sConfig; | ||
| 114 | bool bDot; | ||
| 115 | bool bDebug; | ||
| 116 | bool bAutoInclude; | ||
| 117 | bool bAstDump; | ||
| 118 | bool bEnviron; | ||
| 119 | int iInfoLevel; | ||
| 120 | }; | ||
| 121 | |||
| 122 | int main( int argc, char *argv[] ) | ||
| 123 | { | ||
| 124 | typedef Bu::List<Bu::FString> StrList; | ||
| 125 | StrList lShareList; | ||
| 126 | lShareList.append("/usr/share/build/").append("./share/"); | ||
| 127 | Ast ast; | ||
| 128 | Context cnt; | ||
| 129 | BuildParser bp( ast ); | ||
| 130 | |||
| 131 | for( StrList::iterator i = lShareList.begin(); i; i++ ) | ||
| 132 | { | ||
| 133 | bp.addIncludePath( *i + "include"); | ||
| 134 | } | ||
| 135 | |||
| 136 | Options opts( argc, argv ); | ||
| 137 | |||
| 138 | try | ||
| 139 | { | ||
| 140 | cnt.setView( ViewPlugger::getInstance().instantiate( opts.sView ) ); | ||
| 141 | } | ||
| 142 | catch( Bu::HashException &e ) | ||
| 143 | { | ||
| 144 | sio << "Error: Invalid view specified, please choose from the " | ||
| 145 | "following choices:" << sio.nl << sio.nl << "\t"; | ||
| 146 | |||
| 147 | StrList lViews = ViewPlugger::getInstance().getPluginList(); | ||
| 148 | for( StrList::iterator i = lViews.begin(); i; i++ ) | ||
| 149 | { | ||
| 150 | if( i != lViews.begin() ) | ||
| 151 | sio << ", "; | ||
| 152 | sio << *i; | ||
| 153 | } | ||
| 154 | sio << sio.nl << sio.nl; | ||
| 155 | return 1; | ||
| 156 | } | ||
| 157 | |||
| 158 | // Load up the environment as vars. | ||
| 159 | if( opts.bEnviron ) | ||
| 160 | { | ||
| 161 | for( char **env = environ; *env; env++ ) | ||
| 162 | { | ||
| 163 | int iSplit; | ||
| 164 | for( iSplit = 0; (*env)[iSplit] != '='; iSplit++ ) { } | ||
| 165 | cnt.addVariable( | ||
| 166 | FString( *env, iSplit ), | ||
| 167 | FString( *env+iSplit+1 ) | ||
| 168 | ); | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | if( opts.bAutoInclude ) | ||
| 173 | { | ||
| 174 | DIR *d; | ||
| 175 | Bu::FString sAutoDir; | ||
| 176 | for( StrList::iterator i = lShareList.begin(); i; i++ ) | ||
| 177 | { | ||
| 178 | sAutoDir = *i + "autoinclude"; | ||
| 179 | d = opendir( sAutoDir.getStr() ); | ||
| 180 | if( d ) | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | if( !d ) | ||
| 184 | { | ||
| 185 | cnt.getView()->sysWarning( | ||
| 186 | "Could not find an autoinclude directory." | ||
| 187 | ); | ||
| 188 | } | ||
| 189 | else | ||
| 190 | { | ||
| 191 | struct dirent *de; | ||
| 192 | while( (de = readdir( d )) ) | ||
| 193 | { | ||
| 194 | if( de->d_name[0] == '.' || (de->d_type != DT_REG) ) | ||
| 195 | continue; | ||
| 196 | //sio << "Auto-including: " << de->d_name << sio.nl; | ||
| 197 | bp.load( sAutoDir + "/" + de->d_name ); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | bp.load( opts.sConfig ); | ||
| 203 | |||
| 204 | if( opts.bAstDump ) | ||
| 205 | { | ||
| 206 | sio << ast << sio.nl << sio.nl; | ||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | // sio << ast << sio.nl; | ||
| 211 | |||
| 212 | Runner r( ast, cnt ); | ||
| 213 | r.initialize(); | ||
| 214 | |||
| 215 | r.run(); | ||
| 216 | |||
| 217 | switch( opts.iInfoLevel ) | ||
| 218 | { | ||
| 219 | case 0: | ||
| 220 | // Do nothing | ||
| 221 | break; | ||
| 222 | |||
| 223 | case 1: | ||
| 224 | cnt.printBasicInfo(); | ||
| 225 | return 0; | ||
| 226 | } | ||
| 227 | |||
| 228 | try | ||
| 229 | { | ||
| 230 | r.execAction( opts.sAction ); | ||
| 231 | } | ||
| 232 | catch( std::exception &e ) | ||
| 233 | { | ||
| 234 | cnt.getView()->sysError(e.what()); | ||
| 235 | } | ||
| 236 | catch( ... ) | ||
| 237 | { | ||
| 238 | cnt.getView()->sysError( | ||
| 239 | "Unknown error occured, this is probably bad..." | ||
| 240 | ); | ||
| 241 | } | ||
| 242 | |||
| 243 | if( opts.bDot ) | ||
| 244 | { | ||
| 245 | cnt.writeTargetDot(); | ||
| 246 | } | ||
| 247 | |||
| 248 | if( opts.bDebug ) | ||
| 249 | { | ||
| 250 | sio << "Final context:" << sio.nl << cnt << sio.nl << sio.nl; | ||
| 251 | } | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
diff --git a/src/profile.cpp b/src/profile.cpp new file mode 100644 index 0000000..878a6e9 --- /dev/null +++ b/src/profile.cpp | |||
| @@ -0,0 +1,116 @@ | |||
| 1 | #include "profile.h" | ||
| 2 | #include "ast.h" | ||
| 3 | #include "astbranch.h" | ||
| 4 | #include "astleaf.h" | ||
| 5 | #include "condition.h" | ||
| 6 | |||
| 7 | #include "conditionfiletime.h" | ||
| 8 | #include "conditionalways.h" | ||
| 9 | #include "conditionnever.h" | ||
| 10 | |||
| 11 | #include <bu/sio.h> | ||
| 12 | using namespace Bu; | ||
| 13 | |||
| 14 | Profile::Profile( const class AstBranch *pRoot ) : | ||
| 15 | pRoot( pRoot ), | ||
| 16 | pCond( NULL ), | ||
| 17 | pAst( NULL ) | ||
| 18 | { | ||
| 19 | sName = dynamic_cast<const AstLeaf *>( | ||
| 20 | (*pRoot->getBranchBegin()).first() | ||
| 21 | )->getStrValue(); | ||
| 22 | |||
| 23 | setCondition(); | ||
| 24 | } | ||
| 25 | |||
| 26 | Profile::Profile( const Profile &rSrc ) : | ||
| 27 | sName( rSrc.sName ), | ||
| 28 | pRoot( rSrc.pRoot ), | ||
| 29 | pCond( rSrc.pCond->clone() ), | ||
| 30 | pAst( NULL ) | ||
| 31 | { | ||
| 32 | } | ||
| 33 | |||
| 34 | Profile::~Profile() | ||
| 35 | { | ||
| 36 | delete pAst; | ||
| 37 | pAst = NULL; | ||
| 38 | } | ||
| 39 | |||
| 40 | const Bu::FString &Profile::getName() const | ||
| 41 | { | ||
| 42 | return sName; | ||
| 43 | } | ||
| 44 | |||
| 45 | const AstBranch *Profile::getRoot() const | ||
| 46 | { | ||
| 47 | return pRoot; | ||
| 48 | } | ||
| 49 | |||
| 50 | const Condition *Profile::getCond() const | ||
| 51 | { | ||
| 52 | return pCond; | ||
| 53 | } | ||
| 54 | |||
| 55 | bool Profile::shouldExec( class Runner &r, class Target &rTarget ) const | ||
| 56 | { | ||
| 57 | return pCond->shouldExec( r, rTarget ); | ||
| 58 | } | ||
| 59 | |||
| 60 | Profile *Profile::genDefaultClean() | ||
| 61 | { | ||
| 62 | Ast *pAst = new Ast(); | ||
| 63 | pAst->addNode( AstNode::typeProfile ); | ||
| 64 | pAst->openBranch(); | ||
| 65 | pAst->addNode( AstNode::typeString, "clean" ); | ||
| 66 | pAst->openBranch(); | ||
| 67 | pAst->addNode( AstNode::typeCondition, "always" ); | ||
| 68 | pAst->addNode( AstNode::typeFunction ); | ||
| 69 | pAst->openBranch(); | ||
| 70 | pAst->addNode( AstNode::typeString, "unlink" ); | ||
| 71 | pAst->openBranch(); | ||
| 72 | pAst->addNode( AstNode::typeVariable, "OUTPUT" ); | ||
| 73 | pAst->closeNode(); | ||
| 74 | pAst->closeNode(); | ||
| 75 | //pAst->closeNode(); | ||
| 76 | Profile *pRet = new Profile( | ||
| 77 | dynamic_cast<const AstBranch *>(*pAst->getNodeBegin()) | ||
| 78 | ); | ||
| 79 | pRet->pAst = pAst; | ||
| 80 | |||
| 81 | return pRet; | ||
| 82 | } | ||
| 83 | |||
| 84 | void Profile::setCondition() | ||
| 85 | { | ||
| 86 | for( AstBranch::NodeList::const_iterator i = | ||
| 87 | (*(pRoot->getBranchBegin()+1)).begin(); i; i++ ) | ||
| 88 | { | ||
| 89 | if( (*i)->getType() == AstNode::typeCondition ) | ||
| 90 | { | ||
| 91 | Bu::FString sCond = dynamic_cast<const AstLeaf *>(*i)->getStrValue(); | ||
| 92 | if( sCond == "filetime" ) | ||
| 93 | { | ||
| 94 | delete pCond; | ||
| 95 | pCond = new ConditionFileTime(); | ||
| 96 | } | ||
| 97 | else if( sCond == "always" ) | ||
| 98 | { | ||
| 99 | delete pCond; | ||
| 100 | pCond = new ConditionAlways(); | ||
| 101 | } | ||
| 102 | else if( sCond == "never" ) | ||
| 103 | { | ||
| 104 | delete pCond; | ||
| 105 | pCond = new ConditionNever(); | ||
| 106 | } | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | if( pCond == NULL ) | ||
| 111 | { | ||
| 112 | // The default condition | ||
| 113 | pCond = new ConditionFileTime(); | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
diff --git a/src/profile.h b/src/profile.h new file mode 100644 index 0000000..dbcc1ea --- /dev/null +++ b/src/profile.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #ifndef PROFILE_H | ||
| 2 | #define PROFILE_H | ||
| 3 | |||
| 4 | #include <bu/fstring.h> | ||
| 5 | |||
| 6 | class Profile | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | Profile( const class AstBranch *pRoot ); | ||
| 10 | Profile( const Profile &rSrc ); | ||
| 11 | virtual ~Profile(); | ||
| 12 | |||
| 13 | const Bu::FString &getName() const; | ||
| 14 | const class AstBranch *getRoot() const; | ||
| 15 | const class Condition *getCond() const; | ||
| 16 | bool shouldExec( class Runner &r, class Target &rTarget ) const; | ||
| 17 | |||
| 18 | static Profile *genDefaultClean(); | ||
| 19 | |||
| 20 | private: | ||
| 21 | void setCondition(); | ||
| 22 | |||
| 23 | private: | ||
| 24 | Bu::FString sName; | ||
| 25 | const class AstBranch *pRoot; | ||
| 26 | class Condition *pCond; | ||
| 27 | class Ast *pAst; | ||
| 28 | }; | ||
| 29 | |||
| 30 | #endif | ||
diff --git a/src/rule.cpp b/src/rule.cpp new file mode 100644 index 0000000..4c42346 --- /dev/null +++ b/src/rule.cpp | |||
| @@ -0,0 +1,167 @@ | |||
| 1 | #include "rule.h" | ||
| 2 | #include "target.h" | ||
| 3 | #include "astbranch.h" | ||
| 4 | #include "astleaf.h" | ||
| 5 | #include "runner.h" | ||
| 6 | #include "variable.h" | ||
| 7 | #include "context.h" | ||
| 8 | #include "condition.h" | ||
| 9 | #include "profile.h" | ||
| 10 | |||
| 11 | #include <bu/sio.h> | ||
| 12 | using namespace Bu; | ||
| 13 | |||
| 14 | Rule::Rule( const Bu::FString &sName ) : | ||
| 15 | sName( sName ), | ||
| 16 | pInput( NULL ) | ||
| 17 | { | ||
| 18 | } | ||
| 19 | |||
| 20 | Rule::~Rule() | ||
| 21 | { | ||
| 22 | } | ||
| 23 | |||
| 24 | const Bu::FString &Rule::getName() const | ||
| 25 | { | ||
| 26 | return sName; | ||
| 27 | } | ||
| 28 | |||
| 29 | void Rule::setInput( const AstBranch *pNewInput ) | ||
| 30 | { | ||
| 31 | pInput = pNewInput; | ||
| 32 | } | ||
| 33 | |||
| 34 | const AstBranch *Rule::getInput() const | ||
| 35 | { | ||
| 36 | return pInput; | ||
| 37 | } | ||
| 38 | |||
| 39 | bool Rule::hasOutputs() const | ||
| 40 | { | ||
| 41 | return !lOutput.isEmpty(); | ||
| 42 | } | ||
| 43 | |||
| 44 | void Rule::addOutput( const AstBranch *pNewOutput ) | ||
| 45 | { | ||
| 46 | lOutput.append( pNewOutput ); | ||
| 47 | } | ||
| 48 | |||
| 49 | void Rule::addProfile( const AstBranch *pProfRoot ) | ||
| 50 | { | ||
| 51 | Profile *pProf = new Profile( pProfRoot ); | ||
| 52 | hProfiles.insert( pProf->getName(), pProf ); | ||
| 53 | /* | ||
| 54 | hProfiles.insert( | ||
| 55 | dynamic_cast<const AstLeaf *>( | ||
| 56 | (*pProfile->getBranchBegin()).first() | ||
| 57 | )->getStrValue(), | ||
| 58 | pProfile | ||
| 59 | ); | ||
| 60 | */ | ||
| 61 | } | ||
| 62 | |||
| 63 | void Rule::prepTarget( class Target *pTarget ) | ||
| 64 | { | ||
| 65 | pTarget->setDisplay( getDisplay() ); | ||
| 66 | for( ProfileHash::iterator i = hProfiles.begin(); i; i++ ) | ||
| 67 | { | ||
| 68 | pTarget->addProfile( *i ); | ||
| 69 | } | ||
| 70 | for( AstBranchList::iterator i = lRequires.begin(); i; i++ ) | ||
| 71 | { | ||
| 72 | pTarget->addRequires( *i ); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | Target *Rule::createTarget( class Runner &r, const Bu::FString &sInput ) | ||
| 77 | { | ||
| 78 | r.getContext().pushScope(); | ||
| 79 | r.getContext().addVariable("INPUT", sInput ); | ||
| 80 | Target *pTrg = new Target( false ); | ||
| 81 | for( AstBranchList::iterator i = lOutput.begin(); i; i++ ) | ||
| 82 | { | ||
| 83 | Variable vOut = r.execExpr( | ||
| 84 | (*(*i)->getBranchBegin()).begin(), | ||
| 85 | Variable( sInput ) | ||
| 86 | ); | ||
| 87 | if( vOut.getType() == Variable::typeString ) | ||
| 88 | { | ||
| 89 | pTrg->addOutput( vOut.getString() ); | ||
| 90 | } | ||
| 91 | else if( vOut.getType() == Variable::typeList ) | ||
| 92 | { | ||
| 93 | for( VarList::iterator j = vOut.begin(); j; j++ ) | ||
| 94 | { | ||
| 95 | pTrg->addOutput( (*j).getString() ); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | r.getContext().addVariable("OUTPUT", pTrg->getOutputList() ); | ||
| 100 | pTrg->addInput( sInput ); | ||
| 101 | pTrg->setDisplay( getDisplay() ); | ||
| 102 | for( ProfileHash::iterator i = hProfiles.begin(); i; i++ ) | ||
| 103 | { | ||
| 104 | pTrg->addProfile( *i ); | ||
| 105 | } | ||
| 106 | for( AstBranchList::iterator i = lRequires.begin(); i; i++ ) | ||
| 107 | { | ||
| 108 | pTrg->addRequires( *i ); | ||
| 109 | } | ||
| 110 | pTrg->setVars( r.getContext().getScope() ); | ||
| 111 | r.getContext().popScope(); | ||
| 112 | |||
| 113 | return pTrg; | ||
| 114 | } | ||
| 115 | |||
| 116 | bool Rule::ruleMatches( Runner &r, const Bu::FString &sInput ) | ||
| 117 | { | ||
| 118 | r.getContext().pushScope(); | ||
| 119 | r.getContext().addVariable("INPUT", sInput ); | ||
| 120 | Variable vInput( sInput ); | ||
| 121 | Variable vOut = r.execExpr( | ||
| 122 | (*pInput->getBranchBegin()).begin(), | ||
| 123 | vInput | ||
| 124 | ); | ||
| 125 | r.getContext().popScope(); | ||
| 126 | if( vOut.getType() == Variable::typeBool ) | ||
| 127 | return vOut.getBool(); | ||
| 128 | else if( vOut.getType() == Variable::typeList ) | ||
| 129 | return vOut.begin(); | ||
| 130 | return false; | ||
| 131 | } | ||
| 132 | |||
| 133 | void Rule::addTag( const Bu::FString &sTag ) | ||
| 134 | { | ||
| 135 | lsTags.append( sTag ); | ||
| 136 | } | ||
| 137 | |||
| 138 | const StrList &Rule::getTagList() const | ||
| 139 | { | ||
| 140 | return lsTags; | ||
| 141 | } | ||
| 142 | |||
| 143 | void Rule::setDisplay( const Bu::FString &sStr ) | ||
| 144 | { | ||
| 145 | sDisplay = sStr; | ||
| 146 | } | ||
| 147 | |||
| 148 | const Bu::FString &Rule::getDisplay() const | ||
| 149 | { | ||
| 150 | return ((bool)sDisplay)?(sDisplay):(sName); | ||
| 151 | } | ||
| 152 | |||
| 153 | void Rule::addRequires( const AstBranch *pBr ) | ||
| 154 | { | ||
| 155 | lRequires.append( pBr ); | ||
| 156 | } | ||
| 157 | |||
| 158 | Bu::Formatter &operator<<( Bu::Formatter &f, const Rule &/*t*/ ) | ||
| 159 | { | ||
| 160 | return f << "rule"; | ||
| 161 | } | ||
| 162 | |||
| 163 | template<> Bu::Formatter &Bu::operator<< <Rule>( Bu::Formatter &f, const Rule *t ) | ||
| 164 | { | ||
| 165 | return f << (*t); | ||
| 166 | } | ||
| 167 | |||
diff --git a/src/rule.h b/src/rule.h new file mode 100644 index 0000000..a3c9344 --- /dev/null +++ b/src/rule.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | #ifndef RULE_H | ||
| 2 | #define RULE_H | ||
| 3 | |||
| 4 | #include "types.h" | ||
| 5 | #include <bu/formatter.h> | ||
| 6 | |||
| 7 | class Rule | ||
| 8 | { | ||
| 9 | friend Bu::Formatter &operator<<( Bu::Formatter &f, const Rule &t ); | ||
| 10 | public: | ||
| 11 | Rule( const Bu::FString &sName ); | ||
| 12 | virtual ~Rule(); | ||
| 13 | |||
| 14 | const Bu::FString &getName() const; | ||
| 15 | |||
| 16 | void setInput( const AstBranch *pNewInput ); | ||
| 17 | const AstBranch *getInput() const; | ||
| 18 | |||
| 19 | bool hasOutputs() const; | ||
| 20 | |||
| 21 | void addOutput( const AstBranch *pNewOutput ); | ||
| 22 | void addProfile( const AstBranch *pProfile ); | ||
| 23 | |||
| 24 | void prepTarget( class Target *pTarget ); | ||
| 25 | class Target *createTarget( class Runner &r, const Bu::FString &sInput ); | ||
| 26 | bool ruleMatches( class Runner &r, const Bu::FString &sInput ); | ||
| 27 | |||
| 28 | void addTag( const Bu::FString &sTag ); | ||
| 29 | const StrList &getTagList() const; | ||
| 30 | |||
| 31 | void setDisplay( const Bu::FString &sStr ); | ||
| 32 | const Bu::FString &getDisplay() const; | ||
| 33 | |||
| 34 | void addRequires( const AstBranch *pBr ); | ||
| 35 | |||
| 36 | private: | ||
| 37 | Bu::FString sName; | ||
| 38 | Bu::FString sDisplay; | ||
| 39 | const AstBranch *pInput; | ||
| 40 | AstBranchList lOutput; | ||
| 41 | ProfileHash hProfiles; | ||
| 42 | StrList lsTags; | ||
| 43 | AstBranchList lRequires; | ||
| 44 | }; | ||
| 45 | |||
| 46 | Bu::Formatter &operator<<( Bu::Formatter &f, const Rule &t ); | ||
| 47 | |||
| 48 | namespace Bu | ||
| 49 | { | ||
| 50 | template<> Bu::Formatter &operator<< <Rule>( Bu::Formatter &f, const Rule *t ); | ||
| 51 | }; | ||
| 52 | |||
| 53 | #endif | ||
diff --git a/src/runner.cpp b/src/runner.cpp new file mode 100644 index 0000000..ace9ce9 --- /dev/null +++ b/src/runner.cpp | |||
| @@ -0,0 +1,922 @@ | |||
| 1 | #include "runner.h" | ||
| 2 | |||
| 3 | #include "ast.h" | ||
| 4 | #include "astnode.h" | ||
| 5 | #include "astleaf.h" | ||
| 6 | #include "astbranch.h" | ||
| 7 | #include "context.h" | ||
| 8 | #include "functionast.h" | ||
| 9 | #include "rule.h" | ||
| 10 | #include "variable.h" | ||
| 11 | #include "target.h" | ||
| 12 | #include "action.h" | ||
| 13 | #include "profile.h" | ||
| 14 | #include "view.h" | ||
| 15 | |||
| 16 | #include "bu/sio.h" | ||
| 17 | using Bu::sio; | ||
| 18 | |||
| 19 | Runner::Runner( Ast &rAst, Context &rCont ) : | ||
| 20 | rAst( rAst ), | ||
| 21 | rCont( rCont ), | ||
| 22 | pCurTarget( NULL ), | ||
| 23 | pCurRule( NULL ) | ||
| 24 | { | ||
| 25 | } | ||
| 26 | |||
| 27 | Runner::~Runner() | ||
| 28 | { | ||
| 29 | } | ||
| 30 | |||
| 31 | void Runner::initialize() | ||
| 32 | { | ||
| 33 | for( Ast::NodeList::const_iterator i = rAst.getNodeBegin(); i; i++ ) | ||
| 34 | { | ||
| 35 | if( (*i)->getType() == AstNode::typeFunctionDef ) | ||
| 36 | { | ||
| 37 | AstBranch *pFnc = dynamic_cast<AstBranch *>(*i); | ||
| 38 | rCont.addFunction( new FunctionAst( pFnc, this ) ); | ||
| 39 | } | ||
| 40 | else if( (*i)->getType() == AstNode::typeActionDef ) | ||
| 41 | { | ||
| 42 | AstBranch *pAction = dynamic_cast<AstBranch *>(*i); | ||
| 43 | rCont.addAction( new Action( pAction ) ); | ||
| 44 | } | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | Variable Runner::execFunc( const AstBranch *pFunc, Variable &vIn ) | ||
| 49 | { | ||
| 50 | Bu::FString sName = dynamic_cast<const AstLeaf *>( | ||
| 51 | (*pFunc->getBranchBegin()).first())->getStrValue(); | ||
| 52 | |||
| 53 | VarList lParams; | ||
| 54 | for( AstBranch::BranchList::const_iterator p = | ||
| 55 | pFunc->getBranchBegin()+1; p; p++ ) | ||
| 56 | { | ||
| 57 | lParams.append( execExpr( (*p).begin() ) ); | ||
| 58 | } | ||
| 59 | |||
| 60 | return rCont.call( sName, vIn, lParams ); | ||
| 61 | } | ||
| 62 | |||
| 63 | Variable Runner::execExpr( AstBranch::NodeList::const_iterator e ) | ||
| 64 | { | ||
| 65 | Variable vBlank; | ||
| 66 | return execExpr( e, vBlank ); | ||
| 67 | } | ||
| 68 | |||
| 69 | Variable Runner::execExpr( AstBranch::NodeList::const_iterator e, | ||
| 70 | const Variable &vIn ) | ||
| 71 | { | ||
| 72 | // Variable v( vIn ); | ||
| 73 | VarList lStack; | ||
| 74 | lStack.push( vIn ); | ||
| 75 | |||
| 76 | for(; e; e++ ) | ||
| 77 | { | ||
| 78 | if( ((*e)->getType()&AstNode::typeClassMask) == AstNode::typeBranch ) | ||
| 79 | { | ||
| 80 | const AstBranch *pBranch = dynamic_cast<const AstBranch *>( *e ); | ||
| 81 | switch( pBranch->getType() ) | ||
| 82 | { | ||
| 83 | case AstNode::typeFunction: | ||
| 84 | //sio << "FUNC: " << *pBranch << sio.nl << sio.nl; | ||
| 85 | { | ||
| 86 | Variable v = lStack.peekPop(); | ||
| 87 | lStack.push( execFunc( pBranch, v ) ); | ||
| 88 | } | ||
| 89 | break; | ||
| 90 | |||
| 91 | case AstNode::typeSet: | ||
| 92 | lStack.push( doSet( pBranch ) ); | ||
| 93 | break; | ||
| 94 | |||
| 95 | case AstNode::typeList: | ||
| 96 | { | ||
| 97 | Variable vLst( Variable::typeList ); | ||
| 98 | for( AstBranch::BranchList::const_iterator i = | ||
| 99 | pBranch->getBranchBegin(); i; i++ ) | ||
| 100 | { | ||
| 101 | vLst.append( execExpr( (*i).begin() ) ); | ||
| 102 | } | ||
| 103 | lStack.push( vLst ); | ||
| 104 | } | ||
| 105 | break; | ||
| 106 | |||
| 107 | case AstNode::typeExpr: | ||
| 108 | { | ||
| 109 | sio << "!!! typeExpr in an expr maybe should be an error..." << sio.nl; | ||
| 110 | for( AstBranch::BranchList::const_iterator i = | ||
| 111 | pBranch->getBranchBegin(); i; i++ ) | ||
| 112 | { | ||
| 113 | lStack.push( | ||
| 114 | execExpr( (*i).begin() ) // Are they atomic? | ||
| 115 | ); | ||
| 116 | } | ||
| 117 | if( lStack.getSize() != 1 ) | ||
| 118 | { | ||
| 119 | throw Bu::ExceptionBase( | ||
| 120 | "Something went wrong, expression processing " | ||
| 121 | "left %d elements on stack, should be 1.", | ||
| 122 | lStack.getSize() ); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | break; | ||
| 126 | |||
| 127 | default: | ||
| 128 | sio << "?? branch ???: " | ||
| 129 | << (pBranch)->getType(); | ||
| 130 | break; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | else | ||
| 134 | { | ||
| 135 | const AstLeaf *pLeaf = dynamic_cast<const AstLeaf *>( *e ); | ||
| 136 | switch( pLeaf->getType() ) | ||
| 137 | { | ||
| 138 | case AstNode::typeVariable: | ||
| 139 | try | ||
| 140 | { | ||
| 141 | lStack.push( | ||
| 142 | rCont.getVariable( pLeaf->getStrValue() ) | ||
| 143 | ); | ||
| 144 | } | ||
| 145 | catch(...) | ||
| 146 | { | ||
| 147 | lStack.push( Variable() ); | ||
| 148 | } | ||
| 149 | break; | ||
| 150 | |||
| 151 | case AstNode::typeVariableRef: | ||
| 152 | lStack.push( | ||
| 153 | Variable::mkRef( pLeaf->getStrValue() ) | ||
| 154 | ); | ||
| 155 | break; | ||
| 156 | |||
| 157 | case AstNode::typeString: | ||
| 158 | lStack.push( | ||
| 159 | rCont.expand( pLeaf->getStrValue() ) | ||
| 160 | ); | ||
| 161 | break; | ||
| 162 | |||
| 163 | case AstNode::typeInt: | ||
| 164 | lStack.push( | ||
| 165 | pLeaf->getIntValue() | ||
| 166 | ); | ||
| 167 | break; | ||
| 168 | |||
| 169 | case AstNode::typeFloat: | ||
| 170 | lStack.push( | ||
| 171 | pLeaf->getFloatValue() | ||
| 172 | ); | ||
| 173 | break; | ||
| 174 | |||
| 175 | case AstNode::typeBool: | ||
| 176 | lStack.push( | ||
| 177 | pLeaf->getBoolValue() | ||
| 178 | ); | ||
| 179 | break; | ||
| 180 | |||
| 181 | case AstNode::typeVersion: | ||
| 182 | break; | ||
| 183 | |||
| 184 | case AstNode::typeNull: | ||
| 185 | lStack.push( | ||
| 186 | Variable() | ||
| 187 | ); | ||
| 188 | break; | ||
| 189 | |||
| 190 | case AstNode::typeCmpEq: | ||
| 191 | { | ||
| 192 | Variable a, b; | ||
| 193 | a = lStack.peekPop(); | ||
| 194 | b = lStack.peekPop(); | ||
| 195 | lStack.push( Variable( a == b ) ); | ||
| 196 | } | ||
| 197 | break; | ||
| 198 | |||
| 199 | case AstNode::typeCmpLt: | ||
| 200 | { | ||
| 201 | Variable a, b; | ||
| 202 | a = lStack.peekPop(); | ||
| 203 | b = lStack.peekPop(); | ||
| 204 | lStack.push( Variable( b < a ) ); | ||
| 205 | } | ||
| 206 | break; | ||
| 207 | |||
| 208 | case AstNode::typeCmpGt: | ||
| 209 | { | ||
| 210 | Variable a, b; | ||
| 211 | a = lStack.peekPop(); | ||
| 212 | b = lStack.peekPop(); | ||
| 213 | lStack.push( Variable( b > a ) ); | ||
| 214 | } | ||
| 215 | break; | ||
| 216 | |||
| 217 | case AstNode::typeCmpNe: | ||
| 218 | { | ||
| 219 | Variable a, b; | ||
| 220 | a = lStack.peekPop(); | ||
| 221 | b = lStack.peekPop(); | ||
| 222 | lStack.push( Variable( a != b ) ); | ||
| 223 | } | ||
| 224 | break; | ||
| 225 | |||
| 226 | case AstNode::typeCmpLtEq: | ||
| 227 | { | ||
| 228 | Variable a, b; | ||
| 229 | a = lStack.peekPop(); | ||
| 230 | b = lStack.peekPop(); | ||
| 231 | lStack.push( Variable( b <= a ) ); | ||
| 232 | } | ||
| 233 | break; | ||
| 234 | |||
| 235 | case AstNode::typeCmpGtEq: | ||
| 236 | { | ||
| 237 | Variable a, b; | ||
| 238 | a = lStack.peekPop(); | ||
| 239 | b = lStack.peekPop(); | ||
| 240 | lStack.push( Variable( b >= a ) ); | ||
| 241 | } | ||
| 242 | break; | ||
| 243 | |||
| 244 | case AstNode::typeOpEq: | ||
| 245 | { | ||
| 246 | Variable ref, val; | ||
| 247 | val = lStack.peekPop(); | ||
| 248 | ref = lStack.peekPop(); | ||
| 249 | rCont.addVariable( ref.getString(), val ); | ||
| 250 | lStack.push( val ); | ||
| 251 | } | ||
| 252 | break; | ||
| 253 | |||
| 254 | case AstNode::typeOpPlusEq: | ||
| 255 | { | ||
| 256 | Variable ref, val; | ||
| 257 | val = lStack.peekPop(); | ||
| 258 | ref = lStack.peekPop(); | ||
| 259 | try | ||
| 260 | { | ||
| 261 | Variable &nVal = rCont.getVariable( | ||
| 262 | ref.getString() | ||
| 263 | ); | ||
| 264 | nVal += val; | ||
| 265 | lStack.push( nVal ); | ||
| 266 | } catch(...) | ||
| 267 | { | ||
| 268 | rCont.addVariable( ref.getString(), val ); | ||
| 269 | lStack.push( val ); | ||
| 270 | } | ||
| 271 | } | ||
| 272 | break; | ||
| 273 | |||
| 274 | case AstNode::typeOpPlusEqRaw: | ||
| 275 | { | ||
| 276 | Variable ref, val; | ||
| 277 | val = lStack.peekPop(); | ||
| 278 | ref = lStack.peekPop(); | ||
| 279 | try | ||
| 280 | { | ||
| 281 | Variable &nVal = rCont.getVariable( | ||
| 282 | ref.getString() | ||
| 283 | ); | ||
| 284 | nVal << val; | ||
| 285 | lStack.push( nVal ); | ||
| 286 | } catch(...) | ||
| 287 | { | ||
| 288 | rCont.addVariable( ref.getString(), val ); | ||
| 289 | lStack.push( val ); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | break; | ||
| 293 | |||
| 294 | case AstNode::typeOpPlus: | ||
| 295 | { | ||
| 296 | Variable a, b; | ||
| 297 | a = lStack.peekPop(); | ||
| 298 | b = lStack.peekPop(); | ||
| 299 | lStack.push( Variable( b + a ) ); | ||
| 300 | } | ||
| 301 | break; | ||
| 302 | |||
| 303 | case AstNode::typeOpMinus: | ||
| 304 | { | ||
| 305 | Variable a, b; | ||
| 306 | a = lStack.peekPop(); | ||
| 307 | b = lStack.peekPop(); | ||
| 308 | lStack.push( Variable( b - a ) ); | ||
| 309 | } | ||
| 310 | break; | ||
| 311 | |||
| 312 | case AstNode::typeOpMultiply: | ||
| 313 | { | ||
| 314 | Variable a, b; | ||
| 315 | a = lStack.peekPop(); | ||
| 316 | b = lStack.peekPop(); | ||
| 317 | lStack.push( Variable( b * a ) ); | ||
| 318 | } | ||
| 319 | break; | ||
| 320 | |||
| 321 | case AstNode::typeOpDivide: | ||
| 322 | { | ||
| 323 | Variable a, b; | ||
| 324 | a = lStack.peekPop(); | ||
| 325 | b = lStack.peekPop(); | ||
| 326 | lStack.push( Variable( b / a ) ); | ||
| 327 | } | ||
| 328 | break; | ||
| 329 | |||
| 330 | case AstNode::typeOpNegate: | ||
| 331 | lStack.peek().doNegate(); | ||
| 332 | break; | ||
| 333 | |||
| 334 | case AstNode::typeOpNot: | ||
| 335 | lStack.peek().doNot(); | ||
| 336 | break; | ||
| 337 | |||
| 338 | default: | ||
| 339 | sio << "?? leaf ???: " | ||
| 340 | << (pLeaf)->getType(); | ||
| 341 | break; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | return lStack.peek(); | ||
| 347 | } | ||
| 348 | |||
| 349 | void Runner::run() | ||
| 350 | { | ||
| 351 | run( rAst.getNodeBegin() ); | ||
| 352 | |||
| 353 | rCont.buildTargetTree( *this ); | ||
| 354 | |||
| 355 | rCont.attachDefaults(); | ||
| 356 | rCont.genDefaultActions(); | ||
| 357 | |||
| 358 | // rCont.writeTargetDot(); | ||
| 359 | } | ||
| 360 | |||
| 361 | Variable Runner::run( AstBranch::NodeList::const_iterator n ) | ||
| 362 | { | ||
| 363 | /* Execute the top level code. */ | ||
| 364 | |||
| 365 | Variable vReturn; | ||
| 366 | Bu::List<Ast::NodeList::const_iterator> sI; | ||
| 367 | sI.push( n ); | ||
| 368 | // for( Ast::NodeList::const_iterator i = rAst.getNodeBegin(); i; i++ ) | ||
| 369 | while( !sI.isEmpty() ) | ||
| 370 | { | ||
| 371 | while( !sI.isEmpty() && !(sI.peek()) ) | ||
| 372 | { | ||
| 373 | sI.pop(); | ||
| 374 | } | ||
| 375 | if( sI.isEmpty() ) | ||
| 376 | break; | ||
| 377 | Ast::NodeList::const_iterator &i = sI.peek(); | ||
| 378 | if( ((*i)->getType()&AstNode::typeClassMask) == AstNode::typeLeaf ) | ||
| 379 | { | ||
| 380 | const AstLeaf *pExpr = dynamic_cast<const AstLeaf *>( *i ); | ||
| 381 | switch( pExpr->getType() ) | ||
| 382 | { | ||
| 383 | case AstNode::typeError: | ||
| 384 | { | ||
| 385 | Bu::FString sMsg = rCont.expand( pExpr->getStrValue() ); | ||
| 386 | rCont.getView()->userError( sMsg.getStr() ); | ||
| 387 | throw Bu::ExceptionBase( sMsg.getStr() ); | ||
| 388 | } | ||
| 389 | break; | ||
| 390 | |||
| 391 | case AstNode::typeWarning: | ||
| 392 | rCont.getView()->userWarning( | ||
| 393 | rCont.expand( pExpr->getStrValue() ) | ||
| 394 | ); | ||
| 395 | break; | ||
| 396 | |||
| 397 | case AstNode::typeNotice: | ||
| 398 | rCont.getView()->userNotice( | ||
| 399 | rCont.expand( pExpr->getStrValue() ) | ||
| 400 | ); | ||
| 401 | break; | ||
| 402 | |||
| 403 | case AstNode::typeCondition: | ||
| 404 | break; | ||
| 405 | |||
| 406 | case AstNode::typeDisplay: | ||
| 407 | if( pCurTarget ) | ||
| 408 | { | ||
| 409 | pCurTarget->setDisplay( | ||
| 410 | rCont.expand( pExpr->getStrValue() ) | ||
| 411 | ); | ||
| 412 | } | ||
| 413 | else if( pCurRule ) | ||
| 414 | { | ||
| 415 | pCurRule->setDisplay( | ||
| 416 | rCont.expand( pExpr->getStrValue() ) | ||
| 417 | ); | ||
| 418 | } | ||
| 419 | break; | ||
| 420 | /* | ||
| 421 | case AstNode::typeCondition: | ||
| 422 | if( pCurTarget ) | ||
| 423 | { | ||
| 424 | if( pExpr->getStrValue() == "filetime" ) | ||
| 425 | { | ||
| 426 | pCurTarget->setCondition( | ||
| 427 | new ConditionFileTime() | ||
| 428 | ); | ||
| 429 | } | ||
| 430 | } | ||
| 431 | else if( pCurRule ) | ||
| 432 | { | ||
| 433 | if( pExpr->getStrValue() == "filetime" ) | ||
| 434 | { | ||
| 435 | pCurRule->setCondition( | ||
| 436 | new ConditionFileTime() | ||
| 437 | ); | ||
| 438 | } | ||
| 439 | } | ||
| 440 | else | ||
| 441 | { | ||
| 442 | throw Bu::ExceptionBase( | ||
| 443 | "You can only set a condition in a target or rule."); | ||
| 444 | } | ||
| 445 | break; | ||
| 446 | */ | ||
| 447 | default: | ||
| 448 | sio << "Leaf? " << (*i)->getType() << sio.nl; | ||
| 449 | break; | ||
| 450 | } | ||
| 451 | } | ||
| 452 | else | ||
| 453 | { | ||
| 454 | const AstBranch *pExpr = dynamic_cast<const AstBranch *>( *i ); | ||
| 455 | switch( pExpr->getType() ) | ||
| 456 | { | ||
| 457 | case AstNode::typeSet: | ||
| 458 | { | ||
| 459 | // This is effectively legacy, if we add the set | ||
| 460 | // keyword back in I want it to work. | ||
| 461 | doSet( pExpr ); | ||
| 462 | } | ||
| 463 | break; | ||
| 464 | |||
| 465 | case AstNode::typeUnset: | ||
| 466 | { | ||
| 467 | AstBranch::NodeList::const_iterator n = | ||
| 468 | (*pExpr->getBranchBegin()).begin(); | ||
| 469 | Bu::FString sVar = dynamic_cast<const AstLeaf *>( | ||
| 470 | *n )->getStrValue(); | ||
| 471 | rCont.delVariable( sVar ); | ||
| 472 | } | ||
| 473 | break; | ||
| 474 | |||
| 475 | case AstNode::typeIf: | ||
| 476 | { | ||
| 477 | AstBranch::BranchList::const_iterator b = | ||
| 478 | pExpr->getBranchBegin(); | ||
| 479 | |||
| 480 | Variable v = execExpr( (*b).begin() ); | ||
| 481 | if( v.getType() != Variable::typeBool ) | ||
| 482 | { | ||
| 483 | throw Bu::ExceptionBase( | ||
| 484 | "If statement evaluated to non-boolean."); | ||
| 485 | } | ||
| 486 | b++; | ||
| 487 | if( v.getBool() ) | ||
| 488 | { | ||
| 489 | i++; | ||
| 490 | sI.push( (*b).begin() ); | ||
| 491 | continue; | ||
| 492 | } | ||
| 493 | else | ||
| 494 | { | ||
| 495 | b++; | ||
| 496 | if( b ) | ||
| 497 | { | ||
| 498 | i++; | ||
| 499 | sI.push( (*b).begin() ); | ||
| 500 | continue; | ||
| 501 | } | ||
| 502 | } | ||
| 503 | } | ||
| 504 | break; | ||
| 505 | |||
| 506 | case AstNode::typeFor: | ||
| 507 | { | ||
| 508 | AstBranch::BranchList::const_iterator b = | ||
| 509 | pExpr->getBranchBegin(); | ||
| 510 | Bu::FString sVar = dynamic_cast<const AstLeaf *>( | ||
| 511 | (*b).first() )->getStrValue(); | ||
| 512 | b++; | ||
| 513 | Variable v = execExpr( (*b).begin() ); | ||
| 514 | b++; | ||
| 515 | for( VarList::const_iterator vi = v.getList().begin(); | ||
| 516 | vi; vi++ ) | ||
| 517 | { | ||
| 518 | rCont.addVariable( sVar, *vi ); | ||
| 519 | run( (*b).begin() ); | ||
| 520 | } | ||
| 521 | } | ||
| 522 | break; | ||
| 523 | |||
| 524 | case AstNode::typeFunction: | ||
| 525 | { | ||
| 526 | Variable vIn; | ||
| 527 | execFunc( pExpr, vIn ); | ||
| 528 | } | ||
| 529 | break; | ||
| 530 | |||
| 531 | case AstNode::typeReturn: | ||
| 532 | vReturn = execExpr( (*pExpr->getBranchBegin()).begin() ); | ||
| 533 | return vReturn; | ||
| 534 | break; | ||
| 535 | |||
| 536 | case AstNode::typeFunctionDef: | ||
| 537 | case AstNode::typeActionDef: | ||
| 538 | // We ignore these, we already dealt with them | ||
| 539 | break; | ||
| 540 | |||
| 541 | case AstNode::typeTarget: | ||
| 542 | // This actually runs exactly like a for loop, if there's | ||
| 543 | // only one item, then we only go once, if it's a list, go | ||
| 544 | // more than once :-P | ||
| 545 | if( pCurTarget == NULL ) | ||
| 546 | { | ||
| 547 | AstBranch::BranchList::const_iterator b = | ||
| 548 | pExpr->getBranchBegin(); | ||
| 549 | Variable vLoop = execExpr( (*b).begin() ); | ||
| 550 | b++; | ||
| 551 | if( vLoop.getType() == Variable::typeString ) | ||
| 552 | { | ||
| 553 | rCont.addTarget( | ||
| 554 | buildTarget( | ||
| 555 | vLoop.getString(), (*b).begin() | ||
| 556 | ) | ||
| 557 | ); | ||
| 558 | } | ||
| 559 | else if( vLoop.getType() == Variable::typeList ) | ||
| 560 | { | ||
| 561 | for( VarList::iterator i = vLoop.begin(); i; i++ ) | ||
| 562 | { | ||
| 563 | rCont.addTarget( | ||
| 564 | buildTarget( | ||
| 565 | (*i).getString(), (*b).begin() | ||
| 566 | ) | ||
| 567 | ); | ||
| 568 | } | ||
| 569 | } | ||
| 570 | } | ||
| 571 | else | ||
| 572 | { | ||
| 573 | throw Bu::ExceptionBase( | ||
| 574 | "You cannot declare a target within " | ||
| 575 | "a target decleration."); | ||
| 576 | } | ||
| 577 | break; | ||
| 578 | |||
| 579 | case AstNode::typeRuleDef: | ||
| 580 | if( pCurRule == NULL ) | ||
| 581 | { | ||
| 582 | AstBranch::BranchList::const_iterator b = | ||
| 583 | pExpr->getBranchBegin(); | ||
| 584 | Bu::FString sName = dynamic_cast<const AstLeaf *>( | ||
| 585 | (*b).first() | ||
| 586 | )->getStrValue(); | ||
| 587 | b++; | ||
| 588 | rCont.addRule( buildRule( sName, (*b).begin() ) ); | ||
| 589 | } | ||
| 590 | else | ||
| 591 | { | ||
| 592 | throw Bu::ExceptionBase( | ||
| 593 | "You cannot declare a rule within " | ||
| 594 | "a rule decleration."); | ||
| 595 | } | ||
| 596 | break; | ||
| 597 | |||
| 598 | case AstNode::typeInput: | ||
| 599 | if( pCurTarget != NULL ) | ||
| 600 | { | ||
| 601 | Variable vRet = execExpr( | ||
| 602 | (*pExpr->getBranchBegin()).begin() | ||
| 603 | ); | ||
| 604 | if( vRet.getType() == Variable::typeString ) | ||
| 605 | { | ||
| 606 | pCurTarget->addInput( vRet.getString() ); | ||
| 607 | } | ||
| 608 | else if( vRet.getType() == Variable::typeList ) | ||
| 609 | { | ||
| 610 | for( VarList::iterator i = vRet.begin(); i; i++ ) | ||
| 611 | { | ||
| 612 | pCurTarget->addInput( | ||
| 613 | (*i).getString() | ||
| 614 | ); | ||
| 615 | } | ||
| 616 | } | ||
| 617 | } | ||
| 618 | else if( pCurRule != NULL ) | ||
| 619 | { | ||
| 620 | pCurRule->setInput( pExpr ); | ||
| 621 | } | ||
| 622 | else | ||
| 623 | { | ||
| 624 | throw Bu::ExceptionBase( | ||
| 625 | "input can only occur within a target or rule."); | ||
| 626 | } | ||
| 627 | break; | ||
| 628 | |||
| 629 | case AstNode::typeRequires: | ||
| 630 | if( pCurTarget != NULL ) | ||
| 631 | { | ||
| 632 | Variable vRet = execExpr( | ||
| 633 | (*pExpr->getBranchBegin()).begin() | ||
| 634 | ); | ||
| 635 | if( vRet.getType() == Variable::typeString ) | ||
| 636 | { | ||
| 637 | pCurTarget->addRequires( vRet.getString() ); | ||
| 638 | } | ||
| 639 | else if( vRet.getType() == Variable::typeList ) | ||
| 640 | { | ||
| 641 | for( VarList::iterator i = vRet.begin(); i; i++ ) | ||
| 642 | { | ||
| 643 | pCurTarget->addRequires( | ||
| 644 | (*i).getString() | ||
| 645 | ); | ||
| 646 | } | ||
| 647 | } | ||
| 648 | } | ||
| 649 | else if( pCurRule != NULL ) | ||
| 650 | { | ||
| 651 | pCurRule->addRequires( pExpr ); | ||
| 652 | } | ||
| 653 | else | ||
| 654 | { | ||
| 655 | throw Bu::ExceptionBase( | ||
| 656 | "requires can only occur within a target or rule."); | ||
| 657 | } | ||
| 658 | break; | ||
| 659 | |||
| 660 | case AstNode::typeRule: | ||
| 661 | if( pCurTarget ) | ||
| 662 | { | ||
| 663 | pCurTarget->setRule( | ||
| 664 | dynamic_cast<const AstLeaf *>( | ||
| 665 | (*pExpr->getBranchBegin()).first() | ||
| 666 | )->getStrValue() | ||
| 667 | ); | ||
| 668 | } | ||
| 669 | else | ||
| 670 | { | ||
| 671 | throw Bu::ExceptionBase( | ||
| 672 | "rule can only occur within a target."); | ||
| 673 | } | ||
| 674 | break; | ||
| 675 | |||
| 676 | case AstNode::typeProfile: | ||
| 677 | if( pCurTarget ) | ||
| 678 | { | ||
| 679 | pCurTarget->addProfile( pExpr ); | ||
| 680 | } | ||
| 681 | else if( pCurRule ) | ||
| 682 | { | ||
| 683 | pCurRule->addProfile( pExpr ); | ||
| 684 | } | ||
| 685 | else | ||
| 686 | { | ||
| 687 | throw Bu::ExceptionBase( | ||
| 688 | "profile can only occur within a target or rule."); | ||
| 689 | } | ||
| 690 | break; | ||
| 691 | |||
| 692 | case AstNode::typeOutput: | ||
| 693 | if( pCurRule ) | ||
| 694 | { | ||
| 695 | pCurRule->addOutput( pExpr ); | ||
| 696 | } | ||
| 697 | else | ||
| 698 | { | ||
| 699 | throw Bu::ExceptionBase( | ||
| 700 | "output can only occur within a rule."); | ||
| 701 | } | ||
| 702 | break; | ||
| 703 | |||
| 704 | case AstNode::typeProcessTarget: | ||
| 705 | { | ||
| 706 | AstBranch::BranchList::const_iterator b = | ||
| 707 | pExpr->getBranchBegin(); | ||
| 708 | Bu::FString sProfile = dynamic_cast<const AstLeaf *>( | ||
| 709 | (*b).first() | ||
| 710 | )->getStrValue(); | ||
| 711 | b++; | ||
| 712 | Variable vTargs = execExpr( (*b).begin() ); | ||
| 713 | if( vTargs.getType() == Variable::typeString ) | ||
| 714 | { | ||
| 715 | rCont.getTarget( vTargs.getString() )->process( | ||
| 716 | *this, sProfile | ||
| 717 | ); | ||
| 718 | } | ||
| 719 | else if( vTargs.getType() == Variable::typeList ) | ||
| 720 | { | ||
| 721 | for( VarList::iterator v = vTargs.begin(); | ||
| 722 | v; v++ ) { | ||
| 723 | rCont.getTarget( (*v).getString() )->process( | ||
| 724 | *this, sProfile | ||
| 725 | ); | ||
| 726 | } | ||
| 727 | } | ||
| 728 | } | ||
| 729 | break; | ||
| 730 | |||
| 731 | case AstNode::typeTag: | ||
| 732 | if( pCurTarget ) | ||
| 733 | { | ||
| 734 | AstBranch::BranchList::const_iterator b = | ||
| 735 | pExpr->getBranchBegin(); | ||
| 736 | Variable vTags = execExpr( (*b).begin() ); | ||
| 737 | if( vTags.getType() == Variable::typeList ) | ||
| 738 | { | ||
| 739 | for( VarList::iterator i = vTags.begin(); i; i++ ) | ||
| 740 | { | ||
| 741 | rCont.addTargetToTag( pCurTarget, (*i).toString() ); | ||
| 742 | } | ||
| 743 | } | ||
| 744 | else | ||
| 745 | { | ||
| 746 | Bu::FString sTag = vTags.toString(); | ||
| 747 | if( sTag ) | ||
| 748 | { | ||
| 749 | rCont.addTargetToTag( pCurTarget, sTag ); | ||
| 750 | } | ||
| 751 | else | ||
| 752 | { | ||
| 753 | throw Bu::ExceptionBase( | ||
| 754 | "A tag evaluted to empty string." | ||
| 755 | ); | ||
| 756 | } | ||
| 757 | } | ||
| 758 | } | ||
| 759 | else if( pCurRule ) | ||
| 760 | { | ||
| 761 | AstBranch::BranchList::const_iterator b = | ||
| 762 | pExpr->getBranchBegin(); | ||
| 763 | Variable vTags = execExpr( (*b).begin() ); | ||
| 764 | if( vTags.getType() == Variable::typeList ) | ||
| 765 | { | ||
| 766 | for( VarList::iterator i = vTags.begin(); i; i++ ) | ||
| 767 | { | ||
| 768 | pCurRule->addTag( (*i).toString() ); | ||
| 769 | } | ||
| 770 | } | ||
| 771 | else | ||
| 772 | { | ||
| 773 | Bu::FString sTag = vTags.toString(); | ||
| 774 | if( sTag ) | ||
| 775 | { | ||
| 776 | pCurRule->addTag( sTag ); | ||
| 777 | } | ||
| 778 | else | ||
| 779 | { | ||
| 780 | throw Bu::ExceptionBase( | ||
| 781 | "A tag evaluted to empty string." | ||
| 782 | ); | ||
| 783 | } | ||
| 784 | } | ||
| 785 | } | ||
| 786 | else | ||
| 787 | { | ||
| 788 | throw Bu::ExceptionBase( | ||
| 789 | "tag can only occur within a target or rule."); | ||
| 790 | } | ||
| 791 | break; | ||
| 792 | |||
| 793 | case AstNode::typeExpr: | ||
| 794 | execExpr( (*pExpr->getBranchBegin()).begin() ); | ||
| 795 | break; | ||
| 796 | |||
| 797 | default: | ||
| 798 | sio << "Branch? " << (*i)->getType() << sio.nl; | ||
| 799 | break; | ||
| 800 | } | ||
| 801 | } | ||
| 802 | |||
| 803 | i++; | ||
| 804 | } | ||
| 805 | |||
| 806 | return vReturn; | ||
| 807 | } | ||
| 808 | |||
| 809 | void Runner::execProfile( Target *pTarget, const Bu::FString &sProfile ) | ||
| 810 | { | ||
| 811 | rCont.pushScope( pTarget->getVars() ); | ||
| 812 | run( (*(pTarget->getProfile( sProfile )->getRoot()-> | ||
| 813 | getBranchBegin()+1)).begin() ); | ||
| 814 | rCont.popScope(); | ||
| 815 | } | ||
| 816 | |||
| 817 | void Runner::execAction( const Bu::FString &sName ) | ||
| 818 | { | ||
| 819 | try | ||
| 820 | { | ||
| 821 | Action *pAct = rCont.getAction( sName ); | ||
| 822 | |||
| 823 | pAct->call( this ); | ||
| 824 | } | ||
| 825 | catch( Bu::HashException &e ) | ||
| 826 | { | ||
| 827 | Bu::FString sError("No such action '" + sName + "' found."); | ||
| 828 | rCont.getView()->sysError( sError ); | ||
| 829 | } | ||
| 830 | } | ||
| 831 | |||
| 832 | Context &Runner::getContext() | ||
| 833 | { | ||
| 834 | return rCont; | ||
| 835 | } | ||
| 836 | |||
| 837 | Target *Runner::buildTarget( const Bu::FString &sOutput, | ||
| 838 | AstBranch::NodeList::const_iterator n ) | ||
| 839 | { | ||
| 840 | Target *pTrg = NULL; | ||
| 841 | try | ||
| 842 | { | ||
| 843 | pTrg = rCont.getTarget( sOutput ); | ||
| 844 | rCont.pushScope( pTrg->getVars() ); | ||
| 845 | } | ||
| 846 | catch( Bu::HashException &e ) | ||
| 847 | { | ||
| 848 | pTrg = new Target( sOutput, true ); | ||
| 849 | rCont.pushScope(); | ||
| 850 | } | ||
| 851 | |||
| 852 | // sio << " (target) \"" << sOutput << "\" explicit." << sio.nl; | ||
| 853 | |||
| 854 | rCont.addVariable("OUTPUT", sOutput ); | ||
| 855 | pCurTarget = pTrg; | ||
| 856 | run( n ); | ||
| 857 | |||
| 858 | rCont.addVariable("INPUT", pTrg->getInputList() ); | ||
| 859 | pCurTarget = NULL; | ||
| 860 | |||
| 861 | pTrg->setVars( rCont.getScope() ); | ||
| 862 | rCont.popScope(); | ||
| 863 | |||
| 864 | return pTrg; | ||
| 865 | } | ||
| 866 | |||
| 867 | Rule *Runner::buildRule( const Bu::FString &sName, | ||
| 868 | AstBranch::NodeList::const_iterator n ) | ||
| 869 | { | ||
| 870 | Rule *pRule = new Rule( sName ); | ||
| 871 | |||
| 872 | rCont.pushScope(); | ||
| 873 | pCurRule = pRule; | ||
| 874 | run( n ); | ||
| 875 | rCont.popScope(); | ||
| 876 | pCurRule = NULL; | ||
| 877 | |||
| 878 | return pRule; | ||
| 879 | } | ||
| 880 | |||
| 881 | Variable Runner::doSet( const AstBranch *pRoot ) | ||
| 882 | { | ||
| 883 | AstBranch::NodeList::const_iterator n = | ||
| 884 | (*pRoot->getBranchBegin()).begin(); | ||
| 885 | Bu::FString sVar = dynamic_cast<const AstLeaf *>( *n )->getStrValue(); | ||
| 886 | n++; | ||
| 887 | const AstLeaf *pLeaf = dynamic_cast<const AstLeaf *>( *n ); | ||
| 888 | n++; | ||
| 889 | Variable v = execExpr( n ); | ||
| 890 | |||
| 891 | switch( pLeaf->getType() ) | ||
| 892 | { | ||
| 893 | case AstNode::typeOpEq: | ||
| 894 | rCont.addVariable( sVar, v ); | ||
| 895 | break; | ||
| 896 | |||
| 897 | case AstNode::typeOpPlusEq: | ||
| 898 | try | ||
| 899 | { | ||
| 900 | rCont.getVariable( sVar ) += v; | ||
| 901 | } catch(...) | ||
| 902 | { | ||
| 903 | rCont.addVariable( sVar, v ); | ||
| 904 | } | ||
| 905 | break; | ||
| 906 | |||
| 907 | case AstNode::typeOpPlusEqRaw: | ||
| 908 | try | ||
| 909 | { | ||
| 910 | rCont.getVariable( sVar ) << v; | ||
| 911 | } catch(...) | ||
| 912 | { | ||
| 913 | rCont.addVariable( sVar, v ); | ||
| 914 | } | ||
| 915 | break; | ||
| 916 | |||
| 917 | default: break; | ||
| 918 | } | ||
| 919 | |||
| 920 | return v; | ||
| 921 | } | ||
| 922 | |||
diff --git a/src/runner.h b/src/runner.h new file mode 100644 index 0000000..98894da --- /dev/null +++ b/src/runner.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | #ifndef RUNNER_H | ||
| 2 | #define RUNNER_H | ||
| 3 | |||
| 4 | #include "astbranch.h" | ||
| 5 | |||
| 6 | class Runner | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | Runner( class Ast &rAst, class Context &rCont ); | ||
| 10 | virtual ~Runner(); | ||
| 11 | |||
| 12 | /** | ||
| 13 | * Run through and pull out all of the functions. Maybe more later. | ||
| 14 | */ | ||
| 15 | void initialize(); | ||
| 16 | class Variable execExpr( AstBranch::NodeList::const_iterator e ); | ||
| 17 | class Variable execExpr( AstBranch::NodeList::const_iterator e, | ||
| 18 | const class Variable &vIn ); | ||
| 19 | void run(); | ||
| 20 | Variable run( AstBranch::NodeList::const_iterator n ); | ||
| 21 | class Variable execFunc( const class AstBranch *pFunc, | ||
| 22 | class Variable &vIn ); | ||
| 23 | void execProfile( class Target *pTarget, const Bu::FString &sProfile ); | ||
| 24 | void execAction( const Bu::FString &sName ); | ||
| 25 | |||
| 26 | Context &getContext(); | ||
| 27 | |||
| 28 | private: | ||
| 29 | class Target *buildTarget( const Bu::FString &sOutput, | ||
| 30 | AstBranch::NodeList::const_iterator n ); | ||
| 31 | class Rule *buildRule( const Bu::FString &sName, | ||
| 32 | AstBranch::NodeList::const_iterator n ); | ||
| 33 | void attachDefaults(); | ||
| 34 | Variable doSet( const AstBranch *pRoot ); | ||
| 35 | |||
| 36 | private: | ||
| 37 | class Ast &rAst; | ||
| 38 | class Context &rCont; | ||
| 39 | Target *pCurTarget; | ||
| 40 | Rule *pCurRule; | ||
| 41 | }; | ||
| 42 | |||
| 43 | #endif | ||
diff --git a/src/target.cpp b/src/target.cpp new file mode 100644 index 0000000..f3e54b7 --- /dev/null +++ b/src/target.cpp | |||
| @@ -0,0 +1,402 @@ | |||
| 1 | #include "target.h" | ||
| 2 | #include "variable.h" | ||
| 3 | #include "condition.h" | ||
| 4 | #include "astleaf.h" | ||
| 5 | #include "astbranch.h" | ||
| 6 | #include "runner.h" | ||
| 7 | #include "context.h" | ||
| 8 | #include "profile.h" | ||
| 9 | #include "view.h" | ||
| 10 | |||
| 11 | #include <bu/membuf.h> | ||
| 12 | #include <bu/formatter.h> | ||
| 13 | #include <bu/heap.h> | ||
| 14 | |||
| 15 | #include <bu/sio.h> | ||
| 16 | using namespace Bu; | ||
| 17 | |||
| 18 | Target::Target( bool bExplicit ) : | ||
| 19 | bExplicit( bExplicit ), | ||
| 20 | bRun( false ), | ||
| 21 | iDepCount( 0 ) | ||
| 22 | { | ||
| 23 | } | ||
| 24 | |||
| 25 | Target::Target( const Bu::FString &sOutput, bool bExplicit ) : | ||
| 26 | bExplicit( bExplicit ), | ||
| 27 | lsOutput( sOutput ), | ||
| 28 | iDepCount( 0 ) | ||
| 29 | { | ||
| 30 | } | ||
| 31 | |||
| 32 | Target::~Target() | ||
| 33 | { | ||
| 34 | } | ||
| 35 | |||
| 36 | void Target::addInput( const Bu::FString &sInput ) | ||
| 37 | { | ||
| 38 | lsInput.append( sInput ); | ||
| 39 | } | ||
| 40 | |||
| 41 | const StrList &Target::getInputList() const | ||
| 42 | { | ||
| 43 | return lsInput; | ||
| 44 | } | ||
| 45 | |||
| 46 | void Target::resetInputList( const StrList &lInputs ) | ||
| 47 | { | ||
| 48 | lsInput = lInputs; | ||
| 49 | if( lsInput.getSize() == 1 ) | ||
| 50 | { | ||
| 51 | hVars.insert("INPUT", lsInput.first() ); | ||
| 52 | } | ||
| 53 | else | ||
| 54 | { | ||
| 55 | Variable vInput( Variable::typeList ); | ||
| 56 | for( StrList::iterator i = lsInput.begin(); i; i++ ) | ||
| 57 | { | ||
| 58 | vInput.append( Variable( *i ) ); | ||
| 59 | } | ||
| 60 | hVars.insert("INPUT", vInput ); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | void Target::addRequires( const Bu::FString &sReq ) | ||
| 65 | { | ||
| 66 | lsRequires.append( sReq ); | ||
| 67 | } | ||
| 68 | |||
| 69 | void Target::addRequires( const AstBranch *pBr ) | ||
| 70 | { | ||
| 71 | lbRequires.append( pBr ); | ||
| 72 | } | ||
| 73 | |||
| 74 | const StrList &Target::getRequiresList() const | ||
| 75 | { | ||
| 76 | return lsRequires; | ||
| 77 | } | ||
| 78 | |||
| 79 | void Target::buildRequires( Runner &r ) | ||
| 80 | { | ||
| 81 | r.getContext().getView()->buildRequires( *this ); | ||
| 82 | r.getContext().pushScope( hVars ); | ||
| 83 | for( AstBranchList::iterator i = lbRequires.begin(); i; i++ ) | ||
| 84 | { | ||
| 85 | Variable v = r.execExpr( (*(*i)->getBranchBegin()).begin() ); | ||
| 86 | if( v.getType() == Variable::typeList ) | ||
| 87 | { | ||
| 88 | for( VarList::iterator j = v.begin(); j; j++ ) | ||
| 89 | { | ||
| 90 | Bu::FString sReq = (*j).toString(); | ||
| 91 | addRequires( sReq ); | ||
| 92 | try | ||
| 93 | { | ||
| 94 | addDep( r.getContext().getTarget( sReq ) ); | ||
| 95 | } | ||
| 96 | catch(...) { } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | else | ||
| 100 | { | ||
| 101 | Bu::FString sReq = v.toString(); | ||
| 102 | addRequires( sReq ); | ||
| 103 | try | ||
| 104 | { | ||
| 105 | addDep( r.getContext().getTarget( sReq ) ); | ||
| 106 | } | ||
| 107 | catch(...) { } | ||
| 108 | } | ||
| 109 | } | ||
| 110 | r.getContext().popScope(); | ||
| 111 | } | ||
| 112 | |||
| 113 | void Target::addOutput( const Bu::FString &sOutput ) | ||
| 114 | { | ||
| 115 | lsOutput.append( sOutput ); | ||
| 116 | } | ||
| 117 | |||
| 118 | const StrList &Target::getOutputList() const | ||
| 119 | { | ||
| 120 | return lsOutput; | ||
| 121 | } | ||
| 122 | |||
| 123 | void Target::setPrefix( const Bu::FString &sPrefix ) | ||
| 124 | { | ||
| 125 | this->sPrefix = sPrefix; | ||
| 126 | } | ||
| 127 | |||
| 128 | const Bu::FString &Target::getPrefix() const | ||
| 129 | { | ||
| 130 | return sPrefix; | ||
| 131 | } | ||
| 132 | |||
| 133 | void Target::setRule( const Bu::FString &sRule ) | ||
| 134 | { | ||
| 135 | this->sRule = sRule; | ||
| 136 | } | ||
| 137 | |||
| 138 | const Bu::FString &Target::getRule() const | ||
| 139 | { | ||
| 140 | return sRule; | ||
| 141 | } | ||
| 142 | |||
| 143 | bool Target::hasRule() const | ||
| 144 | { | ||
| 145 | return !sRule.isEmpty(); | ||
| 146 | } | ||
| 147 | |||
| 148 | bool Target::isExplicit() const | ||
| 149 | { | ||
| 150 | return bExplicit; | ||
| 151 | } | ||
| 152 | |||
| 153 | void Target::addDep( Target *pDep ) | ||
| 154 | { | ||
| 155 | lDeps.append( pDep ); | ||
| 156 | } | ||
| 157 | |||
| 158 | const TargetList &Target::getDepList() const | ||
| 159 | { | ||
| 160 | return lDeps; | ||
| 161 | } | ||
| 162 | |||
| 163 | void Target::addProfile( const class AstBranch *pProfRoot ) | ||
| 164 | { | ||
| 165 | Profile *pProf = new Profile( pProfRoot ); | ||
| 166 | hProfiles.insert( pProf->getName(), pProf ); | ||
| 167 | /* | ||
| 168 | hProfiles.insert( | ||
| 169 | dynamic_cast<const AstLeaf *>( | ||
| 170 | (*pProfRoot->getBranchBegin()).first() | ||
| 171 | )->getStrValue(), | ||
| 172 | pProfRoot | ||
| 173 | ); | ||
| 174 | */ | ||
| 175 | } | ||
| 176 | |||
| 177 | void Target::addProfile( const class Profile *pSrc ) | ||
| 178 | { | ||
| 179 | hProfiles.insert( pSrc->getName(), new Profile( *pSrc ) ); | ||
| 180 | } | ||
| 181 | |||
| 182 | bool Target::hasProfile( const Bu::FString &sName ) const | ||
| 183 | { | ||
| 184 | return hProfiles.has( sName ); | ||
| 185 | } | ||
| 186 | |||
| 187 | const Profile *Target::getProfile( const Bu::FString &sName ) const | ||
| 188 | { | ||
| 189 | return hProfiles.get( sName ); | ||
| 190 | } | ||
| 191 | |||
| 192 | void Target::setVars( const VarHash &hNewVars ) | ||
| 193 | { | ||
| 194 | hVars = hNewVars; | ||
| 195 | } | ||
| 196 | |||
| 197 | const VarHash &Target::getVars() const | ||
| 198 | { | ||
| 199 | return hVars; | ||
| 200 | } | ||
| 201 | |||
| 202 | void Target::setDisplay( const Bu::FString &sNewDisplay ) | ||
| 203 | { | ||
| 204 | if( !sDisplay ) | ||
| 205 | sDisplay = sNewDisplay; | ||
| 206 | } | ||
| 207 | |||
| 208 | const Bu::FString &Target::getDisplay() const | ||
| 209 | { | ||
| 210 | return sDisplay; | ||
| 211 | } | ||
| 212 | |||
| 213 | void Target::process( class Runner &r, const Bu::FString &sProfile ) | ||
| 214 | { | ||
| 215 | r.getContext().getView()->beginTarget( sProfile, *this ); | ||
| 216 | bRun = true; | ||
| 217 | bool bShouldExec = false; | ||
| 218 | |||
| 219 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
| 220 | { | ||
| 221 | if( (*i)->bRun ) | ||
| 222 | continue; | ||
| 223 | |||
| 224 | // TODO: This is important, in the future, it may be possible for a | ||
| 225 | // target to be triggered by multiple dependant targets, to cover for | ||
| 226 | // this the below mergeUnder should be *TEMPORARY* and the target | ||
| 227 | // that was marged to be reset post processing. | ||
| 228 | (*i)->mergeUnder( hVars ); | ||
| 229 | (*i)->process( r, sProfile ); | ||
| 230 | } | ||
| 231 | try | ||
| 232 | { | ||
| 233 | bShouldExec = hProfiles.get( sProfile )->shouldExec( r, *this ); | ||
| 234 | } | ||
| 235 | catch( Bu::HashException &e ) | ||
| 236 | { | ||
| 237 | } | ||
| 238 | |||
| 239 | if( !bShouldExec ) | ||
| 240 | { | ||
| 241 | r.getContext().getView()->skipTarget( sProfile, *this ); | ||
| 242 | } | ||
| 243 | else | ||
| 244 | { | ||
| 245 | r.getContext().getView()->processTarget( sProfile, *this ); | ||
| 246 | r.execProfile( this, sProfile ); | ||
| 247 | } | ||
| 248 | |||
| 249 | r.getContext().getView()->endTarget(); | ||
| 250 | } | ||
| 251 | |||
| 252 | void Target::mergeUnder( const VarHash &hNewVars ) | ||
| 253 | { | ||
| 254 | for( VarHash::const_iterator i = hNewVars.begin(); i; i++ ) | ||
| 255 | { | ||
| 256 | if( !hVars.has( i.getKey() ) ) | ||
| 257 | { | ||
| 258 | hVars.insert( i.getKey(), i.getValue() ); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | bool Target::hasRun() | ||
| 264 | { | ||
| 265 | return bRun; | ||
| 266 | } | ||
| 267 | |||
| 268 | void Target::mergeUnder( const Target *pSrc ) | ||
| 269 | { | ||
| 270 | // If either are explicit, then it's explicit | ||
| 271 | bExplicit = bExplicit || pSrc->bExplicit; | ||
| 272 | |||
| 273 | merge( lsInput, pSrc->lsInput ); | ||
| 274 | merge( lsRequires, pSrc->lsRequires ); | ||
| 275 | merge( lsOutput, pSrc->lsOutput ); | ||
| 276 | |||
| 277 | if( !sPrefix ) | ||
| 278 | sPrefix = pSrc->sPrefix; | ||
| 279 | |||
| 280 | sRule = pSrc->sRule; | ||
| 281 | |||
| 282 | mergeUnder( pSrc->hVars ); | ||
| 283 | |||
| 284 | // Deps? They should be computed much after merging anyway, peh! | ||
| 285 | |||
| 286 | for( ProfileHash::const_iterator i = pSrc->hProfiles.begin(); i; i++ ) | ||
| 287 | { | ||
| 288 | if( !hProfiles.has( i.getKey() ) ) | ||
| 289 | { | ||
| 290 | hProfiles.insert( i.getKey(), i.getValue() ); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | if( !sDisplay ) | ||
| 295 | sDisplay = pSrc->sDisplay; | ||
| 296 | |||
| 297 | // Now we need to reset our vars. | ||
| 298 | hVars.insert("INPUT", lsInput ); | ||
| 299 | hVars.insert("REQUIRES", lsRequires ); | ||
| 300 | hVars.insert("OUTPUT", lsOutput ); | ||
| 301 | } | ||
| 302 | |||
| 303 | void Target::merge( StrList &lOut, const StrList &lIn ) | ||
| 304 | { | ||
| 305 | Bu::Heap<Bu::FString> hStr; | ||
| 306 | for( StrList::const_iterator i = lOut.begin(); i; i++ ) | ||
| 307 | { | ||
| 308 | hStr.enqueue( *i ); | ||
| 309 | } | ||
| 310 | for( StrList::const_iterator i = lIn.begin(); i; i++ ) | ||
| 311 | { | ||
| 312 | hStr.enqueue( *i ); | ||
| 313 | } | ||
| 314 | |||
| 315 | lOut.clear(); | ||
| 316 | |||
| 317 | if( hStr.isEmpty() ) | ||
| 318 | return; | ||
| 319 | |||
| 320 | lOut.append( hStr.dequeue() ); | ||
| 321 | while( !hStr.isEmpty() ) | ||
| 322 | { | ||
| 323 | if( hStr.peek() == lOut.last() ) | ||
| 324 | { | ||
| 325 | hStr.dequeue(); | ||
| 326 | } | ||
| 327 | else | ||
| 328 | { | ||
| 329 | lOut.append( hStr.dequeue() ); | ||
| 330 | } | ||
| 331 | } | ||
| 332 | } | ||
| 333 | |||
| 334 | void Target::resetRun( bool bHasRun ) | ||
| 335 | { | ||
| 336 | bRun = bHasRun; | ||
| 337 | |||
| 338 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
| 339 | { | ||
| 340 | (*i)->resetRun( bHasRun ); | ||
| 341 | } | ||
| 342 | } | ||
| 343 | |||
| 344 | void Target::setDepCount() | ||
| 345 | { | ||
| 346 | bRun = true; | ||
| 347 | iDepCount = 1; | ||
| 348 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
| 349 | { | ||
| 350 | if( (*i)->bRun ) | ||
| 351 | { | ||
| 352 | continue; | ||
| 353 | } | ||
| 354 | (*i)->setDepCount(); | ||
| 355 | iDepCount += (*i)->getDepCount(); | ||
| 356 | } | ||
| 357 | } | ||
| 358 | |||
| 359 | int Target::getDepCount() const | ||
| 360 | { | ||
| 361 | return iDepCount; | ||
| 362 | } | ||
| 363 | |||
| 364 | void Target::collapseDeps() | ||
| 365 | { | ||
| 366 | if( lDeps.getSize() <= 1 ) | ||
| 367 | return; | ||
| 368 | Bu::Hash<ptrdiff_t, bool> hDep; | ||
| 369 | for( TargetList::iterator i = lDeps.begin(); i; i++ ) | ||
| 370 | { | ||
| 371 | if( hDep.has( (ptrdiff_t)*i ) ) | ||
| 372 | { | ||
| 373 | lDeps.erase( i ); | ||
| 374 | i--; | ||
| 375 | } | ||
| 376 | else | ||
| 377 | { | ||
| 378 | hDep.insert( (ptrdiff_t)*i, true ); | ||
| 379 | } | ||
| 380 | } | ||
| 381 | } | ||
| 382 | |||
| 383 | Bu::Formatter &operator<<( Bu::Formatter &f, const Target &t ) | ||
| 384 | { | ||
| 385 | f.incIndent(); | ||
| 386 | f << f.nl << "Input = " << t.lsInput << "," << f.nl | ||
| 387 | << "Requires = " << t.lsRequires << "," << f.nl | ||
| 388 | << "Output = \"" << t.lsOutput << "\"," << f.nl | ||
| 389 | << "Prefix = \"" << t.sPrefix << "\"," << f.nl | ||
| 390 | << "Rule = \"" << t.sRule << "\"," << f.nl | ||
| 391 | << "Explicit = " << t.bExplicit << "," << f.nl | ||
| 392 | << "Vars = " << t.hVars | ||
| 393 | << f.nl; | ||
| 394 | f.decIndent(); | ||
| 395 | return f; | ||
| 396 | } | ||
| 397 | |||
| 398 | template<> Bu::Formatter &Bu::operator<< <Target>( Bu::Formatter &f, const Target *t ) | ||
| 399 | { | ||
| 400 | return f << (*t); | ||
| 401 | } | ||
| 402 | |||
diff --git a/src/target.h b/src/target.h new file mode 100644 index 0000000..766366a --- /dev/null +++ b/src/target.h | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | #ifndef TARGET_H | ||
| 2 | #define TARGET_H | ||
| 3 | |||
| 4 | #include "types.h" | ||
| 5 | #include <bu/formatter.h> | ||
| 6 | |||
| 7 | class Target | ||
| 8 | { | ||
| 9 | friend Bu::Formatter &operator<<( Bu::Formatter &f, const Target &t ); | ||
| 10 | public: | ||
| 11 | Target( bool bExplicit ); | ||
| 12 | Target( const Bu::FString &sOutput, bool bExplicit ); | ||
| 13 | virtual ~Target(); | ||
| 14 | |||
| 15 | void addInput( const Bu::FString &sInput ); | ||
| 16 | const StrList &getInputList() const; | ||
| 17 | void resetInputList( const StrList &lInputs ); | ||
| 18 | |||
| 19 | void addRequires( const Bu::FString &sReq ); | ||
| 20 | void addRequires( const AstBranch *pBr ); | ||
| 21 | const StrList &getRequiresList() const; | ||
| 22 | void buildRequires( class Runner &r ); | ||
| 23 | |||
| 24 | void addOutput( const Bu::FString &sOutput ); | ||
| 25 | const StrList &getOutputList() const; | ||
| 26 | |||
| 27 | void setPrefix( const Bu::FString &sPrefix ); | ||
| 28 | const Bu::FString &getPrefix() const; | ||
| 29 | |||
| 30 | void setRule( const Bu::FString &sRule ); | ||
| 31 | const Bu::FString &getRule() const; | ||
| 32 | bool hasRule() const; | ||
| 33 | |||
| 34 | bool isExplicit() const; | ||
| 35 | |||
| 36 | void addDep( Target *pDep ); | ||
| 37 | const TargetList &getDepList() const; | ||
| 38 | |||
| 39 | void addProfile( const class AstBranch *pProfRoot ); | ||
| 40 | void addProfile( const class Profile *pSrc ); | ||
| 41 | bool hasProfile( const Bu::FString &sName ) const; | ||
| 42 | const class Profile *getProfile( const Bu::FString &sName ) const; | ||
| 43 | |||
| 44 | void setVars( const VarHash &hNewVars ); | ||
| 45 | const VarHash &getVars() const; | ||
| 46 | |||
| 47 | void setDisplay( const Bu::FString &sNewDisplay ); | ||
| 48 | const Bu::FString &getDisplay() const; | ||
| 49 | |||
| 50 | void process( class Runner &r, const Bu::FString &sProfile ); | ||
| 51 | |||
| 52 | void mergeUnder( const Target *pSrc ); | ||
| 53 | |||
| 54 | bool hasRun(); | ||
| 55 | |||
| 56 | void resetRun( bool bHasRun=true ); | ||
| 57 | void setDepCount(); | ||
| 58 | int getDepCount() const; | ||
| 59 | |||
| 60 | void collapseDeps(); | ||
| 61 | |||
| 62 | private: | ||
| 63 | void mergeUnder( const VarHash &hVars ); | ||
| 64 | void merge( StrList &lOut, const StrList &lIn ); | ||
| 65 | |||
| 66 | private: | ||
| 67 | bool bExplicit; | ||
| 68 | StrList lsInput; | ||
| 69 | StrList lsRequires; | ||
| 70 | StrList lsOutput; | ||
| 71 | Bu::FString sPrefix; | ||
| 72 | Bu::FString sRule; | ||
| 73 | VarHash hVars; | ||
| 74 | TargetList lDeps; | ||
| 75 | ProfileHash hProfiles; | ||
| 76 | Bu::FString sDisplay; | ||
| 77 | bool bRun; | ||
| 78 | AstBranchList lbRequires; | ||
| 79 | int iDepCount; | ||
| 80 | }; | ||
| 81 | |||
| 82 | Bu::Formatter &operator<<( Bu::Formatter &f, const Target &t ); | ||
| 83 | |||
| 84 | namespace Bu | ||
| 85 | { | ||
| 86 | template<> Bu::Formatter &operator<< <Target>( Bu::Formatter &f, const Target *t ); | ||
| 87 | }; | ||
| 88 | |||
| 89 | #endif | ||
diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..e405e35 --- /dev/null +++ b/src/types.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | #ifndef TYPES_H | ||
| 2 | #define TYPES_H | ||
| 3 | |||
| 4 | #include "bu/fstring.h" | ||
| 5 | #include "bu/list.h" | ||
| 6 | #include "bu/hash.h" | ||
| 7 | |||
| 8 | typedef Bu::List<Bu::FString> StrList; | ||
| 9 | |||
| 10 | class Variable; | ||
| 11 | typedef Bu::List<Variable> VarList; | ||
| 12 | typedef Bu::Hash<Bu::FString, Variable> VarHash; | ||
| 13 | |||
| 14 | class Condition; | ||
| 15 | |||
| 16 | class Target; | ||
| 17 | typedef Bu::List<Target *> TargetList; | ||
| 18 | class Profile; | ||
| 19 | typedef Bu::Hash<Bu::FString, Profile *> ProfileHash; | ||
| 20 | |||
| 21 | class AstNode; | ||
| 22 | class AstBranch; | ||
| 23 | class AstLeaf; | ||
| 24 | typedef Bu::List<const AstBranch *> AstBranchList; | ||
| 25 | |||
| 26 | #endif | ||
diff --git a/src/variable.cpp b/src/variable.cpp new file mode 100644 index 0000000..99bac59 --- /dev/null +++ b/src/variable.cpp | |||
| @@ -0,0 +1,892 @@ | |||
| 1 | #include "variable.h" | ||
| 2 | #include "astleaf.h" | ||
| 3 | #include "bu/sio.h" | ||
| 4 | using Bu::sio; | ||
| 5 | |||
| 6 | #include <stdlib.h> | ||
| 7 | |||
| 8 | Variable::Variable() : | ||
| 9 | eType( typeNone ) | ||
| 10 | { | ||
| 11 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 12 | } | ||
| 13 | |||
| 14 | Variable::Variable( Type t ) : | ||
| 15 | eType( t ) | ||
| 16 | { | ||
| 17 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 18 | if( eType == typeString || eType == typeRef ) | ||
| 19 | { | ||
| 20 | uVal.sVal = new Bu::FString; | ||
| 21 | } | ||
| 22 | else if( eType == typeList ) | ||
| 23 | { | ||
| 24 | uVal.lVal = new VarList; | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | Variable::Variable( int iVal ) : | ||
| 29 | eType( typeInt ) | ||
| 30 | { | ||
| 31 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 32 | uVal.iVal = iVal; | ||
| 33 | } | ||
| 34 | |||
| 35 | Variable::Variable( double fVal ) : | ||
| 36 | eType( typeFloat ) | ||
| 37 | { | ||
| 38 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 39 | uVal.fVal = fVal; | ||
| 40 | } | ||
| 41 | |||
| 42 | Variable::Variable( bool bVal ) : | ||
| 43 | eType( typeBool ) | ||
| 44 | { | ||
| 45 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 46 | uVal.bVal = bVal; | ||
| 47 | } | ||
| 48 | |||
| 49 | Variable::Variable( const Bu::FString &sVal ) : | ||
| 50 | eType( typeString ) | ||
| 51 | { | ||
| 52 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 53 | uVal.sVal = new Bu::FString( sVal ); | ||
| 54 | } | ||
| 55 | |||
| 56 | Variable::Variable( const char *sVal ) : | ||
| 57 | eType( typeString ) | ||
| 58 | { | ||
| 59 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 60 | uVal.sVal = new Bu::FString( sVal ); | ||
| 61 | } | ||
| 62 | |||
| 63 | Variable::Variable( const Variable &v ) : | ||
| 64 | eType( v.eType ) | ||
| 65 | { | ||
| 66 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 67 | if( eType == typeString || eType == typeRef ) | ||
| 68 | { | ||
| 69 | uVal.sVal = new Bu::FString( *v.uVal.sVal ); | ||
| 70 | } | ||
| 71 | else if( eType == typeList ) | ||
| 72 | { | ||
| 73 | uVal.lVal = new VarList( *v.uVal.lVal ); | ||
| 74 | } | ||
| 75 | else | ||
| 76 | { | ||
| 77 | uVal = v.uVal; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | Variable::Variable( const class AstLeaf &l ) | ||
| 82 | { | ||
| 83 | switch( l.getDataType() ) | ||
| 84 | { | ||
| 85 | case AstNode::typeDataInt: | ||
| 86 | eType = typeInt; | ||
| 87 | uVal.iVal = l.getIntValue(); | ||
| 88 | break; | ||
| 89 | |||
| 90 | case AstNode::typeDataFloat: | ||
| 91 | eType = typeFloat; | ||
| 92 | uVal.fVal = l.getFloatValue(); | ||
| 93 | break; | ||
| 94 | |||
| 95 | case AstNode::typeDataBool: | ||
| 96 | eType = typeBool; | ||
| 97 | uVal.bVal = l.getBoolValue(); | ||
| 98 | break; | ||
| 99 | |||
| 100 | case AstNode::typeDataString: | ||
| 101 | eType = typeString; | ||
| 102 | uVal.sVal = new Bu::FString( l.getStrValue() ); | ||
| 103 | break; | ||
| 104 | |||
| 105 | case AstNode::typeDataNone: | ||
| 106 | eType = typeNone; | ||
| 107 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 108 | break; | ||
| 109 | |||
| 110 | default: | ||
| 111 | sio << "Unhandled type <<!>>" << sio.nl << sio.nl; | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | Variable::Variable( const StrList &lst ) | ||
| 117 | { | ||
| 118 | if( lst.getSize() == 1 ) | ||
| 119 | { | ||
| 120 | eType = typeString; | ||
| 121 | uVal.sVal = new Bu::FString( lst.first() ); | ||
| 122 | } | ||
| 123 | else | ||
| 124 | { | ||
| 125 | eType = typeList; | ||
| 126 | uVal.lVal = new VarList(); | ||
| 127 | for( StrList::const_iterator i = lst.begin(); i; i++ ) | ||
| 128 | { | ||
| 129 | uVal.lVal->append( Variable( *i ) ); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | Variable::Variable( const VarList &lst ) | ||
| 135 | { | ||
| 136 | eType = typeList; | ||
| 137 | uVal.lVal = new VarList( lst ); | ||
| 138 | } | ||
| 139 | |||
| 140 | Variable::~Variable() | ||
| 141 | { | ||
| 142 | if( eType == typeString || eType == typeRef ) | ||
| 143 | { | ||
| 144 | delete uVal.sVal; | ||
| 145 | } | ||
| 146 | else if( eType == typeList ) | ||
| 147 | { | ||
| 148 | delete uVal.lVal; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 152 | Variable Variable::mkRef( const Bu::FString &sVal ) | ||
| 153 | { | ||
| 154 | Variable v( typeRef ); | ||
| 155 | (*v.uVal.sVal) = sVal; | ||
| 156 | return v; | ||
| 157 | } | ||
| 158 | |||
| 159 | Variable::Type Variable::getType() const | ||
| 160 | { | ||
| 161 | return eType; | ||
| 162 | } | ||
| 163 | |||
| 164 | int Variable::getInt() const | ||
| 165 | { | ||
| 166 | if( eType != typeInt ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 167 | return uVal.iVal; | ||
| 168 | } | ||
| 169 | |||
| 170 | double Variable::getFloat() const | ||
| 171 | { | ||
| 172 | if( eType != typeFloat ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 173 | return uVal.fVal; | ||
| 174 | } | ||
| 175 | |||
| 176 | bool Variable::getBool() const | ||
| 177 | { | ||
| 178 | if( eType != typeBool ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 179 | return uVal.bVal; | ||
| 180 | } | ||
| 181 | |||
| 182 | const Bu::FString &Variable::getString() const | ||
| 183 | { | ||
| 184 | if( eType != typeString && eType != typeRef ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 185 | return *uVal.sVal; | ||
| 186 | } | ||
| 187 | |||
| 188 | const VarList &Variable::getList() const | ||
| 189 | { | ||
| 190 | if( eType != typeList ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 191 | return *uVal.lVal; | ||
| 192 | } | ||
| 193 | |||
| 194 | int Variable::toInt() const | ||
| 195 | { | ||
| 196 | switch( eType ) | ||
| 197 | { | ||
| 198 | case typeInt: | ||
| 199 | return uVal.iVal; | ||
| 200 | |||
| 201 | case typeFloat: | ||
| 202 | return (int)uVal.fVal; | ||
| 203 | |||
| 204 | case typeBool: | ||
| 205 | return (uVal.bVal)?(1):(0); | ||
| 206 | |||
| 207 | case typeString: | ||
| 208 | case typeRef: | ||
| 209 | return strtol( uVal.sVal->getStr(), NULL, 0 ); | ||
| 210 | |||
| 211 | default: | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | |||
| 217 | double Variable::toFloat() const | ||
| 218 | { | ||
| 219 | switch( eType ) | ||
| 220 | { | ||
| 221 | case typeInt: | ||
| 222 | return (double)uVal.iVal; | ||
| 223 | |||
| 224 | case typeFloat: | ||
| 225 | return uVal.fVal; | ||
| 226 | |||
| 227 | case typeBool: | ||
| 228 | return (uVal.bVal)?(1.0):(0.0); | ||
| 229 | |||
| 230 | case typeString: | ||
| 231 | case typeRef: | ||
| 232 | return strtod( uVal.sVal->getStr(), NULL ); | ||
| 233 | |||
| 234 | default: | ||
| 235 | return 0.0; | ||
| 236 | } | ||
| 237 | return 0.0; | ||
| 238 | } | ||
| 239 | |||
| 240 | bool Variable::toBool() const | ||
| 241 | { | ||
| 242 | switch( eType ) | ||
| 243 | { | ||
| 244 | case typeInt: | ||
| 245 | return uVal.iVal != 0; | ||
| 246 | |||
| 247 | case typeFloat: | ||
| 248 | return uVal.fVal != 0.0; | ||
| 249 | |||
| 250 | case typeBool: | ||
| 251 | return uVal.bVal; | ||
| 252 | |||
| 253 | case typeString: | ||
| 254 | case typeRef: | ||
| 255 | return (*uVal.sVal) == "true"; | ||
| 256 | |||
| 257 | case typeList: | ||
| 258 | return !(*uVal.lVal).isEmpty(); | ||
| 259 | |||
| 260 | default: | ||
| 261 | return false; | ||
| 262 | } | ||
| 263 | return false; | ||
| 264 | } | ||
| 265 | |||
| 266 | Bu::FString Variable::toString() const | ||
| 267 | { | ||
| 268 | Bu::FString sRet; | ||
| 269 | switch( eType ) | ||
| 270 | { | ||
| 271 | case typeNone: | ||
| 272 | // No type, no data, we return empty string | ||
| 273 | break; | ||
| 274 | |||
| 275 | case typeInt: | ||
| 276 | sRet.format("%d", uVal.iVal ); | ||
| 277 | break; | ||
| 278 | |||
| 279 | case typeFloat: | ||
| 280 | sRet.format("%f", uVal.fVal ); | ||
| 281 | break; | ||
| 282 | |||
| 283 | case typeBool: | ||
| 284 | sRet = (uVal.bVal)?("true"):("false"); | ||
| 285 | break; | ||
| 286 | |||
| 287 | case typeString: | ||
| 288 | case typeRef: | ||
| 289 | sRet = *uVal.sVal; | ||
| 290 | break; | ||
| 291 | |||
| 292 | case typeList: | ||
| 293 | { | ||
| 294 | for( VarList::const_iterator i = uVal.lVal->begin(); i; i++ ) | ||
| 295 | { | ||
| 296 | if( i != uVal.lVal->begin() ) | ||
| 297 | sRet += " "; | ||
| 298 | sRet += (*i).toString(); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | break; | ||
| 302 | |||
| 303 | case typeVersion: | ||
| 304 | break; | ||
| 305 | } | ||
| 306 | |||
| 307 | return sRet; | ||
| 308 | } | ||
| 309 | |||
| 310 | VarList Variable::toList() const | ||
| 311 | { | ||
| 312 | if( eType == typeList ) | ||
| 313 | return *this; | ||
| 314 | return VarList( *this ); | ||
| 315 | } | ||
| 316 | |||
| 317 | Variable Variable::toType( Type eNewType ) const | ||
| 318 | { | ||
| 319 | switch( eNewType ) | ||
| 320 | { | ||
| 321 | case typeNone: | ||
| 322 | return Variable(); | ||
| 323 | |||
| 324 | case typeBool: | ||
| 325 | return Variable( toBool() ); | ||
| 326 | |||
| 327 | case typeInt: | ||
| 328 | return Variable( toInt() ); | ||
| 329 | |||
| 330 | case typeFloat: | ||
| 331 | return Variable( toFloat() ); | ||
| 332 | |||
| 333 | case typeVersion: | ||
| 334 | return Variable(); | ||
| 335 | |||
| 336 | case typeString: | ||
| 337 | return Variable( toString() ); | ||
| 338 | |||
| 339 | case typeList: | ||
| 340 | return Variable( toList() ); | ||
| 341 | |||
| 342 | case typeRef: | ||
| 343 | return Variable::mkRef( toString() ); | ||
| 344 | } | ||
| 345 | throw Bu::ExceptionBase("Unhandled case in Variable toType"); | ||
| 346 | } | ||
| 347 | |||
| 348 | void Variable::append( const Variable &v ) | ||
| 349 | { | ||
| 350 | if( eType != typeList ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 351 | |||
| 352 | if( v.eType == typeList ) | ||
| 353 | { | ||
| 354 | uVal.lVal->append( *v.uVal.lVal ); | ||
| 355 | } | ||
| 356 | else | ||
| 357 | { | ||
| 358 | uVal.lVal->append( v ); | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | VarList::iterator Variable::begin() | ||
| 363 | { | ||
| 364 | if( eType != typeList ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 365 | |||
| 366 | return uVal.lVal->begin(); | ||
| 367 | } | ||
| 368 | |||
| 369 | VarList::const_iterator Variable::begin() const | ||
| 370 | { | ||
| 371 | if( eType != typeList ) throw Bu::ExceptionBase("Wrong variable type."); | ||
| 372 | |||
| 373 | return const_cast<const VarList *>(uVal.lVal)->begin(); | ||
| 374 | } | ||
| 375 | |||
| 376 | void Variable::doNegate() | ||
| 377 | { | ||
| 378 | switch( eType ) | ||
| 379 | { | ||
| 380 | case typeNone: | ||
| 381 | break; | ||
| 382 | |||
| 383 | case typeBool: | ||
| 384 | throw Bu::ExceptionBase("You cannot negate boolean values."); | ||
| 385 | |||
| 386 | case typeInt: | ||
| 387 | uVal.iVal = -uVal.iVal; | ||
| 388 | break; | ||
| 389 | |||
| 390 | case typeFloat: | ||
| 391 | uVal.fVal = -uVal.fVal; | ||
| 392 | break; | ||
| 393 | |||
| 394 | case typeVersion: | ||
| 395 | throw Bu::ExceptionBase("You cannot negate version values."); | ||
| 396 | |||
| 397 | case typeString: | ||
| 398 | throw Bu::ExceptionBase("You cannot negate string values."); | ||
| 399 | |||
| 400 | case typeList: | ||
| 401 | throw Bu::ExceptionBase("You cannot negate list values."); | ||
| 402 | |||
| 403 | case typeRef: | ||
| 404 | throw Bu::ExceptionBase("You cannot negate reference values."); | ||
| 405 | } | ||
| 406 | } | ||
| 407 | |||
| 408 | void Variable::doNot() | ||
| 409 | { | ||
| 410 | bool bVal = !toBool(); | ||
| 411 | reset( typeBool ); | ||
| 412 | uVal.bVal = bVal; | ||
| 413 | } | ||
| 414 | |||
| 415 | const Variable &Variable::operator=( const Variable &rhs ) | ||
| 416 | { | ||
| 417 | reset( rhs.eType ); | ||
| 418 | if( rhs.eType == typeString || rhs.eType == typeRef ) | ||
| 419 | { | ||
| 420 | uVal.sVal = new Bu::FString( *rhs.uVal.sVal ); | ||
| 421 | } | ||
| 422 | else if( rhs.eType == typeList ) | ||
| 423 | { | ||
| 424 | uVal.lVal = new VarList( *rhs.uVal.lVal ); | ||
| 425 | } | ||
| 426 | else | ||
| 427 | { | ||
| 428 | uVal = rhs.uVal; | ||
| 429 | } | ||
| 430 | |||
| 431 | return *this; | ||
| 432 | } | ||
| 433 | |||
| 434 | const Variable &Variable::operator=( const int &rhs ) | ||
| 435 | { | ||
| 436 | reset( typeInt ); | ||
| 437 | uVal.iVal = rhs; | ||
| 438 | |||
| 439 | return *this; | ||
| 440 | } | ||
| 441 | |||
| 442 | const Variable &Variable::operator=( const double &rhs ) | ||
| 443 | { | ||
| 444 | reset( typeFloat ); | ||
| 445 | uVal.fVal = rhs; | ||
| 446 | |||
| 447 | return *this; | ||
| 448 | } | ||
| 449 | |||
| 450 | const Variable &Variable::operator=( const bool &rhs ) | ||
| 451 | { | ||
| 452 | reset( typeBool ); | ||
| 453 | uVal.bVal = rhs; | ||
| 454 | |||
| 455 | return *this; | ||
| 456 | } | ||
| 457 | |||
| 458 | const Variable &Variable::operator=( const Bu::FString &rhs ) | ||
| 459 | { | ||
| 460 | reset( typeString ); | ||
| 461 | uVal.sVal = new Bu::FString( rhs ); | ||
| 462 | |||
| 463 | return *this; | ||
| 464 | } | ||
| 465 | |||
| 466 | const Variable &Variable::operator+=( const Variable &rhs ) | ||
| 467 | { | ||
| 468 | switch( eType ) | ||
| 469 | { | ||
| 470 | case typeNone: | ||
| 471 | reset( rhs.eType ); | ||
| 472 | if( eType == typeString || eType == typeRef ) | ||
| 473 | { | ||
| 474 | uVal.sVal = new Bu::FString( *rhs.uVal.sVal ); | ||
| 475 | } | ||
| 476 | else if( eType == typeList ) | ||
| 477 | { | ||
| 478 | uVal.lVal = new VarList( *rhs.uVal.lVal ); | ||
| 479 | } | ||
| 480 | else | ||
| 481 | { | ||
| 482 | uVal = rhs.uVal; | ||
| 483 | } | ||
| 484 | break; | ||
| 485 | |||
| 486 | case typeInt: | ||
| 487 | uVal.iVal += rhs.getInt(); | ||
| 488 | break; | ||
| 489 | |||
| 490 | case typeFloat: | ||
| 491 | uVal.fVal += rhs.getFloat(); | ||
| 492 | break; | ||
| 493 | |||
| 494 | case typeBool: | ||
| 495 | throw Bu::ExceptionBase("Can't += with a boolean..."); | ||
| 496 | break; | ||
| 497 | |||
| 498 | case typeString: | ||
| 499 | uVal.sVal->append(" "); | ||
| 500 | uVal.sVal->append( rhs.getString() ); | ||
| 501 | break; | ||
| 502 | |||
| 503 | case typeList: | ||
| 504 | uVal.lVal->append( rhs.getList() ); | ||
| 505 | break; | ||
| 506 | |||
| 507 | case typeVersion: | ||
| 508 | break; | ||
| 509 | |||
| 510 | default: | ||
| 511 | break; | ||
| 512 | } | ||
| 513 | return *this; | ||
| 514 | } | ||
| 515 | |||
| 516 | const Variable &Variable::operator<<( const Variable &rhs ) | ||
| 517 | { | ||
| 518 | switch( eType ) | ||
| 519 | { | ||
| 520 | case typeNone: | ||
| 521 | reset( rhs.eType ); | ||
| 522 | if( eType == typeString ) | ||
| 523 | { | ||
| 524 | uVal.sVal = new Bu::FString( *rhs.uVal.sVal ); | ||
| 525 | } | ||
| 526 | else if( eType == typeList ) | ||
| 527 | { | ||
| 528 | uVal.lVal = new VarList( *rhs.uVal.lVal ); | ||
| 529 | } | ||
| 530 | else | ||
| 531 | { | ||
| 532 | uVal = rhs.uVal; | ||
| 533 | } | ||
| 534 | break; | ||
| 535 | |||
| 536 | case typeString: | ||
| 537 | uVal.sVal->append( rhs.getString() ); | ||
| 538 | break; | ||
| 539 | |||
| 540 | case typeList: | ||
| 541 | uVal.lVal->append( rhs.getList() ); | ||
| 542 | break; | ||
| 543 | |||
| 544 | default: | ||
| 545 | throw Bu::ExceptionBase("Can't << with non-string or non-list."); | ||
| 546 | break; | ||
| 547 | } | ||
| 548 | return *this; | ||
| 549 | } | ||
| 550 | |||
| 551 | bool Variable::operator==( const Variable &rhs ) const | ||
| 552 | { | ||
| 553 | if( eType != rhs.eType ) | ||
| 554 | return false; | ||
| 555 | switch( eType ) | ||
| 556 | { | ||
| 557 | case typeNone: | ||
| 558 | return true; | ||
| 559 | |||
| 560 | case typeInt: | ||
| 561 | return uVal.iVal == rhs.uVal.iVal; | ||
| 562 | |||
| 563 | case typeFloat: | ||
| 564 | return uVal.fVal == rhs.uVal.fVal; | ||
| 565 | |||
| 566 | case typeBool: | ||
| 567 | return uVal.bVal == rhs.uVal.bVal; | ||
| 568 | |||
| 569 | case typeString: | ||
| 570 | case typeRef: | ||
| 571 | return *uVal.sVal == *rhs.uVal.sVal; | ||
| 572 | |||
| 573 | case typeList: | ||
| 574 | return *uVal.lVal == *rhs.uVal.lVal; | ||
| 575 | |||
| 576 | case typeVersion: | ||
| 577 | return false; | ||
| 578 | } | ||
| 579 | |||
| 580 | return false; | ||
| 581 | } | ||
| 582 | |||
| 583 | bool Variable::operator!=( const Variable &rhs ) const | ||
| 584 | { | ||
| 585 | return !(*this == rhs); | ||
| 586 | } | ||
| 587 | |||
| 588 | bool Variable::operator<( const Variable &rhs ) const | ||
| 589 | { | ||
| 590 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 591 | switch( eTop ) | ||
| 592 | { | ||
| 593 | case typeNone: | ||
| 594 | return false; | ||
| 595 | |||
| 596 | case typeBool: | ||
| 597 | throw Bu::ExceptionBase("You cannot < compare boolean values."); | ||
| 598 | |||
| 599 | case typeInt: | ||
| 600 | return toInt() < rhs.toInt(); | ||
| 601 | |||
| 602 | case typeFloat: | ||
| 603 | return toFloat() < rhs.toFloat(); | ||
| 604 | |||
| 605 | case typeVersion: | ||
| 606 | return true; | ||
| 607 | |||
| 608 | case typeString: | ||
| 609 | return toString() < rhs.toString(); | ||
| 610 | |||
| 611 | case typeList: | ||
| 612 | throw Bu::ExceptionBase("You cannot < compare list values."); | ||
| 613 | |||
| 614 | case typeRef: | ||
| 615 | throw Bu::ExceptionBase("You cannot < compare reference values."); | ||
| 616 | } | ||
| 617 | throw Bu::ExceptionBase("Unhandled case in Variable < compare"); | ||
| 618 | } | ||
| 619 | |||
| 620 | bool Variable::operator>( const Variable &rhs ) const | ||
| 621 | { | ||
| 622 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 623 | switch( eTop ) | ||
| 624 | { | ||
| 625 | case typeNone: | ||
| 626 | return false; | ||
| 627 | |||
| 628 | case typeBool: | ||
| 629 | throw Bu::ExceptionBase("You cannot > compare boolean values."); | ||
| 630 | |||
| 631 | case typeInt: | ||
| 632 | return toInt() > rhs.toInt(); | ||
| 633 | |||
| 634 | case typeFloat: | ||
| 635 | return toFloat() > rhs.toFloat(); | ||
| 636 | |||
| 637 | case typeVersion: | ||
| 638 | return true; | ||
| 639 | |||
| 640 | case typeString: | ||
| 641 | return toString() > rhs.toString(); | ||
| 642 | |||
| 643 | case typeList: | ||
| 644 | throw Bu::ExceptionBase("You cannot > compare list values."); | ||
| 645 | |||
| 646 | case typeRef: | ||
| 647 | throw Bu::ExceptionBase("You cannot > compare reference values."); | ||
| 648 | } | ||
| 649 | throw Bu::ExceptionBase("Unhandled case in Variable > compare"); | ||
| 650 | } | ||
| 651 | |||
| 652 | bool Variable::operator<=( const Variable &rhs ) const | ||
| 653 | { | ||
| 654 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 655 | switch( eTop ) | ||
| 656 | { | ||
| 657 | case typeNone: | ||
| 658 | return false; | ||
| 659 | |||
| 660 | case typeBool: | ||
| 661 | throw Bu::ExceptionBase("You cannot <= compare boolean values."); | ||
| 662 | |||
| 663 | case typeInt: | ||
| 664 | return toInt() <= rhs.toInt(); | ||
| 665 | |||
| 666 | case typeFloat: | ||
| 667 | return toFloat() <= rhs.toFloat(); | ||
| 668 | |||
| 669 | case typeVersion: | ||
| 670 | return true; | ||
| 671 | |||
| 672 | case typeString: | ||
| 673 | return toString() <= rhs.toString(); | ||
| 674 | |||
| 675 | case typeList: | ||
| 676 | throw Bu::ExceptionBase("You cannot <= compare list values."); | ||
| 677 | |||
| 678 | case typeRef: | ||
| 679 | throw Bu::ExceptionBase("You cannot <= compare reference values."); | ||
| 680 | } | ||
| 681 | throw Bu::ExceptionBase("Unhandled case in Variable <= compare"); | ||
| 682 | } | ||
| 683 | |||
| 684 | bool Variable::operator>=( const Variable &rhs ) const | ||
| 685 | { | ||
| 686 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 687 | switch( eTop ) | ||
| 688 | { | ||
| 689 | case typeNone: | ||
| 690 | return false; | ||
| 691 | |||
| 692 | case typeBool: | ||
| 693 | throw Bu::ExceptionBase("You cannot >= compare boolean values."); | ||
| 694 | |||
| 695 | case typeInt: | ||
| 696 | return toInt() >= rhs.toInt(); | ||
| 697 | |||
| 698 | case typeFloat: | ||
| 699 | return toFloat() >= rhs.toFloat(); | ||
| 700 | |||
| 701 | case typeVersion: | ||
| 702 | return true; | ||
| 703 | |||
| 704 | case typeString: | ||
| 705 | return toString() >= rhs.toString(); | ||
| 706 | |||
| 707 | case typeList: | ||
| 708 | throw Bu::ExceptionBase("You cannot >= compare list values."); | ||
| 709 | |||
| 710 | case typeRef: | ||
| 711 | throw Bu::ExceptionBase("You cannot >= compare reference values."); | ||
| 712 | } | ||
| 713 | throw Bu::ExceptionBase("Unhandled case in Variable >= compare"); | ||
| 714 | } | ||
| 715 | |||
| 716 | Variable Variable::operator+( const Variable &rhs ) const | ||
| 717 | { | ||
| 718 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 719 | switch( eTop ) | ||
| 720 | { | ||
| 721 | case typeNone: | ||
| 722 | return Variable(); | ||
| 723 | |||
| 724 | case typeBool: | ||
| 725 | throw Bu::ExceptionBase("You cannot add boolean values."); | ||
| 726 | |||
| 727 | case typeInt: | ||
| 728 | return Variable( toInt() + rhs.toInt() ); | ||
| 729 | |||
| 730 | case typeFloat: | ||
| 731 | return Variable( toFloat() + rhs.toFloat() ); | ||
| 732 | |||
| 733 | case typeVersion: | ||
| 734 | throw Bu::ExceptionBase("You cannot add version values."); | ||
| 735 | |||
| 736 | case typeString: | ||
| 737 | return Variable( toString() + rhs.toString() ); | ||
| 738 | |||
| 739 | case typeList: | ||
| 740 | return Variable( toList() + rhs.toList() ); | ||
| 741 | |||
| 742 | case typeRef: | ||
| 743 | throw Bu::ExceptionBase("You cannot add reference values."); | ||
| 744 | } | ||
| 745 | throw Bu::ExceptionBase("Unhandled case in Variable add"); | ||
| 746 | } | ||
| 747 | |||
| 748 | Variable Variable::operator-( const Variable &rhs ) const | ||
| 749 | { | ||
| 750 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 751 | switch( eTop ) | ||
| 752 | { | ||
| 753 | case typeNone: | ||
| 754 | return Variable(); | ||
| 755 | |||
| 756 | case typeBool: | ||
| 757 | throw Bu::ExceptionBase("You cannot subtract boolean values."); | ||
| 758 | |||
| 759 | case typeInt: | ||
| 760 | return Variable( toInt() - rhs.toInt() ); | ||
| 761 | |||
| 762 | case typeFloat: | ||
| 763 | return Variable( toFloat() - rhs.toFloat() ); | ||
| 764 | |||
| 765 | case typeVersion: | ||
| 766 | throw Bu::ExceptionBase("You cannot subtract version values."); | ||
| 767 | |||
| 768 | case typeString: | ||
| 769 | throw Bu::ExceptionBase("You cannot subtract string values."); | ||
| 770 | |||
| 771 | case typeList: | ||
| 772 | throw Bu::ExceptionBase("You cannot subtract list values."); | ||
| 773 | |||
| 774 | case typeRef: | ||
| 775 | throw Bu::ExceptionBase("You cannot subtract reference values."); | ||
| 776 | } | ||
| 777 | throw Bu::ExceptionBase("Unhandled case in Variable subtract"); | ||
| 778 | } | ||
| 779 | |||
| 780 | Variable Variable::operator*( const Variable &rhs ) const | ||
| 781 | { | ||
| 782 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 783 | switch( eTop ) | ||
| 784 | { | ||
| 785 | case typeNone: | ||
| 786 | return Variable(); | ||
| 787 | |||
| 788 | case typeBool: | ||
| 789 | throw Bu::ExceptionBase("You cannot multiply boolean values."); | ||
| 790 | |||
| 791 | case typeInt: | ||
| 792 | return Variable( toInt() * rhs.toInt() ); | ||
| 793 | |||
| 794 | case typeFloat: | ||
| 795 | return Variable( toFloat() * rhs.toFloat() ); | ||
| 796 | |||
| 797 | case typeVersion: | ||
| 798 | throw Bu::ExceptionBase("You cannot multiply version values."); | ||
| 799 | |||
| 800 | case typeString: | ||
| 801 | throw Bu::ExceptionBase("You cannot multiply string values."); | ||
| 802 | |||
| 803 | case typeList: | ||
| 804 | throw Bu::ExceptionBase("You cannot multiply list values."); | ||
| 805 | |||
| 806 | case typeRef: | ||
| 807 | throw Bu::ExceptionBase("You cannot multiply reference values."); | ||
| 808 | } | ||
| 809 | throw Bu::ExceptionBase("Unhandled case in Variable multiply"); | ||
| 810 | } | ||
| 811 | |||
| 812 | Variable Variable::operator/( const Variable &rhs ) const | ||
| 813 | { | ||
| 814 | Type eTop = Bu::max( eType, rhs.eType ); | ||
| 815 | switch( eTop ) | ||
| 816 | { | ||
| 817 | case typeNone: | ||
| 818 | return Variable(); | ||
| 819 | |||
| 820 | case typeBool: | ||
| 821 | throw Bu::ExceptionBase("You cannot divide boolean values."); | ||
| 822 | |||
| 823 | case typeInt: | ||
| 824 | return Variable( toInt() / rhs.toInt() ); | ||
| 825 | |||
| 826 | case typeFloat: | ||
| 827 | return Variable( toFloat() / rhs.toFloat() ); | ||
| 828 | |||
| 829 | case typeVersion: | ||
| 830 | throw Bu::ExceptionBase("You cannot divide version values."); | ||
| 831 | |||
| 832 | case typeString: | ||
| 833 | throw Bu::ExceptionBase("You cannot divide string values."); | ||
| 834 | |||
| 835 | case typeList: | ||
| 836 | throw Bu::ExceptionBase("You cannot divide list values."); | ||
| 837 | |||
| 838 | case typeRef: | ||
| 839 | throw Bu::ExceptionBase("You cannot divide reference values."); | ||
| 840 | } | ||
| 841 | throw Bu::ExceptionBase("Unhandled case in Variable divide"); | ||
| 842 | } | ||
| 843 | |||
| 844 | void Variable::reset( Type eNewType ) | ||
| 845 | { | ||
| 846 | if( eType == typeString || eType == typeRef ) | ||
| 847 | { | ||
| 848 | delete uVal.sVal; | ||
| 849 | } | ||
| 850 | else if( eType == typeList ) | ||
| 851 | { | ||
| 852 | delete uVal.lVal; | ||
| 853 | } | ||
| 854 | memset( &uVal, 0, sizeof(uVal) ); | ||
| 855 | |||
| 856 | eType = eNewType; | ||
| 857 | } | ||
| 858 | |||
| 859 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variable::Type &t ) | ||
| 860 | { | ||
| 861 | switch( t ) | ||
| 862 | { | ||
| 863 | case Variable::typeNone: f << "*typeless*"; break; | ||
| 864 | case Variable::typeInt: f << "int"; break; | ||
| 865 | case Variable::typeFloat: f << "double"; break; | ||
| 866 | case Variable::typeBool: f << "bool"; break; | ||
| 867 | case Variable::typeString: f << "string"; break; | ||
| 868 | case Variable::typeList: f << "list"; break; | ||
| 869 | case Variable::typeVersion: f << "version"; break; | ||
| 870 | case Variable::typeRef: f << "ref"; break; | ||
| 871 | } | ||
| 872 | return f; | ||
| 873 | } | ||
| 874 | |||
| 875 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variable &v ) | ||
| 876 | { | ||
| 877 | f << "Variable(" << v.getType() << ") = "; | ||
| 878 | switch( v.getType() ) | ||
| 879 | { | ||
| 880 | case Variable::typeNone: break; | ||
| 881 | case Variable::typeInt: f << v.getInt(); break; | ||
| 882 | case Variable::typeFloat: f << v.getFloat(); break; | ||
| 883 | case Variable::typeBool: f << v.getBool(); break; | ||
| 884 | case Variable::typeString: f << v.getString(); break; | ||
| 885 | case Variable::typeList: f << v.getList(); break; | ||
| 886 | case Variable::typeVersion:/*f << v.getVersion();*/ break; | ||
| 887 | case Variable::typeRef: f << v.getString(); break; | ||
| 888 | } | ||
| 889 | |||
| 890 | return f; | ||
| 891 | } | ||
| 892 | |||
diff --git a/src/variable.h b/src/variable.h new file mode 100644 index 0000000..1b5542e --- /dev/null +++ b/src/variable.h | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | #ifndef VARIABLE_H | ||
| 2 | #define VARIABLE_H | ||
| 3 | |||
| 4 | #include "types.h" | ||
| 5 | |||
| 6 | /** | ||
| 7 | * A build variable, which is basically a flexible, limited type range variant. | ||
| 8 | */ | ||
| 9 | class Variable | ||
| 10 | { | ||
| 11 | public: | ||
| 12 | enum Type | ||
| 13 | { | ||
| 14 | typeNone, | ||
| 15 | typeBool, | ||
| 16 | typeInt, | ||
| 17 | typeFloat, | ||
| 18 | typeVersion, | ||
| 19 | typeString, | ||
| 20 | typeList, | ||
| 21 | typeRef /**< Reference by name, it's just a string. */ | ||
| 22 | }; | ||
| 23 | |||
| 24 | public: | ||
| 25 | Variable(); | ||
| 26 | Variable( Type t ); | ||
| 27 | Variable( int iVal ); | ||
| 28 | Variable( double fVal ); | ||
| 29 | Variable( bool bVal ); | ||
| 30 | Variable( const Bu::FString &sVal ); | ||
| 31 | Variable( const char *sVal ); | ||
| 32 | Variable( const Variable &v ); | ||
| 33 | Variable( const class AstLeaf &l ); | ||
| 34 | /** | ||
| 35 | * This special case function turns the variable into a string if there is | ||
| 36 | * only one string in the list, or a list of strings if there is more or | ||
| 37 | * less than one. | ||
| 38 | */ | ||
| 39 | Variable( const StrList &lst ); | ||
| 40 | Variable( const VarList &lst ); | ||
| 41 | virtual ~Variable(); | ||
| 42 | |||
| 43 | static Variable mkRef( const Bu::FString &sVal ); | ||
| 44 | |||
| 45 | Type getType() const; | ||
| 46 | |||
| 47 | // Raw aquisition functions, if the type isn't right, | ||
| 48 | // they throw an exception | ||
| 49 | int getInt() const; | ||
| 50 | double getFloat() const; | ||
| 51 | bool getBool() const; | ||
| 52 | const Bu::FString &getString() const; | ||
| 53 | const VarList &getList() const; | ||
| 54 | |||
| 55 | // Conversion functions, they'll return the requested type, maybe an error | ||
| 56 | // if the source data is really bad | ||
| 57 | int toInt() const; | ||
| 58 | double toFloat() const; | ||
| 59 | bool toBool() const; | ||
| 60 | Bu::FString toString() const; | ||
| 61 | VarList toList() const; | ||
| 62 | |||
| 63 | Variable toType( Type eNewType ) const; | ||
| 64 | |||
| 65 | void append( const Variable &v ); | ||
| 66 | VarList::iterator begin(); | ||
| 67 | VarList::const_iterator begin() const; | ||
| 68 | |||
| 69 | void doNegate(); | ||
| 70 | void doNot(); | ||
| 71 | |||
| 72 | const Variable &operator=( const Variable &rhs ); | ||
| 73 | const Variable &operator=( const int &rhs ); | ||
| 74 | const Variable &operator=( const double &rhs ); | ||
| 75 | const Variable &operator=( const bool &rhs ); | ||
| 76 | const Variable &operator=( const Bu::FString &rhs ); | ||
| 77 | |||
| 78 | const Variable &operator+=( const Variable &rhs ); | ||
| 79 | const Variable &operator<<( const Variable &rhs ); | ||
| 80 | |||
| 81 | bool operator==( const Variable &rhs ) const; | ||
| 82 | bool operator!=( const Variable &rhs ) const; | ||
| 83 | bool operator<( const Variable &rhs ) const; | ||
| 84 | bool operator>( const Variable &rhs ) const; | ||
| 85 | bool operator<=( const Variable &rhs ) const; | ||
| 86 | bool operator>=( const Variable &rhs ) const; | ||
| 87 | |||
| 88 | Variable operator+( const Variable &rhs ) const; | ||
| 89 | Variable operator-( const Variable &rhs ) const; | ||
| 90 | Variable operator*( const Variable &rhs ) const; | ||
| 91 | Variable operator/( const Variable &rhs ) const; | ||
| 92 | |||
| 93 | private: | ||
| 94 | Type eType; | ||
| 95 | union | ||
| 96 | { | ||
| 97 | int iVal; | ||
| 98 | double fVal; | ||
| 99 | bool bVal; | ||
| 100 | Bu::FString *sVal; | ||
| 101 | VarList *lVal; | ||
| 102 | } uVal; | ||
| 103 | |||
| 104 | void reset( Type eType ); | ||
| 105 | }; | ||
| 106 | |||
| 107 | namespace Bu | ||
| 108 | { | ||
| 109 | class Formatter; | ||
| 110 | } | ||
| 111 | |||
| 112 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variable::Type &t ); | ||
| 113 | Bu::Formatter &operator<<( Bu::Formatter &f, const Variable &v ); | ||
| 114 | |||
| 115 | #endif | ||
diff --git a/src/view.cpp b/src/view.cpp new file mode 100644 index 0000000..6dcc9bb --- /dev/null +++ b/src/view.cpp | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #include "view.h" | ||
| 2 | |||
| 3 | View::View() | ||
| 4 | { | ||
| 5 | } | ||
| 6 | |||
| 7 | View::~View() | ||
| 8 | { | ||
| 9 | } | ||
| 10 | |||
diff --git a/src/view.h b/src/view.h new file mode 100644 index 0000000..fb172aa --- /dev/null +++ b/src/view.h | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | #ifndef VIEW_H | ||
| 2 | #define VIEW_H | ||
| 3 | |||
| 4 | #include <bu/fstring.h> | ||
| 5 | #include "types.h" | ||
| 6 | |||
| 7 | /** | ||
| 8 | * Base class for all views. A view is the only way that build is allowed to | ||
| 9 | * communicate with the user during the processing of a buildfile, the main | ||
| 10 | * executable may output some things for command line arguments and whatnot on | ||
| 11 | * it's own, or debugging info, but all reports of everything happening during | ||
| 12 | * the process is sent through a view, so it can be made pretty and usable. | ||
| 13 | */ | ||
| 14 | class View | ||
| 15 | { | ||
| 16 | public: | ||
| 17 | View(); | ||
| 18 | virtual ~View(); | ||
| 19 | |||
| 20 | virtual void beginAction( const Bu::FString &sAction )=0; | ||
| 21 | virtual void endAction()=0; | ||
| 22 | |||
| 23 | virtual void skipTarget( const Bu::FString &sProfile, | ||
| 24 | const Target &rTarget )=0; | ||
| 25 | virtual void beginTarget( const Bu::FString &sProfile, | ||
| 26 | const Target &rTarget )=0; | ||
| 27 | virtual void processTarget( const Bu::FString &sProfile, | ||
| 28 | const Target &rTarget )=0; | ||
| 29 | virtual void endTarget()=0; | ||
| 30 | |||
| 31 | virtual void buildRequires( const Target &rTarget )=0; | ||
| 32 | virtual void cmdStarted( const Bu::FString &sCmd )=0; | ||
| 33 | virtual void cmdFinished( const Bu::FString &sStdOut, | ||
| 34 | const Bu::FString &sStdErr, long iExit )=0; | ||
| 35 | |||
| 36 | virtual void userError( const Bu::FString &sMsg )=0; | ||
| 37 | virtual void userWarning( const Bu::FString &sMsg )=0; | ||
| 38 | virtual void userNotice( const Bu::FString &sMsg )=0; | ||
| 39 | |||
| 40 | virtual void sysError( const Bu::FString &sMsg )=0; | ||
| 41 | virtual void sysWarning( const Bu::FString &sMsg )=0; | ||
| 42 | |||
| 43 | private: | ||
| 44 | }; | ||
| 45 | |||
| 46 | #endif | ||
diff --git a/src/viewdefault.cpp b/src/viewdefault.cpp new file mode 100644 index 0000000..c38c62f --- /dev/null +++ b/src/viewdefault.cpp | |||
| @@ -0,0 +1,170 @@ | |||
| 1 | #include "viewdefault.h" | ||
| 2 | #include "target.h" | ||
| 3 | |||
| 4 | #include <bu/plugger.h> | ||
| 5 | |||
| 6 | #include <bu/sio.h> | ||
| 7 | using namespace Bu; | ||
| 8 | |||
| 9 | PluginInterface3( pluginViewDefault, default, ViewDefault, View, | ||
| 10 | "Mike Buland", 0, 1 ); | ||
| 11 | |||
| 12 | #define ESC "\x1b" | ||
| 13 | |||
| 14 | #define C_RESET ESC "[0m" | ||
| 15 | #define C_RED ESC "[31m" | ||
| 16 | #define C_GREEN ESC "[32m" | ||
| 17 | #define C_YELLOW ESC "[33m" | ||
| 18 | #define C_BLUE ESC "[34m" | ||
| 19 | #define C_MAGENTA ESC "[35m" | ||
| 20 | #define C_CYAN ESC "[36m" | ||
| 21 | #define C_WHITE ESC "[37m" | ||
| 22 | #define C_DEFAULT ESC "[39m" | ||
| 23 | |||
| 24 | #define C_BR_RED ESC "[1;31m" | ||
| 25 | #define C_BR_GREEN ESC "[1;32m" | ||
| 26 | #define C_BR_YELLOW ESC "[1;33m" | ||
| 27 | #define C_BR_BLUE ESC "[1;34m" | ||
| 28 | #define C_BR_MAGENTA ESC "[1;35m" | ||
| 29 | #define C_BR_CYAN ESC "[1;36m" | ||
| 30 | #define C_BR_WHITE ESC "[1;37m" | ||
| 31 | |||
| 32 | ViewDefault::ViewDefault() : | ||
| 33 | bFirst( true ), | ||
| 34 | iDepth( 0 ), | ||
| 35 | iTotal( 0 ), | ||
| 36 | iCurrent( 0 ) | ||
| 37 | { | ||
| 38 | } | ||
| 39 | |||
| 40 | ViewDefault::~ViewDefault() | ||
| 41 | { | ||
| 42 | } | ||
| 43 | |||
| 44 | void ViewDefault::beginAction( const Bu::FString &/*sAction*/ ) | ||
| 45 | { | ||
| 46 | } | ||
| 47 | |||
| 48 | void ViewDefault::endAction() | ||
| 49 | { | ||
| 50 | } | ||
| 51 | |||
| 52 | void ViewDefault::skipTarget( const Bu::FString &/*sProfile*/, | ||
| 53 | const Target &/*rTarget*/ ) | ||
| 54 | { | ||
| 55 | iCurrent++; | ||
| 56 | } | ||
| 57 | |||
| 58 | void ViewDefault::beginTarget( const Bu::FString &sProfile, | ||
| 59 | const Target &rTarget ) | ||
| 60 | { | ||
| 61 | if( iDepth == 0 ) | ||
| 62 | { | ||
| 63 | iTotal = rTarget.getDepCount(); | ||
| 64 | iCurrent = 0; | ||
| 65 | if( bFirst == false ) | ||
| 66 | { | ||
| 67 | sio << sio.nl; | ||
| 68 | } | ||
| 69 | bFirst = false; | ||
| 70 | sio << C_BR_WHITE << " --- " << C_BR_CYAN << sProfile << " " | ||
| 71 | << rTarget.getOutputList().first() << C_BR_WHITE << " --- " | ||
| 72 | << C_RESET << sio.nl; | ||
| 73 | } | ||
| 74 | iDepth++; | ||
| 75 | } | ||
| 76 | |||
| 77 | void ViewDefault::processTarget( const Bu::FString &/*sProfile*/, | ||
| 78 | const Target &rTarget ) | ||
| 79 | { | ||
| 80 | iCurrent++; | ||
| 81 | |||
| 82 | int iPct = (iTotal>0)?(iCurrent*100/iTotal):(100); | ||
| 83 | sio << C_BR_WHITE << "[" << C_BR_GREEN << Fmt(3) << iPct | ||
| 84 | << "%" << C_BR_WHITE << "] " << C_BR_MAGENTA | ||
| 85 | << Fmt(10) << rTarget.getDisplay() << C_BR_WHITE | ||
| 86 | << ": " << rTarget.getOutputList().first() << C_RESET << sio.nl; | ||
| 87 | } | ||
| 88 | |||
| 89 | void ViewDefault::endTarget() | ||
| 90 | { | ||
| 91 | iDepth--; | ||
| 92 | } | ||
| 93 | |||
| 94 | void ViewDefault::buildRequires( const Target &rTarget ) | ||
| 95 | { | ||
| 96 | int iPct = (iTotal>0)?(iCurrent*100/iTotal):(100); | ||
| 97 | sio << C_BR_WHITE << "[" << C_BR_GREEN << Fmt(3) << iPct | ||
| 98 | << "%" << C_BR_WHITE << "] " << C_BR_MAGENTA | ||
| 99 | << Fmt(10) << "deps" << C_BR_WHITE | ||
| 100 | << ": " << rTarget.getOutputList().first() << C_RESET << sio.nl; | ||
| 101 | } | ||
| 102 | |||
| 103 | void ViewDefault::cmdStarted( const Bu::FString &/*sCmd*/ ) | ||
| 104 | { | ||
| 105 | } | ||
| 106 | |||
| 107 | void ViewDefault::cmdFinished( const Bu::FString &sStdOut, | ||
| 108 | const Bu::FString &sStdErr, long /*iExit*/ ) | ||
| 109 | { | ||
| 110 | if( sStdOut ) | ||
| 111 | { | ||
| 112 | Bu::FString::const_iterator b; | ||
| 113 | b = sStdOut.begin(); | ||
| 114 | while( b ) | ||
| 115 | { | ||
| 116 | Bu::FString::const_iterator e, max; | ||
| 117 | max = b + 78; | ||
| 118 | for( e = b; e != max && *e != '\n'; e++ ) { } | ||
| 119 | sio << C_BR_GREEN << "| " << C_RESET << FString( b, e ) << sio.nl; | ||
| 120 | b = e; | ||
| 121 | if( *b == '\n' ) | ||
| 122 | b++; | ||
| 123 | } | ||
| 124 | sio << C_BR_GREEN << "\\-----" << C_RESET << sio.nl; | ||
| 125 | } | ||
| 126 | if( sStdErr ) | ||
| 127 | { | ||
| 128 | Bu::FString::const_iterator b; | ||
| 129 | b = sStdErr.begin(); | ||
| 130 | while( b ) | ||
| 131 | { | ||
| 132 | Bu::FString::const_iterator e, max; | ||
| 133 | max = b + 78; | ||
| 134 | for( e = b; e != max && *e != '\n'; e++ ) { } | ||
| 135 | sio << C_BR_RED << "| " << C_RESET << FString( b, e ) << sio.nl; | ||
| 136 | b = e; | ||
| 137 | if( *b == '\n' ) | ||
| 138 | b++; | ||
| 139 | } | ||
| 140 | sio << C_BR_RED << "\\-----" << C_RESET << sio.nl; | ||
| 141 | } | ||
| 142 | //sio << C_BR_WHITE << "[" << C_BR_GREEN << sStdOut << C_BR_WHITE << "]" << sio.nl; | ||
| 143 | //sio << C_BR_WHITE << "[" << C_BR_RED << sStdErr << C_BR_WHITE << "]" << sio.nl; | ||
| 144 | } | ||
| 145 | |||
| 146 | void ViewDefault::userError( const Bu::FString &sMsg ) | ||
| 147 | { | ||
| 148 | sio << C_BR_RED << "Error: " << sMsg << C_RESET << sio.nl; | ||
| 149 | } | ||
| 150 | |||
| 151 | void ViewDefault::userWarning( const Bu::FString &sMsg ) | ||
| 152 | { | ||
| 153 | sio << C_BR_YELLOW << "Warning: " << sMsg << C_RESET << sio.nl; | ||
| 154 | } | ||
| 155 | |||
| 156 | void ViewDefault::userNotice( const Bu::FString &sMsg ) | ||
| 157 | { | ||
| 158 | sio << C_BR_GREEN << "Notice: " << sMsg << C_RESET << sio.nl; | ||
| 159 | } | ||
| 160 | |||
| 161 | void ViewDefault::sysError( const Bu::FString &sMsg ) | ||
| 162 | { | ||
| 163 | sio << C_BR_RED << sMsg << C_RESET << sio.nl; | ||
| 164 | } | ||
| 165 | |||
| 166 | void ViewDefault::sysWarning( const Bu::FString &sMsg ) | ||
| 167 | { | ||
| 168 | sio << C_BR_YELLOW << sMsg << C_RESET << sio.nl; | ||
| 169 | } | ||
| 170 | |||
diff --git a/src/viewdefault.h b/src/viewdefault.h new file mode 100644 index 0000000..c9a554d --- /dev/null +++ b/src/viewdefault.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | #ifndef VIEW_DEFAULT_H | ||
| 2 | #define VIEW_DEFAULT_H | ||
| 3 | |||
| 4 | #include "view.h" | ||
| 5 | |||
| 6 | class ViewDefault : public View | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | ViewDefault(); | ||
| 10 | virtual ~ViewDefault(); | ||
| 11 | |||
| 12 | virtual void beginAction( const Bu::FString &sAction ); | ||
| 13 | virtual void endAction(); | ||
| 14 | |||
| 15 | virtual void skipTarget( const Bu::FString &sProfile, | ||
| 16 | const Target &rTarget ); | ||
| 17 | virtual void beginTarget( const Bu::FString &sProfile, | ||
| 18 | const Target &rTarget ); | ||
| 19 | virtual void processTarget( const Bu::FString &sProfile, | ||
| 20 | const Target &rTarget ); | ||
| 21 | virtual void endTarget(); | ||
| 22 | |||
| 23 | virtual void buildRequires( const Target &rTarget ); | ||
| 24 | virtual void cmdStarted( const Bu::FString &sCmd ); | ||
| 25 | virtual void cmdFinished( const Bu::FString &sStdOut, | ||
| 26 | const Bu::FString &sStdErr, long iExit ); | ||
| 27 | |||
| 28 | virtual void userError( const Bu::FString &sMsg ); | ||
| 29 | virtual void userWarning( const Bu::FString &sMsg ); | ||
| 30 | virtual void userNotice( const Bu::FString &sMsg ); | ||
| 31 | |||
| 32 | virtual void sysError( const Bu::FString &sMsg ); | ||
| 33 | virtual void sysWarning( const Bu::FString &sMsg ); | ||
| 34 | |||
| 35 | private: | ||
| 36 | bool bFirst; | ||
| 37 | int iDepth; | ||
| 38 | int iTotal; | ||
| 39 | int iCurrent; | ||
| 40 | }; | ||
| 41 | |||
| 42 | #endif | ||
diff --git a/src/viewmake.cpp b/src/viewmake.cpp new file mode 100644 index 0000000..39d1327 --- /dev/null +++ b/src/viewmake.cpp | |||
| @@ -0,0 +1,86 @@ | |||
| 1 | #include "viewmake.h" | ||
| 2 | #include "target.h" | ||
| 3 | |||
| 4 | #include <bu/plugger.h> | ||
| 5 | |||
| 6 | #include <bu/sio.h> | ||
| 7 | using namespace Bu; | ||
| 8 | |||
| 9 | PluginInterface3( pluginViewMake, make, ViewMake, View, | ||
| 10 | "Mike Buland", 0, 1 ); | ||
| 11 | |||
| 12 | ViewMake::ViewMake() | ||
| 13 | { | ||
| 14 | } | ||
| 15 | |||
| 16 | ViewMake::~ViewMake() | ||
| 17 | { | ||
| 18 | } | ||
| 19 | |||
| 20 | void ViewMake::beginAction( const Bu::FString &/*sAction*/ ) | ||
| 21 | { | ||
| 22 | } | ||
| 23 | |||
| 24 | void ViewMake::endAction() | ||
| 25 | { | ||
| 26 | } | ||
| 27 | |||
| 28 | void ViewMake::skipTarget( const Bu::FString &/*sProfile*/, | ||
| 29 | const Target &/*rTarget*/ ) | ||
| 30 | { | ||
| 31 | } | ||
| 32 | |||
| 33 | void ViewMake::beginTarget( const Bu::FString &/*sProfile*/, | ||
| 34 | const Target &/*rTarget*/ ) | ||
| 35 | { | ||
| 36 | } | ||
| 37 | |||
| 38 | void ViewMake::processTarget( const Bu::FString &/*sProfile*/, | ||
| 39 | const Target &/*rTarget*/ ) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | |||
| 43 | void ViewMake::endTarget() | ||
| 44 | { | ||
| 45 | } | ||
| 46 | |||
| 47 | void ViewMake::buildRequires( const Target &/*rTarget*/ ) | ||
| 48 | { | ||
| 49 | } | ||
| 50 | |||
| 51 | void ViewMake::cmdStarted( const Bu::FString &sCmd ) | ||
| 52 | { | ||
| 53 | sio << sCmd << sio.nl; | ||
| 54 | } | ||
| 55 | |||
| 56 | void ViewMake::cmdFinished( const Bu::FString &sStdOut, | ||
| 57 | const Bu::FString &sStdErr, long /*iExit*/ ) | ||
| 58 | { | ||
| 59 | sio << sStdOut << sStdErr; | ||
| 60 | } | ||
| 61 | |||
| 62 | void ViewMake::userError( const Bu::FString &sMsg ) | ||
| 63 | { | ||
| 64 | sio << "Error: " << sMsg << sio.nl; | ||
| 65 | } | ||
| 66 | |||
| 67 | void ViewMake::userWarning( const Bu::FString &sMsg ) | ||
| 68 | { | ||
| 69 | sio << "Warning: " << sMsg << sio.nl; | ||
| 70 | } | ||
| 71 | |||
| 72 | void ViewMake::userNotice( const Bu::FString &sMsg ) | ||
| 73 | { | ||
| 74 | sio << "Notice: " << sMsg << sio.nl; | ||
| 75 | } | ||
| 76 | |||
| 77 | void ViewMake::sysError( const Bu::FString &sMsg ) | ||
| 78 | { | ||
| 79 | sio << sMsg << sio.nl; | ||
| 80 | } | ||
| 81 | |||
| 82 | void ViewMake::sysWarning( const Bu::FString &sMsg ) | ||
| 83 | { | ||
| 84 | sio << sMsg << sio.nl; | ||
| 85 | } | ||
| 86 | |||
diff --git a/src/viewmake.h b/src/viewmake.h new file mode 100644 index 0000000..9100a86 --- /dev/null +++ b/src/viewmake.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #ifndef VIEW_MAKE_H | ||
| 2 | #define VIEW_MAKE_H | ||
| 3 | |||
| 4 | #include "view.h" | ||
| 5 | |||
| 6 | class ViewMake : public View | ||
| 7 | { | ||
| 8 | public: | ||
| 9 | ViewMake(); | ||
| 10 | virtual ~ViewMake(); | ||
| 11 | |||
| 12 | virtual void beginAction( const Bu::FString &sAction ); | ||
| 13 | virtual void endAction(); | ||
| 14 | |||
| 15 | virtual void skipTarget( const Bu::FString &sProfile, | ||
| 16 | const Target &rTarget ); | ||
| 17 | virtual void beginTarget( const Bu::FString &sProfile, | ||
| 18 | const Target &rTarget ); | ||
| 19 | virtual void processTarget( const Bu::FString &sProfile, | ||
| 20 | const Target &rTarget ); | ||
| 21 | virtual void endTarget(); | ||
| 22 | |||
| 23 | virtual void buildRequires( const Target &rTarget ); | ||
| 24 | virtual void cmdStarted( const Bu::FString &sCmd ); | ||
| 25 | virtual void cmdFinished( const Bu::FString &sStdOut, | ||
| 26 | const Bu::FString &sStdErr, long iExit ); | ||
| 27 | |||
| 28 | virtual void userError( const Bu::FString &sMsg ); | ||
| 29 | virtual void userWarning( const Bu::FString &sMsg ); | ||
| 30 | virtual void userNotice( const Bu::FString &sMsg ); | ||
| 31 | |||
| 32 | virtual void sysError( const Bu::FString &sMsg ); | ||
| 33 | virtual void sysWarning( const Bu::FString &sMsg ); | ||
| 34 | }; | ||
| 35 | |||
| 36 | #endif | ||
diff --git a/src/viewplugger.cpp b/src/viewplugger.cpp new file mode 100644 index 0000000..6046f82 --- /dev/null +++ b/src/viewplugger.cpp | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #include "viewplugger.h" | ||
| 2 | |||
| 3 | extern Bu::PluginInfo pluginViewDefault; | ||
| 4 | extern Bu::PluginInfo pluginViewMake; | ||
| 5 | ViewPlugger::ViewPlugger() | ||
| 6 | { | ||
| 7 | registerBuiltinPlugin( &pluginViewDefault ); | ||
| 8 | registerBuiltinPlugin( &pluginViewMake ); | ||
| 9 | } | ||
| 10 | |||
| 11 | ViewPlugger::~ViewPlugger() | ||
| 12 | { | ||
| 13 | } | ||
| 14 | |||
diff --git a/src/viewplugger.h b/src/viewplugger.h new file mode 100644 index 0000000..b58635c --- /dev/null +++ b/src/viewplugger.h | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | #ifndef VIEW_PLUGGER_H | ||
| 2 | #define VIEW_PLUGGER_H | ||
| 3 | |||
| 4 | #include "view.h" | ||
| 5 | #include <bu/plugger.h> | ||
| 6 | #include <bu/singleton.h> | ||
| 7 | |||
| 8 | class ViewPlugger : public Bu::Plugger<View>, public Bu::Singleton<ViewPlugger> | ||
| 9 | { | ||
| 10 | friend class Bu::Singleton<ViewPlugger>; | ||
| 11 | private: | ||
| 12 | ViewPlugger(); | ||
| 13 | |||
| 14 | public: | ||
| 15 | virtual ~ViewPlugger(); | ||
| 16 | |||
| 17 | private: | ||
| 18 | }; | ||
| 19 | |||
| 20 | #endif | ||
