Code

some changes bcs of the name of uninstall.exe
[inkscape.git] / buildtool.cpp
index 34d801c5776bd0a073b233a8ff29d9e851ef2e7b..5975f86e195fa0289c0a07eb1782bb7d23b0d9d8 100644 (file)
  * or 
  * btool {target}
  * 
- * Note: recent win32api builds from MinGW have gettimeofday()
- * defined, so you might need to build with 
- * g++ -O3 -DHAVE_GETTIMEOFDAY buildtool.cpp -o btool.exe
+ * 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.3, 2007 Bob Jamison"
+#define BUILDTOOL_VERSION  "BuildTool v0.7.0, 2007 Bob Jamison"
 
 #include <stdio.h>
+#include <fcntl.h>
 #include <unistd.h>
 #include <stdarg.h>
 #include <sys/stat.h>
@@ -64,7 +66,7 @@
 //########################################################################
 //# Definition of gettimeofday() for those who don't have it
 //########################################################################
-#ifndef HAVE_GETTIMEOFDAY
+#ifdef NEED_GETTIMEOFDAY
 #include <sys/timeb.h>
 
 struct timezone {
@@ -960,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;
         }
@@ -1039,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;
@@ -1050,6 +1061,7 @@ protected:
         namespaces = other.namespaces;
         name       = other.name;
         value      = other.value;
+        line       = other.line;
         }
 
     void findElementsRecursive(std::vector<Element *>&res, const String &name);
@@ -1065,7 +1077,8 @@ protected:
 
     String name;
     String value;
-
+    
+    int line;
 };
 
 
@@ -1133,15 +1146,17 @@ private:
         currentPosition = 0;
         }
 
-    void getLineAndColumn(long pos, long *lineNr, long *colNr);
+    int countLines(int begin, int end);
 
-    void error(char *fmt, ...);
+    void getLineAndColumn(int pos, int *lineNr, int *colNr);
+
+    void error(const 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);
 
@@ -1157,12 +1172,10 @@ private:
 
     bool       keepGoing;
     Element    *currentNode;
-    long       parselen;
+    int        parselen;
     XMLCh      *parsebuf;
-    String  cdatabuf;
-    long       currentPosition;
-    int        colNr;
-
+    String     cdatabuf;
+    int        currentPosition;
 };
 
 
@@ -1178,6 +1191,7 @@ Element *Element::clone()
     elem->parent     = parent;
     elem->attributes = attributes;
     elem->namespaces = namespaces;
+    elem->line       = line;
 
     std::vector<Element *>::iterator iter;
     for (iter = children.begin(); iter != children.end() ; iter++)
@@ -1311,7 +1325,7 @@ void Element::print()
 
 typedef struct
     {
-    char *escaped;
+    const char *escaped;
     char value;
     } EntityEntry;
 
@@ -1356,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)
 {
-    long line = 1;
-    long col  = 1;
+    int count = 0;
+    for (int i=begin ; i<end ; i++)
+        {
+        XMLCh ch = parsebuf[i];
+        if (ch == '\n' || ch == '\r')
+            count++;
+        }
+    return count;
+}
+
+
+void Parser::getLineAndColumn(int pos, int *lineNr, int *colNr)
+{
+    int line = 1;
+    int col  = 1;
     for (long i=0 ; i<pos ; i++)
         {
         XMLCh ch = parsebuf[i];
@@ -1377,13 +1405,13 @@ void Parser::getLineAndColumn(long pos, long *lineNr, long *colNr)
 }
 
 
-void Parser::error(char *fmt, ...)
+void Parser::error(const char *fmt, ...)
 {
-    long lineNr;
-    long colNr;
+    int lineNr;
+    int colNr;
     getLineAndColumn(currentPosition, &lineNr, &colNr);
     va_list args;
-    fprintf(stderr, "xml error at line %ld, column %ld:", lineNr, colNr);
+    fprintf(stderr, "xml error at line %d, column %d:", lineNr, colNr);
     va_start(args,fmt);
     vfprintf(stderr,fmt,args);
     va_end(args) ;
@@ -1392,7 +1420,7 @@ void Parser::error(char *fmt, ...)
 
 
 
-int Parser::peek(long pos)
+int Parser::peek(int pos)
 {
     if (pos >= parselen)
         return -1;
@@ -1428,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)
@@ -1442,7 +1470,7 @@ int Parser::match(long p0, const char *text)
 
 
 
-int Parser::skipwhite(long p)
+int Parser::skipwhite(int p)
 {
 
     while (p<parselen)
@@ -1599,7 +1627,9 @@ int Parser::parseDoctype(int p0)
     return p;
 }
 
-int Parser::parseElement(int p0, Element *par,int depth)
+
+
+int Parser::parseElement(int p0, Element *par,int lineNr)
 {
 
     int p = p0;
@@ -1613,6 +1643,9 @@ int Parser::parseElement(int p0, Element *par,int depth)
     if (ch!='<')
         return p0;
 
+    //int line, col;
+    //getLineAndColumn(p, &line, &col);
+
     p++;
 
     String openTagName;
@@ -1623,6 +1656,7 @@ int Parser::parseElement(int p0, Element *par,int depth)
 
     //Add element to tree
     Element *n = new Element(openTagName);
+    n->line = lineNr + countLines(p0, p);
     n->parent = par;
     par->addChild(n);
 
@@ -1717,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)
                 {
                 /*
@@ -1809,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;
 }
 
@@ -2115,7 +2149,7 @@ private:
 
     int peek(int p);
 
-    int match(int p, char *key);
+    int match(int p, const char *key);
 
     int parseScheme(int p);
 
@@ -2137,9 +2171,9 @@ private:
 
 typedef struct
 {
-    int  ival;
-    char *sval;
-    int  port;
+    int         ival;
+    const char *sval;
+    int         port;
 } LookupEntry;
 
 LookupEntry schemes[] =
@@ -2467,7 +2501,7 @@ int URI::peek(int p)
 
 
 
-int URI::match(int p0, char *key)
+int URI::match(int p0, const char *key)
 {
     int p = p0;
     while (p < parselen)
@@ -2839,8 +2873,9 @@ private:
 class MakeBase
 {
 public:
+
     MakeBase()
-        {}
+        { line = 0; }
     virtual ~MakeBase()
         {}
 
@@ -2870,6 +2905,51 @@ 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; }
+
+
+    /**
+     * Set a property to a given value
+     */
+    virtual void setProperty(const String &name, const String &val)
+        {
+        properties[name] = val;
+        }
+
+    /**
+     * Return a named property is found, else a null string
+     */
+    virtual String getProperty(const String &name)
+        {
+        String val;
+        std::map<String, String>::iterator iter = properties.find(name);
+        if (iter != properties.end())
+            val = iter->second;
+        return val;
+        }
+
+    /**
+     * Return true if a named property is found, else false
+     */
+    virtual bool hasProperty(const String &name)
+        {
+        std::map<String, String>::iterator iter = properties.find(name);
+        if (iter == properties.end())
+            return false;
+        return true;
+        }
+
 
 protected:
 
@@ -2882,17 +2962,17 @@ protected:
     /**
      *  Print a printf()-like formatted error message
      */
-    void error(char *fmt, ...);
+    void error(const char *fmt, ...);
 
     /**
      *  Print a printf()-like formatted trace message
      */
-    void status(char *fmt, ...);
+    void status(const char *fmt, ...);
 
     /**
      *  Print a printf()-like formatted trace message
      */
-    void trace(char *fmt, ...);
+    void trace(const char *fmt, ...);
 
     /**
      *  Check if a given string matches a given regex pattern
@@ -2926,6 +3006,11 @@ protected:
      */
     String trim(const String &s);
 
+    /**
+     *  Return a lower case version of the given string
+     */
+    String toLower(const String &s);
+
     /**
      * Return the native format of the canonical
      * path which we store
@@ -2983,19 +3068,6 @@ protected:
     virtual std::map<String, String> &getProperties()
         { return properties; }
 
-    /**
-     * Return a named property if found, else a null string
-     */
-    virtual String getProperty(const String &name)
-        {
-        String val;
-        std::map<String, String>::iterator iter;
-        iter = properties.find(name);
-        if (iter != properties.end())
-            val = iter->second;
-        return val;
-        }
-
 
     std::map<String, String> properties;
 
@@ -3042,6 +3114,7 @@ private:
      */         
     bool getSubstitutions(const String &s, String &result);
 
+    int line;
 
 
 };
@@ -3052,11 +3125,11 @@ private:
 /**
  *  Print a printf()-like formatted error message
  */
-void MakeBase::error(char *fmt, ...)
+void MakeBase::error(const 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) ;
@@ -3067,7 +3140,7 @@ void MakeBase::error(char *fmt, ...)
 /**
  *  Print a printf()-like formatted trace message
  */
-void MakeBase::status(char *fmt, ...)
+void MakeBase::status(const char *fmt, ...)
 {
     va_list args;
     va_start(args,fmt);
@@ -3094,7 +3167,7 @@ String MakeBase::resolve(const String &otherPath)
 /**
  *  Print a printf()-like formatted trace message
  */
-void MakeBase::trace(char *fmt, ...)
+void MakeBase::trace(const char *fmt, ...)
 {
     va_list args;
     va_start(args,fmt);
@@ -3301,6 +3374,24 @@ String MakeBase::trim(const String &s)
     return res;
 }
 
+
+/**
+ *  Return a lower case version of the given string
+ */
+String MakeBase::toLower(const String &s)
+{
+    if (s.size()==0)
+        return s;
+
+    String ret;
+    for(unsigned int i=0; i<s.size() ; i++)
+        {
+        ret.push_back(tolower(s[i]));
+        }
+    return ret;
+}
+
+
 /**
  * Return the native format of the canonical
  * path which we store
@@ -3398,6 +3489,9 @@ bool MakeBase::executeCommand(const String &command,
        }
     strcpy(paramBuf, (char *)command.c_str());
 
+    //# Go to http://msdn2.microsoft.com/en-us/library/ms682499.aspx
+    //# to see how Win32 pipes work
+
     //# Create pipes
     SECURITY_ATTRIBUTES saAttr; 
     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
@@ -3448,6 +3542,8 @@ bool MakeBase::executeCommand(const String &command,
         ret = false;
         }
 
+    delete[] paramBuf;
+
     DWORD bytesWritten;
     if (inbuf.size()>0 &&
         !WriteFile(stdinWrite, inbuf.c_str(), inbuf.size(), 
@@ -3471,16 +3567,20 @@ bool MakeBase::executeCommand(const String &command,
         error("executeCommand: could not close read pipe");
         return false;
         }
+
+    bool lastLoop = false;
     while (true)
         {
-        //trace("## stderr");
         DWORD avail;
+        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;
+            bytesRead = 0;
+            if (avail>4096) avail = 4096;
             ReadFile(stderrRead, readBuf, avail, &bytesRead, NULL);
             if (bytesRead > 0)
                 {
@@ -3493,9 +3593,8 @@ bool MakeBase::executeCommand(const String &command,
         PeekNamedPipe(stdoutRead, NULL, 0, NULL, &avail, NULL);
         if (avail > 0)
             {
-            DWORD bytesRead = 0;
-            char readBuf[1025];
-            if (avail>1024) avail = 1024;
+            bytesRead = 0;
+            if (avail>4096) avail = 4096;
             ReadFile(stdoutRead, readBuf, avail, &bytesRead, NULL);
             if (bytesRead > 0)
                 {
@@ -3503,11 +3602,17 @@ bool MakeBase::executeCommand(const String &command,
                     outbuf.push_back(readBuf[i]);
                 }
             }
+            
+        //Was this the final check after program done?
+        if (lastLoop)
+            break;
+
         DWORD exitCode;
         GetExitCodeProcess(piProcessInfo.hProcess, &exitCode);
         if (exitCode != STILL_ACTIVE)
-            break;
-        Sleep(100);
+            lastLoop = true;
+
+        Sleep(10);
         }    
     //trace("outbuf:%s", outbuf.c_str());
     if (!CloseHandle(stdoutRead))
@@ -3529,11 +3634,9 @@ bool MakeBase::executeCommand(const String &command,
         ret = false;
         }
     
-    // Clean up
     CloseHandle(piProcessInfo.hProcess);
     CloseHandle(piProcessInfo.hThread);
 
-
     return ret;
 
 #else //do it unix-style
@@ -4252,13 +4355,7 @@ public:
      *
      */
     PkgConfig()
-        { init(); }
-
-    /**
-     *
-     */
-    PkgConfig(const String &namearg)
-        { init(); name = namearg; }
+        { path="."; init(); }
 
     /**
      *
@@ -4284,6 +4381,30 @@ public:
     virtual String getName()
         { return name; }
 
+    /**
+     *
+     */
+    virtual String getPath()
+        { return path; }
+
+    /**
+     *
+     */
+    virtual void setPath(const String &val)
+        { path = val; }
+
+    /**
+     *
+     */
+    virtual String getPrefix()
+        { return prefix; }
+
+    /**
+     *  Allow the user to override the prefix in the file
+     */
+    virtual void setPrefix(const String &val)
+        { prefix = val; }
+
     /**
      *
      */
@@ -4302,6 +4423,17 @@ public:
     virtual String getLibs()
         { return libs; }
 
+    /**
+     *
+     */
+    virtual String getAll()
+        {
+         String ret = cflags;
+         ret.append(" ");
+         ret.append(libs);
+         return ret;
+        }
+
     /**
      *
      */
@@ -4338,12 +4470,21 @@ public:
     virtual std::vector<String> &getRequireList()
         { return requireList; }
 
+    /**
+     *  Read a file for its details
+     */         
     virtual bool readFile(const String &fileName);
 
+    /**
+     *  Read a file for its details
+     */         
+    virtual bool query(const String &name);
+
 private:
 
     void init()
         {
+        //do not set path or prefix here
         name         = "";
         description  = "";
         cflags       = "";
@@ -4361,6 +4502,8 @@ private:
     void assign(const PkgConfig &other)
         {
         name         = other.name;
+        path         = other.path;
+        prefix       = other.prefix;
         description  = other.description;
         cflags       = other.cflags;
         libs         = other.libs;
@@ -4386,12 +4529,18 @@ private:
 
     void parseVersion();
 
+    bool parseLine(const String &lineBuf);
+
     bool parse(const String &buf);
 
     void dumpAttrs();
 
     String name;
 
+    String path;
+
+    String prefix;
+
     String description;
 
     String cflags;
@@ -4435,6 +4584,7 @@ int PkgConfig::get(int pos)
 /**
  *  Skip over all whitespace characters beginning at pos.  Return
  *  the position of the first non-whitespace character.
+ *  Pkg-config is line-oriented, so check for newline
  */
 int PkgConfig::skipwhite(int pos)
 {
@@ -4544,15 +4694,12 @@ void PkgConfig::parseVersion()
 }
 
 
-bool PkgConfig::parse(const String &buf)
+bool PkgConfig::parseLine(const String &lineBuf)
 {
-    init();
-
-    parsebuf = (char *)buf.c_str();
-    parselen = buf.size();
+    parsebuf = (char *)lineBuf.c_str();
+    parselen = lineBuf.size();
     int pos = 0;
-
-
+    
     while (pos < parselen)
         {
         String attrName;
@@ -4573,6 +4720,7 @@ bool PkgConfig::parse(const String &buf)
         pos = getword(pos, attrName);
         if (attrName.size() == 0)
             continue;
+        
         pos = skipwhite(pos);
         ch = get(pos);
         if (ch != ':' && ch != '=')
@@ -4607,10 +4755,18 @@ bool PkgConfig::parse(const String &buf)
                         subName.push_back((char)ch);
                     pos++;
                     }
-                //trace("subName:%s", subName.c_str());
-                String subVal = attrs[subName];
-                //trace("subVal:%s", subVal.c_str());
-                attrVal.append(subVal);
+                //trace("subName:%s %s", subName.c_str(), prefix.c_str());
+                if (subName == "prefix" && prefix.size()>0)
+                    {
+                    attrVal.append(prefix);
+                    //trace("prefix override:%s", prefix.c_str());
+                    }
+                else
+                    {
+                    String subVal = attrs[subName];
+                    //trace("subVal:%s", subVal.c_str());
+                    attrVal.append(subVal);
+                    }
                 }
             else
                 attrVal.push_back((char)ch);
@@ -4620,23 +4776,55 @@ bool PkgConfig::parse(const String &buf)
         attrVal = trim(attrVal);
         attrs[attrName] = attrVal;
 
-        if (attrName == "Name")
+        String attrNameL = toLower(attrName);
+
+        if (attrNameL == "name")
             name = attrVal;
-        else if (attrName == "Description")
+        else if (attrNameL == "description")
             description = attrVal;
-        else if (attrName == "Cflags")
+        else if (attrNameL == "cflags")
             cflags = attrVal;
-        else if (attrName == "Libs")
+        else if (attrNameL == "libs")
             libs = attrVal;
-        else if (attrName == "Requires")
+        else if (attrNameL == "requires")
             requires = attrVal;
-        else if (attrName == "Version")
+        else if (attrNameL == "version")
             version = attrVal;
 
         //trace("name:'%s'  value:'%s'",
         //      attrName.c_str(), attrVal.c_str());
         }
 
+    return true;
+}
+
+
+bool PkgConfig::parse(const String &buf)
+{
+    init();
+
+    String line;
+    int lineNr = 0;
+    for (unsigned int p=0 ; p<buf.size() ; p++)
+        {
+        int ch = buf[p];
+        if (ch == '\n' || ch == '\r')
+            {
+            if (!parseLine(line))
+                return false;
+            line.clear();
+            lineNr++;
+            }
+        else
+            {
+            line.push_back(ch);
+            }
+        }
+    if (line.size()>0)
+        {
+        if (!parseLine(line))
+            return false;
+        }
 
     parseRequires();
     parseVersion();
@@ -4644,6 +4832,9 @@ bool PkgConfig::parse(const String &buf)
     return true;
 }
 
+
+
+
 void PkgConfig::dumpAttrs()
 {
     //trace("### PkgConfig attributes for %s", fileName.c_str());
@@ -4655,9 +4846,9 @@ void PkgConfig::dumpAttrs()
 }
 
 
-bool PkgConfig::readFile(const String &fileNameArg)
+bool PkgConfig::readFile(const String &fname)
 {
-    fileName = fileNameArg;
+    fileName = getNativePath(fname);
 
     FILE *f = fopen(fileName.c_str(), "r");
     if (!f)
@@ -4681,13 +4872,30 @@ bool PkgConfig::readFile(const String &fileNameArg)
         return false;
         }
 
-    dumpAttrs();
+    //dumpAttrs();
 
     return true;
 }
 
 
 
+bool PkgConfig::query(const String &pkgName)
+{
+    name = pkgName;
+
+    String fname = path;
+    fname.append("/");
+    fname.append(name);
+    fname.append(".pc");
+
+    if (!readFile(fname))
+        return false;
+    
+    return true;
+}
+
+
+
 
 
 //########################################################################
@@ -4715,23 +4923,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; }
 
 
     /**
@@ -4853,7 +5061,7 @@ private:
         path     = other.path;
         name     = other.name;
         suffix   = other.suffix;
-        files    = other.files;
+        files    = other.files; //avoid recursion
         }
 
 };
@@ -4867,19 +5075,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; }
 
 
     /**
@@ -4985,7 +5193,7 @@ private:
     /**
      *
      */
-    bool sequ(int pos, char *key);
+    bool sequ(int pos, const char *key);
 
     /**
      *
@@ -5000,9 +5208,7 @@ private:
     /**
      *
      */
-    bool processDependency(FileRec *ofile,
-                           FileRec *include,
-                           int depth);
+    bool processDependency(FileRec *ofile, FileRec *include);
 
     /**
      *
@@ -5021,8 +5227,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<String, FileRec *> allFiles;
 
@@ -5030,7 +5235,7 @@ private:
      * The list of .o files, and the
      * dependencies upon them.
      */
-    std::map<String, FileRec *> depFiles;
+    std::map<String, FileRec *> oFiles;
 
     int depFileSize;
     char *depFileBuf;
@@ -5055,13 +5260,15 @@ void DepTool::init()
     fileList.clear();
     directories.clear();
     
-    //clear refs
-    depFiles.clear();
-    //clear records
+    //clear output file list
     std::map<String, FileRec *>::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(); 
 
 }
@@ -5206,7 +5413,7 @@ int DepTool::getword(int pos, String &ret)
  * Return whether the sequence of characters in the buffer
  * beginning at pos match the key,  for the length of the key
  */
-bool DepTool::sequ(int pos, char *key)
+bool DepTool::sequ(int pos, const char *key)
 {
     while (*key)
         {
@@ -5226,7 +5433,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<String, FileRec *>::iterator iter =
            allFiles.find(iname);
     if (iter != allFiles.end()) //already exists
@@ -5239,6 +5447,7 @@ bool DepTool::addIncludeFile(FileRec *frec, const String &iname)
         }
     else 
         {
+        //## Ok, it was not found directly
         //look in other dirs
         std::vector<String>::iterator diter;
         for (diter=directories.begin() ;
@@ -5247,12 +5456,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;
                 }
             }
@@ -5359,9 +5573,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<String, FileRec *>::iterator iter;
     for (iter=include->files.begin() ; iter!=include->files.end() ; iter++)
@@ -5375,7 +5587,7 @@ bool DepTool::processDependency(FileRec *ofile,
         FileRec *child  = iter->second;
         ofile->files[fname] = child;
       
-        processDependency(ofile, child, depth+1);
+        processDependency(ofile, child);
         }
 
 
@@ -5408,23 +5620,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);
             }
         }
 
@@ -5472,7 +5684,7 @@ bool DepTool::saveDepFile(const String &fileName)
 
     fprintf(f, "<dependencies source='%s'>\n\n", sourceDir.c_str());
     std::map<String, FileRec *>::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)
@@ -5523,7 +5735,7 @@ std::vector<DepRec> DepTool::loadDepFile(const String &depFile)
     if (root->getChildren().size()==0 ||
         root->getChildren()[0]->getName()!="dependencies")
         {
-        error("Main xml element should be <dependencies>");
+        error("loadDepFile: main xml element should be <dependencies>");
         delete root;
         return result;
         }
@@ -5536,47 +5748,53 @@ std::vector<DepRec> 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<Element *> depElems = objectElem->getChildren();
-            for (unsigned int i=0 ; i<depElems.size() ; i++)
+        if (tagName != "object")
+            {
+            error("loadDepFile: <dependencies> should have only <object> 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<Element *> depElems = objectElem->getChildren();
+        for (unsigned int i=0 ; i<depElems.size() ; i++)
+            {
+            Element *depElem = depElems[i];
+            tagName = depElem->getName();
+            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: <object> should have only <dep> children");
+                return result;
                 }
-            //Insert into the result list, in a sorted manner
-            bool inserted = false;
-            std::vector<DepRec>::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<DepRec>::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;
@@ -5641,6 +5859,7 @@ public:
         TASK_MAKEFILE,
         TASK_MKDIR,
         TASK_MSGFMT,
+        TASK_PKG_CONFIG,
         TASK_RANLIB,
         TASK_RC,
         TASK_SHAREDLIB,
@@ -5715,7 +5934,7 @@ public:
     /**
      *
      */
-    Task *createTask(Element *elem);
+    Task *createTask(Element *elem, int lineNr);
 
 
 protected:
@@ -5772,7 +5991,7 @@ public:
     virtual ~TaskCC()
         {}
 
-    virtual bool needsCompiling(const DepRec &depRec,
+    virtual bool needsCompiling(const FileRec &depRec,
               const String &src, const String &dest)
         {
         return false;
@@ -5782,6 +6001,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");
@@ -5841,8 +6063,8 @@ public:
             //## Select command
             String sfx = dep.suffix;
             String command = ccCommand;
-            if (sfx == "cpp" || sfx == "c++" || sfx == "cc"
-                 || sfx == "CC")
+            if (sfx == "cpp" || sfx == "cxx" || sfx == "c++" ||
+                 sfx == "cc" || sfx == "CC")
                 command = cxxCommand;
  
             //## Make paths
@@ -5880,6 +6102,7 @@ public:
             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",
@@ -5888,17 +6111,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 ; i<dep.files.size() ; i++)
                     {
                     String depName;
-                    if (srcPath.size()>0)
+                    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());
@@ -5928,11 +6156,48 @@ public:
             //## 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 (unsigned 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;
@@ -6049,6 +6314,7 @@ public:
                        }
                    if (!isNewerThan(fullSource, fullDest))
                        {
+                       status("          : skipped");
                        return true;
                        }
                    if (!copyFile(fullSource, fullDest))
@@ -6146,6 +6412,7 @@ public:
                        }
                    if (!isNewerThan(fullSource, fullDest))
                        {
+                       status("          : skipped");
                        return true;
                        }
                    if (!copyFile(fullSource, fullDest))
@@ -6315,7 +6582,12 @@ public:
             delType = DEL_DIR;
         if (fileName.size()>0 && dirName.size()>0)
             {
-            error("<delete> can only have one attribute of file= or dir=");
+            error("<delete> can have one attribute of file= or dir=");
+            return false;
+            }
+        if (fileName.size()==0 && dirName.size()==0)
+            {
+            error("<delete> must have one attribute of file= or dir=");
             return false;
             }
         String ret;
@@ -6438,7 +6710,8 @@ public:
                 }
             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))
@@ -6803,6 +7076,145 @@ private:
 
 
 
+/**
+ *  Perform a Package-Config query similar to pkg-config
+ */
+class TaskPkgConfig : public Task
+{
+public:
+
+    typedef enum
+        {
+        PKG_CONFIG_QUERY_CFLAGS,
+        PKG_CONFIG_QUERY_LIBS,
+        PKG_CONFIG_QUERY_ALL
+        } QueryTypes;
+
+    TaskPkgConfig(MakeBase &par) : Task(par)
+        {
+        type = TASK_PKG_CONFIG;
+        name = "pkg-config";
+        }
+
+    virtual ~TaskPkgConfig()
+        {}
+
+    virtual bool execute()
+        {
+        String path = parent.resolve(pkg_config_path);
+        PkgConfig pkgconfig;
+        pkgconfig.setPath(path);
+        pkgconfig.setPrefix(prefix);
+        if (!pkgconfig.query(pkgName))
+            {
+            error("<pkg-config> query failed for '%s", name.c_str());
+            return false;
+            }
+        String ret;
+        switch (query)
+            {
+            case PKG_CONFIG_QUERY_CFLAGS:
+                {
+                ret = pkgconfig.getCflags();
+                break;
+                }
+            case PKG_CONFIG_QUERY_LIBS:
+                {
+                ret = pkgconfig.getLibs();
+                break;
+                }
+            case PKG_CONFIG_QUERY_ALL:
+                {
+                ret = pkgconfig.getAll();
+                break;
+                }
+            default:
+                {
+                error("<pkg-config> unhandled query : %d", query);
+                return false;
+                }
+            
+            }
+        status("          : %s", ret.c_str());
+        parent.setProperty(propName, ret);
+        return true;
+        }
+
+    virtual bool parse(Element *elem)
+        {
+        String s;
+        //# NAME
+        if (!parent.getAttribute(elem, "name", s))
+            return false;
+        if (s.size()>0)
+           pkgName = s;
+        else
+            {
+            error("<pkg-config> requires 'name=\"package\"' attribute");
+            return false;
+            }
+
+        //# PROPERTY
+        if (!parent.getAttribute(elem, "property", s))
+            return false;
+        if (s.size()>0)
+           propName = s;
+        else
+            {
+            error("<pkg-config> requires 'property=\"name\"' attribute");
+            return false;
+            }
+        if (parent.hasProperty(propName))
+            {
+            error("<pkg-config> property '%s' is already defined",
+                          propName.c_str());
+            return false;
+            }
+        parent.setProperty(propName, "undefined");
+
+        //# PATH
+        if (!parent.getAttribute(elem, "path", s))
+            return false;
+        if (s.size()>0)
+           pkg_config_path = s;
+
+        //# PREFIX
+        if (!parent.getAttribute(elem, "prefix", s))
+            return false;
+        if (s.size()>0)
+           prefix = s;
+
+        //# QUERY
+        if (!parent.getAttribute(elem, "query", s))
+            return false;
+        if (s == "cflags")
+            query = PKG_CONFIG_QUERY_CFLAGS;
+        else if (s == "libs")
+            query = PKG_CONFIG_QUERY_LIBS;
+        else if (s == "both")
+            query = PKG_CONFIG_QUERY_ALL;
+        else
+            {
+            error("<pkg-config> requires 'query=\"type\"' attribute");
+            error("where type = cflags, libs, or both");
+            return false;
+            }
+        return true;
+        }
+
+private:
+
+    String pkgName;
+    String prefix;
+    String propName;
+    String pkg_config_path;
+    int query;
+
+};
+
+
+
+
 
 
 /**
@@ -6941,7 +7353,7 @@ public:
     TaskSharedLib(MakeBase &par) : Task(par)
         {
         type = TASK_SHAREDLIB; name = "dll";
-        command = "ar crv";
+        command = "dllwrap";
         }
 
     virtual ~TaskSharedLib()
@@ -7326,7 +7738,7 @@ public:
 /**
  *
  */
-Task *Task::createTask(Element *elem)
+Task *Task::createTask(Element *elem, int lineNr)
 {
     String tagName = elem->getName();
     //trace("task:%s", tagName.c_str());
@@ -7349,6 +7761,8 @@ Task *Task::createTask(Element *elem)
         task = new TaskMkDir(parent);
     else if (tagName == "msgfmt")
         task = new TaskMsgFmt(parent);
+    else if (tagName == "pkg-config")
+        task = new TaskPkgConfig(parent);
     else if (tagName == "ranlib")
         task = new TaskRanlib(parent);
     else if (tagName == "rc")
@@ -7369,6 +7783,8 @@ Task *Task::createTask(Element *elem)
         return NULL;
         }
 
+    task->setLine(lineNr);
+
     if (!task->parse(elem))
         {
         delete task;
@@ -7665,11 +8081,6 @@ private:
      */
     bool parseProperty(Element *elem);
 
-    /**
-     *
-     */
-    bool parseTask(Task &task, Element *elem);
-
     /**
      *
      */
@@ -7819,7 +8230,8 @@ bool Make::executeTarget(Target &target,
             }
         }
 
-    status("## Target : %s", name.c_str());
+    status("## Target : %s : %s", name.c_str(),
+            target.getDescription().c_str());
 
     //Now let's do the tasks
     std::vector<Task *> &tasks = target.getTasks();
@@ -8128,6 +8540,8 @@ bool Make::parseFile()
 {
     status("######## PARSE : %s", uri.getPath().c_str());
 
+    setLine(0);
+
     Parser parser;
     Element *root = parser.parseFile(uri.getNativePath());
     if (!root)
@@ -8136,6 +8550,8 @@ bool Make::parseFile()
               uri.getNativePath().c_str());
         return false;
         }
+    
+    setLine(root->getLine());
 
     if (root->getChildren().size()==0 ||
         root->getChildren()[0]->getName()!="project")
@@ -8162,6 +8578,7 @@ bool Make::parseFile()
     for (unsigned int i=0 ; i<children.size() ; i++)
         {
         Element *elem = children[i];
+        setLine(elem->getLine());
         String tagName = elem->getName();
 
         //########## DESCRIPTION
@@ -8196,7 +8613,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);
@@ -8218,6 +8635,12 @@ bool Make::parseFile()
             //more work than targets[tname]=target, but avoids default allocator
             targets.insert(std::make_pair<String, Target>(tname, target));
             }
+        //######### none of the above
+        else
+            {
+            error("unknown toplevel tag: <%s>", tagName.c_str());
+            return false;
+            }
 
         }
 
@@ -8337,7 +8760,7 @@ typedef buildtool::String String;
 /**
  *  Format an error message in printf() style
  */
-static void error(char *fmt, ...)
+static void error(const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
@@ -8377,7 +8800,7 @@ static bool parseProperty(const String &s, String &name, String &val)
 /**
  * Compare a buffer with a key, for the length of the key
  */
-static bool sequ(const String &buf, char *key)
+static bool sequ(const String &buf, const char *key)
 {
     int len = buf.size();
     for (int i=0 ; key[i] && i<len ; i++)
@@ -8511,7 +8934,7 @@ static bool depTest()
     deptool.setSourceDirectory("/dev/ink/inkscape/src");
     if (!deptool.generateDependencies("build.dep"))
         return false;
-    std::vector<buildtool::DepRec> res =
+    std::vector<buildtool::FileRec> res =
            deptool.loadDepFile("build.dep");
     if (res.size() == 0)
         return false;