/*

    PROGRAM:  conv_ctd
    USAGE:    conv_ctd [dbname]

          This program opens an existing CTD CODAS3 database and
          converts the ancillary_1 data and structure definition to
          the "sparcified" version.
*/

#include "dbinc.h"      /* *db declaration */
#include "use_db.h"     /* db*_cnf() */
#include "ioserv.h"     /* error_found() */
#include "data_id.h"    /* CTD variable ids */

#if PROTOTYPE_ALLOWED
int check_anc1(void);
int convert_ancillary1(void);
#else
int check_anc1();
int convert_ancillary1();
#endif

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;

static struct
{
   STRUCT_DEF_HDR_TYPE  hdr;
   STRUCT_DEF_ELEM_TYPE e[10];
} newanc1_def[] =
{
   "ANCILLARY_1"           , 9      , "" ,
   "station"               , "none" , USHORT_VALUE_CODE,  1 , "" ,
   "cast_num"              , "none" , USHORT_VALUE_CODE,  1 , "" ,
   "end_time"              , "none" , USHORT_VALUE_CODE,  1 , "" ,
   "inst"                  , "none" , SHORT_VALUE_CODE ,  1 , "" ,
   "max_pressure"          , "db"   , FLOAT_VALUE_CODE ,  1 , "" ,
   "aver"                  , "s"    , FLOAT_VALUE_CODE ,  1 , "" ,
   "rate"                  , "Hz"   , FLOAT_VALUE_CODE ,  1 , "" ,
   "ocean_depth"           , "m"    , FLOAT_VALUE_CODE ,  1 , "" ,
   "unused"                , "none" , CHAR_VALUE_CODE  , 20 , ""
};

static struct
{
   STRUCT_DEF_HDR_TYPE  hdr;
   STRUCT_DEF_ELEM_TYPE e[10];
} oldanc1_def[] =
{
   "ANCILLARY_1"           , 9      , "" ,
   "station"               , "none" , USHORT_VALUE_CODE,  1 , "" ,
   "cruise_no"             , "none" , USHORT_VALUE_CODE,  1 , "" ,
   "end_time"              , "none" , USHORT_VALUE_CODE,  1 , "" ,
   "max_pressure"          , "db"   , FLOAT_VALUE_CODE ,  1 , "" ,
   "aver"                  , "s"    , FLOAT_VALUE_CODE ,  1 , "" ,
   "inst"                  , "none" , SHORT_VALUE_CODE ,  1 , "" ,
   "rate"                  , "Hz"   , FLOAT_VALUE_CODE ,  1 , "" ,
   "ocean_depth"           , "m"    , FLOAT_VALUE_CODE ,  1 , "" ,
   "unused"                , "none" , CHAR_VALUE_CODE  , 22 , ""
};

#if PROTOTYPE_ALLOWED
void main(int argc, char *argv[])
#else
void main(argc, argv)
int argc;
char *argv[];
#endif
{
   FILE_NAME_TYPE dbname;
   char answer[2];
   int  iblkprf[2], blksave = -99;
   int  conv_anc1;
   unsigned int n;

   if (argc < 2)
   {
      printf("\n Enter database name ==> ");
      scanf(" %79s", dbname);
   }
   else
      strncpy(dbname, argv[1], 79);

   if (dbopen_cnf(1, dbname, READ_WRITE, DIR_IN_MEMORY)) exit(-1);

   /*------------------------
       MAIN PROCESSING LOOP
     ------------------------*/
   do
   {
      n = 2 * sizeof(int);
      if (dbget_cnf(BLOCK_PROFILE_INDEX, (char *) iblkprf, &n,
         "getting block-profile index")) goto close;
      if (iblkprf[0] != blksave)  /* new block */
      {
         blksave = iblkprf[0];
         /*--------------------------------------------------
             CHECK ASSUMPTIONS PRIOR TO UPDATING BLOCK FILE
           --------------------------------------------------*/
         printf("\n Checking block %3d: ", iblkprf[0]);
         if (!db->block_strdef_loaded)
            load_block_strdef();

         /* see what needs converting by checking the structure definitions */
         conv_anc1 = check_anc1();
         if (conv_anc1 == 0)
         {
            printf("up-to-date");
            if (error_found( (-1 == (iblkprf[1] = get_nprofs() - 1)),
               "getting no. of profiles" )) goto close;
            if (dbsrch_cnf(BLOCK_PROFILE_SEARCH, (char *) iblkprf)) goto close;
            continue; /* dbmove to next block */
         }
         if (iblkprf[0] == 0 && conv_anc1 == -1)
         {
            printf("\n\n Continue? (y/n) ==> ");
            scanf(" %1s", answer);
            if (toupper(answer[0]) == 'N') goto close;
         }
         printf("converting ");

         /* store new structure definition if needed */
         if (conv_anc1 == 1)
         {
            printf("ancillary_1...");
            n = sizeof(newanc1_def);
            if (dbput_cnf(STRUCTURE_DEF, (char *) newanc1_def, &n,
               "storing ANCILLARY_1 definition")) goto close;
         }
      }
      if (conv_anc1 == 1)
         if (convert_ancillary1()) goto close;

   } while (dbmove_cnf(1) != SEARCH_BEYOND_END);
   printf("\n Database update completed.");

close:
   printf("\n Last block-profile number = %d-%d\n", iblkprf[0], iblkprf[1]);
   dbclose_cnf();
   puts("");
}

/*-----------------------------------------------------------------------------

   FUNCTIONS:  check_anc1

      This checks if the ANCILLARY_1 structure should be converted, by
      looking for particular entries in the structure definitions stored
      in the block file.

   RETURN:

      0 = already up-to-date
     -1 = inapplicable (not present or mismatch)
      1 = proceed with conversion
*/

#if PROTOTYPE_ALLOWED
int check_anc1(void)
#else
int check_anc1()
#endif
{
   STRUCT_DEF_HDR_TYPE *anc1_def;
   unsigned int n = 0;

   if ( (anc1_def = find_def("ANCILLARY_1", db->block_strdef)) == NULL )
   {
      printf("\n WARNING: ANCILLARY_1 definition not in block file");
      printf("\n NO ancillary_1 conversion performed on this block\n");
      return(-1);
   }
   if ( cmp_byte(
      (char *) anc1_def, (char *) oldanc1_def, sizeof(oldanc1_def)) == 0 )
      return(1);
   if ( cmp_byte(
      (char *) anc1_def, (char *) newanc1_def, sizeof(newanc1_def)) == 0 )
      return(0);
   printf("\n WARNING: Unrecognized ANCILLARY_1 definition");
   printf("\n NO ancillary_1 conversion performed on this block\n");
   return(-1);
}

/*-----------------------------------------------------------------------------

   FUNCTION:  convert_ancillary1

      This gets the old data from the database, perform the required byte-
      swapping, and store the converted data back into the database.

   RETURN:

      0 = okay;
     -1 = database error

*/

#if PROTOTYPE_ALLOWED
int convert_ancillary1(void)
#else
int convert_ancillary1()
#endif
{
   unsigned int n = sizeof(ANCILLARY_1_TYPE);
   char old_anc1[2 + sizeof(ANCILLARY_1_TYPE)];
   ANCILLARY_1_TYPE new_anc1;
   int ierr = 0;

   if ( (ierr = dbget_cnf(ANCILLARY_1, old_anc1, &n, "getting ancillary_1")) != 0
      && ierr != INVALID_TYPE_REQUEST) return(-1);
   if (ierr == INVALID_TYPE_REQUEST || n == 0) return(0);  /* data not present */
   if (error_found( (n != sizeof(ANCILLARY_1_TYPE)),
      "size mismatch for ANCILLARY_1")) return(-1);
   move_byte(old_anc1   , (char *) &(new_anc1.station), 3*sizeof(USHORT));
   move_byte(old_anc1+14, (char *) &(new_anc1.inst   ), 1*sizeof(SHORT));
   move_byte(old_anc1+06, (char *) &(new_anc1.max_pressure), 2*sizeof(FLOAT));
   move_byte(old_anc1+16, (char *) &(new_anc1.rate), 2*sizeof(FLOAT));
   move_byte(old_anc1+24, (char *) &(new_anc1.unused[0]), 20*sizeof(CHAR));
   if (dbput_cnf(ANCILLARY_1, (char *) &new_anc1, &n,
      "storing ancillary_1 data")) return(-1);
   return(0);
}

