Code

Added regex. Greatly improved <fileset> scanning.
authorishmal <ishmal@users.sourceforge.net>
Sat, 18 Nov 2006 00:54:53 +0000 (00:54 +0000)
committerishmal <ishmal@users.sourceforge.net>
Sat, 18 Nov 2006 00:54:53 +0000 (00:54 +0000)
build.xml
buildtool.cpp

index 79b3bf42cb436fca525a490badb34d6b0ce052a0..76ab1f66d83fda9a4d1260940a781e398e368885 100644 (file)
--- a/build.xml
+++ b/build.xml
     <link command="g++" out="${build}/inkscape.exe">
        <flags>
        </flags>
-          <fileset>
-              <include name="${build}/inkres.o"/>
-              <include name="${build}/obj/main.o"/>
-              <include name="${build}/obj/winmain.o"/>
-              <include name="${build}/libinkscape.a"/>
+          <fileset dir="${build}">
+              <include name="inkres.o"/>
+              <include name="obj/main.o"/>
+              <include name="obj/winmain.o"/>
+              <include name="libinkscape.a"/>
           </fileset>
           <libs>
               -L${gtk}/lib
     <copy file="${gtk}/bin/intl.dll" tofile="${dist}/libintl-2.dll"/>
 
     <!-- MSGFMT files -->
-    <copy todir="${dist}"> <fileset dir="${build}/po"/> </copy>
+    <copy todir="${dist}">
+           <fileset dir="${build}/po">
+                 <exclude name=".*\.am"/>
+               </fileset>
+       </copy>
 
     <!-- GTK -->
     <copy todir="${dist}"> <fileset dir="${gtk}/etc"/> </copy>
     <copy todir="${dist}/lib"> <fileset dir="${gtk}/lib/glib-2.0"/> </copy>
     <copy todir="${dist}/lib"> <fileset dir="${gtk}/lib/locale"/> </copy>
     <copy todir="${dist}/lib"> <fileset dir="${gtk}/lib/pango"/> </copy>
-    <copy todir="${dist}"> <fileset dir="share"/> </copy>
+    <copy todir="${dist}">
+           <fileset dir="share">
+                 <exclude name=".*\.am"/>
+               </fileset>
+       </copy>
     <copy todir="${dist}/share"> <fileset dir="${gtk}/share/themes"/> </copy>
     <mkdir dir="${dist}/data"/>
     <mkdir dir="${dist}/locale"/>
index e3efeff5eb4270a3714547768f3069825a85b30a..97c5a179d2d3f3631b7c803c31b02f31bf80d6c8 100644 (file)
@@ -58,6 +58,748 @@ namespace buildtool
 
 
 
+//########################################################################
+//########################################################################
+//##  R E G E X P
+//########################################################################
+//########################################################################
+
+/**
+ * This is the T-Rex regular expression library, which we
+ * gratefully acknowledge.  It's clean code and small size allow
+ * us to embed it in BuildTool without adding a dependency
+ *
+ */    
+
+//begin trex.h
+
+#ifndef _TREX_H_
+#define _TREX_H_
+/***************************************************************
+       T-Rex a tiny regular expression library
+
+       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.
+
+       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.
+
+               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.
+
+****************************************************************/
+
+#ifdef _UNICODE
+#define TRexChar unsigned short
+#define MAX_CHAR 0xFFFF
+#define _TREXC(c) L##c 
+#define trex_strlen wcslen
+#define trex_printf wprintf
+#else
+#define TRexChar char
+#define MAX_CHAR 0xFF
+#define _TREXC(c) (c) 
+#define trex_strlen strlen
+#define trex_printf printf
+#endif
+
+#ifndef TREX_API
+#define TREX_API extern
+#endif
+
+#define TRex_True 1
+#define TRex_False 0
+
+typedef unsigned int TRexBool;
+typedef struct TRex TRex;
+
+typedef struct {
+       const TRexChar *begin;
+       int len;
+} TRexMatch;
+
+TREX_API TRex *trex_compile(const TRexChar *pattern,const TRexChar **error);
+TREX_API void trex_free(TRex *exp);
+TREX_API TRexBool trex_match(TRex* exp,const TRexChar* text);
+TREX_API TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end);
+TREX_API TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end);
+TREX_API int trex_getsubexpcount(TRex* exp);
+TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
+
+#endif
+
+//end trex.h
+
+//start trex.c
+
+
+#include <stdio.h>
+#include <string>
+
+/* see copyright notice in trex.h */
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <setjmp.h>
+//#include "trex.h"
+
+#ifdef _UINCODE
+#define scisprint iswprint
+#define scstrlen wcslen
+#define scprintf wprintf
+#define _SC(x) L(x)
+#else
+#define scisprint isprint
+#define scstrlen strlen
+#define scprintf printf
+#define _SC(x) (x)
+#endif
+
+#ifdef _DEBUG
+#include <stdio.h>
+
+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")
+};
+
+#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 TREX_SYMBOL_ANY_CHAR ('.')
+#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
+#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
+#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
+#define TREX_SYMBOL_BRANCH ('|')
+#define TREX_SYMBOL_END_OF_STRING ('$')
+#define TREX_SYMBOL_BEGINNING_OF_STRING ('^')
+#define TREX_SYMBOL_ESCAPE_CHAR ('\\')
+
+
+typedef int TRexNodeType;
+
+typedef struct tagTRexNode{
+       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;
+};
+
+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;
+}
+
+static void trex_error(TRex *exp,const TRexChar *error)
+{
+       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++;
+}
+
+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++);
+}
+
+static int trex_charclass(TRex *exp,int classid)
+{
+       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);
+}
+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;
+            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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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*/
+}
+
+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;
+}
+
+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;
+}
+
+/* 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"));
+#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"));
+               }
+#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;
+}
+
+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);
+       }
+}
+
+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;
+}
+
+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;
+}
+
+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);
+}
+
+int trex_getsubexpcount(TRex* exp)
+{
+       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;
+}
+
+
+//########################################################################
+//########################################################################
+//##  E N D    R E G E X P
+//########################################################################
+//########################################################################
+
+
 
 
 
@@ -1912,6 +2654,129 @@ bool URI::parse(const String &str)
 //########################################################################
 //########################################################################
 
+//########################################################################
+//# F I L E S E T
+//########################################################################
+/**
+ * This is the descriptor for a <fileset> item
+ */
+class FileSet
+{
+public:
+
+    /**
+     *
+     */
+    FileSet()
+        {}
+
+    /**
+     *
+     */
+    FileSet(const FileSet &other)
+        { assign(other); }
+
+    /**
+     *
+     */
+    FileSet &operator=(const FileSet &other)
+        { assign(other); return *this; }
+
+    /**
+     *
+     */
+    virtual ~FileSet()
+        {}
+
+    /**
+     *
+     */
+    String getDirectory()
+        { return directory; }
+        
+    /**
+     *
+     */
+    void setDirectory(const String &val)
+        { directory = val; }
+
+    /**
+     *
+     */
+    void setFiles(const std::vector<String> &val)
+        { files = val; }
+
+    /**
+     *
+     */
+    std::vector<String> getFiles()
+        { return files; }
+        
+    /**
+     *
+     */
+    void setIncludes(const std::vector<String> &val)
+        { includes = val; }
+
+    /**
+     *
+     */
+    std::vector<String> getIncludes()
+        { return includes; }
+        
+    /**
+     *
+     */
+    void setExcludes(const std::vector<String> &val)
+        { excludes = val; }
+
+    /**
+     *
+     */
+    std::vector<String> getExcludes()
+        { return excludes; }
+        
+    /**
+     *
+     */
+    unsigned int size()
+        { return files.size(); }
+        
+    /**
+     *
+     */
+    String operator[](int index)
+        { return files[index]; }
+        
+    /**
+     *
+     */
+    void clear()
+        {
+        directory = "";
+        files.clear();
+        includes.clear();
+        excludes.clear();
+        }
+        
+
+private:
+
+    void assign(const FileSet &other)
+        {
+        directory = other.directory;
+        files     = other.files;
+        includes  = other.includes;
+        excludes  = other.excludes;
+        }
+
+    String directory;
+    std::vector<String> files;
+    std::vector<String> includes;
+    std::vector<String> excludes;
+};
+
+
 
 
 //########################################################################
@@ -1978,6 +2843,11 @@ protected:
      */
     void trace(char *fmt, ...);
 
+    /**
+     *  Check if a given string matches a given regex pattern
+     */
+    bool regexMatch(const String &str, const String &pattern);
+
     /**
      *
      */
@@ -2029,18 +2899,21 @@ protected:
                          std::vector<String> &res);
 
     /**
-     * Find all files in the named directory whose short names (no path) match
-     * the given regex pattern     
+     * Find all files in the named directory 
      */             
     bool listFiles(const String &baseName,
                    const String &dirname,
-                   std::vector<String> &excludes,
-                   std::vector<String> &res);
+                   std::vector<String> &result);
+
+    /**
+     * Perform a listing for a fileset 
+     */             
+    bool listFiles(MakeBase &propRef, FileSet &fileSet);
 
     /**
      * Parse a <patternset>
      */  
-    bool getPatternSet(Element *elem,
+    bool parsePatternSet(Element *elem,
                        MakeBase &propRef,
                                           std::vector<String> &includes,
                                           std::vector<String> &excludes);
@@ -2049,10 +2922,9 @@ protected:
      * Parse a <fileset> entry, and determine which files
      * should be included
      */  
-    bool getFileSet(Element *elem,
+    bool parseFileSet(Element *elem,
                     MakeBase &propRef,
-                    String &dir,
-                                       std::vector<String> &result);
+                                       FileSet &fileSet);
 
     /**
      * Return this object's property list
@@ -2182,6 +3054,40 @@ void MakeBase::trace(char *fmt, ...)
 }
 
 
+
+/**
+ *  Check if a given string matches a given regex pattern
+ */
+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;
+               } 
+
+    bool ret = true;
+
+       const TRexChar *cstr = str.c_str();
+       if (trex_match(expr, cstr))
+               {
+               ret = true;
+               }
+       else
+           {
+               ret = false;
+               }
+
+       trex_free(expr);
+
+    return ret;
+}
+
 /**
  *  Return the suffix, if any, of a file name
  */
@@ -2661,7 +3567,6 @@ bool MakeBase::listDirectories(const String &baseName,
 
 bool MakeBase::listFiles(const String &baseDir,
                          const String &dirName,
-                         std::vector<String> &excludes,
                          std::vector<String> &res)
 {
     String fullDir = baseDir;
@@ -2695,34 +3600,22 @@ bool MakeBase::listFiles(const String &baseDir,
         fullChild.append("/");
         fullChild.append(childName);
         
-        if (std::find(excludes.begin(), excludes.end(), childName)
-                       != excludes.end())
-            {
-            //trace("EXCLUDED:%s", childName.c_str());
-            continue;
-            }
-
-        struct stat finfo;
-        String nativeName = getNativePath(fullChild);
-        if (stat(nativeName.c_str(), &finfo)<0)
-            {
-            error("cannot stat file:%s", childName.c_str());
-            return false;
-            }
-        else if (S_ISDIR(finfo.st_mode))
+        if (isDirectory(fullChild))
             {
             //trace("directory: %s", childName.c_str());
-            if (!listFiles(baseDir, childName, excludes, res))
+            if (!listFiles(baseDir, childName, res))
                 return false;
+            continue;
             }
-        else if (!S_ISREG(finfo.st_mode))
-            {
-            trace("not regular: %s", childName.c_str());
-            }
-        else
+        else if (!isRegularFile(fullChild))
             {
-            res.push_back(childName);
+            error("unknown file:%s", childName.c_str());
+            return false;
             }
+
+       //all done!
+        res.push_back(childName);
+
         }
     closedir(dir);
 
@@ -2730,7 +3623,68 @@ bool MakeBase::listFiles(const String &baseDir,
 }
 
 
+bool MakeBase::listFiles(MakeBase &propRef, FileSet &fileSet)
+{
+    String baseDir = propRef.resolve(fileSet.getDirectory());
+    std::vector<String> fileList;
+    if (!listFiles(baseDir, "", fileList))
+           return false;
 
+    std::vector<String> includes = fileSet.getIncludes();
+    std::vector<String> excludes = fileSet.getExcludes();
+
+    std::vector<String> incs;
+    std::vector<String>::iterator iter;
+
+    std::sort(fileList.begin(), fileList.end());
+
+    //If there are <includes>, then add files to the output
+    //in the order of the include list
+    if (includes.size()==0)
+           incs = fileList;
+       else
+           {
+        for (iter = includes.begin() ; iter != includes.end() ; iter++)
+            {
+            String pattern = *iter;
+            std::vector<String>::iterator siter;
+            for (siter = fileList.begin() ; siter != fileList.end() ; siter++)
+                {
+                String s = *siter;
+                if (regexMatch(s, pattern))
+                    {
+                    //trace("INCLUDED:%s", s.c_str());
+                    incs.push_back(s);
+                    }
+                }
+            }
+        }
+
+    //Now trim off the <excludes>
+    std::vector<String> res;
+    for (iter = incs.begin() ; iter != incs.end() ; iter++)
+        {
+        String s = *iter;
+        bool skipme = false;
+        std::vector<String>::iterator siter;
+        for (siter = excludes.begin() ; siter != excludes.end() ; siter++)
+            {
+            String pattern = *siter;
+            if (regexMatch(s, pattern))
+                {
+                //trace("EXCLUDED:%s", s.c_str());
+                skipme = true;
+                break;
+                }
+            }
+        if (!skipme)
+            res.push_back(s);
+        }
+        
+       fileSet.setFiles(res);
+
+       return true;
+}
 
 
 
@@ -2828,7 +3782,7 @@ bool MakeBase::getBool(const String &str, bool &val)
 /**
  * Parse a <patternset> entry
  */  
-bool MakeBase::getPatternSet(Element *elem,
+bool MakeBase::parsePatternSet(Element *elem,
                           MakeBase &propRef,
                                                  std::vector<String> &includes,
                                                  std::vector<String> &excludes
@@ -2867,10 +3821,9 @@ bool MakeBase::getPatternSet(Element *elem,
  * Parse a <fileset> entry, and determine which files
  * should be included
  */  
-bool MakeBase::getFileSet(Element *elem,
+bool MakeBase::parseFileSet(Element *elem,
                           MakeBase &propRef,
-                                                 String &dir,
-                                                 std::vector<String> &result)
+                                                 FileSet &fileSet)
 {
     String name = elem->getName();
     if (name != "fileset")
@@ -2884,7 +3837,7 @@ bool MakeBase::getFileSet(Element *elem,
     std::vector<String> excludes;
 
     //A fileset has one implied patternset
-    if (!getPatternSet(elem, propRef, includes, excludes))
+    if (!parsePatternSet(elem, propRef, includes, excludes))
         {
         return false;
         }
@@ -2896,34 +3849,35 @@ bool MakeBase::getFileSet(Element *elem,
         String tagName = child->getName();
         if (tagName == "patternset")
             {
-            if (!getPatternSet(child, propRef, includes, excludes))
+            if (!parsePatternSet(child, propRef, includes, excludes))
                 {
                 return false;
                 }
             }
         }
 
+    String dir;
     //Now do the stuff
     //Get the base directory for reading file names
     if (!propRef.getAttribute(elem, "dir", dir))
         return false;
 
+    fileSet.setDirectory(dir);
+    fileSet.setIncludes(includes);
+    fileSet.setExcludes(excludes);
+    
+    /*
     std::vector<String> fileList;
     if (dir.size() > 0)
         {
         String baseDir = propRef.resolve(dir);
-           if (!listFiles(baseDir, "", excludes, fileList))
+           if (!listFiles(baseDir, "", includes, excludes, fileList))
                return false;
            }
-       
-       std::vector<String>::iterator iter;
-    for (iter=includes.begin() ; iter!=includes.end() ; iter++)
-        {
-        String fname = *iter;
-        fileList.push_back(fname);
-        }
-        
+    std::sort(fileList.begin(), fileList.end());
        result = fileList;
+       */
+
        
        /*
        for (unsigned int i=0 ; i<result.size() ; i++)
@@ -2932,7 +3886,6 @@ bool MakeBase::getFileSet(Element *elem,
            }
     */
 
-    std::sort(fileList.begin(), fileList.end());
     
     return true;
 }
@@ -3037,7 +3990,7 @@ bool MakeBase::removeDirectory(const String &dirName)
             }
         else if (!S_ISREG(finfo.st_mode))
             {
-            trace("not regular: %s", cnative);
+            //trace("not regular: %s", cnative);
             }
         else
             {
@@ -3626,7 +4579,7 @@ bool PkgConfig::parse(const String &buf)
 
 void PkgConfig::dumpAttrs()
 {
-    trace("### PkgConfig attributes for %s", fileName.c_str());
+    //trace("### PkgConfig attributes for %s", fileName.c_str());
     std::map<String, String>::iterator iter;
     for (iter=attrs.begin() ; iter!=attrs.end() ; iter++)
         {
@@ -3655,7 +4608,7 @@ bool PkgConfig::readFile(const String &fileNameArg)
         }
     fclose(f);
 
-    trace("####### File:\n%s", buf.c_str());
+    //trace("####### File:\n%s", buf.c_str());
     if (!parse(buf))
         {
         return false;
@@ -4736,6 +5689,9 @@ public:
         String fullOut = parent.resolve(fileName);
         //trace("ar fullout: %s", fullOut.c_str());
         
+        if (!listFiles(parent, fileSet))
+            return false;
+        String fileSetDir = fileSet.getDirectory();
 
         for (unsigned int i=0 ; i<fileSet.size() ; i++)
             {
@@ -4797,7 +5753,7 @@ public:
             String tagName = child->getName();
             if (tagName == "fileset")
                 {
-                if (!getFileSet(child, parent, fileSetDir, fileSet))
+                if (!parseFileSet(child, parent, fileSet))
                     return false;
                 }
             }
@@ -4808,8 +5764,7 @@ private:
 
     String command;
     String fileName;
-    String fileSetDir;
-    std::vector<String> fileSet;
+    FileSet fileSet;
 
 };
 
@@ -4833,7 +5788,7 @@ public:
                flags       = "";
                defines     = "";
                includes    = "";
-               sourceFiles.clear();
+               fileSet.clear();
         }
 
     virtual ~TaskCC()
@@ -4841,9 +5796,12 @@ public:
 
     virtual bool execute()
         {
+        if (!listFiles(parent, fileSet))
+            return false;
+
         DepTool depTool;
         depTool.setSourceDirectory(source);
-        depTool.setFileList(sourceFiles);
+        depTool.setFileList(fileSet.getFiles());
         std::vector<DepRec> deps = depTool.getDepFile("build.dep");
         
         String incs;
@@ -4991,8 +5949,9 @@ public:
                 }
             else if (tagName == "fileset")
                 {
-                if (!getFileSet(child, parent, source, sourceFiles))
+                if (!parseFileSet(child, parent, fileSet))
                     return false;
+                source = fileSet.getDirectory();
                 }
             }
 
@@ -5008,7 +5967,7 @@ protected:
     String flags;
     String defines;
     String includes;
-    std::vector<String> sourceFiles;
+    FileSet fileSet;
     
 };
 
@@ -5071,6 +6030,10 @@ public:
                {
                if (haveFileSet)
                    {
+                   if (!listFiles(parent, fileSet))
+                       return false;
+                   String fileSetDir = fileSet.getDirectory();
+
                    int nrFiles = 0;
                    status("          : %s", fileSetDir.c_str());
                    for (unsigned int i=0 ; i<fileSet.size() ; i++)
@@ -5189,7 +6152,7 @@ public:
             String tagName = child->getName();
             if (tagName == "fileset")
                 {
-                if (!getFileSet(child, parent, fileSetDir, fileSet))
+                if (!parseFileSet(child, parent, fileSet))
                     {
                     error("problem getting fileset");
                                        return false;
@@ -5232,8 +6195,7 @@ private:
 
     int cptype;
     String fileName;
-    String fileSetDir;
-    std::vector<String> fileSet;
+    FileSet fileSet;
     String toFileName;
     String toDirName;
     bool verbose;
@@ -5417,6 +6379,10 @@ public:
 
     virtual bool execute()
         {
+        if (!listFiles(parent, fileSet))
+            return false;
+        String fileSetDir = fileSet.getDirectory();
+        //trace("%d files in %s", fileSet.size(), fileSetDir.c_str());
         bool doit = false;
         String fullTarget = parent.resolve(fileName);
         String cmd = command;
@@ -5436,6 +6402,8 @@ public:
             obj.append(fileSet[i]);
             String fullObj = parent.resolve(obj);
             cmd.append(fullObj);
+            //trace("link: tgt:%s obj:%s", fullTarget.c_str(),
+            //          fullObj.c_str());
             if (isNewerThan(fullObj, fullTarget))
                 doit = true;
             }
@@ -5472,7 +6440,7 @@ public:
             String tagName = child->getName();
             if (tagName == "fileset")
                 {
-                if (!getFileSet(child, parent, fileSetDir, fileSet))
+                if (!parseFileSet(child, parent, fileSet))
                     return false;
                 }
             else if (tagName == "flags")
@@ -5497,8 +6465,7 @@ private:
     String fileName;
     String flags;
     String libs;
-    String fileSetDir;
-    std::vector<String> fileSet;
+    FileSet fileSet;
 
 };
 
@@ -5626,6 +6593,10 @@ public:
 
     virtual bool execute()
         {
+        if (!listFiles(parent, fileSet))
+            return false;
+        String fileSetDir = fileSet.getDirectory();
+
         //trace("msgfmt: %d", fileSet.size());
         for (unsigned int i=0 ; i<fileSet.size() ; i++)
             {
@@ -5696,7 +6667,7 @@ public:
             String tagName = child->getName();
             if (tagName == "fileset")
                 {
-                if (!getFileSet(child, parent, fileSetDir, fileSet))
+                if (!parseFileSet(child, parent, fileSet))
                     return false;
                 }
             }
@@ -5707,8 +6678,7 @@ private:
 
     String command;
     String toDirName;
-    String fileSetDir;
-    std::vector<String> fileSet;
+    FileSet fileSet;
 
 };
 
@@ -5896,7 +6866,7 @@ public:
 
     virtual bool parse(Element *elem)
         {
-        trace("tstamp parse");
+        //trace("tstamp parse");
         return true;
         }
 };
@@ -6804,7 +7774,8 @@ bool Make::run(const String &target)
 {
     status("##################################");
     status("#   BuildTool");
-    status("#   version 0.2");
+    status("#   version 0.3");
+    status("#   16 Nov 06");
     status("##################################");
     specifiedTarget = target;
     if (!run())