Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/.cvsignore
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/.cvsignore	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/.cvsignore	(revision 21773)
@@ -0,0 +1,1 @@
+lib
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/Makefile
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/Makefile	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/Makefile	(revision 21773)
@@ -0,0 +1,61 @@
+default: install
+help:
+	@echo "make options: install libohana clean dist"
+
+include ../../Configure
+HOME 	=	$(ROOT)/src/libohana
+BIN	= 	$(HOME)/bin
+LIB	= 	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	=	$(HOME)/include
+TESTDIR =       $(HOME)/test
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+TFLAGS        = $(FULL_CFLAGS) $(FULL_LDFLAGS) -ltap_ohana
+
+install: $(DESTLIB)/libohana.a $(DESTLIB)/libohana.so
+libohana: $(LIB)/libohana.$(ARCH).a $(LIB)/libohana.$(ARCH).so
+testcode: install $(TEST)
+test:
+	make testcode
+	for i in $(TEST); do $$i; done
+
+INCS = \
+$(DESTINC)/Xohana.h  \
+$(DESTINC)/ohana_allocate.h \
+$(DESTINC)/ohana.h
+
+OBJS = \
+$(SRC)/ohana_allocate.$(ARCH).o  \
+$(SRC)/string.$(ARCH).o		 \
+$(SRC)/findexec.$(ARCH).o	 \
+$(SRC)/glockfile.$(ARCH).o	 \
+$(SRC)/time.$(ARCH).o		 \
+$(SRC)/gaussj.$(ARCH).o		 \
+$(SRC)/config.$(ARCH).o		 \
+$(SRC)/Fread.$(ARCH).o		 \
+$(SRC)/IOBufferOps.$(ARCH).o	 \
+$(SRC)/CommOps.$(ARCH).o	 \
+$(SRC)/version.$(ARCH).o
+
+TEST = \
+$(TESTDIR)/string.$(ARCH)
+
+$(OBJS): $(INCS)
+
+$(LIB)/libohana.$(ARCH).a: $(OBJS)
+$(LIB)/libohana.$(ARCH).so: $(OBJS)
+
+$(DESTLIB)/libohana.a:  $(LIB)/libohana.$(ARCH).a
+$(DESTLIB)/libohana.so: $(LIB)/libohana.$(ARCH).so
+
+$(TESTDIR)/%.$(ARCH) : $(TESTDIR)/%.c
+	$(CC) $^ -o $@ $(TFLAGS)
+
+.PHONY: test
+
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/ChangeLog.txt
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/ChangeLog.txt	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/ChangeLog.txt	(revision 21773)
@@ -0,0 +1,66 @@
+
+- libohana 1.8.1 : 2006.10.04
+  * added tap-based tests
+  * added strsubs functions
+
+- libohana 1.8 : 2006.08.23
+  * cleanups in ohana.h
+  * moved gaussj to libohana
+  * added PrintIOBuffer functions
+  * added check_dir_access 
+  * added ohana_lst to time.c
+
+- libohana 1.7
+  * added 'mode' to mkdirhier
+  * moved _check_permissions to check_file_exec
+
+- libohana 1.6
+  * added check_file_access (check parent dirs and permissions)
+  * cleaned up signed/unsigned inconsistencies
+  * allow date_to_set to handle enclosing quotes
+
+libohana-1-5
+  moved dvo functions to libdvo
+  made libfits depend on libohana
+  added IOBuffer and Comm functions to libohana
+  added time functions from opihi and others
+  moved Fseek into findexec.c
+
+2005.10.07
+
+	I was having some memory collision problems, and attempting to
+	use the ohana_allocate functions reminded me that the libFITS
+	functions were not supported under ohana_allocate.  This was
+	unhelpful.  I bit the bullet and split libohana into libohana
+	(base functions only, including ohana_allocate) and libdvo
+	(functions based on the libautocode structures).  Doing this
+	allowed me to make libFITS depend on libohana (including
+	ohana_allocate).  BUT, this forced me to change all LDFLAGS
+	entries in ohana to swap -lohana -lFITS for -lFITS -lohana,
+	and to add include <fitsio.h> in some cases.
+
+libohana-1-4
+  further cleanup of the autocode system
+  eliminated the elixir.h, panstarrs.h, loneos.h files:
+   these are now completely absorbed into libautocode
+  minor improvements to ohana_allocate
+
+libohana-1-3
+  changed meaning of PLY / WRP / DIS (see coordtrans.txt)
+  added check on ALLOCATE/REALLOCATE to avoid failures on Nvalues < 1
+  added ohana_allocate system (memory tracking)
+  added autocode elements (refers to libautocode)
+  cleanup glockfile APIs
+
+libohana-1-2
+  added 'STG' to allowed coordinate transforms (inaccurate & stop-gap)
+  set default Npolyterms to 1
+  initialized filemode in glockfile.c
+
+libohana-1-1
+  dropped the configuration source ./.(name)rc : was just confusing
+  in glockfile : made closing a NULL file OK
+  added imreg_datatypes (part of imregister-1-1 datatype reorganization)
+
+libohana-1-0
+  import to CVS
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/VERSIONS
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/VERSIONS	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/VERSIONS	(revision 21773)
@@ -0,0 +1,5 @@
+
+tag names used by libohana:
+
+TAG         : Comment
+libohana-1-0 : first version under CVS
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/autocode.txt
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/autocode.txt	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/autocode.txt	(revision 21773)
@@ -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: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/coords_minimal.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/coords_minimal.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/coords_minimal.c	(revision 21773)
@@ -0,0 +1,115 @@
+/* 
+here is some C code to project from R,D to x,y (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+# define FULLPROJECTION 0
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+RD_to_XY (double *x, double *y, double R, double D, double Ro, double Do) {
+
+  double sdp, cdp, salp, calp, sdel, cdel, stht, sphi, cphi;
+                 
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  salp = sin(RAD_DEG*(ra - Ro));
+  calp = cos(RAD_DEG*(ra - Ro));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+  
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) { return 0; /* projection from the wrong side of the sphere */ }
+  
+  X =  DEG_RAD * sphi;
+  Y = -DEG_RAD * cphi;
+  
+# if (FULLPROJECTION) 
+  
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+
+  tmp_d = 1.0 / (pc_1_1*pc_2_2 - pc_1_2*pc_2_1); 
+  *x = tmp_d * (pc_2_2*X - pc_1_2*Y) / cdelt1 + Xo;
+  *y = tmp_d * (pc_1_1*Y - pc_2_1*X) / cdelt2 + Yo;
+
+# else
+
+  *x = X;
+  *y = Y;
+  
+# endif
+
+
+  return (1);
+
+}
+
+
+/* 
+here is some C code to project from x,y to R,D (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+XY_to_RD (double *ra, double *dec, double x, double y, double Ro, double Do) {
+
+
+  double L, M, X, Y, T, Z;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+  stht = ctht = 1;
+
+  
+# if (FULLPROJECTION) 
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+  X = cdelt1 * (x - Xo);
+  Y = cdelt2 * (y - Yo);
+
+  L = (X*pc1_1 + Y*pc1_2);
+  M = (X*pc2_1 + Y*pc2_2);
+# else 
+  L = x;
+  M = y;
+# endif
+
+  R = hypot (L,M);
+  if ((L == 0) && (M == 0)) {
+    sphi = 0;
+    cphi = 1;
+  }
+  else {
+    sphi =  L / R;
+    cphi = -M / R;
+  }
+
+  ctht = RAD_DEG * R;
+  stht = sqrt (1 - ctht*ctht);
+
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  
+  sdel = stht*sdp - ctht*cphi*cdp;
+  salp = ctht*sphi;
+  calp = stht*cdp + ctht*cphi*sdp;
+  alpha = atan2 (salp, calp);
+  delta = asin (sdel);
+  
+  *ra  = DEG_RAD*alpha + Ro;
+  *dec = DEG_RAD*delta;
+  
+  return (1);
+
+}
+
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/coordtrans.txt
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/coordtrans.txt	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/coordtrans.txt	(revision 21773)
@@ -0,0 +1,70 @@
+
+I have changed the meaning of coord type PLY from the historical
+meaning.  The only previous use that is in a DVO-style database is in
+the loneos data (all cfht data needed to go to linear terms).  these
+can be easily converted by changing from PLY to DIS.
+
+There are now three types of higher-order transformation which may be
+used depending on the circumstance.  The new naming scheme is:
+
+PLY : a cartesian transformation (ie, no projection implied)
+DIS : equivalent to TAN projection with up-to-3rd order polynomial
+WRP : a second-level cartesian transformation, implying the presence
+      of a DIS coord frame (must be registered with libohana function)
+
+{ 
+
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+  R = hypot (L,M);
+  if ((L == 0) && (M == 0)) {
+    sphi = 0;
+    cphi = 1;
+  } else {
+    sphi =  L / R;
+    cphi = -M / R;
+  }
+  if (R == 0) {
+    stht = 1.0;
+    ctht = 0.0;
+  } else {
+    T = DEG_RAD / R;
+    stht =   T / sqrt ( 1.0 + T*T);
+    ctht = 1.0 / sqrt ( 1.0 + T*T);
+  }
+  sdp  = sin(RAD_DEG*coords[0].crval2);
+  cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+  sdel = stht*sdp - ctht*cphi*cdp;
+  salp = ctht*sphi;
+  calp = stht*cdp + ctht*cphi*sdp;
+  alpha = atan2 (salp, calp);
+  delta = asin (sdel);
+    
+  *ra  = DEG_RAD*alpha + coords[0].crval1;
+  *dec = DEG_RAD*delta;
+}
+
+RD_to_XY () {
+
+  sdp  = sin(RAD_DEG*coords[0].crval2);
+  cdp  = cos(RAD_DEG*coords[0].crval2);
+  salp = sin(RAD_DEG*(ra - coords[0].crval1));
+  calp = cos(RAD_DEG*(ra - coords[0].crval1));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) status = FALSE;
+
+  X =  DEG_RAD * sphi / stht;
+  Y = -DEG_RAD * cphi / stht;
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/glockfile.txt
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/glockfile.txt	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/doc/glockfile.txt	(revision 21773)
@@ -0,0 +1,55 @@
+
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
+   
+ set a lockfile on [path]/filename.  
+
+ we allow three types of locks: 
+ LCK_HARD - exclusive lock with persistent lock file
+ LCK_XCLD - exclusive lock, no persistent lock file
+ LCK_SOFT - shared lock
+
+ all three types of locks set a filesystem lock (using NFS lockd) on
+ the given file, using an exclusive lock for HARD and XCLD and a
+ shared lock for SOFT locks.  
+
+ a HARD lock also uses a lockfile to make the lock persistent in the
+ event the calling program crashes: the lockfile must be actively
+ removed and will not vanish even if the locking program dies
+
+ SOFT and XCLD locks will vanish if the locking program dies.
+
+ if a HARD or XCLD lock is set, HARD, XCLD & SOFT locks will block
+
+ if a SOFT lock is set, HARD and XCLD locks will block, but not a SOFT
+ lock
+
+ the hard lockfile uses the file [path]/.filename.lck
+
+ this function locks and opens the file, returning the file pointer to
+ the now opened file.  the file is either opened for reading and
+ writing (HARD, XCLD == r+) or just reading (SOFT).
+
+ Error Conditions:
+
+ on error, fsetlockfile closes the file, closes the lockfile, and
+ returns NULL.  In come cases, an empty file may be left behind
+ (LCK_TIMEOUT, LCK_HARDOPEN, LCK_HARDLOCK, LCK_HARDLOCKHARD,
+ LCK_HARDLOCKCLOSE)
+
+ - invalid type (LCK_INVALID)
+   * no file created, no lock file created : OK
+ - SOFT and file does not exist (LCK_EMPTY)
+   * no file created, no lock file created : OK 
+ - file not accessible, cannot be opened (LCK_ACCESS)
+   * no file created, no lock file created : OK
+ - FS lock timed out (LCK_TIMEOUT)
+   * new file is created, file is open, file is unlocked, lock file is not created : OK
+ - lockfile not accessible (LCK_HARDOPEN)
+   * new file is created, file is open, file is locked, lock file is not created : OK
+ - cannot lock lockfile, held by another user (LCK_HARDLOCK)
+   * new file is created, file is open, file is locked, lock file is created : OK
+ - lockfile says 'BUSY', previous holder crashed (LCK_HARDLOCKHARD)
+   * new file is created, file is open, file is locked, lock file exists, lock file locked : OK
+ - error writing 'BUSY' to lockfile (LCK_HARDCLOSE)
+   * new file is created, file is open, file is locked, lock file exists, lock file locked
+
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/Xohana.h
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/Xohana.h	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/Xohana.h	(revision 21773)
@@ -0,0 +1,8 @@
+# include <ohana.h>
+# include <X11/Xatom.h>
+# include <X11/Xlib.h>
+# include <X11/Xresource.h>
+# include <X11/Xutil.h>
+# include <X11/cursorfont.h>
+# include <X11/keysym.h>
+# include <X11/keysymdef.h>
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/convert.h
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/convert.h	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/convert.h	(revision 21773)
@@ -0,0 +1,3 @@
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues);
+Average *FixOldAverage (OldAverage *in, int Nvalues);
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues);
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/ohana.h
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/ohana.h	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/ohana.h	(revision 21773)
@@ -0,0 +1,213 @@
+# include <stdio.h>
+# include <fcntl.h>
+# include <malloc.h>
+# include <math.h>
+# include <errno.h>
+# include <time.h>
+# include <memory.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/socket.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <unistd.h>
+# include <stdarg.h> 
+# include <readline/history.h>
+# include <readline/readline.h>
+
+/* OHANA included stuff */
+# ifndef OHANA_H
+# define OHANA_H
+
+# ifndef TRUE
+# define TRUE (1)
+# endif
+
+# ifndef FALSE
+# define FALSE (0)
+# endif 
+
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+# define ROUND(X) ((int) ((X) + 0.5*SIGN(X)))
+# define SQR(X)   (double) (((double)(X))*((double)(X)))
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# 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))
+
+enum {
+ LCK_UNLOCK,        /* file is unlocked */
+ LCK_INVALID,       /* invalid locktype requested */
+ LCK_MISSING,       /* soft requested and file missing (error) */
+ LCK_ACCESS,        /* can't get access to file */
+ LCK_TIMEOUT,       /* timeout setting lock */
+ LCK_HARDOPEN,      /* cannot open hard lockfile */
+ LCK_HARDLOCK,      /* cannot lock hard lockfile */
+ LCK_HARDLOCKHARD,  /* hard lockfile is locked */
+ LCK_HARDCLOSE,     /* cannot write to hardlock */
+
+ LCK_EMPTY,         /* file is locked and empty */
+ LCK_FULL,          /* file is locked and not empty */
+ LCK_UNKNOWN,       /* file is locked, but can't get size */
+
+ LCK_SOFT,          /* soft lock */
+ LCK_HARD,          /* hard lock */
+ LCK_XCLD,          /* exclusive soft lock */
+};
+
+# ifndef M_PI
+# define M_PI 3.14159265358979323846264
+# endif
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+# ifndef PROTO
+#   define PROTO(A) A
+# endif
+
+/* 
+# else
+#   ifndef PROTO
+#   define PROTO(A) ()
+#   endif
+# include <varargs.h>
+# endif
+*/
+
+/* ohana_allocate.h provides ohana memory tools.  to use them
+   you must # define OHANA_MEMORY before including ohana.h */
+# include <ohana_allocate.h>
+
+# ifndef FOPEN 
+# define FOPEN(F,NAME) \
+  F = fopen (NAME, "r"); \
+  if (F == NULL) { \
+    fprintf (stderr, "failed to open %s\n", NAME); \
+    exit (0); \
+  }
+# endif /* FOPEN */
+
+/*
+  isspace is c99 : do we require c99 now? 
+  isspace()
+   checks  for white-space characters.  In the "C" and "POSIX" locales, these are: space, form-feed ('\f'), newline ('\n'),
+   carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
+   horiz. tab: 0x09, vert. tab: 0x0b, newline: 0x0a, form-feed: 0x0c, return: 0x0d, space: 0x20, 
+*/
+# define OHANA_WHITESPACE(c)(((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0b) || ((c) == 0x0b) || ((c) == 0x0c) || ((c) == 0x0d) || ((c) == 0x20))
+
+/* socket / pipe communication buffer */
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nreset;
+  int   Nblock;
+  int   Nbuffer;
+} IOBuffer;
+
+extern double hypot();
+
+/* in string.c */
+int     stripwhite             PROTO((char *string));
+int     strnumcmp              PROTO((char *str1, char *str2));
+char   *strcreate              PROTO((char *string));
+char   *strncreate             PROTO((char *string, int n));
+int     scan_line              PROTO((FILE *f, char *line)); 
+int     dparse                 PROTO((double *X, int NX, char *line));
+int     fparse                 PROTO((float *X, int NX, char *line));
+int     get_argument           PROTO((int argc, char **argv, char *arg));
+int     remove_argument        PROTO((int N, int *argc, char **argv));
+void    uppercase              PROTO((char *string));
+char   *strip_version          PROTO((char *input));
+char   *strsubs                PROTO((char *string, char *match, char *with));
+
+/* in findexec.c */
+char   *pathname               PROTO((char *name));
+char   *filebasename           PROTO((char *name));
+char   *filerootname           PROTO((char *name));
+char   *fileextname            PROTO((char *file));
+char   *findexec               PROTO((int argc, char **argv));
+int     mkdirhier              PROTO((char *path, int mode));
+void    make_backup            PROTO((char *filename));
+int     check_file_access      PROTO((char *basefile, int backup, int verbose));
+int     check_dir_access       PROTO((char *path, int verbose));
+int     check_file_exec        PROTO((char *filename));
+
+/* in glockfile.c */
+FILE   *fsetlockfile           PROTO((char *filename, double timeout, int type, int *state));
+int     fclearlockfile         PROTO((char *filename, FILE *f, int type, int *state));
+
+/* in config.c */
+char   *SelectConfigFile       PROTO((int *argc, char **argv, char *progname));
+char   *LoadConfigFile         PROTO((char *filename));
+char   *ScanConfig             PROTO((char *config, char *field, char *mode, int N,...));
+char   *expandline             PROTO((char *line, char *config));
+char   *fileextname            PROTO((char *file));
+char   *LoadRawConfigFile      PROTO((char *, int));
+
+/* others */
+int     Fseek                  PROTO((FILE *f, long offset, int whence));
+char   *ohana_version          PROTO(());
+
+int     dgaussj                PROTO((double **a, int n, double **b, int m));
+int     fgaussj                PROTO((float **a, int n, float **b, int m));
+
+/* in time.c */
+enum {TIME_NONE, TIME_DATE, TIME_DAYS, TIME_HOURS, TIME_MINUTES, TIME_SECONDS, TIME_JD, TIME_MJD};
+
+int     chk_time               PROTO((char *line));
+time_t  date_to_sec            PROTO((char *date));
+int     dms_to_ddd             PROTO((double *Value, char *string));
+time_t  jd_to_sec              PROTO((double jd));
+char   *sec_to_date            PROTO((time_t second));
+double  sec_to_jd              PROTO((time_t second));
+int     str_to_dtime           PROTO((char *line, double *second));
+int     str_to_time            PROTO((char *line, time_t *second));
+double  sec_to_mjd             PROTO((time_t second));
+time_t  mjd_to_sec             PROTO((double mjd));
+double  ohana_lst              PROTO((double jd, double longitude));
+
+int     hstgsc_hms_to_deg      PROTO((double *h0, double *h1, double *d0, double *d1, char *string));
+int     str_to_radec           PROTO((double *ra, double *dec, char *str1, char *str2));
+
+/* IO Buffer functions */
+int     InitIOBuffer   	       PROTO((IOBuffer *buffer, int Nalloc));
+int 	FlushIOBuffer  	       PROTO((IOBuffer *buffer));
+int 	ReadtoIOBuffer 	       PROTO((IOBuffer *buffer, int fd));
+int 	EmptyIOBuffer  	       PROTO((IOBuffer *buffer, int Nmax, int fd));
+void    FreeIOBuffer   	       PROTO((IOBuffer *buffer));
+int 	PrintIOBuffer  	       PROTO((IOBuffer *buffer, char *format, ...));
+int 	vPrintIOBuffer 	       PROTO((IOBuffer *buffer, char *format, va_list argp));
+
+/* communication functions */
+int 	ExpectMessage 	       PROTO((int device, double timeout, IOBuffer *message));
+int 	ExpectCommand 	       PROTO((int device, int length, double timeout, IOBuffer *buffer));
+int 	SendMessage   	       PROTO((int device, char *format, ...));
+int 	SendMessageFixed       PROTO((int device, int length, char *messge));
+int 	SendCommand   	       PROTO((int device, int length, char *format, ...));
+int 	SendCommandV  	       PROTO((int device, int length, char *format, va_list argp));
+
+char   *CheckForMessage        PROTO((IOBuffer *buffer));
+
+/*
+#   define F_SETFL         4   
+#   define O_NONBLOCK      0200000  
+#   define AF_UNIX         1          
+#   define SOCK_STREAM     1
+*/
+
+/*
+# ifndef ANSI
+# include <varargs.h>
+# else
+# include <stdarg.h> 
+# include <cfuncs.h> 
+# endif
+*/
+
+# endif
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/ohana_allocate.h
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/ohana_allocate.h	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/include/ohana_allocate.h	(revision 21773)
@@ -0,0 +1,55 @@
+# ifndef OHANA_ALLOCATE
+# define OHANA_ALLOCATE
+
+/* default is to use basic system memory functions */
+# ifdef OHANA_MEMORY
+
+void *ohana_malloc (char *file, int line, int Nelem, size_t esize);
+void *ohana_realloc (char *file, int line, void *in, int Nelem, size_t esize);
+void  ohana_free (char *file, int line, void *in);
+void  ohana_memregister_func (char *file, int line, void *ptr);
+void  ohana_memdump_func (int mode);
+void  ohana_memcheck_func (int mode);
+
+# define ohana_memregister(X) ohana_memregister_func (__FILE__, __LINE__, (X));
+# define ohana_memcheck(X) ohana_memcheck_func (X);
+# define ohana_memdump(X) ohana_memdump_func (X);
+
+# define ALLOCATE(X,T,S) \
+  X = (T *) ohana_malloc (__FILE__, __LINE__, (S), sizeof(T))
+# define REALLOCATE(X,T,S) \
+  X = (T *) ohana_realloc(__FILE__, __LINE__, X, (S), sizeof(T));
+# define CHECK_REALLOCATE(X,T,S,N,D) \
+  if ((N) >= (S)) { S += D; \
+  X = (T *) ohana_realloc(__FILE__, __LINE__, X, (S), sizeof(T)); }
+# define FREE(X) if (X != NULL) { ohana_free (__FILE__, __LINE__, X); }
+# define free(X) ohana_free(__FILE__, __LINE__, X)
+
+# else 
+# define ohana_memregister(X) /* NOP */
+# define ohana_memcheck(X) /* NOP */
+# define ohana_memdump(X) /* NOP */
+# endif /* OHANA_MEMORY */
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X = (T *) malloc ((unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+  if (X == NULL) { \
+    fprintf(stderr,"failed malloc at %d in %s\n", __LINE__, __FILE__);\
+    exit (10); } 
+# define REALLOCATE(X,T,S) \
+  X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+  if (X == NULL) { \
+    fprintf(stderr,"failed realloc at %d in %s\n", __LINE__, __FILE__);\
+    exit (10); }
+# define CHECK_REALLOCATE(X,T,S,N,D) \
+  if ((N) >= (S)) { \
+    S += D; \
+    X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+    if (X == NULL) { \
+      fprintf(stderr,"failed realloc increment at %d in %s\n", __LINE__, __FILE__);\
+      exit (10); } }
+# define FREE(X) if (X != NULL) { free (X); }
+# endif /* ALLOCATE */
+
+# endif /* OHANA_ALLOCATE */
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/lib/.cvsignore
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/lib/.cvsignore	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/lib/.cvsignore	(revision 21773)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/CommOps.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/CommOps.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/CommOps.c	(revision 21773)
@@ -0,0 +1,179 @@
+# include <ohana.h>
+
+// XXX this is somewhat poor: the Send commands return TRUE / FALSE for success/failure
+// the Expect commands return 0 for success, -N for different errors
+
+int ExpectMessage (int device, double timeout, IOBuffer *message) {
+
+  int status, length;
+  IOBuffer command;
+
+  status = ExpectCommand (device, 16, timeout, &command);
+  if (status) {
+    FreeIOBuffer (&command);
+    return (status);
+  }
+
+  /* buffer contains an EOL NULL, we can just sscan it */
+  sscanf (command.buffer, "%*s %d", &length);
+  FreeIOBuffer (&command);
+  
+  status = ExpectCommand (device, length, timeout, message);
+  return (status);
+}
+
+int ExpectCommand (int device, int length, double timeout, IOBuffer *buffer) {
+
+  /* read from device until we have length bytes, or timeout */
+
+  int Nread;
+  double dtime;
+  struct timespec request, remain;
+  struct timeval start, stop;
+
+  gettimeofday (&start, NULL);
+
+  /* avoid blocking on waitpid, test every 1000 usec, up to timeout msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 1000000;
+
+  InitIOBuffer (buffer, length + 1);
+
+  while (buffer[0].Nbuffer < length) {
+    Nread = read (device, &buffer[0].buffer[buffer[0].Nbuffer], length - buffer[0].Nbuffer);
+    
+    if (Nread > 0) {
+      buffer[0].Nbuffer += Nread;
+      continue;
+    }
+
+    if (Nread == -1) {
+      switch (errno) {
+	case EAGAIN:
+	case EIO:
+	  /** no data available in pipe, wait a bit, check for timeout **/
+	  nanosleep (&request, &remain);
+	  break;
+	default:
+	  /** error reading from pipe **/
+	  perror ("ReadtoIOBuffer read error");
+	  return (-2);
+      }
+    }
+
+    if (Nread == 0) return (-3);
+
+    gettimeofday (&stop, NULL);
+    dtime = DTIME (stop, start);
+    if (dtime > timeout) return (-1);
+  }
+  return (0);
+}
+
+/* send a message of arbitrary size, sending the size first */
+int SendMessage (int device, char *format, ...) {
+
+  int Nbyte;
+  char tmp;
+  va_list argp;  
+
+  va_start (argp, format);
+  Nbyte = vsnprintf (&tmp, 0, format, argp);
+  va_end (argp);
+
+  if (!Nbyte) return (FALSE);
+
+  va_start (argp, format);
+  if (!SendCommand (device, 16, "NBYTES: %6d", Nbyte)) goto escape;
+  if (!SendCommandV (device, Nbyte, format, argp)) goto escape;
+  va_end (argp);
+  return TRUE;
+
+escape:
+  va_end (argp);
+  return FALSE;
+}
+
+/* send a message of known size, sending the size first */
+int SendMessageFixed (int device, int length, char *message) {
+
+  if (!SendCommand (device, 16, "NBYTES: %6d", length)) return FALSE;
+  if (!SendCommand (device, length, message)) return FALSE;
+  return TRUE;
+}
+
+int SendCommand (int device, int length, char *format, ...) {
+
+  int status;
+  va_list argp;  
+
+  va_start (argp, format);
+  status = SendCommandV (device, length, format, argp);
+  va_end (argp);
+  return (status);
+}
+  
+int SendCommandV (int device, int length, char *format, va_list argp) {
+
+  int status;
+  char *string;
+
+  /* I allocated and zero 1 extra byte */
+  ALLOCATE (string, char, length + 1);
+  memset (string, 0, length + 1);
+  vsnprintf (string, length + 1, format, argp);
+
+  status = write (device, string, length);
+  free (string);
+
+  if (status == -1) return FALSE;
+  return (TRUE);
+}
+
+/* 
+
+ I need an alternative ExpectCommand function which appends to an existing buffer
+ until the complete message is ready.  
+
+ A command looks like this (pre-determined length):
+ NN bytes: XXXXX\0 
+
+ A message looks like this (preceded by NBYTES command) :
+ 16 bytes: WORD NNN\0
+ NNN bytes: message.... \0
+
+ the expect function needs to monitor the number of bytes already received
+ we need to be able to call it repeatedly until the buffer is full.
+
+*/
+
+/* check if the first entry in the buffer corresponds to a message:
+   A message looks like this (preceded by NBYTES command) :
+    16 bytes: WORD NNN
+    NNN bytes: message....
+    note that the NULL bytes are not sent
+  If a message is found, it is popped off the buffer and sent back as a
+  complete line (the length portion is dropped) 
+*/
+
+char *CheckForMessage (IOBuffer *buffer) {
+
+  int Nbytes;
+  char command[20], *line;
+
+  if (buffer[0].Nbuffer < 16) return NULL;
+  memcpy (command, buffer[0].buffer, 16);
+  command[16] = 0;
+
+  sscanf (command, "NBYTES: %d", &Nbytes);
+
+  if (buffer[0].Nbuffer < Nbytes + 16) return NULL;
+
+  ALLOCATE (line, char, Nbytes + 1);
+  memcpy (line, &buffer[0].buffer[16], Nbytes);
+  line[Nbytes] = 0;
+
+  buffer[0].Nbuffer -= Nbytes + 16;
+  memmove (buffer[0].buffer, &buffer[0].buffer[Nbytes+16], buffer[0].Nbuffer);
+  return (line);
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/Fread.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/Fread.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/Fread.c	(revision 21773)
@@ -0,0 +1,474 @@
+# include <ohana.h>
+
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+
+# define BYTE_EXCHANGE(X,Y) tmp = byte[X]; byte[X] = byte[Y]; byte[Y] = tmp;
+# 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;
+
+/** this is also used in libautocode/def/common.h -- consolidate **/
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+# ifdef dec
+# define BYTE_SWAP
+# endif
+
+/* add other architectures here, ie dec, alpha, etc */ 
+
+int Fread (void *ptr, int size, int nitems, FILE *f, char *type) {
+
+  int valid, status;
+
+  status = fread (ptr, size, nitems, f);
+
+  valid = ByteSwap (ptr, size, nitems, type);
+
+  if (!valid) return (FALSE);
+  return (status);
+}
+
+int Fwrite (void *ptr, int size, int nitems, FILE *f, char *type) {
+
+  int valid, status;
+
+  valid = ByteSwap (ptr, size, nitems, type);
+
+  if (!valid) return (FALSE);
+
+  status = fwrite (ptr, size, nitems, f);
+  return (status);
+}
+
+int ByteSwap (char *ptr, int size, int nitems, char *type) {
+
+# ifdef BYTE_SWAP
+
+  int i;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+
+  if (!strcmp (type, "char")) return (TRUE);
+
+  if (!strcmp (type, "short")) {
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    for (i = 0; i < nitems; i++, byte0 += 2, byte1 += 2) {
+      tmp = *byte0;
+      *byte0 = *byte1;
+      *byte1 = tmp;
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "int") || !strcmp (type, "float")) {
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    byte2 = (unsigned char *)ptr + 2;
+    byte3 = (unsigned char *)ptr + 3;
+    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+      tmp = *byte0;
+      *byte0 = *byte3;
+      *byte3 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte2;
+      *byte2 = tmp;
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "double")) {
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    byte2 = (unsigned char *)ptr + 2;
+    byte3 = (unsigned char *)ptr + 3;
+    byte4 = (unsigned char *)ptr + 4;
+    byte5 = (unsigned char *)ptr + 5;
+    byte6 = (unsigned char *)ptr + 6;
+    byte7 = (unsigned char *)ptr + 7;
+    for (i = 0; i < nitems; i++, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+      tmp = *byte0;
+      *byte0 = *byte7;
+      *byte7 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte6;
+      *byte6 = tmp;
+      tmp = *byte1;
+      *byte2 = *byte5;
+      *byte5 = tmp;
+      tmp = *byte1;
+      *byte3 = *byte4;
+      *byte4 = tmp;
+    }
+    return (TRUE);
+  }
+
+# if (0) /** now in autocode **/
+  if (!strcmp (type, "regimage")) {
+    if (size != REGIMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (RegImage) %d vs %d\n", size, REGIMAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += REGIMAGE_SIZE) {
+      SWAP_WORD (284); /* exptime */ 
+      SWAP_WORD (288); /* airmass */ 
+      SWAP_WORD (292); /* sky */     
+      SWAP_WORD (296); /* bias */    
+      SWAP_WORD (300); /* fwhm */    
+      SWAP_WORD (304); /* telfocus */ 
+      SWAP_WORD (308); /* xprobe */ 
+      SWAP_WORD (312); /* yprobe */ 
+      SWAP_WORD (316); /* zprobe */ 
+      SWAP_WORD (320); /* dettemp */ 
+      SWAP_WORD (324); /* teltemp[0] */ 
+      SWAP_WORD (328); /* teltemp[1] */  
+      SWAP_WORD (332); /* teltemp[2] */ 
+      SWAP_WORD (336); /* teltemp[3] */ 
+      SWAP_WORD (340); /* rotangle */
+      SWAP_WORD (344); /* ra */      
+      SWAP_WORD (348); /* dec */     
+      SWAP_WORD (352); /* obstime */ 
+      SWAP_WORD (356); /* regtime */  
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "detreg")) {
+    if (size != DETREG_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, DETREG_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += DETREG_SIZE) {
+      SWAP_WORD (0);   /* tstart */
+      SWAP_WORD (4);   /* tstop */
+      SWAP_WORD (8);   /* treg */
+      SWAP_WORD (12);  /* exptime */
+      SWAP_WORD (16);  /* type */
+      SWAP_WORD (20);  /* filter */
+      SWAP_WORD (24);  /* ccd */
+      SWAP_WORD (28);  /* Nentry */
+      SWAP_WORD (32);  /* Norder */
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "photpars")) {
+    if (size != PHOTPARS_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (PhotPars) %d vs %d\n", size, PHOTPARS_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += PHOTPARS_SIZE) {
+      SWAP_WORD (0);    /* ZP */
+      SWAP_WORD (4);    /* ZPo */
+      SWAP_WORD (8);    /* dZP */
+      SWAP_WORD (12);   /* K */
+      SWAP_WORD (16);   /* A */
+      SWAP_WORD (20);   /* tstart */
+      SWAP_WORD (24);   /* tstop */
+      SWAP_BYTE (28);   /* c1 */
+      SWAP_BYTE (30);   /* c2 */
+      SWAP_BYTE (32);   /* photcode */
+      SWAP_WORD (100);   /* Ntime */
+      SWAP_WORD (104);   /* Nmeas */
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "missing")) {
+    if (size != MISSING_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Missing) %d vs %d\n", size, MISSING_SIZE);
+      return (FALSE);
+    }
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    byte2 = (unsigned char *)ptr + 2;
+    byte3 = (unsigned char *)ptr + 3;
+    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+      tmp = *byte0;
+      *byte0 = *byte3;
+      *byte3 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte2;
+      *byte2 = tmp;
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "secfilt")) {
+    if (size != SECFILT_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (SecFilt) %d vs %d\n", size, SECFILT_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *) ptr;
+    for (i = 0; i < nitems; i++, byte += SECFILT_SIZE) {
+      SWAP_BYTE (0);   /* M */
+      SWAP_BYTE (2);   /* Xm */
+      SWAP_BYTE (4);   /* dM */
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "spectrum")) {
+    if (size != SPECTRUM_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Spectrum) %d vs %d\n", size, SPECTRUM_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += SPECTRUM_SIZE) {
+      SWAP_WORD (0);  /* ra */ 
+      SWAP_WORD (4);  /* dec */ 
+      SWAP_WORD (8);  /* exptime */ 
+      SWAP_WORD (12); /* airmass */ 
+      SWAP_WORD (16); /* Ws */ 
+      SWAP_WORD (20); /* We */ 
+      SWAP_WORD (24); /* dW */ 
+      SWAP_WORD (28); /* Nspec */ 
+      SWAP_WORD (32); /* obstime */ 
+      SWAP_WORD (36); /* regtime */ 
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "image")) {
+    if (size != IMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Image) %d vs %d\n", size, IMAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += IMAGE_SIZE) {
+      SWAP_DBLE (0); /* coords.crval1 */
+      SWAP_DBLE (8); /* coords.crval2 */
+      for (j = 16; j < 104; j+=4) { /* coords.crpix, delt, pc_ij, polyterms[7][2] */
+	SWAP_WORD (j);
+      }
+      SWAP_WORD (120); /* tzero */
+      SWAP_WORD (124); /* nstar */
+      for (j = 128; j < 146; j+=2) { /* sec z, NX, NY, apmifit, dapmifit, source, Mcal, dMcal, Xm */
+	SWAP_BYTE (j);
+      }
+      SWAP_WORD (184); /* exptime */
+      SWAP_WORD (210); /* order */
+      /**** this (210) is an error! (don't fix, replaced with autocode) ****/
+      for (j = 212; j < 240; j+=2) {
+	SWAP_BYTE (j); /* Mx - Myyy */
+      }
+    }
+    return (TRUE);
+  }
+
+# if (PANSTARRS)
+  if (!strcmp (type, "average")) {
+    if (size != AVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Average) %d vs %d\n", size, AVERAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += AVERAGE_SIZE) {
+      SWAP_DBLE (0);   /* R */
+      SWAP_DBLE (8);   /* D */
+      SWAP_BYTE (16);  /* M */
+      SWAP_BYTE (18);  /* Nm */
+      SWAP_BYTE (20);  /* Nn */
+      SWAP_BYTE (22);  /* Xp */
+      SWAP_BYTE (24);  /* Xm */
+      SWAP_BYTE (26);  /* code */
+      SWAP_WORD (28);  /* offset */
+      SWAP_WORD (32);  /* missing */
+      SWAP_BYTE (36);  /* dM */
+      SWAP_BYTE (38);  /* Xg */
+    }
+    return (TRUE);
+  } 
+  if (!strcmp (type, "measure")) {
+    if (size != MEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Measure) %d vs %d\n", size, MEASURE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += MEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (8);   /* Mgal */
+      SWAP_BYTE (10);  /* Map  */
+      SWAP_BYTE (12);  /* FWx */
+      /* 14, 15, 16, 17 - char */
+      SWAP_BYTE (18);  /* source */
+      SWAP_WORD (20);  /* t */
+      SWAP_WORD (24);  /* averef */
+      SWAP_BYTE (28);  /* dt */
+      SWAP_BYTE (30);  /* flags */
+    }
+    return (TRUE);
+  }
+
+# endif /** PANSTARRS **/
+
+
+# if (ELIXIR)
+  if (!strcmp (type, "average")) {
+    if (size != AVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Average) %d vs %d\n", size, AVERAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += AVERAGE_SIZE) {
+      SWAP_WORD (0);   /* R */
+      SWAP_WORD (4);   /* D */
+      SWAP_BYTE (8);   /* M */
+      SWAP_BYTE (10);  /* Nm */
+      SWAP_BYTE (12);  /* Nn */
+      SWAP_BYTE (14);  /* Xp */
+      SWAP_BYTE (16);  /* Xm */
+      SWAP_BYTE (18);  /* code */
+      SWAP_WORD (20);  /* offset */
+      SWAP_WORD (24);  /* missing */
+      SWAP_BYTE (28);  /* dM */
+      SWAP_BYTE (30);  /* Xg */
+    }
+    return (TRUE);
+  } 
+  if (!strcmp (type, "measure")) {
+    if (size != MEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Measure) %d vs %d\n", size, MEASURE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += MEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (8);   /* Mgal */
+      SWAP_BYTE (10);  /* Map  */
+      SWAP_BYTE (12);  /* FWx */
+      /* 14, 15, 16, 17 - char */
+      SWAP_BYTE (18);  /* source */
+      SWAP_WORD (20);  /* t */
+      SWAP_WORD (24);  /* averef */
+      SWAP_BYTE (28);  /* dt */
+      SWAP_BYTE (30);  /* flags */
+    }
+    return (TRUE);
+  }
+
+# endif /** ELIXIR **/
+
+
+# if (LONEOS)
+  if (!strcmp (type, "average")) {
+    if (size != OLDAVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldAverage) %d vs %d\n", size, OLDAVERAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDAVERAGE_SIZE) {
+      SWAP_WORD (0);   /* R */
+      SWAP_WORD (4);   /* D */
+      SWAP_BYTE (8);   /* M */
+      SWAP_BYTE (10); /* Nm */
+      SWAP_BYTE (12); /* Nn */
+      SWAP_BYTE (14); /* Xp */
+      SWAP_BYTE (16); /* Xm */
+      SWAP_BYTE (18); /* code */
+      SWAP_WORD (20); /* offset */
+      SWAP_WORD (24); /* missing */
+    }
+    return (TRUE);
+  } 
+  if (!strcmp (type, "measure")) {
+    if (size != OLDMEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldMeasure) %d vs %d\n", size, OLDMEASURE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDMEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (10);  /* source */
+      SWAP_WORD (12);  /* t */
+      SWAP_WORD (16);  /* average */
+    }
+    return (TRUE);
+  }
+# endif /** LONEOS **/
+
+# if (0) /*** others ***/
+  if (!strcmp (type, "oldsecfilt")) {
+    if (size != OLDSECFILT_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldSecFilt) %d vs %d\n", size, OLDSECFILT_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *) ptr;
+    for (i = 0; i < nitems; i++, byte += OLDSECFILT_SIZE) {
+      SWAP_BYTE (0);   /* M */
+      SWAP_BYTE (2);   /* Xm */
+    }
+    return (TRUE);
+  }
+  if (!strcmp (type, "rufimage")) {
+    if (size != RUFIMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (RufImage) %d vs %d\n", size, RUFIMAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += RUFIMAGE_SIZE) {
+      SWAP_WORD (0);   /* sky */
+      SWAP_WORD (4);   /* bias */
+      SWAP_WORD (8);  /* fwhm */
+      SWAP_WORD (12); /* exptime */
+      SWAP_WORD (16); /* airmass */
+      SWAP_WORD (20); /* obstime */
+      SWAP_BYTE (24); /* ccdnum */
+    }
+    return (TRUE);
+  }
+  if (!strcmp (type, "olddetreg")) {
+    if (size != OLDDETREG_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, OLDDETREG_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDDETREG_SIZE) {
+      SWAP_WORD (0);   /* tstart */
+      SWAP_WORD (4);   /* tstop */
+      SWAP_WORD (8);   /* treg */
+      SWAP_WORD (12);  /* sigma */
+      SWAP_WORD (16);  /* clipsigma */
+      SWAP_WORD (20);  /* type */
+      SWAP_WORD (24);  /* filter */
+      SWAP_WORD (28);  /* ccd */
+    }
+    return (TRUE);
+  }
+# endif /** others **/
+# endif /** now in autocode **/
+
+  fprintf (stderr, "unknown type %s\n", type);
+  return (FALSE);
+
+# else
+
+  return (TRUE);
+
+# endif 
+
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/IOBufferOps.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/IOBufferOps.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/IOBufferOps.c	(revision 21773)
@@ -0,0 +1,122 @@
+# include <ohana.h>
+
+int InitIOBuffer (IOBuffer *buffer, int Nalloc) {
+
+  buffer[0].Nalloc = Nalloc;
+  buffer[0].Nreset = Nalloc;
+  buffer[0].Nblock = Nalloc / 2;
+  buffer[0].Nbuffer = 0;
+
+  ALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+  bzero (buffer[0].buffer, buffer[0].Nalloc);
+
+  return (TRUE);
+}
+
+int FlushIOBuffer (IOBuffer *buffer) {
+
+  buffer[0].Nbuffer = 0;
+  buffer[0].Nalloc = buffer[0].Nreset;
+  REALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+  bzero (buffer[0].buffer, buffer[0].Nalloc);
+
+  return (TRUE);
+}
+
+int ReadtoIOBuffer (IOBuffer *buffer, int fd) {
+
+  int Nread, Nfree;
+
+  if (fd == 0) {
+    /* pipe is closed */
+    return (0);
+  }
+
+  Nfree = buffer[0].Nalloc - buffer[0].Nbuffer;
+  if (Nfree < buffer[0].Nblock) {
+    buffer[0].Nblock *= 2;
+    buffer[0].Nblock = MIN (buffer[0].Nblock, 0x10000);
+    buffer[0].Nalloc += 2*buffer[0].Nblock;
+    REALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+    Nfree = buffer[0].Nalloc - buffer[0].Nbuffer;
+    bzero (buffer[0].buffer + buffer[0].Nbuffer, Nfree);
+  }
+
+  Nread = read (fd, &buffer[0].buffer[buffer[0].Nbuffer], buffer[0].Nblock);
+
+  /* on success, increase the block size for the next read */
+  
+  if (Nread >= 0) {
+    buffer[0].Nbuffer += Nread;
+    return (Nread);
+  }
+
+  if (Nread == -1) {
+    switch (errno) {
+    case EAGAIN:
+    case EIO:
+      /** no data available in pipe **/
+      return (-1);
+    default:
+      /** error reading from pipe **/
+      perror ("ReadtoIOBuffer read error");
+      return (-2);
+    }
+  }
+  return (Nread);
+}
+
+/* read until buffer is empty (Nmax retries) */
+int EmptyIOBuffer (IOBuffer *buffer, int Nmax, int fd) {
+
+  int i, status;
+
+  status = -1;
+  for (i = 0; (status != 0) && (i < Nmax); i++) {
+    status = ReadtoIOBuffer (buffer, fd);
+    if (status == -1) usleep (10000);
+    if (status > 0) i = 0;
+  }
+  if (status == -1) return (FALSE);
+  return (TRUE);
+}
+
+void FreeIOBuffer (IOBuffer *buffer) {
+
+  if (buffer[0].buffer != (char *) NULL) {
+    free (buffer[0].buffer);
+  }
+}
+
+/* print to an IOBuffer (varargs form) */
+int PrintIOBuffer (IOBuffer *buffer, char *format, ...) {
+
+  int status;
+  va_list argp;  
+
+  va_start (argp, format);
+  status = vPrintIOBuffer (buffer, format, argp);
+  va_end (argp);
+  return (status);
+}
+
+/* print to an IOBuffer (va_list form) */
+int vPrintIOBuffer (IOBuffer *buffer, char *format, va_list argp) {
+
+  /* add the output line to the given IOBuffer */
+  
+  int Nbyte;
+  char tmp;
+
+  Nbyte = vsnprintf (&tmp, 0, format, argp);
+
+  if (buffer[0].Nbuffer + Nbyte + 1>= buffer[0].Nalloc) {
+    buffer[0].Nalloc = buffer[0].Nbuffer + Nbyte + 64;
+    REALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+  }
+
+  vsnprintf (&buffer[0].buffer[buffer[0].Nbuffer], Nbyte + 1, format, argp);
+  buffer[0].Nbuffer += Nbyte;
+  return (TRUE);
+}
+  
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/config.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/config.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/config.c	(revision 21773)
@@ -0,0 +1,454 @@
+# include <ohana.h>
+
+# define D_NBYTES 4096
+
+static char *ConfigVariable = (char *) NULL;
+static int NDefineVariable;
+static char **DefineVariable;
+static char **DefineValue;
+
+char *SelectConfigFile (int *argc, char **argv, char *progname) {
+  
+  /* 
+     config file selection rules (first ones override later ones):
+
+     1) -c Filename   : use Filename
+     2) PROGNAME      : use environment variable as config file
+     3) progname.rc   : use alternate name in local dir as config file
+     4) .prognamerc   : use rc file in local dir as config file
+     5) ~/.prognamerc : use rc file in homedir as config file
+
+     special variable definitions:
+     1) -C WORD       : set CONFIG variable to WORD
+     2) -D NAME WORD  : set NAME variable to WORD
+        -D overrides variables in param file
+
+     these command-line options are removed and a complete arg list left behind
+  */
+
+  char *filename, *find, *home;
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int i, N, NDEF, status;
+  
+  /* first look for -C CONFIG variable */
+  if ((N = get_argument (*argc, argv, "-C"))) {
+    remove_argument (N, argc, argv);
+    if (ConfigVariable != (char *) NULL) free (ConfigVariable);
+    ConfigVariable = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+    
+  /* next look for -D NAME WORD variables */
+  NDEF = 10;
+  ALLOCATE (DefineVariable, char *, NDEF);
+  ALLOCATE (DefineValue, char *, NDEF);
+  for (i = 0; (N = get_argument (*argc, argv, "-D")); i++) {
+    remove_argument (N, argc, argv);
+    DefineVariable[i] = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    DefineValue[i] = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    if (i == NDEF - 1) {
+      NDEF += 10;
+      REALLOCATE (DefineVariable, char *, NDEF);
+      REALLOCATE (DefineValue, char *, NDEF);
+    }      
+  }    
+  NDefineVariable = i;
+  REALLOCATE (DefineVariable, char *, MAX (1, i));
+    
+  /* look for -c FILENAME for config file */
+  if ((N = get_argument (*argc, argv, "-c"))) {
+    remove_argument (N, argc, argv);
+    filename = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    return (filename);
+  }
+  
+  /* look for PROGNAME env var */
+  find = strcreate (progname);
+  for (i = 0; i < strlen(find); i++) find[i] = toupper (find[i]);
+  filename = getenv (find);
+  free (find);
+  if (filename != (char *) NULL) {
+    find = strcreate (filename);
+    return (find);
+  }
+
+  uid = getuid();
+  gid = getgid();
+  ALLOCATE (find, char, strlen(progname) + 32);
+
+  /* look for progname.rc */
+  sprintf (find, "%s.rc", progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+
+  /* we eliminate this option: this is just confusing */
+# if (0)  
+  /* look for ./.prognamerc */
+  sprintf (find, ".%src", progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+  free (find);
+# endif
+
+  /* look for ~/.prognamerc */
+  home = getenv ("HOME");
+  if (home == (char *) NULL) { return ((char *) NULL); }
+  ALLOCATE (find, char, 1024);
+  sprintf (find, "%s/.%src", home, progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+  free (find);
+  return ((char *) NULL);
+}
+
+char *LoadConfigFile (char *filename) {
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, nbytes, Nout, Ncpy, INPUT, Nlevel;
+  char *ibuffer, *obuffer, *tbuffer;
+  char *last, *next;
+  char infile[256], line[256];
+  
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return ((char *) NULL);
+  }
+ 
+  /* allocate tmp space, 2 extra bytes for a final return and EOL */
+  Nbytes = 0;
+  NBYTES = D_NBYTES;
+  ALLOCATE (ibuffer, char, NBYTES + 2);
+    
+  /* load data from file */
+  done = FALSE;
+  while ((nbytes = fread (&ibuffer[Nbytes], sizeof(char), D_NBYTES, f)) == D_NBYTES) {
+    Nbytes += nbytes;
+    NBYTES += D_NBYTES;
+    REALLOCATE (ibuffer, char, NBYTES + 2);
+  }
+  Nbytes += nbytes;
+  fclose (f);
+
+  /* add final return & EOL if non-existent */
+  if (ibuffer[Nbytes-1] != '\n') {
+    ibuffer[Nbytes] = '\n';
+    Nbytes ++;
+  }
+  if (ibuffer[Nbytes]) ibuffer[Nbytes] = 0;
+
+  /* add the optional variables to the end of the input buffer */
+  if (ConfigVariable != (char *) NULL) {
+    snprintf (line, 256, "%s %s\n", "CONFIG", ConfigVariable);
+    Ncpy = strlen (line);
+    if (Nbytes + Ncpy >= NBYTES - 1) {
+      NBYTES = Nbytes + Ncpy + D_NBYTES;
+      REALLOCATE (ibuffer, char, NBYTES);
+    }    
+    memcpy (&ibuffer[Nbytes], line, Ncpy);
+    Nbytes += Ncpy;
+    ibuffer[Nbytes] = 0;
+  }
+  for (i = 0; i < NDefineVariable; i++) {
+    snprintf (line, 256, "%s %s\n", DefineVariable[i], DefineValue[i]);
+    Ncpy = strlen (line);
+    if (Nbytes + Ncpy >= NBYTES - 1) {
+      NBYTES = Nbytes + Ncpy + D_NBYTES;
+      REALLOCATE (ibuffer, char, NBYTES);
+    }    
+    memcpy (&ibuffer[Nbytes], line, Ncpy);
+    Nbytes += Ncpy;
+    ibuffer[Nbytes] = 0;
+  }
+  
+  /* loop over input buffer, interpolating 'input' lines until none are added */
+  Nlevel = 0;
+  do {
+    INPUT = FALSE;
+
+    /* allocate output buffer & set counter */
+    NBYTES = Nbytes + D_NBYTES;
+    ALLOCATE (obuffer, char, NBYTES);
+    Nout = 0;
+    
+    /* copy from ibuffer to obuffer, interpolating 'input' lines */
+    last = next = ibuffer;
+    for (i = 1; (next = ScanConfig (ibuffer, "input", "%s", i, infile)) != (char *) NULL; i++) {
+      /* copy data from last point to before 'input' */ 
+      Ncpy = next - last - 5;
+      if (Nout + Ncpy >= NBYTES - 1) {
+	NBYTES = Nout + Ncpy + D_NBYTES;
+	REALLOCATE (obuffer, char, NBYTES);
+      }      
+      memcpy (&obuffer[Nout], last, Ncpy);
+      Nout += Ncpy;
+      obuffer[Nout] = 0;
+      
+      /* insert data from 'input' file */
+      tbuffer = LoadRawConfigFile (infile, FALSE);
+      if (tbuffer != (char *) NULL) {
+	Ncpy = strlen (tbuffer);
+	if (Nout + Ncpy >= NBYTES - 1) {
+	  NBYTES = Nout + Ncpy + D_NBYTES;
+	  REALLOCATE (obuffer, char, NBYTES);
+	}      
+	memcpy (&obuffer[Nout], tbuffer, Ncpy);
+	free (tbuffer);
+	Nout += Ncpy;
+	obuffer[Nout] = 0;
+      }
+      
+      /* pointer goes to end of input line */
+      last = strchr (next, '\n');
+      if (last == (char *) NULL) break;
+      last ++;
+      INPUT = TRUE;
+    }
+    /* last set of bytes after last input */
+    Ncpy = strlen (last);
+    if (Nout + Ncpy >= NBYTES - 1) {
+      NBYTES = Nout + Ncpy + D_NBYTES;
+      REALLOCATE (obuffer, char, NBYTES);
+    }      
+    memcpy (&obuffer[Nout], last, Ncpy);
+    Nout += Ncpy;
+    obuffer[Nout] = 0;
+    free (ibuffer);
+    ibuffer = obuffer;
+    Nlevel ++;
+  } while (INPUT && (Nlevel < 20));
+  if (Nlevel == 20) {
+    fprintf (stderr, "warning: config reached max depth of 20\n");
+  }
+
+  /* 'obuffer' now has complete set of interpolated lines from 'filename' */
+  return (obuffer);
+}
+
+char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...) {
+  
+  int i;
+  char *p, *p2, *tmp, *tfield, *start, *expandline();
+  va_list argp;
+  double value;
+  
+  if (config == (char *) NULL) return ((char *) NULL);
+  va_start (argp, Nentry);
+
+  ALLOCATE (tfield, char, strlen (field) + 3);
+  sprintf (tfield, "\n%s", field);
+
+  /* we search for Nentry matching fields,
+     or until the end if Nentry == 0 */
+  p = (char *) NULL;
+  p2 = config;
+  for (i = 0; (i < Nentry) || !Nentry;) {
+    tmp = strstr (p2, tfield);
+    if (tmp == (char *) NULL) {
+      break;
+    }
+    p2 = tmp + strlen (tfield);
+    if (OHANA_WHITESPACE (*p2)) {
+      p = p2;
+      i++;
+    }
+  }
+  free (tfield);
+  if (Nentry && (i != Nentry)) {
+    p = va_arg (argp, char *);
+    p[0] = 0;
+    return ((char *) NULL);
+  }
+  if (p == (char *) NULL) {
+    p = va_arg (argp, char *);
+    p[0] = 0;
+    return ((char *) NULL);
+  }
+
+  start = p;
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL) p2 = config + strlen(config);
+    ALLOCATE (tmp, char, p2-p + 2);
+    memcpy (tmp, p, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    tmp = expandline (tmp, config);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+    free (tmp);
+  } else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (start);
+  
+}
+
+
+char *expandline (char *line, char *config) {
+
+  int Nin, Nout, Ncpy, NBYTES;
+  char *p1, *p2, word[256], value[256];
+  char *outline;
+  
+  NBYTES = 256;
+  ALLOCATE (outline, char, NBYTES);
+  Nout = 0;
+  Nin  = 0;
+  while ((p1 = strchr (&line[Nin], '$')) != (char *) NULL) {
+    Ncpy = p1 - line - Nin;
+    if (Nout + Ncpy >= NBYTES) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES - 2);
+    }
+    memcpy (&outline[Nout], &line[Nin], Ncpy);
+    Nout += Ncpy;
+    
+    p1 ++;
+    for (p2 = p1; isalnum (*p2) || (*p2 == '_') || (*p2 == '-'); p2++);
+    memcpy (word, p1, p2 - p1);
+    word[p2-p1] = 0;
+    Nin += Ncpy + 1 + p2 - p1;
+    
+    /* search for last entry of word */
+    if (!ScanConfig (config, word, "%s", 0, value)) {
+      fprintf (stderr, "variable %s not found in config file\n", word);
+      return (line);
+    }
+    Ncpy = strlen(value);
+    if (Nout + Ncpy >= NBYTES - 2) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES);
+    }    
+    memcpy (&outline[Nout], value, Ncpy);
+    Nout += Ncpy;
+  }
+  Ncpy = strlen(&line[Nin]);
+  if (Nout + Ncpy >= NBYTES - 2) {
+    NBYTES = Nout + Ncpy + 256;
+    REALLOCATE (outline, char, NBYTES);
+  }  
+  memcpy (&outline[Nout], &line[Nin], Ncpy);
+  Nout += Ncpy;
+  outline[Nout] = 0;
+  free (line);
+  return (outline);
+
+}
+
+char *LoadRawConfigFile (char *filename, int options) {
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, nbytes, Ncpy;
+  char *ibuffer;
+  char line[256];
+  
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return ((char *) NULL);
+  }
+ 
+  /* allocate tmp space, 2 extra bytes for a final return and EOL */
+  Nbytes = 0;
+  NBYTES = D_NBYTES;
+  ALLOCATE (ibuffer, char, NBYTES + 2);
+    
+  /* load data from file */
+  done = FALSE;
+  while ((nbytes = fread (&ibuffer[Nbytes], sizeof(char), D_NBYTES, f)) == D_NBYTES) {
+    Nbytes += nbytes;
+    NBYTES += D_NBYTES;
+    REALLOCATE (ibuffer, char, NBYTES + 2);
+  }
+  Nbytes += nbytes;
+  fclose (f);
+
+  /* add final return & EOL, if non-existent */
+  if (ibuffer[Nbytes-1] != '\n') {
+    ibuffer[Nbytes] = '\n';
+    Nbytes ++;
+  }
+  if (ibuffer[Nbytes]) ibuffer[Nbytes] = 0;
+
+  if (options) {
+    /* write optional variables to bottom of buffer, overriding entries in the file */
+    if (ConfigVariable != (char *) NULL) {
+      snprintf (line, 256, "%s %s\n", "CONFIG", ConfigVariable);
+      Ncpy = strlen (line);
+      if (Nbytes + Ncpy >= NBYTES) {
+	NBYTES = Nbytes + Ncpy + D_NBYTES;
+	REALLOCATE (ibuffer, char, NBYTES + 2);
+      }    
+      memcpy (&ibuffer[Nbytes], line, Ncpy);
+      Nbytes += Ncpy;
+      ibuffer[Nbytes] = 0;
+    }
+    for (i = 0; i < NDefineVariable; i++) {
+      snprintf (line, 256, "%s %s\n", DefineVariable[i], DefineValue[i]);
+      Ncpy = strlen (line);
+      if (Nbytes + Ncpy >= NBYTES) {
+	NBYTES = Nbytes + Ncpy + D_NBYTES;
+	REALLOCATE (ibuffer, char, NBYTES + 2);
+      }    
+      memcpy (&ibuffer[Nbytes], line, Ncpy);
+      Nbytes += Ncpy;
+      ibuffer[Nbytes] = 0;
+    }
+  }
+
+  return (ibuffer);
+}
+
+/* 
+char *LoadConfigFile (char *filename) {
+  
+  char *config;
+
+  config = LoadSubConfigFile (filename, TRUE);
+
+  return (config);
+
+}
+
+*/
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/findexec.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/findexec.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/findexec.c	(revision 21773)
@@ -0,0 +1,378 @@
+# include <ohana.h>
+
+int check_file_exec (char *filename) {
+  
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to exec file */
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IXUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IXGRP)) || 
+	(                            (filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IXOTH))) {
+      return (TRUE);
+    } else {
+      return (FALSE);
+    }
+  }
+  return (FALSE);
+}
+
+/* check that:
+   - dir exists
+   - dir permissions OK
+*/
+int check_dir_access (char *path, int VERBOSE) {
+  
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  status = stat (path, &filestat);
+  if (status == -1) {
+    if (VERBOSE) fprintf (stderr, "directory %s does not exist, creating...\n", path);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdirhier (path, cmode);
+    if (status == -1) {
+      if (VERBOSE) fprintf (stderr, "can't create %s\n", path);
+      return (FALSE);
+    }
+  } 
+  status = stat (path, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    if (VERBOSE) fprintf (stderr, "can't write to %s\n", path);
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* check that file can be written to:
+   - dir exists
+   - dir permissions OK
+   - file permissions OK, 
+   - file backup permission OK (optional)
+*/
+int check_file_access (char *basefile, int BACKUP, int VERBOSE) {
+  
+  char *path, *filename;
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  path = pathname (basefile);
+  status = check_dir_access (path, VERBOSE);
+  free (path);
+  if (!status) return (FALSE);
+  
+  /* check permission to write to file */
+  status = stat (basefile, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      if (VERBOSE) fprintf (stderr, "can't write to %s\n", basefile);
+      return (FALSE);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  if (BACKUP) {
+    ALLOCATE (filename, char, strlen(basefile) + 2);
+    sprintf (filename, "%s~", basefile);
+    status = stat (filename, &filestat);
+    if (status == 0) { /* file exists, are permissions OK? */
+      if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	  ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	  ((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+      } else {
+	if (VERBOSE) fprintf (stderr, "can't write to %s\n", filename);
+	return (FALSE);
+      }
+    }
+    free (filename);
+  }
+  return (TRUE);
+}
+
+/* pathname:
+   given path/filename, returns path
+   given just filename, returns . 
+   given path1/path2/,  returns path1
+*/
+
+char *pathname (char *infile) {
+ 
+  int i;
+  char *c, *file;
+
+  /* make working version */
+  file = strcreate (infile);
+
+  /* strip off trailing / */
+  for (i = strlen (file); (i > 0) && (file[i] == '/'); i--) file[i] = 0;
+
+  c = strrchr (file, '/');
+  if (c == (char *) NULL) {
+    strcpy (file, ".");
+  } else {
+    *c = 0;
+  }
+  
+  return (file);
+  
+}
+
+/* filerootname
+
+   given /path/file.ext return file 
+   given /path/file return file 
+   given /path/file/ return file 
+*/
+
+char *filerootname (char *infile) {
+
+  int i;
+  char *file, *root, *p1, *p2;
+
+  /* make working version */
+  file = strcreate (infile);
+
+  /* strip off trailing / */
+  for (i = strlen (file); (i > 0) && (file[i] == '/'); i--) file[i] = 0;
+
+  /* find last / */
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) 
+    p1 = file;
+  else
+  p1 ++;
+
+  /* find last . */
+  p2 = strrchr (file, '.');
+  if (p2 == (char *) NULL) p2 = p1 + strlen(p1);
+
+  /* create new string, free working space */
+  root = strncreate (p1, p2-p1);
+  free (file);
+
+  return (root);
+
+}  
+
+/* fileextname
+
+   given /path/file.ext return ext 
+   given /path/file return NULL 
+   given /path/file/ return NULL 
+   given file.ext return ext
+*/
+
+char *fileextname (char *file) {
+
+  char *root, *p1, *p2;
+
+  /* find last / */
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) p1 = file;
+
+  /* find last . after p1 */
+  p2 = strrchr (p1, '.');
+  if (p2 == (char *) NULL) return ((char *) NULL);
+  p2 ++;
+
+  /* create new string, free working space */
+  root = strncreate (p2, strlen(p2));
+  return (root);
+
+}  
+
+/* given /path/file.ext return file.ext */
+char *filebasename (char *name) {
+ 
+  char *c, *file;
+
+  ALLOCATE (file, char, strlen(name) + 1);
+  strcpy (file, name);
+  c = strrchr (file, '/');
+  if (c == (char *) NULL) {
+    strcpy (file, name);
+  } else {
+    strcpy (file, c+1);
+  }
+  
+  return (file);
+  
+}
+
+char *findexec (int argc, char **argv) {
+
+  int i, N, done, status;
+  char *c, *e, *dir, path[1024], name[1024];
+
+  /* if given an absolute or relative path, use it */
+  if (strchr (argv[0], '/') != (char *) NULL) {
+    status = check_file_exec (argv[0]);
+    if (status) {
+      if (realpath (argv[0], path) == (char *) NULL) return ((char *) NULL);
+      dir = pathname (path);
+      return (dir);
+    } else {
+      return ((char *) NULL);
+    }
+  }
+  N = 0;
+  for (i = argc+1; argv[i] != (char *) NULL; i++) {
+    if (!strncmp (argv[i], "PATH", 4)) {
+      N = i;
+      break;
+    }
+  }
+
+  if (N) {
+    c = &argv[N][5];
+    e = strchr (c, ':');
+    done = FALSE;
+    i = 0;
+    while (!done) {
+      bzero (path, 1024);
+      if (e == (char *) NULL) {
+	done = TRUE;
+	strncpy (path, c, strlen(c));
+      } else {
+	strncpy (path, c, e-c);
+	c = e+1;
+	e = strchr (c, ':');
+      }
+      sprintf (name, "%s/%s", path, argv[0]);
+      status = check_file_exec (name);
+
+      if (status) {
+	if (realpath (name, path) == (char *) NULL) continue;
+	dir = pathname (path);
+	return (dir);
+      }
+    }
+  }
+  return ((char *) NULL);
+}
+
+/* make directory hierarchy, 0: success, -1: failure (just like mkdir) */
+int mkdirhier (char *path, int mode) {
+
+  char *tpath;
+
+  /* force addition of user exec/read/write */
+  mode |= S_IRWXU;
+  if (mkdir (path, mode)) {
+    if (errno == ENOENT) { 
+      tpath = pathname (path);
+      if (!mkdirhier (tpath, mode)) {
+	if (mkdir (path, mode)) {
+	  return (-1);
+	} else {
+	  errno = 0;
+	  return (0);
+	}
+      } else {
+	return (-1);
+      }
+    } else {
+      return (-1);
+    }
+  } else {
+    return (0);
+  }
+}
+
+char *getcwd_cfht (char *path, int size) {
+  
+  char *hostname, *newpath, *p;
+
+  path = getcwd (path, size);
+  
+  if (!strncmp (path, "/local/data", strlen ("/local/data"))) {
+    
+    ALLOCATE (hostname, char, size);
+
+    if (gethostname (hostname, size-1)) {
+      fprintf (stderr, "ERROR: can't get hostname\n");
+      free (hostname);
+      return ((char *) NULL);
+    }
+    if ((p = strchr (hostname, '.')) != (char *) NULL) *p = 0;
+    
+    ALLOCATE (newpath, char, size);
+    /* path might be just /local/data or /local/data/ */
+       
+    p = path + strlen ("/local/data/");
+    if (strlen (path) <= strlen ("/local/data/")) {
+      snprintf (newpath, size, "/data/%s", hostname);
+    } else {
+      snprintf (newpath, size, "/data/%s/%s", hostname, p);
+    }      
+
+    free (hostname);
+    strcpy (path, newpath);
+
+    free (newpath);
+
+  }
+
+  return (path);
+
+}
+
+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 (1);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~", filename);
+    chmod (line, cmode);
+  }
+}
+
+/* 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: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/gaussj.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/gaussj.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/gaussj.c	(revision 21773)
@@ -0,0 +1,155 @@
+# include <ohana.h>
+
+int dgaussj (double **a, int n, double **b, int m) {
+
+  int *indexCol;
+  int *indexRow;
+  int *pivot;
+  int i, col, row, j, k, l, ll;
+  double big, temp;
+  
+  ALLOCATE (indexCol, int, n);
+  ALLOCATE (indexRow, int, n);
+  ALLOCATE (pivot, int, n);
+  for (j = 0; j < n; j++) pivot[j] = 0;
+
+  row = col = 0;
+  big = fabs(a[0][0]);
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (!finite(a[i][j])) goto escape;
+      if (pivot[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (pivot[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big = fabs (a[j][k]);
+	      row = j;
+	      col = k;
+	    }
+	  } else {
+	    if (pivot[k] > 1) goto escape;
+	  }
+	}
+      }
+    }
+    pivot[col]++;
+    if (row != col) {
+      for (l = 0; l < n; l++) SWAP (a[row][l], a[col][l]);
+      for (l = 0; l < m; l++) SWAP (b[row][l], b[col][l]);
+    }
+    indexRow[i] = row;
+    indexCol[i] = col;
+    if (a[col][col] == 0.0) goto escape;
+
+    /* rescale by pivot reciprocal */
+    temp = 1.0 / a[col][col];
+    a[col][col] = 1.0;
+    for (l = 0; l < n; l++) a[col][l] *= temp;
+    for (l = 0; l < m; l++) b[col][l] *= temp;
+
+    /* adjust the elements above the pivot */
+    for (ll = 0; ll < n; ll++) {
+      if (ll != col) {
+	temp = a[ll][col];
+	a[ll][col] = 0.0;
+	for (l = 0; l < n; l++) a[ll][l] -= a[col][l]*temp;
+	for (l = 0; l < m; l++) b[ll][l] -= b[col][l]*temp;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indexRow[l] != indexCol[l]) {
+      for (k = 0; k < n; k++) SWAP (a[k][indexRow[l]], a[k][indexCol[l]]);
+    }
+  }
+  free (pivot);
+  free (indexRow);
+  free (indexCol);
+  return (TRUE);
+
+escape:
+  free (pivot);
+  free (indexRow);
+  free (indexCol);
+  return (FALSE);
+}
+
+int fgaussj (float **a, int n, float **b, int m) {
+
+  int *indexCol;
+  int *indexRow;
+  int *pivot;
+  int i, col, row, j, k, l, ll;
+  float big, temp;
+  
+  ALLOCATE (indexCol, int, n);
+  ALLOCATE (indexRow, int, n);
+  ALLOCATE (pivot, int, n);
+  for (j = 0; j < n; j++) pivot[j] = 0;
+
+  row = col = 0;
+  big = fabs(a[0][0]);
+
+  for (i = 0; i < n; i++) {
+    big = 0.0;
+    for (j = 0; j < n; j++) {
+      if (!finite(a[i][j])) goto escape;
+      if (pivot[j] != 1) {
+	for (k = 0; k < n; k++) {
+	  if (pivot[k] == 0) {
+	    if (fabs (a[j][k]) >= big) {
+	      big  = fabs (a[j][k]);
+	      row = j;
+	      col = k;
+	    }
+	  } else {
+	    if (pivot[k] > 1) goto escape;
+	  }
+	}
+      }
+    }
+    pivot[col]++;
+    if (row != col) {
+      for (l = 0; l < n; l++) SWAP (a[row][l], a[col][l]);
+      for (l = 0; l < m; l++) SWAP (b[row][l], b[col][l]);
+    }
+    indexRow[i] = row;
+    indexCol[i] = col;
+    if (a[col][col] == 0.0) goto escape;
+
+    /* rescale by pivot reciprocal */
+    temp = 1.0 / a[col][col];
+    a[col][col] = 1.0;
+    for (l = 0; l < n; l++) a[col][l] *= temp;
+    for (l = 0; l < m; l++) b[col][l] *= temp;
+ 
+    /* adjust the elements above the pivot */
+    for (ll = 0; ll < n; ll++) {
+      if (ll != col) {
+	temp = a[ll][col];
+	a[ll][col] = 0.0;
+	for (l = 0; l < n; l++) a[ll][l] -= a[col][l]*temp;
+	for (l = 0; l < m; l++) b[ll][l] -= b[col][l]*temp;
+      }
+    }
+  }
+
+  for (l = n - 1; l >= 0; l--) {
+    if (indexRow[l] != indexCol[l]) {
+      for (k = 0; k < n; k++) SWAP (a[k][indexRow[l]], a[k][indexCol[l]]);
+    }
+  }
+  free (pivot);
+  free (indexRow);
+  free (indexCol);
+  return (TRUE);
+
+escape:
+  free (pivot);
+  free (indexRow);
+  free (indexCol);
+  return (FALSE);
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/glockfile.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/glockfile.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/glockfile.c	(revision 21773)
@@ -0,0 +1,242 @@
+# include <ohana.h>
+
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state) {
+  
+  int i, nbytes, status;
+  char *lockname, buffer[64];
+  char *file, *path, mode[3];
+  int fd;
+  FILE *f, *flock;
+  struct stat filestat;
+  struct flock filelock;
+  struct timeval now, then;
+
+  f = flock = NULL;
+  file = path = lockname = NULL;
+
+  /* define lock type */
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  switch (type) {
+  case LCK_HARD:
+  case LCK_XCLD:
+    filelock.l_type   = F_WRLCK;  /* set an exclusive lock */
+    strcpy (mode, "r+");
+    break;
+  case LCK_SOFT:
+    filelock.l_type   = F_RDLCK;  /* set a shared lock */
+    strcpy (mode, "r");
+    break;
+  default:
+    *state = LCK_INVALID;
+    goto failure;
+  }
+
+  /* check if file exists */
+  status = stat (filename, &filestat);
+  if ((status == -1) && (errno == ENOENT)) {
+    /* if soft, return LCK_ACCESS */
+    if (type == LCK_SOFT) {
+      *state = LCK_MISSING;
+      goto failure;
+    } 
+    /* otherwise, we need to be able to create file */ 
+    strcpy (mode, "w+");
+  }
+  
+  /* try to open file (create if it does not exist) */
+  f = fopen (filename, mode);
+  if (f == NULL) {
+    *state = LCK_ACCESS;
+    goto failure;
+  }
+  fd = fileno (f);
+
+  /* we first try to set a FS level lock on the file */
+  gettimeofday (&then, (void *) NULL);
+  while (1) {
+    /* try to lock file */
+    if (fcntl (fd, F_SETLK, &filelock) != -1) goto got_lock;
+
+    /* check for timeout */
+    gettimeofday (&now, (void *) NULL);
+    if (DTIME (now, then) > timeout) {
+      *state = LCK_TIMEOUT;
+      goto failure;
+    }
+    usleep (10000); /* 10 ms is min utime */
+  }
+got_lock:
+
+  /* check if blocking hardlock exists */
+  if (type == LCK_HARD) {
+    /* set up name to lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+
+    status = stat (lockname, &filestat);
+    if ((status == -1) && (errno == ENOENT)) {
+      strcpy (mode, "w+");
+    } else {
+      strcpy (mode, "r+");
+    }
+
+    /* try to open lockfile */
+    flock = fopen (lockname, mode);
+    if (flock == NULL) {
+      *state = LCK_HARDOPEN;
+      goto failure;
+    }
+    fd = fileno (flock);
+    
+    /* try a few times to lock lockfile (locking the lockfile before checking
+       the contents will ensure the data is synced across NFS) */
+    for (i = 0; (i < 20) && (fcntl (fd, F_SETLK, &filelock) == -1); i++) usleep (10000);
+    if (i == 20) {
+      *state = LCK_HARDLOCK;
+      goto failure;
+    }
+    
+    /* we've locked the lockfile, now read the contents */
+    nbytes = fread (buffer, 1, 4, flock);
+    if (nbytes == 4) { /* lock file has a word in it */
+      buffer[4] = 0;
+      if (!strcmp (buffer, "BUSY")) { 
+	*state = LCK_HARDLOCKHARD;
+	goto failure;
+      }
+      /* note that we don't care if the lockfile has random garbage */
+    }
+  }
+    
+  /* set blocking hardlock */
+  if (type == LCK_HARD) {
+    /* we've really got the lock, write BUSY to protect it */
+    fseek (flock, 0, SEEK_SET);
+    nbytes = fprintf (flock, "BUSY\n");
+
+    /* 
+    if (nbytes != 5) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+      } */
+    
+    /* now fclose lockfile (also unlocks file) */
+    if (fclose (flock)) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+    }
+    flock = NULL;
+  }
+
+  /* check if file is empty or not */
+  fd = fileno (f);
+  if (fstat (fd, &filestat)) {
+    *state = LCK_UNKNOWN;
+  } else {
+    if (filestat.st_size == 0) {
+      *state = LCK_EMPTY;
+    } else {
+      *state = LCK_FULL;
+    }
+  }
+
+  if (path     != NULL) free (path);
+  if (file     != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  if (flock    != NULL) fclose (flock);
+  return (f);
+
+failure:
+  if (f        != NULL) fclose (f);
+  if (flock    != NULL) fclose (flock);
+  if (path     != NULL) free (path);
+  if (file     != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (NULL);
+}
+  
+/* clears lock. removes hardlock even if file pointer is not supplied */
+int fclearlockfile (char *filename, FILE *f, int type, int *state) {
+
+  int i, fd, status, nbytes;
+  char *lockname, *path, *file;
+  FILE *flock;
+  struct stat filestat;
+  struct flock filelock;
+
+  file = path = lockname = (char *) NULL;
+
+  /* define lock */
+  filelock.l_type   = F_UNLCK;
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+
+  /* first clear hard lockfile */
+  if (type == LCK_HARD) {
+
+    /* define lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+    
+    /* check for lockfile existance */
+    status = stat (lockname, &filestat);
+    if (status == -1) {
+      *state = LCK_HARDLOCK;
+      goto failure;
+    } 
+  
+    /* try to open lockfile */
+    flock = fopen (lockname, "w+");
+    if (flock == NULL) {
+      *state = LCK_HARDOPEN;
+      goto failure;
+    }
+    fd = fileno (flock);
+
+    /* try a few times to lock lockfile */
+    filelock.l_type = F_WRLCK;
+    for (i = 0; (i < 20) && (fcntl (fd, F_SETLK, &filelock) == -1); i++) usleep (10000);
+    if (i == 20) {
+      *state = LCK_HARDLOCKHARD;
+      goto failure;
+    }
+
+    /* set value to IDLE */
+    fseek (flock, 0, SEEK_SET);
+    nbytes = fprintf (flock, "IDLE\n");
+    if (nbytes != 5) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+    }
+
+    if (fclose (flock)) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+    }
+    flock = NULL;
+  }
+  
+  /* now unlock the file */
+  fclose (f);
+
+  *state = LCK_UNLOCK;
+  if (path != NULL)     free (path);
+  if (file != NULL)     free (file);
+  if (lockname != NULL) free (lockname);
+  return (1);
+
+failure:
+  if (path != NULL)     free (path);
+  if (file != NULL)     free (file);
+  if (lockname != NULL) free (lockname);
+  return (0);
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/ohana_allocate.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/ohana_allocate.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/ohana_allocate.c	(revision 21773)
@@ -0,0 +1,293 @@
+# include <stdio.h>
+# include <stdlib.h>
+# include <stdarg.h>
+
+/* need an internal version that does not use ohana_memory functions */
+# define FALSE 0 
+# define TRUE 1
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define OHANA_ALLOCATE(X,T,S)  \
+  X = (T *) malloc ((unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+  if (X == NULL) { \
+    fprintf(stderr,"failed malloc at %d in %s\n", __LINE__, __FILE__);\
+    abort(); } 
+# define OHANA_REALLOCATE(X,T,S) \
+  X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+  if (X == NULL) { \
+    fprintf(stderr,"failed realloc at %d in %s\n", __LINE__, __FILE__);\
+    abort(); }
+# define OHANA_CHECK_REALLOCATE(X,T,S,N,D) \
+  if ((N) >= (S)) { \
+    S += D; \
+    X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+    if (X == NULL) { \
+      fprintf(stderr,"failed realloc increment at %d in %s\n", __LINE__, __FILE__);\
+      abort(); } }
+# define OHANA_FREE(X) free(X)
+
+# define STATE_ALLOC    0
+# define STATE_REALLOC  1
+# define STATE_FREE     2
+# define STATE_EXTERNAL 3
+
+typedef struct {
+  char *file;
+  int   line;
+  void *ptr;   // location of externally visible entry
+  int   size;
+  int   state;
+} Memlist;
+
+// XXX consider fixing the memory tracking model (list?)
+// static long *memsort;
+// static long *memhash;
+static Memlist *memlist = NULL;
+int Nmemlist = 0;
+int NMEMLIST = 0;
+int NMEMBYTE = 0;
+
+void ohana_meminit () {
+  Nmemlist = 0;
+  NMEMLIST = 1000;
+  OHANA_ALLOCATE (memlist, Memlist, NMEMLIST);
+  // OHANA_ALLOCATE (memsort, long, NMEMLIST);
+  // OHANA_ALLOCATE (memhash, long, NMEMLIST);
+  NMEMBYTE = sizeof(size_t);
+}
+
+void ohana_memabort (char *format, ...) {
+  va_list argp;  
+
+  va_start (argp, format);
+  vfprintf (stderr, format, argp);
+  va_end (argp);
+  abort();
+}
+
+void *ohana_malloc (char *file, int line, int Nelem, size_t esize) {
+
+  void *ptr, *new;
+  int size;
+  size_t *marker;
+
+  if (memlist == NULL) ohana_meminit ();
+
+  Nelem = MAX (1, Nelem);
+  size = Nelem * esize;
+
+  new = malloc (size + 2*NMEMBYTE); /* 2 extra locations to save endposts */
+  if (new == NULL) ohana_memabort ("failed to allocate memory (%s, %d)\n", file, line);
+  ptr = new + NMEMBYTE;
+
+  marker = (size_t *) new;
+  *marker = 0xdeadbeef;
+  marker = (size_t *)(new + size + NMEMBYTE);
+  *marker = 0xdeadbeef;
+
+  /* new memory, add to stack */
+  memlist[Nmemlist].ptr  = ptr;
+  memlist[Nmemlist].file = file;
+  memlist[Nmemlist].line = line;
+  memlist[Nmemlist].size = size;
+  memlist[Nmemlist].state = STATE_ALLOC;
+
+  // before each free, we sort this pair to speed up searching
+  // memsort[Nmemlist] = ptr;
+  // memhash[Nmemlist] = Nmemlist;
+
+  Nmemlist ++;
+  if (Nmemlist == NMEMLIST) {
+    NMEMLIST += 1000;
+    OHANA_REALLOCATE (memlist, Memlist, NMEMLIST);
+  }
+  return (ptr);
+}
+
+void *ohana_realloc (char *file, int line, void *in, int Nelem, size_t esize) {
+
+  int i, size;
+  void *ptr, *ref, *new;
+  size_t *marker;
+
+  if (memlist == NULL) ohana_memabort ("REALLOCATE before ALLOCATE");
+
+  Nelem = MAX (1, Nelem);
+  size = Nelem * esize;
+
+  ref = in - NMEMBYTE;
+
+  /* find old entry, update ptr, file, line */
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_FREE) continue;
+    if (memlist[i].ptr == in) {
+
+      if (memlist[i].state == STATE_EXTERNAL) ohana_memabort ("ERROR: realloc of external memory");
+
+      /* ask for new memory */
+      new = realloc (ref, size + 2*NMEMBYTE); /* 2 extra slots to save endposts */
+      if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d)\n", file, line);
+      ptr = new + NMEMBYTE;
+      
+      /* set the marker */
+      marker = (size_t *) new;
+      *marker = 0xdeadbeef;
+      marker = (size_t *)(ptr + size);
+      *marker = 0xdeadbeef;
+
+      /* otherwise, update memory new location */
+      memlist[i].ptr = ptr;
+      memlist[i].size = size;
+      memlist[i].state = STATE_REALLOC;
+
+      /* if new memory in new location, update references */
+      if (ptr != in) {
+	memlist[i].file = file;
+	memlist[i].line = line;
+      }
+
+      return (ptr);
+    }
+  }
+  ohana_memabort ("allocated memory not found for realloc (%s, %d)\n", file, line);
+  return (NULL);
+}
+
+// this is very slow.  should we speed this up by indexing on the ptr?
+void ohana_free (char *file, int line, void *in) {
+
+  int i;
+
+  if (memlist == NULL) ohana_memabort ("FREE before ALLOCATE");
+
+  /* find old entry, set state */
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_FREE) continue;
+    if (memlist[i].ptr == in) {
+      memlist[i].state = STATE_FREE;
+      return;
+    }
+  }
+
+  /* find already freed examples */
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].ptr == in) {
+      fprintf (stderr, "used here: %4d %s %d\n", i, memlist[i].file, memlist[i].line);
+    }
+  }
+
+  ohana_memabort ("allocated memory not found for free (%s, %d : %x)\n", file, line, in);
+  return;
+}
+
+/* register externally allocated memory with ohana memory manager */
+void ohana_memregister_func (char *file, int line, void *ptr) {
+
+  if (memlist == NULL) ohana_meminit ();
+
+  /* add to stack */
+  memlist[Nmemlist].ptr  = ptr;
+  memlist[Nmemlist].file = file;
+  memlist[Nmemlist].line = line;
+  memlist[Nmemlist].state = STATE_EXTERNAL;
+  Nmemlist ++;
+  if (Nmemlist == NMEMLIST) {
+    NMEMLIST += 1000;
+    OHANA_REALLOCATE (memlist, Memlist, NMEMLIST);
+  }
+  return;
+}
+
+void ohana_memcheck_func (int allmemory) {
+
+  int i, j, next, prev, header;
+  size_t *marker;
+  char top, bottom;
+
+  if (Nmemlist == 0) {
+    fprintf (stderr, "no memory allocated\n");
+    return;
+  }
+
+  header = FALSE;
+  fprintf (stderr, "checking %d memory blocks\n", Nmemlist);
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_EXTERNAL) continue;
+    if ((allmemory == 0) && (memlist[i].state == STATE_FREE)) continue;
+
+    top = bottom = 'Y';
+    marker = (size_t *)(memlist[i].ptr - NMEMBYTE);
+    if (*marker == 0xdeadbeef) bottom = 'N';
+    marker = (size_t *)(memlist[i].ptr + memlist[i].size);
+    if (*marker == 0xdeadbeef) top = 'N';
+    
+    if ((top == 'N') && (bottom == 'N')) continue;
+    if (!header) {
+      fprintf (stderr, "         Nmem start end file            line\n");
+      header = TRUE;
+    }
+      fprintf (stderr, "corrupt:  %3d   %c    %c  %-15s %3d\n", i, bottom, top, memlist[i].file, memlist[i].line);
+    prev = next = -1;
+    for (j = 0; j < Nmemlist; j++) {
+      if (memlist[j].ptr < memlist[i].ptr) {
+	if (prev == -1) prev = j;
+	if (memlist[j].ptr > memlist[prev].ptr) prev = j;
+      }
+      if (memlist[j].ptr > memlist[i].ptr) {
+	if (next == -1) next = j;
+	if (memlist[j].ptr < memlist[next].ptr) next = j;
+      }
+    }	  
+    if (prev == -1) {
+      fprintf (stderr, "no previous memory block\n");
+    } else {
+      fprintf (stderr, "prev:     %3d           %-15s %3d\n", prev, memlist[prev].file, memlist[prev].line);
+    }
+    if (next == -1) {
+      fprintf (stderr, "no next memory block\n");
+    } else {
+      fprintf (stderr, "next:     %3d           %-15s %3d\n", next, memlist[next].file, memlist[next].line);
+    }
+    abort ();
+  }
+  return;
+}
+
+void ohana_memdump_func (int allmemory) {
+
+  int i, Ns[3], N;
+  char S[3];
+
+  if (Nmemlist == 0) {
+    fprintf (stderr, "no memory allocated\n");
+    return;
+  }
+
+  S[0] = 'A';
+  S[1] = 'R';
+  S[2] = 'F';
+  S[3] = 'X';
+  Ns[0] = Ns[1] = Ns[2] = Ns[3] = 0;
+  N = 0;
+
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_ALLOC)    N = 0;
+    if (memlist[i].state == STATE_REALLOC)  N = 1;
+    if (memlist[i].state == STATE_FREE)     N = 2;
+    if (memlist[i].state == STATE_EXTERNAL) N = 2;
+    Ns[N] ++;
+    if ((allmemory == 0) && (memlist[i].state == STATE_FREE)) continue;
+    if (memlist[i].state == STATE_EXTERNAL) {
+      fprintf (stderr, "%3d %4d %lx : %lx - extern (extern     extern) %c %s %d\n", 
+	       Ns[N], i, (long)memlist[i].ptr, (long)memlist[i].ptr, 
+	       S[N], memlist[i].file, memlist[i].line);
+    } else {
+      fprintf (stderr, "%3d %4d %lx : %lx - %lx (%lx %lx) %c %s %d\n", 
+	       Ns[N], i, (long)memlist[i].ptr, (long)(memlist[i].ptr - NMEMBYTE), (long)(memlist[i].ptr + memlist[i].size + NMEMBYTE), 
+	       *(long *)(memlist[i].ptr - NMEMBYTE), *(long *)(memlist[i].ptr + memlist[i].size), 
+	       S[N], memlist[i].file, memlist[i].line);
+    }
+  }
+  fprintf (stderr, "Nused: %d (Nalloc: %d, Nrealloc: %d), Nfree: %d\n", 
+	   Ns[0]+Ns[1], Ns[0], Ns[1], Ns[2]);
+  return;
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/string.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/string.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/string.c	(revision 21773)
@@ -0,0 +1,239 @@
+# include <ohana.h>
+
+/* Strip WHITESPACE from the start and end of STRING. */
+int stripwhite (char *string) {
+
+  int i;
+
+  if (string == (char *) NULL) return (FALSE);
+
+  for (i = 0; OHANA_WHITESPACE (string[i]); i++);
+  if (i) memmove (string, string + i, strlen(string+i)+1);
+  for (i = strlen (string) - 1; (i > 0) && OHANA_WHITESPACE (string[i]); i--);
+  string[++i] = 0;
+  return (i);
+
+}
+
+/* compare two strings either as strings, or as numbers if both are
+   pure numeric strings (base 10) */
+int strnumcmp (char *str1, char *str2) {
+
+  char *end1;
+  char *end2;
+  int num1, num2;
+  int value;
+ 
+  value = FALSE;
+  num1 = strtol (str1, &end1, 10);
+  num2 = strtol (str2, &end2, 10);
+
+  if (!end1[0] && !end2[0] && (num1 == num2)) {
+    value = TRUE;
+  }
+  if (!strcmp (str1, str2)) {
+    value = TRUE;
+  }
+  
+  return (value);
+}
+
+/* create a new string from this string */
+char *strcreate (char *string) {
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, MAX (1, strlen(string)) + 1);
+  line = strcpy (line, string);
+
+  return (line);
+}
+
+/* create a new string of length n from this string */
+char *strncreate (char *string, int n) {
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, n + 1);
+  memcpy (line, string, n);
+  line[n] = 0;
+  return (line);
+}
+
+// replace a single entry of 'match' in the string with 'with'
+// (quick-and-dirty regex for a common case...)
+char *strsubs (char *string, char *match, char *with) {
+
+  int N1, N2, N3;
+  char *root;
+  char *out;
+  char *ext;
+
+  if (string == NULL) return NULL;
+  if (match == NULL) return NULL;
+  if (with == NULL) return NULL;
+
+  root = strstr (string, match);
+  if (root == NULL) {
+    return (strcreate (string));
+  }
+  N1 = root - string;
+
+  N2 = strlen (with);
+
+  ext = root + strlen(match);
+  N3 = strlen (ext);
+
+  ALLOCATE (out, char, N1 + N2 + N3 + 1);
+
+  strncpy (out, string, N1);
+  strncpy (&out[N1], with, N2);
+  strncpy (&out[N1+N2], ext, N3);
+  out[N1+N2+N3] = 0;
+
+  return out;
+}
+
+# if 0
+// replace a single entry of 'match' in the string with 'with'
+// (quick-and-dirty regex for a common case...)
+char *strrsubs (char *string, char *match, char *with) {
+
+  char *root;
+  char *out;
+
+  if (string == NULL) return NULL;
+  if (match == NULL) return NULL;
+  if (with == NULL) return NULL;
+
+  root = strstr (string, match);
+  if (root == NULL) return NULL;
+
+  ext = string + strlen (match);
+  ALLOCATE (out, char *, strlen(with) + strlen(ext) + 1);
+  strcpy (out, with);
+  strcat (out, ext);
+
+  return out;
+}
+# endif
+
+int scan_line (FILE *f, char *line) {
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+}
+
+char *_parse_nextword (char *string) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (double *X, int NX, char *line) {
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word) return (FALSE);
+  if (word[0] == '-') return (-1);
+  return (1);
+}
+
+int fparse (float *X, int NX, char *line) {
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word) return (FALSE);
+  if (word[0] == '-') return (-1);
+  return (1);
+}
+
+int get_argument (int argc, char **argv, char *arg) {
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int)NULL);
+}
+
+int remove_argument (int N, int *argc, char **argv) {
+
+  int i;
+
+  if ((N != (int)NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+}
+
+void uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
+
+/* expect a line of the form "$Name: not supported by cvs2svn $", strip out contents */
+char *strip_version (char *input) {
+
+  char *p, *q;
+
+  p = strstr (input, "$Name:");
+  if (p == NULL) return (strcreate ("NONE"));
+
+  q = strcreate (input + 6);
+  p = strrchr (q, '$');
+  if (p != NULL) *p = 0;
+  stripwhite (q);
+  if (*q == 0) {
+    free (q);
+    q = strcreate ("NONE");
+  }
+
+  return (q);
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/time.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/time.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/time.c	(revision 21773)
@@ -0,0 +1,435 @@
+# include "ohana.h"
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+    case 0:
+      fprintf (stderr, "syntax error in RA\n");
+      return (FALSE);
+    case 1:
+      break;
+    case 2:
+      Ra = Ra * 15;
+      break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+    case 0:
+      fprintf (stderr, "syntax error in DEC\n");
+      return (FALSE);
+    case 1:
+    case 2:
+      break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  mode = TIME_DATE;
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = TIME_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = TIME_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = TIME_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = TIME_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = TIME_JD;
+    }
+    if (*p2 == 'J') {
+      mode = TIME_MJD;
+    }
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, time_t *second) {
+  
+  char *tmpline;
+  struct tm *gmt;
+  struct timeval now;
+  double jd;
+  time_t tsec;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strncasecmp (line, "TODAY", 5)) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    if (line[5]) { /* line has extra data (ie, hh:mm:ss) */
+      tsec = now.tv_sec;
+      ALLOCATE (tmpline, char, 64);
+      gmt   = gmtime (&tsec);
+      sprintf (tmpline, "%04d/%02d/%02d,%s", 1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, &line[6]);
+      *second = date_to_sec (tmpline);
+      free (tmpline);
+      return (TRUE);
+    } else {
+      *second = 86400 * ((int)(now.tv_sec / 86400));
+      return (TRUE); 
+    }
+  }
+    
+  switch (chk_time (line)) {
+    case 0:
+      return (FALSE);
+    case TIME_DATE:
+      *second = date_to_sec (line);
+      return (TRUE);
+    case TIME_DAYS:
+      *second = strtod (line, 0) * 86400.0;
+      return (TRUE);
+    case TIME_HOURS:
+      *second = strtod (line, 0) * 3600.0;
+      return (TRUE);
+    case TIME_MINUTES:
+      *second = strtod (line, 0) * 60.0;
+      return (TRUE);
+    case TIME_SECONDS:
+      *second = strtod (line, 0);
+      return (TRUE);
+    case TIME_JD:
+      jd = strtod (line, 0);
+      *second = jd_to_sec (jd);
+      return (TRUE);
+    case TIME_MJD:
+      jd = strtod (line, 0);
+      *second = mjd_to_sec (jd);
+      return (TRUE);
+  }
+  return (FALSE);
+}
+
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+    case 0:
+    case TIME_JD:
+    case TIME_MJD:
+    case TIME_DATE:
+      return (FALSE);
+    case TIME_DAYS:
+      *second = strtod (line, 0) * 86400.0;
+      return (TRUE);
+    case TIME_HOURS:
+      *second = strtod (line, 0) * 3600.0;
+      return (TRUE);
+    case TIME_MINUTES:
+      *second = strtod (line, 0) * 60.0;
+      return (TRUE);
+    case TIME_SECONDS:
+      *second = strtod (line, 0);
+      return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (time_t second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+time_t jd_to_sec (double jd) {
+
+  time_t second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+double sec_to_mjd (time_t second) {
+
+  double mjd;
+  
+  mjd = second/86400.0 + 40587.0;
+  return (mjd);
+}
+
+/**********/
+time_t mjd_to_sec (double mjd) {
+
+  time_t second;
+
+  second = (mjd - 40587.0)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (time_t second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%04d/%02d/%02d,%02d:%02d:%02d", 1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+time_t date_to_sec (char *date) {
+  
+  time_t second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  if (p1 == NULL) return 0;
+
+  /* ignore standard leading quoting options: " ' ( */
+  if (*p1 == 0x22) p1++; /* " */
+  if (*p1 == 0x27) p1++; /* ' */
+  if (*p1 == 0x28) p1++; /* ( */
+
+  px = p1 + strlen(p1);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+/***** short date in format yymmdd *****/
+time_t short_date_to_sec (char *date) {
+  
+  time_t second;
+  double jd;
+  struct tm now;
+  
+  bzero (&now, sizeof(now));
+
+  sscanf (date, "%2d%2d%2d", &now.tm_year, &now.tm_mon, &now.tm_mday);
+
+  if (now.tm_year >   51) now.tm_year +=   0;
+  if (now.tm_year <   50) now.tm_year += 100;
+  now.tm_mon --; /* tm_mon runs from 0 - 11 */
+
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+/**********/
+int hstgsc_hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string) {
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+/* times may be in forms as:
+ * 20040200450s (N seconds since 1970.0)
+ * 2440900.232j (julian date)
+ * 99/02/23,03:22:18 (date string)
+ * (separators may be anything except space, +, -)
+ * 99:02:15:12:23:30
+ * 99:02:15:12h23m30s
+ */
+
+
+/* returns the local MEAN sidereal time (dec hrs) at julian date jd
+   at west longitude long (decimal hours).  Follows
+   definitions in 1992 Astronomical Almanac, pp. B7 and L2.
+   Expression for GMST at 0h ut referenced to Aoki et al, A&A 105,
+   p.359, 1982.  On workstations, accuracy (numerical only!)
+   is about a millisecond in the 1990s.
+   EAM: function from skycalc (thorstensen) 
+*/
+#define  J2000             2451545.        /* Julian date at standard epoch */
+#define  SEC_IN_DAY        86400.
+
+double ohana_lst (double jd, double longitude) {
+
+  double t, ut, jdmid, jdint, jdfrac, sid_g;
+  long sid_int;
+
+  jdint = (int) jd;
+  jdfrac = jd - jdint;
+
+  if (jdfrac < 0.5) {
+    jdmid = jdint - 0.5;
+    ut = jdfrac + 0.5;
+  } else {
+    jdmid = jdint + 0.5;
+    ut = jdfrac - 0.5;
+  }
+
+  t = (jdmid - J2000)/36525;
+  sid_g = (24110.54841+8640184.812866*t+0.093104*t*t-6.2e-6*t*t*t)/SEC_IN_DAY;
+  sid_int = sid_g;
+  sid_g = sid_g - (double) sid_int;
+  sid_g = sid_g + 1.0027379093 * ut - longitude/24.;
+  sid_int = sid_g;
+  sid_g = (sid_g - (double) sid_int) * 24.;
+  if (sid_g < 0.) sid_g = sid_g + 24.;
+  return (sid_g);
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/version.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/version.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/src/version.c	(revision 21773)
@@ -0,0 +1,6 @@
+# include <ohana.h>
+static char *name = "$Name: not supported by cvs2svn $";
+
+char *ohana_version () {
+  return (name);
+}
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/test/.cvsignore
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/test/.cvsignore	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/test/.cvsignore	(revision 21773)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol
Index: /tags/ohana/libohana-1-10-1/Ohana/src/libohana/test/string.c
===================================================================
--- /tags/ohana/libohana-1-10-1/Ohana/src/libohana/test/string.c	(revision 21773)
+++ /tags/ohana/libohana-1-10-1/Ohana/src/libohana/test/string.c	(revision 21773)
@@ -0,0 +1,70 @@
+# include "ohana.h"
+# include "tap_ohana.h"
+
+int main (void) {
+
+  plan_tests (16);
+
+  diag ("libohana string.c tests");
+
+  /*** stripwhite ***/
+  {
+    int status;
+    char string[128];
+
+    status = stripwhite (NULL);
+    
+    ok (!status, "stripwhite status for NULL is FALSE");
+
+    sprintf (string, "  a test line  ");
+    status = stripwhite (string);
+    
+    ok (status, "stripwhite returns %d", status);
+    ok (!strcmp (string, "a test line"), "string is stripped");
+
+    sprintf (string, "a test line");
+    status = stripwhite (string);
+    
+    ok (status, "stripwhite returns %d", status);
+    ok (!strcmp (string, "a test line"), "string is stripped");
+  }
+    
+  /*** strsubs ***/
+  {
+    char *output;
+
+    output = strsubs (NULL, "needle", "noodle");
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", NULL, "noodle");
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", "needle", NULL);
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", "needle", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "noodle in haystack"), "successful sustitution at beginning: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "in", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle noodle haystack"), "successful sustitution in middle: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "stack", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle in haynoodle"), "successful sustitution at end: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "junk", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle in haystack"), "successful sustitution without match: %s", output);
+    skip_end();
+  }
+  return exit_status();
+}
