aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2006-07-30 09:07:20 +0000
committerMike Buland <eichlan@xagasoft.com>2006-07-30 09:07:20 +0000
commit113fc467a7170a8a564049c64d1036dd10e6abac (patch)
treee4719817a3e0175a9f7cbd4e07fc994ff41f8ef6
parent900976d2d74e0de57858b265c2ef0d17a29e921a (diff)
downloadbuild-113fc467a7170a8a564049c64d1036dd10e6abac.tar.gz
build-113fc467a7170a8a564049c64d1036dd10e6abac.tar.bz2
build-113fc467a7170a8a564049c64d1036dd10e6abac.tar.xz
build-113fc467a7170a8a564049c64d1036dd10e6abac.zip
It's starting to look pretty good, just trying to figure out how to get through
everything that needs to be made modular and general.
-rw-r--r--congo77
-rw-r--r--pymake.conf13
-rw-r--r--src/action.cpp38
-rw-r--r--src/action.h35
-rw-r--r--src/build.l26
-rw-r--r--src/build.y87
-rw-r--r--src/builder.cpp45
-rw-r--r--src/builder.h41
-rw-r--r--src/command.cpp19
-rw-r--r--src/command.h38
-rw-r--r--src/main.cpp2
11 files changed, 361 insertions, 60 deletions
diff --git a/congo b/congo
index ddf7e7b..3031f4e 100644
--- a/congo
+++ b/congo
@@ -1,16 +1,83 @@
1#
2# Simple build.conf test file
3#
4# you can have as many actions as you'd like, the one that's run by default is
5# called "default action", you need a default action.
6#
7# Actions are filled with a comma-seperated list of commands, like "check xxx"
8# to check to see if a target needs to be rebuilt
9#
10default action: check congo, check congod
1 11
2default action: create congo, congod 12#
13# This action will only build the server program
14#
15server action: check congod
3 16
4create file congod from files in src/congod using rule exe 17#
5create file congo from files in src/congo using rule exe 18# After that, it helps to define some targets, things that commands usually
19# refer to and interact with.
20#
6 21
22#
23# "create file" will do just what it says, create a file based on some
24# information and a rule.
25#
26# "from files in" tells us that a list of directories follows, and the input
27# list for the rule should be built from these files.
28#
29# "using rule" tells us which rule to use to actuall create the file
30#
31create file congod from files in src/congod, src/shared using rule exe
32create file congo from files in src/congo, src/shared using rule exe
33
34#
35# After all of that, some targets or list items may have their own additional
36# dependancies, depending on the rule that built them. You can define these
37# extra dependancies using "xxx requires yyy" which will force the system to
38# attempt to create yyy before xxx.
39#
7congod requires libcongo.a 40congod requires libcongo.a
8congo requires libcongo.a 41congo requires libcongo.a
9 42
43#
44# There are a number of variables that the rules can use, including any in the
45# environment. Sometimes you want to modify these, to do that you can use "set"
46# and the name of the variable, along with what to do to it.
47#
48# You can use '=' to set the value, destroying what was there, or '+=' to add
49# the new text to the variable, this will assume that the text you provide is
50# made up of space-delimited tokens, and will ensure spaces surround them when
51# they are added.
52#
10set CXXFLAGS += "-Ilibbu++/src" 53set CXXFLAGS += "-Ilibbu++/src"
11set LDFLAGS += "-Llibbu++ -lbu++" 54set LDFLAGS += "-Llibbu++ -lbu++"
12 55
56#
57# Sometimes individual targets or list items require special settings, this is
58# easy since build maintians a seperate set of variables for any items that need
59# special support.
60#
61# Currently you can only set, for an item, later you may be able to do more.
62#
13for congo set LDFLAGS += "-lreadline" 63for congo set LDFLAGS += "-lreadline"
14 64
15rule exe matches all /(.*)\.o/ perform command "g++ {matches} {LDFLAGS} -o {target}" 65#
16rule cpp matches one /(.*)\.cpp/ produces {1}.o perform command "g++ {CXXFLAGS} -o {target} {match}" 66# Finally, no file is complete without some rules. Rules determine how to
67# fulfill target checking based on some input data. Generally this is going to
68# be creating an executable from a list of source files.
69#
70#
71# First specify the rule name, then you can filter the input list, if desired,
72# in two ways. You can use items that match a regular expression, and execute
73# the rule once for the whole list collectively, or once for each element that
74# made it through the filter.
75#
76# Within the perform, there are several things that could go there, for now,
77# just command, which takes a string, you can use {} for variable substitution.
78#
79rule exe matches all /(.*)\.o/ perform command ...
80 "g++ {matches} {LDFLAGS} -o {target}"
81
82rule cpp matches one /(.*)\.cpp/ produces {1}.o perform command ...
83 "g++ {CXXFLAGS} -o {target} {match}"
diff --git a/pymake.conf b/pymake.conf
index 83d9885..2340fd5 100644
--- a/pymake.conf
+++ b/pymake.conf
@@ -5,6 +5,16 @@
5CXXFLAGS: -Ilibbu++/src 5CXXFLAGS: -Ilibbu++/src
6LDFLAGS: -Llibbu++ -lbu++ 6LDFLAGS: -Llibbu++ -lbu++
7 7
8[BUILD]
9FILE: src/build.y
10COMMAND: stupid
11OUTPUT: parser
12
13[BUILD]
14FILE: src/build.l
15COMMAND: stupid
16OUTPUT: lexer
17
8## A simple command to build everything in this directory, and output 18## A simple command to build everything in this directory, and output
9## an executable with the name 'main' 19## an executable with the name 'main'
10[BUILD] 20[BUILD]
@@ -79,6 +89,9 @@ COMMAND: g++ {INPUT} {LDFLAGS} -o {OUTPUT}
79NAME: lib 89NAME: lib
80COMMAND: ar cr{ARFLAGS} {OUTPUT} {INPUT} 90COMMAND: ar cr{ARFLAGS} {OUTPUT} {INPUT}
81 91
92[COMMAND]
93NAME: stupid
94
82### Strange example ### 95### Strange example ###
83## The following trigger will take all *.q files, strip all '&'s from them 96## The following trigger will take all *.q files, strip all '&'s from them
84## and generate a .cpp file, which will then be compiled using the cpp trigger. 97## and generate a .cpp file, which will then be compiled using the cpp trigger.
diff --git a/src/action.cpp b/src/action.cpp
new file mode 100644
index 0000000..7a7bbb8
--- /dev/null
+++ b/src/action.cpp
@@ -0,0 +1,38 @@
1#include "action.h"
2#include "command.h"
3
4Action::Action() :
5 bDefault( true ),
6 sName("")
7{
8}
9
10Action::Action( const char *sName ) :
11 bDefault( false ),
12 sName( sName )
13{
14}
15
16Action::~Action()
17{
18}
19
20void Action::add( Command *pCmd )
21{
22 lCommand.push_back( pCmd );
23}
24
25void Action::debug()
26{
27 if( bDefault )
28 printf("action default:\n");
29 else
30 printf("action \"%s\":\n", sName.getString() );
31
32 for( std::list<Command *>::iterator i = lCommand.begin();
33 i != lCommand.end(); i++ )
34 {
35 (*i)->debug();
36 }
37}
38
diff --git a/src/action.h b/src/action.h
new file mode 100644
index 0000000..12c2cc4
--- /dev/null
+++ b/src/action.h
@@ -0,0 +1,35 @@
1#ifndef ACTION_H
2#define ACTION_H
3
4#include <list>
5#include "staticstring.h"
6
7class Command;
8
9class Action
10{
11public:
12 Action();
13 Action( const char *sName );
14 virtual ~Action();
15
16 void add( Command *pCmd );
17
18 const char *getName()
19 {
20 return sName;
21 }
22 bool isDefault()
23 {
24 return bDefault;
25 }
26
27 void debug();
28
29private:
30 bool bDefault;
31 StaticString sName;
32 std::list<Command *> lCommand;
33};
34
35#endif
diff --git a/src/build.l b/src/build.l
index 6a80f45..3a457b1 100644
--- a/src/build.l
+++ b/src/build.l
@@ -7,13 +7,14 @@
7std::string strbuf; 7std::string strbuf;
8%} 8%}
9 9
10%x regexp
10%x strsq 11%x strsq
11%x strdq 12%x strdq
12%x comment 13%x comment
13%option noyywrap nounput batch debug 14%option noyywrap nounput batch debug
14 15
15%{ 16%{
16# define YY_USER_ACTION yylloc->columns (yyleng); 17//# define YY_USER_ACTION yylloc->columns (yyleng);
17%} 18%}
18%% 19%%
19 20
@@ -38,16 +39,27 @@ std::string strbuf;
38"perform" return TOK_PERFORM; 39"perform" return TOK_PERFORM;
39"produces" return TOK_PRODUCES; 40"produces" return TOK_PRODUCES;
40"command" return TOK_COMMAND; 41"command" return TOK_COMMAND;
42"check" return TOK_CHECK;
41 43
42"..."\n /* elipsis line continuation */ 44"..."\n /* elipsis line continuation */
43\n+ return TOX_EOL; 45\n+ return TOK_EOL;
44[ \t\r]* /* whitespace */ 46[ \t\r]* /* whitespace */
45 47
46\/\/.* /* single line comment */ 48"/" {
49 BEGIN( regexp );
50 strbuf = "";
51}
52<regexp>[^\n/]* strbuf += yytext;
53<regexp>"/" {
54 BEGIN( INITIAL );
55 yylval->strval = stringdup( strbuf.c_str() );
56 return REGEXP;
57}
58
47"#".* /* single line comment */ 59"#".* /* single line comment */
48 60
49[^ \t\r\n\'\"]+ { 61[^ \t\r\n\'\":=,.]+ {
50 yylval.strval = stringdup( yytext ); 62 yylval->strval = stringdup( yytext );
51 return STRING; 63 return STRING;
52} 64}
53 65
@@ -86,11 +98,13 @@ std::string strbuf;
86 return STRING; 98 return STRING;
87} 99}
88 100
101%%
89 102
90void Builder::scanBegin() 103void Builder::scanBegin()
91{ 104{
105 yy_flex_debug = false;
92 if( !(yyin = fopen( file.c_str(), "r" )) ) 106 if( !(yyin = fopen( file.c_str(), "r" )) )
93 error( std::string("cannot open ") + file ); 107 fprintf( stderr, "cannot open %s\n", file.c_str() );
94} 108}
95 109
96void Builder::scanEnd() 110void Builder::scanEnd()
diff --git a/src/build.y b/src/build.y
index 600b923..45a84f1 100644
--- a/src/build.y
+++ b/src/build.y
@@ -1,19 +1,21 @@
1%skeleton "lalr1.cc"
2%define "parser_class_name" "BuildParser"
3%defines 1%defines
4%{ 2%{
5# include <string> 3# include <string>
6# include "builder.h" 4# include "builder.h"
5# include "action.h"
6# include "command.h"
7# include "build.tab.h" 7# include "build.tab.h"
8void yyerror( YYLTYPE *locp, Builder &bld, char const *msg );
8%} 9%}
9 10
10%parse-param { Builder &bld } 11%parse-param { Builder &bld }
11%lex-param { Builder &bld } 12%lex-param { Builder &bld }
13%pure-parser
12 14
13%locations 15%locations
14%initial-action 16%initial-action
15{ 17{
16 @$.begin.filename = @$.end.filename = &bld.file; 18 //@$.begin.filename = @$.end.filename = &bld.file;
17} 19}
18 20
19%debug 21%debug
@@ -23,6 +25,7 @@
23} 25}
24 26
25%token <strval> STRING "string literal" 27%token <strval> STRING "string literal"
28%token <strval> REGEXP "regular expression"
26 29
27%token TOK_ADDSET "+=" 30%token TOK_ADDSET "+="
28%token TOK_DEFAULT "keyword 'default'" 31%token TOK_DEFAULT "keyword 'default'"
@@ -43,49 +46,69 @@
43%token TOK_PERFORM "keyword 'perform'" 46%token TOK_PERFORM "keyword 'perform'"
44%token TOK_PRODUCES "keyword 'produces'" 47%token TOK_PRODUCES "keyword 'produces'"
45%token TOK_COMMAND "keyword 'command'" 48%token TOK_COMMAND "keyword 'command'"
49%token TOK_CHECK "keyword 'check'"
46%token TOK_EOL "end of line" 50%token TOK_EOL "end of line"
51%token ',' ':' '='
47 52
48%destructor { delete[] $$; } STRING 53%destructor { delete[] $$; } STRING
49 54
50%% 55%%
51 56
52input: 57input:
53 | input line 58 | input fullline
54 ; 59 ;
55 60
56line: stuff TOK_EOL { printf("\n"); } 61fullline: TOK_EOL
62 | line TOK_EOL
63 ;
64
65line: TOK_DEFAULT TOK_ACTION ':'
66 {
67 bld.add( new Action() );
68 }
69 actionlst
70 | STRING TOK_ACTION ':'
71 {
72 bld.add( new Action( $1 ) );
73 }
74 actionlst
75 | TOK_CREATE createwhat TOK_FROM createfrom TOK_USING createusing
57 ; 76 ;
58 77
59stuff: 78createwhat: TOK_FILE STRING { printf("target: %s\n", $2 ); }
60 | stuff token 79 ;
61 ;
62 80
63token: TOK_ADDSET { printf("+= "); } 81createfrom: TOK_FILES TOK_IN createfromdirlst
64 | TOK_DEFAULT { printf("default "); } 82 ;
65 | TOK_ACTION { printf("action "); } 83
66 | TOK_CREATE { printf("create "); } 84createfromdirlst: createfromdir
67 | TOK_FILE { printf("file "); } 85 | createfromdirlst ',' createfromdir
68 | TOK_FROM { printf("from "); } 86 ;
69 | TOK_FILES { printf("files "); } 87
70 | TOK_IN { printf("in "); } 88createfromdir: STRING { printf(" srcdir: %s\n", $1 ); }
71 | TOK_USING { printf("using "); } 89 ;
72 | TOK_RULE { printf("rule "); } 90
73 | TOK_REQUIRES { printf("requires "); } 91createusing: TOK_RULE STRING { printf(" rule: %s\n", $2 ); }
74 | TOK_FOR { printf("for "); } 92 ;
75 | TOK_SET { printf("set "); } 93
76 | TOK_MATCHES { printf("matches "); } 94actionlst: action
77 | TOK_ALL { printf("all "); } 95 | actionlst ',' action
78 | TOK_ONE { printf("one "); } 96 ;
79 | TOK_PERFORM { printf("perform "); } 97
80 | TOK_PRODUCES { printf("produces "); } 98action: TOK_CHECK STRING
81 | TOK_COMMAND { printf("command "); } 99 {
82 ; 100 bld.add( new Command( Command::cmdCheck, $2 ) );
101 }
102 ;
83 103
84%% 104%%
85 105
86void yy::BuildParser::error( const yy::BuildParser::location_type &l, 106void yyerror( YYLTYPE *locp, Builder &bld, char const *msg )
87 const std::string &m )
88{ 107{
89 bld.error( l, m ); 108 fprintf( stderr, "%s:%d-%d:%d-%d: %s\n",
109 bld.file.c_str(),
110 locp->first_line, locp->last_line,
111 locp->first_column, locp->last_column,
112 msg
113 );
90} 114}
91
diff --git a/src/builder.cpp b/src/builder.cpp
index 8c72fef..2de6f5c 100644
--- a/src/builder.cpp
+++ b/src/builder.cpp
@@ -1,9 +1,15 @@
1#include <iostream> 1#include <iostream>
2 2
3#include "builder.h" 3#include "builder.h"
4#include "action.h"
5#include "command.h"
4#include "build.tab.h" 6#include "build.tab.h"
5 7
6Builder::Builder() 8subExceptionDef( BuildException )
9
10Builder::Builder() :
11 pDefaultAction( NULL ),
12 pLastAddedAction( NULL )
7{ 13{
8} 14}
9 15
@@ -11,24 +17,47 @@ Builder::~Builder()
11{ 17{
12} 18}
13 19
20void yyparse( Builder &bld );
21
14void Builder::load( const char *sFN ) 22void Builder::load( const char *sFN )
15{ 23{
16 file = sFN; 24 file = sFN;
17 25
18 scanBegin(); 26 scanBegin();
19 yy::BuildParser parser( *this ); 27 yyparse( *this );
20 parser.set_debug_level( false );
21 parser.parse();
22 scanEnd(); 28 scanEnd();
23} 29}
24 30
25void Builder::error( const yy::location &l, const std::string &m ) 31void Builder::add( Action *pAct )
32{
33 if( pAct->isDefault() )
34 {
35 if( pDefaultAction )
36 throw BuildException("There's already a default exception");
37 pDefaultAction = pAct;
38 }
39 else
40 {
41 mAction[pAct->getName()] = pAct;
42 }
43 pLastAddedAction = pAct;
44}
45
46void Builder::add( Command *pCmd )
26{ 47{
27 std::cerr << l << ": " << m << std::endl; 48 if( pLastAddedAction )
49 {
50 pLastAddedAction->add( pCmd );
51 }
28} 52}
29 53
30void Builder::error( const std::string &m ) 54void Builder::debug()
31{ 55{
32 std::cerr << m << std::endl; 56 pDefaultAction->debug();
57 for( std::map<const char *, Action *, ltstr>::iterator i = mAction.begin();
58 i != mAction.end(); i++ )
59 {
60 (*i).second->debug();
61 }
33} 62}
34 63
diff --git a/src/builder.h b/src/builder.h
index e379608..58afaf5 100644
--- a/src/builder.h
+++ b/src/builder.h
@@ -2,35 +2,58 @@
2#define BUILDER_H 2#define BUILDER_H
3 3
4#include <string> 4#include <string>
5#include <list>
6#include <map>
7#include "build.tab.h"
8#include "exceptionbase.h"
5 9
6union YYSTYPE; 10subExceptionDecl( BuildException )
7 11
8namespace yy
9{
10 class location;
11 class BuildParser;
12}
13class Builder; 12class Builder;
13class Action;
14class Command;
14 15
15#define YY_DECL int yylex( YYSTYPE *yylval_param, yy::location *yylloc, Builder &bld ) 16#define YY_DECL int yylex( YYSTYPE *yylval_param, YYLTYPE *yylloc_param, Builder &bld )
16YY_DECL; 17YY_DECL;
17 18
18class Builder 19class Builder
19{ 20{
21 struct ltstr
22 {
23 bool operator()(const char* s1, const char* s2) const
24 {
25 return strcmp(s1, s2) < 0;
26 }
27 };
28
20public: 29public:
21 Builder(); 30 Builder();
22 virtual ~Builder(); 31 virtual ~Builder();
23 32
24 void load( const char *sFN ); 33 void load( const char *sFN );
25 34
26 void error( const yy::location &l, const std::string &m ); 35 //void error( const yy::location &l, const std::string &m );
27 void error( const std::string &m ); 36 //void error( const std::string &m );
28 37
29 std::string file; 38 std::string file;
30 39
40 void add( Action *pAct );
41 void add( Command *pCmd );
42
43 bool hasDefaultAction()
44 {
45 return pDefaultAction != NULL;
46 }
47
48 void debug();
49
31private: 50private:
32 void scanBegin(); 51 void scanBegin();
33 void scanEnd(); 52 void scanEnd();
53
54 Action *pDefaultAction;
55 Action *pLastAddedAction;
56 std::map<const char *, Action *, ltstr> mAction;
34}; 57};
35 58
36#endif 59#endif
diff --git a/src/command.cpp b/src/command.cpp
new file mode 100644
index 0000000..4a1fa6c
--- /dev/null
+++ b/src/command.cpp
@@ -0,0 +1,19 @@
1#include "command.h"
2
3Command::Command( CmdType cmd, const char *sTarget ) :
4 nType( cmd ),
5 sTarget( sTarget )
6{
7}
8
9Command::~Command()
10{
11}
12
13void Command::debug()
14{
15 static const char *cmdt[]={"Check", "Clean"};
16 printf(" command: %s %s\n", cmdt[ nType ], sTarget.getString() );
17
18}
19
diff --git a/src/command.h b/src/command.h
new file mode 100644
index 0000000..aa00eae
--- /dev/null
+++ b/src/command.h
@@ -0,0 +1,38 @@
1#ifndef COMMAND_H
2#define COMMAND_H
3
4#include <stdint.h>
5#include "staticstring.h"
6
7class Command
8{
9public:
10 enum CmdType
11 {
12 cmdCheck = 0,
13 cmdClean
14 };
15
16public:
17 Command( CmdType cmd, const char *sTarget );
18 virtual ~Command();
19
20 CmdType getType()
21 {
22 return nType;
23 }
24
25 const char *getTarget()
26 {
27 return sTarget;
28 }
29
30 void debug();
31
32private:
33 CmdType nType;
34 StaticString sTarget;
35
36};
37
38#endif
diff --git a/src/main.cpp b/src/main.cpp
index 7e130bc..598a97f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -5,5 +5,7 @@ int main()
5 Builder bld; 5 Builder bld;
6 6
7 bld.load("congo"); 7 bld.load("congo");
8
9 bld.debug();
8} 10}
9 11