Index: trunk/ippTools/src/pztoolConfig.c
===================================================================
--- trunk/ippTools/src/pztoolConfig.c	(revision 7037)
+++ trunk/ippTools/src/pztoolConfig.c	(revision 7921)
@@ -6,5 +6,7 @@
 
 #include "pxtools.h"
+#include "pzsearch.h"
 
+// this function can not fail -- exits on error
 pxConfig *pzsearchConfig(pxConfig *config, int argc, char **argv) {
     if (!config) {
@@ -12,6 +14,6 @@
     }
 
+    // setup site config
     config->modules = pmConfigRead(&argc, argv);
-
     if (! config->modules) {
         psError(PS_ERR_UNKNOWN, false, "Can't find site configuration!\n");
@@ -19,54 +21,59 @@
     }
 
-    int N;
-    config->mode = PX_MODE_NONE;
-    if ((N = psArgumentGet (argc, argv, "-seen"))) {
-        psArgumentRemove (N, &argc, argv);
-        if (config->mode) {
-            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
-        }
-        config->mode = PX_MODE_SEEN;
-    }
-    if ((N = psArgumentGet (argc, argv, "-pending"))) {
-        psArgumentRemove (N, &argc, argv);
-        if (config->mode) {
-            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
-        }
-        config->mode = PX_MODE_PENDING;
-    }
-    if ((N = psArgumentGet (argc, argv, "-copydone"))) {
-        psArgumentRemove (N, &argc, argv);
-        if (config->mode) {
-            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
-        }
-        config->mode = PX_MODE_COPYDONE;
-    }
+    // -seen
+    psMetadata *seenArgs = psMetadataAlloc();
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-exp_id",  0,
+        "define exposure ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-inst",  0,
+        "define camera ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-telescope",  0,
+        "define telescope ID", NULL); 
+    psMetadataAddStr(seenArgs, PS_LIST_TAIL, "-exp_type",  0,
+        "define exposure type", NULL); 
+    
+    // -pending
+    psMetadata *pendingArgs = psMetadataAlloc();
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-exp_id",  0,
+        "define exposure ID", NULL); 
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-inst",  0,
+        "define camera ID", NULL); 
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-telescope",  0,
+        "define telescope ID", NULL); 
+    psMetadataAddStr(pendingArgs, PS_LIST_TAIL, "-exp_type",  0,
+        "define exposure type", NULL); 
 
-    // paul's argument parsing convention requires: -key value
-    // Parse other command-line arguments
-    psMetadata *args = psMetadataAlloc();
-    psMetadataAddStr(args , PS_LIST_TAIL, "-seen", 0,
-        "list all uncopied exposure IDs", "");
-    psMetadataAddStr(args , PS_LIST_TAIL, "-pending",  0,
-        "list all image files pending download", "");
-    psMetadataAddStr(args , PS_LIST_TAIL, "-copydone",  0,
-        "indicate that an image file has been downloaded", "");
-
-    // -copydone search
+    // -copydone
     psMetadata *copydoneArgs = psMetadataAlloc();
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-exp_id",  0,
-        "define exposure ID", "");
+        "define exposure ID", NULL); 
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class",  0,
-        "define class", "");
+        "define class", NULL);
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-class_id",  0,
-        "define class_id", "");
+        "define class_id", NULL);
     psMetadataAddStr(copydoneArgs, PS_LIST_TAIL, "-suri",  0,
-        "define storage uri", "");
+        "define storage uri", NULL);
+
+#define PXTOOL_MODE(option, modeval, argset) \
+{ \
+    int N = 0; \
+    if ((N = psArgumentGet (argc, argv, option))) { \
+        psArgumentRemove (N, &argc, argv); \
+        if (config->mode) { \
+            psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed"); \
+        } \
+        config->mode = modeval; \
+        config->args = psMemIncrRefCounter(argset); \
+    } \
+}
+
+    PXTOOL_MODE("-seen",            PZSEARCH_MODE_SEEN,         seenArgs);
+    PXTOOL_MODE("-pending",         PZSEARCH_MODE_PENDING,      pendingArgs);
+    PXTOOL_MODE("-copydone",        PZSEARCH_MODE_COPYDONE,     copydoneArgs);
 
     bool argErr = false;
-    if (config->mode == PX_MODE_NONE) {
+    if (config->mode == PZSEARCH_MODE_NONE) {
         argErr = true;
         fprintf (stderr, "mode argument is required\n");
-    } else if (! psArgumentParse(args, &argc, argv) || argc != 1) {
+    } else if (! psArgumentParse(config->args, &argc, argv) || argc != 1) {
         argErr = true;
         fprintf (stderr, "error parsing arguments\n");
@@ -77,62 +84,68 @@
         printf("Usage: %s <mode> [<options>]\n\n", argv[0]);
         printf(" <mode> : -seen | -pending | -copydone\n\n");
+
+        fprintf (stdout, "-seen ");
+        psArgumentHelp(seenArgs);
+        psFree(seenArgs);
+
+        fprintf (stdout, "-pending ");
+        psArgumentHelp(pendingArgs);
+        psFree(pendingArgs);
+
         fprintf (stdout, "-copydone ");
         psArgumentHelp(copydoneArgs);
-        psFree(args);
         psFree(copydoneArgs);
-        exit(EXIT_FAILURE);
+
+        goto FAIL;
     }
 
+    psFree(seenArgs);
+    psArgumentHelp(pendingArgs);
     psFree(copydoneArgs);
 
-    // XXX why is "" being returned when -[foo] isn't specified?
-#define EMPTY_TO_NULL_STRING(var) \
-    if (var != NULL && strcmp(var, "") == 0) { \
-        var = NULL; \
+    // setup search criterion
+#define addWhereStr(name) \
+{ \
+    psString str = NULL; \
+    bool status = false; \
+    if ((str = psMetadataLookupStr(&status, config->args, "-" #name))) { \
+        if (!psMetadataAddStr(config->where, PS_LIST_TAIL, #name, 0, "==", str)) {\
+            psError(PS_ERR_UNKNOWN, false, "failed to add item " #name); \
+            goto FAIL; \
+        } \
+    } \
+}
+
+    // generate SQL where claus
+    config->where = psMetadataAlloc();
+
+    addWhereStr(exp_id); 
+    addWhereStr(class); 
+    addWhereStr(class_id); 
+
+    if (config->where->list->n < 1) {
+        psFree(config->where);
+        config->where = NULL;
     }
 
-    config->args = args;
-
-if (config->mode == PX_MODE_COPYDONE) {
-    psMetadata *where = psMetadataAlloc();
-
-    bool status;
-    psString str;
-    if ((str = psMetadataLookupStr(&status, args, "-exp_id"))) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "exp_id", 0, "==", str)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item exp_id");
-            psFree(where);
-            exit(EXIT_FAILURE);
-        }
-    }
-    if ((str = psMetadataLookupStr(&status, args, "-class"))) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "class", 0, "==", str)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item class");
-            psFree(where);
-            exit(EXIT_FAILURE);
-        }
-    }
-    if ((str = psMetadataLookupStr(&status, args, "-class_id"))) {
-        if (!psMetadataAddStr(where, PS_LIST_TAIL, "class_id", 0, "==", str)) {
-            psError(PS_ERR_UNKNOWN, false, "failed to add item class_id");
-            psFree(where);
-            exit(EXIT_FAILURE);
-        }
-    }
-
-    if (where->list->n < 1) {
-        psFree(where);
-        where = NULL;
-    }
-    config->where = where;
-}
-
     // define Database handle, if used
+    // do this last so we don't setup a connection before CLI options are
+    // validated
     config->dbh = pmConfigDB(config->modules);
     if (!config->dbh) {
         psError(PS_ERR_UNKNOWN, false, "Can't configure database");
-        exit(EXIT_FAILURE);
+        goto FAIL;
     }
 
+    // save argv/argc
+    config->argv = argv;
+    config->argc = argc;
+
     return config;
+
+FAIL:
+    psFree(config);
+    pmConfigDone();
+    psLibFinalize();
+    exit(EXIT_FAILURE);
 }
