Code

2geomify the static defined hatchcircles of dropper tool, dyna draw and tweak tool.
[inkscape.git] / buildtool.cpp
index 471a8194cac220c321b6f9e496377405ea07122a..c3b0a29530cc9b8e079104e02b387fca4b9ac9b3 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Authors:
  *   Bob Jamison
+ *   Jasper van de Gronde
  *
  * Copyright (C) 2006-2008 Bob Jamison
  *
@@ -38,7 +39,7 @@
  *
  */
 
-#define BUILDTOOL_VERSION  "BuildTool v0.9.3"
+#define BUILDTOOL_VERSION  "BuildTool v0.9.5"
 
 #include <stdio.h>
 #include <fcntl.h>
@@ -54,6 +55,8 @@
 #include <map>
 #include <set>
 #include <vector>
+#include <algorithm>
+
 
 #ifdef __WIN32__
 #include <windows.h>
@@ -688,7 +691,7 @@ static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *s
             return cur;
     }                 
     case OP_WB:
-        if(str == exp->_bol && !isspace(*str)
+        if((str == exp->_bol && !isspace(*str))
          || (str == exp->_eol && !isspace(*(str-1)))
          || (!isspace(*str) && isspace(*(str+1)))
          || (isspace(*str) && !isspace(*(str+1))) ) {
@@ -2776,7 +2779,7 @@ public:
     /**
      *
      */
-    String getDirectory()
+    String getDirectory() const
         { return directory; }
         
     /**
@@ -2794,7 +2797,7 @@ public:
     /**
      *
      */
-    std::vector<String> getFiles()
+    std::vector<String> getFiles() const
         { return files; }
         
     /**
@@ -2806,7 +2809,7 @@ public:
     /**
      *
      */
-    std::vector<String> getIncludes()
+    std::vector<String> getIncludes() const
         { return includes; }
         
     /**
@@ -2818,19 +2821,19 @@ public:
     /**
      *
      */
-    std::vector<String> getExcludes()
+    std::vector<String> getExcludes() const
         { return excludes; }
         
     /**
      *
      */
-    unsigned int size()
+    unsigned int size() const
         { return files.size(); }
         
     /**
      *
      */
-    String operator[](int index)
+    String operator[](int index) const
         { return files[index]; }
         
     /**
@@ -3864,6 +3867,9 @@ static String win32LastError()
 
 
 
+
+#ifdef __WIN32__
+
 /**
  * Execute a system call, using pipes to send data to the
  * program's stdin,  and reading stdout and stderr.
@@ -3880,7 +3886,6 @@ bool MakeBase::executeCommand(const String &command,
     outbuf.clear();
     errbuf.clear();
     
-#ifdef __WIN32__
 
     /*
     I really hate having win32 code in this program, but the
@@ -4049,37 +4054,136 @@ bool MakeBase::executeCommand(const String &command,
 
     return ret;
 
-#else //do it unix-style
+} 
+
+#else  /*do it unix style*/
+
+#include <sys/wait.h>
+
+
 
-    String pipeCommand = command;
-    pipeCommand.append("  2>&1");
-    String s;
-    FILE *f = popen(pipeCommand.c_str(), "r");
-    int errnum = 0;
-    if (f)
+/**
+ * Execute a system call, using pipes to send data to the
+ * program's stdin,  and reading stdout and stderr.
+ */
+bool MakeBase::executeCommand(const String &command,
+                              const String &inbuf,
+                              String &outbuf,
+                              String &errbuf)
+{
+
+    status("============ cmd ============\n%s\n=============================",
+                command.c_str());
+
+    outbuf.clear();
+    errbuf.clear();
+    
+
+    int outfds[2];
+    if (pipe(outfds) < 0)
+        return false;
+    int errfds[2];
+    if (pipe(errfds) < 0)
+        return false;
+    int pid = fork();
+    if (pid < 0)
+        {
+        close(outfds[0]);
+        close(outfds[1]);
+        close(errfds[0]);
+        close(errfds[1]);
+        error("launch of command '%s' failed : %s",
+             command.c_str(), strerror(errno));
+        return false;
+        }
+    else if (pid > 0) // parent
+        {
+        close(outfds[1]);
+        close(errfds[1]);
+        }
+    else // == 0, child
         {
-        while (true)
+        close(outfds[0]);
+        dup2(outfds[1], STDOUT_FILENO);
+        close(outfds[1]);
+        close(errfds[0]);
+        dup2(errfds[1], STDERR_FILENO);
+        close(errfds[1]);
+
+        char *args[4];
+        args[0] = (char *)"sh";
+        args[1] = (char *)"-c";
+        args[2] = (char *)command.c_str();
+        args[3] = NULL;
+        execv("/bin/sh", args);
+        exit(EXIT_FAILURE);
+        }
+
+    String outb;
+    String errb;
+
+    int outRead = outfds[0];
+    int errRead = errfds[0];
+    int max = outRead;
+    if (errRead > max)
+        max = errRead;
+
+    bool outOpen = true;
+    bool errOpen = true;
+
+    while (outOpen || errOpen)
+        {
+        char ch;
+        fd_set fdset;
+        FD_ZERO(&fdset);
+        if (outOpen)
+            FD_SET(outRead, &fdset);
+        if (errOpen)
+            FD_SET(errRead, &fdset);
+        int ret = select(max+1, &fdset, NULL, NULL, NULL);
+        if (ret < 0)
+            break;
+        if (FD_ISSET(outRead, &fdset))
             {
-            int ch = fgetc(f);
-            if (ch < 0)
-                break;
-            s.push_back((char)ch);
+            if (read(outRead, &ch, 1) <= 0)
+                { outOpen = false; }
+            else if (ch <= 0)
+                { /* outOpen = false; */ }
+            else
+                { outb.push_back(ch); }
+            }
+        if (FD_ISSET(errRead, &fdset))
+            {
+            if (read(errRead, &ch, 1) <= 0)
+                { errOpen = false; }
+            else if (ch <= 0)
+                { /* errOpen = false; */ }
+            else
+                { errb.push_back(ch); }
             }
-        errnum = pclose(f);
         }
-    outbuf = s;
-    if (errnum != 0)
+
+    int childReturnValue;
+    wait(&childReturnValue);
+
+    close(outRead);
+    close(errRead);
+
+    outbuf = outb;
+    errbuf = errb;
+
+    if (childReturnValue != 0)
         {
         error("exec of command '%s' failed : %s",
-             command.c_str(), strerror(errno));
+             command.c_str(), strerror(childReturnValue));
         return false;
         }
-    else
-        return true;
 
-#endif
+    return true;
 } 
 
+#endif
+
 
 
 
@@ -4491,10 +4595,12 @@ bool MakeBase::evalBool(const String &s, bool defaultVal)
     if (s.size()==0)
         return defaultVal;
     String val = eval(s, "false");
-    if (s == "true" || s == "TRUE")
+    if (val.size()==0)
+        return defaultVal;
+    if (val == "true" || val == "TRUE")
         return true;
     else
-        return defaultVal;
+        return false;
 }
 
 
@@ -5302,7 +5408,11 @@ bool PkgConfig::query(const String &pkgName)
     fname.append(".pc");
 
     if (!readFile(fname))
+        {
+        error("Cannot find package '%s'. Do you have it installed?",
+                       pkgName.c_str());
         return false;
+        }
     
     return true;
 }
@@ -6265,6 +6375,8 @@ public:
         TASK_NONE,
         TASK_CC,
         TASK_COPY,
+        TASK_CXXTEST_PART,
+        TASK_CXXTEST_ROOT,
         TASK_DELETE,
         TASK_ECHO,
         TASK_JAR,
@@ -6970,6 +7082,208 @@ private:
 };
 
 
+/**
+ * Generate CxxTest files
+ */
+class TaskCxxTestPart: public Task
+{
+public:
+
+    TaskCxxTestPart(MakeBase &par) : Task(par)
+         {
+         type    = TASK_CXXTEST_PART;
+         name    = "cxxtestpart";
+         }
+
+    virtual ~TaskCxxTestPart()
+        {}
+
+    virtual bool execute()
+        {
+        if (!listFiles(parent, fileSet))
+            return false;
+        String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
+                
+        String fullDest = parent.resolve(parent.eval(destPathOpt, "."));
+        String cmd = parent.eval(commandOpt, "cxxtestgen.py");
+        cmd.append(" --part -o ");
+        cmd.append(fullDest);
+
+        unsigned int newFiles = 0;
+        for (unsigned int i=0 ; i<fileSet.size() ; i++)
+            {
+            String fileName = fileSet[i];
+            if (getSuffix(fileName) != "h")
+                continue;
+            String sourcePath;
+            if (fileSetDir.size()>0)
+                {
+                sourcePath.append(fileSetDir);
+                sourcePath.append("/");
+                }
+            sourcePath.append(fileName);
+            String fullSource = parent.resolve(sourcePath);
+
+            cmd.append(" ");
+            cmd.append(fullSource);
+            if (isNewerThan(fullSource, fullDest)) newFiles++;
+            }
+        
+        if (newFiles>0) {
+            size_t const lastSlash = fullDest.find_last_of('/');
+            if (lastSlash != fullDest.npos) {
+                String directory(fullDest, 0, lastSlash);
+                if (!createDirectory(directory))
+                    return false;
+            }
+
+            String outString, errString;
+            if (!executeCommand(cmd.c_str(), "", outString, errString))
+                {
+                error("<cxxtestpart> problem: %s", errString.c_str());
+                return false;
+                }
+        }
+
+        return true;
+        }
+
+    virtual bool parse(Element *elem)
+        {
+        if (!parent.getAttribute(elem, "command", commandOpt))
+            return false;
+        if (!parent.getAttribute(elem, "out", destPathOpt))
+            return false;
+            
+        std::vector<Element *> children = elem->getChildren();
+        for (unsigned int i=0 ; i<children.size() ; i++)
+            {
+            Element *child = children[i];
+            String tagName = child->getName();
+            if (tagName == "fileset")
+                {
+                if (!parseFileSet(child, parent, fileSet))
+                    return false;
+                }
+            }
+        return true;
+        }
+
+private:
+
+    String  commandOpt;
+    String  destPathOpt;
+    FileSet fileSet;
+
+};
+
+
+/**
+ * Generate the CxxTest root file
+ */
+class TaskCxxTestRoot: public Task
+{
+public:
+
+    TaskCxxTestRoot(MakeBase &par) : Task(par)
+         {
+         type    = TASK_CXXTEST_ROOT;
+         name    = "cxxtestroot";
+         }
+
+    virtual ~TaskCxxTestRoot()
+        {}
+
+    virtual bool execute()
+        {
+        if (!listFiles(parent, fileSet))
+            return false;
+        String fileSetDir = parent.eval(fileSet.getDirectory(), ".");
+        unsigned int newFiles = 0;
+                
+        String fullDest = parent.resolve(parent.eval(destPathOpt, "."));
+        String cmd = parent.eval(commandOpt, "cxxtestgen.py");
+        cmd.append(" --root -o ");
+        cmd.append(fullDest);
+        String templateFile = parent.eval(templateFileOpt, "");
+        if (templateFile.size()>0) {
+            String fullTemplate = parent.resolve(templateFile);
+            cmd.append(" --template=");
+            cmd.append(fullTemplate);
+            if (isNewerThan(fullTemplate, fullDest)) newFiles++;
+        }
+
+        for (unsigned int i=0 ; i<fileSet.size() ; i++)
+            {
+            String fileName = fileSet[i];
+            if (getSuffix(fileName) != "h")
+                continue;
+            String sourcePath;
+            if (fileSetDir.size()>0)
+                {
+                sourcePath.append(fileSetDir);
+                sourcePath.append("/");
+                }
+            sourcePath.append(fileName);
+            String fullSource = parent.resolve(sourcePath);
+
+            cmd.append(" ");
+            cmd.append(fullSource);
+            if (isNewerThan(fullSource, fullDest)) newFiles++;
+            }
+        
+        if (newFiles>0) {
+            size_t const lastSlash = fullDest.find_last_of('/');
+            if (lastSlash != fullDest.npos) {
+                String directory(fullDest, 0, lastSlash);
+                if (!createDirectory(directory))
+                    return false;
+            }
+
+            String outString, errString;
+            if (!executeCommand(cmd.c_str(), "", outString, errString))
+                {
+                error("<cxxtestroot> problem: %s", errString.c_str());
+                return false;
+                }
+        }
+
+        return true;
+        }
+
+    virtual bool parse(Element *elem)
+        {
+        if (!parent.getAttribute(elem, "command", commandOpt))
+            return false;
+        if (!parent.getAttribute(elem, "template", templateFileOpt))
+            return false;
+        if (!parent.getAttribute(elem, "out", destPathOpt))
+            return false;
+            
+        std::vector<Element *> children = elem->getChildren();
+        for (unsigned int i=0 ; i<children.size() ; i++)
+            {
+            Element *child = children[i];
+            String tagName = child->getName();
+            if (tagName == "fileset")
+                {
+                if (!parseFileSet(child, parent, fileSet))
+                    return false;
+                }
+            }
+        return true;
+        }
+
+private:
+
+    String  commandOpt;
+    String  templateFileOpt;
+    String  destPathOpt;
+    FileSet fileSet;
+
+};
+
+
 /**
  *
  */
@@ -8372,6 +8686,10 @@ Task *Task::createTask(Element *elem, int lineNr)
         task = new TaskCC(parent);
     else if (tagName == "copy")
         task = new TaskCopy(parent);
+    else if (tagName == "cxxtestpart")
+        task = new TaskCxxTestPart(parent);
+    else if (tagName == "cxxtestroot")
+        task = new TaskCxxTestRoot(parent);
     else if (tagName == "delete")
         task = new TaskDelete(parent);
     else if (tagName == "echo")