/*****************************************************************************

   FILE:  load_ctd.c 
   USAGE: load_ctd <control file name>

   This program loads CTD data from WOCE/NODC/WHOI format ASCII files into
   a CODAS database.  The <control file> must contain the following
   information:

      DATABASE NAME - the name to use for the CODAS database to be created
      PRODUCER DEFINITION FILE NAME
      FORMAT - NODC or WHOI or WOCE
      SHIP NAME - maximum of 11 characters or "none" to use default NODC code
      START_PRESSURE - smallest possible pressure value (usually 0 or 1)
      MAX_PRESSURE - largest pressure value to store in database
      PRESSURE_INCREMENT - the pressure interval in decibars
      ASCII FILE NAME(S) - the name of the ASCII files containing the CTD data
             .             (they must use NODC or WHOI format)
             .
             .

   All the data are loaded into one block file unless the
   OPTIMUM_PROFILES_PER_BLOCK figure has been exceeded, in which case a
   new block file is started.

 *****************************************************************************/

#include "geninc.h"
#include "data_id.h"
#include "ioserv.h"    /* error_found() */
#include "use_db.h"    /* db*_cnf() */

#define  NMAX    3000          /* maximum array size -- adjust if needed     */

int  MAX_PRESSURE; /* largest pressure value to use in loading pressure var. */
int  START_PRESSURE;    /* smallest possible pressure value (usually 0 or 1) */
int  PRESSURE_INCREMENT; /* set in control file to pressure interval used    */
int  N_DATA;   /* no. of pressure, temp, oxygen, salinity values to be added */
int  N_PRESSURE;  /* no. of pressure values to store in database */
SHORT pressure[NMAX];
FLOAT data[NMAX];
FILE_NAME_TYPE dbname, prdname, ascname;
char FORMAT[5], SHIP_NAME[12];

typedef struct
{
   CHAR   ship_name[12];
   CHAR   cruise_id[12];
   CHAR   unused[24];
} CONFIGURATION_1_TYPE;

typedef struct
{
   USHORT station;
   USHORT cast_num;
   USHORT end_time;             /* station end-time (hour & minute only) */
   SHORT  inst;
   FLOAT  max_pressure;
   FLOAT  aver;
   FLOAT  rate;
   FLOAT  ocean_depth;
   CHAR   unused[20];  
} ANCILLARY_1_TYPE;

#if PROTOTYPE_ALLOWED
int get_header(FILE *fpasc, CONFIGURATION_1_TYPE *conf,
   ANCILLARY_1_TYPE *anc, YMDHMS_TIME_TYPE *prftime, DMSH_POSITION_TYPE
   position[], char *profile_comment);
int get_temperature(FILE *fpasc, int *nvalues, FLOAT temp[], FLOAT *anc_max_pressure);
int get_salinity(FILE *fpasc, int *nvalues, FLOAT sal[]);
int get_oxygen(FILE *fpasc, int *nvalues, FLOAT oxy[]);
int convert_time(USHORT ztime, YMDHMS_TIME_TYPE *time);
int dbaddf_cnf(int type, FLOAT data[], unsigned int n, char *msg);
#else
int get_header();
int get_temperature();
int get_salinity();
int get_oxygen();
int convert_time();
int dbaddf_cnf();
#endif

#if PROTOTYPE_ALLOWED
void do_it(FILE *fpcnt)
#else
void do_it(fpcnt)
FILE *fpcnt;
#endif
{
   int                  dbid = 1, memory_mode = 0, ierr, iprf, n, i;
   long                 filepos;
   FILE                 *fpasc;
   CONFIGURATION_1_TYPE conf;
   ANCILLARY_1_TYPE     anc;
   DMSH_POSITION_TYPE   position[2];
   YMDHMS_TIME_TYPE     prftime;
   char                 profile_comment[40];

   static PARAMETER_LIST_ENTRY_TYPE ctdcnt[] =
   {
      " DATABASE_NAME:"     , " %79s", dbname             , TYPE_STRING,
      " DEFINITION_FILE:"   , " %79s", prdname            , TYPE_STRING,
      " FORMAT:"            , " %4s" , FORMAT             , TYPE_STRING,
      " SHIP_NAME:"         , " %11s", SHIP_NAME          , TYPE_STRING,
      " START_PRESSURE:"    , " %d"  , &START_PRESSURE    , TYPE_INT,
      " MAX_PRESSURE:"      , " %d"  , &MAX_PRESSURE      , TYPE_INT,
      " PRESSURE_INCREMENT:", " %d"  , &PRESSURE_INCREMENT, TYPE_INT,
      " ASCII_FILE(S):"     , NULL   , NULL               , 0,
      NULL                  , NULL   , NULL               , 0
   };

   if (get_parameters(fpcnt, ctdcnt, NULL)) return;
   dbname[79] = prdname[79] = '\0';
   print_parameters(stdout, ctdcnt, NULL, "\n");

   /* 1999/08/04 Pierre Jaccard
      First GFI pluggin for C78 format 
      Same test, but with the C78 format added
   */
#ifdef USE_GFI_C78_CTD_FORMAT
#define gfiplug_c78_ctd_format_1
#include "../../gfi/src/plugs/load_ctd.c"
#undef  gfiplug_c78_ctd_format_1
#else


   if ( stricmp(FORMAT, "NODC") && stricmp(FORMAT, "WHOI") && stricmp(FORMAT, "WOCE") )
   {
      printf("\n ERROR: Invalid value for FORMAT flag %s\n\n", FORMAT);
      return;
   }
#endif /* gfiplug_c78_ctd_format_1 */

/*
  --> INITIALIZATION OF STRUCTURES FOR UNUSED FIELDS
*/
   set_byte((UBYTE *) &conf, '\0', sizeof(CONFIGURATION_1_TYPE));
   set_byte((UBYTE *) &anc, '\0', sizeof(ANCILLARY_1_TYPE));

   /*---------------------------------------------------------------
       NOTE:  pressures are initialized by equation rather than
              read from the file because there have been instances
              of missing data toward the surface.
     ---------------------------------------------------------------*/
   N_PRESSURE = (MAX_PRESSURE - START_PRESSURE + PRESSURE_INCREMENT) /
      PRESSURE_INCREMENT;
   if (error_found( (N_PRESSURE > NMAX), "array limit exceeded\n\n")) return;
   for (i = 0; i < N_PRESSURE; i++)
      pressure[i] = START_PRESSURE + i * PRESSURE_INCREMENT;

/*
  --> CREATE DATABASE
*/
   DBCREATE(&dbid, dbname, prdname, &memory_mode, &ierr);
   if (error_found(ierr, "DBCREATE\n\n")) return;

   iprf = 0;
   /*---------------------------------------------------
       NOTE THAT THERE IS ONE ASCII FILE FOR EACH CAST   
     ---------------------------------------------------*/
   while (fscanf(fpcnt, " %79s", ascname) == 1)
   {
      ascname[79] = '\0';
      if ((fpasc = fopen(ascname, "r")) == NULL)
      {
         printf("\n ERROR: Cannot open ASCII file %s\n\n", ascname);
         goto close;
      }
      printf("\n    %s ", ascname);

      if (get_header(fpasc, &conf, &anc, &prftime, position, profile_comment) == 0)
      {
         if (iprf == 0)
         {
            /*----------------
                CREATE BLOCK
              ----------------*/
            DBNEWBLK(&ierr);
            if (error_found(ierr, "DBNEWBLK")) goto close;

            if (dbadd_cnf(CONFIGURATION_1, (char *) &conf,
               sizeof(CONFIGURATION_1_TYPE), "adding configuration")) goto close;

            if (dbadd_cnf(P, (char *) pressure, N_PRESSURE * sizeof(SHORT),
               "adding pressure")) goto close;
         }
         /*------------------ CREATE PROFILE ------------------*/
         DBNEWPRF(&prftime, &ierr);
         if (error_found(ierr, "DBNEWPRF")) goto close;
         printf(" ...Profile %3d => ", iprf);
         print_ymdhms_time(stdout, &prftime);

         if (dbadd_cnf(POSITION, (char *) position, sizeof(position),
            "adding position")) goto close;

         /*----------------------------------------------------------------
             NOTE:  The data in the ASCII file are read in a column at a
                    time, rather than a line at a time, to cover the case
                    where the number of observations is so large as to
                    cause a memory shortage.  Hence, to conserve memory,
                    only one data array is used to read all the variables.
           ----------------------------------------------------------------*/
         filepos = ftell(fpasc);
         if (get_temperature(fpasc, &n, data, &(anc.max_pressure))) goto close;
         if (dbaddf_cnf(TEMPERATURE, data, n, "adding temperature")) goto close;

         if (error_found(fseek(fpasc, filepos, 0L), "seek error")) goto close;
         if (get_salinity(fpasc, &n, data)) goto close;
         if (dbaddf_cnf(SALINITY, data, n, "adding salinity")) goto close;

/*
         if (error_found(fseek(fpasc, filepos, 0L), "seek error")) goto close;
         if (get_oxygen(fpasc, &n, data)) goto close;
         if (dbaddf_cnf(OXYGEN, data, n, "adding oxygen")) goto close;
	 */

         if (dbadd_cnf(ANCILLARY_1, (char *) &anc, sizeof(ANCILLARY_1_TYPE),
            "adding ancillary")) goto close;
         if (stricmp(FORMAT, "WOCE") == 0)
	    if (dbadd_cnf(PROFILE_COMMENTS, (char *) profile_comment, sizeof(profile_comment),
	       "adding profile comments")) goto close;

         DBENDPRF(&ierr);
         if (error_found(ierr, "DBENDPRF")) goto close;
         iprf++;
         if (iprf == OPTIMUM_PROFILES_PER_BLOCK)
         {
            DBENDBLK(&ierr);
            if (error_found(ierr, "DBENDBLK")) goto close;
            iprf = 0;
         }
         fclose(fpasc);
      } 
      else             
      {
				 /* 1998/03/30 Pierre Jaccard
						Skipping current file instead of aborting the programme. This is
						because some files have zero length
           
            The original code was:

            printf("\n ERROR: Scanning header information\n\n");
            goto close;

            And is replaced by:
         */
         printf("\n ERROR: Scanning header information.");
				 printf("\n ERROR: Skipping to next file\n\n");
      }
   } /* end while not end-of-control-file loop */

close:
   printf("\n\n");
   DBENDBLK(&ierr);
   error_found(ierr, "DBENDBLK");
   dbclose_cnf();
}

#if PROTOTYPE_ALLOWED
int get_header(FILE *fpasc, CONFIGURATION_1_TYPE *conf, ANCILLARY_1_TYPE *anc,
  YMDHMS_TIME_TYPE *time, DMSH_POSITION_TYPE position[], char profile_comment[])
#else
int get_header(fpasc, conf, anc, time, position, profile_comment)
FILE                 *fpasc;
CONFIGURATION_1_TYPE *conf;
ANCILLARY_1_TYPE     *anc;
YMDHMS_TIME_TYPE     *time;
DMSH_POSITION_TYPE   position[];
char                 profile_comment[];
#endif
{
   char   header_line[85], lon_dir, lat_dir, ccast[6], clatdeg[3],
	  clondeg[4], cdepth[6];
   USHORT stime;
   int    status, lon_degrees, lat_degrees;
   float  lat_minutes, lon_minutes;
   long   hundredths;

/* 1999/08/04 Pierre Jaccard
   Second pluggin for reading CTD data in C78 format
   Additionnal variables
*/

#ifdef USE_GFI_C78_CTD_FORMAT
#define gfiplug_c78_ctd_format_2
#include "../../gfi/src/plugs/load_ctd.c"
#undef  gfiplug_c78_ctd_format_2
#endif

   set_byte((UBYTE *) header_line, '\0', sizeof(header_line));
   set_byte((UBYTE *) profile_comment, '\0', 40);

/* 1999/08/04 Pierre Jaccard
   Third pluggin for reading CTD data in C78 format
   Reading the C78 header
*/

#ifdef USE_GFI_C78_CTD_FORMAT
#define gfiplug_c78_ctd_format_3
#include "../../gfi/src/plugs/load_ctd.c"
#undef  gfiplug_c78_ctd_format_3
#endif

   if (stricmp(FORMAT, "WOCE") == 0)
   {
      if (fgets(header_line, 85, fpasc) == NULL) return(EOF);
      status = sscanf(header_line, 
	 "%5c%5hu%5c%2hd%2hd%2hd  %3c%2c%f%c%3c%f%c%2hd%2hd%5c%30c",
	 conf->cruise_id, &(anc->station), ccast,             
	 &(time->day), &(time->month), &(time->year),
	 anc->unused,    
	 clatdeg, &lat_minutes, &lat_dir,
	 clondeg, &lon_minutes, &lon_dir,
	 &(time->hour), &(time->minute), cdepth,
	 profile_comment);
      if (error_found( (status != 17), "scanning header line"))
	 return(1);
      ccast[5] = clatdeg[2] = clondeg[3] = cdepth[5] = '\0';

      anc->cast_num = (USHORT) atoi(ccast);
      anc->ocean_depth = (FLOAT) atof(cdepth); 
      time->second = 0;
      time->year = yr4digit(time->year);
      anc->end_time = BADUSHORT;
      anc->inst = BADSHORT;
      anc->aver = anc->rate = BADFLOAT;
      hundredths = (atoi(clondeg) * 360000L) + (long) (lon_minutes * 6000L);
      if (lon_dir == 'W') hundredths *= -1.0;
      HUNPOS(&position[0], &hundredths);
      if (error_found(invalid_position(&position[0], 0), "invalid longitude"))
         return(1);
      hundredths = (atoi(clatdeg) * 360000L) + (long) (lat_minutes * 6000L);
      if (lat_dir == 'S') hundredths *= -1.0;
      HUNPOS(&position[1], &hundredths);
      if (error_found(invalid_position(&position[1], 0), "invalid latitude"))
         return(1);
      if (stricmp(SHIP_NAME, "none")) strncpy(conf->ship_name, SHIP_NAME, 11);
      return(0);
   }

   status = fscanf(fpasc,
      " SHIP %11s CRUIS  %11s STAT: %hu C#: %hu DATE %2hu-%2hu-%2hu",
      conf->ship_name, conf->cruise_id, &(anc->station), &(anc->cast_num),
      &(time->year), &(time->month), &(time->day));
   switch(status)
   {
      case 7:   break;
      case EOF: return(EOF);
      default:
         printf("\n ERROR: scanning ship & cruise name, station & cast no., date");
         return(1);
   }
   if (stricmp(SHIP_NAME, "none")) strncpy(conf->ship_name, SHIP_NAME, 11);

   if (stricmp(FORMAT, "NODC") == 0)
   {
      if (error_found( (fscanf(fpasc,
         " STIME: %huZ ETIME: %huZ LAT %d%f LNG %d%f",
         &stime, &(anc->end_time), &lat_degrees, &lat_minutes,
         &lon_degrees, &lon_minutes) != 6),
         "scanning ASCII file for time & position") ) return(1);
   }
   else
   {
      if (error_found((fscanf(fpasc,
         " TIME: %hu Z LAT %d%f LG %d%f",
         &stime, &lat_degrees, &lat_minutes, &lon_degrees, &lon_minutes) != 5),
         "scanning ASCII file for time & position")) return(1);

      /* WHOI format ASCII files do not have end time */
      anc->end_time = BADUSHORT;
   }

   time->year = yr4digit(time->year);
   if (error_found(convert_time(stime, time), "converting time")) return(1);
   if ((lat_degrees < 0) || (lat_minutes < 0.0))
   {
      hundredths = -
         (abs_val(lat_degrees * 360000L) +
         (long) (abs_val(lat_minutes * 6000L)));
   }
   else hundredths = (lat_degrees * 360000L) + (long) (lat_minutes * 6000L);
   HUNPOS(&position[1], &hundredths);
   if (error_found(invalid_position(&position[1], 1), "invalid latitude"))
      return(1);
   hundredths = (lon_degrees *  360000L) + (long) (lon_minutes * 6000L);
   HUNPOS(&position[0], &hundredths);
   if (error_found(invalid_position(&position[0], 0), "invalid longitude"))
      return(1);

   if (error_found((fscanf(fpasc,
      " MAX. PRS= %f DB  DEPTH= %f M AVER %f INST %hd RATE %fHZ",
      &(anc->max_pressure), &(anc->ocean_depth),
      &(anc->aver), &(anc->inst), &(anc->rate)) != 5),
      "scanning max. pressure, depth, aver, inst, & rate")) return(1);
   if (anc->ocean_depth < 0) anc->ocean_depth = BADFLOAT; /* BAD coded as -99 */

   if (stricmp(FORMAT, "NODC") == 0)
   {
      if (error_found( (fscanf(fpasc, " DATA %d", &N_DATA) != 1),
         "scanning no. of data points" )) return(1);
   }

   if (error_found((fgets(header_line, 80, fpasc) == NULL),
      "scanning ASCII file header")) return(1);  /* read till end of line */

   if (stricmp(FORMAT, "WHOI") == 0)
      if (error_found((fgets(header_line, 80, fpasc) == NULL),
         "scanning ASCII file header")) return(1);  /* read OBS/FMT line */

   if (error_found((fgets(header_line, 80, fpasc) == NULL),
      "scanning column titles line")) return(1);
   return(0);
}

#if PROTOTYPE_ALLOWED
int get_temperature(FILE *fpasc, int *nvalues, FLOAT temp[], FLOAT *anc_max_pressure)
#else
int get_temperature(fpasc, nvalues, temp, anc_max_pressure)
FILE *fpasc;
int *nvalues;
FLOAT temp[], *anc_max_pressure;
#endif
{
   int i, j = -1;
   FLOAT t, p = 0.0;
   char line[80];

   /*----------------------------------------------------------
       INITIALIZE ARRAY TO BADFLOAT IN CASE OF MISSING DATA,
       PARTICULARLY FOR INITIAL PRESSURE INTERVALS
     ----------------------------------------------------------*/
   for (i = 0; i < N_PRESSURE; i++) temp[i] = BADFLOAT;

/* 1999/08/04 Pierre Jaccard
   Third pluggin for reading CTD data in C78 format
   Reading the C78 temperature
*/

#ifdef USE_GFI_C78_CTD_FORMAT
#define gfiplug_c78_ctd_format_4
#include "../../gfi/src/plugs/load_ctd.c"
#undef gfiplug_c78_ctd_format_4
#endif

   if (stricmp(FORMAT, "WOCE") == 0)
   {
      while (fgets(line, 80, fpasc) != NULL)
      {
         if (sscanf(line, " %f %f %*f %*f", &p, &t) < 2)
         {
            printf("\n ERROR: Scanning temperature for n = %d", *nvalues+1);
            return(1);
         }
	 if (p <= MAX_PRESSURE) /* store only up to MAX_PRESSURE */
	 {
            if (t >= 0) 
	    {
               j = ((int) p - START_PRESSURE) / PRESSURE_INCREMENT; 
		  /* may be missing data at initial pressures */
	       temp[j] = t;  /* BADs coded as negative values */
            }
         }
      }
      *nvalues = j + 1;
      *anc_max_pressure = p;  /* from last data line in file */
      return(0);
   }

   if (stricmp(FORMAT, "WHOI") == 0)
   {
      /*-----------------------------------------------
          SCAN AVAILABLE PROFILE DATA FROM ASCII FILE
        -----------------------------------------------*/
      while (fgets(line, 80, fpasc) != NULL)
      {
         if (sscanf(line, " %f %f %*f %*f", &p, &t) < 2)
         {
            printf("\n ERROR: Scanning temperature for n = %d", *nvalues+1);
            return(1);
         }
	 if (p > MAX_PRESSURE) break;
	 if (t >= 0) /* BADs coded as negative values */
	 {
            j = ((int) p - START_PRESSURE) / PRESSURE_INCREMENT; /* may be missing data at initial pressures */
            temp[j] = t;  
         }
      }  /* end while not eof loop */
      *nvalues = j + 1;
   }
   else /* NODC */
   {
      for (i = 0, p = START_PRESSURE; i < N_DATA && p < MAX_PRESSURE; i++)
      {
         if (fscanf(fpasc, " %f %f %*f %*f", &p, &t) < 2)
         {
            printf("\n ERROR: Scanning temperature for n = %d", i+1);
            return(1);
         }
         j = ((int) p - START_PRESSURE) / PRESSURE_INCREMENT; /* may be missing data at initial pressures */
         if (t >= 0) /* BADs coded as negative values */
	    temp[j] = t;
      }
      *nvalues = j + 1;
   }
   return(0);
}

#if PROTOTYPE_ALLOWED
int get_salinity(FILE *fpasc, int *nvalues, FLOAT sal[])
#else
int get_salinity(fpasc, nvalues, sal)
FILE *fpasc;
int *nvalues;
FLOAT sal[];
#endif
{
   int i, j = -1;
   FLOAT s, p = 0.0;
   char line[80], scan_format[20];

   /*----------------------------------------------------------
       INITIALIZE ARRAYS TO BADFLOAT IN CASE OF MISSING DATA,
       PARTICULARLY FOR INITIAL PRESSURE INTERVALS
     ----------------------------------------------------------*/
   for (i = 0; i < N_PRESSURE; i++) sal[i] = BADFLOAT;

   if (stricmp(FORMAT, "NODC") == 0)
   {
      for (i = 0, p = START_PRESSURE; i < N_DATA && p < MAX_PRESSURE; i++)
      {
         if (fscanf(fpasc, " %f %*f %f %*f", &p, &s) < 2)
         {
            printf("\n ERROR: Scanning salinity data for n = %d", i+1);
            return(1);
         }
         j = ((int) p - START_PRESSURE) / PRESSURE_INCREMENT; /* may have missing data at initial pressures */
         if (s >= 0) sal[j] = s;
      }
      *nvalues = j + 1;
      return(0);
   }

   if (stricmp(FORMAT, "WHOI") == 0) 
      strcpy(scan_format, " %f %*f %f %*f");

/* 1999/08/04 Pierre Jaccard
   Fifth pluggin for reading CTD data in C78 format
   Reading the C78 salinity
*/
#ifdef USE_GFI_C78_CTD_FORMAT
#define gfiplug_c78_ctd_format_5
#include "../../gfi/src/plugs/load_ctd.c"
#undef gfiplug_c78_ctd_format_5
#endif

   else
      strcpy(scan_format, " %f %*f %*f %f"); 
   while (fgets(line, 80, fpasc) != NULL)
   {
      if (sscanf(line, scan_format, &p, &s) < 2)
      {
         printf("\n ERROR: Scanning salinity for n = %d", *nvalues+1);
         return(1);
      }
      if (p > MAX_PRESSURE) break;
      if (s >= 0) 
      {
         j = ((int) p - START_PRESSURE) / PRESSURE_INCREMENT; /* may be missing data at initial pressures */
	 sal[j] = s;  /* BADs coded as negative values */
      }
   }
   *nvalues = j + 1;
   return(0);
}

#if PROTOTYPE_ALLOWED
int get_oxygen(FILE *fpasc, int *nvalues, FLOAT oxy[])
#else
int get_oxygen(fpasc, nvalues, oxy)
FILE *fpasc;
int *nvalues;
FLOAT oxy[];
#endif
{
   int i, j = -1;
   FLOAT o, p = 0.0;
   char line[80], scan_format[30];

   /*----------------------------------------------------------
       INITIALIZE ARRAYS TO BADFLOAT IN CASE OF MISSING DATA,
       PARTICULARLY FOR INITIAL PRESSURE INTERVALS
     ----------------------------------------------------------*/
   for (i = 0; i < N_PRESSURE; i++) oxy[i] = BADFLOAT;

   if (stricmp(FORMAT, "NODC") == 0)
   {
      /*-----------------------------------------------
          SCAN AVAILABLE PROFILE DATA FROM ASCII FILE
        -----------------------------------------------*/
      for (i = 0, p = START_PRESSURE; i < N_DATA && p < MAX_PRESSURE; i++)
      {
         if (fscanf(fpasc, " %f %*f %*f %f", &p, &o) < 2)
         {
            printf("\n ERROR: Scanning oxygen data for n = %d", i+1);
            return(1);
         }
         j = ((int) p - START_PRESSURE) / PRESSURE_INCREMENT; /* may have missing data at initial pressures */
         if (o >= 0) oxy[j] = o;
      }
      *nvalues = j + 1;
      return(0);
   }

   if (stricmp(FORMAT, "WHOI") == 0) 
      strcpy(scan_format, " %f %*f %*f %f");
   else
      strcpy(scan_format, " %f %*f %*f %*f %*f %f"); 
   while (fgets(line, 80, fpasc) != NULL)
   {
      if (sscanf(line, scan_format, &p, &o) < 2)
      {
         printf("\n ERROR: Scanning oxygen for n = %d", *nvalues+1);
         return(1);
      }
      if (p > MAX_PRESSURE) break;                                  
      if (o >= 0) 
      {
         j = ((int) p - START_PRESSURE) / PRESSURE_INCREMENT; /* may be missing data at initial pressures */
	 oxy[j] = o;  /* BADs coded as negative values */
      } 
   }  
   *nvalues = j + 1;
   return(0);
}

#if PROTOTYPE_ALLOWED
int convert_time(USHORT ztime, YMDHMS_TIME_TYPE *time)
#else
int convert_time(ztime, time)
USHORT ztime;
YMDHMS_TIME_TYPE *time;
#endif
{
   time->hour = ztime / 100;
   time->minute = ztime % 100;
   time->second = 0;
   if (error_found(invalid_time(time), "invalid time "))
   {
      print_ymdhms_time(stdout, time);
      return(1);
   }
   return(0);
}

#if PROTOTYPE_ALLOWED 
int dbaddf_cnf(int type, FLOAT data[], unsigned int n, char *msg)
#else
int dbaddf_cnf(type, data, n, msg)
int type;
FLOAT data[];
unsigned int n;
char *msg;
#endif
{
   int ierr;
   unsigned int nbad = 0;
   char badmsg[40];

   DBADD_F(&type, data, &n, &nbad, &ierr);
   if (error_found(ierr, msg)) return(ierr);
   strcpy(badmsg, "bad values ");
   strcat(badmsg, msg);
   error_found(nbad, badmsg);
   return(nbad);
}

