X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=buildtool.cpp;h=39ae5be6ef87214665a371ed77809106453d419a;hb=0e2a2cc7bb4f35dbc5150de387b2e651714b6d5b;hp=8d05b6bcdb26b30d980fbc2d67b17dace23f750d;hpb=21c39849d91886d1350954e5abee660df2e5a667;p=inkscape.git diff --git a/buildtool.cpp b/buildtool.cpp index 8d05b6bcd..39ae5be6e 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 @@ -24,22 +24,30 @@ /** * To use this file, compile with: *
- * g++ -O3 buildtool.cpp -o build.exe
+ * g++ -O3 buildtool.cpp -o btool.exe
  * (or whatever your compiler might be) 
  * Then
- * build
+ * btool
  * or 
- * build {target}
+ * btool {target}
+ * 
+ * Note: if you are using MinGW, and a not very recent version of it,
+ * gettimeofday() might be missing.  If so, just build this file with
+ * this command:
+ * g++ -O3 -DNEED_GETTIMEOFDAY buildtool.cpp -o btool.exe
+ *     
  */  
 
-
+#define BUILDTOOL_VERSION  "BuildTool v0.6.13, 2007 Bob Jamison"
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -52,12 +60,52 @@
 #endif
 
 
+#include 
+
+
+//########################################################################
+//# Definition of gettimeofday() for those who don't have it
+//########################################################################
+#ifdef NEED_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
 {
 
 
 
+
 //########################################################################
 //########################################################################
 //##  R E G E X P
@@ -76,29 +124,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.
 
 ****************************************************************/
 
@@ -127,8 +175,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);
@@ -173,26 +221,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 ('+')
@@ -207,589 +255,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;
 }
 
 
@@ -914,18 +962,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;
         }
@@ -993,9 +1041,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;
@@ -1004,6 +1061,7 @@ protected:
         namespaces = other.namespaces;
         name       = other.name;
         value      = other.value;
+        line       = other.line;
         }
 
     void findElementsRecursive(std::vector&res, const String &name);
@@ -1019,7 +1077,8 @@ protected:
 
     String name;
     String value;
-
+    
+    int line;
 };
 
 
@@ -1087,15 +1146,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);
 
@@ -1111,12 +1172,10 @@ private:
 
     bool       keepGoing;
     Element    *currentNode;
-    long       parselen;
+    int        parselen;
     XMLCh      *parsebuf;
-    String  cdatabuf;
-    long       currentPosition;
-    int        colNr;
-
+    String     cdatabuf;
+    int        currentPosition;
 };
 
 
@@ -1132,6 +1191,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++)
@@ -1310,10 +1370,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;
@@ -1382,7 +1456,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)
@@ -1396,7 +1470,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);
 
@@ -1671,7 +1751,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)
                 {
                 /*
@@ -1763,7 +1843,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;
 }
 
@@ -1830,8 +1910,6 @@ Element *Parser::parseFile(const String &fileName)
     return n;
 }
 
-
-
 //########################################################################
 //########################################################################
 //##  E N D    X M L
@@ -1839,6 +1917,10 @@ Element *Parser::parseFile(const String &fileName)
 //########################################################################
 
 
+
+
+
+
 //########################################################################
 //########################################################################
 //##  U R I
@@ -2284,6 +2366,7 @@ URI URI::resolve(const URI &other) const
 }
 
 
+
 /**
  *  This follows the Java URI algorithm:
  *   1. All "." segments are removed.
@@ -2402,6 +2485,7 @@ void URI::trace(const char *fmt, ...)
 
 
 
+
 //#########################################################################
 //# P A R S I N G
 //#########################################################################
@@ -2789,13 +2873,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; }
@@ -2820,11 +2905,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;
 
@@ -2859,7 +2956,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
@@ -2885,30 +2982,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);
 
     /**
@@ -2916,8 +3013,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
@@ -2925,7 +3022,7 @@ protected:
      */  
     bool parseFileSet(Element *elem,
                     MakeBase &propRef,
-					FileSet &fileSet);
+                    FileSet &fileSet);
 
     /**
      * Return this object's property list
@@ -2951,13 +3048,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);
 
     /**
@@ -2989,9 +3086,10 @@ private:
 
     /**
      * replace variable refs like ${a} with their values
-     */	     
+     */         
     bool getSubstitutions(const String &s, String &result);
 
+    int line;
 
 
 };
@@ -3006,7 +3104,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) ;
@@ -3061,30 +3159,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;
 }
@@ -3194,16 +3292,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 subdirs;
     DIR *dir = opendir(dirNative.c_str());
+    if (!dir)
+        {
+        error("Could not open directory %s : %s",
+              dirNative.c_str(), strerror(errno));
+        return false;
+        }
     while (true)
         {
         struct dirent *de = readdir(dir);
@@ -3629,7 +3745,7 @@ bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet)
     String baseDir = propRef.resolve(fileSet.getDirectory());
     std::vector fileList;
     if (!listFiles(baseDir, "", fileList))
-	    return false;
+        return false;
 
     std::vector includes = fileSet.getIncludes();
     std::vector excludes = fileSet.getExcludes();
@@ -3642,9 +3758,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;
@@ -3682,9 +3798,9 @@ bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet)
             res.push_back(s);
         }
         
-	fileSet.setFiles(res);
+    fileSet.setFiles(res);
 
-	return true;
+    return true;
 }
 
 
@@ -3700,44 +3816,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;
@@ -3762,7 +3878,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")
@@ -3785,9 +3901,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")
@@ -3872,19 +3988,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;
 }
@@ -4654,23 +4775,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; }
 
 
     /**
@@ -4792,7 +4913,7 @@ private:
         path     = other.path;
         name     = other.name;
         suffix   = other.suffix;
-        files    = other.files;
+        files    = other.files; //avoid recursion
         }
 
 };
@@ -4806,19 +4927,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; }
 
 
     /**
@@ -4939,9 +5060,7 @@ private:
     /**
      *
      */
-    bool processDependency(FileRec *ofile,
-                           FileRec *include,
-                           int depth);
+    bool processDependency(FileRec *ofile, FileRec *include);
 
     /**
      *
@@ -4960,8 +5079,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;
 
@@ -4969,7 +5087,7 @@ private:
      * The list of .o files, and the
      * dependencies upon them.
      */
-    std::map depFiles;
+    std::map oFiles;
 
     int depFileSize;
     char *depFileBuf;
@@ -4994,13 +5112,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(); 
 
 }
@@ -5060,7 +5180,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;
@@ -5165,7 +5285,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
@@ -5178,6 +5299,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() ;
@@ -5186,12 +5308,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;
                 }
             }
@@ -5298,9 +5425,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++)
@@ -5314,7 +5439,7 @@ bool DepTool::processDependency(FileRec *ofile,
         FileRec *child  = iter->second;
         ofile->files[fname] = child;
       
-        processDependency(ofile, child, depth+1);
+        processDependency(ofile, child);
         }
 
 
@@ -5347,23 +5472,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);
             }
         }
 
@@ -5411,13 +5536,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++)
                 {
@@ -5462,7 +5587,7 @@ std::vector DepTool::loadDepFile(const String &depFile)
     if (root->getChildren().size()==0 ||
         root->getChildren()[0]->getName()!="dependencies")
         {
-        error("Main xml element should be ");
+        error("loadDepFile: main xml element should be ");
         delete root;
         return result;
         }
@@ -5475,47 +5600,53 @@ std::vector DepTool::loadDepFile(const String &depFile)
         {
         Element *objectElem = objects[i];
         String tagName = objectElem->getName();
-        if (tagName == "object")
-            {
-            String objName   = objectElem->getAttribute("name");
-             //trace("object:%s", objName.c_str());
-            DepRec depObject(objName);
-            depObject.path   = objectElem->getAttribute("path");
-            depObject.suffix = objectElem->getAttribute("suffix");
-            //########## DESCRIPTION
-            std::vector depElems = objectElem->getChildren();
-            for (unsigned int i=0 ; i should have only  children");
+            return result;
+            }
+
+        String objName   = objectElem->getAttribute("name");
+         //trace("object:%s", objName.c_str());
+        DepRec depObject(objName);
+        depObject.path   = objectElem->getAttribute("path");
+        depObject.suffix = objectElem->getAttribute("suffix");
+        //########## DESCRIPTION
+        std::vector depElems = objectElem->getChildren();
+        for (unsigned int i=0 ; igetName();
+            if (tagName != "dep")
                 {
-                Element *depElem = depElems[i];
-                tagName = depElem->getName();
-                if (tagName == "dep")
-                    {
-                    String depName = depElem->getAttribute("name");
-                    //trace("    dep:%s", depName.c_str());
-                    depObject.files.push_back(depName);
-                    }
+                error("loadDepFile:  should have only  children");
+                return result;
                 }
-            //Insert into the result list, in a sorted manner
-            bool inserted = false;
-            std::vector::iterator iter;
-            for (iter = result.begin() ; iter != result.end() ; iter++)
+            String depName = depElem->getAttribute("name");
+            //trace("    dep:%s", depName.c_str());
+            depObject.files.push_back(depName);
+            }
+
+        //Insert into the result list, in a sorted manner
+        bool inserted = false;
+        std::vector::iterator iter;
+        for (iter = result.begin() ; iter != result.end() ; iter++)
+            {
+            String vpath = iter->path;
+            vpath.append("/");
+            vpath.append(iter->name);
+            String opath = depObject.path;
+            opath.append("/");
+            opath.append(depObject.name);
+            if (vpath > opath)
                 {
-                String vpath = iter->path;
-                vpath.append("/");
-                vpath.append(iter->name);
-                String opath = depObject.path;
-                opath.append("/");
-                opath.append(depObject.name);
-                if (vpath > opath)
-                    {
-                    inserted = true;
-                    iter = result.insert(iter, depObject);
-                    break;
-                    }
+                inserted = true;
+                iter = result.insert(iter, depObject);
+                break;
                 }
-            if (!inserted)
-                result.push_back(depObject);
             }
+        if (!inserted)
+            result.push_back(depObject);
         }
 
     delete root;
@@ -5585,6 +5716,7 @@ public:
         TASK_SHAREDLIB,
         TASK_STATICLIB,
         TASK_STRIP,
+        TASK_TOUCH,
         TASK_TSTAMP
         } TaskType;
         
@@ -5653,7 +5785,7 @@ public:
     /**
      *
      */
-    Task *createTask(Element *elem);
+    Task *createTask(Element *elem, int lineNr);
 
 
 protected:
@@ -5696,21 +5828,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;
@@ -5720,6 +5852,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");
@@ -5779,45 +5914,46 @@ public:
             //## Select command
             String sfx = dep.suffix;
             String command = ccCommand;
-            if (sfx == "cpp" || sfx == "c++" || sfx == "cc"
-			     || sfx == "CC")
-			    command = cxxCommand;
+            if (sfx == "cpp" || sfx == "cxx" || sfx == "c++" ||
+                 sfx == "cc" || 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;
+            //# First we check if the source is newer than the .o
             if (isNewerThan(srcFullName, destFullName))
                 {
                 status("          : compile of %s required by %s",
@@ -5826,17 +5962,22 @@ public:
                 }
             else
                 {
+                //# secondly, we check if any of the included dependencies
+                //# of the .c/.cpp is newer than the .o
                 for (unsigned int i=0 ; i0)
+                    if (source.size()>0)
                         {
-                        depName.append(srcPath);
+                        depName.append(source);
                         depName.append("/");
                         }
                     depName.append(dep.files[i]);
                     String depFullName = parent.resolve(depName);
-                    if (isNewerThan(depFullName, destFullName))
+                    bool depRequires = isNewerThan(depFullName, destFullName);
+                    //trace("%d %s %s\n", depRequires,
+                    //        destFullName.c_str(), depFullName.c_str());
+                    if (depRequires)
                         {
                         status("          : compile of %s required by %s",
                                 destFullName.c_str(), depFullName.c_str());
@@ -5854,23 +5995,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;
@@ -5957,11 +6135,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()
         {}
@@ -5979,14 +6157,15 @@ 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))
                        {
+                       status("          : skipped");
                        return true;
                        }
                    if (!copyFile(fullSource, fullDest))
@@ -6024,11 +6203,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)
                            {
@@ -6044,7 +6223,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());
@@ -6076,14 +6255,15 @@ 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))
                        {
+                       status("          : skipped");
                        return true;
                        }
                    if (!copyFile(fullSource, fullDest))
@@ -6127,18 +6307,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=");
@@ -6149,16 +6329,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;
         }
@@ -6191,13 +6371,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()
         {}
@@ -6253,7 +6433,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;
@@ -6342,9 +6527,12 @@ public:
 
     TaskLink(MakeBase &par) : Task(par)
         {
-		type = TASK_LINK; name = "link";
-		command = "g++";
-		}
+        type = TASK_LINK; name = "link";
+        command = "g++";
+        doStrip = false;
+                stripCommand = "strip";
+                objcopyCommand = "objcopy";
+        }
 
     virtual ~TaskLink()
         {}
@@ -6367,13 +6555,14 @@ public:
             cmd.append(" ");
             String obj;
             if (fileSetDir.size()>0)
-			    {
-				obj.append(fileSetDir);
+                {
+                obj.append(fileSetDir);
                 obj.append("/");
                 }
             obj.append(fileSet[i]);
             String fullObj = parent.resolve(obj);
-            cmd.append(fullObj);
+            String nativeFullObj = getNativePath(fullObj);
+            cmd.append(nativeFullObj);
             //trace("link: tgt:%s obj:%s", fullTarget.c_str(),
             //          fullObj.c_str());
             if (isNewerThan(fullObj, fullTarget))
@@ -6389,12 +6578,40 @@ public:
         //trace("LINK cmd:%s", cmd.c_str());
 
 
-        String outString, errString;
-        if (!executeCommand(cmd.c_str(), "", outString, errString))
+        String outbuf, errbuf;
+        if (!executeCommand(cmd.c_str(), "", outbuf, errbuf))
             {
-            error("LINK problem: %s", errString.c_str());
+            error("LINK problem: %s", errbuf.c_str());
             return false;
             }
+
+        if (symFileName.size()>0)
+            {
+            String symFullName = parent.resolve(symFileName);
+            cmd = objcopyCommand;
+            cmd.append(" --only-keep-debug ");
+            cmd.append(getNativePath(fullTarget));
+            cmd.append(" ");
+            cmd.append(getNativePath(symFullName));
+            if (!executeCommand(cmd, "", outbuf, errbuf))
+                {
+                error(" symbol file failed : %s", errbuf.c_str());
+                return false;
+                }
+            }
+            
+        if (doStrip)
+            {
+            cmd = stripCommand;
+            cmd.append(" ");
+            cmd.append(getNativePath(fullTarget));
+            if (!executeCommand(cmd, "", outbuf, errbuf))
+               {
+               error(" failed : %s", errbuf.c_str());
+               return false;
+               }
+            }
+
         return true;
         }
 
@@ -6405,8 +6622,22 @@ public:
             return false;
         if (s.size()>0)
             command = s;
+        if (!parent.getAttribute(elem, "objcopycommand", s))
+            return false;
+        if (s.size()>0)
+            objcopyCommand = s;
+        if (!parent.getAttribute(elem, "stripcommand", s))
+            return false;
+        if (s.size()>0)
+            stripCommand = s;
         if (!parent.getAttribute(elem, "out", fileName))
             return false;
+        if (!parent.getAttribute(elem, "strip", s))
+            return false;
+        if (s.size()>0 && !getBool(s, doStrip))
+            return false;
+        if (!parent.getAttribute(elem, "symfile", symFileName))
+            return false;
             
         std::vector children = elem->getChildren();
         for (unsigned int i=0 ; i0)
-			    {
-			    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)
@@ -6603,8 +6839,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))
@@ -6642,12 +6887,18 @@ public:
 
     virtual bool parse(Element *elem)
         {
+        String s;
+        if (!parent.getAttribute(elem, "command", s))
+            return false;
+        if (s.size()>0)
+            command = s;
         if (!parent.getAttribute(elem, "todir", toDirName))
             return false;
-        String s;
+        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();
@@ -6666,10 +6917,11 @@ public:
 
 private:
 
-    String command;
-    String toDirName;
+    String  command;
+    String  toDirName;
+    String  outName;
     FileSet fileSet;
-    bool owndir;
+    bool    owndir;
 
 };
 
@@ -6685,7 +6937,10 @@ class TaskRanlib : public Task
 public:
 
     TaskRanlib(MakeBase &par) : Task(par)
-        { type = TASK_RANLIB; name = "ranlib"; }
+        {
+        type = TASK_RANLIB; name = "ranlib";
+        command = "ranlib";
+        }
 
     virtual ~TaskRanlib()
         {}
@@ -6694,7 +6949,8 @@ public:
         {
         String fullName = parent.resolve(fileName);
         //trace("fullDir:%s", fullDir.c_str());
-        String cmd = "ranlib ";
+        String cmd = command;
+        cmd.append(" ");
         cmd.append(fullName);
         String outbuf, errbuf;
         if (!executeCommand(cmd, "", outbuf, errbuf))
@@ -6704,6 +6960,11 @@ public:
 
     virtual bool parse(Element *elem)
         {
+        String s;
+        if (!parent.getAttribute(elem, "command", s))
+            return false;
+        if (s.size()>0)
+           command = s;
         if (!parent.getAttribute(elem, "file", fileName))
             return false;
         if (fileName.size() == 0)
@@ -6717,6 +6978,7 @@ public:
 private:
 
     String fileName;
+    String command;
 };
 
 
@@ -6730,9 +6992,9 @@ public:
 
     TaskRC(MakeBase &par) : Task(par)
         {
-		type = TASK_RC; name = "rc";
-		command = "windres -o";
-		}
+        type = TASK_RC; name = "rc";
+        command = "windres";
+        }
 
     virtual ~TaskRC()
         {}
@@ -6744,7 +7006,7 @@ public:
         if (!isNewerThan(fullFile, fullOut))
             return true;
         String cmd = command;
-        cmd.append(" ");
+        cmd.append(" -o ");
         cmd.append(fullOut);
         cmd.append(" ");
         cmd.append(flags);
@@ -6802,9 +7064,9 @@ public:
 
     TaskSharedLib(MakeBase &par) : Task(par)
         {
-		type = TASK_SHAREDLIB; name = "dll";
-		command = "ar crv";
-		}
+        type = TASK_SHAREDLIB; name = "dll";
+        command = "dllwrap";
+        }
 
     virtual ~TaskSharedLib()
         {}
@@ -6824,9 +7086,9 @@ public:
         for (unsigned int i=0 ; i0)
-			    {
-			    fname.append(fileSetDir);
+            if (fileSetDir.size()>0)
+                {
+                fname.append(fileSetDir);
                 fname.append("/");
                 }
             fname.append(fileSet[i]);
@@ -6859,9 +7121,9 @@ public:
         for (unsigned int i=0 ; i0)
-			    {
-			    fname.append(fileSetDir);
+            if (fileSetDir.size()>0)
+                {
+                fname.append(fileSetDir);
                 fname.append("/");
                 }
             fname.append(fileSet[i]);
@@ -6924,6 +7186,7 @@ private:
 };
 
 
+
 /**
  * Run the "ar" command to archive .o's into a .a
  */
@@ -6933,9 +7196,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()
         {}
@@ -6955,9 +7218,9 @@ public:
         for (unsigned int i=0 ; i0)
-			    {
-			    fname.append(fileSetDir);
+            if (fileSetDir.size()>0)
+                {
+                fname.append(fileSetDir);
                 fname.append("/");
                 }
             fname.append(fileSet[i]);
@@ -6978,9 +7241,9 @@ public:
         for (unsigned int i=0 ; i0)
-			    {
-			    fname.append(fileSetDir);
+            if (fileSetDir.size()>0)
+                {
+                fname.append(fileSetDir);
                 fname.append("/");
                 }
             fname.append(fileSet[i]);
@@ -7000,8 +7263,14 @@ public:
         return true;
         }
 
+
     virtual bool parse(Element *elem)
         {
+        String s;
+        if (!parent.getAttribute(elem, "command", s))
+            return false;
+        if (s.size()>0)
+            command = s;
         if (!parent.getAttribute(elem, "file", fileName))
             return false;
             
@@ -7028,6 +7297,8 @@ private:
 };
 
 
+
+
 /**
  * Strip an executable
  */
@@ -7045,12 +7316,30 @@ public:
         {
         String fullName = parent.resolve(fileName);
         //trace("fullDir:%s", fullDir.c_str());
-        String cmd = "strip ";
-        cmd.append(fullName);
-
+        String cmd;
         String outbuf, errbuf;
+
+        if (symFileName.size()>0)
+            {
+            String symFullName = parent.resolve(symFileName);
+            cmd = "objcopy --only-keep-debug ";
+            cmd.append(getNativePath(fullName));
+            cmd.append(" ");
+            cmd.append(getNativePath(symFullName));
+            if (!executeCommand(cmd, "", outbuf, errbuf))
+                {
+                error(" symbol file failed : %s", errbuf.c_str());
+                return false;
+                }
+            }
+            
+        cmd = "strip ";
+        cmd.append(getNativePath(fullName));
         if (!executeCommand(cmd, "", outbuf, errbuf))
+            {
+            error(" failed : %s", errbuf.c_str());
             return false;
+            }
         return true;
         }
 
@@ -7058,9 +7347,11 @@ public:
         {
         if (!parent.getAttribute(elem, "file", fileName))
             return false;
+        if (!parent.getAttribute(elem, "symfile", symFileName))
+            return false;
         if (fileName.size() == 0)
             {
-            error(" requires 'file=\"fileNname\"' attribute");
+            error(" requires 'file=\"fileName\"' attribute");
             return false;
             }
         return true;
@@ -7069,6 +7360,63 @@ public:
 private:
 
     String fileName;
+    String symFileName;
+};
+
+
+/**
+ *
+ */
+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;
 };
 
 
@@ -7102,7 +7450,7 @@ public:
 /**
  *
  */
-Task *Task::createTask(Element *elem)
+Task *Task::createTask(Element *elem, int lineNr)
 {
     String tagName = elem->getName();
     //trace("task:%s", tagName.c_str());
@@ -7135,6 +7483,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
@@ -7143,6 +7493,8 @@ Task *Task::createTask(Element *elem)
         return NULL;
         }
 
+    task->setLine(lineNr);
+
     if (!task->parse(elem))
         {
         delete task;
@@ -7367,13 +7719,13 @@ public:
      *
      */
     virtual String version()
-        { return "BuildTool v0.3, 2006 Bob Jamison"; }
+        { return BUILDTOOL_VERSION; }
 
     /**
      * Overload a 
      */
     virtual bool specifyProperty(const String &name,
-	                             const String &value);
+                                 const String &value);
 
     /**
      *
@@ -7414,7 +7766,7 @@ private:
      *
      */
     bool executeTarget(Target &target,
-	         std::set &targetsCompleted);
+             std::set &targetsCompleted);
 
 
     /**
@@ -7432,18 +7784,13 @@ private:
      *
      */
     bool parsePropertyFile(const String &fileName,
-	                       const String &prefix);
+                           const String &prefix);
 
     /**
      *
      */
     bool parseProperty(Element *elem);
 
-    /**
-     *
-     */
-    bool parseTask(Task &task, Element *elem);
-
     /**
      *
      */
@@ -7638,11 +7985,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;
         }
         
@@ -7761,51 +8108,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
@@ -7817,7 +8165,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;
@@ -7840,8 +8188,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;
@@ -7850,10 +8198,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 =
@@ -7869,8 +8215,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] != '.')
@@ -7903,14 +8249,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")
@@ -7937,6 +8287,7 @@ bool Make::parseFile()
     for (unsigned int i=0 ; igetLine());
         String tagName = elem->getName();
 
         //########## DESCRIPTION
@@ -7971,7 +8322,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);
@@ -7993,6 +8344,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;
+            }
 
         }
 
@@ -8045,22 +8402,54 @@ 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;
+    
+}
+
 /**
  *
  */
 bool Make::run(const String &target)
 {
-    status("##################################");
-    status("#   BuildTool");
-    status("#   version 0.5");
-    status("#   21 Nov 06");
-    status("##################################");
+    status("####################################################");
+    status("#   %s", version().c_str());
+    status("####################################################");
+    struct timeval timeStart, timeEnd;
+    ::gettimeofday(&timeStart, NULL);
     specifiedTarget = target;
     if (!run())
         return false;
-    status("##################################");
-    status("#   BuildTool Completed");
-    status("##################################");
+    ::gettimeofday(&timeEnd, NULL);
+    String timeStr = timeDiffString(timeEnd, timeStart);
+    status("####################################################");
+    status("#   BuildTool Completed : %s", timeStr.c_str());
+    status("####################################################");
     return true;
 }
 
@@ -8254,9 +8643,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;
 }
@@ -8265,7 +8654,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;
 }