Index: trunk/SophyaExt/XephemAstroLib/dbfmt.c
===================================================================
--- trunk/SophyaExt/XephemAstroLib/dbfmt.c	(revision 1719)
+++ trunk/SophyaExt/XephemAstroLib/dbfmt.c	(revision 2551)
@@ -4,21 +4,12 @@
 #include <ctype.h>
 #include <math.h>
-
-#if defined(__STDC__)
 #include <stdlib.h>
 #include <string.h>
-#endif
-
-#include "P_.h"
+
 #include "astro.h"
-#include "circum.h"
 #include "preferences.h"
 
-extern void zero_mem P_((void *loc, unsigned len));
-extern double atod P_((char *buf));
-
-int get_fields P_((char *s, int delim, char *fields[]));
-int db_set_field P_((char bp[], int id, PrefDateFormat pref, Obj *op));
-int db_chk_planet P_((char name[], Obj *op));
+
+int get_fields (char *s, int delim, char *fields[]);
 
 #define MAXDBLINE       256     /* longest allowed db line */
@@ -28,16 +19,31 @@
 #define MAXFLDS 20              /* must be more than on any expected line */
 
-#define ASIZ(a) (sizeof(a)/sizeof(a[0]))
-
-static int line_candidate P_((char *buf));
-static void crack_year P_((char *bp, PrefDateFormat pref, double *p));
-static int db_get_field P_((Obj *op, int id, char *bp));
-static int tle_sum P_((char *l));
-static double tle_fld P_((char *l, int from, int thru));
-static double tle_expfld P_((char *l, int start));
+static char *enm (char *flds[MAXFLDS]);
+static int crack_f (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
+static int crack_e (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
+static int crack_h (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
+static int crack_p (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
+static int crack_E (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
+static int crack_P (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
+static int crack_B (Obj *op, char *flds[MAXFLDS], int nf, char whynot[]);
+static int crack_name (Obj *op, char *flds[MAXFLDS], int nf,
+    char nm[][MAXNM], int nnm);
+static void crack_year (char *bp, double *p);
+static void crack_okdates (char *fld, float *startok, float *endok);
+static int get_okdates (char *lp, float *sp, float *ep);
+static int tle_sum (char *l);
+static double tle_fld (char *l, int from, int thru);
+static double tle_expfld (char *l, int start);
+static void write_f (Obj *op, char lp[]);
+static void write_e (Obj *op, char lp[]);
+static void write_h (Obj *op, char lp[]);
+static void write_p (Obj *op, char lp[]);
+static void write_E (Obj *op, char lp[]);
+static void write_P (Obj *op, char lp[]);
+static void write_B (Obj *op, char lp[]);
 
 /* crack the given .edb database line into op.
  * if ok
- *   return 0
+ *   return number of names in nm[], or 1 if nm == NULL
  * else
  *   if whynot
@@ -47,23 +53,22 @@
  *       fill whynot with reason message.
  *   return -1
+ * only the first name is stored in op, all names (up to nnm) are in nm[], or
+ *   ignored if nm == NULL.
  */
 int
-db_crack_line (s, op, whynot)
-char s[];
-Obj *op;
-char whynot[];
-{
+db_crack_line (char s[], Obj *op, char nm[][MAXNM], int nnm, char whynot[])
+{
+	char copy[MAXDBLINE];	/* work copy; leave s untouched */
 	char *flds[MAXFLDS];	/* point to each field for easy reference */
-	char *sflds[MAXFLDS];	/* point to each sub field for easy reference */
-	char copy[MAXDBLINE];	/* work copy; leave s untouched */
-	int nf, nsf;		/* number of fields and subfields */
+	int nf;
 	int i;
 
+	/* init no response */
+	if (whynot)
+	    whynot[0] = '\0';
+
 	/* basic initial check */
-	if (line_candidate (s) < 0) {
-	    if (whynot)
-		whynot[0] = '\0';
-	    return (-1);
-	}
+	if (dbline_candidate (s) < 0)
+	    return (-1);
 
 	/* do all the parsing on a copy */
@@ -79,5 +84,5 @@
 	if (nf < 2) {
 	    if (whynot)
-		sprintf (whynot, "Found only %d fields", nf);
+		sprintf (whynot, "Bogus: %s", s);
 	    return (-1);
 	}
@@ -85,169 +90,99 @@
 	/* switch out on type of object - the second field */
 	switch (flds[1][0]) {
-	case 'f': {
-	    static int ids[] = {F_RA, F_DEC, F_MAG};
-	    if (nf < 5 || nf > 7) {
-		if (whynot)
-		    sprintf (whynot, "f needs 5-7 fields: %d", nf);
-		return (-1);
-	    }
-	    zero_mem ((void *)op, sizeof(ObjF));
-	    op->o_type = FIXED;
-	    nsf = get_fields(flds[1], SUBFLD, sflds);
-	    if (nsf > 1 && db_set_field (sflds[1], F_CLASS, PREF_MDY, op) < 0) {
-		if (whynot)
-		    sprintf (whynot, "Bad f class: %c", sflds[1][0]);
-		return (-1);
-	    }
-	    if (nsf > 2)
-		(void) db_set_field (sflds[2], F_SPECT, PREF_MDY, op);
-	    for (i = 2; i < ASIZ(ids)+2; i++)
-		(void) db_set_field (flds[i], ids[i-2], PREF_MDY, op);
-	    (void) db_set_field (nf>5 && flds[5][0] ? flds[5] : "2000",
-							F_EPOCH, PREF_MDY, op);
-	    if (nf == 7)
-		(void) db_set_field (flds[6], F_SIZE, PREF_MDY, op);
-	    break;
-	}
-
-	case 'e': {
-	    static int ids[] = {E_INC, E_LAN, E_AOP, E_A, E_N, E_E, E_M,
-						E_CEPOCH, E_EPOCH, E_M1, E_M2
-	    };
-	    if (nf != 13 && nf != 14) {
-		if (whynot)
-		    sprintf (whynot, "e needs 13 or 14 fields: %d", nf);
-		return (-1);
-	    }
-	    zero_mem ((void *)op, sizeof(ObjE));
-	    op->o_type = ELLIPTICAL;
-	    for (i = 2; i < ASIZ(ids)+2; i++)
-		(void) db_set_field (flds[i], ids[i-2], PREF_MDY, op);
-	    if (nf == 14)
-		(void) db_set_field (flds[13], E_SIZE, PREF_MDY, op);
-	    break;
-	}
-
-	case 'h': {
-	    static int ids[]= {H_EP,H_INC,H_LAN,H_AOP,H_E,H_QP,H_EPOCH,H_G,H_K};
-	    if (nf != 11 && nf != 12) {
-		if (whynot)
-		    sprintf (whynot, "h needs 11 or 12 fields: %d", nf);
-		return (-1);
-	    }
-	    zero_mem ((void *)op, sizeof(ObjH));
-	    op->o_type = HYPERBOLIC;
-	    for (i = 2; i < ASIZ(ids)+2; i++)
-		(void) db_set_field (flds[i], ids[i-2], PREF_MDY, op);
-	    if (nf == 12)
-		(void) db_set_field (flds[11], H_SIZE, PREF_MDY, op);
-	    break;
-	}
-
-	case 'p': {
-	    static int ids[] = {P_EP,P_INC,P_AOP,P_QP,P_LAN,P_EPOCH,P_G,P_K};
-	    if (nf != 10 && nf != 11) {
-		if (whynot)
-		    sprintf (whynot, "p needs 10 or 11 fields: %d", nf);
-		return (-1);
-	    }
-	    zero_mem ((void *)op, sizeof(ObjP));
-	    op->o_type = PARABOLIC;
-	    for (i = 2; i < ASIZ(ids)+2; i++)
-		(void) db_set_field (flds[i], ids[i-2], PREF_MDY, op);
-	    if (nf == 11)
-		(void) db_set_field (flds[10], P_SIZE, PREF_MDY, op);
-	    break;
-	}
-
-	case 'E': {
-	    static int ids[] = {ES_EPOCH,ES_INC,ES_RAAN,ES_E,ES_AP,ES_M,ES_N,
-							    ES_DECAY,ES_ORBIT};
-	    if (nf != 11 && nf != 12) {
-		if (whynot)
-		    sprintf (whynot, "E needs 11 or 12 fields: %d", nf);
-		return (-1);
-	    }
-	    zero_mem ((void *)op, sizeof(ObjES));
-	    op->o_type = EARTHSAT;
-	    for (i = 2; i < ASIZ(ids)+2; i++)
-		(void) db_set_field (flds[i], ids[i-2], PREF_MDY, op);
-	    if (nf == 12)
-		(void) db_set_field (flds[11], ES_DRAG, PREF_MDY, op);
-	    break;
-	}
+
+	case 'f':
+	    if (crack_f (op, flds, nf, whynot) < 0)
+		return (-1);
+	    break;
+
+	case 'e':
+	    if (crack_e (op, flds, nf, whynot) < 0)
+		return (-1);
+	    break;
+
+	case 'h':
+	    if (crack_h (op, flds, nf, whynot) < 0)
+		return (-1);
+	    break;
+
+	case 'p':
+	    if (crack_p (op, flds, nf, whynot) < 0)
+		return (-1);
+	    break;
+
+	case 'B':
+	    if (crack_B (op, flds, nf, whynot) < 0)
+		return (-1);
+	    break;
+
+	case 'E':
+	    if (crack_E (op, flds, nf, whynot) < 0)
+		return (-1);
+	    break;
 
 	case 'P':
-	    /* allow, though ignore, anything after the P */
-	    i = db_chk_planet (flds[0], op);	/* does o_name too */
-	    if (i < 0) {
-		if (whynot)
-		    sprintf (whynot, "Bad planet: %s", flds[0]);
-	    }
-	    return (i);
+	    if (crack_P (op, flds, nf, whynot) < 0)
+		return (-1);
+	    break;
 
 	default:
 	    if (whynot)
-		sprintf (whynot, "Unknown type: %c", flds[1][0]);
-	    return (-1);
-	}
-
-	/* load up o_name */
-	(void) db_set_field (flds[0], O_NAME, PREF_MDY, op);
-
-	return (0);
-}
-
-/* return 0 if TLE checksum is ok, else -1 */
-static int
-tle_sum (l)
-char *l;
-{
-	char *lastl = l + 68;
-	int sum;
-
-	for (sum = 0; l < lastl; ) {
-	    char c = *l++;
-	    if (c == '\0')
-		return (-1);
-	    if (isdigit(c))
-		sum += c - '0';
-	    else if (c == '-')
-		sum++;
-	}
-
-	return (*l - '0' == (sum%10) ? 0 : -1);
-}
-
-/* extract the given columns and return value.
- * N.B. from and to are 1-based within l
+		sprintf (whynot, "%s: Unknown type %c for %s", enm(flds),
+							flds[1][0], flds[0]);
+	    return (-1);
+	}
+
+	return (crack_name (op, flds, nf, nm, nnm));
+}
+
+/* write the given Obj in .edb format to lp[].
+ * we do _not_ include a trailing '\n'.
  */
-static double
-tle_fld (l, from, thru)
-char *l;
-int from, thru;
-{
-	char buf[32];
-
-	sprintf (buf, "%.*s", thru-from+1, l+from-1);
-	return (atod (buf));
-}
-
-/* extract the exponential value starting at the given column.
- * N.B. start is 1-based within l
- */
-static double
-tle_expfld (l, start)
-char *l;
-int start;
-{
-	char buf[32];
-	double v;
-
-	sprintf (buf, ".%.*s", 5, l+start);
-	v = atod (buf) * pow (10.0, tle_fld(l, start+6, start+7));
-	if (l[start-1] == '-')
-	    v = -v;
-	return (v);
+void
+db_write_line (Obj *op, char lp[])
+{
+	int priorpref;
+
+	/* .edb format always uses MDY.
+	 * N.B. must restore old value before returning from here!
+	 */
+	priorpref = pref_set (PREF_DATE_FORMAT, PREF_MDY);
+
+	switch (op->o_type) {
+	case FIXED:
+	    write_f (op, lp);
+	    break;
+
+	case BINARYSTAR:
+	    write_B (op, lp);
+	    break;
+
+	case ELLIPTICAL:
+	    write_e (op, lp);
+	    break;
+
+	case HYPERBOLIC:
+	    write_h (op, lp);
+	    break;
+
+	case PARABOLIC:
+	    write_p (op, lp);
+	    break;
+
+	case EARTHSAT:
+	    write_E (op, lp);
+	    break;
+
+	case PLANET:
+	    write_P (op, lp);
+	    break;
+
+	default:
+	    printf ("Unknown type for %s: %d\n", op->o_name, op->o_type);
+	    abort();
+	}
+
+	/* restore date format preference */
+	(void) pref_set (PREF_DATE_FORMAT, priorpref);
 }
 
@@ -261,7 +196,5 @@
  */
 int
-db_tle (name, l1, l2, op)
-char *name, *l1, *l2;
-Obj *op;
+db_tle (char *name, char *l1, char *l2, Obj *op)
 {
 	double ep;
@@ -306,4 +239,5 @@
 	/* goodies from "line 1" */
 	op->es_drag = (float) tle_expfld (l1, 54);
+	op->es_decay = (float) tle_fld (l1, 34, 43);
 	i = (int) tle_fld (l1, 19, 20);
 	if (i < 57)
@@ -325,332 +259,36 @@
 }
 
-/* write the given Obj in .edb format to lp[].
- * we do _not_ include a trailing '\n'.
- */
-void
-db_write_line (op, lp)
-Obj *op;
-char *lp;
-{
-	int priorpref;
-	int i;
-
-	/* .edb format always uses MDY.
-	 * N.B. must restore old value before returning from here!
-	 */
-	priorpref = pref_set (PREF_DATE_FORMAT, PREF_MDY);
-
-	switch (op->o_type) {
-	case FIXED: {
-	    static int ids[] = {F_CLASS, F_SPECT, F_RA, F_DEC, F_MAG, F_EPOCH,
-		F_SIZE
-	    };
-
-	    sprintf (lp, "%s,f", op->o_name);
-	    lp += strlen(lp);
-	    for (i = 0; i < ASIZ(ids); i++)
-		lp += db_get_field (op, ids[i], lp);
-	    break;
-	    }
-
-	case ELLIPTICAL: {
-	    static int ids[] = {E_INC, E_LAN, E_AOP, E_A, E_N, E_E, E_M,
-					E_CEPOCH, E_EPOCH, E_M1, E_M2, E_SIZE
-	    };
-
-	    sprintf (lp, "%s,e", op->o_name);
-	    lp += strlen(lp);
-	    for (i = 0; i < ASIZ(ids); i++)
-		lp += db_get_field (op, ids[i], lp);
-	    break;
-	    }
-
-	case HYPERBOLIC: {
-	    static int ids[]= {H_EP, H_INC, H_LAN, H_AOP, H_E, H_QP, H_EPOCH,
-		H_G, H_K, H_SIZE
-	    };
-
-	    sprintf (lp, "%s,h", op->o_name);
-	    lp += strlen(lp);
-	    for (i = 0; i < ASIZ(ids); i++)
-		lp += db_get_field (op, ids[i], lp);
-	    break;
-	    }
-
-	case PARABOLIC: {
-	    static int ids[] = {P_EP, P_INC, P_AOP, P_QP, P_LAN, P_EPOCH, P_G,
-		P_K, P_SIZE
-	    };
-
-	    sprintf (lp, "%s,p", op->o_name);
-	    lp += strlen(lp);
-	    for (i = 0; i < ASIZ(ids); i++)
-		lp += db_get_field (op, ids[i], lp);
-	    break;
-	    }
-
-	case EARTHSAT: {
-	    static int ids[] = {ES_EPOCH, ES_INC, ES_RAAN, ES_E, ES_AP, ES_M,
-		ES_N, ES_DECAY,ES_ORBIT,ES_DRAG
-	    };
-
-	    sprintf (lp, "%s,E", op->o_name);
-	    lp += strlen(lp);
-	    for (i = 0; i < ASIZ(ids); i++)
-		lp += db_get_field (op, ids[i], lp);
-	    break;
-	    }
-
-	case PLANET:
-	    sprintf (lp, "%s,P", op->o_name);
-	    lp += strlen(lp);
-	    break;
-
-	default:
-	    printf ("Unknown type for %s: %d\n", op->o_name, op->o_type);
-	    exit(1);
-	}
-
-	/* restore date format preference */
-	(void) pref_set (PREF_DATE_FORMAT, priorpref);
-}
-
-/* given a text buffer and a field id, and a PREF_DATE_FORMAT,
- *   set the corresponding member in *op.
- * return 0 if ok, else -1.
+/* return 0 if op has no date range information or what it does have brackets
+ * now, else -1
  */
 int
-db_set_field (bp, id, pref, op)
-char bp[];
-int id;
-PrefDateFormat pref;
-Obj *op;
-{
-	double tmp;
-
-	/* include all the enums and in numeric order to give us the best
-	 * possible chance the compiler will implement this as a jump table.
-	 */
-	switch (id) {
-	case O_TYPE:
-	    printf ("db_set_field: called with id==O_TYPE\n");
-	    exit(1);
-	    break;
-	case O_NAME:
-	    (void) strncpy (op->o_name, bp, sizeof(op->o_name)-1);
-	    op->o_name[sizeof(op->o_name)-1] = '\0';
-	    break;
-	case F_RA:
-	    f_scansex (radhr(op->f_RA), bp, &tmp);
-	    op->f_RA = (float) hrrad(tmp);
-	    break;
-	case F_DEC:
-	    f_scansex (raddeg(op->f_dec), bp, &tmp);
-	    op->f_dec = (float) degrad(tmp);
-	    break;
-	case F_EPOCH:
-	    tmp = op->f_epoch;
-	    crack_year (bp, pref, &tmp);
-	    op->f_epoch = (float) tmp;
-	    break;
-	case F_MAG:
-	    set_fmag (op, atod(bp));
-	    break;
-	case F_SIZE:
-	    op->f_size = (float) atod(bp);
-	    {
-		/* optional minor axis and position angle subfields */
-		char *sflds[MAXFLDS];
-		int nsf = get_fields(bp, SUBFLD, sflds);
-
-		if (nsf == 3) {
-		    set_ratio(op, op->s_size, atod(sflds[1]));
-		    set_pa(op,degrad(atod(sflds[2])));
-		} else {
-		    set_ratio(op,1,1);	/* round */
-		    set_pa(op,0.0);
-		}
-	    }
-	    break;
-	case F_CLASS:
-	    switch (bp[0]) {
-	    case 'A': case 'B': case 'C': case 'D': case 'F': case 'G':
-	    case 'H': case 'K': case 'J': case 'L': case 'M': case 'N':
-	    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
-	    case 'U': case 'V':
-		op->f_class = bp[0];
-		break;
-	    default:
-		return (-1);
-	    }
-	    break;
-	case F_SPECT: {
-	    int i, j;
-	    /* fill f_spect all the way */
-	    for (i = j = 0; i < sizeof(op->f_spect); i++)
-		if ((op->f_spect[i] = bp[j]) != 0)
-		    j++;
-	    break;
-	}
-
-	case E_INC:
-	    op->e_inc = (float) atod (bp);
-	    break;
-	case E_LAN:
-	    op->e_Om = (float) atod (bp);
-	    break;
-	case E_AOP:
-	    op->e_om = (float) atod (bp);
-	    break;
-	case E_A:
-	    op->e_a = (float) atod (bp);
-	    break;
-	case E_N:
-	    /* retired */
-	    break;
-	case E_E:
-	    op->e_e = atod (bp);
-	    break;
-	case E_M:
-	    op->e_M = (float) atod (bp);
-	    break;
-	case E_CEPOCH:
-	    crack_year (bp, pref, &op->e_cepoch);
-	    break;
-	case E_EPOCH:
-	    crack_year (bp, pref, &op->e_epoch);
-	    break;
-	case E_M1:
-	    switch (bp[0]) {
-	    case 'g':
-		op->e_mag.whichm = MAG_gk;
-		bp++;
-		break;
-	    case 'H':
-		op->e_mag.whichm = MAG_HG;
-		bp++;
-		break;
-	    default:
-		/* leave type unchanged if no or unrecognized prefix */
-		break;
-	    }
-	    op->e_mag.m1 = (float) atod(bp);
-	    break;
-	case E_M2:
-	    switch (bp[0]) {
-	    case 'k':
-		op->e_mag.whichm = MAG_gk;
-		bp++;
-		break;
-	    case 'G':
-		op->e_mag.whichm = MAG_HG;
-		bp++;
-		break;
-	    default:
-		/* leave type unchanged if no or unrecognized prefix */
-		break;
-	    }
-	    op->e_mag.m2 = (float) atod(bp);
-	    break;
-	case E_SIZE:
-	    op->e_size = (float) atod (bp);
-	    break;
-
-	case H_EP:
-	    crack_year (bp, pref, &op->h_ep);
-	    break;
-	case H_INC:
-	    op->h_inc = (float) atod (bp);
-	    break;
-	case H_LAN:
-	    op->h_Om = (float) atod (bp);
-	    break;
-	case H_AOP:
-	    op->h_om = (float) atod (bp);
-	    break;
-	case H_E:
-	    op->h_e = (float) atod (bp);
-	    break;
-	case H_QP:
-	    op->h_qp = (float) atod (bp);
-	    break;
-	case H_EPOCH:
-	    crack_year (bp, pref, &op->h_epoch);
-	    break;
-	case H_G:
-	    op->h_g = (float) atod (bp);
-	    break;
-	case H_K:
-	    op->h_k = (float) atod (bp);
-	    break;
-	case H_SIZE:
-	    op->h_size = (float) atod (bp);
-	    break;
-
-	case P_EP:
-	    crack_year (bp, pref, &op->p_ep);
-	    break;
-	case P_INC:
-	    op->p_inc = (float) atod (bp);
-	    break;
-	case P_AOP:
-	    op->p_om = (float) atod (bp);
-	    break;
-	case P_QP:
-	    op->p_qp = (float) atod (bp);
-	    break;
-	case P_LAN:
-	    op->p_Om = (float) atod (bp);
-	    break;
-	case P_EPOCH:
-	    crack_year (bp, pref, &op->p_epoch);
-	    break;
-	case P_G:
-	    op->p_g = (float) atod (bp);
-	    break;
-	case P_K:
-	    op->p_k = (float) atod (bp);
-	    break;
-	case P_SIZE:
-	    op->p_size = (float) atod (bp);
-	    break;
-
-	case ES_EPOCH:
-	    crack_year (bp, pref, &op->es_epoch);
-	    break;
-	case ES_INC:
-	    op->es_inc = (float) atod (bp);
-	    break;
-	case ES_RAAN:
-	    op->es_raan = (float) atod (bp);
-	    break;
-	case ES_E:
-	    op->es_e = (float) atod (bp);
-	    break;
-	case ES_AP:
-	    op->es_ap = (float) atod (bp);
-	    break;
-	case ES_M:
-	    op->es_M = (float) atod (bp);
-	    break;
-	case ES_N:
-	    op->es_n = atod (bp);
-	    break;
-	case ES_DECAY:
-	    op->es_decay = (float) atod (bp);
-	    break;
-	case ES_ORBIT:
-	    op->es_orbit = atoi (bp);
-	    break;
-	case ES_DRAG:
-	    op->es_drag = (float) atod (bp);
-	    break;
-
+dateRangeOK (Now *np, Obj *op)
+{
+	float *sp, *ep;
+
+	switch (op->o_type) {
+	case ELLIPTICAL:
+	    sp = &op->e_startok;
+	    ep = &op->e_endok;
+	    break;
+	case HYPERBOLIC:
+	    sp = &op->h_startok;
+	    ep = &op->h_endok;
+	    break;
+	case PARABOLIC:
+	    sp = &op->p_startok;
+	    ep = &op->p_endok;
+	    break;
+	case EARTHSAT:
+	    sp = &op->es_startok;
+	    ep = &op->es_endok;
+	    break;
 	default:
-	    printf ("BUG! db_set_field: bad id: %d\n", id);
-	    exit (1);
-	}
-
-	return (0);
+	    return (0);
+	}
+
+	if (*sp <= mjd && (!*ep || mjd <= *ep))
+	    return (0);
+	return (-1);
 }
 
@@ -662,8 +300,5 @@
  */
 int
-get_fields (s, delim, fields)
-char *s;
-int delim;
-char *fields[];
+get_fields (char *s, int delim, char *fields[])
 {
 	int n;
@@ -684,62 +319,471 @@
 }
 
-/* check name for being a planet.
- * if so, fill in *op and return 0, else return -1.
- */
-int
-db_chk_planet (name, op)
-char name[];
-Obj *op;
-{
-	char namecpy[256];
-	int i;
-
-	/* these must match the order in astro.h */
-	static char *planet_names[] = {
-	    "Mercury", "Venus", "Mars", "Jupiter", "Saturn",
-	    "Uranus", "Neptune", "Pluto", "Sun", "Moon",
-	};
-
-	/* make a copy to match our case -- strcasecmp() not entirely portable*/
-	strcpy (namecpy, name);
-	if (islower(namecpy[0]))
-	    namecpy[0] = toupper(namecpy[0]);
-	for (i = 1; namecpy[i]; i++)
-	    if (isupper(namecpy[i]))
-		namecpy[i] = tolower(namecpy[i]);
-
-	for (i = MERCURY; i <= MOON; i++) {
-	    if (strcmp (namecpy, planet_names[i]) == 0) {
-		zero_mem ((void *)op, sizeof(ObjPl));
-		op->o_type = PLANET;
-		(void) strcpy (op->o_name, planet_names[i]);
-		op->pl.pl_code = i;
-		return (0);
-	    }
-	}
-
-	return (-1);
-}
-
 /* return 0 if buf qualifies as a database line worthy of a cracking
  * attempt, else -1.
  */
+int
+dbline_candidate (char *buf)
+{
+	char c = buf[0];
+
+	return (c == '#' || c == '!' || isspace(c) ? -1 : 0);
+}
+
+/* return 0 if TLE checksum is ok, else -1 */
 static int
-line_candidate (buf)
-char *buf;
-{
-	char c = buf[0];
-
-	return (c == '#' || c == '!' || isspace(c) ? -1 : 0);
-}
-
-/* given either a decimal year (xxxx[.xxx]) or a calendar (x/x/x)
- * and a DateFormat preference convert it to an mjd and store it at *p.
+tle_sum (char *l)
+{
+	char *lastl = l + 68;
+	int sum;
+
+	for (sum = 0; l < lastl; ) {
+	    char c = *l++;
+	    if (c == '\0')
+		return (-1);
+	    if (isdigit(c))
+		sum += c - '0';
+	    else if (c == '-')
+		sum++;
+	}
+
+	return (*l - '0' == (sum%10) ? 0 : -1);
+}
+
+/* extract the given columns and return value.
+ * N.B. from and to are 1-based within l
+ */
+static double
+tle_fld (char *l, int from, int thru)
+{
+	char buf[32];
+
+	sprintf (buf, "%.*s", thru-from+1, l+from-1);
+	return (atod (buf));
+}
+
+/* extract the exponential value starting at the given column.
+ * N.B. start is 1-based within l
+ */
+static double
+tle_expfld (char *l, int start)
+{
+	char buf[32];
+	double v;
+
+	sprintf (buf, ".%.*s", 5, l+start);
+	v = atod (buf) * pow (10.0, tle_fld(l, start+6, start+7));
+	if (l[start-1] == '-')
+	    v = -v;
+	return (v);
+}
+
+static int
+crack_f (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
+{
+	char *sflds[MAXFLDS];
+	double tmp;
+	int nsf;
+
+	if (nf < 5 || nf > 7) {
+	    if (whynot)
+		sprintf (whynot, "%s: f needs 5-7 fields, not %d",enm(flds),nf);
+	    return (-1);
+	}
+
+	zero_mem ((void *)op, sizeof(ObjF));
+	op->o_type = FIXED;
+
+	nsf = get_fields(flds[1], SUBFLD, sflds);
+	if (nsf > 1) {
+	    switch (sflds[1][0]) {
+	    case 'A': case 'B': case 'C': case 'D': case 'F': case 'G':
+	    case 'H': case 'K': case 'J': case 'L': case 'M': case 'N':
+	    case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':
+	    case 'U': case 'V': case 'Y':
+		op->f_class = sflds[1][0];
+		if (op->f_class == 'B')
+		    op->f_class = 'D';	/* merge B and D since BINARYSTAR */
+		break;
+	    default:
+		if (whynot)
+		    sprintf (whynot, "%s: Bad f class: %c", enm(flds),
+		    						sflds[1][0]);
+		return (-1);
+	    }
+	}
+	if (nsf > 2) {
+	    /* fill f_spect all the way */
+	    char buf[sizeof(op->f_spect)+1];
+	    memset (buf, 0, sizeof(buf));
+	    sprintf (buf, "%.*s", (int)sizeof(op->f_spect), sflds[2]);
+	    memcpy (op->f_spect, buf, (int)sizeof(op->f_spect));
+	}
+
+	nsf = get_fields(flds[2], SUBFLD, sflds);
+	f_scansexa (sflds[0], &tmp);
+	op->f_RA = (float) hrrad(tmp);
+	if (nsf > 1)
+	    op->f_pmRA = (float) 1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
+
+	nsf = get_fields(flds[3], SUBFLD, sflds);
+	f_scansexa (sflds[0], &tmp);
+	op->f_dec = (float) degrad(tmp);
+	if (nsf > 1)
+	    op->f_pmdec = (float)1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
+	if (fabs(op->f_dec) < PI/2)
+	    op->f_pmRA /= cos (op->f_dec);
+
+	set_fmag (op, atod(flds[4]));
+
+	if (nf > 5 && flds[5][0]) {
+	    tmp = op->f_epoch;
+	    crack_year (flds[5], &tmp);
+	    op->f_epoch = (float) tmp;
+	} else
+	    op->f_epoch = J2000;	/* default */
+
+	if (nf > 6) {
+	    op->f_size = (float) atod(flds[6]);
+
+	    /* optional minor axis and position angle subfields */
+	    nsf = get_fields(flds[6], SUBFLD, sflds);
+	    if (nsf == 3) {
+		set_ratio(op, op->s_size, atod(sflds[1]));
+		set_pa(op,degrad(atod(sflds[2])));
+	    } else {
+		set_ratio(op,1,1);	/* round */
+		set_pa(op,0.0);
+	    }
+	}
+
+	return (0);
+}
+
+static int
+crack_e (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
+{
+	if (nf != 13 && nf != 14) {
+	    if (whynot)
+		sprintf (whynot, "%s: e needs 13 or 14 fields, not %d",
+								enm(flds), nf);
+	    return (-1);
+	}
+
+	zero_mem ((void *)op, sizeof(ObjE));
+	op->o_type = ELLIPTICAL;
+
+	op->e_inc = (float) atod (flds[2]);
+	op->e_Om = (float) atod (flds[3]);
+	op->e_om = (float) atod (flds[4]);
+	op->e_a = (float) atod (flds[5]);
+	/* retired op->e_n = (float) atod (flds[6]); */
+	op->e_e = atod (flds[7]);
+	op->e_M = (float) atod (flds[8]);
+	crack_year (flds[9], &op->e_cepoch);
+	crack_okdates (flds[9], &op->e_startok, &op->e_endok);
+	crack_year (flds[10], &op->e_epoch);
+
+	/* magnitude model gk or HG(default). allow prefixes in either field */
+	op->e_mag.whichm = flds[11][0] == 'g' ? MAG_gk : MAG_HG;
+	if (isdigit(flds[11][0]))
+	    op->e_mag.m1 = (float) atod(&flds[11][0]);
+	else
+	    op->e_mag.m1 = (float) atod(&flds[11][1]);
+	if (isdigit(flds[12][0]))
+	    op->e_mag.m2 = (float) atod(&flds[12][0]);
+	else
+	    op->e_mag.m2 = (float) atod(&flds[12][1]);
+
+	if (nf == 14)
+	    op->e_size = (float) atod (flds[13]);
+
+	return (0);
+}
+
+static int
+crack_h (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
+{
+	if (nf != 11 && nf != 12) {
+	    if (whynot)
+		sprintf (whynot, "%s: h needs 11 or 12 fields, not %d",
+								enm(flds), nf);
+	    return (-1);
+	}
+
+	zero_mem ((void *)op, sizeof(ObjH));
+	op->o_type = HYPERBOLIC;
+
+	crack_year (flds[2], &op->h_ep);
+	crack_okdates (flds[2], &op->h_startok, &op->h_endok);
+	op->h_inc = (float) atod (flds[3]);
+	op->h_Om = (float) atod (flds[4]);
+	op->h_om = (float) atod (flds[5]);
+	op->h_e = (float) atod (flds[6]);
+	op->h_qp = (float) atod (flds[7]);
+	crack_year (flds[8], &op->h_epoch);
+	op->h_g = (float) atod (flds[9]);
+	op->h_k = (float) atod (flds[10]);
+
+	if (nf == 12)
+	    op->h_size = (float) atod (flds[11]);
+
+	return (0);
+}
+
+static int
+crack_p (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
+{
+	if (nf != 10 && nf != 11) {
+	    if (whynot)
+		sprintf (whynot, "%s: p needs 10 or 11 fields, not %d",	
+								enm(flds), nf);
+	    return (-1);
+	}
+
+	zero_mem ((void *)op, sizeof(ObjP));
+	op->o_type = PARABOLIC;
+
+	crack_year (flds[2], &op->p_ep);
+	crack_okdates (flds[2], &op->p_startok, &op->p_endok);
+	op->p_inc = (float) atod (flds[3]);
+	op->p_om = (float) atod (flds[4]);
+	op->p_qp = (float) atod (flds[5]);
+	op->p_Om = (float) atod (flds[6]);
+	crack_year (flds[7], &op->p_epoch);
+	op->p_g = (float) atod (flds[8]);
+	op->p_k = (float) atod (flds[9]);
+
+	if (nf == 11)
+	    op->p_size = (float) atod (flds[10]);
+
+	return (0);
+}
+
+static int
+crack_E (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
+{
+	if (nf != 11 && nf != 12) {
+	    if (whynot)
+		sprintf (whynot, "%s: E needs 11 or 12 fields, not %d",
+							    enm(flds), nf);
+	    return (-1);
+	}
+
+	zero_mem ((void *)op, sizeof(ObjES));
+	op->o_type = EARTHSAT;
+	crack_year (flds[2], &op->es_epoch);
+	crack_okdates (flds[2], &op->es_startok, &op->es_endok);
+	op->es_inc = (float) atod (flds[3]);
+	op->es_raan = (float) atod (flds[4]);
+	op->es_e = (float) atod (flds[5]);
+	op->es_ap = (float) atod (flds[6]);
+	op->es_M = (float) atod (flds[7]);
+	op->es_n = atod (flds[8]);
+	op->es_decay = (float) atod (flds[9]);
+	op->es_orbit = atoi (flds[10]);
+	if (nf == 12)
+	    op->es_drag = (float) atod (flds[11]);
+
+	return (0);
+}
+
+static int
+crack_P (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
+{
+	Obj *bi;
+	int nbi;
+	int i;
+
+	nbi = getBuiltInObjs (&bi);
+
+	for (i = 0; i < nbi; i++) {
+	    Obj *bop = bi + i;
+	    if (is_type(bop,PLANETM) && !strcmp (flds[0], bop->o_name)) {
+		memcpy ((void *)op, bop, sizeof(ObjPl));
+		return (0);
+	    }
+	}
+
+	if (whynot)
+	    sprintf (whynot, "%s: Unknown planet or moon", enm(flds));
+	return (-1);
+}
+
+static int
+crack_B (Obj *op, char *flds[MAXFLDS], int nf, char whynot[])
+{
+	char *sflds[MAXFLDS];
+	double tmp;
+	int nsf;
+
+	if (nf != 7) {
+	    if (whynot)
+		sprintf (whynot, "%s: B need 7 fields, not %d", enm(flds), nf);
+	    return (-1);
+	}
+
+	zero_mem ((void *)op, sizeof(ObjB));
+	op->o_type = BINARYSTAR;
+
+	nsf = get_fields(flds[1], SUBFLD, sflds);
+	if (nsf > 1) {
+	    switch (sflds[1][0]) {
+	    case 'a': case 'c': case 'e': case 'x': case 'y': case 'o':
+	    case 's': case 't': case 'u': case 'v': case 'b': case 'd':
+	    case 'q': case 'r': case 'p': case 'U': case 'V': case 'Y':
+		op->f_class = sflds[1][0];
+		break;
+	    default:
+		if (whynot)
+		    sprintf (whynot, "%s: Bad B class: %c", enm(flds),
+		    						sflds[1][0]);
+		return (-1);
+	    }
+	}
+	if (nsf > 2) {
+	    /* fill f_spect all the way */
+	    char buf[sizeof(op->f_spect)+1];
+	    memset (buf, 0, sizeof(buf));
+	    sprintf (buf, "%.*s", (int)sizeof(op->f_spect), sflds[2]);
+	    memcpy (op->f_spect, buf, (int)sizeof(op->f_spect));
+	}
+	if (nsf > 3) {
+	    /* fill b_2spect all the way */
+	    char buf[sizeof(op->b_2spect)+1];
+	    memset (buf, 0, sizeof(buf));
+	    sprintf (buf, "%.*s", (int)sizeof(op->b_2spect), sflds[3]);
+	    memcpy (op->b_2spect, buf, (int)sizeof(op->b_2spect));
+	}
+
+	nsf = get_fields(flds[2], SUBFLD, sflds);
+	f_scansexa (sflds[0], &tmp);
+	op->f_RA = (float) hrrad(tmp);
+	if (nsf > 1)
+	    op->f_pmRA = (float) 1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
+
+	nsf = get_fields(flds[3], SUBFLD, sflds);
+	f_scansexa (sflds[0], &tmp);
+	op->f_dec = (float) degrad(tmp);
+	if (nsf > 1)
+	    op->f_pmdec = (float)1.327e-11*atod(sflds[1]);/*mas/yr->rad/dy*/
+	if (fabs(op->f_dec) < PI/2)
+	    op->f_pmRA /= cos (op->f_dec);
+
+	nsf = get_fields(flds[4], SUBFLD, sflds);
+	if (nsf > 0)
+	    set_fmag (op, atod(sflds[0]));
+	if (nsf > 1)
+	    op->b_2mag = (short)floor((atod(sflds[1]))*MAGSCALE + 0.5);
+
+	if (flds[5][0]) {
+	    tmp = op->f_epoch;
+	    crack_year (flds[5], &tmp);
+	    op->f_epoch = (float) tmp;
+	} else
+	    op->f_epoch = J2000;	/* default */
+
+	nsf = get_fields(flds[6], SUBFLD, sflds);
+	if (nsf == 7) {
+	    int l;
+	    char c;
+
+	    op->b_bo.bo_a = atod(sflds[0]);
+	    op->b_bo.bo_i = atod(sflds[1]);
+	    op->b_bo.bo_O = atod(sflds[2]);
+	    op->b_bo.bo_e = atod(sflds[3]);
+	    op->b_bo.bo_T = atod(sflds[4]);
+	    op->b_bo.bo_o = atod(sflds[5]);
+	    op->b_bo.bo_P = atod(sflds[6]);
+
+	    /* reject some weird entries actually seen in real lists */
+	    if (op->b_bo.bo_a <= 0) {
+		if (whynot)
+		    sprintf (whynot, "%s: Bogus B semi major axis: %g",
+						    enm(flds), op->b_bo.bo_a);
+		return (-1);
+	    }
+	    if (op->b_bo.bo_P <= 0) {
+		if (whynot)
+		    sprintf (whynot, "%s: Bogus B period: %g", enm(flds),
+		    						op->b_bo.bo_P);
+		return (-1);
+	    }
+
+	    /* scale period */
+	    l = strlen (sflds[6]);
+	    c = sflds[6][l-1];
+	    switch (c) {
+	    case 'y': case 'Y':
+		break;
+	    case 'h': case 'H':
+		op->b_bo.bo_P /= (24.0*365.25);
+		break;
+	    case 'd': case 'D':
+		op->b_bo.bo_P /= 365.25;
+		break;
+	    default:
+		if (c != ' ' && !isdigit(c)) {
+		    if (whynot)
+			sprintf (whynot,"%s: B period suffix not Y, D or H: %c",
+								enm(flds), c);
+		    return (-1);
+		}
+	    }
+
+	} else if (nsf==3 || nsf==6 || nsf==9) {
+	    double yr;
+	    int i;
+
+	    op->b_nbp = nsf/3;
+	    for (i = 0; i < nsf; i += 3) {
+		tmp = 0;
+		crack_year (sflds[i+0], &tmp);
+		mjd_year (tmp, &yr);
+		op->b_bp[i/3].bp_ep = (float)yr;
+		op->b_bp[i/3].bp_sep = atod(sflds[i+1]);
+		op->b_bp[i/3].bp_pa = degrad(atod(sflds[i+2]));
+	    }
+	} else {
+	    if (whynot)
+		sprintf (whynot,
+			"%s: B needs 3,6 or 7 subfields in field 7, not %d",
+								enm(flds), nsf);
+	    return (-1);
+	}
+
+	return (0);
+}
+
+/* put all names in nm but load only the first into o_name */
+static int
+crack_name (Obj *op, char *flds[MAXFLDS], int nf, char nm[][MAXNM], int nnm)
+{
+	char *sflds[MAXFLDS];
+	int nsf;
+	int i;
+	
+	nsf = get_fields (flds[0], SUBFLD, sflds);
+	for (i = 0; nm && i < nsf && i < nnm; i++) {
+	    strncpy (nm[i], sflds[i], MAXNM);
+	    nm[i][MAXNM-1] = '\0';
+	}
+	strncpy (op->o_name, sflds[0], MAXNM-1);
+	return (nsf);
+}
+
+/* simple name cracker just for error messages */
+static char *
+enm (char *flds[MAXFLDS])
+{
+	char *sflds[MAXFLDS];
+	int nsf = get_fields (flds[0], SUBFLD, sflds);
+	return (nsf > 0 ? sflds[0] : "Unknown");
+}
+
+/* given either a decimal year (xxxx[.xxx]) or a calendar (x/x/x) date
+ * convert it to an mjd and store it at *p.
  */
 static void
-crack_year (bp, pref, p)
-char *bp;
-PrefDateFormat pref;
-double *p;
+crack_year (char *bp, double *p)
 {
 	int m, y;
@@ -747,270 +791,216 @@
 
 	mjd_cal (*p, &m, &d, &y);	/* init with current */
-	f_sscandate (bp, pref, &m, &d, &y);
+	f_sscandate (bp, PREF_MDY, &m, &d, &y);
 	cal_mjd (m, d, y, p);
 }
 
-/* given an *op and a field id, add it to the given text buffer bp.
- * return the number of characters added to bp.
+/* crack the startok and endok date fields found in several Obj types.
+ * set to 0 if blank or any problems.
+ */
+static void
+crack_okdates (char *fld, float *startok, float *endok)
+{
+	char *sflds[MAXFLDS];
+	double tmp;
+	int m, y;
+	double d;
+	int nsf;
+
+	*startok = *endok = 0;
+	nsf = get_fields(fld, SUBFLD, sflds);
+	if (nsf > 1) {
+	    d = m = y = 0;
+	    f_sscandate (sflds[1], PREF_MDY, &m, &d, &y);
+	    cal_mjd (m, d, y, &tmp);
+	    *startok = (float)tmp;
+	    if (nsf > 2) {
+		d = m = y = 0;
+		f_sscandate (sflds[2], PREF_MDY, &m, &d, &y);
+		cal_mjd (m, d, y, &tmp);
+		*endok = (float)tmp;
+	    }
+	}
+}
+
+/* add startok and endok to string at lp if non-zero.
+ * return number of characters added.
  */
 static int
-db_get_field (op, id, bp)
-Obj *op;
-int id;
-char *bp;
-{
-	char *bpsave = bp;
+get_okdates (char *lp, float *sp, float *ep)
+{
+	char *lp0 = lp;
+
+	if (*sp || *ep) {
+	    *lp++ = '|';
+	    if (*sp)
+		lp += fs_date (lp, *sp);
+	    if (*ep) {
+		*lp++ = '|';
+		lp += fs_date (lp, *ep);
+	    }
+	}
+
+	return (lp - lp0);
+}
+
+static void
+write_f (Obj *op, char lp[])
+{
 	double tmp;
 
-	/* include all the enums and in numeric order to give us the best
-	 * possible chance the compiler will implement this as a jump table.
-	 */
-	switch (id) {
-	case F_RA:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_sexa (bp, radhr(op->f_RA), 2, 36000);
-	    bp += strlen(bp);
-	    break;
-	case F_DEC:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_sexa (bp, raddeg(op->f_dec), 3, 3600);
-	    bp += strlen(bp);
-	    break;
-	case F_EPOCH:
-	    mjd_year (op->f_epoch, &tmp);
-	    sprintf (bp, ",%.6g", tmp); /* %.7g gives 2000.001 */
-	    bp += strlen(bp);
-	    break;
-	case F_MAG:
-	    sprintf (bp, ",%6.2f", get_mag(op));
-	    bp += strlen(bp);
-	    break;
-	case F_SIZE:
-	    sprintf (bp, ",%.7g", op->f_size);
-	    bp += strlen(bp);
-	    if (op->f_ratio || op->f_pa) {
-		sprintf (bp,"|%g|%g", op->f_size*get_ratio(op),
+	lp += sprintf (lp, "%s,f", op->o_name);
+	if (op->f_class)
+	    lp += sprintf (lp, "|%c", op->f_class);
+	if (op->f_spect[0])
+	    lp += sprintf (lp, "|%.*s", (int)sizeof(op->f_spect), op->f_spect);
+	*lp++ = ',';
+	lp += fs_sexa (lp, radhr(op->f_RA), 2, 36000);
+	if (op->f_pmRA)
+	    lp += sprintf (lp, "|%.6g",cos(op->f_dec)*op->f_pmRA/1.327e-11);
+	*lp++ = ',';
+	lp += fs_sexa (lp, raddeg(op->f_dec), 3, 3600);
+	if (op->f_pmdec)
+	    lp += sprintf (lp, "|%.6g", op->f_pmdec/1.327e-11);
+	lp += sprintf (lp, ",%.2f", get_mag(op));
+	mjd_year (op->f_epoch, &tmp);
+	lp += sprintf (lp, ",%.6g", tmp); /* %.7g gives 2000.001 */
+	lp += sprintf (lp, ",%.7g", op->f_size);
+	if (op->f_size && (op->f_ratio || op->f_pa))
+	    lp += sprintf (lp,"|%g|%g", op->f_size*get_ratio(op),
 							    raddeg(get_pa(op)));
-		bp += strlen(bp);
-	    }
-	    break;
-	case F_CLASS:
-	    if (op->f_class) {
-		sprintf (bp, "|%c", op->f_class);
-		bp += strlen(bp);
-	    }
-	    break;
-	case F_SPECT:
-	    if (op->f_spect[0] != '\0') {
-		sprintf (bp, "|%c", op->f_spect[0]);
-		bp += strlen(bp);
-		if (op->f_spect[1] != '\0') {
-		    sprintf (bp, "%c", op->f_spect[1]);
-		    bp += strlen(bp);
-		}
-	    }
-	    break;
-
-	case E_INC:
-	    sprintf (bp, ",%.7g", op->e_inc);
-	    bp += strlen(bp);
-	    break;
-	case E_LAN:
-	    sprintf (bp, ",%.7g", op->e_Om);
-	    bp += strlen(bp);
-	    break;
-	case E_AOP:
-	    sprintf (bp, ",%.7g", op->e_om);
-	    bp += strlen(bp);
-	    break;
-	case E_A:
-	    sprintf (bp, ",%.7g", op->e_a);
-	    bp += strlen(bp);
-	    break;
-	case E_N:
-	    /* retired */
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    break;
-	case E_E:
-	    sprintf (bp, ",%.7g", op->e_e);
-	    bp += strlen(bp);
-	    break;
-	case E_M:
-	    sprintf (bp, ",%.7g", op->e_M);
-	    bp += strlen(bp);
-	    break;
-	case E_CEPOCH:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_date (bp, op->e_cepoch);
-	    bp += strlen(bp);
-	    break;
-	case E_EPOCH:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_date (bp, op->e_epoch);
-	    bp += strlen(bp);
-	    break;
-	case E_M1:
-	    if (op->e_mag.whichm == MAG_gk) {
-		sprintf (bp, ",g%.7g", op->e_mag.m1);
-		bp += strlen(bp);
-	    } else if (op->e_mag.whichm == MAG_HG) {
-		sprintf (bp, ",H%.7g", op->e_mag.m1);
-		bp += strlen(bp);
-	    } else {
-		sprintf (bp, ",%.7g", op->e_mag.m1);
-		bp += strlen(bp);
-	    }
-	    break;
-	case E_M2:
-	    sprintf (bp, ",%.7g", op->e_mag.m2);
-	    bp += strlen(bp);
-	    break;
-	case E_SIZE:
-	    sprintf (bp, ",%.7g", op->e_size);
-	    bp += strlen(bp);
-	    break;
-
-	case H_EP:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_date (bp, op->h_ep);
-	    bp += strlen(bp);
-	    break;
-	case H_INC:
-	    sprintf (bp, ",%.7g", op->h_inc);
-	    bp += strlen(bp);
-	    break;
-	case H_LAN:
-	    sprintf (bp, ",%.7g", op->h_Om);
-	    bp += strlen(bp);
-	    break;
-	case H_AOP:
-	    sprintf (bp, ",%.7g", op->h_om);
-	    bp += strlen(bp);
-	    break;
-	case H_E:
-	    sprintf (bp, ",%.7g", op->h_e);
-	    bp += strlen(bp);
-	    break;
-	case H_QP:
-	    sprintf (bp, ",%.7g", op->h_qp);
-	    bp += strlen(bp);
-	    break;
-	case H_EPOCH:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_date (bp, op->h_epoch);
-	    bp += strlen(bp);
-	    break;
-	case H_G:
-	    sprintf (bp, ",%.7g", op->h_g);
-	    bp += strlen(bp);
-	    break;
-	case H_K:
-	    sprintf (bp, ",%.7g", op->h_k);
-	    bp += strlen(bp);
-	    break;
-	case H_SIZE:
-	    sprintf (bp, ",%.7g", op->h_size);
-	    bp += strlen(bp);
-	    break;
-
-	case P_EP:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_date (bp, op->p_ep);
-	    bp += strlen(bp);
-	    break;
-	case P_INC:
-	    sprintf (bp, ",%.7g", op->p_inc);
-	    bp += strlen(bp);
-	    break;
-	case P_AOP:
-	    sprintf (bp, ",%.7g", op->p_om);
-	    bp += strlen(bp);
-	    break;
-	case P_QP:
-	    sprintf (bp, ",%.7g", op->p_qp);
-	    bp += strlen(bp);
-	    break;
-	case P_LAN:
-	    sprintf (bp, ",%.7g", op->p_Om);
-	    bp += strlen(bp);
-	    break;
-	case P_EPOCH:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_date (bp, op->p_epoch);
-	    bp += strlen(bp);
-	    break;
-	case P_G:
-	    sprintf (bp, ",%.7g", op->p_g);
-	    bp += strlen(bp);
-	    break;
-	case P_K:
-	    sprintf (bp, ",%.7g", op->p_k);
-	    bp += strlen(bp);
-	    break;
-	case P_SIZE:
-	    sprintf (bp, ",%.7g", op->p_size);
-	    bp += strlen(bp);
-	    break;
-
-	case ES_EPOCH:
-	    sprintf (bp, ",");
-	    bp += strlen(bp);
-	    fs_date (bp, op->es_epoch);
-	    bp += strlen(bp);
-	    break;
-	case ES_INC:
-	    sprintf (bp, ",%.7g", op->es_inc);
-	    bp += strlen(bp);
-	    break;
-	case ES_RAAN:
-	    sprintf (bp, ",%.7g", op->es_raan);
-	    bp += strlen(bp);
-	    break;
-	case ES_E:
-	    sprintf (bp, ",%.7g", op->es_e);
-	    bp += strlen(bp);
-	    break;
-	case ES_AP:
-	    sprintf (bp, ",%.7g", op->es_ap);
-	    bp += strlen(bp);
-	    break;
-	case ES_M:
-	    sprintf (bp, ",%.7g", op->es_M);
-	    bp += strlen(bp);
-	    break;
-	case ES_N:
-	    sprintf (bp, ",%.7g", op->es_n);
-	    bp += strlen(bp);
-	    break;
-	case ES_DECAY:
-	    sprintf (bp, ",%.7g", op->es_decay);
-	    bp += strlen(bp);
-	    break;
-	case ES_ORBIT:
-	    sprintf (bp, ",%d", op->es_orbit);
-	    bp += strlen(bp);
-	    break;
-	case ES_DRAG:
-	    sprintf (bp, ",%.7g", op->es_drag);
-	    bp += strlen(bp);
-	    break;
-
-	default:
-	    printf ("BUG! db_set_field: bad id: %d\n", id);
-	    exit (1);
-	}
-
-	return (bp - bpsave);
+}
+
+static void
+write_e (Obj *op, char lp[])
+{
+	lp += sprintf (lp, "%s,e", op->o_name);
+	lp += sprintf (lp, ",%.7g", op->e_inc);
+	lp += sprintf (lp, ",%.7g", op->e_Om);
+	lp += sprintf (lp, ",%.7g", op->e_om);
+	lp += sprintf (lp, ",%.7g", op->e_a);
+	lp += sprintf (lp, ",%.7g", 0.0);		/* retired op->e_n */
+	lp += sprintf (lp, ",%.7g", op->e_e);
+	lp += sprintf (lp, ",%.7g", op->e_M);
+	*lp++ = ',';
+	lp += fs_date (lp, op->e_cepoch);
+	lp += get_okdates (lp, &op->e_startok, &op->e_endok);
+	*lp++ = ',';
+	lp += fs_date (lp, op->e_epoch);
+	if (op->e_mag.whichm == MAG_gk)
+	    lp += sprintf (lp, ",g%.7g", op->e_mag.m1);
+	else if (op->e_mag.whichm == MAG_HG)
+	    lp += sprintf (lp, ",H%.7g", op->e_mag.m1);
+	else
+	    lp += sprintf (lp, ",%.7g", op->e_mag.m1);
+	lp += sprintf (lp, ",%.7g", op->e_mag.m2);
+	lp += sprintf (lp, ",%.7g", op->e_size);
+}
+
+static void
+write_h (Obj *op, char lp[])
+{
+	lp += sprintf (lp, "%s,h", op->o_name);
+	*lp++ = ',';
+	lp += fs_date (lp, op->h_ep);
+	lp += get_okdates (lp, &op->h_startok, &op->h_endok);
+	lp += sprintf (lp, ",%.7g", op->h_inc);
+	lp += sprintf (lp, ",%.7g", op->h_Om);
+	lp += sprintf (lp, ",%.7g", op->h_om);
+	lp += sprintf (lp, ",%.7g", op->h_e);
+	lp += sprintf (lp, ",%.7g", op->h_qp);
+	*lp++ = ',';
+	lp += fs_date (lp, op->h_epoch);
+	lp += sprintf (lp, ",%.7g", op->h_g);
+	lp += sprintf (lp, ",%.7g", op->h_k);
+	lp += sprintf (lp, ",%.7g", op->h_size);
+}
+
+static void
+write_p (Obj *op, char lp[])
+{
+	lp += sprintf (lp, "%s,p", op->o_name);
+	*lp++ = ',';
+	lp += fs_date (lp, op->p_ep);
+	lp += get_okdates (lp, &op->p_startok, &op->p_endok);
+	lp += sprintf (lp, ",%.7g", op->p_inc);
+	lp += sprintf (lp, ",%.7g", op->p_om);
+	lp += sprintf (lp, ",%.7g", op->p_qp);
+	lp += sprintf (lp, ",%.7g", op->p_Om);
+	*lp++ = ',';
+	lp += fs_date (lp, op->p_epoch);
+	lp += sprintf (lp, ",%.7g", op->p_g);
+	lp += sprintf (lp, ",%.7g", op->p_k);
+	lp += sprintf (lp, ",%.7g", op->p_size);
+}
+
+static void
+write_E (Obj *op, char lp[])
+{
+	lp += sprintf (lp, "%s,E", op->o_name);
+	*lp++ = ',';
+	lp += fs_date (lp, op->es_epoch);
+	lp += get_okdates (lp, &op->es_startok, &op->es_endok);
+	lp += sprintf (lp, ",%.7g", op->es_inc);
+	lp += sprintf (lp, ",%.7g", op->es_raan);
+	lp += sprintf (lp, ",%.7g", op->es_e);
+	lp += sprintf (lp, ",%.7g", op->es_ap);
+	lp += sprintf (lp, ",%.7g", op->es_M);
+	lp += sprintf (lp, ",%.7g", op->es_n);
+	lp += sprintf (lp, ",%.7g", op->es_decay);
+	lp += sprintf (lp, ",%d", op->es_orbit);
+	lp += sprintf (lp, ",%.7g", op->es_drag);
+}
+
+static void
+write_B (Obj *op, char lp[])
+{
+	double tmp;
+
+	lp += sprintf (lp, "%s,B", op->o_name);
+	if (op->f_class)
+	    lp += sprintf (lp, "|%c", op->f_class);
+	if (op->f_spect[0])
+	    lp += sprintf (lp, "|%.*s", (int)sizeof(op->f_spect), op->f_spect);
+	if (op->b_2spect[0])
+	    lp += sprintf (lp, "|%.*s", (int)sizeof(op->b_2spect),op->b_2spect);
+	*lp++ = ',';
+	lp += fs_sexa (lp, radhr(op->f_RA), 2, 36000);
+	if (op->f_pmRA)
+	    lp += sprintf (lp, "|%.6g",cos(op->f_dec)*op->f_pmRA/1.327e-11);
+	*lp++ = ',';
+	lp += fs_sexa (lp, raddeg(op->f_dec), 3, 3600);
+	if (op->f_pmdec)
+	    lp += sprintf (lp, "|%.6g", op->f_pmdec/1.327e-11);
+	lp += sprintf (lp, ",%.2f", get_mag(op));
+	lp += sprintf (lp, "|%.2f", op->b_2mag/MAGSCALE);
+	mjd_year (op->f_epoch, &tmp);
+	lp += sprintf (lp, ",%.6g", tmp); /* %.7g gives 2000.001 */
+	if (op->b_nbp == 0) {
+	    lp += sprintf (lp, ",%.6g",  op->b_bo.bo_a);
+	    lp += sprintf (lp, "|%.6g",  op->b_bo.bo_i);
+	    lp += sprintf (lp, "|%.6g",  op->b_bo.bo_O);
+	    lp += sprintf (lp, "|%.6g",  op->b_bo.bo_e);
+	    lp += sprintf (lp, "|%.6g",  op->b_bo.bo_T);
+	    lp += sprintf (lp, "|%.6g",  op->b_bo.bo_o);
+	    lp += sprintf (lp, "|%.6gy", op->b_bo.bo_P);
+	} else {
+	    int i;
+
+	    for (i = 0; i < op->b_nbp; i++) {
+		BinPos *bp = &op->b_bp[i];
+		lp += sprintf (lp, "%c%.6g", i==0?',':'|', bp->bp_ep);
+		lp += sprintf (lp, "|%.6g", bp->bp_sep);
+		lp += sprintf (lp, "|%.6g", raddeg(bp->bp_pa));
+	    }
+	}
+}
+
+static void
+write_P (Obj *op, char lp[])
+{
+
+	lp += sprintf (lp, "%s,P", op->o_name);
 }
 
 /* For RCS Only -- Do Not Edit */
-static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: dbfmt.c,v $ $Date: 2001-10-22 12:08:26 $ $Revision: 1.2 $ $Name: not supported by cvs2svn $"};
+static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: dbfmt.c,v $ $Date: 2004-06-15 16:52:38 $ $Revision: 1.3 $ $Name: not supported by cvs2svn $"};
