Index: trunk/ppstamp/src/ppstampArguments.c
===================================================================
--- trunk/ppstamp/src/ppstampArguments.c	(revision 15280)
+++ trunk/ppstamp/src/ppstampArguments.c	(revision 15323)
@@ -4,32 +4,31 @@
 
 #include "ppstamp.h"
-
-static void usage (void) {
-    fprintf(stderr, "USAGE: ppstamp -pixcenter x y    -pixrange dx dy    -chip chipname [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
-
-    fprintf(stderr, "USAGE: ppstamp -pixcenter x y    -celrange dRA dDEC -chip chipname [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
+#include "ohana.h"
+
+static bool get2Angles(int argnum, int *pArgc, char **argv, bool bothDegrees, double *p1, double *p2);
+static bool get2Ints(int argnum, int *pArgc, char **argv, int *p1, int *p2);
+
+// XXX This usage output is kind of busy
+
+static void usage (void)
+{
+    fprintf(stderr, "\n");
+
+    fprintf(stderr, "USAGE: ppstamp -celcenter RA DEC -arcrange dRA dDEC [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
     fprintf(stderr, "       ppstamp -celcenter RA DEC -celrange dRA dDEC [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
     fprintf(stderr, "       ppstamp -celcenter RA DEC -pixrange dx dy    [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
-    fprintf(stderr, "\n");
-
-#ifdef notyet
+    fprintf(stderr, "       ppstamp -pixcenter x y    -pixrange dx dy    -chip chipname [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
+    fprintf(stderr, "       ppstamp -pixcenter x y    -arcrange dRA dDEC -chip chipname [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
+    fprintf(stderr, "       ppstamp -pixcenter x y    -celrange dRA dDEC -chip chipname [-file INPUT.fits] [-list INPUT.txt] OUTPUT\n");
+    fprintf(stderr, "\n");
+
+    fprintf(stderr, "celcenter & celrange may be specified in HH:MM:SS DD:MM:SS or as 2 values in decimal degrees\n");
+    fprintf(stderr, "arcrange may be specfied as 2 values DD:MM:SS DD:MM:SS or decimal degrees\n");
+    fprintf(stderr, "\n");
     fprintf(stderr, "Optional arguments:\n");
-    fprintf(stderr, "\t-stats STATS.mdc: Output statistics into STATS.mdc\n");
-    fprintf(stderr, "\n");
-    fprintf(stderr, "Input options (single file / file list):\n");
-    fprintf(stderr, "\n");
-#endif
+    fprintf(stderr, "         -chip chipName    selects chip (only used with -pixcenter)\n");
+    fprintf(stderr, "\n");
+
     exit (2);
-}
-
-void get2Doubles(int argnum, int *pArgc, char **argv, double *p1, double *p2) {
-    if (*pArgc < 3) {
-        usage();
-    }
-    psArgumentRemove(argnum, pArgc, argv);
-    *p1 = atof(argv[argnum]);
-    psArgumentRemove(argnum, pArgc, argv);
-    *p2 = atof(argv[argnum]);
-    psArgumentRemove(argnum, pArgc, argv);
 }
 
@@ -48,8 +47,4 @@
         psString version;
         version = ppstampVersionLong();   fprintf (stdout, "%s\n", version); psFree (version);
-// don't need these
-//      version = ppStatsVersionLong();   fprintf (stdout, "%s\n", version); psFree (version);
-//      version = psphotVersionLong();    fprintf (stdout, "%s\n", version); psFree (version);
-//      version = psastroVersionLong();   fprintf (stdout, "%s\n", version); psFree (version);
         version = psModulesVersionLong(); fprintf (stdout, "%s\n", version); psFree (version);
         version = psLibVersionLong();     fprintf (stdout, "%s\n", version); psFree (version);
@@ -58,5 +53,5 @@
 
     // load the site-wide configuration information
-    pmConfig *config = pmConfigRead(&argc, argv, RECIPE_NAME);
+    pmConfig *config = pmConfigRead(&argc, argv, NULL);
     if (config == NULL) {
         psErrorStackPrint(stderr, "Can't find site configuration!\n");
@@ -64,6 +59,4 @@
     }
 
-    (void) pmConfigRecipeOptions (config, RECIPE_NAME);
-
     options = ppstampOptionsAlloc();
     *pOptions = options;
@@ -72,6 +65,12 @@
         gotCenter = true;
         options->celestialCenter = false;
-        get2Doubles(argnum, &argc, argv, &options->centerX, &options->centerY);
-    }
+        psArgumentRemove(argnum, &argc, argv);
+
+        if (!get2Ints(argnum, &argc, argv, &options->centerX, &options->centerY)) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "invalid pixcenter specification\n");
+            usage();
+        }
+    }
+
     if ((argnum = psArgumentGet(argc, argv, "-celcenter"))) {
         if (gotCenter) {
@@ -79,32 +78,65 @@
             usage();
         }
-        get2Doubles(argnum, &argc, argv, &options->centerRA, &options->centerDEC);
-        options->centerRA  = DEG_TO_RAD(options->centerRA);
-        options->centerDEC = DEG_TO_RAD(options->centerDEC);
+        psArgumentRemove(argnum, &argc, argv);
+
+        double raDeg, decDeg;
+        if (!get2Angles(argnum, &argc, argv, false, &raDeg, &decDeg)) {
+            usage();
+        }
+        options->centerRA  = DEG_TO_RAD(raDeg);
+        options->centerDEC = DEG_TO_RAD(decDeg);
         gotCenter = true;
         options->celestialCenter = true;
     }
+
     if (!gotCenter) {
-        usage();
-    }
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "must specify center of region of interest\n");
+        usage();
+    }
+
     if ((argnum = psArgumentGet(argc, argv, "-pixrange"))) {
         gotRange = true;
         options->celestialRange = false;
-        get2Doubles(argnum, &argc, argv, &options->dX, &options->dY);
-    }
-    if ((argnum = psArgumentGet(argc, argv, "-celrange"))) {
-        fprintf(stderr, "Specifying range in celestial coordinates is not implemented yet\n");
-        exit(1);
+        psArgumentRemove(argnum, &argc, argv);
+        if (!get2Ints(argnum, &argc, argv, &options->dX, &options->dY)) {
+            usage();
+        }
+    }
+
+    if ((argnum = psArgumentGet(argc, argv, "-arcrange"))) {
         if (gotRange) {
-            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "can't specify both -pixrange and -celrange\n");;
-            usage();
-        }
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "specify only one of -pixrange or -arcrange or -celrange\n");;
+            usage();
+        }
+        psArgumentRemove(argnum, &argc, argv);
         gotRange = true;
         options->celestialRange = true;
-        get2Doubles(argnum, &argc, argv, &options->dRA, &options->dDEC);
-        options->dRA  = DEG_TO_RAD(options->dRA);
-        options->dDEC = DEG_TO_RAD(options->dDEC);
-    }
+
+        double deg1, deg2;
+        if (!get2Angles(argnum, &argc, argv, true, &deg1, &deg2)) {
+            usage();
+        }
+        options->dRA = DEG_TO_RAD(deg1);
+        options->dDEC = DEG_TO_RAD(deg2);
+    }
+    if ((argnum = psArgumentGet(argc, argv, "-celrange"))) {
+        if (gotRange) {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "specify one of -pixrange or -arcrange or -celrange\n");;
+            usage();
+        }
+        psArgumentRemove(argnum, &argc, argv);
+        gotRange = true;
+        options->celestialRange = true;
+
+        double deg1, deg2;
+        if (!get2Angles(argnum, &argc, argv, false, &deg1, &deg2)) {
+            usage();
+        }
+        options->dRA = DEG_TO_RAD(deg1);
+        options->dDEC = DEG_TO_RAD(deg2);
+    }
+
     if (!gotRange) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "must specify range\n");
         usage();
     }
@@ -114,9 +146,4 @@
         options->chipName = psStringCopy(argv[argnum]);
         psArgumentRemove(argnum, &argc, argv);
-    }
-
-    if (!options->celestialCenter && (options->chipName == NULL)) {
-        fprintf(stderr, "must specify chip name when using -pixcenter\n");
-        usage();
     }
 
@@ -125,8 +152,13 @@
     if (!status) {
         // TODO: shall we print a specific message?
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "must specify INPUT\n");
         usage ();
     }
 
-    if (argc != 2) usage ();
+    // finally the output file
+    if (argc != 2) {
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "must specify OUTPUT\n");
+        usage ();
+    }
 
     // Add the input and output images (which remain on the command-line) to the arguments list
@@ -137,2 +169,59 @@
     return config;
 }
+
+static bool validNumber(char *string)
+{
+    char *p = string;
+    if ((*p == '+') || (*p == '-')) {
+        p++;
+    }
+    return isdigit(*p);
+}
+
+static bool get2Ints(int argnum, int *pArgc, char **argv, int *p1, int *p2)
+{
+    if (*pArgc < 2) {
+        usage();
+    }
+
+    if (!validNumber(argv[argnum])) {
+        return false;
+    }
+
+    *p1 = atoi(argv[argnum]);
+    psArgumentRemove(argnum, pArgc, argv);
+
+    if (!validNumber(argv[argnum])) {
+        return false;
+    }
+
+    *p2 = atoi(argv[argnum]);
+    psArgumentRemove(argnum, pArgc, argv);
+
+    return true;
+}
+
+static bool get2Angles(int argnum, int *pArgc, char **argv, bool bothInDegrees, double *p1, double *p2)
+{
+    bool rval;
+
+    if (*pArgc < 2) {
+        usage();
+    }
+
+    if (bothInDegrees) {
+        // both values are angles of arc DD:MM:SS or decimal degrees
+        rval   = ohana_dms_to_ddd(p1, argv[argnum]);
+        if (rval) {
+            rval  = ohana_dms_to_ddd(p1, argv[argnum+1]);
+        }
+    } else {
+        // first value may be in HH:MM:SS
+        rval = ohana_str_to_radec(p1, p2, argv[argnum], argv[argnum+1]);
+    }
+
+    psArgumentRemove(argnum, pArgc, argv);
+    psArgumentRemove(argnum, pArgc, argv);
+
+    return rval;
+}
