X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=buildtool.cpp;h=3dc7ed07ee052cea7096b940483af1950e3e0ead;hb=b5907d886fa60e2613d2f0fa60273f4747625b26;hp=ef80f872aaed951b61d18fd8621350a4832eafdf;hpb=f3d3720abcbae388db665983633890de94371df8;p=inkscape.git diff --git a/buildtool.cpp b/buildtool.cpp index ef80f872a..3dc7ed07e 100644 --- a/buildtool.cpp +++ b/buildtool.cpp @@ -4,7 +4,7 @@ * Authors: * Bob Jamison * - * Copyright (C) 2006 Bob Jamison + * Copyright (C) 2006-2007 Bob Jamison * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,16 +30,23 @@ * btool * or * btool {target} + * + * Note: recent win32api builds from MinGW have gettimeofday() + * defined, so you might need to build with + * g++ -O3 -DHAVE_GETTIMEOFDAY buildtool.cpp -o btool.exe + * */ - +#define BUILDTOOL_VERSION "BuildTool v0.6.9, 2007 Bob Jamison" #include +#include #include #include #include #include #include +#include #include #include @@ -55,6 +62,41 @@ #include +//######################################################################## +//# Definition of gettimeofday() for those who don't have it +//######################################################################## +#ifndef HAVE_GETTIMEOFDAY +#include + +struct timezone { + int tz_minuteswest; /* minutes west of Greenwich */ + int tz_dsttime; /* type of dst correction */ + }; + +static int gettimeofday (struct timeval *tv, struct timezone *tz) +{ + struct _timeb tb; + + if (!tv) + return (-1); + + _ftime (&tb); + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000 + 500; + if (tz) + { + tz->tz_minuteswest = -60 * _timezone; + tz->tz_dsttime = _daylight; + } + return 0; +} + +#endif + + + + + namespace buildtool @@ -62,6 +104,7 @@ namespace buildtool + //######################################################################## //######################################################################## //## R E G E X P @@ -80,29 +123,29 @@ namespace buildtool #ifndef _TREX_H_ #define _TREX_H_ /*************************************************************** - T-Rex a tiny regular expression library + T-Rex a tiny regular expression library - Copyright (C) 2003-2006 Alberto Demichelis + Copyright (C) 2003-2006 Alberto Demichelis - This software is provided 'as-is', without any express - or implied warranty. In no event will the authors be held - liable for any damages arising from the use of this software. + This software is provided 'as-is', without any express + or implied warranty. In no event will the authors be held + liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for - any purpose, including commercial applications, and to alter - it and redistribute it freely, subject to the following restrictions: + Permission is granted to anyone to use this software for + any purpose, including commercial applications, and to alter + it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment - in the product documentation would be appreciated but - is not required. + 1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but + is not required. - 2. Altered source versions must be plainly marked as such, - and must not be misrepresented as being the original software. + 2. Altered source versions must be plainly marked as such, + and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any - source distribution. + 3. This notice may not be removed or altered from any + source distribution. ****************************************************************/ @@ -131,8 +174,8 @@ typedef unsigned int TRexBool; typedef struct TRex TRex; typedef struct { - const TRexChar *begin; - int len; + const TRexChar *begin; + int len; } TRexMatch; TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error); @@ -177,26 +220,26 @@ TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp); static const TRexChar *g_nnames[] = { - _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), - _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), - _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), - _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") + _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), + _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), + _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), + _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") }; #endif -#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} -#define OP_OR (MAX_CHAR+2) -#define OP_EXPR (MAX_CHAR+3) //parentesis () -#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) -#define OP_DOT (MAX_CHAR+5) -#define OP_CLASS (MAX_CHAR+6) -#define OP_CCLASS (MAX_CHAR+7) -#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ -#define OP_RANGE (MAX_CHAR+9) -#define OP_CHAR (MAX_CHAR+10) -#define OP_EOL (MAX_CHAR+11) -#define OP_BOL (MAX_CHAR+12) -#define OP_WB (MAX_CHAR+13) +#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} +#define OP_OR (MAX_CHAR+2) +#define OP_EXPR (MAX_CHAR+3) //parentesis () +#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) +#define OP_DOT (MAX_CHAR+5) +#define OP_CLASS (MAX_CHAR+6) +#define OP_CCLASS (MAX_CHAR+7) +#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ +#define OP_RANGE (MAX_CHAR+9) +#define OP_CHAR (MAX_CHAR+10) +#define OP_EOL (MAX_CHAR+11) +#define OP_BOL (MAX_CHAR+12) +#define OP_WB (MAX_CHAR+13) #define TREX_SYMBOL_ANY_CHAR ('.') #define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') @@ -211,589 +254,589 @@ static const TRexChar *g_nnames[] = typedef int TRexNodeType; typedef struct tagTRexNode{ - TRexNodeType type; - int left; - int right; - int next; + TRexNodeType type; + int left; + int right; + int next; }TRexNode; struct TRex{ - const TRexChar *_eol; - const TRexChar *_bol; - const TRexChar *_p; - int _first; - int _op; - TRexNode *_nodes; - int _nallocated; - int _nsize; - int _nsubexpr; - TRexMatch *_matches; - int _currsubexp; - void *_jmpbuf; - const TRexChar **_error; + const TRexChar *_eol; + const TRexChar *_bol; + const TRexChar *_p; + int _first; + int _op; + TRexNode *_nodes; + int _nallocated; + int _nsize; + int _nsubexpr; + TRexMatch *_matches; + int _currsubexp; + void *_jmpbuf; + const TRexChar **_error; }; static int trex_list(TRex *exp); static int trex_newnode(TRex *exp, TRexNodeType type) { - TRexNode n; - int newid; - n.type = type; - n.next = n.right = n.left = -1; - if(type == OP_EXPR) - n.right = exp->_nsubexpr++; - if(exp->_nallocated < (exp->_nsize + 1)) { - //int oldsize = exp->_nallocated; - exp->_nallocated *= 2; - exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); - } - exp->_nodes[exp->_nsize++] = n; - newid = exp->_nsize - 1; - return (int)newid; + TRexNode n; + int newid; + n.type = type; + n.next = n.right = n.left = -1; + if(type == OP_EXPR) + n.right = exp->_nsubexpr++; + if(exp->_nallocated < (exp->_nsize + 1)) { + //int oldsize = exp->_nallocated; + exp->_nallocated *= 2; + exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + newid = exp->_nsize - 1; + return (int)newid; } static void trex_error(TRex *exp,const TRexChar *error) { - if(exp->_error) *exp->_error = error; - longjmp(*((jmp_buf*)exp->_jmpbuf),-1); + if(exp->_error) *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf),-1); } static void trex_expect(TRex *exp, int n){ - if((*exp->_p) != n) - trex_error(exp, _SC("expected paren")); - exp->_p++; + if((*exp->_p) != n) + trex_error(exp, _SC("expected paren")); + exp->_p++; } static TRexChar trex_escapechar(TRex *exp) { - if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ - exp->_p++; - switch(*exp->_p) { - case 'v': exp->_p++; return '\v'; - case 'n': exp->_p++; return '\n'; - case 't': exp->_p++; return '\t'; - case 'r': exp->_p++; return '\r'; - case 'f': exp->_p++; return '\f'; - default: return (*exp->_p++); - } - } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected")); - return (*exp->_p++); + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ + exp->_p++; + switch(*exp->_p) { + case 'v': exp->_p++; return '\v'; + case 'n': exp->_p++; return '\n'; + case 't': exp->_p++; return '\t'; + case 'r': exp->_p++; return '\r'; + case 'f': exp->_p++; return '\f'; + default: return (*exp->_p++); + } + } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected")); + return (*exp->_p++); } static int trex_charclass(TRex *exp,int classid) { - int n = trex_newnode(exp,OP_CCLASS); - exp->_nodes[n].left = classid; - return n; + int n = trex_newnode(exp,OP_CCLASS); + exp->_nodes[n].left = classid; + return n; } static int trex_charnode(TRex *exp,TRexBool isclass) { - TRexChar t; - if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { - exp->_p++; - switch(*exp->_p) { - case 'n': exp->_p++; return trex_newnode(exp,'\n'); - case 't': exp->_p++; return trex_newnode(exp,'\t'); - case 'r': exp->_p++; return trex_newnode(exp,'\r'); - case 'f': exp->_p++; return trex_newnode(exp,'\f'); - case 'v': exp->_p++; return trex_newnode(exp,'\v'); - case 'a': case 'A': case 'w': case 'W': case 's': case 'S': - case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': - case 'p': case 'P': case 'l': case 'u': - { - t = *exp->_p; exp->_p++; - return trex_charclass(exp,t); - } - case 'b': - case 'B': - if(!isclass) { - int node = trex_newnode(exp,OP_WB); - exp->_nodes[node].left = *exp->_p; - exp->_p++; - return node; - } //else default - default: - t = *exp->_p; exp->_p++; - return trex_newnode(exp,t); - } - } - else if(!scisprint(*exp->_p)) { - - trex_error(exp,_SC("letter expected")); - } - t = *exp->_p; exp->_p++; - return trex_newnode(exp,t); + TRexChar t; + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch(*exp->_p) { + case 'n': exp->_p++; return trex_newnode(exp,'\n'); + case 't': exp->_p++; return trex_newnode(exp,'\t'); + case 'r': exp->_p++; return trex_newnode(exp,'\r'); + case 'f': exp->_p++; return trex_newnode(exp,'\f'); + case 'v': exp->_p++; return trex_newnode(exp,'\v'); + case 'a': case 'A': case 'w': case 'W': case 's': case 'S': + case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': + case 'p': case 'P': case 'l': case 'u': + { + t = *exp->_p; exp->_p++; + return trex_charclass(exp,t); + } + case 'b': + case 'B': + if(!isclass) { + int node = trex_newnode(exp,OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } //else default + default: + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); + } + } + else if(!scisprint(*exp->_p)) { + + trex_error(exp,_SC("letter expected")); + } + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); } static int trex_class(TRex *exp) { - int ret = -1; - int first = -1,chain; - if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ - ret = trex_newnode(exp,OP_NCLASS); - exp->_p++; - }else ret = trex_newnode(exp,OP_CLASS); - - if(*exp->_p == ']') trex_error(exp,_SC("empty class")); - chain = ret; - while(*exp->_p != ']' && exp->_p != exp->_eol) { - if(*exp->_p == '-' && first != -1){ - int r,t; - if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); - r = trex_newnode(exp,OP_RANGE); - if(first>*exp->_p) trex_error(exp,_SC("invalid range")); - if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); - exp->_nodes[r].left = exp->_nodes[first].type; - t = trex_escapechar(exp); - exp->_nodes[r].right = t; + int ret = -1; + int first = -1,chain; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ + ret = trex_newnode(exp,OP_NCLASS); + exp->_p++; + }else ret = trex_newnode(exp,OP_CLASS); + + if(*exp->_p == ']') trex_error(exp,_SC("empty class")); + chain = ret; + while(*exp->_p != ']' && exp->_p != exp->_eol) { + if(*exp->_p == '-' && first != -1){ + int r,t; + if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); + r = trex_newnode(exp,OP_RANGE); + if(first>*exp->_p) trex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + t = trex_escapechar(exp); + exp->_nodes[r].right = t; exp->_nodes[chain].next = r; - chain = r; - first = -1; - } - else{ - if(first!=-1){ - int c = first; - exp->_nodes[chain].next = c; - chain = c; - first = trex_charnode(exp,TRex_True); - } - else{ - first = trex_charnode(exp,TRex_True); - } - } - } - if(first!=-1){ - int c = first; - exp->_nodes[chain].next = c; - chain = c; - first = -1; - } - /* hack? */ - exp->_nodes[ret].left = exp->_nodes[ret].next; - exp->_nodes[ret].next = -1; - return ret; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = trex_charnode(exp,TRex_True); + } + else{ + first = trex_charnode(exp,TRex_True); + } + } + } + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; } static int trex_parsenumber(TRex *exp) { - int ret = *exp->_p-'0'; - int positions = 10; - exp->_p++; - while(isdigit(*exp->_p)) { - ret = ret*10+(*exp->_p++-'0'); - if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); - positions *= 10; - }; - return ret; + int ret = *exp->_p-'0'; + int positions = 10; + exp->_p++; + while(isdigit(*exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; } static int trex_element(TRex *exp) { - int ret = -1; - switch(*exp->_p) - { - case '(': { - int expr,newn; - exp->_p++; - - - if(*exp->_p =='?') { - exp->_p++; - trex_expect(exp,':'); - expr = trex_newnode(exp,OP_NOCAPEXPR); - } - else - expr = trex_newnode(exp,OP_EXPR); - newn = trex_list(exp); - exp->_nodes[expr].left = newn; - ret = expr; - trex_expect(exp,')'); - } - break; - case '[': - exp->_p++; - ret = trex_class(exp); - trex_expect(exp,']'); - break; - case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; - case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; - default: - ret = trex_charnode(exp,TRex_False); - break; - } - - { - int op; - TRexBool isgreedy = TRex_False; - unsigned short p0 = 0, p1 = 0; - switch(*exp->_p){ - case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; - case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; - case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; - case '{': - exp->_p++; - if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected")); - p0 = (unsigned short)trex_parsenumber(exp); - /*******************************/ - switch(*exp->_p) { - case '}': - p1 = p0; exp->_p++; - break; - case ',': - exp->_p++; - p1 = 0xFFFF; - if(isdigit(*exp->_p)){ - p1 = (unsigned short)trex_parsenumber(exp); - } - trex_expect(exp,'}'); - break; - default: - trex_error(exp,_SC(", or } expected")); - } - /*******************************/ - isgreedy = TRex_True; - break; - - } - if(isgreedy) { - int nnode = trex_newnode(exp,OP_GREEDY); - op = OP_GREEDY; - exp->_nodes[nnode].left = ret; - exp->_nodes[nnode].right = ((p0)<<16)|p1; - ret = nnode; - } - } - if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { - int nnode = trex_element(exp); - exp->_nodes[ret].next = nnode; - } - - return ret; + int ret = -1; + switch(*exp->_p) + { + case '(': { + int expr,newn; + exp->_p++; + + + if(*exp->_p =='?') { + exp->_p++; + trex_expect(exp,':'); + expr = trex_newnode(exp,OP_NOCAPEXPR); + } + else + expr = trex_newnode(exp,OP_EXPR); + newn = trex_list(exp); + exp->_nodes[expr].left = newn; + ret = expr; + trex_expect(exp,')'); + } + break; + case '[': + exp->_p++; + ret = trex_class(exp); + trex_expect(exp,']'); + break; + case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; + case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; + default: + ret = trex_charnode(exp,TRex_False); + break; + } + + { + int op; + TRexBool isgreedy = TRex_False; + unsigned short p0 = 0, p1 = 0; + switch(*exp->_p){ + case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; + case '{': + exp->_p++; + if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected")); + p0 = (unsigned short)trex_parsenumber(exp); + /*******************************/ + switch(*exp->_p) { + case '}': + p1 = p0; exp->_p++; + break; + case ',': + exp->_p++; + p1 = 0xFFFF; + if(isdigit(*exp->_p)){ + p1 = (unsigned short)trex_parsenumber(exp); + } + trex_expect(exp,'}'); + break; + default: + trex_error(exp,_SC(", or } expected")); + } + /*******************************/ + isgreedy = TRex_True; + break; + + } + if(isgreedy) { + int nnode = trex_newnode(exp,OP_GREEDY); + op = OP_GREEDY; + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0)<<16)|p1; + ret = nnode; + } + } + if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { + int nnode = trex_element(exp); + exp->_nodes[ret].next = nnode; + } + + return ret; } static int trex_list(TRex *exp) { - int ret=-1,e; - if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { - exp->_p++; - ret = trex_newnode(exp,OP_BOL); - } - e = trex_element(exp); - if(ret != -1) { - exp->_nodes[ret].next = e; - } - else ret = e; - - if(*exp->_p == TREX_SYMBOL_BRANCH) { - int temp,tright; - exp->_p++; - temp = trex_newnode(exp,OP_OR); - exp->_nodes[temp].left = ret; - tright = trex_list(exp); - exp->_nodes[temp].right = tright; - ret = temp; - } - return ret; + int ret=-1,e; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = trex_newnode(exp,OP_BOL); + } + e = trex_element(exp); + if(ret != -1) { + exp->_nodes[ret].next = e; + } + else ret = e; + + if(*exp->_p == TREX_SYMBOL_BRANCH) { + int temp,tright; + exp->_p++; + temp = trex_newnode(exp,OP_OR); + exp->_nodes[temp].left = ret; + tright = trex_list(exp); + exp->_nodes[temp].right = tright; + ret = temp; + } + return ret; } static TRexBool trex_matchcclass(int cclass,TRexChar c) { - switch(cclass) { - case 'a': return isalpha(c)?TRex_True:TRex_False; - case 'A': return !isalpha(c)?TRex_True:TRex_False; - case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; - case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; - case 's': return isspace(c)?TRex_True:TRex_False; - case 'S': return !isspace(c)?TRex_True:TRex_False; - case 'd': return isdigit(c)?TRex_True:TRex_False; - case 'D': return !isdigit(c)?TRex_True:TRex_False; - case 'x': return isxdigit(c)?TRex_True:TRex_False; - case 'X': return !isxdigit(c)?TRex_True:TRex_False; - case 'c': return iscntrl(c)?TRex_True:TRex_False; - case 'C': return !iscntrl(c)?TRex_True:TRex_False; - case 'p': return ispunct(c)?TRex_True:TRex_False; - case 'P': return !ispunct(c)?TRex_True:TRex_False; - case 'l': return islower(c)?TRex_True:TRex_False; - case 'u': return isupper(c)?TRex_True:TRex_False; - } - return TRex_False; /*cannot happen*/ + switch(cclass) { + case 'a': return isalpha(c)?TRex_True:TRex_False; + case 'A': return !isalpha(c)?TRex_True:TRex_False; + case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; + case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; + case 's': return isspace(c)?TRex_True:TRex_False; + case 'S': return !isspace(c)?TRex_True:TRex_False; + case 'd': return isdigit(c)?TRex_True:TRex_False; + case 'D': return !isdigit(c)?TRex_True:TRex_False; + case 'x': return isxdigit(c)?TRex_True:TRex_False; + case 'X': return !isxdigit(c)?TRex_True:TRex_False; + case 'c': return iscntrl(c)?TRex_True:TRex_False; + case 'C': return !iscntrl(c)?TRex_True:TRex_False; + case 'p': return ispunct(c)?TRex_True:TRex_False; + case 'P': return !ispunct(c)?TRex_True:TRex_False; + case 'l': return islower(c)?TRex_True:TRex_False; + case 'u': return isupper(c)?TRex_True:TRex_False; + } + return TRex_False; /*cannot happen*/ } static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c) { - do { - switch(node->type) { - case OP_RANGE: - if(c >= node->left && c <= node->right) return TRex_True; - break; - case OP_CCLASS: - if(trex_matchcclass(node->left,c)) return TRex_True; - break; - default: - if(c == node->type)return TRex_True; - } - } while((node->next != -1) && (node = &exp->_nodes[node->next])); - return TRex_False; + do { + switch(node->type) { + case OP_RANGE: + if(c >= node->left && c <= node->right) return TRex_True; + break; + case OP_CCLASS: + if(trex_matchcclass(node->left,c)) return TRex_True; + break; + default: + if(c == node->type)return TRex_True; + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return TRex_False; } static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next) { - - TRexNodeType type = node->type; - switch(type) { - case OP_GREEDY: { - //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; - TRexNode *greedystop = NULL; - int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; - const TRexChar *s=str, *good = str; - - if(node->next != -1) { - greedystop = &exp->_nodes[node->next]; - } - else { - greedystop = next; - } - - while((nmaches == 0xFFFF || nmaches < p1)) { - - const TRexChar *stop; - if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) - break; - nmaches++; - good=s; - if(greedystop) { - //checks that 0 matches satisfy the expression(if so skips) - //if not would always stop(for instance if is a '?') - if(greedystop->type != OP_GREEDY || - (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) - { - TRexNode *gnext = NULL; - if(greedystop->next != -1) { - gnext = &exp->_nodes[greedystop->next]; - }else if(next && next->next != -1){ - gnext = &exp->_nodes[next->next]; - } - stop = trex_matchnode(exp,greedystop,s,gnext); - if(stop) { - //if satisfied stop it - if(p0 == p1 && p0 == nmaches) break; - else if(nmaches >= p0 && p1 == 0xFFFF) break; - else if(nmaches >= p0 && nmaches <= p1) break; - } - } - } - - if(s >= exp->_eol) - break; - } - if(p0 == p1 && p0 == nmaches) return good; - else if(nmaches >= p0 && p1 == 0xFFFF) return good; - else if(nmaches >= p0 && nmaches <= p1) return good; - return NULL; - } - case OP_OR: { - const TRexChar *asd = str; - TRexNode *temp=&exp->_nodes[node->left]; - while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - asd = str; - temp = &exp->_nodes[node->right]; - while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - return NULL; - break; - } - case OP_EXPR: - case OP_NOCAPEXPR:{ - TRexNode *n = &exp->_nodes[node->left]; - const TRexChar *cur = str; - int capture = -1; - if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { - capture = exp->_currsubexp; - exp->_matches[capture].begin = cur; - exp->_currsubexp++; - } - - do { - TRexNode *subnext = NULL; - if(n->next != -1) { - subnext = &exp->_nodes[n->next]; - }else { - subnext = next; - } - if(!(cur = trex_matchnode(exp,n,cur,subnext))) { - if(capture != -1){ - exp->_matches[capture].begin = 0; - exp->_matches[capture].len = 0; - } - return NULL; - } - } while((n->next != -1) && (n = &exp->_nodes[n->next])); - - if(capture != -1) - exp->_matches[capture].len = cur - exp->_matches[capture].begin; - return cur; - } - case OP_WB: - if(str == exp->_bol && !isspace(*str) - || (str == exp->_eol && !isspace(*(str-1))) - || (!isspace(*str) && isspace(*(str+1))) - || (isspace(*str) && !isspace(*(str+1))) ) { - return (node->left == 'b')?str:NULL; - } - return (node->left == 'b')?NULL:str; - case OP_BOL: - if(str == exp->_bol) return str; - return NULL; - case OP_EOL: - if(str == exp->_eol) return str; - return NULL; - case OP_DOT:{ - *str++; - } - return str; - case OP_NCLASS: - case OP_CLASS: - if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { - *str++; - return str; - } - return NULL; - case OP_CCLASS: - if(trex_matchcclass(node->left,*str)) { - *str++; - return str; - } - return NULL; - default: /* char */ - if(*str != node->type) return NULL; - *str++; - return str; - } - return NULL; + + TRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + TRexNode *greedystop = NULL; + int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const TRexChar *s=str, *good = str; + + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } + + while((nmaches == 0xFFFF || nmaches < p1)) { + + const TRexChar *stop; + if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + TRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = trex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } + + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const TRexChar *asd = str; + TRexNode *temp=&exp->_nodes[node->left]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + TRexNode *n = &exp->_nodes[node->left]; + const TRexChar *cur = str; + int capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } + + do { + TRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = trex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); + + if(capture != -1) + exp->_matches[capture].len = cur - exp->_matches[capture].begin; + return cur; + } + case OP_WB: + if(str == exp->_bol && !isspace(*str) + || (str == exp->_eol && !isspace(*(str-1))) + || (!isspace(*str) && isspace(*(str+1))) + || (isspace(*str) && !isspace(*(str+1))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT:{ + *str++; + } + return str; + case OP_NCLASS: + case OP_CLASS: + if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { + *str++; + return str; + } + return NULL; + case OP_CCLASS: + if(trex_matchcclass(node->left,*str)) { + *str++; + return str; + } + return NULL; + default: /* char */ + if(*str != node->type) return NULL; + *str++; + return str; + } + return NULL; } /* public api */ TRex *trex_compile(const TRexChar *pattern,const TRexChar **error) { - TRex *exp = (TRex *)malloc(sizeof(TRex)); - exp->_eol = exp->_bol = NULL; - exp->_p = pattern; - exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); - exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); - exp->_nsize = 0; - exp->_matches = 0; - exp->_nsubexpr = 0; - exp->_first = trex_newnode(exp,OP_EXPR); - exp->_error = error; - exp->_jmpbuf = malloc(sizeof(jmp_buf)); - if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { - int res = trex_list(exp); - exp->_nodes[exp->_first].left = res; - if(*exp->_p!='\0') - trex_error(exp,_SC("unexpected character")); + TRex *exp = (TRex *)malloc(sizeof(TRex)); + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); + exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = trex_newnode(exp,OP_EXPR); + exp->_error = error; + exp->_jmpbuf = malloc(sizeof(jmp_buf)); + if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + int res = trex_list(exp); + exp->_nodes[exp->_first].left = res; + if(*exp->_p!='\0') + trex_error(exp,_SC("unexpected character")); #ifdef _DEBUG - { - int nsize,i; - TRexNode *t; - nsize = exp->_nsize; - t = &exp->_nodes[0]; - scprintf(_SC("\n")); - for(i = 0;i < nsize; i++) { - if(exp->_nodes[i].type>MAX_CHAR) - scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); - else - scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); - scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); - } - scprintf(_SC("\n")); - } + { + int nsize,i; + TRexNode *t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } #endif - exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); - memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); - } - else{ - trex_free(exp); - return NULL; - } - return exp; + exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); + memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); + } + else{ + trex_free(exp); + return NULL; + } + return exp; } void trex_free(TRex *exp) { - if(exp) { - if(exp->_nodes) free(exp->_nodes); - if(exp->_jmpbuf) free(exp->_jmpbuf); - if(exp->_matches) free(exp->_matches); - free(exp); - } + if(exp) { + if(exp->_nodes) free(exp->_nodes); + if(exp->_jmpbuf) free(exp->_jmpbuf); + if(exp->_matches) free(exp->_matches); + free(exp); + } } TRexBool trex_match(TRex* exp,const TRexChar* text) { - const TRexChar* res = NULL; - exp->_bol = text; - exp->_eol = text + scstrlen(text); - exp->_currsubexp = 0; - res = trex_matchnode(exp,exp->_nodes,text,NULL); - if(res == NULL || res != exp->_eol) - return TRex_False; - return TRex_True; + const TRexChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = trex_matchnode(exp,exp->_nodes,text,NULL); + if(res == NULL || res != exp->_eol) + return TRex_False; + return TRex_True; } TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) { - const TRexChar *cur = NULL; - int node = exp->_first; - if(text_begin >= text_end) return TRex_False; - exp->_bol = text_begin; - exp->_eol = text_end; - do { - cur = text_begin; - while(node != -1) { - exp->_currsubexp = 0; - cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); - if(!cur) - break; - node = exp->_nodes[node].next; - } - *text_begin++; - } while(cur == NULL && text_begin != text_end); - - if(cur == NULL) - return TRex_False; - - --text_begin; - - if(out_begin) *out_begin = text_begin; - if(out_end) *out_end = cur; - return TRex_True; + const TRexChar *cur = NULL; + int node = exp->_first; + if(text_begin >= text_end) return TRex_False; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while(node != -1) { + exp->_currsubexp = 0; + cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); + if(!cur) + break; + node = exp->_nodes[node].next; + } + *text_begin++; + } while(cur == NULL && text_begin != text_end); + + if(cur == NULL) + return TRex_False; + + --text_begin; + + if(out_begin) *out_begin = text_begin; + if(out_end) *out_end = cur; + return TRex_True; } TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) { - return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); + return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); } int trex_getsubexpcount(TRex* exp) { - return exp->_nsubexpr; + return exp->_nsubexpr; } TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp) { - if( n<0 || n >= exp->_nsubexpr) return TRex_False; - *subexp = exp->_matches[n]; - return TRex_True; + if( n<0 || n >= exp->_nsubexpr) return TRex_False; + *subexp = exp->_matches[n]; + return TRex_True; } @@ -918,18 +961,18 @@ friend class Parser; public: Element() { - parent = NULL; + init(); } Element(const String &nameArg) { - parent = NULL; + init(); name = nameArg; } Element(const String &nameArg, const String &valueArg) { - parent = NULL; + init(); name = nameArg; value = valueArg; } @@ -997,9 +1040,18 @@ public: * @param elem the element to output */ void print(); + + int getLine() + { return line; } protected: + void init() + { + parent = NULL; + line = 0; + } + void assign(const Element &other) { parent = other.parent; @@ -1008,6 +1060,7 @@ protected: namespaces = other.namespaces; name = other.name; value = other.value; + line = other.line; } void findElementsRecursive(std::vector&res, const String &name); @@ -1023,7 +1076,8 @@ protected: String name; String value; - + + int line; }; @@ -1091,15 +1145,17 @@ private: currentPosition = 0; } - void getLineAndColumn(long pos, long *lineNr, long *colNr); + int countLines(int begin, int end); + + void getLineAndColumn(int pos, int *lineNr, int *colNr); void error(char *fmt, ...); - int peek(long pos); + int peek(int pos); - int match(long pos, const char *text); + int match(int pos, const char *text); - int skipwhite(long p); + int skipwhite(int p); int getWord(int p0, String &buf); @@ -1115,12 +1171,10 @@ private: bool keepGoing; Element *currentNode; - long parselen; + int parselen; XMLCh *parsebuf; - String cdatabuf; - long currentPosition; - int colNr; - + String cdatabuf; + int currentPosition; }; @@ -1136,6 +1190,7 @@ Element *Element::clone() elem->parent = parent; elem->attributes = attributes; elem->namespaces = namespaces; + elem->line = line; std::vector::iterator iter; for (iter = children.begin(); iter != children.end() ; iter++) @@ -1314,10 +1369,24 @@ String Parser::trim(const String &s) return res; } -void Parser::getLineAndColumn(long pos, long *lineNr, long *colNr) + +int Parser::countLines(int begin, int end) +{ + int count = 0; + for (int i=begin ; i= parselen) return -1; @@ -1386,7 +1455,7 @@ String Parser::encode(const String &str) } -int Parser::match(long p0, const char *text) +int Parser::match(int p0, const char *text) { int p = p0; while (*text) @@ -1400,7 +1469,7 @@ int Parser::match(long p0, const char *text) -int Parser::skipwhite(long p) +int Parser::skipwhite(int p) { while (pline = lineNr + countLines(p0, p); n->parent = par; par->addChild(n); @@ -1675,7 +1750,7 @@ int Parser::parseElement(int p0, Element *par,int depth) //# CHILD ELEMENT if (ch == '<') { - p2 = parseElement(p, n, depth+1); + p2 = parseElement(p, n, lineNr + countLines(p0, p)); if (p2 == p) { /* @@ -1767,7 +1842,7 @@ Element *Parser::parse(XMLCh *buf,int pos,int len) Element *rootNode = new Element("root"); pos = parseVersion(pos); pos = parseDoctype(pos); - pos = parseElement(pos, rootNode, 0); + pos = parseElement(pos, rootNode, 1); return rootNode; } @@ -1834,8 +1909,6 @@ Element *Parser::parseFile(const String &fileName) return n; } - - //######################################################################## //######################################################################## //## E N D X M L @@ -1843,6 +1916,10 @@ Element *Parser::parseFile(const String &fileName) //######################################################################## + + + + //######################################################################## //######################################################################## //## U R I @@ -2288,6 +2365,7 @@ URI URI::resolve(const URI &other) const } + /** * This follows the Java URI algorithm: * 1. All "." segments are removed. @@ -2406,6 +2484,7 @@ void URI::trace(const char *fmt, ...) + //######################################################################### //# P A R S I N G //######################################################################### @@ -2793,13 +2872,14 @@ private: class MakeBase { public: + MakeBase() - {} + { line = 0; } virtual ~MakeBase() {} /** - * Return the URI of the file associated with this object + * Return the URI of the file associated with this object */ URI getURI() { return uri; } @@ -2824,11 +2904,23 @@ public: * Get an element value, performing substitutions if necessary */ bool getValue(Element *elem, String &result); + + /** + * Set the current line number in the file + */ + void setLine(int val) + { line = val; } + + /** + * Get the current line number in the file + */ + int getLine() + { return line; } protected: /** - * The path to the file associated with this object + * The path to the file associated with this object */ URI uri; @@ -2863,7 +2955,7 @@ protected: * in delimiters. Null-length substrings are ignored */ std::vector tokenize(const String &val, - const String &delimiters); + const String &delimiters); /** * replace runs of whitespace with a space @@ -2889,30 +2981,30 @@ protected: /** * Execute a shell command. Outbuf is a ref to a string * to catch the result. - */ + */ bool executeCommand(const String &call, - const String &inbuf, - String &outbuf, - String &errbuf); + const String &inbuf, + String &outbuf, + String &errbuf); /** * List all directories in a given base and starting directory * It is usually called like: - * bool ret = listDirectories("src", "", result); - */ + * bool ret = listDirectories("src", "", result); + */ bool listDirectories(const String &baseName, const String &dirname, std::vector &res); /** * Find all files in the named directory - */ + */ bool listFiles(const String &baseName, const String &dirname, std::vector &result); /** * Perform a listing for a fileset - */ + */ bool listFiles(MakeBase &propRef, FileSet &fileSet); /** @@ -2920,8 +3012,8 @@ protected: */ bool parsePatternSet(Element *elem, MakeBase &propRef, - std::vector &includes, - std::vector &excludes); + std::vector &includes, + std::vector &excludes); /** * Parse a entry, and determine which files @@ -2929,7 +3021,7 @@ protected: */ bool parseFileSet(Element *elem, MakeBase &propRef, - FileSet &fileSet); + FileSet &fileSet); /** * Return this object's property list @@ -2955,13 +3047,13 @@ protected: /** * Turn 'true' and 'false' into boolean values - */ + */ bool getBool(const String &str, bool &val); /** * Create a directory, making intermediate dirs * if necessary - */ + */ bool createDirectory(const String &dirname); /** @@ -2993,9 +3085,10 @@ private: /** * replace variable refs like ${a} with their values - */ + */ bool getSubstitutions(const String &s, String &result); + int line; }; @@ -3010,7 +3103,7 @@ void MakeBase::error(char *fmt, ...) { va_list args; va_start(args,fmt); - fprintf(stderr, "Make error: "); + fprintf(stderr, "Make error line %d: ", line); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args) ; @@ -3065,30 +3158,30 @@ void MakeBase::trace(char *fmt, ...) */ bool MakeBase::regexMatch(const String &str, const String &pattern) { - const TRexChar *terror = NULL; - const TRexChar *cpat = pattern.c_str(); - TRex *expr = trex_compile(cpat, &terror); - if (!expr) - { - if (!terror) - terror = "undefined"; - error("compilation error [%s]!\n", terror); - return false; - } + const TRexChar *terror = NULL; + const TRexChar *cpat = pattern.c_str(); + TRex *expr = trex_compile(cpat, &terror); + if (!expr) + { + if (!terror) + terror = "undefined"; + error("compilation error [%s]!\n", terror); + return false; + } bool ret = true; - const TRexChar *cstr = str.c_str(); - if (trex_match(expr, cstr)) - { - ret = true; - } - else - { - ret = false; - } + const TRexChar *cstr = str.c_str(); + if (trex_match(expr, cstr)) + { + ret = true; + } + else + { + ret = false; + } - trex_free(expr); + trex_free(expr); return ret; } @@ -3198,16 +3291,16 @@ String MakeBase::leftJustify(const String &s) //Skip to first visible character while (i0 && !WriteFile(stdinWrite, inbuf.c_str(), inbuf.size(), &bytesWritten, NULL)) { error("executeCommand: could not write to pipe"); - return false; - } + return false; + } if (!CloseHandle(stdinWrite)) - { + { error("executeCommand: could not close write pipe"); - return false; - } + return false; + } if (!CloseHandle(stdoutWrite)) - { + { error("executeCommand: could not close read pipe"); - return false; - } + return false; + } if (!CloseHandle(stderrWrite)) - { + { error("executeCommand: could not close read pipe"); - return false; - } - while (true) + return false; + } + + bool lastLoop = false; + while (true) { - //trace("## stderr"); DWORD avail; - if (!PeekNamedPipe(stderrRead, NULL, 0, NULL, &avail, NULL)) - break; + DWORD bytesRead; + char readBuf[4096]; + + //trace("## stderr"); + PeekNamedPipe(stderrRead, NULL, 0, NULL, &avail, NULL); if (avail > 0) { - DWORD bytesRead = 0; - char readBuf[1025]; - if (avail>1024) avail = 1024; - if (!ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL) - || bytesRead == 0) + bytesRead = 0; + if (avail>4096) avail = 4096; + ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL); + if (bytesRead > 0) { - break; + for (unsigned int i=0 ; i 0) { - DWORD bytesRead = 0; - char readBuf[1025]; - if (avail>1024) avail = 1024; - if (!ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL) - || bytesRead==0) + bytesRead = 0; + if (avail>4096) avail = 4096; + ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL); + if (bytesRead > 0) { - break; + for (unsigned int i=0 ; i fileList; if (!listFiles(baseDir, "", fileList)) - return false; + return false; std::vector includes = fileSet.getIncludes(); std::vector excludes = fileSet.getExcludes(); @@ -3655,9 +3757,9 @@ bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet) //If there are , then add files to the output //in the order of the include list if (includes.size()==0) - incs = fileList; - else - { + incs = fileList; + else + { for (iter = includes.begin() ; iter != includes.end() ; iter++) { String pattern = *iter; @@ -3695,9 +3797,9 @@ bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet) res.push_back(s); } - fileSet.setFiles(res); + fileSet.setFiles(res); - return true; + return true; } @@ -3713,44 +3815,44 @@ bool MakeBase::getSubstitutions(const String &str, String &result) { char ch = s[i]; if (ch == '$' && s[i+1] == '{') - { + { String varname; - int j = i+2; - for ( ; j::iterator iter; - iter = properties.find(trim(varname)); - if (iter != properties.end()) - { - val.append(iter->second); - } - else - { - error("property ${%s} not found", varname.c_str()); - return false; - } - break; - } - else - { - varname.push_back(ch); - } - } - i = j; - } - else - { - val.push_back(ch); - } + int j = i+2; + for ( ; j::iterator iter; + iter = properties.find(trim(varname)); + if (iter != properties.end()) + { + val.append(iter->second); + } + else + { + error("property ${%s} not found", varname.c_str()); + return false; + } + break; + } + else + { + varname.push_back(ch); + } + } + i = j; + } + else + { + val.push_back(ch); + } } result = val; return true; @@ -3775,7 +3877,7 @@ bool MakeBase::getValue(Element *elem, String &result) /** * Turn 'true' and 'false' into boolean values - */ + */ bool MakeBase::getBool(const String &str, bool &val) { if (str == "true") @@ -3798,9 +3900,9 @@ bool MakeBase::getBool(const String &str, bool &val) */ bool MakeBase::parsePatternSet(Element *elem, MakeBase &propRef, - std::vector &includes, - std::vector &excludes - ) + std::vector &includes, + std::vector &excludes + ) { std::vector children = elem->getChildren(); for (unsigned int i=0 ; igetName(); if (name != "fileset") @@ -3885,19 +3987,19 @@ bool MakeBase::parseFileSet(Element *elem, if (dir.size() > 0) { String baseDir = propRef.resolve(dir); - if (!listFiles(baseDir, "", includes, excludes, fileList)) - return false; - } + if (!listFiles(baseDir, "", includes, excludes, fileList)) + return false; + } std::sort(fileList.begin(), fileList.end()); - result = fileList; - */ - - - /* - for (unsigned int i=0 ; i infoB.st_mtime) { - return true; - } + return true; + } return false; } @@ -4672,23 +4774,23 @@ public: * Constructor */ FileRec() - {init(); type = UNKNOWN;} + { init(); type = UNKNOWN; } /** * Copy constructor */ FileRec(const FileRec &other) - {init(); assign(other);} + { init(); assign(other); } /** * Constructor */ FileRec(int typeVal) - {init(); type = typeVal;} + { init(); type = typeVal; } /** * Assignment operator */ FileRec &operator=(const FileRec &other) - {init(); assign(other); return *this;} + { init(); assign(other); return *this; } /** @@ -4810,7 +4912,7 @@ private: path = other.path; name = other.name; suffix = other.suffix; - files = other.files; + files = other.files; //avoid recursion } }; @@ -4824,19 +4926,19 @@ public: * Constructor */ DepTool() - {init();} + { init(); } /** * Copy constructor */ DepTool(const DepTool &other) - {init(); assign(other);} + { init(); assign(other); } /** * Assignment operator */ DepTool &operator=(const DepTool &other) - {init(); assign(other); return *this;} + { init(); assign(other); return *this; } /** @@ -4957,9 +5059,7 @@ private: /** * */ - bool processDependency(FileRec *ofile, - FileRec *include, - int depth); + bool processDependency(FileRec *ofile, FileRec *include); /** * @@ -4978,8 +5078,7 @@ private: /** * A list of all files which will be processed for - * dependencies. This is the only list that has the actual - * records. All other lists have pointers to these records. + * dependencies. */ std::map allFiles; @@ -4987,7 +5086,7 @@ private: * The list of .o files, and the * dependencies upon them. */ - std::map depFiles; + std::map oFiles; int depFileSize; char *depFileBuf; @@ -5012,13 +5111,15 @@ void DepTool::init() fileList.clear(); directories.clear(); - //clear refs - depFiles.clear(); - //clear records + //clear output file list std::map::iterator iter; - for (iter=allFiles.begin() ; iter!=allFiles.end() ; iter++) - delete iter->second; + for (iter=oFiles.begin(); iter!=oFiles.end() ; iter++) + delete iter->second; + oFiles.clear(); + //allFiles actually contains the master copies. delete them + for (iter= allFiles.begin(); iter!=allFiles.end() ; iter++) + delete iter->second; allFiles.clear(); } @@ -5078,7 +5179,7 @@ bool DepTool::createFileList() String sfx; parseName(fileName, path, basename, sfx); if (sfx == "cpp" || sfx == "c" || sfx == "cxx" || - sfx == "cc" || sfx == "CC") + sfx == "cc" || sfx == "CC") { FileRec *fe = new FileRec(FileRec::CFILE); fe->path = path; @@ -5183,7 +5284,8 @@ bool DepTool::sequ(int pos, char *key) */ bool DepTool::addIncludeFile(FileRec *frec, const String &iname) { - + //# if the name is an exact match to a path name + //# in allFiles, like "myinc.h" std::map::iterator iter = allFiles.find(iname); if (iter != allFiles.end()) //already exists @@ -5196,6 +5298,7 @@ bool DepTool::addIncludeFile(FileRec *frec, const String &iname) } else { + //## Ok, it was not found directly //look in other dirs std::vector::iterator diter; for (diter=directories.begin() ; @@ -5204,12 +5307,17 @@ bool DepTool::addIncludeFile(FileRec *frec, const String &iname) String dfname = *diter; dfname.append("/"); dfname.append(iname); - iter = allFiles.find(dfname); + URI fullPathURI(dfname); //normalize path name + String fullPath = fullPathURI.getPath(); + if (fullPath[0] == '/') + fullPath = fullPath.substr(1); + //trace("Normalized %s to %s", dfname.c_str(), fullPath.c_str()); + iter = allFiles.find(fullPath); if (iter != allFiles.end()) { FileRec *other = iter->second; //trace("other: '%s'", iname.c_str()); - frec->files[dfname] = other; + frec->files[fullPath] = other; return true; } } @@ -5316,9 +5424,7 @@ bool DepTool::scanFile(const String &fname, FileRec *frec) * Recursively check include lists to find all files in allFiles to which * a given file is dependent. */ -bool DepTool::processDependency(FileRec *ofile, - FileRec *include, - int depth) +bool DepTool::processDependency(FileRec *ofile, FileRec *include) { std::map::iterator iter; for (iter=include->files.begin() ; iter!=include->files.end() ; iter++) @@ -5332,7 +5438,7 @@ bool DepTool::processDependency(FileRec *ofile, FileRec *child = iter->second; ofile->files[fname] = child; - processDependency(ofile, child, depth+1); + processDependency(ofile, child); } @@ -5365,23 +5471,23 @@ bool DepTool::generateDependencies() FileRec *include = iter->second; if (include->type == FileRec::CFILE) { - String cFileName = iter->first; - FileRec *ofile = new FileRec(FileRec::OFILE); - ofile->path = include->path; - ofile->baseName = include->baseName; - ofile->suffix = include->suffix; - String fname = include->path; + String cFileName = iter->first; + FileRec *ofile = new FileRec(FileRec::OFILE); + ofile->path = include->path; + ofile->baseName = include->baseName; + ofile->suffix = include->suffix; + String fname = include->path; if (fname.size()>0) fname.append("/"); fname.append(include->baseName); fname.append(".o"); - depFiles[fname] = ofile; + oFiles[fname] = ofile; //add the .c file first? no, don't //ofile->files[cFileName] = include; //trace("ofile:%s", fname.c_str()); - processDependency(ofile, include, 0); + processDependency(ofile, include); } } @@ -5429,13 +5535,13 @@ bool DepTool::saveDepFile(const String &fileName) fprintf(f, "\n\n", sourceDir.c_str()); std::map::iterator iter; - for (iter=depFiles.begin() ; iter!=depFiles.end() ; iter++) + for (iter=oFiles.begin() ; iter!=oFiles.end() ; iter++) { FileRec *frec = iter->second; if (frec->type == FileRec::OFILE) { fprintf(f, "\n", - frec->path.c_str(), frec->baseName.c_str(), frec->suffix.c_str()); + frec->path.c_str(), frec->baseName.c_str(), frec->suffix.c_str()); std::map::iterator citer; for (citer=frec->files.begin() ; citer!=frec->files.end() ; citer++) { @@ -5603,6 +5709,7 @@ public: TASK_SHAREDLIB, TASK_STATICLIB, TASK_STRIP, + TASK_TOUCH, TASK_TSTAMP } TaskType; @@ -5671,7 +5778,7 @@ public: /** * */ - Task *createTask(Element *elem); + Task *createTask(Element *elem, int lineNr); protected: @@ -5714,21 +5821,21 @@ public: TaskCC(MakeBase &par) : Task(par) { - type = TASK_CC; name = "cc"; - ccCommand = "gcc"; - cxxCommand = "g++"; - source = "."; - dest = "."; - flags = ""; - defines = ""; - includes = ""; - fileSet.clear(); + type = TASK_CC; name = "cc"; + ccCommand = "gcc"; + cxxCommand = "g++"; + source = "."; + dest = "."; + flags = ""; + defines = ""; + includes = ""; + fileSet.clear(); } virtual ~TaskCC() {} - virtual bool needsCompiling(const DepRec &depRec, + virtual bool needsCompiling(const FileRec &depRec, const String &src, const String &dest) { return false; @@ -5738,6 +5845,9 @@ public: { if (!listFiles(parent, fileSet)) return false; + + FILE *f = NULL; + f = fopen("compile.lst", "w"); bool refreshCache = false; String fullName = parent.resolve("build.dep"); @@ -5798,44 +5908,44 @@ public: String sfx = dep.suffix; String command = ccCommand; if (sfx == "cpp" || sfx == "c++" || sfx == "cc" - || sfx == "CC") - command = cxxCommand; + || sfx == "CC") + command = cxxCommand; //## Make paths String destPath = dest; String srcPath = source; if (dep.path.size()>0) - { + { destPath.append("/"); - destPath.append(dep.path); + destPath.append(dep.path); srcPath.append("/"); - srcPath.append(dep.path); - } + srcPath.append(dep.path); + } //## Make sure destination directory exists - if (!createDirectory(destPath)) - return false; - + if (!createDirectory(destPath)) + return false; + //## Check whether it needs to be done - String destName; + String destName; if (destPath.size()>0) { destName.append(destPath); - destName.append("/"); - } - destName.append(dep.name); - destName.append(".o"); - String destFullName = parent.resolve(destName); - String srcName; + destName.append("/"); + } + destName.append(dep.name); + destName.append(".o"); + String destFullName = parent.resolve(destName); + String srcName; if (srcPath.size()>0) { srcName.append(srcPath); srcName.append("/"); } - srcName.append(dep.name); - srcName.append("."); - srcName.append(dep.suffix); - String srcFullName = parent.resolve(srcName); - bool compileMe = false; + srcName.append(dep.name); + srcName.append("."); + srcName.append(dep.suffix); + String srcFullName = parent.resolve(srcName); + bool compileMe = false; if (isNewerThan(srcFullName, destFullName)) { status(" : compile of %s required by %s", @@ -5872,23 +5982,60 @@ public: String cmd = command; cmd.append(" -c "); cmd.append(flags); - cmd.append(" "); + cmd.append(" "); cmd.append(defines); - cmd.append(" "); + cmd.append(" "); cmd.append(incs); - cmd.append(" "); - cmd.append(srcFullName); + cmd.append(" "); + cmd.append(srcFullName); cmd.append(" -o "); - cmd.append(destFullName); + cmd.append(destFullName); //## Execute the command String outString, errString; - if (!executeCommand(cmd.c_str(), "", outString, errString)) + bool ret = executeCommand(cmd.c_str(), "", outString, errString); + + if (f) + { + fprintf(f, "########################### File : %s\n", + srcFullName.c_str()); + fprintf(f, "#### COMMAND ###\n"); + int col = 0; + for (int i = 0 ; i < cmd.size() ; i++) + { + char ch = cmd[i]; + if (isspace(ch) && col > 63) + { + fputc('\n', f); + col = 0; + } + else + { + fputc(ch, f); + col++; + } + if (col > 76) + { + fputc('\n', f); + col = 0; + } + } + fprintf(f, "\n"); + fprintf(f, "#### STDOUT ###\n%s\n", outString.c_str()); + fprintf(f, "#### STDERR ###\n%s\n\n", errString.c_str()); + } + if (!ret) { error("problem compiling: %s", errString.c_str()); return false; } + + } + + if (f) + { + fclose(f); } return true; @@ -5975,11 +6122,11 @@ public: TaskCopy(MakeBase &par) : Task(par) { - type = TASK_COPY; name = "copy"; - cptype = CP_NONE; - verbose = false; - haveFileSet = false; - } + type = TASK_COPY; name = "copy"; + cptype = CP_NONE; + verbose = false; + haveFileSet = false; + } virtual ~TaskCopy() {} @@ -5997,12 +6144,12 @@ public: String fullSource = parent.resolve(fileName); String fullDest = parent.resolve(toFileName); //trace("copy %s to file %s", fullSource.c_str(), - // fullDest.c_str()); - if (!isRegularFile(fullSource)) - { + // fullDest.c_str()); + if (!isRegularFile(fullSource)) + { error("copy : file %s does not exist", fullSource.c_str()); - return false; - } + return false; + } if (!isNewerThan(fullSource, fullDest)) { return true; @@ -6042,11 +6189,11 @@ public: String baseFileSetDir = fileSetDir; unsigned int pos = baseFileSetDir.find_last_of('/'); if (pos!=baseFileSetDir.npos && - pos < baseFileSetDir.size()-1) + pos < baseFileSetDir.size()-1) baseFileSetDir = - baseFileSetDir.substr(pos+1, - baseFileSetDir.size()); - //Now make the new path + baseFileSetDir.substr(pos+1, + baseFileSetDir.size()); + //Now make the new path String destPath; if (toDirName.size()>0) { @@ -6062,7 +6209,7 @@ public: String fullDest = parent.resolve(destPath); //trace("fileName:%s", fileName.c_str()); //trace("copy %s to new dir : %s", fullSource.c_str(), - // fullDest.c_str()); + // fullDest.c_str()); if (!isNewerThan(fullSource, fullDest)) { //trace("copy skipping %s", fullSource.c_str()); @@ -6094,12 +6241,12 @@ public: destPath.append(baseName); String fullDest = parent.resolve(destPath); //trace("copy %s to new dir : %s", fullSource.c_str(), - // fullDest.c_str()); - if (!isRegularFile(fullSource)) - { + // fullDest.c_str()); + if (!isRegularFile(fullSource)) + { error("copy : file %s does not exist", fullSource.c_str()); - return false; - } + return false; + } if (!isNewerThan(fullSource, fullDest)) { return true; @@ -6145,18 +6292,18 @@ public: if (!parseFileSet(child, parent, fileSet)) { error("problem getting fileset"); - return false; - } - haveFileSet = true; + return false; + } + haveFileSet = true; } } //Perform validity checks - if (fileName.size()>0 && fileSet.size()>0) - { - error(" can only have one of : file= and "); - return false; - } + if (fileName.size()>0 && fileSet.size()>0) + { + error(" can only have one of : file= and "); + return false; + } if (toFileName.size()>0 && toDirName.size()>0) { error(" can only have one of : tofile= or todir="); @@ -6167,16 +6314,16 @@ public: error("a task with a must have : todir="); return false; } - if (cptype == CP_TOFILE && fileName.size()==0) - { - error(" tofile= must be associated with : file="); - return false; - } - if (cptype == CP_TODIR && fileName.size()==0 && !haveFileSet) - { - error(" todir= must be associated with : file= or "); - return false; - } + if (cptype == CP_TOFILE && fileName.size()==0) + { + error(" tofile= must be associated with : file="); + return false; + } + if (cptype == CP_TODIR && fileName.size()==0 && !haveFileSet) + { + error(" todir= must be associated with : file= or "); + return false; + } return true; } @@ -6209,13 +6356,13 @@ public: TaskDelete(MakeBase &par) : Task(par) { - type = TASK_DELETE; - name = "delete"; - delType = DEL_FILE; + type = TASK_DELETE; + name = "delete"; + delType = DEL_FILE; verbose = false; quiet = false; failOnError = true; - } + } virtual ~TaskDelete() {} @@ -6271,7 +6418,12 @@ public: delType = DEL_DIR; if (fileName.size()>0 && dirName.size()>0) { - error(" can only have one attribute of file= or dir="); + error(" can have one attribute of file= or dir="); + return false; + } + if (fileName.size()==0 && dirName.size()==0) + { + error(" must have one attribute of file= or dir="); return false; } String ret; @@ -6360,12 +6512,12 @@ public: TaskLink(MakeBase &par) : Task(par) { - type = TASK_LINK; name = "link"; - command = "g++"; - doStrip = false; + type = TASK_LINK; name = "link"; + command = "g++"; + doStrip = false; stripCommand = "strip"; objcopyCommand = "objcopy"; - } + } virtual ~TaskLink() {} @@ -6388,8 +6540,8 @@ public: cmd.append(" "); String obj; if (fileSetDir.size()>0) - { - obj.append(fileSetDir); + { + obj.append(fileSetDir); obj.append("/"); } obj.append(fileSet[i]); @@ -6466,7 +6618,7 @@ public: return false; if (!parent.getAttribute(elem, "strip", s)) return false; - if (!getBool(s, doStrip)) + if (s.size()>0 && !getBool(s, doStrip)) return false; if (!parent.getAttribute(elem, "symfile", symFileName)) return false; @@ -6625,11 +6777,12 @@ public: TaskMsgFmt(MakeBase &par) : Task(par) { - type = TASK_MSGFMT; - name = "msgfmt"; - command = "msgfmt"; - owndir = false; - } + type = TASK_MSGFMT; + name = "msgfmt"; + command = "msgfmt"; + owndir = false; + outName = ""; + } virtual ~TaskMsgFmt() {} @@ -6647,18 +6800,18 @@ public: if (getSuffix(fileName) != "po") continue; String sourcePath; - if (fileSetDir.size()>0) - { - sourcePath.append(fileSetDir); + if (fileSetDir.size()>0) + { + sourcePath.append(fileSetDir); sourcePath.append("/"); } sourcePath.append(fileName); String fullSource = parent.resolve(sourcePath); String destPath; - if (toDirName.size()>0) - { - destPath.append(toDirName); + if (toDirName.size()>0) + { + destPath.append(toDirName); destPath.append("/"); } if (owndir) @@ -6670,8 +6823,17 @@ public: destPath.append(subdir); destPath.append("/"); } - destPath.append(fileName); - destPath[destPath.size()-2] = 'm'; + //Pick the output file name + if (outName.size() > 0) + { + destPath.append(outName); + } + else + { + destPath.append(fileName); + destPath[destPath.size()-2] = 'm'; + } + String fullDest = parent.resolve(destPath); if (!isNewerThan(fullSource, fullDest)) @@ -6716,9 +6878,11 @@ public: command = s; if (!parent.getAttribute(elem, "todir", toDirName)) return false; + if (!parent.getAttribute(elem, "out", outName)) + return false; if (!parent.getAttribute(elem, "owndir", s)) return false; - if (!getBool(s, owndir)) + if (s.size()>0 && !getBool(s, owndir)) return false; std::vector children = elem->getChildren(); @@ -6737,10 +6901,11 @@ public: private: - String command; - String toDirName; + String command; + String toDirName; + String outName; FileSet fileSet; - bool owndir; + bool owndir; }; @@ -6811,9 +6976,9 @@ public: TaskRC(MakeBase &par) : Task(par) { - type = TASK_RC; name = "rc"; - command = "windres"; - } + type = TASK_RC; name = "rc"; + command = "windres"; + } virtual ~TaskRC() {} @@ -6883,9 +7048,9 @@ public: TaskSharedLib(MakeBase &par) : Task(par) { - type = TASK_SHAREDLIB; name = "dll"; - command = "ar crv"; - } + type = TASK_SHAREDLIB; name = "dll"; + command = "dllwrap"; + } virtual ~TaskSharedLib() {} @@ -6905,9 +7070,9 @@ public: for (unsigned int i=0 ; i0) - { - fname.append(fileSetDir); + if (fileSetDir.size()>0) + { + fname.append(fileSetDir); fname.append("/"); } fname.append(fileSet[i]); @@ -6940,9 +7105,9 @@ public: for (unsigned int i=0 ; i0) - { - fname.append(fileSetDir); + if (fileSetDir.size()>0) + { + fname.append(fileSetDir); fname.append("/"); } fname.append(fileSet[i]); @@ -7005,6 +7170,7 @@ private: }; + /** * Run the "ar" command to archive .o's into a .a */ @@ -7014,9 +7180,9 @@ public: TaskStaticLib(MakeBase &par) : Task(par) { - type = TASK_STATICLIB; name = "staticlib"; - command = "ar crv"; - } + type = TASK_STATICLIB; name = "staticlib"; + command = "ar crv"; + } virtual ~TaskStaticLib() {} @@ -7036,9 +7202,9 @@ public: for (unsigned int i=0 ; i0) - { - fname.append(fileSetDir); + if (fileSetDir.size()>0) + { + fname.append(fileSetDir); fname.append("/"); } fname.append(fileSet[i]); @@ -7059,9 +7225,9 @@ public: for (unsigned int i=0 ; i0) - { - fname.append(fileSetDir); + if (fileSetDir.size()>0) + { + fname.append(fileSetDir); fname.append("/"); } fname.append(fileSet[i]); @@ -7081,6 +7247,7 @@ public: return true; } + virtual bool parse(Element *elem) { String s; @@ -7114,6 +7281,8 @@ private: }; + + /** * Strip an executable */ @@ -7179,6 +7348,62 @@ private: }; +/** + * + */ +class TaskTouch : public Task +{ +public: + + TaskTouch(MakeBase &par) : Task(par) + { type = TASK_TOUCH; name = "touch"; } + + virtual ~TaskTouch() + {} + + virtual bool execute() + { + String fullName = parent.resolve(fileName); + String nativeFile = getNativePath(fullName); + if (!isRegularFile(fullName) && !isDirectory(fullName)) + { + // S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH + int ret = creat(nativeFile.c_str(), 0666); + if (ret != 0) + { + error(" could not create '%s' : %s", + nativeFile.c_str(), strerror(ret)); + return false; + } + return true; + } + int ret = utime(nativeFile.c_str(), (struct utimbuf *)0); + if (ret != 0) + { + error(" could not update the modification time for '%s' : %s", + nativeFile.c_str(), strerror(ret)); + return false; + } + return true; + } + + virtual bool parse(Element *elem) + { + //trace("touch parse"); + if (!parent.getAttribute(elem, "file", fileName)) + return false; + if (fileName.size() == 0) + { + error(" requires 'file=\"fileName\"' attribute"); + return false; + } + return true; + } + + String fileName; +}; + + /** * */ @@ -7209,7 +7434,7 @@ public: /** * */ -Task *Task::createTask(Element *elem) +Task *Task::createTask(Element *elem, int lineNr) { String tagName = elem->getName(); //trace("task:%s", tagName.c_str()); @@ -7242,6 +7467,8 @@ Task *Task::createTask(Element *elem) task = new TaskStaticLib(parent); else if (tagName == "strip") task = new TaskStrip(parent); + else if (tagName == "touch") + task = new TaskTouch(parent); else if (tagName == "tstamp") task = new TaskTstamp(parent); else @@ -7250,6 +7477,8 @@ Task *Task::createTask(Element *elem) return NULL; } + task->setLine(lineNr); + if (!task->parse(elem)) { delete task; @@ -7474,13 +7703,13 @@ public: * */ virtual String version() - { return "BuildTool v0.6, 2006 Bob Jamison"; } + { return BUILDTOOL_VERSION; } /** * Overload a */ virtual bool specifyProperty(const String &name, - const String &value); + const String &value); /** * @@ -7521,7 +7750,7 @@ private: * */ bool executeTarget(Target &target, - std::set &targetsCompleted); + std::set &targetsCompleted); /** @@ -7539,18 +7768,13 @@ private: * */ bool parsePropertyFile(const String &fileName, - const String &prefix); + const String &prefix); /** * */ bool parseProperty(Element *elem); - /** - * - */ - bool parseTask(Task &task, Element *elem); - /** * */ @@ -7745,11 +7969,11 @@ bool Make::execute() } std::map::iterator iter = - targets.find(currentTarget); + targets.find(currentTarget); if (iter == targets.end()) { error("Initial target '%s' not found", - currentTarget.c_str()); + currentTarget.c_str()); return false; } @@ -7868,51 +8092,52 @@ bool Make::parsePropertyFile(const String &fileName, if (p2 <= p) { error("property file %s, line %d: expected keyword", - fileName.c_str(), linenr); - return false; - } - if (prefix.size() > 0) - { - key.insert(0, prefix); - } + fileName.c_str(), linenr); + return false; + } + if (prefix.size() > 0) + { + key.insert(0, prefix); + } //skip whitespace - for (p=p2 ; p=len || s[p]!='=') { error("property file %s, line %d: expected '='", - fileName.c_str(), linenr); + fileName.c_str(), linenr); return false; } p++; //skip whitespace - for ( ; p=len) + if (p>=len) { error("property file %s, line %d: expected value", - fileName.c_str(), linenr); - return false; - } + fileName.c_str(), linenr); + return false; + } val = s.substr(p); - if (key.size()==0 || val.size()==0) - continue; + if (key.size()==0) + continue; + //allow property to be set, even if val="" //trace("key:'%s' val:'%s'", key.c_str(), val.c_str()); //See if we wanted to overload this property @@ -7924,7 +8149,7 @@ bool Make::parsePropertyFile(const String &fileName, status("overloading property '%s' = '%s'", key.c_str(), val.c_str()); } - properties[key] = val; + properties[key] = val; } fclose(f); return true; @@ -7947,8 +8172,8 @@ bool Make::parseProperty(Element *elem) if (attrName == "name") { String val; - if (!getAttribute(elem, "value", val)) - return false; + if (!getAttribute(elem, "value", val)) + return false; if (val.size() > 0) { properties[attrVal] = val; @@ -7957,10 +8182,8 @@ bool Make::parseProperty(Element *elem) { if (!getAttribute(elem, "location", val)) return false; - if (val.size() > 0) - { - properties[attrVal] = val; - } + //let the property exist, even if not defined + properties[attrVal] = val; } //See if we wanted to overload this property std::map::iterator iter = @@ -7976,8 +8199,8 @@ bool Make::parseProperty(Element *elem) else if (attrName == "file") { String prefix; - if (!getAttribute(elem, "prefix", prefix)) - return false; + if (!getAttribute(elem, "prefix", prefix)) + return false; if (prefix.size() > 0) { if (prefix[prefix.size()-1] != '.') @@ -8010,14 +8233,18 @@ bool Make::parseFile() { status("######## PARSE : %s", uri.getPath().c_str()); + setLine(0); + Parser parser; Element *root = parser.parseFile(uri.getNativePath()); if (!root) { error("Could not open %s for reading", - uri.getNativePath().c_str()); + uri.getNativePath().c_str()); return false; } + + setLine(root->getLine()); if (root->getChildren().size()==0 || root->getChildren()[0]->getName()!="project") @@ -8044,6 +8271,7 @@ bool Make::parseFile() for (unsigned int i=0 ; igetLine()); String tagName = elem->getName(); //########## DESCRIPTION @@ -8078,7 +8306,7 @@ bool Make::parseFile() { Element *telem = telems[i]; Task breeder(*this); - Task *task = breeder.createTask(telem); + Task *task = breeder.createTask(telem, telem->getLine()); if (!task) return false; allTasks.push_back(task); @@ -8100,6 +8328,12 @@ bool Make::parseFile() //more work than targets[tname]=target, but avoids default allocator targets.insert(std::make_pair(tname, target)); } + //######### none of the above + else + { + error("unknown toplevel tag: <%s>", tagName.c_str()); + return false; + } } @@ -8152,6 +8386,36 @@ bool Make::run() } + + +/** + * Get a formatted MM:SS.sss time elapsed string + */ +static String +timeDiffString(struct timeval &x, struct timeval &y) +{ + long microsX = x.tv_usec; + long secondsX = x.tv_sec; + long microsY = y.tv_usec; + long secondsY = y.tv_sec; + if (microsX < microsY) + { + microsX += 1000000; + secondsX -= 1; + } + + int seconds = (int)(secondsX - secondsY); + int millis = (int)((microsX - microsY)/1000); + + int minutes = seconds/60; + seconds -= minutes*60; + char buf[80]; + snprintf(buf, 79, "%dm %d.%03ds", minutes, seconds, millis); + String ret = buf; + return ret; + +} + /** * */ @@ -8160,11 +8424,15 @@ bool Make::run(const String &target) status("####################################################"); status("# %s", version().c_str()); status("####################################################"); + struct timeval timeStart, timeEnd; + ::gettimeofday(&timeStart, NULL); specifiedTarget = target; if (!run()) return false; + ::gettimeofday(&timeEnd, NULL); + String timeStr = timeDiffString(timeEnd, timeStart); status("####################################################"); - status("# BuildTool Completed "); + status("# BuildTool Completed : %s", timeStr.c_str()); status("####################################################"); return true; } @@ -8359,9 +8627,9 @@ static bool depTest() deptool.setSourceDirectory("/dev/ink/inkscape/src"); if (!deptool.generateDependencies("build.dep")) return false; - std::vector res = - deptool.loadDepFile("build.dep"); - if (res.size() == 0) + std::vector res = + deptool.loadDepFile("build.dep"); + if (res.size() == 0) return false; return true; } @@ -8370,7 +8638,7 @@ static bool popenTest() { buildtool::Make make; buildtool::String out, err; - bool ret = make.executeCommand("gcc xx.cpp", "", out, err); + bool ret = make.executeCommand("gcc xx.cpp", "", out, err); printf("Popen test:%d '%s' '%s'\n", ret, out.c_str(), err.c_str()); return true; }