Index: trunk/SophyaExt/XephemAstroLib/formats.c
===================================================================
--- trunk/SophyaExt/XephemAstroLib/formats.c	(revision 1719)
+++ trunk/SophyaExt/XephemAstroLib/formats.c	(revision 2551)
@@ -5,5 +5,4 @@
 #include <string.h>
 
-#include "P_.h"
 #include "astro.h"
 #include "preferences.h"
@@ -17,12 +16,10 @@
  *	600:	<w>:mm.m
  *	60:	<w>:mm
- */
-void
-fs_sexa (out, a, w, fracbase)
-char *out;
-double a;
-int w;
-int fracbase;
-{
+ * return number of characters written to out, not counting final '\0'.
+ */
+int
+fs_sexa (char *out, double a, int w, int fracbase)
+{
+	char *out0 = out;
 	unsigned long n;
 	int d;
@@ -44,8 +41,7 @@
 	/* form the whole part; "negative 0" is a special case */
 	if (isneg && d == 0)
-	    (void) sprintf (out, "%*s-0", w-2, "");
+	    out += sprintf (out, "%*s-0", w-2, "");
 	else
-	    (void) sprintf (out, "%*d", w, isneg ? -d : d);
-	out += w;
+	    out += sprintf (out, "%*d", w, isneg ? -d : d);
 
 	/* do the rest */
@@ -53,39 +49,41 @@
 	case 60:	/* dd:mm */
 	    m = f/(fracbase/60);
-	    (void) sprintf (out, ":%02d", m);
+	    out += sprintf (out, ":%02d", m);
 	    break;
 	case 600:	/* dd:mm.m */
-	    (void) sprintf (out, ":%02d.%1d", f/10, f%10);
+	    out += sprintf (out, ":%02d.%1d", f/10, f%10);
 	    break;
 	case 3600:	/* dd:mm:ss */
 	    m = f/(fracbase/60);
 	    s = f%(fracbase/60);
-	    (void) sprintf (out, ":%02d:%02d", m, s);
+	    out += sprintf (out, ":%02d:%02d", m, s);
 	    break;
 	case 36000:	/* dd:mm:ss.s*/
 	    m = f/(fracbase/60);
 	    s = f%(fracbase/60);
-	    (void) sprintf (out, ":%02d:%02d.%1d", m, s/10, s%10);
+	    out += sprintf (out, ":%02d:%02d.%1d", m, s/10, s%10);
 	    break;
 	case 360000:	/* dd:mm:ss.ss */
 	    m = f/(fracbase/60);
 	    s = f%(fracbase/60);
-	    (void) sprintf (out, ":%02d:%02d.%02d", m, s/100, s%100);
+	    out += sprintf (out, ":%02d:%02d.%02d", m, s/100, s%100);
 	    break;
 	default:
 	    printf ("fs_sexa: unknown fracbase: %d\n", fracbase);
-	    exit(1);
+	    abort();
 	}
+
+	return (out - out0);
 }
 
 /* put the given modified Julian date, jd, in out[] according to preference
  * format.
- */
-void
-fs_date (out, jd)
-char out[];
-double jd;
+ * return number of characters written to out, not counting final '\0'.
+ */
+int
+fs_date (char out[], double jd)
 {
 	int p = pref_get (PREF_DATE_FORMAT);
+	char *out0 = out;
 	int m, y;
 	double d;
@@ -100,81 +98,50 @@
 	switch (p) {
 	case PREF_YMD:
-	    (void) sprintf (out, "%4d/%02d/%02.6g", y, m, d);
+	    out += sprintf (out, "%4d/%02d/%02.6g", y, m, d);
 	    break;
 	case PREF_DMY:
-	    (void) sprintf (out, "%2.6g/%02d/%-4d", d, m, y);
+	    out += sprintf (out, "%2.6g/%02d/%-4d", d, m, y);
 	    break;
 	case PREF_MDY:
-	    (void) sprintf (out, "%2d/%02.6g/%-4d", m, d, y);
+	    out += sprintf (out, "%2d/%02.6g/%-4d", m, d, y);
 	    break;
 	default:
 	    printf ("fs_date: bad date pref: %d\n", p);
-	    exit (1);
+	    abort();
 	}
-}
-
-/* scan a sexagesimal string and update a double. the string is of the form
- *   H:M:S. a negative value may be indicated by a '-' char before any
- *   component. All components may be integral or real. In addition to ':' the
- *    separator may also be '/' or ';' or ',' or '-'.
- * any components not specified in bp[] are copied from old's.
- *   eg:  ::10	only changes S
- *        10    only changes H
- *        10:0  changes H and M
- */
-void
-f_scansex (o, bp, np)
-double o;	/* old value */
-char bp[];	/* input string */
-double *np;	/* new value */
-{
-	double oh, om, os;
-	double nh, nm, ns;
-	int nneg;
-	double tmp;
-	char c;
-
-	/* fast macro to scan each segment of bp */
-#define	SCANSEX(new,old)						\
-	if (*bp == '-') {nneg = 1; bp++;}				\
-	if (sscanf (bp, "%lf", &new) != 1) new = old;			\
-	while ((c=(*bp)) != '\0') {					\
-	    bp++;							\
-	    if (c==':' || c=='/' || c==';' || c==',' || c=='-')		\
-		break;							\
-	}
-
-	/* get h:m:s components of o in case bp[] defers.
-	 * and constrain to positive for now.
-	 */
-	if (o < 0.0)
-	    o = -o;
-        oh = floor(o);
-	tmp = (o - oh)*60.0;
-	om = floor(tmp);
-	os = (tmp - om)*60.0;
-	
-	/* round to small portion of a second to reduce differencing errors. */
-	if (os > 59.99999) {
-	    os = 0.0;
-	    if ((om += 1.0) >= 60.0) {
-		om = 0.0;
-		oh += 1.0;
-	    }
-	}
-
-	/* scan each component of the buffer */
-	while (*bp == ' ') bp++;
-	nneg = 0;
-	SCANSEX (nh, oh)
-	SCANSEX (nm, om)
-	SCANSEX (ns, os)
-
-	/* back to hours */
-	tmp = ns/3600.0 + nm/60.0 + nh;
-	if (nneg)
-	    tmp = -tmp;
-
-	*np = tmp;
+
+	return (out - out0);
+}
+
+
+/* convert sexagesimal string str AxBxC to double.
+ *   x can be anything non-numeric. Any missing A, B or C will be assumed 0.
+ *   optional - and + can be anywhere.
+ * return 0 if ok, -1 if can't find a thing.
+ */
+int
+f_scansexa (
+const char *str0,	/* input string */
+double *dp)		/* cracked value, if return 0 */
+{
+	double a = 0, b = 0, c = 0;
+	char str[128];
+	char *neg;
+	int r;
+
+	/* copy str0 so we can play with it */
+	strncpy (str, str0, sizeof(str)-1);
+	str[sizeof(str)-1] = '\0';
+
+	neg = strchr(str, '-');
+	if (neg)
+	    *neg = ' ';
+	r = sscanf (str, "%lf%*[^0-9]%lf%*[^0-9]%lf", &a, &b, &c);
+	if (r < 1)
+	    return (-1);
+	*dp = a + b/60 + c/3600;
+	if (neg)
+	    *dp *= -1;
+	return (0);
 }
 
@@ -182,126 +149,56 @@
  *   PREF_DATE_FORMAT preference into its components. allow the day to be a
  *   floating point number,
- * a lone component is always a year if it contains a decimal point or pref
- *   is MDY or DMY and it is not a reasonable month or day value, respectively.
- * leave any unspecified component unchanged.
- * actually, the slashes may be anything but digits or a decimal point.
+ * actually the slashes may be anything but digits.
+ * a lone component with a decimal point is considered a year.
  */
 void
-f_sscandate (bp, pref, m, d, y)
-char *bp;
-int pref;       /* one of PREF_X for PREF_DATE_FORMAT */
-int *m, *y;
-double *d;
-{
-        double comp[3]; /* the three components */
-        int set[3];     /* set[i] is 1 if component i is present */
-	int in;		/* scan state: 1 while we are in a component */
-	int ncomp;	/* incremented as each component is discovered */
-	int ndp;	/* number of decimal points in last component */
-        char *bp0 = NULL, c;
-
-	set[0] = set[1] = set[2] = 0;
-	ncomp = 0;
-	in = 0;
-	ndp = 0;
-
-	/* scan the input string.
-	 * '\0' counts as a component terminator too.
-	 */
-	do {
-	    /* here, *bp is the next character to be investigated */
-	    c = *bp;
-	    if (c == '.' || isdigit(c) || (c == '-' && !in)) {
-		/* found what passes for a floating point number */
-		if (in == 0) {
-		    /* save the beginning of it in bp0 and init ndp */
-		    bp0 = bp;
-		    in = 1;
-		    ndp = 0;
-		}
-		if (c == '.')
-		    ndp++;
-	    } else if (c != ' ') {
-		/* not in a number now ... */
-		if (in) {
-		    /* ... but we *were* in a number, so it counts */
-		    if (ncomp >= 3)
-			return;	/* too many components.. just bail */
-		    comp[ncomp] = atod (bp0);
-		    set[ncomp] = 1;
-		    in = 0;
-		}
-
-		/* regardless, a non-blank non-float means another component */
-		ncomp++;
+f_sscandate (
+char *bp,
+int pref,       /* one of PREF_X for PREF_DATE_FORMAT */
+int *m,
+double *d,
+int *y)
+{
+        double c[3]; /* the three components */
+	int n;
+
+	memset (c, 0, sizeof(c));
+	n = sscanf (bp, "%lf%*[^0-9]%lf%*[^0-9]%lf", &c[0], &c[1], &c[2]);
+	if (n == 1 && (strchr(bp, '.')
+			|| (pref == PREF_MDY && (c[0] < 1 || c[0] > 12))
+			|| (pref == PREF_DMY && (c[0] < 1 || c[0] > 31)))) {
+	    double Mjd;
+	    year_mjd (c[0], &Mjd);
+	    mjd_cal (Mjd, m, d, y);
+	} else {
+	    switch (pref) {
+	    case PREF_MDY:
+		if (n > 0 && c[0] != 0)
+		    *m = (int)c[0];
+		if (n > 1 && c[1] != 0)
+		    *d = c[1];
+		if (n > 2 && c[2] != 0)
+		    *y = (int)c[2];
+		break;
+	    case PREF_YMD:
+		if (n > 0 && c[0] != 0)
+		    *y = (int)c[0];
+		if (n > 1 && c[1] != 0)
+		    *m = (int)c[1];
+		if (n > 2 && c[2] != 0)
+		    *d = c[2];
+		break;
+	    case PREF_DMY:
+		if (n > 1 && c[0] != 0)
+		    *d = c[0];
+		if (n > 2 && c[1] != 0)
+		    *m = (int)c[1];
+		if (n > 3 && c[2] != 0)
+		    *y = (int)c[2];
+		break;
 	    }
-	    bp++;
-	} while (c);
-
-	/* it's a decimal year if there is exactly one component and
-	 *   it contains a decimal point
-	 *   or we are in MDY format and it's not in the range 1..12
-	 *   or we are in DMY format and it's not int the rangle 1..31
-	 */
-	if (ncomp == 1 &&
-		(ndp > 0
-		 || (pref == PREF_MDY && !(comp[0] >= 1 && comp[0] <= 12))
-		 || (pref == PREF_DMY && !(comp[0] >= 1 && comp[0] <= 31)))) {
-	    double Mjd;
-	    year_mjd (comp[0], &Mjd);
-	    mjd_cal (Mjd, m, d, y);
-	    return;
 	}
-
-        switch (pref) {
-        case PREF_MDY:
-            if (set[0]) *m = (int)comp[0];
-            if (set[1]) *d = comp[1];
-            if (set[2]) *y = (int)comp[2];
-            break;
-        case PREF_YMD:
-            if (set[0]) *y = (int)comp[0];
-            if (set[1]) *m = (int)comp[1];
-            if (set[2]) *d = comp[2];
-            break;
-        case PREF_DMY:
-            if (set[0]) *d = comp[0];
-            if (set[1]) *m = (int)comp[1];
-            if (set[2]) *y = (int)comp[2];
-            break;
-	}
-}
-
-/* given a string of the form xx:mm[:ss] or xx:mm.dd, convert it to a double at
- * *dp. actually, ':' may also be ';', '/' or ',' too. all components may be 
- * floats.
- * return -1 if trouble, else 0
- */
-int
-scansex (str, dp)
-char *str;
-double *dp;
-{
-	double x, m = 0.0, s = 0.0;
-	int isneg;
-	int nf;
-
-	while (isspace(*str))
-	    str++;
-	if (*str == '-') {
-	    isneg = 1;
-	    str++;
-	} else
-	    isneg = 0;
-
-	nf = sscanf (str, "%lf%*[:;/,]%lf%*[:;/,]%lf", &x, &m, &s);
-	if (nf < 1)
-	    return (-1);
-	*dp = x + m/60.0 + s/3600.0;
-	if (isneg)
-	    *dp = - *dp;
-	return (0);
 }
 
 /* For RCS Only -- Do Not Edit */
-static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: formats.c,v $ $Date: 2001-10-22 12:08:27 $ $Revision: 1.2 $ $Name: not supported by cvs2svn $"};
+static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: formats.c,v $ $Date: 2004-06-15 16:52:38 $ $Revision: 1.3 $ $Name: not supported by cvs2svn $"};
