Index: trunk/ippTools/src/chiptool.c
===================================================================
--- trunk/ippTools/src/chiptool.c	(revision 17856)
+++ trunk/ippTools/src/chiptool.c	(revision 17859)
@@ -45,4 +45,6 @@
 static bool unmaskedMode(pxConfig *config);
 static bool unblockMode(pxConfig *config);
+static bool pendingcleanupMode(pxConfig *config);
+static bool donecleanupMode(pxConfig *config);
 
 static bool chipProcessedCompleteExp(pxConfig *config);
@@ -76,4 +78,6 @@
         MODECASE(CHIPTOOL_MODE_UNMASKED,                unmaskedMode);
         MODECASE(CHIPTOOL_MODE_UNBLOCK,                 unblockMode);
+        MODECASE(CHIPTOOL_MODE_PENDINGCLEANUP,          pendingcleanupMode);
+        MODECASE(CHIPTOOL_MODE_DONECLEANUP,             donecleanupMode);
         default:
             psAbort("invalid option (this should not happen)");
@@ -936,4 +940,138 @@
 
 
+static bool pendingcleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("chiptool_pendingcleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!convertIdToStr(output)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to convert id fields into a strings");
+        psFree(output);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipPendingCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
+static bool donecleanupMode(pxConfig *config)
+{
+    PS_ASSERT_PTR_NON_NULL(config, NULL);
+
+    PXOPT_LOOKUP_U64(limit, config->args, "-limit", false, false);
+    PXOPT_LOOKUP_BOOL(simple, config->args, "-simple", false);
+
+    psMetadata *where = psMetadataAlloc();
+    PXOPT_COPY_STR(config->args, where, "-label", "label", "==");
+
+    psString query = pxDataGet("chiptool_donecleanup.sql");
+    if (!query) {
+        psError(PXTOOLS_ERR_DATA, false, "failed to retreive SQL statement");
+        return false;
+    }
+
+    if (where && psListLength(where->list)) {
+        psString whereClause = psDBGenerateWhereConditionSQL(where, NULL);
+        psStringAppend(&query, " AND %s", whereClause);
+        psFree(whereClause);
+    }
+    psFree(where);
+
+    // treat limit == 0 as "no limit"
+    if (limit) {
+        psString limitString = psDBGenerateLimitSQL(limit);
+        psStringAppend(&query, " %s", limitString);
+        psFree(limitString);
+    }
+
+    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) {
+        psError(PS_ERR_UNKNOWN, false, "database error");
+        return false;
+    }
+    if (!psArrayLength(output)) {
+        psTrace("chiptool", PS_LOG_INFO, "no rows found");
+        psFree(output);
+        return true;
+    }
+
+    if (!convertIdToStr(output)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to convert id fields into a strings");
+        psFree(output);
+        return false;
+    }
+
+    // negative simple so the default is true
+    if (!ippdbPrintMetadatas(stdout, output, "chipDoneCleanup", !simple)) {
+        psError(PS_ERR_UNKNOWN, false, "failed to print array");
+        psFree(output);
+        return false;
+    }
+
+    psFree(output);
+
+    return true;
+}
+
+
 static bool chipProcessedCompleteExp(pxConfig *config)
 {
Index: trunk/ippTools/src/chiptool.h
===================================================================
--- trunk/ippTools/src/chiptool.h	(revision 17856)
+++ trunk/ippTools/src/chiptool.h	(revision 17859)
@@ -2,5 +2,5 @@
  * chiptool.h
  *
- * Copyright (C) 2006  Joshua Hoblitt
+ * Copyright (C) 2006-2008  Joshua Hoblitt
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -36,5 +36,7 @@
     CHIPTOOL_MODE_UNMASKED,
     CHIPTOOL_MODE_UNBLOCK,
-    CHIPTOOL_MODE_RETRYPROCESSEDIMFILE
+    CHIPTOOL_MODE_RETRYPROCESSEDIMFILE,
+    CHIPTOOL_MODE_PENDINGCLEANUP,
+    CHIPTOOL_MODE_DONECLEANUP,
 } chiptoolMode;
 
Index: trunk/ippTools/src/chiptoolConfig.c
===================================================================
--- trunk/ippTools/src/chiptoolConfig.c	(revision 17856)
+++ trunk/ippTools/src/chiptoolConfig.c	(revision 17859)
@@ -271,18 +271,45 @@
     psMetadataAddStr(unblockArgs, PS_LIST_TAIL, "-label",  0,            "name of a label to unmask (required)", NULL);
 
+    // -pendingcleanup
+    psMetadata *pendingcleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingcleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(pendingcleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(pendingcleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
+    // -doneclenaup
+    psMetadata *donecleanupArgs = psMetadataAlloc();
+    psMetadataAddStr(donecleanupArgs, PS_LIST_TAIL, "-label",  0,            "list blocks for specified label", NULL);
+    psMetadataAddBool(donecleanupArgs, PS_LIST_TAIL, "-simple",  0,            "use the simple output format", false);
+    psMetadataAddU64(donecleanupArgs, PS_LIST_TAIL, "-limit",  0,            "limit result set to N items", 0);
+
     psMetadata *argSets = psMetadataAlloc();
     psMetadata *modes = psMetadataAlloc();
 
-    PXOPT_ADD_MODE("-queue",                 "create runs from raw exposures",        CHIPTOOL_MODE_QUEUE,    queueArgs);
-    PXOPT_ADD_MODE("-updaterun",             "change chip run properties",        CHIPTOOL_MODE_UPDATERUN, updaterunArgs);
-    PXOPT_ADD_MODE("-pendingimfile",         "show pending imfiles",        CHIPTOOL_MODE_PENDINGIMFILE,  pendingimfileArgs);
-    PXOPT_ADD_MODE("-addprocessedimfile",    "add a processed imfile",        CHIPTOOL_MODE_ADDPROCESSEDIMFILE,addprocessedimfileArgs);
-    PXOPT_ADD_MODE("-processedimfile",       "show processed imfiles",        CHIPTOOL_MODE_PROCESSEDIMFILE, processedimfileArgs);
-    PXOPT_ADD_MODE("-updateprocessedimfile", "change procesed imfile properties", CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,    updateprocessedimfileArgs);
-    PXOPT_ADD_MODE("-revertprocessedimfile", "undo a processed imfile", CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,    revertprocessedimfileArgs);
-    PXOPT_ADD_MODE("-block",                 "set a label block", CHIPTOOL_MODE_BLOCK,          blockArgs);
-    PXOPT_ADD_MODE("-masked",                "show blocked labels", CHIPTOOL_MODE_MASKED,         maskedArgs);
-    PXOPT_ADD_MODE("-unmasked",              "", CHIPTOOL_MODE_UNMASKED,       unmaskedArgs);
-    PXOPT_ADD_MODE("-unblock",               "remove a label block", CHIPTOOL_MODE_UNBLOCK,        unblockArgs);
+    PXOPT_ADD_MODE("-queue",                "create runs from raw exposures",
+        CHIPTOOL_MODE_QUEUE,                queueArgs);
+    PXOPT_ADD_MODE("-updaterun",            "change chip run properties",
+        CHIPTOOL_MODE_UPDATERUN,            updaterunArgs);
+    PXOPT_ADD_MODE("-pendingimfile",        "show pending imfiles",
+        CHIPTOOL_MODE_PENDINGIMFILE,        pendingimfileArgs);
+    PXOPT_ADD_MODE("-addprocessedimfile",   "add a processed imfile",
+        CHIPTOOL_MODE_ADDPROCESSEDIMFILE,   addprocessedimfileArgs);
+    PXOPT_ADD_MODE("-processedimfile",      "show processed imfiles",
+        CHIPTOOL_MODE_PROCESSEDIMFILE,      processedimfileArgs);
+    PXOPT_ADD_MODE("-updateprocessedimfile","change procesed imfile properties",
+        CHIPTOOL_MODE_UPDATEPROCESSEDIMFILE,updateprocessedimfileArgs);
+    PXOPT_ADD_MODE("-revertprocessedimfile","undo a processed imfile",
+        CHIPTOOL_MODE_REVERTPROCESSEDIMFILE,revertprocessedimfileArgs);
+    PXOPT_ADD_MODE("-block",                "set a label block",
+        CHIPTOOL_MODE_BLOCK,                blockArgs);
+    PXOPT_ADD_MODE("-masked",               "show blocked labels",
+        CHIPTOOL_MODE_MASKED,               maskedArgs);
+    PXOPT_ADD_MODE("-unmasked",             "",
+        CHIPTOOL_MODE_UNMASKED,             unmaskedArgs);
+    PXOPT_ADD_MODE("-unblock",              "remove a label block",
+        CHIPTOOL_MODE_UNBLOCK,              unblockArgs);
+    PXOPT_ADD_MODE("-pendingcleanup",       "show runs that need to be cleaned up",
+        CHIPTOOL_MODE_PENDINGCLEANUP,       pendingcleanupArgs);
+    PXOPT_ADD_MODE("-donecleanup",          "show runs that have been cleaned",
+        CHIPTOOL_MODE_DONECLEANUP,          donecleanupArgs);
 
     if (!pxGetOptions(stderr, argc, argv, config, modes, argSets)) {
