Index: /trunk/Ohana/src/libohana/Makefile
===================================================================
--- /trunk/Ohana/src/libohana/Makefile	(revision 3507)
+++ /trunk/Ohana/src/libohana/Makefile	(revision 3508)
@@ -6,4 +6,5 @@
 MAN	=	$(HOME)/doc
 INC	=	$(HOME)/include
+DVO	=	$(HOME)/dvo/src
 DESTBIN	=	$(LBIN)
 DESTLIB	=	$(LLIB)
@@ -30,10 +31,21 @@
 
 LOBJ = \
-$(SRC)/string.$(ARCH).o		$(SRC)/findexec.$(ARCH).o	 \
-$(SRC)/config.$(ARCH).o		$(SRC)/coordops.$(ARCH).o	 \
-$(SRC)/Fread.$(ARCH).o		$(SRC)/glockfile.$(ARCH).o	 \
-$(SRC)/LoadPhotcodes.$(ARCH).o  $(SRC)/photfits.$(ARCH).o	 \
-$(SRC)/phot_catalog.$(ARCH).o   $(SRC)/imreg_datatypes.$(ARCH).o \
-$(SRC)/mosaic_astrom.$(ARCH).o
+$(SRC)/string.$(ARCH).o		 \
+$(SRC)/findexec.$(ARCH).o	 \
+$(SRC)/glockfile.$(ARCH).o	 \
+$(SRC)/config.$(ARCH).o		 \
+$(SRC)/coordops.$(ARCH).o	 \
+$(SRC)/Fread.$(ARCH).o		 \
+$(SRC)/Fseek.$(ARCH).o           \
+$(SRC)/LoadPhotcodes.$(ARCH).o   \
+$(SRC)/photfits.$(ARCH).o	 \
+$(SRC)/phot_catalog.$(ARCH).o    \
+$(SRC)/imreg_datatypes.$(ARCH).o \
+$(SRC)/mosaic_astrom.$(ARCH).o   \
+$(SRC)/fits_db.$(ARCH).o	 
+
+DOBJ = \
+$(DVO)/spectrum.$(ARCH).o \
+$(DVO)/spectrum-ascii.$(ARCH).o
 
 $(DESTLIB)/libohana.a: $(LIB)/libohana.$(ARCH).a
@@ -43,7 +55,8 @@
 
 $(LIB)/libohana.$(ARCH).a: $(HOBJ) $(LOBJ)
+	cd dvo && make install
 	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
 	rm -f $(LIB)/libohana.$(ARCH).a
-	ar rcv $(LIB)/libohana.$(ARCH).a $(LOBJ)
+	ar rcv $(LIB)/libohana.$(ARCH).a $(LOBJ) $(DOBJ)
 	$(RANLIB) $(LIB)/libohana.$(ARCH).a
 
@@ -60,4 +73,5 @@
 	rm -f */*.o
 	rm -f */*.a
+	cd dvo && make clean
 
 dist: clean
Index: /trunk/Ohana/src/libohana/doc/autocode.txt
===================================================================
--- /trunk/Ohana/src/libohana/doc/autocode.txt	(revision 3508)
+++ /trunk/Ohana/src/libohana/doc/autocode.txt	(revision 3508)
@@ -0,0 +1,71 @@
+
+This directory contains a collection of autocoded FITS I/O routines
+used to define FITS Table DB functions.  
+
+The autocoder program is a perl script 'generate'.  This scripts takes
+as input a schema file and a template source code file, and produces
+an output file from these two inputs.  A single schema file is meant
+to be associated with a single data concept which is being coded.  For
+example, in the case of the FITS DB tables, a single schema file
+defines a single FITS table, or equivalently, a single C structure
+representing a row in that FITS table.
+
+Schema File
+
+The schema file currently consists of two types of information.
+
+First, there are simple keyword / name pairs which the autocoder
+simply applies as a direct replacement anywhere in the template.  For
+example, the keyword NAME replaces any instance of "$NAME" in the
+template with the corresponding value.  
+
+Second, there is a special type of keyword: FIELD.  The FIELD entry
+defines an entry in the data structure.  The FIELD entry is followed
+by the following comma-separated pieces of information:
+
+- the element name
+- the element data type
+- the element description
+- the element physical unit
+
+Template File
+
+The template file is a source code in whatever language is desired.
+Within the template, the defined keywords may be used as desired,
+wherever needed.  In addition, there are special directives which
+invoke additional special behavior.  All special directives have the
+form of comments within their target language.  They are replaced with
+a block of code in that target language, normally one which iterates
+over the FIELD elements of the schema file.  As such, the directive
+appropriate for one language should not be used within code for a
+different language.  Here is a list of existing special directives:
+
+/** STRUCT DEFINITION **/
+
+This tells the autocoder to create a structure definition for the
+schema.  The structure definition creates a structure with elements
+based on the FIELD entries, with the name $NAME (NOTE: this is perhaps
+making too much of an assumption.  we could require the template to
+provide the wrapper: "typedef struct { } $NAME;" and have the
+autocoder only insert the field lines).  
+
+/** TABLE DEFINITION **/
+
+This tells the autocoder to output the lines which add a column to an
+exiting empty table.  The assumption is that the template contains
+code to initialize a table.  It then invokes the table definition
+code, which defines each of the appropriate columns.  This is perhaps
+followed by some code which finalizes the table definition.  (Note:
+the code output by the autocoder in this block is not very flexible:
+it the current example, it explicitly uses the Elixir FITS Table
+functions, and refers to some data elements in the template code.  The
+latter could possibly be more abstracted with the keyword / value
+pairs, but in any case, the autocoded lines will have to be
+constructed somewhat by hand for a specific API set.
+
+/** BYTE SWAP **/
+
+This tells the autocoder to output code defining the byte swaps
+appropriat to the data structure.  Again, the resulting code depends a
+bit on the intended use and API set.
+
Index: /trunk/Ohana/src/libohana/dvo/Makefile
===================================================================
--- /trunk/Ohana/src/libohana/dvo/Makefile	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/Makefile	(revision 3508)
@@ -0,0 +1,90 @@
+default: dvo-autocode
+help:
+	@echo "make options: install dvo-autocode (default)"
+
+include ../../../Configure
+
+HOME	=	$(ROOT)/src/libohana/dvo
+SRC	=	$(HOME)/src
+BIN	=	$(HOME)/bin
+DEF	=	$(HOME)/def
+LIB	=	$(HOME)/lib
+INC	=	$(HOME)/include
+MAN	= 	$(HOME)/doc
+DESTLIB	=	$(LLIB)
+DESTINC	=	$(LINC)
+DESTMAN	=	$(LMAN)
+
+INCS	=	-I$(INC) -I$(LINC)
+LIBS	= 	-L$(LLIB)
+CFLAGS	=	$(INCS) -D$(ARCH)
+LFLAGS	=	$(LIBS)
+
+install: $(DESTINC)/dvo-autocode.h $(DESTLIB)/libdvo-autocode.a
+	@echo done install
+
+dvo-autocode: $(INC)/dvo-autocode.h $(LIB)/libdvo-autocode.$(ARCH).a 
+	@echo done dvo-autocode
+
+LIBOBJ = \
+$(SRC)/spectrum.$(ARCH).o \
+$(SRC)/spectrum-ascii.$(ARCH).o
+
+LIBINC = \
+$(INC)/spectrum.h \
+$(INC)/spectrum-ascii.h
+
+COMINC = \
+$(DEF)/common.h
+
+$(LIBOBJ): $(INC)/dvo-autocode.h
+
+$(INC)/dvo-autocode.h: $(LIBINC)
+	cat $(COMINC) $(LIBINC) > $(INC)/dvo-autocode.h
+	@echo done with libdvo-autocode.a:
+
+$(DESTINC)/dvo-autocode.h: $(INC)/dvo-autocode.h
+	@if [ ! -d $(DESTINC) ]; then mkdir -p $(DESTINC); fi
+	rm -f $(DESTINC)/dvo-autocode.h
+	cp $(INC)/dvo-autocode.h $(DESTINC)/
+	@echo installed dvo-autocode.h
+
+$(LIB)/libdvo-autocode.$(ARCH).a: $(LIBOBJ)
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $(LIB)/libdvo-autocode.$(ARCH).a
+	ar rcv $(LIB)/libdvo-autocode.$(ARCH).a $(LIBOBJ)
+	$(RANLIB) $(LIB)/libdvo-autocode.$(ARCH).a
+	@echo done with libdvo-autocode.$(ARCH).a
+
+$(DESTLIB)/libdvo-autocode.a: $(LIB)/libdvo-autocode.$(ARCH).a 
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f  $(DESTLIB)/libdvo-autocode.a
+	cp $(LIB)/libdvo-autocode.$(ARCH).a $(DESTLIB)/libdvo-autocode.a
+	@echo installed libdvo-autocode.a
+
+$(INC)/%.h: $(DEF)/%.d $(DEF)/dvo-autocode.h
+	@if [ ! -d $(INC) ]; then mkdir -p $(INC); fi
+	generate $< $(DEF)/dvo-autocode.h $@
+	@echo done with $*.h
+
+$(SRC)/%.c: $(DEF)/%.d $(DEF)/dvo-autocode.c
+	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
+	generate $< $(DEF)/dvo-autocode.c $@
+	@echo done with $*.c
+
+%.$(ARCH).o: %.c
+	$(CC) $(CFLAGS) -c $*.c -o $@
+	@echo done with $*.o
+
+clean:	
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*.a"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+	rm -f `find src -name "*.c"`
+	rm -f `find include -name "*.h"`
+# 	this is an unusual target!  it deletes .c and .h files!
+
+.PRECIOUS: $(SRC)/%.c
+.PRECIOUS: %.$(ARCH).o
+.PRECIOUS: $(BIN)/%.$(ARCH)
Index: /trunk/Ohana/src/libohana/dvo/def/common.h
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/common.h	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/def/common.h	(revision 3508)
@@ -0,0 +1,25 @@
+# include <ohana.h>
+
+# define SWAP_BYTE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+1]; byte[X+1] = tmp;
+# define SWAP_WORD(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+3]; byte[X+3] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+2]; byte[X+2] = tmp;
+# define SWAP_DBLE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+7]; byte[X+7] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+6]; byte[X+6] = tmp; \
+  tmp = byte[X+2]; byte[X+2] = byte[X+5]; byte[X+5] = tmp; \
+  tmp = byte[X+3]; byte[X+3] = byte[X+4]; byte[X+4] = tmp;
+
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+# ifdef dec
+# define BYTE_SWAP
+# endif
+
Index: /trunk/Ohana/src/libohana/dvo/def/dvo-autocode.c
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/dvo-autocode.c	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/def/dvo-autocode.c	(revision 3508)
@@ -0,0 +1,60 @@
+# include "dvo-autocode.h"
+
+int fits_convert_$STRUCT ($STRUCT *data, int size, int nitems) {
+
+  int i;
+  unsigned char *byte, tmp;
+
+  if (size != $SIZE) { 
+    fprintf (stderr, "ERROR: mismatch in data types $STRUCT: %d vs %d\n",
+	     size, $SIZE);
+    exit (1);
+  }
+
+  /* provide initial values to avoid compiler warnings for non-BYTE_SWAP arch */
+  i = tmp = 0;
+  byte = NULL;
+
+# ifdef BYTE_SWAP
+  byte = (char *) data;
+  for (i = 0; i < nitems; i++, byte += $SIZE) {
+    /** BYTE SWAP **/
+  }
+# endif  
+
+  return (TRUE);
+} 
+
+/*** add test of EXTNAME and header-defined columns? ***/
+$STRUCT *fits_table_get_$STRUCT (FTable *ftable, int *Ndata) {
+
+  $STRUCT *data;
+
+  *Ndata = ftable[0].header[0].Naxis[1];
+  data = ($STRUCT *) ftable[0].buffer;
+  fits_convert_$STRUCT (data, sizeof ($STRUCT), *Ndata);
+  
+  return (data);
+}
+
+int fits_table_set_$STRUCT (FTable *ftable, $STRUCT *data, int Ndata) {
+
+  Header *header;
+
+  header = ftable[0].header;
+
+  /* create table header */
+  fits_create_table_header (header, "$TYPE", "$EXTNAME");
+
+  /* define table layout */
+  /** TABLE DEFINITION **/
+
+  /* create table */
+  fits_create_table (header, ftable);
+
+  /* add data values */
+  fits_convert_$STRUCT (data, sizeof ($STRUCT), Ndata);
+  fits_add_rows (ftable, (char *) data, Ndata, sizeof ($STRUCT));
+
+  return (TRUE);
+}
Index: /trunk/Ohana/src/libohana/dvo/def/dvo-autocode.h
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/dvo-autocode.h	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/def/dvo-autocode.h	(revision 3508)
@@ -0,0 +1,6 @@
+
+/** STRUCT DEFINITION **/
+
+$STRUCT *fits_table_get_$STRUCT (FTable *table, int *Ndata);
+int      fits_table_set_$STRUCT (FTable *ftable, $STRUCT *data, int Ndata);
+int      fits_convert_$STRUCT ($STRUCT *data, int size, int nitems);
Index: /trunk/Ohana/src/libohana/dvo/def/smpdata.d
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/smpdata.d	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/def/smpdata.d	(revision 3508)
@@ -0,0 +1,17 @@
+# name of structure type
+STRUCT  SMPData
+EXTNAME SMPFILE
+
+# elements of data structure / FITS table
+FIELD X,      X_PIX,      float,    x coord,              pixels
+FIELD Y,      Y_PIX,      float,    y coord,              pixels
+FIELD M,      MAG_RAW,    float,    inst mags,            mags
+FIELD dM,     MAG_ERR,    float,    inst mag error,       mags
+FIELD Mgal,   MAG_GAL,    float,    galaxy mag,           mags
+FIELD Map,    MAG_AP,     float,    aperture mag,         mags
+FIELD sky,    LOG_SKY,    float,    log-10 of sky,        cnts/sec
+FIELD fx,     FWHM_X,     float,    semi-major,           pixels
+FIELD fy,     FWHM_Y,     float,    semi-minor,           pixels
+FIELD df,     THETA,      float,    ellipse angle,        degrees
+FIELD dophot, DOPHOT,     char,     dophot type,          none
+FIELD dummy,  DUMMY,      char[3],  padding,              none
Index: /trunk/Ohana/src/libohana/dvo/def/spectrum-ascii.d
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/spectrum-ascii.d	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/def/spectrum-ascii.d	(revision 3508)
@@ -0,0 +1,29 @@
+# name of structure type
+STRUCT  SpectrumASCII
+EXTNAME SPECTRUM
+TYPE    TABLE
+SIZE    328
+
+# elements of data structure / FITS table
+FIELD filename,   FILENAME,   char[32],    filename in db,        
+FIELD pathname,   PATHNAME,   char[64],    fullpath in db,        
+FIELD instrument, INSTRUMENT, char[16],    instrument,            
+FIELD telescope,  TELESCOPE,  char[16],    telescope,             
+FIELD objname,    OBJNAME,    char[16],    object name,           
+FIELD extname,    EXTNAME,    char[16],    extname in file,       
+
+FIELD ra,         RA,         float[10.6], ra,                    degrees
+FIELD dec,        DEC,        float[10.6], dec,                   degrees
+FIELD exptime,    EXPTIME,    float[6.1],  exposure time,         seconds
+FIELD airmass,    AIRMASS,    float[5.3],  airmass,               none
+FIELD Ws,         Ws,         float[7.2],  spectral range start,  Angstrom
+FIELD We,         We,         float[7.2],  spectral range end,    Angstrom
+FIELD dW,         dW,         float[7.2],  spectral resolution,   Angstrom / pix
+	       			      
+FIELD Nspec,      NSPECTRA,   int[3],      number of spectra,     none
+FIELD obstime,    OBS_TIME,   char[20],    time of measurement,   yyyy/mm/dd
+FIELD regtime,    REG_TIME,   char[20],    time of registration,  yyyy/mm/dd
+	       			      
+FIELD mode,       MODE,       int[2],      phu/mef/ext,           
+FIELD state,      STATE,      int[2],      raw/wav/flx/etc,       
+FIELD flag,       FLAG,       int[3],      status flags,          
Index: /trunk/Ohana/src/libohana/dvo/def/spectrum.d
===================================================================
--- /trunk/Ohana/src/libohana/dvo/def/spectrum.d	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/def/spectrum.d	(revision 3508)
@@ -0,0 +1,32 @@
+# name of structure type
+STRUCT  Spectrum
+EXTNAME SPECTRUM_DATABASE
+TYPE    BINTABLE
+SIZE    216
+
+# elements of data structure / FITS table
+	       			      
+FIELD ra,         RA,         float,     ra,                    degrees
+FIELD dec,        DEC,        float,     dec,                   degrees
+FIELD exptime,    EXPTIME,    float,     exposure time,         seconds
+FIELD airmass,    AIRMASS,    float,     airmass,               
+FIELD Ws,         Ws,         float,     spectral range start,  Angstrom
+FIELD We,         We,         float,     spectral range end,    Angstrom
+FIELD dW,         dW,         float,     spectral resolution,   Angstrom / pix
+	       			      
+FIELD Nspec,      NSPECTRA,   int,       number of spectra,     
+FIELD obstime,    OBS_TIME,   int,       time of measurement,   seconds since 1 Jan 1970 UT
+FIELD regtime,    REG_TIME,   int,       time of registration,  seconds since 1 Jan 1970 UT
+	       			      
+FIELD mode,       MODE,       char,      phu/mef/ext           
+FIELD state,      STATE,      char,      raw/wav/flx/etc       
+FIELD flag,       FLAG,       char,      status flags
+FIELD extra,      EXTRA,      char[13],  room for expansion
+
+FIELD pathname,   PATHNAME,   char[64],  fullpath in db
+FIELD filename,   FILENAME,   char[32],  filename in db
+FIELD extname,    EXTNAME,    char[16],  extname in file,       
+
+FIELD instrument, INSTRUMENT, char[16],  instrument,            
+FIELD telescope,  TELESCOPE,  char[16],  telescope,             
+FIELD objname,    OBJNAME,    char[16],  object name,           
Index: /trunk/Ohana/src/libohana/dvo/generate
===================================================================
--- /trunk/Ohana/src/libohana/dvo/generate	(revision 3508)
+++ /trunk/Ohana/src/libohana/dvo/generate	(revision 3508)
@@ -0,0 +1,277 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 3) { die "generate (schema) (template) (output)\n"; }
+
+$schema   = $ARGV[0];
+$template = $ARGV[1];
+$output   = $ARGV[2];
+
+&parse_schema;
+&parse_template;
+exit 0;
+
+sub parse_schema {
+    open (FILE, "$schema");
+    @list = <FILE>;
+    close (FILE);
+
+    $NAME    = "";
+    $FILE    = "";
+    $Nfield  = 0;
+    $TIMEOUT = 0;
+
+    &init_key ("TIMEOUT");
+    &init_key ("NAME");
+    &init_key ("EXTNAME");
+    &init_key ("STRUCT");
+    &init_key ("FILE");
+    &init_key ("SIZE");
+    &init_key ("TYPE");
+
+    foreach $line (@list) {
+	chop $line;
+	($key, $value) = split (" ", $line, 2);
+	
+	&set_keypair ($key, $value);
+
+	# there are used internally (not just a replacement)
+	if ($key eq "TYPE") { $TYPE = $value; }
+	if ($key eq "STRUCT") { $STRUCT = $value; }
+
+	# not a simple key/value entry
+	if ($key eq "FIELD") {
+	    ($element, $field, $format, $comment, $unit) = split (/,\s+/, $value);
+	    push @element, $element;
+	    push @field,   $field;
+	    push @format,  $format;
+	    push @comment, $comment;
+	    push @unit,    $unit;
+	}
+    }
+    if ($TYPE eq "BINTABLE") { &count_bintablesize; }
+    if ($TYPE eq "TABLE") { &count_tablesize; }
+}
+
+sub parse_template {
+    open (FILE, $template);
+    @list = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$output");
+
+    foreach $line (@list) {
+	
+	&check_keypairs;
+
+	print FILE $line;
+
+	# fill in structure
+	if ($line =~ m|/\*\* STRUCT DEFINITION \*\*/|) {
+	    &write_structure;
+	}
+
+	# fill in structure
+	if ($line =~ m|/\*\* TABLE DEFINITION \*\*/|) {
+	    if ($TYPE eq "BINTABLE") { &write_bintabledefs; }
+	    if ($TYPE eq "TABLE")    { &write_tabledefs; }
+	}
+
+	# fill in swaps
+	if ($line =~ m|/\*\* BYTE SWAP \*\*/|) {
+	    &write_byteswaps;
+	}
+    }
+    close (FILE);
+}
+
+sub write_bintabledefs {
+
+    for ($i = 0; $i < @field; $i++) {
+	# add [\d\.] to match ascii-type formats
+	($type, $length) = $format[$i] =~ m|^(\w+)\[(\d+)\]|;
+	if (!$type && !$length) { $type = $format[$i]; }
+
+	if ($type eq "char") {
+	    if ($length == 0) { 
+		$pt1 = sprintf "A";
+	    } else {
+		$pt1 = sprintf "%dA", $length;
+	    }
+	}
+
+	if ($type eq "byte")   { $pt1 = "B"; }
+	if ($type eq "short")  { $pt1 = "I"; }
+	if ($type eq "int")    { $pt1 = "J"; }
+	if ($type eq "float")  { $pt1 = "E"; }
+	if ($type eq "double") { $pt1 = "D"; }
+
+	printf FILE "  fits_define_bintable_column (header, ";
+	printf FILE "\"%s\",   ", $pt1;
+	printf FILE "\"%s\",   ", $field[$i];
+	printf FILE "\"%s\", ",   $comment[$i];
+	printf FILE "\"%s\", 1.0, 0.0);\n", $unit[$i];
+    }
+
+}
+
+sub write_tabledefs {
+
+    for ($i = 0; $i < @field; $i++) {
+	($type, $length) = $format[$i] =~ m|^(\w+)\[([\d\.]+)\]|;
+	if (!$type && !$length) { die "format must be specified for ASCII table"; }
+
+	if ($type eq "char")   { $pt1 = sprintf "A%s", $length; }
+	if ($type eq "byte")   { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "short")  { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "int")    { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "float")  { $pt1 = sprintf "F%s", $length; }
+	if ($type eq "double") { $pt1 = sprintf "F%s", $length; }
+
+	printf FILE "  fits_define_table_column (header, ";
+	printf FILE "\"%s\", ",   $pt1;
+	printf FILE "\"%s\", ",   $field[$i];
+	printf FILE "\"%s\", ",   $comment[$i];
+	printf FILE "\"%s\");\n", $unit[$i];
+    }
+
+}
+
+sub write_structure {
+    print FILE "typedef struct {\n";
+    for ($i = 0; $i < @element; $i++) {
+	($type, $length) = $format[$i] =~ m|^(\w+)\[([\d\.]+)\]|;
+	if (!$type && !$length) { $type = $format[$i]; }
+
+	if (($type eq "char") && ($length != 0)) { 
+	    $pt2 = sprintf "%s[%d];", $element[$i], $length;
+	} else {
+	    $pt2 = sprintf "%s;", $element[$i];
+	}
+
+	if ($unit[$i] eq "") {
+	    $pt3 = sprintf "// %s", $comment[$i];
+	} else {
+	    $pt3 = sprintf "// %s (%s)", $comment[$i], $unit[$i];
+	}
+	printf FILE "  %-16s %-21s %s\n", $type, $pt2, $pt3;
+    }    
+    print FILE "} $STRUCT;\n";
+}
+
+sub write_byteswaps {
+    $N = 0;
+    for ($i = 0; $i < @field; $i++) {
+	($type, $length) = $format[$i] =~ m|^(\w+)\[([\d\.]+)\]|;
+	if (!$type && !$length) { $type = $format[$i]; }
+
+	if ($type eq "char") {
+	    if ($length == 0) { 
+		$N ++;
+	    } else {
+		$N += $length;
+	    }
+	    next;   # skip byte swap command
+	}
+	if ($type eq "byte")  {
+	    $N ++;
+	    next;
+	}
+	if ($type eq "short")  {
+	    $T = "BYTE";
+	    $n = 2;
+	}
+	if ($type eq "float")  {
+	    $T = "WORD";
+	    $n = 4;
+	}
+	if ($type eq "int")    {
+	    $T = "WORD";
+	    $n = 4;
+	}
+	if ($type eq "double") { 
+	    $T = "DBLE";
+	    $n = 8;
+	}
+	printf FILE "    SWAP_%s (%d); // %s\n", $T, $N, $field[$i];
+	$N += $n;
+    }
+}
+
+sub count_bintablesize {
+
+    $Nbytes = 0;
+    for ($i = 0; $i < @field; $i++) {
+
+	# add [\d\.] to match ascii-type formats
+	($type, $length) = $format[$i] =~ m|^(\w+)\[(\d+)\]|;
+	if (!$type && !$length) { 
+	    $type = $format[$i]; 
+	    $length = 0;
+	}
+
+	if ($type eq "char") {
+	    if ($length) {
+		$Nbytes += $length;
+	    } else {
+		$Nbytes ++;
+	    }
+	}
+	if ($type eq "double") { $Nbytes += 8; }
+	if ($type eq "int")    { $Nbytes += 4; }
+	if ($type eq "short")  { $Nbytes += 2; }
+	if ($type eq "float")  { $Nbytes += 4; }
+    }
+    return ($Nbytes);
+}
+
+sub count_tablesize {
+
+    $Nbytes = 0;
+    for ($i = 0; $i < @field; $i++) {
+	($length) = $format[$i] =~ m|^\w+\[([\d\.]+)\]|;
+	if ($length == 0) { die "ASCII table format requires field size"; }
+	$Nbytes += $length;
+    }
+    return ($Nbytes);
+}
+
+sub init_key {
+    my ($key)   = $_[0];
+
+    push @key, $key;
+    push @value, "";
+}
+
+sub set_keypair {
+    my ($i);
+    my ($key)   = $_[0];
+    my ($value) = $_[1];
+
+    for ($i = 0; $i < @key; $i++) {
+	if ($key eq $key[$i]) {
+	    if ($value[$i] ne "") { die "key is multiply defined\n"; }
+	    $value[$i] = $value;
+	    return;
+	}
+    }
+}
+
+sub check_keypairs {
+    my ($i);
+    for ($i = 0; $i < @key; $i++) {
+	if ($line =~ m|\$$key[$i]|) {
+#	    print "$key[$i]  -- $value[$i]\n";
+	    if ($value[$i] eq "") { die "missing value for required key $key[$i]\n"; }
+	    $line =~ s|\$$key[$i]|$value[$i]|g;
+	}
+    }
+}
+
+# we need to find the structure size, including padding 
+# i'm not sure I know the answer to this: it is probably 
+# the total number of bytes rounded up to the largest 
+# data item in the structure (ie, 8 for a double, etc)
+# if we have the size, then we can double check the structure
+# against the expectation at runtime.  for the moment,
+# calculate by hand and add to def.d file 
+
Index: /trunk/Ohana/src/libohana/include/dvo.h
===================================================================
--- /trunk/Ohana/src/libohana/include/dvo.h	(revision 3507)
+++ /trunk/Ohana/src/libohana/include/dvo.h	(revision 3508)
@@ -3,4 +3,129 @@
 # define LONEOS    0
 # define PANSTARRS 0
+
+/*** this file uses data types which must have fixed sizes regardless 
+     of the platform.  It originally used the basic C primitives: 
+       float, double, int, short int, unsigned long int, etc.
+     this breaks under 64 bit (and probably on other systems).
+     I should define internal data types which should be set by the 
+     use of # define statements if needed.  I will cheat for now and use
+     the time_t to replace unsigned long int in this file 
+***/
+
+# define e_time unsigned int
+
+/* image data modes in RegImage */
+enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE};
+enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE};
+
+/* convert these to enums? */
+/* RegImage.flag values */
+# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
+
+/* catalog values to be loaded */
+# define LOAD_AVES 0x01
+# define LOAD_MEAS 0x02
+# define LOAD_MISS 0x04
+# define LOAD_SECF 0x08
+
+/* invalid mag value */
+# define NO_MAG    0x7fff
+# define NO_ERR    0xff
+
+/* photometry code types */
+# define PHOT_PRI 0x01
+# define PHOT_SEC 0x02
+# define PHOT_DEP 0x03
+# define PHOT_REF 0x04
+# define PHOT_ALT 0x05  /* never stored, only for look-ups */
+
+/* Image.code values.  these are codes to note bad images */
+# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
+# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
+# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
+# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
+# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
+
+/* Measure.flags values */
+# define ID_MEAS_NOCAL        0x0001
+# define ID_MEAS_POOR         0x0002
+# define ID_MEAS_SKIP         0x0004
+# define ID_MEAS_AREA         0x0008
+# define BLEND_IMAGE          0x0100 
+# define BLEND_CATALOG        0x0200
+# define BLEND_IMAGE_NEIGHBOR 0x1000
+# define ID_MEAS_TRAIL        0x2000
+# define ID_MEAS_GHOST        0x4000
+
+/* Average.code values */
+# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
+# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_VARIABLE   0x2000 /* not currently set? */
+# define ID_ASTEROID   0x2000 /* identified with an asteroid */
+# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
+# define ID_MOVING     0x8000
+# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
+# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
+# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
+# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
+# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
+
+/* 
+   BLEND_IMAGE: the star on an image is matched with more 
+      than one star in the catalog (image has worse seeing than catalog)
+   BLEND_CATALOG: the star in the catalog is matched with more 
+      than one star on the image (image has better seeing than catalog)
+   CALIBRATED: relative photometry has been performed on this measurement
+   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
+      than one star in the catalog, but not in the same catalog file.
+*/
+
+/*** FITS DB structure  ***/
+typedef struct {
+  FILE  *f;
+  char  *filename;
+  int    dbstate;
+  int    lockstate;
+  double timeout;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+} FITS_DB;
+
+/* the standard astrometric coordinates structure */
+typedef struct {
+  double   crval1, crval2;
+  float    crpix1, crpix2;
+  float    cdelt1, cdelt2;
+  float    pc1_1, pc1_2;
+  float    pc2_1, pc2_2;
+  float    polyterms[7][2];
+  char     ctype[15];
+  char     Npolyterms;
+} Coords;  /* 120 bytes / Coords */
+
+/*** FITS_DB functions ***/
+
+/* in fits_db.c */
+int   fits_db_init                PROTO((FITS_DB *db));
+int   fits_db_lock                PROTO((FITS_DB *db, char *filename));
+int   fits_db_load                PROTO((FITS_DB *db));
+int   fits_db_close               PROTO((FITS_DB *db));
+int   fits_db_free                PROTO((FITS_DB *db));
+int   fits_db_save                PROTO((FITS_DB *db));
+int   fits_db_update              PROTO((FITS_DB *db, VTable *vtable));
+
+/* in coords.c */
+int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
+int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
+int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
+int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
+int  GetCoords (Coords *coords, Header *header);
+int  PutCoords (Coords *coords, Header *header);
+void RegisterMosaic (Coords *coords);
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
 
 # if (LONEOS)
@@ -16,2 +141,9 @@
 # endif
 
+# include <dvo-autocode.h>
+
+/* these functions refer to the DVO structures define in the includes above */
+int   Fread (void *ptr, int size, int nitems, FILE *f, char *type);
+int   Fwrite (void *ptr, int size, int nitems, FILE *f, char *type);
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+int   ConvertStruct (char *buffer, int size, int Nbytes, char *type);
Index: /trunk/Ohana/src/libohana/include/elixir.h
===================================================================
--- /trunk/Ohana/src/libohana/include/elixir.h	(revision 3507)
+++ /trunk/Ohana/src/libohana/include/elixir.h	(revision 3508)
@@ -11,74 +11,4 @@
 # ifndef ELIXIR_H
 # define ELIXIR_H
-
-# define e_time unsigned int
-
-/* image data modes in RegImage */
-enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE};
-enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE};
-
-/* convert these to enums? */
-/* RegImage.flag values */
-# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
-
-/* catalog values to be loaded */
-# define LOAD_AVES 0x01
-# define LOAD_MEAS 0x02
-# define LOAD_MISS 0x04
-# define LOAD_SECF 0x08
-
-/* invalid mag value */
-# define NO_MAG    0x7fff
-# define NO_ERR    0xff
-
-/* photometry code types */
-# define PHOT_PRI 0x01
-# define PHOT_SEC 0x02
-# define PHOT_DEP 0x03
-# define PHOT_REF 0x04
-# define PHOT_ALT 0x05  /* never stored, only for look-ups */
-
-/* Image.code values.  these are codes to note bad images */
-# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
-# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
-# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
-# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
-# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
-
-/* Measure.flags values */
-# define ID_MEAS_NOCAL        0x0001
-# define ID_MEAS_POOR         0x0002
-# define ID_MEAS_SKIP         0x0004
-# define ID_MEAS_AREA         0x0008
-# define BLEND_IMAGE          0x0100 
-# define BLEND_CATALOG        0x0200
-# define BLEND_IMAGE_NEIGHBOR 0x1000
-# define ID_MEAS_TRAIL        0x2000
-# define ID_MEAS_GHOST        0x4000
-
-/* Average.code values */
-# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
-# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
-# define ID_PROPER     0x0400 /* star with large proper motion */
-# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
-# define ID_VARIABLE   0x2000 /* not currently set? */
-# define ID_ASTEROID   0x2000 /* identified with an asteroid */
-# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
-# define ID_MOVING     0x8000
-# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
-# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
-# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
-# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
-# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
-
-/* 
-   BLEND_IMAGE: the star on an image is matched with more 
-      than one star in the catalog (image has worse seeing than catalog)
-   BLEND_CATALOG: the star in the catalog is matched with more 
-      than one star on the image (image has better seeing than catalog)
-   CALIBRATED: relative photometry has been performed on this measurement
-   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
-      than one star in the catalog, but not in the same catalog file.
-*/
 
 /************  database structures ************************************/
@@ -194,16 +124,4 @@
   short int dM;               /* scatter on alt mag */
 } SecFilt; /* 6 byte / SecFilt */
-
-/* the standard astrometric coordinates structure */
-typedef struct {
-  double   crval1, crval2;
-  float    crpix1, crpix2;
-  float    cdelt1, cdelt2;
-  float    pc1_1, pc1_2;
-  float    pc2_1, pc2_2;
-  float    polyterms[7][2];
-  char     ctype[15];
-  char     Npolyterms;
-} Coords;  /* 120 bytes / Coords */
 
 /* image structure for binary data storage of image data */
@@ -296,17 +214,4 @@
 int save_catalog (Catalog *catalog, char VERBOSE);
 
-int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
-int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
-int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
-int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
-int  GetCoords (Coords *coords, Header *header);
-int  PutCoords (Coords *coords, Header *header);
-void RegisterMosaic (Coords *coords);
-void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
-int FindMosaicForImage (Image *images, int Nimages, int entry);
-int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
-int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
-int BuildChipMatch (Image *images, int Nimages);
-
 int FindMosaicForImage (Image *images, int Nimages, int entry);
 int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
Index: /trunk/Ohana/src/libohana/include/loneos.h
===================================================================
--- /trunk/Ohana/src/libohana/include/loneos.h	(revision 3507)
+++ /trunk/Ohana/src/libohana/include/loneos.h	(revision 3508)
@@ -1,84 +1,7 @@
-
-/*** this file uses data types which must have fixed sizes regardless 
-     of the platform.  It originally used the basic C primitives: 
-       float, double, int, short int, unsigned long int, etc.
-     this breaks under 64 bit (and probably on other systems).
-     I should define internal data types which should be set by the 
-     use of # define statements if needed.  I will cheat for now and use
-     the time_t to replace unsigned long int in this file 
-***/
 
 # ifndef LONEOS_H
 # define LONEOS_H
 
-# define e_time unsigned int
-
-/* image data modes in RegImage */
-enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE};
-enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE};
-
-/* convert these to enums? */
-/* RegImage.flag values */
-# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
-
-/* catalog values to be loaded */
-# define LOAD_AVES 0x01
-# define LOAD_MEAS 0x02
-# define LOAD_MISS 0x04
-# define LOAD_SECF 0x08
-
-/* invalid mag value */
-# define NO_MAG    0x7fff
-# define NO_ERR    0xff
-
-/* photometry code types */
-# define PHOT_PRI 0x01
-# define PHOT_SEC 0x02
-# define PHOT_DEP 0x03
-# define PHOT_REF 0x04
-# define PHOT_ALT 0x05  /* never stored, only for look-ups */
-
-/* Image.code values.  these are codes to note bad images */
-# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
-# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
-# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
-# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
-# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
-
-/* Measure.flags values */
-# define ID_MEAS_NOCAL        0x0001
-# define ID_MEAS_POOR         0x0002
-# define ID_MEAS_SKIP         0x0004
-# define ID_MEAS_AREA         0x0008
-# define BLEND_IMAGE          0x0100 
-# define BLEND_CATALOG        0x0200
-# define BLEND_IMAGE_NEIGHBOR 0x1000
-# define ID_MEAS_TRAIL        0x2000
-# define ID_MEAS_GHOST        0x4000
-
-/* Average.code values */
-# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
-# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
-# define ID_PROPER     0x0400 /* star with large proper motion */
-# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
-# define ID_VARIABLE   0x2000 /* not currently set? */
-# define ID_ASTEROID   0x2000 /* identified with an asteroid */
-# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
-# define ID_MOVING     0x8000
-# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
-# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
-# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
-# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
-# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
-
-/* 
-   BLEND_IMAGE: the star on an image is matched with more 
-      than one star in the catalog (image has worse seeing than catalog)
-   BLEND_CATALOG: the star in the catalog is matched with more 
-      than one star on the image (image has better seeing than catalog)
-   CALIBRATED: relative photometry has been performed on this measurement
-   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
-      than one star in the catalog, but not in the same catalog file.
-*/
+/************  database structures ************************************/
 
 /* structure for Image Registration Database */
@@ -183,16 +106,4 @@
   short int dM;               /* scatter on alt mag */
 } SecFilt; /* 6 byte / SecFilt */
-
-/* the standard astrometric coordinates structure */
-typedef struct {
-  double   crval1, crval2;
-  float    crpix1, crpix2;
-  float    cdelt1, cdelt2;
-  float    pc1_1, pc1_2;
-  float    pc2_1, pc2_2;
-  float    polyterms[7][2];
-  char     ctype[15];
-  char     Npolyterms;
-} Coords;  /* 120 bytes / Coords */
 
 /* image structure for binary data storage of image data */
@@ -286,17 +197,4 @@
 SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues);
 
-int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
-int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
-int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
-int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
-int  GetCoords (Coords *coords, Header *header);
-int  PutCoords (Coords *coords, Header *header);
-void RegisterMosaic (Coords *coords);
-void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
-int FindMosaicForImage (Image *images, int Nimages, int entry);
-int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
-int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
-int BuildChipMatch (Image *images, int Nimages);
-
 int FindMosaicForImage (Image *images, int Nimages, int entry);
 int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
Index: /trunk/Ohana/src/libohana/include/ohana.h
===================================================================
--- /trunk/Ohana/src/libohana/include/ohana.h	(revision 3507)
+++ /trunk/Ohana/src/libohana/include/ohana.h	(revision 3508)
@@ -25,6 +25,4 @@
 # define OHANA_H
 
-extern double hypot();
-
 # define TRUE (1)
 # define FALSE (0)
@@ -36,4 +34,5 @@
 # define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
 # define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
 
 # define LCK_UNLOCK  0   /* file is unlocked */
@@ -55,9 +54,6 @@
 # endif
 
-int setlockfile2 (char *filename, double timeout, int type, int *state);
-int clearlockfile2 (char *filename, int fd, int type, int *state);
-
-FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
-int fclearlockfile (char *filename, FILE *f, int type, int *state);
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
 
 # ifndef PROTO
@@ -103,8 +99,5 @@
 # endif /* FOPEN */
 
-# define DEG_RAD 57.295779513082322
-# define RAD_DEG  0.017453292519943
-
-# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+extern double hypot();
 
 /* in string.c */
@@ -118,21 +111,21 @@
 int   get_argument (int argc, char **argv, char *arg);
 int   remove_argument (int N, int *argc, char **argv);
+void  uppercase (char *string);
 
-int   Fread (void *ptr, int size, int nitems, FILE *f, char *type);
-int   Fwrite (void *ptr, int size, int nitems, FILE *f, char *type);
-int   ByteSwap (char *ptr, int size, int nitems, char *type);
-int   ConvertStruct (char *buffer, int size, int Nbytes, char *type);
-
+/* in findexec.c */
 char *pathname (char *name);
 char *filebasename (char *name);
 char *filerootname (char *name);
 char *findexec (int argc, char **argv);
-int mkdirhier (char *path);
+int   mkdirhier (char *path);
+void  make_backup (char *filename);
 
+/* in glockfile.c */
 FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
-int fclearlockfile (char *filename, FILE *f, int type, int *state);
-int setlockfile2 (char *filename, double timeout, int type, int *state);
-int clearlockfile2 (char *filename, int fd, int type, int *state);
+int   fclearlockfile (char *filename, FILE *f, int type, int *state);
+int   setlockfile2 (char *filename, double timeout, int type, int *state);
+int   clearlockfile2 (char *filename, int fd, int type, int *state);
 
+/* in config.c */
 char *SelectConfigFile (int *argc, char **argv, char *progname);
 char *LoadConfigFile (char *filename);
@@ -141,4 +134,7 @@
 char *fileextname (char *file);
 char *LoadRawConfigFile (char *, int);
+
+/* in Fseek.c */
+int   Fseek (FILE *f, long offset, int whence);
 
 /*
Index: /trunk/Ohana/src/libohana/include/panstarrs.h
===================================================================
--- /trunk/Ohana/src/libohana/include/panstarrs.h	(revision 3507)
+++ /trunk/Ohana/src/libohana/include/panstarrs.h	(revision 3508)
@@ -2,74 +2,4 @@
 # ifndef PANSTARRS_H
 # define PANSTARRS_H
-
-# define e_time unsigned int
-
-/* image data modes in RegImage */
-enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE};
-enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE};
-
-/* convert these to enums? */
-/* RegImage.flag values */
-# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
-
-/* catalog values to be loaded */
-# define LOAD_AVES 0x01
-# define LOAD_MEAS 0x02
-# define LOAD_MISS 0x04
-# define LOAD_SECF 0x08
-
-/* invalid mag value */
-# define NO_MAG    0x7fff
-# define NO_ERR    0xff
-
-/* photometry code types */
-# define PHOT_PRI 0x01
-# define PHOT_SEC 0x02
-# define PHOT_DEP 0x03
-# define PHOT_REF 0x04
-# define PHOT_ALT 0x05  /* never stored, only for look-ups */
-
-/* Image.code values.  these are codes to note bad images */
-# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
-# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
-# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
-# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
-# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
-
-/* Measure.flags values */
-# define ID_MEAS_NOCAL        0x0001
-# define ID_MEAS_POOR         0x0002
-# define ID_MEAS_SKIP         0x0004
-# define ID_MEAS_AREA         0x0008
-# define BLEND_IMAGE          0x0100 
-# define BLEND_CATALOG        0x0200
-# define BLEND_IMAGE_NEIGHBOR 0x1000
-# define ID_MEAS_TRAIL        0x2000
-# define ID_MEAS_GHOST        0x4000
-
-/* Average.code values */
-# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
-# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
-# define ID_PROPER     0x0400 /* star with large proper motion */
-# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
-# define ID_VARIABLE   0x2000 /* not currently set? */
-# define ID_ASTEROID   0x2000 /* identified with an asteroid */
-# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
-# define ID_MOVING     0x8000
-# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
-# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
-# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
-# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
-# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
-
-/* 
-   BLEND_IMAGE: the star on an image is matched with more 
-      than one star in the catalog (image has worse seeing than catalog)
-   BLEND_CATALOG: the star in the catalog is matched with more 
-      than one star on the image (image has better seeing than catalog)
-   CALIBRATED: relative photometry has been performed on this measurement
-   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
-      than one star in the catalog, but not in the same catalog file.
-*/
 
 /************  database structures ************************************/
@@ -185,16 +115,4 @@
   short int dM;               /* scatter on alt mag */
 } SecFilt; /* 6 byte / SecFilt */
-
-/* the standard astrometric coordinates structure */
-typedef struct {
-  double   crval1, crval2;
-  float    crpix1, crpix2;
-  float    cdelt1, cdelt2;
-  float    pc1_1, pc1_2;
-  float    pc2_1, pc2_2;
-  float    polyterms[7][2];
-  char     ctype[15];
-  char     Npolyterms;
-} Coords;  /* 120 bytes / Coords */
 
 /* image structure for binary data storage of image data */
@@ -287,17 +205,4 @@
 int save_catalog (Catalog *catalog, char VERBOSE);
 
-int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
-int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
-int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
-int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
-int  GetCoords (Coords *coords, Header *header);
-int  PutCoords (Coords *coords, Header *header);
-void RegisterMosaic (Coords *coords);
-void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
-int FindMosaicForImage (Image *images, int Nimages, int entry);
-int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
-int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
-int BuildChipMatch (Image *images, int Nimages);
-
 int FindMosaicForImage (Image *images, int Nimages, int entry);
 int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
Index: /trunk/Ohana/src/libohana/src/Fseek.c
===================================================================
--- /trunk/Ohana/src/libohana/src/Fseek.c	(revision 3508)
+++ /trunk/Ohana/src/libohana/src/Fseek.c	(revision 3508)
@@ -0,0 +1,17 @@
+# include <ohana.h>
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status, k;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      return (0);
+    }
+  }
+  return (1);
+}
+
Index: /trunk/Ohana/src/libohana/src/backup.c
===================================================================
--- /trunk/Ohana/src/libohana/src/backup.c	(revision 3508)
+++ /trunk/Ohana/src/libohana/src/backup.c	(revision 3508)
@@ -0,0 +1,2 @@
+# include <ohana.h>
+
Index: /trunk/Ohana/src/libohana/src/findexec.c
===================================================================
--- /trunk/Ohana/src/libohana/src/findexec.c	(revision 3507)
+++ /trunk/Ohana/src/libohana/src/findexec.c	(revision 3508)
@@ -250,2 +250,22 @@
 
 }
+
+void make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line[256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (0);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~", filename);
+    chmod (line, cmode);
+  }
+}
Index: /trunk/Ohana/src/libohana/src/fits_db.c
===================================================================
--- /trunk/Ohana/src/libohana/src/fits_db.c	(revision 3508)
+++ /trunk/Ohana/src/libohana/src/fits_db.c	(revision 3508)
@@ -0,0 +1,146 @@
+# include "ohana.h"
+# include "dvo.h"
+
+int fits_db_init (FITS_DB *db) {
+
+  db[0].filename      = NULL;
+  db[0].header.buffer = NULL;
+  db[0].matrix.buffer = NULL;
+  db[0].ftable.buffer = NULL;
+  db[0].ftable.header = &db[0].theader;
+  return (TRUE);
+}
+
+int fits_db_lock (FITS_DB *db, char *filename) {
+  
+  /* database name must be set first */
+  if (filename == NULL) {
+    fprintf (stderr, "ERROR: db file is not set\n");
+    return (FALSE);
+  }
+
+  /* database handle must be set first */
+  if (db == NULL) {
+    fprintf (stderr, "ERROR: db handle is not set\n");
+    return (FALSE);
+  }
+
+  /* lock & open database */
+  db[0].f = fsetlockfile (filename, db[0].timeout, db[0].lockstate, &db[0].dbstate);
+  if (db[0].f == NULL) {
+    fprintf (stderr, "ERROR: cannot set lock on db\n");
+    return (FALSE);
+  }
+  
+  db[0].filename = strcreate (filename);
+  return (TRUE);
+}
+
+/* load the complete db table into memory - load first extension, do not validate EXTNAME */
+int fits_db_load (FITS_DB *db) {
+
+  /* database name must be set first */
+  if (db == NULL) {
+    fprintf (stderr, "ERROR: db handle is not set\n");
+    return (FALSE);
+  }
+
+  /* init & load in FITS table data - return FALSE on error */
+  if (!fits_fread_header (db[0].f, &db[0].header)) {
+    fprintf (stderr, "ERROR: can't read primary header\n"); 
+    return (FALSE);
+  }
+  if (!fits_fread_matrix (db[0].f, &db[0].matrix, &db[0].header)) {
+    fprintf (stderr, "ERROR: can't read primary matrix");
+    return (FALSE);
+  }
+  if (!fits_fread_header (db[0].f, &db[0].theader)) {
+    fprintf (stderr, "ERROR: can't read table header");
+    return (FALSE);
+  }
+  if (!fits_fread_ftable_data (db[0].f, &db[0].ftable)) {
+    fprintf (stderr, "ERROR: can't read table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* write complete db file */
+int fits_db_save (FITS_DB *db) {
+
+  /* write all data to file */
+  make_backup (db[0].filename);
+  Fseek (db[0].f, 0, SEEK_SET);
+
+  if (!fits_fwrite_header  (db[0].f, &db[0].header)) {
+    fprintf (stderr, "ERROR: can't write primary header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_matrix  (db[0].f, &db[0].matrix)) {
+    fprintf (stderr, "ERROR: can't write primary matrix");
+    return (FALSE);
+  }
+  if (!fits_fwrite_Theader (db[0].f, &db[0].theader)) {
+    fprintf (stderr, "ERROR: can't write table header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_table   (db[0].f, &db[0].ftable)) {
+    fprintf (stderr, "ERROR: can't write table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* write vtable to db file (also appends rows to the end of the table) */
+int fits_db_update (FITS_DB *db, VTable *vtable) {
+
+  /* this section is not valid if we have changed the size of header, matrix, theader */
+
+  /* write subset to file */
+  make_backup (db[0].filename);
+  Fseek (db[0].f, 0, SEEK_SET);
+
+  /* do we revert to the old version if this fails? */
+  if (!fits_fwrite_header   (db[0].f, &db[0].header))  {
+    fprintf (stderr, "ERROR: can't update primary header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_matrix   (db[0].f, &db[0].matrix))  {
+    fprintf (stderr, "ERROR: can't update primary matrix");
+    return (FALSE);
+  }
+  if (!fits_fwrite_Theader  (db[0].f, &db[0].theader)) {
+    fprintf (stderr, "ERROR: can't update table header");
+    return (FALSE);
+  }
+  if (!fits_fwrite_vtable   (db[0].f, vtable))  {
+    fprintf (stderr, "ERROR: can't update table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* free memory associated with db handle */
+int fits_db_free (FITS_DB *db) {
+  fits_free_header (&db[0].header);
+  fits_free_matrix (&db[0].matrix);
+  fits_free_header (&db[0].theader);
+  fits_free_table  (&db[0].ftable);
+  if (db[0].filename != NULL) {
+    free (db[0].filename);
+    db[0].filename = NULL;
+  }
+  return (TRUE);
+}
+
+/* close the db files (close open file & unlock) */
+int fits_db_close (FITS_DB *db) {
+  if (db[0].dbstate == LCK_UNLOCK) return (TRUE);
+  fclearlockfile (db[0].filename, db[0].f, db[0].lockstate, &db[0].dbstate);
+  /* fclearlockfile also performs fclose (f) */
+
+  /* for this to be atomic, need to unlink before we unlock */
+  /* unlink file here if resulting file is empty? */
+  /* if (db[0].Nrow == 0) && (lockstate != LCK_SOFT)) unlink (dBFile); */
+  return (TRUE);
+}  
Index: /trunk/Ohana/src/libohana/src/string.c
===================================================================
--- /trunk/Ohana/src/libohana/src/string.c	(revision 3507)
+++ /trunk/Ohana/src/libohana/src/string.c	(revision 3508)
@@ -156,2 +156,10 @@
   return (N);
 }
+
+void uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
