Index: trunk/ippTools/src/magictool.c
===================================================================
--- trunk/ippTools/src/magictool.c	(revision 18522)
+++ trunk/ippTools/src/magictool.c	(revision 18523)
@@ -36,4 +36,5 @@
 static bool addinputskyfileMode(pxConfig *config);
 static bool inputskyfileMode(pxConfig *config);
+static bool totreeMode(pxConfig *config);
 static bool inputtreeMode(pxConfig *config);
 static bool toprocessMode(pxConfig *config);
@@ -63,9 +64,10 @@
 
     switch (config->mode) {
-        MODECASE(MAGICTOOL_MODE_DEFINEBYQUERY,          definebyqueryMode);
+        MODECASE(MAGICTOOL_MODE_DEFINEBYQUERY,  definebyqueryMode);
         MODECASE(MAGICTOOL_MODE_DEFINERUN,      definerunMode);
         MODECASE(MAGICTOOL_MODE_UPDATERUN,      updaterunMode);
         MODECASE(MAGICTOOL_MODE_ADDINPUTSKYFILE,addinputskyfileMode);
         MODECASE(MAGICTOOL_MODE_INPUTSKYFILE,   inputskyfileMode);
+        MODECASE(MAGICTOOL_MODE_TOTREE,         totreeMode);
         MODECASE(MAGICTOOL_MODE_INPUTTREE,      inputtreeMode);
         MODECASE(MAGICTOOL_MODE_TOPROCESS,      toprocessMode);
@@ -411,96 +413,13 @@
 
 
-static bool inputtreeMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    // required
-    PXOPT_LOOKUP_STR(magic_id, config->args, "-magic_id", true, false);
-    PXOPT_LOOKUP_STR(dep_file, config->args, "-dep_file", true, false);
-
-    if (!parseAndInsertNodeDeps(config, (psS64)atoll(magic_id), dep_file)) {
-        psError(PS_ERR_UNKNOWN, false, "failed to parse file");
-        return false;
-    }
-
-    return true;
-}
-
-
-bool findBaseNodes(void *arg, pxNode *node)
-{
-    bool status = false;
-    psS64 done = psMetadataLookupS64(&status, node->data, "done");
-    if (!status) {
-        psAbort("failed to lookup value for done column");
-    }
-
-    if ((!pxNodeHasChildren(node)) && (!done)) {
-        // if this node has no child and it's not 'done', then push it's data
-        // onto the void *array
-        psArrayAdd((psArray *)arg, 0, node->data);
-        return false;
-    }
-
-    return true;
-}
-
-
-bool findReadyNodes(void *arg, pxNode *node)
-{
-
-    if (pxNodeHasChildren(node)) {
-        psListIterator *iter = psListIteratorAlloc(node->children, 0, false);
-        psMetadata *work = psMetadataCopy(NULL, node->data);
-        psMetadataRemoveKey(work, "dep");
-        psMetadataRemoveKey(work, "done");
-        psMetadataRemoveKey(work, "uri");
-        pxNode *child = NULL;
-        while ((child = psListGetAndIncrement(iter))) {
-            psMetadata *data = child->data;
-
-            bool status = false;
-            psS32 done = psMetadataLookupS32(&status, data, "done");
-            if (!status) {
-                psAbort("failed to lookup value for done column");
-            }
-
-            if (!done) {
-                // if a child isn't "done", give up on this node and continue
-                // to crawl the tree
-                psFree(iter);
-                psFree(work);
-                return true;
-            }
-
-            char *uri = psMetadataLookupStr(&status, data, "uri");
-            if (!status) {
-                psAbort("failed to lookup value for uri column");
-            }
-
-            psMetadataAddStr(work, PS_LIST_TAIL, "uri", PS_META_DUPLICATE_OK, NULL, uri);
-
-        }
-        psFree(iter);
-        // if all this nodes children are done, then push it's data onto the
-        // void *array
-        psArrayAdd((psArray *)arg, 0, work);
-        psFree(work);
-        return false;
-    }
-
-    return true;
-}
-
-
-static bool toprocessMode(pxConfig *config)
-{
-    PS_ASSERT_PTR_NON_NULL(config, false);
-
-    PXOPT_LOOKUP_STR(magic_id, config->args, "-magic_id", false, false);
+static bool totreeMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
     PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
 
     // look for "inputs" that need to processed
-    psString query = pxDataGet("magictool_toprocess_inputs.sql");
+    psString query = pxDataGet("magictool_totree.sql");
     if (!query) {
         psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
@@ -508,11 +427,9 @@
     }
 
-    if (magic_id) {
-        psMetadata *where = psMetadataAlloc();
-        psMetadataAddS64(where, PS_LIST_TAIL, "magic_id", 0, "==", (psS64)atoll(magic_id));
-        psString whereClause = psDBGenerateWhereSQL(where, NULL);
-        psFree(where);
-        psStringAppend(&query, " %s", whereClause);
-        psFree(whereClause);
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
     }
 
@@ -540,4 +457,152 @@
     if (!psArrayLength(output)) {
         psTrace("magictool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (psArrayLength(output)) {
+        // negative simple so the default is true
+        if (!ippdbPrintMetadatas(stdout, output, "totree", !simple)) {
+            psError(PS_ERR_UNKNOWN, false, "failed to print array");
+            psFree(output);
+            return false;
+        }
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool inputtreeMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    // required
+    PXOPT_LOOKUP_STR(magic_id, config->args, "-magic_id", true, false);
+    PXOPT_LOOKUP_STR(dep_file, config->args, "-dep_file", true, false);
+
+    if (!parseAndInsertNodeDeps(config, (psS64)atoll(magic_id), dep_file)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to parse file");
+        return false;
+    }
+
+    return true;
+}
+
+
+bool findBaseNodes(void *arg, pxNode *node)
+{
+    bool status = false;
+    psS64 done = psMetadataLookupS64(&status, node->data, "done");
+    if (!status) {
+        psAbort("failed to lookup value for done column");
+    }
+
+    if ((!pxNodeHasChildren(node)) && (!done)) {
+        // if this node has no child and it's not 'done', then push it's data
+        // onto the void *array
+        psArrayAdd((psArray *)arg, 0, node->data);
+        return false;
+    }
+
+    return true;
+}
+
+
+bool findReadyNodes(void *arg, pxNode *node)
+{
+
+    if (pxNodeHasChildren(node)) {
+        psListIterator *iter = psListIteratorAlloc(node->children, 0, false);
+        psMetadata *work = psMetadataCopy(NULL, node->data);
+        psMetadataRemoveKey(work, "dep");
+        psMetadataRemoveKey(work, "done");
+        psMetadataRemoveKey(work, "uri");
+        pxNode *child = NULL;
+        while ((child = psListGetAndIncrement(iter))) {
+            psMetadata *data = child->data;
+
+            bool status = false;
+            psS32 done = psMetadataLookupS32(&status, data, "done");
+            if (!status) {
+                psAbort("failed to lookup value for done column");
+            }
+
+            if (!done) {
+                // if a child isn't "done", give up on this node and continue
+                // to crawl the tree
+                psFree(iter);
+                psFree(work);
+                return true;
+            }
+
+            char *uri = psMetadataLookupStr(&status, data, "uri");
+            if (!status) {
+                psAbort("failed to lookup value for uri column");
+            }
+
+            psMetadataAddStr(work, PS_LIST_TAIL, "uri", PS_META_DUPLICATE_OK, NULL, uri);
+
+        }
+        psFree(iter);
+        // if all this nodes children are done, then push it's data onto the
+        // void *array
+        psArrayAdd((psArray *)arg, 0, work);
+        psFree(work);
+        return false;
+    }
+
+    return true;
+}
+
+
+static bool toprocessMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, false);
+
+    PXOPT_LOOKUP_STR(magic_id, config->args, "-magic_id", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    // look for "inputs" that need to processed
+    psString query = pxDataGet("magictool_toprocess_inputs.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (magic_id) {
+        psMetadata *where = psMetadataAlloc();
+        psMetadataAddS64(where, PS_LIST_TAIL, "magic_id", 0, "==", (psS64)atoll(magic_id));
+        psString whereClause = psDBGenerateWhereSQL(where, NULL);
+        psFree(where);
+        psStringAppend(&query, " %s", whereClause);
+        psFree(whereClause);
+    }
+
+    if (!p_psDBRunQuery(config->dbh, query)) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        psFree(query);
+        return false;
+    }
+    psFree(query);
+
+    psArray *output = p_psDBFetchResult(config->dbh);
+    if (!output) {
+        psErrorCode err = psErrorCodeLast();
+        switch (err) {
+            case PS_ERR_DB_CLIENT:
+                psError(PXTOOLS_ERR_SYS, false, "database error");
+            case PS_ERR_DB_SERVER:
+                psError(PXTOOLS_ERR_PROG, false, "database error");
+            default:
+                psError(PXTOOLS_ERR_PROG, false, "unknown error");
+        }
+
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("magictool", PS_LOG_INFO, "no rows found");
 //        psFree(output);
 //        return true;
