Index: /trunk/ippTools/src/dettoolConfig.c
===================================================================
--- /trunk/ippTools/src/dettoolConfig.c	(revision 13563)
+++ /trunk/ippTools/src/dettoolConfig.c	(revision 13564)
@@ -22,8 +22,38 @@
 #endif
 
+#include <string.h>
+
 #include <psmodules.h>
 
 #include "pxtools.h"
 #include "dettool.h"
+
+#define PXTOOL_MODE(option, comment, modeval, argset) \
+{ \
+    if (!psMetadataAddMetadata(argSets, PS_LIST_TAIL, option, 0, comment, argset)) {;\
+        psError(PS_ERR_UNKNOWN, false, "failed to add argset for %s", option); \
+    } \
+    psFree(argset); \
+\
+    if (!psMetadataAddU32(modes, PS_LIST_TAIL, option, 0, comment, modeval)) {;\
+        psError(PS_ERR_UNKNOWN, false, "failed to add argset for %s", option); \
+    } \
+}
+
+static void printUsage(int argc, char **argv, psMetadata *modes) 
+{
+    printf("Usage: %s <mode> [<options>]\n\n", argv[0]);
+    printf("<mode>:\n");
+
+    psArgumentHelpSimple(stderr, modes);
+}
+
+static void printUsageMode(int argc, char **argv, const char *modeName, psMetadata *argSet) 
+{
+    printf("Usage: %s <mode> [<options>]\n\n", argv[0]);
+    printf("%s:\n", modeName);
+
+    psArgumentHelpSimple(stderr, argSet);
+}
 
 pxConfig *dettoolConfig(pxConfig *config, int argc, char **argv) {
@@ -45,4 +75,7 @@
     psString now = psTimeToISO(time);
     psFree(time);
+
+    psMetadata *argSets = psMetadataAlloc();
+    psMetadata *modes = psMetadataAlloc();
 
     // -pending
@@ -780,109 +813,186 @@
     psFree(now);
 
-
-#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"); \
-            psFree(argset); \
-            psFree(argSets); \
-            psFree(config); \
-            return NULL; \
-        } \
-        config->mode = modeval; \
-        config->args = psMemIncrRefCounter(argset); \
-    } \
-    if (!psMetadataAddMetadata(argSets, PS_LIST_TAIL, option, 0, NULL, argset)) {;\
-        psError(PS_ERR_UNKNOWN, false, "failed to add argset for %s", option); \
-    } \
-    psFree(argset); \
-}
-
-    psMetadata *argSets = psMetadataAlloc();
     // find which mode we're running under
-    PXTOOL_MODE("-pending",         DETTOOL_MODE_PENDING,       pendingArgs);
-    PXTOOL_MODE("-definebytag",     DETTOOL_MODE_DEFINEBYTAG,   definebytagArgs);
-    PXTOOL_MODE("-definebyquery",   DETTOOL_MODE_DEFINEBYQUERY, definebyqueryArgs);
-    PXTOOL_MODE("-definebydetrun",  DETTOOL_MODE_DEFINEBYDETRUN, definebydetrunArgs);
-    PXTOOL_MODE("-raw",             DETTOOL_MODE_RAW,           rawArgs);
-    PXTOOL_MODE("-runs",            DETTOOL_MODE_RUNS,          runsArgs);
-    PXTOOL_MODE("-childlessrun",    DETTOOL_MODE_CHILDLESSRUN,  childlessrunArgs);
-    PXTOOL_MODE("-input",           DETTOOL_MODE_INPUT,         inputArgs);
-    PXTOOL_MODE("-toprocessedimfile", DETTOOL_MODE_TOPROCESSEDIMFILE, toprocessedimfileArgs);
-    PXTOOL_MODE("-addprocessedimfile", DETTOOL_MODE_ADDPROCESSEDIMFILE,  addprocessedimfileArgs);
-    PXTOOL_MODE("-processedimfile", DETTOOL_MODE_PROCESSEDIMFILE, processedimfileArgs);
-    PXTOOL_MODE("-toprocessedexp",  DETTOOL_MODE_TOPROCESSEDEXP,  toprocessedexpArgs);
-    PXTOOL_MODE("-addprocessedexp", DETTOOL_MODE_ADDPROCESSEDEXP, addprocessedexpArgs);
-    PXTOOL_MODE("-processedexp",    DETTOOL_MODE_PROCESSEDEXP, processedexpArgs);
-    PXTOOL_MODE("-tostacked",       DETTOOL_MODE_TOSTACKED,     tostackedArgs);
-    PXTOOL_MODE("-addstacked",      DETTOOL_MODE_ADDSTACKED,    addstackedArgs);
-    PXTOOL_MODE("-stacked",         DETTOOL_MODE_STACKED,       stackedArgs);
-    PXTOOL_MODE("-tonormalize",     DETTOOL_MODE_TONORMALIZE,   tonormalizeArgs);
-    PXTOOL_MODE("-addnormalizedstat",     DETTOOL_MODE_ADDNORMALIZEDSTAT,   addnormstatArgs);
-    PXTOOL_MODE("-tonormalizedstat",      DETTOOL_MODE_TONORMALIZEDSTAT,    tonormstatArgs);
-    PXTOOL_MODE("-addnormalizedimfile", DETTOOL_MODE_ADDNORMALIZEDIMFILE,addnormalizedimfileArgs);
-    PXTOOL_MODE("-normalizedimfile",DETTOOL_MODE_NORMALIZEDIMFILE, normalizedimfileArgs);
-    PXTOOL_MODE("-tonormalizedexp", DETTOOL_MODE_TONORMALIZEDEXP, tonormalizedexpArgs);
-    PXTOOL_MODE("-addnormalizedexp", DETTOOL_MODE_ADDNORMALIZEDEXP, addnormalizedexpArgs);
-    PXTOOL_MODE("-normalizedexp",   DETTOOL_MODE_NORMALIZEDEXP, normalizedexpArgs);
-    PXTOOL_MODE("-toresidimfile",   DETTOOL_MODE_TORESIDIMFILE, toresidimfileArgs);
-    PXTOOL_MODE("-addresidimfile",  DETTOOL_MODE_ADDRESIDIMFILE,  addresidimfileArgs);
-    PXTOOL_MODE("-residimfile",     DETTOOL_MODE_RESIDIMFILE,    residimfileArgs);
-    PXTOOL_MODE("-toresidexp",      DETTOOL_MODE_TORESIDEXP,    toresidexpArgs);
-    PXTOOL_MODE("-addresidexp",     DETTOOL_MODE_ADDRESIDEXP,  addresidexpArgs);
-    PXTOOL_MODE("-residexp",        DETTOOL_MODE_RESIDEXP,     residexpArgs);
-    PXTOOL_MODE("-residdetrun",     DETTOOL_MODE_RESIDDETRUN,  residdetrunArgs);
-    PXTOOL_MODE("-updateresidexp", DETTOOL_MODE_UPDATERESIDEXP,updateresidexpArgs);
-    PXTOOL_MODE("-adddetrunsummary", DETTOOL_MODE_ADDDETRUNSUMMARY,adddetrunsummaryArgs);
-    PXTOOL_MODE("-detrunsummary", DETTOOL_MODE_DETRUNSUMMARY,detrunsummaryArgs);
-    PXTOOL_MODE("-updatedetrun", DETTOOL_MODE_UPDATEDETRUN, updatedetrunArgs);
-    PXTOOL_MODE("-rerun",           DETTOOL_MODE_RERUN,         rerunArgs);
-    PXTOOL_MODE("-register_detrend", DETTOOL_MODE_REGISTER_DETREND, register_detrendArgs);
-    PXTOOL_MODE("-register_detrend_imfile", DETTOOL_MODE_REGISTER_DETREND_IMFILE, register_detrend_imfileArgs);
-
-    bool argErr = false;
+    PXTOOL_MODE("-pending",         "list active detruns", DETTOOL_MODE_PENDING,       pendingArgs);
+    PXTOOL_MODE("-definebytag",     "", DETTOOL_MODE_DEFINEBYTAG,   definebytagArgs);
+    PXTOOL_MODE("-definebyquery",   "", DETTOOL_MODE_DEFINEBYQUERY, definebyqueryArgs);
+    PXTOOL_MODE("-definebydetrun",  "", DETTOOL_MODE_DEFINEBYDETRUN, definebydetrunArgs);
+    PXTOOL_MODE("-raw",             "", DETTOOL_MODE_RAW,           rawArgs);
+    PXTOOL_MODE("-runs",            "", DETTOOL_MODE_RUNS,          runsArgs);
+    PXTOOL_MODE("-childlessrun",    "", DETTOOL_MODE_CHILDLESSRUN,  childlessrunArgs);
+    PXTOOL_MODE("-input",           "", DETTOOL_MODE_INPUT,         inputArgs);
+    PXTOOL_MODE("-toprocessedimfile", "", DETTOOL_MODE_TOPROCESSEDIMFILE, toprocessedimfileArgs);
+    PXTOOL_MODE("-addprocessedimfile", "", DETTOOL_MODE_ADDPROCESSEDIMFILE,  addprocessedimfileArgs);
+    PXTOOL_MODE("-processedimfile", "", DETTOOL_MODE_PROCESSEDIMFILE, processedimfileArgs);
+    PXTOOL_MODE("-toprocessedexp",  "", DETTOOL_MODE_TOPROCESSEDEXP,  toprocessedexpArgs);
+    PXTOOL_MODE("-addprocessedexp", "", DETTOOL_MODE_ADDPROCESSEDEXP, addprocessedexpArgs);
+    PXTOOL_MODE("-processedexp",    "", DETTOOL_MODE_PROCESSEDEXP, processedexpArgs);
+    PXTOOL_MODE("-tostacked",       "", DETTOOL_MODE_TOSTACKED,     tostackedArgs);
+    PXTOOL_MODE("-addstacked",      "", DETTOOL_MODE_ADDSTACKED,    addstackedArgs);
+    PXTOOL_MODE("-stacked",         "", DETTOOL_MODE_STACKED,       stackedArgs);
+    PXTOOL_MODE("-tonormalize",     "", DETTOOL_MODE_TONORMALIZE,   tonormalizeArgs);
+    PXTOOL_MODE("-addnormalizedstat",     "", DETTOOL_MODE_ADDNORMALIZEDSTAT,   addnormstatArgs);
+    PXTOOL_MODE("-tonormalizedstat",      "", DETTOOL_MODE_TONORMALIZEDSTAT,    tonormstatArgs);
+    PXTOOL_MODE("-addnormalizedimfile", "", DETTOOL_MODE_ADDNORMALIZEDIMFILE,addnormalizedimfileArgs);
+    PXTOOL_MODE("-normalizedimfile","", DETTOOL_MODE_NORMALIZEDIMFILE, normalizedimfileArgs);
+    PXTOOL_MODE("-tonormalizedexp", "", DETTOOL_MODE_TONORMALIZEDEXP, tonormalizedexpArgs);
+    PXTOOL_MODE("-addnormalizedexp", "", DETTOOL_MODE_ADDNORMALIZEDEXP, addnormalizedexpArgs);
+    PXTOOL_MODE("-normalizedexp",   "", DETTOOL_MODE_NORMALIZEDEXP, normalizedexpArgs);
+    PXTOOL_MODE("-toresidimfile",   "", DETTOOL_MODE_TORESIDIMFILE, toresidimfileArgs);
+    PXTOOL_MODE("-addresidimfile",  "", DETTOOL_MODE_ADDRESIDIMFILE,  addresidimfileArgs);
+    PXTOOL_MODE("-residimfile",     "", DETTOOL_MODE_RESIDIMFILE,    residimfileArgs);
+    PXTOOL_MODE("-toresidexp",      "", DETTOOL_MODE_TORESIDEXP,    toresidexpArgs);
+    PXTOOL_MODE("-addresidexp",     "", DETTOOL_MODE_ADDRESIDEXP,  addresidexpArgs);
+    PXTOOL_MODE("-residexp",        "", DETTOOL_MODE_RESIDEXP,     residexpArgs);
+    PXTOOL_MODE("-residdetrun",     "", DETTOOL_MODE_RESIDDETRUN,  residdetrunArgs);
+    PXTOOL_MODE("-updateresidexp", "", DETTOOL_MODE_UPDATERESIDEXP,updateresidexpArgs);
+    PXTOOL_MODE("-adddetrunsummary", "", DETTOOL_MODE_ADDDETRUNSUMMARY,adddetrunsummaryArgs);
+    PXTOOL_MODE("-detrunsummary", "", DETTOOL_MODE_DETRUNSUMMARY,detrunsummaryArgs);
+    PXTOOL_MODE("-updatedetrun", "", DETTOOL_MODE_UPDATEDETRUN, updatedetrunArgs);
+    PXTOOL_MODE("-rerun",           "", DETTOOL_MODE_RERUN,         rerunArgs);
+    PXTOOL_MODE("-register_detrend", "", DETTOOL_MODE_REGISTER_DETREND, register_detrendArgs);
+    PXTOOL_MODE("-register_detrend_imfile", "", DETTOOL_MODE_REGISTER_DETREND_IMFILE, register_detrend_imfileArgs);
+
+
+    // figure out what mode we're running in
+    char *modeName = NULL;
+    psMetadataIterator *iter = psMetadataIteratorAlloc(modes, PS_LIST_HEAD, NULL);
+    psMetadataItem *item = NULL; // Item from iterator
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        int N = 0;
+        if ((N = psArgumentGet(argc, argv, item->name))) {
+            psArgumentRemove(N, &argc, argv);
+            // check for duplicate mode specification
+            if (config->mode) {
+                psError(PS_ERR_UNKNOWN, true, "only one mode selection is allowed");
+                fprintf(stderr, "only one mode selection is allowed\n");
+                printUsage(argc, argv, modes);
+                psFree(argSets);
+                psFree(modes);
+                psFree(config);
+                return NULL;
+            }
+
+            config->mode = item->data.U32;
+            modeName = item->name;
+
+            bool status = false;
+            psMetadata *argset = psMetadataLookupMetadata(&status, argSets, item->name);
+            // make sure we can find the argSet for the sepcified mode
+            if (!status) {
+                psError(PS_ERR_UNKNOWN, true, "can not find arguments for mode");
+                fprintf(stderr, "can not find arugments for mode");
+                psFree(argSets);
+                psFree(modes);
+                psFree(config);
+                return NULL;
+            }
+
+            config->args = psMemIncrRefCounter(argset);
+        }
+
+    }
+
+    psFree(iter);
+    psFree(argSets);
+
+    // make sure we found a mode
     if (config->mode == DETTOOL_MODE_NONE) {
-        argErr = true;
-        fprintf (stderr, "mode argument is required\n");
-    } else {
-        if (! psArgumentParse(config->args, &argc, argv)) {
-            argErr = true;
-            fprintf (stderr, "error parsing arguments\n");
-        }
-        if (argc != 1) {
-            fprintf (stderr, "extra arguments: ");
-            for (int i = 1; i < argc; i++) {
-                fprintf (stderr, "%s ", argv[i]);
-            }
-            fprintf (stderr, "\n");
-            argErr = true;
-        }
-    }
-
-    if (argErr) {
-        printf("\nPan-STARRS Detrend Tool\n");
-        printf("Usage: %s <mode> [<options>]\n\n", argv[0]);
-        printf(" <mode> :\n\n");
-
-        psMetadataIterator *iter = psMetadataIteratorAlloc(argSets, 0, NULL);
-        psMetadataItem *item = NULL;
-        while ((item = psMetadataGetAndIncrement(iter))) {
-            if (!item->type == PS_DATA_METADATA) {
-                psAbort("all options must be specified as a metadata");
-            }
-
-            fprintf(stdout, "%s ", item->name);
-            psArgumentHelp(item->data.md);
-        }
-        psFree(iter);
-        psFree(argSets);
+        psError(PS_ERR_UNKNOWN, true, "mode argument is required");
+        fprintf(stderr, "mode argument is required\n");
+        printUsage(argc, argv, modes);
+
+        psFree(modes);
         psFree(config);
         return NULL;
     }
 
-    psFree(argSets);
+    psFree(modes);
+
+    // actually parse the command line
+    if (!psArgumentParse(config->args, &argc, argv)) {
+        psError(PS_ERR_UNKNOWN, true, "error parsing arguments");
+        fprintf(stderr, "error parsing arguments\n");
+        printUsageMode(argc, argv, modeName, config->args);
+
+        psFree(config);
+        return NULL;
+    }
+
+    // look for left overs on the command line
+    if (argc != 1) {
+        psError(PS_ERR_UNKNOWN, true, "extra arguments: ");
+        fprintf(stderr, "extra arguments: ");
+        for (int i = 1; i < argc; i++) {
+            fprintf (stderr, "%s ", argv[i]);
+        }
+        fprintf(stderr, "\n");
+        printUsageMode(argc, argv, modeName, config->args);
+
+        psFree(config);
+        return NULL;
+    }
+
+    // make sure that all require parameters have been specified
+    iter = psMetadataIteratorAlloc(config->args, PS_LIST_HEAD, NULL);
+    item = NULL; // Item from iterator
+    while ((item = psMetadataGetAndIncrement(iter))) {
+        if (strstr(item->comment, "require") == NULL) {
+            continue;
+        }
+
+        switch (item->type) {
+            case PS_DATA_BOOL:
+                psError(PS_ERR_UNKNOWN, false, "boolean type can not be required");
+                fprintf(stderr, "boolean type can not be required\n");
+                psFree(iter);
+                psFree(config);
+                return NULL;
+                break;
+            case PS_DATA_S8:
+            case PS_DATA_S16:
+            case PS_DATA_S32:
+            case PS_DATA_S64:
+                if (item->data.S64 != 0) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_U8:
+            case PS_DATA_U16:
+            case PS_DATA_U32:
+            case PS_DATA_U64:
+                if (item->data.U64 != 0) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_F32:
+            case PS_DATA_F64:
+                if (!isnan(item->data.F64)) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            case PS_DATA_STRING:
+            case PS_DATA_METADATA:
+                if (item->data.V) {
+                    break;
+                }
+                goto ARG_REQUIRED;
+            default:
+                psError(PS_ERR_UNKNOWN, false, "unknown argument type");
+                fprintf(stderr, "unknown argument type\n");
+                psFree(iter);
+                psFree(config);
+                return NULL;
+            ARG_REQUIRED:                
+                psError(PS_ERR_UNKNOWN, false, "argument %s is required", item->name);
+                fprintf(stderr, "argument %s is required\n", item->name);
+                printUsageMode(argc, argv, modeName, config->args);
+                psFree(iter);
+                psFree(config);
+                return NULL;
+        }
+
+    }
+    psFree(iter);
 
     // setup search criterion
Index: /trunk/ippTools/src/pxconfig.c
===================================================================
--- /trunk/ippTools/src/pxconfig.c	(revision 13563)
+++ /trunk/ippTools/src/pxconfig.c	(revision 13564)
@@ -33,4 +33,5 @@
     psMemSetDeallocator(config, (psFreeFunc)pxConfigFree);
 
+    config->modeName        = NULL;
     config->mode            = 0;
     config->dbh             = NULL;
@@ -44,5 +45,6 @@
 static void pxConfigFree(pxConfig *config)
 {
-    psDBCleanup(config->dbh);
+    psFree(config->modeName);
+    psFree(config->dbh);
     psFree(config->modules);
     psFree(config->where);
Index: /trunk/ippTools/src/pxtools.h
===================================================================
--- /trunk/ippTools/src/pxtools.h	(revision 13563)
+++ /trunk/ippTools/src/pxtools.h	(revision 13564)
@@ -39,4 +39,5 @@
 
 typedef struct {
+    char *modeName;
     int mode;
     pmConfig *modules;
