Index: trunk/ippTools/src/pxconfig.c
===================================================================
--- trunk/ippTools/src/pxconfig.c	(revision 13564)
+++ trunk/ippTools/src/pxconfig.c	(revision 13575)
@@ -21,4 +21,9 @@
 #include <config.h>
 #endif
+
+#include <string.h>
+
+#include <pslib.h>
+#include <psmodules.h>
 
 #include "pxtools.h"
@@ -51,2 +56,144 @@
     psFree(config->args);
 }
+
+void pxUsage(FILE *stream, int argc, char **argv, psMetadata *modes) 
+{
+    fprintf(stream, "Usage: %s <mode> [<options>]\n\n", argv[0]);
+    fprintf(stream, "<mode>:\n");
+
+    psArgumentHelpSimple(stream, modes);
+}
+
+
+void pxUsageMode(FILE *stream, int argc, char **argv, const char *modeName, psMetadata *argSet) 
+{
+    fprintf(stream, "Usage: %s <mode> [<options>]\n\n", argv[0]);
+    fprintf(stream, "%s:\n", modeName);
+
+    psArgumentHelpSimple(stream, argSet);
+}
+
+
+bool pxGetOptions(FILE *stream, int argc, char **argv, pxConfig *config, psMetadata *modes, psMetadata *argSets)
+{
+    // figure out what mode we're running in
+    psMetadataIterator *iter = psMetadataIteratorAlloc(modes, PS_LIST_HEAD, NULL);
+    psMetadataItem *item = NULL;
+    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(stream, "only one mode selection is allowed\n");
+                pxUsage(stream, argc, argv, modes);
+                return NULL;
+            }
+
+            config->mode = item->data.U32;
+            config->modeName = psStringCopy(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");
+                return NULL;
+            }
+
+            config->args = psMemIncrRefCounter(argset);
+        }
+
+    }
+
+    psFree(iter);
+
+    // make sure we found a mode
+    if (config->mode == PXTOOL_MODE_NONE) {
+        psError(PS_ERR_UNKNOWN, true, "mode argument is required");
+        fprintf(stderr, "mode argument is required\n");
+        pxUsage(stream, argc, argv, modes);
+        return NULL;
+    }
+
+    // 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");
+        pxUsageMode(stream, argc, argv, config->modeName, config->args);
+        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");
+        pxUsageMode(stream, argc, argv, config->modeName, config->args);
+        return NULL;
+    }
+
+    // make sure that all required 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");
+                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(stream, "unknown argument type\n");
+                return NULL;
+            ARG_REQUIRED:                
+                psError(PS_ERR_UNKNOWN, false, "argument %s is required", item->name);
+                fprintf(stream, "argument %s is required\n", item->name);
+                pxUsageMode(stream, argc, argv, config->modeName, config->args);
+                return NULL;
+        }
+
+    }
+
+    psFree(iter);
+
+    return true;
+}
