/* *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */
/* ** Copyright UCAR                                                         */
/* ** University Corporation for Atmospheric Research (UCAR)                 */
/* ** National Center for Atmospheric Research (NCAR)                        */
/* ** Boulder, Colorado, USA                                                 */
/* ** BSD licence applies - redistribution and use in source and binary      */
/* ** forms, with or without modification, are permitted provided that       */
/* ** the following conditions are met:                                      */
/* ** 1) If the software is modified to produce derivative works,            */
/* ** such modified software should be clearly marked, so as not             */
/* ** to confuse it with the version available from UCAR.                    */
/* ** 2) Redistributions of source code must retain the above copyright      */
/* ** notice, this list of conditions and the following disclaimer.          */
/* ** 3) Redistributions in binary form must reproduce the above copyright   */
/* ** notice, this list of conditions and the following disclaimer in the    */
/* ** documentation and/or other materials provided with the distribution.   */
/* ** 4) Neither the name of UCAR nor the names of its contributors,         */
/* ** if any, may be used to endorse or promote products derived from        */
/* ** this software without specific prior written permission.               */
/* ** DISCLAIMER: THIS SOFTWARE IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESS  */
/* ** OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
/* ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.    */
/* *=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* */
////////////////////////////////////////////
// Params.cc
//
// TDRP C++ code file for class 'Params'.
//
// Code for program Grib2toMdv
//
// This file has been automatically
// generated by TDRP, do not modify.
//
/////////////////////////////////////////////

/**
 *
 * @file Params.cc
 *
 * @class Params
 *
 * This class is automatically generated by the Table
 * Driven Runtime Parameters (TDRP) system
 *
 * @note Source is automatically generated from
 *       paramdef file at compile time, do not modify
 *       since modifications will be overwritten.
 *
 *
 * @author Automatically generated
 *
 */
#include "Params.hh"
#include <cstring>

  ////////////////////////////////////////////
  // Default constructor
  //

  Params::Params()

  {

    // zero out table

    memset(_table, 0, sizeof(_table));

    // zero out members

    memset(&_start_, 0, &_end_ - &_start_);

    // class name

    _className = "Params";

    // initialize table

    _init();

    // set members

    tdrpTable2User(_table, &_start_);

    _exitDeferred = false;

  }

  ////////////////////////////////////////////
  // Copy constructor
  //

  Params::Params(const Params& source)

  {

    // sync the source object

    source.sync();

    // zero out table

    memset(_table, 0, sizeof(_table));

    // zero out members

    memset(&_start_, 0, &_end_ - &_start_);

    // class name

    _className = "Params";

    // copy table

    tdrpCopyTable((TDRPtable *) source._table, _table);

    // set members

    tdrpTable2User(_table, &_start_);

    _exitDeferred = false;

  }

  ////////////////////////////////////////////
  // Destructor
  //

  Params::~Params()

  {

    // free up

    freeAll();

  }

  ////////////////////////////////////////////
  // Assignment
  //

  void Params::operator=(const Params& other)

  {

    // sync the other object

    other.sync();

    // free up any existing memory

    freeAll();

    // zero out table

    memset(_table, 0, sizeof(_table));

    // zero out members

    memset(&_start_, 0, &_end_ - &_start_);

    // copy table

    tdrpCopyTable((TDRPtable *) other._table, _table);

    // set members

    tdrpTable2User(_table, &_start_);

    _exitDeferred = other._exitDeferred;

  }

  ////////////////////////////////////////////
  // loadFromArgs()
  //
  // Loads up TDRP using the command line args.
  //
  // Check usage() for command line actions associated with
  // this function.
  //
  //   argc, argv: command line args
  //
  //   char **override_list: A null-terminated list of overrides
  //     to the parameter file.
  //     An override string has exactly the format of an entry
  //     in the parameter file itself.
  //
  //   char **params_path_p:
  //     If this is non-NULL, it is set to point to the path
  //     of the params file used.
  //
  //   bool defer_exit: normally, if the command args contain a 
  //      print or check request, this function will call exit().
  //      If defer_exit is set, such an exit is deferred and the
  //      private member _exitDeferred is set.
  //      Use exidDeferred() to test this flag.
  //
  //  Returns 0 on success, -1 on failure.
  //

  int Params::loadFromArgs(int argc, char **argv,
                           char **override_list,
                           char **params_path_p,
                           bool defer_exit)
  {
    int exit_deferred;
    if (_tdrpLoadFromArgs(argc, argv,
                          _table, &_start_,
                          override_list, params_path_p,
                          _className,
                          defer_exit, &exit_deferred)) {
      return (-1);
    } else {
      if (exit_deferred) {
        _exitDeferred = true;
      }
      return (0);
    }
  }

  ////////////////////////////////////////////
  // loadApplyArgs()
  //
  // Loads up TDRP using the params path passed in, and applies
  // the command line args for printing and checking.
  //
  // Check usage() for command line actions associated with
  // this function.
  //
  //   const char *param_file_path: the parameter file to be read in
  //
  //   argc, argv: command line args
  //
  //   char **override_list: A null-terminated list of overrides
  //     to the parameter file.
  //     An override string has exactly the format of an entry
  //     in the parameter file itself.
  //
  //   bool defer_exit: normally, if the command args contain a 
  //      print or check request, this function will call exit().
  //      If defer_exit is set, such an exit is deferred and the
  //      private member _exitDeferred is set.
  //      Use exidDeferred() to test this flag.
  //
  //  Returns 0 on success, -1 on failure.
  //

  int Params::loadApplyArgs(const char *params_path,
                            int argc, char **argv,
                            char **override_list,
                            bool defer_exit)
  {
    int exit_deferred;
    if (tdrpLoadApplyArgs(params_path, argc, argv,
                          _table, &_start_,
                          override_list,
                          _className,
                          defer_exit, &exit_deferred)) {
      return (-1);
    } else {
      if (exit_deferred) {
        _exitDeferred = true;
      }
      return (0);
    }
  }

  ////////////////////////////////////////////
  // isArgValid()
  // 
  // Check if a command line arg is a valid TDRP arg.
  //

  bool Params::isArgValid(const char *arg)
  {
    return (tdrpIsArgValid(arg));
  }

  ////////////////////////////////////////////
  // isArgValid()
  // 
  // Check if a command line arg is a valid TDRP arg.
  // return number of args consumed.
  //

  int Params::isArgValidN(const char *arg)
  {
    return (tdrpIsArgValidN(arg));
  }

  ////////////////////////////////////////////
  // load()
  //
  // Loads up TDRP for a given class.
  //
  // This version of load gives the programmer the option to load
  // up more than one class for a single application. It is a
  // lower-level routine than loadFromArgs, and hence more
  // flexible, but the programmer must do more work.
  //
  //   const char *param_file_path: the parameter file to be read in.
  //
  //   char **override_list: A null-terminated list of overrides
  //     to the parameter file.
  //     An override string has exactly the format of an entry
  //     in the parameter file itself.
  //
  //   expand_env: flag to control environment variable
  //               expansion during tokenization.
  //               If TRUE, environment expansion is set on.
  //               If FALSE, environment expansion is set off.
  //
  //  Returns 0 on success, -1 on failure.
  //

  int Params::load(const char *param_file_path,
                   char **override_list,
                   int expand_env, int debug)
  {
    if (tdrpLoad(param_file_path,
                 _table, &_start_,
                 override_list,
                 expand_env, debug)) {
      return (-1);
    } else {
      return (0);
    }
  }

  ////////////////////////////////////////////
  // loadFromBuf()
  //
  // Loads up TDRP for a given class.
  //
  // This version of load gives the programmer the option to
  // load up more than one module for a single application,
  // using buffers which have been read from a specified source.
  //
  //   const char *param_source_str: a string which describes the
  //     source of the parameter information. It is used for
  //     error reporting only.
  //
  //   char **override_list: A null-terminated list of overrides
  //     to the parameter file.
  //     An override string has exactly the format of an entry
  //     in the parameter file itself.
  //
  //   const char *inbuf: the input buffer
  //
  //   int inlen: length of the input buffer
  //
  //   int start_line_num: the line number in the source which
  //     corresponds to the start of the buffer.
  //
  //   expand_env: flag to control environment variable
  //               expansion during tokenization.
  //               If TRUE, environment expansion is set on.
  //               If FALSE, environment expansion is set off.
  //
  //  Returns 0 on success, -1 on failure.
  //

  int Params::loadFromBuf(const char *param_source_str,
                          char **override_list,
                          const char *inbuf, int inlen,
                          int start_line_num,
                          int expand_env, int debug)
  {
    if (tdrpLoadFromBuf(param_source_str,
                        _table, &_start_,
                        override_list,
                        inbuf, inlen, start_line_num,
                        expand_env, debug)) {
      return (-1);
    } else {
      return (0);
    }
  }

  ////////////////////////////////////////////
  // loadDefaults()
  //
  // Loads up default params for a given class.
  //
  // See load() for more detailed info.
  //
  //  Returns 0 on success, -1 on failure.
  //

  int Params::loadDefaults(int expand_env)
  {
    if (tdrpLoad(NULL,
                 _table, &_start_,
                 NULL, expand_env, FALSE)) {
      return (-1);
    } else {
      return (0);
    }
  }

  ////////////////////////////////////////////
  // sync()
  //
  // Syncs the user struct data back into the parameter table,
  // in preparation for printing.
  //
  // This function alters the table in a consistent manner.
  // Therefore it can be regarded as const.
  //

  void Params::sync(void) const
  {
    tdrpUser2Table(_table, (char *) &_start_);
  }

  ////////////////////////////////////////////
  // print()
  // 
  // Print params file
  //
  // The modes supported are:
  //
  //   PRINT_SHORT:   main comments only, no help or descriptions
  //                  structs and arrays on a single line
  //   PRINT_NORM:    short + descriptions and help
  //   PRINT_LONG:    norm  + arrays and structs expanded
  //   PRINT_VERBOSE: long  + private params included
  //

  void Params::print(FILE *out, tdrp_print_mode_t mode)
  {
    tdrpPrint(out, _table, _className, mode);
  }

  ////////////////////////////////////////////
  // checkAllSet()
  //
  // Return TRUE if all set, FALSE if not.
  //
  // If out is non-NULL, prints out warning messages for those
  // parameters which are not set.
  //

  int Params::checkAllSet(FILE *out)
  {
    return (tdrpCheckAllSet(out, _table, &_start_));
  }

  //////////////////////////////////////////////////////////////
  // checkIsSet()
  //
  // Return TRUE if parameter is set, FALSE if not.
  //
  //

  int Params::checkIsSet(const char *paramName)
  {
    return (tdrpCheckIsSet(paramName, _table, &_start_));
  }

  ////////////////////////////////////////////
  // freeAll()
  //
  // Frees up all TDRP dynamic memory.
  //

  void Params::freeAll(void)
  {
    tdrpFreeAll(_table, &_start_);
  }

  ////////////////////////////////////////////
  // usage()
  //
  // Prints out usage message for TDRP args as passed
  // in to loadFromArgs().
  //

  void Params::usage(ostream &out)
  {
    out << "TDRP args: [options as below]\n"
        << "   [ -params/--params path ] specify params file path\n"
        << "   [ -check_params/--check_params] check which params are not set\n"
        << "   [ -print_params/--print_params [mode]] print parameters\n"
        << "     using following modes, default mode is 'norm'\n"
        << "       short:   main comments only, no help or descr\n"
        << "                structs and arrays on a single line\n"
        << "       norm:    short + descriptions and help\n"
        << "       long:    norm  + arrays and structs expanded\n"
        << "       verbose: long  + private params included\n"
        << "       short_expand:   short with env vars expanded\n"
        << "       norm_expand:    norm with env vars expanded\n"
        << "       long_expand:    long with env vars expanded\n"
        << "       verbose_expand: verbose with env vars expanded\n"
        << "   [ -tdrp_debug] debugging prints for tdrp\n"
        << "   [ -tdrp_usage] print this usage\n";
  }

  ////////////////////////////////////////////
  // arrayRealloc()
  //
  // Realloc 1D array.
  //
  // If size is increased, the values from the last array 
  // entry is copied into the new space.
  //
  // Returns 0 on success, -1 on error.
  //

  int Params::arrayRealloc(const char *param_name, int new_array_n)
  {
    if (tdrpArrayRealloc(_table, &_start_,
                         param_name, new_array_n)) {
      return (-1);
    } else {
      return (0);
    }
  }

  ////////////////////////////////////////////
  // array2DRealloc()
  //
  // Realloc 2D array.
  //
  // If size is increased, the values from the last array 
  // entry is copied into the new space.
  //
  // Returns 0 on success, -1 on error.
  //

  int Params::array2DRealloc(const char *param_name,
                             int new_array_n1,
                             int new_array_n2)
  {
    if (tdrpArray2DRealloc(_table, &_start_, param_name,
                           new_array_n1, new_array_n2)) {
      return (-1);
    } else {
      return (0);
    }
  }

  ////////////////////////////////////////////
  // _init()
  //
  // Class table initialization function.
  //
  //

  void Params::_init()

  {

    TDRPtable *tt = _table;

    // Parameter 'Comment 0'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = COMMENT_TYPE;
    tt->param_name = tdrpStrDup("Comment 0");
    tt->comment_hdr = tdrpStrDup("Grib2toMdv PARAMETER FILE");
    tt->comment_text = tdrpStrDup("Grib2toMdv creates MDV from grib2 data files\n");
    tt++;
    
    // Parameter 'Comment 1'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = COMMENT_TYPE;
    tt->param_name = tdrpStrDup("Comment 1");
    tt->comment_hdr = tdrpStrDup("PROGRAM MODES OF OPERATION.");
    tt->comment_text = tdrpStrDup("");
    tt++;
    
    // Parameter 'debug'
    // ctype is 'int'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = INT_TYPE;
    tt->param_name = tdrpStrDup("debug");
    tt->descr = tdrpStrDup("Debug option");
    tt->help = tdrpStrDup("0 = No Debug info\n1 = Regular Debug info\n2 = Full Grib2 file output (see printSec params).");
    tt->val_offset = (char *) &debug - &_start_;
    tt->single_val.i = 0;
    tt++;
    
    // Parameter 'instance'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("instance");
    tt->descr = tdrpStrDup("Instance");
    tt->help = tdrpStrDup("Process instance for registration with process mapper");
    tt->val_offset = (char *) &instance - &_start_;
    tt->single_val.s = tdrpStrDup("Test");
    tt++;
    
    // Parameter 'procmap_register_interval_secs'
    // ctype is 'int'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = INT_TYPE;
    tt->param_name = tdrpStrDup("procmap_register_interval_secs");
    tt->descr = tdrpStrDup("Interval for procmap registration");
    tt->help = tdrpStrDup("Set to a high value if processing takes a long time. This will prevent the auto_restarter from killing and restarting the app.");
    tt->val_offset = (char *) &procmap_register_interval_secs - &_start_;
    tt->single_val.i = 1200;
    tt++;
    
    // Parameter 'input_dir'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("input_dir");
    tt->descr = tdrpStrDup("Input directory");
    tt->help = tdrpStrDup("Directory which contains input grib2 files. Used only if files are not specified on the command line");
    tt->val_offset = (char *) &input_dir - &_start_;
    tt->single_val.s = tdrpStrDup("./");
    tt++;
    
    // Parameter 'input_suffix'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("input_suffix");
    tt->descr = tdrpStrDup("Input file suffix");
    tt->help = tdrpStrDup("Input file suffixes will be checked against this string. Used only if files are not specified on the command line");
    tt->val_offset = (char *) &input_suffix - &_start_;
    tt->single_val.s = tdrpStrDup("");
    tt++;
    
    // Parameter 'input_substring'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("input_substring");
    tt->descr = tdrpStrDup("Input file substring check.");
    tt->help = tdrpStrDup("Input files will be checked against this string.Can be used to filter different forecast times.Used only if files are not specified on the command line");
    tt->val_offset = (char *) &input_substring - &_start_;
    tt->single_val.s = tdrpStrDup("");
    tt++;
    
    // Parameter 'input_substrings'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("input_substrings");
    tt->descr = tdrpStrDup("Input file substrings check.");
    tt->help = tdrpStrDup("Input files will be checked against these strings. Can be used to filter different forecast times. Used only if files are not specified on the command line and input_substring is set to an empty string.");
    tt->array_offset = (char *) &_input_substrings - &_start_;
    tt->array_n_offset = (char *) &input_substrings_n - &_start_;
    tt->is_array = TRUE;
    tt->array_len_fixed = FALSE;
    tt->array_elem_size = sizeof(char*);
    tt->array_n = 0;
    tt->array_vals = (tdrpVal_t *)
        tdrpMalloc(tt->array_n * sizeof(tdrpVal_t));
    tt++;
    
    // Parameter 'max_input_data_age'
    // ctype is 'int'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = INT_TYPE;
    tt->param_name = tdrpStrDup("max_input_data_age");
    tt->descr = tdrpStrDup("Max age (in seconds) of input data");
    tt->help = tdrpStrDup("Used only if files are not specified on the command line");
    tt->val_offset = (char *) &max_input_data_age - &_start_;
    tt->has_min = TRUE;
    tt->min_val.i = 60;
    tt->single_val.i = 10800;
    tt++;
    
    // Parameter 'latest_data_info_avail'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("latest_data_info_avail");
    tt->descr = tdrpStrDup("If TRUE, watch input_dir for change in _latest_data_info.");
    tt->help = tdrpStrDup("If FALSE, watch input_dir for new files.");
    tt->val_offset = (char *) &latest_data_info_avail - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'recursive_search'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("recursive_search");
    tt->descr = tdrpStrDup("Option to recurse when searching for new files.");
    tt->help = tdrpStrDup("Only applies if latest_data_info_avail is FALSE.");
    tt->val_offset = (char *) &recursive_search - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'latest_file_only'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("latest_file_only");
    tt->descr = tdrpStrDup("Option to only process the latest file in directory.");
    tt->help = tdrpStrDup("If TRUE, only the latest file will be processed. If FALSE, previously-written files will be processed.");
    tt->val_offset = (char *) &latest_file_only - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'data_check_interval_secs'
    // ctype is 'int'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = INT_TYPE;
    tt->param_name = tdrpStrDup("data_check_interval_secs");
    tt->descr = tdrpStrDup("How often to check for new data (secs).");
    tt->help = tdrpStrDup("");
    tt->val_offset = (char *) &data_check_interval_secs - &_start_;
    tt->single_val.i = 5;
    tt++;
    
    // Parameter 'Comment 2'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = COMMENT_TYPE;
    tt->param_name = tdrpStrDup("Comment 2");
    tt->comment_hdr = tdrpStrDup("PRINT SECTIONS PARAMETERS");
    tt->comment_text = tdrpStrDup("Parameters only used with -printSec or debug > 1\nFor each grib message prints the sections defined below\n");
    tt++;
    
    // Parameter 'printSec_is'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_is");
    tt->descr = tdrpStrDup("If TRUE prints the Indicator Section.");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_is - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'printSec_ids'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_ids");
    tt->descr = tdrpStrDup("If TRUE prints the Identification Section.");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_ids - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'printSec_lus'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_lus");
    tt->descr = tdrpStrDup("If TRUE prints the Local Use Section (if present).");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_lus - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'printSec_gds'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_gds");
    tt->descr = tdrpStrDup("If TRUE prints the Grid Definition Section.");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_gds - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'printSec_pds'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_pds");
    tt->descr = tdrpStrDup("If TRUE prints the Product Definition Section.");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_pds - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'printSec_drs'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_drs");
    tt->descr = tdrpStrDup("If TRUE prints the Data Representation Section.");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_drs - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'printSec_bms'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_bms");
    tt->descr = tdrpStrDup("If TRUE prints the Bit-map Section.");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_bms - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'printSec_ds'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("printSec_ds");
    tt->descr = tdrpStrDup("If TRUE prints the Data Section.");
    tt->help = tdrpStrDup("Only prints with -printSec or debug > 1");
    tt->val_offset = (char *) &printSec_ds - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'Comment 3'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = COMMENT_TYPE;
    tt->param_name = tdrpStrDup("Comment 3");
    tt->comment_hdr = tdrpStrDup("MDV OUTPUT PARAMETERS");
    tt->comment_text = tdrpStrDup("");
    tt++;
    
    // Parameter 'autoset_missing_value'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("autoset_missing_value");
    tt->descr = tdrpStrDup("This option will infer the missing value from the data if possible.");
    tt->help = tdrpStrDup("Grib2 doesnt allow for setting a missing value unless complex data packing used. ");
    tt->val_offset = (char *) &autoset_missing_value - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'check_lead_time'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("check_lead_time");
    tt->descr = tdrpStrDup("Option to limit the lead time of output files.");
    tt->help = tdrpStrDup("If set, we check the lead time before writing files.");
    tt->val_offset = (char *) &check_lead_time - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'max_lead_time_secs'
    // ctype is 'int'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = INT_TYPE;
    tt->param_name = tdrpStrDup("max_lead_time_secs");
    tt->descr = tdrpStrDup("Maximum lead time for output files (secs).");
    tt->help = tdrpStrDup("See 'check_lead_time'.");
    tt->val_offset = (char *) &max_lead_time_secs - &_start_;
    tt->single_val.i = 86400;
    tt++;
    
    // Parameter 'lead_time_subsampling'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("lead_time_subsampling");
    tt->descr = tdrpStrDup("Lead time subsampling flag");
    tt->help = tdrpStrDup("Set to true to enable lead time subsampling.");
    tt->val_offset = (char *) &lead_time_subsampling - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'subsample_lead_times'
    // ctype is 'int'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = INT_TYPE;
    tt->param_name = tdrpStrDup("subsample_lead_times");
    tt->descr = tdrpStrDup("The subsampled lead times to process");
    tt->help = tdrpStrDup("");
    tt->array_offset = (char *) &_subsample_lead_times - &_start_;
    tt->array_n_offset = (char *) &subsample_lead_times_n - &_start_;
    tt->is_array = TRUE;
    tt->array_len_fixed = FALSE;
    tt->array_elem_size = sizeof(int);
    tt->array_n = 0;
    tt->array_vals = (tdrpVal_t *)
        tdrpMalloc(tt->array_n * sizeof(tdrpVal_t));
    tt++;
    
    // Parameter 'write_forecast'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("write_forecast");
    tt->descr = tdrpStrDup("Write mdv files in a forecast directory structure");
    tt->help = tdrpStrDup("If this is true, mdv files will be written in the rap forecast directory structure.  Note that if write_non_forecast is also set to true, two mdv files will be written");
    tt->val_offset = (char *) &write_forecast - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'forecast_mdv_url'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("forecast_mdv_url");
    tt->descr = tdrpStrDup("Url for mdv files in forecast structure");
    tt->help = tdrpStrDup("");
    tt->val_offset = (char *) &forecast_mdv_url - &_start_;
    tt->single_val.s = tdrpStrDup("mdvp:://localhost::./mdv");
    tt++;
    
    // Parameter 'write_non_forecast'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("write_non_forecast");
    tt->descr = tdrpStrDup("Write mdv files in a non-forecast directory structure");
    tt->help = tdrpStrDup("If this is true, mdv files will be written in the regular (non-forecast) rap directory structure.  Note that if write_forecast is also set to true, two mdv files will be written.  Note also that this option allows for overwriting files, since the forecast time will be used as the data time in this case.  This is a temporary option to allow for easier display of the data");
    tt->val_offset = (char *) &write_non_forecast - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'non_forecast_mdv_url'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("non_forecast_mdv_url");
    tt->descr = tdrpStrDup("Url for mdv files in non-forecast structure");
    tt->help = tdrpStrDup("");
    tt->val_offset = (char *) &non_forecast_mdv_url - &_start_;
    tt->single_val.s = tdrpStrDup("mdvp:://localhost::./mdv");
    tt++;
    
    // Parameter 'non_forecast_timestamp'
    // ctype is '_timestamp_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = ENUM_TYPE;
    tt->param_name = tdrpStrDup("non_forecast_timestamp");
    tt->descr = tdrpStrDup("This parameter allows user to timestamp non-forecast mdv files based on the model's run time or the forecast time.");
    tt->help = tdrpStrDup("The choices are TIMESTAMP_GEN_TIME and TIMESTAMP_FCAST_TIME");
    tt->val_offset = (char *) &non_forecast_timestamp - &_start_;
    tt->enum_def.name = tdrpStrDup("timestamp_t");
    tt->enum_def.nfields = 2;
    tt->enum_def.fields = (enum_field_t *)
        tdrpMalloc(tt->enum_def.nfields * sizeof(enum_field_t));
      tt->enum_def.fields[0].name = tdrpStrDup("TIMESTAMP_GEN_TIME");
      tt->enum_def.fields[0].val = TIMESTAMP_GEN_TIME;
      tt->enum_def.fields[1].name = tdrpStrDup("TIMESTAMP_FCAST_TIME");
      tt->enum_def.fields[1].val = TIMESTAMP_FCAST_TIME;
    tt->single_val.e = TIMESTAMP_FCAST_TIME;
    tt++;
    
    // Parameter 'data_is_non_forecast'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("data_is_non_forecast");
    tt->descr = tdrpStrDup("Write mdv files as regular data files");
    tt->help = tdrpStrDup("If this is true, the output mdv files are assumed to be non-forecast data.  If this flag is set true, the write_non_forecast flag must also be set true and the non_forecast_mdv_url must be set.  If this flag is set false, and write_non_forecast_mdv_url is true, the output is assumed to be forecast data, but written into a regular (non-forecast) rap directory structure anyway");
    tt->val_offset = (char *) &data_is_non_forecast - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'writeLdataInfo'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("writeLdataInfo");
    tt->descr = tdrpStrDup("Write _latest_data_info files for output data.");
    tt->help = tdrpStrDup("If false, will suppress writing of _latest_data_info files.");
    tt->val_offset = (char *) &writeLdataInfo - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'data_set_info'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("data_set_info");
    tt->descr = tdrpStrDup("Data set info.");
    tt->help = tdrpStrDup("This is placed in the MDV master header for documentation purposes.");
    tt->val_offset = (char *) &data_set_info - &_start_;
    tt->single_val.s = tdrpStrDup("Converted to MDV with Grib2toMdv.");
    tt++;
    
    // Parameter 'data_set_name'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("data_set_name");
    tt->descr = tdrpStrDup("Data set name.");
    tt->help = tdrpStrDup("This is placed in the MDV master header for documentation purposes.");
    tt->val_offset = (char *) &data_set_name - &_start_;
    tt->single_val.s = tdrpStrDup("GFS model output.");
    tt++;
    
    // Parameter 'data_set_source'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("data_set_source");
    tt->descr = tdrpStrDup("Data set source details.");
    tt->help = tdrpStrDup("This is placed in the MDV master header for documentation purposes.");
    tt->val_offset = (char *) &data_set_source - &_start_;
    tt->single_val.s = tdrpStrDup("Grib2.");
    tt++;
    
    // Parameter 'process_everything'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("process_everything");
    tt->descr = tdrpStrDup("Flag to process all fields");
    tt->help = tdrpStrDup("If TRUE, all fields will be processed.\nIf FALSE, only fields listed in output_fields list will be processed");
    tt->val_offset = (char *) &process_everything - &_start_;
    tt->single_val.b = pTRUE;
    tt++;
    
    // Parameter 'output_fields'
    // ctype is '_out_field_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRUCT_TYPE;
    tt->param_name = tdrpStrDup("output_fields");
    tt->descr = tdrpStrDup("List of output fields, which are descibed by the field parameter and vertical level type\n");
    tt->help = tdrpStrDup("To determine the available params and levels, use the command line argument -printSummary -file [filename]\n  No Mdv output will be created, only a list of params and associated levels contained in the GRIB file.\nNote: process_everything must be set to FALSE to use this list.\n                                 \nout_field_t structure definition:\n  param:string GRIB2 product ID.\n  level:string GRIB2 level ID.\n  mdv_name:string MDV short field name. Overrides default name.\n                  Use empty string to keep default (param) name.\n  out_units:out_units_t simple unit conversion utility. Options are:\n    NO_CHANGE            -- no change to units\n    MPS_TO_KNOTS         -- convert m/s to knots\n    M_TO_KM              -- convert meters to kilometers\n    M_TO_FT              -- convert meters to feet, \n    M_TO_MI              -- convert meters to miles, \n    M_TO_100FT           -- convert meters to 100's of feet, \n                            flight levels\n    PASCALS_TO_MBAR      -- convert pascals to millibars\n    KELVIN_TO_CELCIUS    -- convert degrees kelvin to to degrees\n                            celcius\n    KGPKG_TO_GPKG        -- convert kilogram per kilogram to gram\n                            per kilogram\n    PERCENT_TO_FRACTION  -- convert percentage to fraction, values\n                            between 0 and 1\n    FRACTION_TO_PERCENT  -- convert fraction to percentage, values\n                            between 0 and 100\n                                           \n   upper_range_limit:double upper limit threshold for field.\n   lower_range_limit:double lower limit threshold for field. \n                            When both upper and lower limits are set\n                            to zero no thresholds are applied.\n  encoding_type:encoding_type_t  Output variable encoding type\n  qc_default_type:qc_default_t Replacement value for inputs outside\n                               of the range_limit\n  qc_default_value:double User defined replacement value.\n  vert_level_min: minimum integer level that will be processed(If set to -1,\n                  no restrictions will be set.)\n  vert_level_max: maximum integer level that will be processed(If set to -1,\n                  no restrictions will be set.)\n  vert_level_dz:  integer change in vertical levels that will be processed.\n\nDefault behavior is to process everything with no changes");
    tt->array_offset = (char *) &_output_fields - &_start_;
    tt->array_n_offset = (char *) &output_fields_n - &_start_;
    tt->is_array = TRUE;
    tt->array_len_fixed = FALSE;
    tt->array_elem_size = sizeof(out_field_t);
    tt->array_n = 1;
    tt->struct_def.name = tdrpStrDup("out_field_t");
    tt->struct_def.nfields = 16;
    tt->struct_def.fields = (struct_field_t *)
        tdrpMalloc(tt->struct_def.nfields * sizeof(struct_field_t));
      tt->struct_def.fields[0].ftype = tdrpStrDup("string");
      tt->struct_def.fields[0].fname = tdrpStrDup("param");
      tt->struct_def.fields[0].ptype = STRING_TYPE;
      tt->struct_def.fields[0].rel_offset = 
        (char *) &_output_fields->param - (char *) _output_fields;
      tt->struct_def.fields[1].ftype = tdrpStrDup("string");
      tt->struct_def.fields[1].fname = tdrpStrDup("level");
      tt->struct_def.fields[1].ptype = STRING_TYPE;
      tt->struct_def.fields[1].rel_offset = 
        (char *) &_output_fields->level - (char *) _output_fields;
      tt->struct_def.fields[2].ftype = tdrpStrDup("string");
      tt->struct_def.fields[2].fname = tdrpStrDup("mdv_name");
      tt->struct_def.fields[2].ptype = STRING_TYPE;
      tt->struct_def.fields[2].rel_offset = 
        (char *) &_output_fields->mdv_name - (char *) _output_fields;
      tt->struct_def.fields[3].ftype = tdrpStrDup("out_units_t");
      tt->struct_def.fields[3].fname = tdrpStrDup("units");
      tt->struct_def.fields[3].ptype = ENUM_TYPE;
      tt->struct_def.fields[3].rel_offset = 
        (char *) &_output_fields->units - (char *) _output_fields;
        tt->struct_def.fields[3].enum_def.name = tdrpStrDup("out_units_t");
        tt->struct_def.fields[3].enum_def.nfields = 13;
        tt->struct_def.fields[3].enum_def.fields = (enum_field_t *) tdrpMalloc
          (tt->struct_def.fields[3].enum_def.nfields * sizeof(enum_field_t));
        tt->struct_def.fields[3].enum_def.fields[0].name = tdrpStrDup("NO_CHANGE");
        tt->struct_def.fields[3].enum_def.fields[0].val = NO_CHANGE;
        tt->struct_def.fields[3].enum_def.fields[1].name = tdrpStrDup("MPS_TO_KNOTS");
        tt->struct_def.fields[3].enum_def.fields[1].val = MPS_TO_KNOTS;
        tt->struct_def.fields[3].enum_def.fields[2].name = tdrpStrDup("M_TO_KM");
        tt->struct_def.fields[3].enum_def.fields[2].val = M_TO_KM;
        tt->struct_def.fields[3].enum_def.fields[3].name = tdrpStrDup("M_TO_100FT");
        tt->struct_def.fields[3].enum_def.fields[3].val = M_TO_100FT;
        tt->struct_def.fields[3].enum_def.fields[4].name = tdrpStrDup("PASCALS_TO_MBAR");
        tt->struct_def.fields[3].enum_def.fields[4].val = PASCALS_TO_MBAR;
        tt->struct_def.fields[3].enum_def.fields[5].name = tdrpStrDup("KELVIN_TO_CELCIUS");
        tt->struct_def.fields[3].enum_def.fields[5].val = KELVIN_TO_CELCIUS;
        tt->struct_def.fields[3].enum_def.fields[6].name = tdrpStrDup("KGPKG_TO_GPKG");
        tt->struct_def.fields[3].enum_def.fields[6].val = KGPKG_TO_GPKG;
        tt->struct_def.fields[3].enum_def.fields[7].name = tdrpStrDup("PERCENT_TO_FRACTION");
        tt->struct_def.fields[3].enum_def.fields[7].val = PERCENT_TO_FRACTION;
        tt->struct_def.fields[3].enum_def.fields[8].name = tdrpStrDup("FRACTION_TO_PERCENT");
        tt->struct_def.fields[3].enum_def.fields[8].val = FRACTION_TO_PERCENT;
        tt->struct_def.fields[3].enum_def.fields[9].name = tdrpStrDup("M_TO_FT");
        tt->struct_def.fields[3].enum_def.fields[9].val = M_TO_FT;
        tt->struct_def.fields[3].enum_def.fields[10].name = tdrpStrDup("M_TO_MI");
        tt->struct_def.fields[3].enum_def.fields[10].val = M_TO_MI;
        tt->struct_def.fields[3].enum_def.fields[11].name = tdrpStrDup("M_TO_KFT");
        tt->struct_def.fields[3].enum_def.fields[11].val = M_TO_KFT;
        tt->struct_def.fields[3].enum_def.fields[12].name = tdrpStrDup("MM_S_TO_MM_HR");
        tt->struct_def.fields[3].enum_def.fields[12].val = MM_S_TO_MM_HR;
      tt->struct_def.fields[4].ftype = tdrpStrDup("double");
      tt->struct_def.fields[4].fname = tdrpStrDup("upper_range_limit");
      tt->struct_def.fields[4].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[4].rel_offset = 
        (char *) &_output_fields->upper_range_limit - (char *) _output_fields;
      tt->struct_def.fields[5].ftype = tdrpStrDup("double");
      tt->struct_def.fields[5].fname = tdrpStrDup("lower_range_limit");
      tt->struct_def.fields[5].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[5].rel_offset = 
        (char *) &_output_fields->lower_range_limit - (char *) _output_fields;
      tt->struct_def.fields[6].ftype = tdrpStrDup("encoding_type_t");
      tt->struct_def.fields[6].fname = tdrpStrDup("encoding_type");
      tt->struct_def.fields[6].ptype = ENUM_TYPE;
      tt->struct_def.fields[6].rel_offset = 
        (char *) &_output_fields->encoding_type - (char *) _output_fields;
        tt->struct_def.fields[6].enum_def.name = tdrpStrDup("encoding_type_t");
        tt->struct_def.fields[6].enum_def.nfields = 4;
        tt->struct_def.fields[6].enum_def.fields = (enum_field_t *) tdrpMalloc
          (tt->struct_def.fields[6].enum_def.nfields * sizeof(enum_field_t));
        tt->struct_def.fields[6].enum_def.fields[0].name = tdrpStrDup("ENCODING_ASIS");
        tt->struct_def.fields[6].enum_def.fields[0].val = ENCODING_ASIS;
        tt->struct_def.fields[6].enum_def.fields[1].name = tdrpStrDup("ENCODING_INT8");
        tt->struct_def.fields[6].enum_def.fields[1].val = ENCODING_INT8;
        tt->struct_def.fields[6].enum_def.fields[2].name = tdrpStrDup("ENCODING_INT16");
        tt->struct_def.fields[6].enum_def.fields[2].val = ENCODING_INT16;
        tt->struct_def.fields[6].enum_def.fields[3].name = tdrpStrDup("ENCODING_FLOAT32");
        tt->struct_def.fields[6].enum_def.fields[3].val = ENCODING_FLOAT32;
      tt->struct_def.fields[7].ftype = tdrpStrDup("qc_default_t");
      tt->struct_def.fields[7].fname = tdrpStrDup("qc_default_type");
      tt->struct_def.fields[7].ptype = ENUM_TYPE;
      tt->struct_def.fields[7].rel_offset = 
        (char *) &_output_fields->qc_default_type - (char *) _output_fields;
        tt->struct_def.fields[7].enum_def.name = tdrpStrDup("qc_default_t");
        tt->struct_def.fields[7].enum_def.nfields = 3;
        tt->struct_def.fields[7].enum_def.fields = (enum_field_t *) tdrpMalloc
          (tt->struct_def.fields[7].enum_def.nfields * sizeof(enum_field_t));
        tt->struct_def.fields[7].enum_def.fields[0].name = tdrpStrDup("BAD_VALUE");
        tt->struct_def.fields[7].enum_def.fields[0].val = BAD_VALUE;
        tt->struct_def.fields[7].enum_def.fields[1].name = tdrpStrDup("UNKNOWN_VALUE");
        tt->struct_def.fields[7].enum_def.fields[1].val = UNKNOWN_VALUE;
        tt->struct_def.fields[7].enum_def.fields[2].name = tdrpStrDup("USER_DEFINED");
        tt->struct_def.fields[7].enum_def.fields[2].val = USER_DEFINED;
      tt->struct_def.fields[8].ftype = tdrpStrDup("double");
      tt->struct_def.fields[8].fname = tdrpStrDup("qc_default_value");
      tt->struct_def.fields[8].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[8].rel_offset = 
        (char *) &_output_fields->qc_default_value - (char *) _output_fields;
      tt->struct_def.fields[9].ftype = tdrpStrDup("int");
      tt->struct_def.fields[9].fname = tdrpStrDup("vert_level_min");
      tt->struct_def.fields[9].ptype = INT_TYPE;
      tt->struct_def.fields[9].rel_offset = 
        (char *) &_output_fields->vert_level_min - (char *) _output_fields;
      tt->struct_def.fields[10].ftype = tdrpStrDup("int");
      tt->struct_def.fields[10].fname = tdrpStrDup("vert_level_max");
      tt->struct_def.fields[10].ptype = INT_TYPE;
      tt->struct_def.fields[10].rel_offset = 
        (char *) &_output_fields->vert_level_max - (char *) _output_fields;
      tt->struct_def.fields[11].ftype = tdrpStrDup("int");
      tt->struct_def.fields[11].fname = tdrpStrDup("vert_level_dz");
      tt->struct_def.fields[11].ptype = INT_TYPE;
      tt->struct_def.fields[11].rel_offset = 
        (char *) &_output_fields->vert_level_dz - (char *) _output_fields;
      tt->struct_def.fields[12].ftype = tdrpStrDup("boolean");
      tt->struct_def.fields[12].fname = tdrpStrDup("use_additional_bad_data_value");
      tt->struct_def.fields[12].ptype = BOOL_TYPE;
      tt->struct_def.fields[12].rel_offset = 
        (char *) &_output_fields->use_additional_bad_data_value - (char *) _output_fields;
      tt->struct_def.fields[13].ftype = tdrpStrDup("double");
      tt->struct_def.fields[13].fname = tdrpStrDup("additional_bad_data_value");
      tt->struct_def.fields[13].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[13].rel_offset = 
        (char *) &_output_fields->additional_bad_data_value - (char *) _output_fields;
      tt->struct_def.fields[14].ftype = tdrpStrDup("boolean");
      tt->struct_def.fields[14].fname = tdrpStrDup("use_additional_missing_data_value");
      tt->struct_def.fields[14].ptype = BOOL_TYPE;
      tt->struct_def.fields[14].rel_offset = 
        (char *) &_output_fields->use_additional_missing_data_value - (char *) _output_fields;
      tt->struct_def.fields[15].ftype = tdrpStrDup("double");
      tt->struct_def.fields[15].fname = tdrpStrDup("additional_missing_data_value");
      tt->struct_def.fields[15].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[15].rel_offset = 
        (char *) &_output_fields->additional_missing_data_value - (char *) _output_fields;
    tt->n_struct_vals = 16;
    tt->struct_vals = (tdrpVal_t *)
        tdrpMalloc(tt->n_struct_vals * sizeof(tdrpVal_t));
      tt->struct_vals[0].s = tdrpStrDup("PRES");
      tt->struct_vals[1].s = tdrpStrDup("HYBL");
      tt->struct_vals[2].s = tdrpStrDup("");
      tt->struct_vals[3].e = NO_CHANGE;
      tt->struct_vals[4].d = 0;
      tt->struct_vals[5].d = 0;
      tt->struct_vals[6].e = ENCODING_FLOAT32;
      tt->struct_vals[7].e = BAD_VALUE;
      tt->struct_vals[8].d = 0;
      tt->struct_vals[9].i = -1;
      tt->struct_vals[10].i = -1;
      tt->struct_vals[11].i = 1;
      tt->struct_vals[12].b = pFALSE;
      tt->struct_vals[13].d = 0;
      tt->struct_vals[14].b = pFALSE;
      tt->struct_vals[15].d = 0;
    tt++;
    
    // Parameter 'encoding_type'
    // ctype is '_encoding_type_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = ENUM_TYPE;
    tt->param_name = tdrpStrDup("encoding_type");
    tt->descr = tdrpStrDup("File encoding type, Used only when process_everything is true.");
    tt->help = tdrpStrDup("");
    tt->val_offset = (char *) &encoding_type - &_start_;
    tt->enum_def.name = tdrpStrDup("encoding_type_t");
    tt->enum_def.nfields = 4;
    tt->enum_def.fields = (enum_field_t *)
        tdrpMalloc(tt->enum_def.nfields * sizeof(enum_field_t));
      tt->enum_def.fields[0].name = tdrpStrDup("ENCODING_ASIS");
      tt->enum_def.fields[0].val = ENCODING_ASIS;
      tt->enum_def.fields[1].name = tdrpStrDup("ENCODING_INT8");
      tt->enum_def.fields[1].val = ENCODING_INT8;
      tt->enum_def.fields[2].name = tdrpStrDup("ENCODING_INT16");
      tt->enum_def.fields[2].val = ENCODING_INT16;
      tt->enum_def.fields[3].name = tdrpStrDup("ENCODING_FLOAT32");
      tt->enum_def.fields[3].val = ENCODING_FLOAT32;
    tt->single_val.e = ENCODING_FLOAT32;
    tt++;
    
    // Parameter 'compression_type'
    // ctype is '_compression_type_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = ENUM_TYPE;
    tt->param_name = tdrpStrDup("compression_type");
    tt->descr = tdrpStrDup("File compression type, Used only when process_everything is true.");
    tt->help = tdrpStrDup("");
    tt->val_offset = (char *) &compression_type - &_start_;
    tt->enum_def.name = tdrpStrDup("compression_type_t");
    tt->enum_def.nfields = 7;
    tt->enum_def.fields = (enum_field_t *)
        tdrpMalloc(tt->enum_def.nfields * sizeof(enum_field_t));
      tt->enum_def.fields[0].name = tdrpStrDup("COMPRESSION_ASIS");
      tt->enum_def.fields[0].val = COMPRESSION_ASIS;
      tt->enum_def.fields[1].name = tdrpStrDup("COMPRESSION_NONE");
      tt->enum_def.fields[1].val = COMPRESSION_NONE;
      tt->enum_def.fields[2].name = tdrpStrDup("COMPRESSION_RLE");
      tt->enum_def.fields[2].val = COMPRESSION_RLE;
      tt->enum_def.fields[3].name = tdrpStrDup("COMPRESSION_LZO");
      tt->enum_def.fields[3].val = COMPRESSION_LZO;
      tt->enum_def.fields[4].name = tdrpStrDup("COMPRESSION_ZLIB");
      tt->enum_def.fields[4].val = COMPRESSION_ZLIB;
      tt->enum_def.fields[5].name = tdrpStrDup("COMPRESSION_BZIP");
      tt->enum_def.fields[5].val = COMPRESSION_BZIP;
      tt->enum_def.fields[6].name = tdrpStrDup("COMPRESSION_GZIP");
      tt->enum_def.fields[6].val = COMPRESSION_GZIP;
    tt->single_val.e = COMPRESSION_GZIP;
    tt++;
    
    // Parameter 'output_scaling_info'
    // ctype is '_Scaling_info_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRUCT_TYPE;
    tt->param_name = tdrpStrDup("output_scaling_info");
    tt->descr = tdrpStrDup("Options for user defined scale and bias.");
    tt->help = tdrpStrDup("Only applies if ENCODING type is INT8 or INT16.\nIf SpecifyScaling is true then the following scale and bias values will be used. If false dynamic scaling is applied.");
    tt->val_offset = (char *) &output_scaling_info - &_start_;
    tt->struct_def.name = tdrpStrDup("Scaling_info_t");
    tt->struct_def.nfields = 3;
    tt->struct_def.fields = (struct_field_t *)
        tdrpMalloc(tt->struct_def.nfields * sizeof(struct_field_t));
      tt->struct_def.fields[0].ftype = tdrpStrDup("boolean");
      tt->struct_def.fields[0].fname = tdrpStrDup("SpecifyScaling");
      tt->struct_def.fields[0].ptype = BOOL_TYPE;
      tt->struct_def.fields[0].rel_offset = 
        (char *) &output_scaling_info.SpecifyScaling - (char *) &output_scaling_info;
      tt->struct_def.fields[1].ftype = tdrpStrDup("double");
      tt->struct_def.fields[1].fname = tdrpStrDup("scale");
      tt->struct_def.fields[1].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[1].rel_offset = 
        (char *) &output_scaling_info.scale - (char *) &output_scaling_info;
      tt->struct_def.fields[2].ftype = tdrpStrDup("double");
      tt->struct_def.fields[2].fname = tdrpStrDup("bias");
      tt->struct_def.fields[2].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[2].rel_offset = 
        (char *) &output_scaling_info.bias - (char *) &output_scaling_info;
    tt->n_struct_vals = 3;
    tt->struct_vals = (tdrpVal_t *)
        tdrpMalloc(tt->n_struct_vals * sizeof(tdrpVal_t));
      tt->struct_vals[0].b = pFALSE;
      tt->struct_vals[1].d = 0.5;
      tt->struct_vals[2].d = -32;
    tt++;
    
    // Parameter 'remap_output'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("remap_output");
    tt->descr = tdrpStrDup("If TRUE remaps output.");
    tt->help = tdrpStrDup("");
    tt->val_offset = (char *) &remap_output - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'out_projection_info'
    // ctype is '_projection_info_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRUCT_TYPE;
    tt->param_name = tdrpStrDup("out_projection_info");
    tt->descr = tdrpStrDup("This is the user defined projection");
    tt->help = tdrpStrDup("If remap_output is true this defines the projection to remap to.\n\nThe choice of projections are PROJ_LATLON, PROJ_LAMBERT_CONF and PROJ_FLAT.\n\nPROJ_LATLON is a latitude/longitude projection, and if it is chosen the remaining parameters can be ignored.\n\nPROJ_FLAT is a flat projection, and if it is chosen the parameters rotation, origin_lat, origin_lon must be set.\n\nPROJ_LAMBERT_CONF is a Lambert conformal projection, and if it is chosen the parameters origin_lat, origin_lon, ref_lat_1 and ref_lat_2 must be set.");
    tt->val_offset = (char *) &out_projection_info - &_start_;
    tt->struct_def.name = tdrpStrDup("projection_info_t");
    tt->struct_def.nfields = 6;
    tt->struct_def.fields = (struct_field_t *)
        tdrpMalloc(tt->struct_def.nfields * sizeof(struct_field_t));
      tt->struct_def.fields[0].ftype = tdrpStrDup("projection_t");
      tt->struct_def.fields[0].fname = tdrpStrDup("type");
      tt->struct_def.fields[0].ptype = ENUM_TYPE;
      tt->struct_def.fields[0].rel_offset = 
        (char *) &out_projection_info.type - (char *) &out_projection_info;
        tt->struct_def.fields[0].enum_def.name = tdrpStrDup("projection_t");
        tt->struct_def.fields[0].enum_def.nfields = 3;
        tt->struct_def.fields[0].enum_def.fields = (enum_field_t *) tdrpMalloc
          (tt->struct_def.fields[0].enum_def.nfields * sizeof(enum_field_t));
        tt->struct_def.fields[0].enum_def.fields[0].name = tdrpStrDup("PROJ_LATLON");
        tt->struct_def.fields[0].enum_def.fields[0].val = PROJ_LATLON;
        tt->struct_def.fields[0].enum_def.fields[1].name = tdrpStrDup("PROJ_LAMBERT_CONF");
        tt->struct_def.fields[0].enum_def.fields[1].val = PROJ_LAMBERT_CONF;
        tt->struct_def.fields[0].enum_def.fields[2].name = tdrpStrDup("PROJ_FLAT");
        tt->struct_def.fields[0].enum_def.fields[2].val = PROJ_FLAT;
      tt->struct_def.fields[1].ftype = tdrpStrDup("double");
      tt->struct_def.fields[1].fname = tdrpStrDup("rotation");
      tt->struct_def.fields[1].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[1].rel_offset = 
        (char *) &out_projection_info.rotation - (char *) &out_projection_info;
      tt->struct_def.fields[2].ftype = tdrpStrDup("double");
      tt->struct_def.fields[2].fname = tdrpStrDup("origin_lat");
      tt->struct_def.fields[2].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[2].rel_offset = 
        (char *) &out_projection_info.origin_lat - (char *) &out_projection_info;
      tt->struct_def.fields[3].ftype = tdrpStrDup("double");
      tt->struct_def.fields[3].fname = tdrpStrDup("origin_lon");
      tt->struct_def.fields[3].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[3].rel_offset = 
        (char *) &out_projection_info.origin_lon - (char *) &out_projection_info;
      tt->struct_def.fields[4].ftype = tdrpStrDup("double");
      tt->struct_def.fields[4].fname = tdrpStrDup("ref_lat_1");
      tt->struct_def.fields[4].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[4].rel_offset = 
        (char *) &out_projection_info.ref_lat_1 - (char *) &out_projection_info;
      tt->struct_def.fields[5].ftype = tdrpStrDup("double");
      tt->struct_def.fields[5].fname = tdrpStrDup("ref_lat_2");
      tt->struct_def.fields[5].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[5].rel_offset = 
        (char *) &out_projection_info.ref_lat_2 - (char *) &out_projection_info;
    tt->n_struct_vals = 6;
    tt->struct_vals = (tdrpVal_t *)
        tdrpMalloc(tt->n_struct_vals * sizeof(tdrpVal_t));
      tt->struct_vals[0].e = PROJ_LAMBERT_CONF;
      tt->struct_vals[1].d = 0;
      tt->struct_vals[2].d = 25;
      tt->struct_vals[3].d = -95;
      tt->struct_vals[4].d = 25;
      tt->struct_vals[5].d = 25;
    tt++;
    
    // Parameter 'out_grid_info'
    // ctype is '_grid_info_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRUCT_TYPE;
    tt->param_name = tdrpStrDup("out_grid_info");
    tt->descr = tdrpStrDup("This is the user defined grid.");
    tt->help = tdrpStrDup("If remap_output is true this defines the grid info for the remap.\n\nFor a LATLON projection:\n  minx = minLon\n  miny = minLat\n  dx = deltaLon\n  dy = deltaLat.");
    tt->val_offset = (char *) &out_grid_info - &_start_;
    tt->struct_def.name = tdrpStrDup("grid_info_t");
    tt->struct_def.nfields = 6;
    tt->struct_def.fields = (struct_field_t *)
        tdrpMalloc(tt->struct_def.nfields * sizeof(struct_field_t));
      tt->struct_def.fields[0].ftype = tdrpStrDup("int");
      tt->struct_def.fields[0].fname = tdrpStrDup("nx");
      tt->struct_def.fields[0].ptype = INT_TYPE;
      tt->struct_def.fields[0].rel_offset = 
        (char *) &out_grid_info.nx - (char *) &out_grid_info;
      tt->struct_def.fields[1].ftype = tdrpStrDup("int");
      tt->struct_def.fields[1].fname = tdrpStrDup("ny");
      tt->struct_def.fields[1].ptype = INT_TYPE;
      tt->struct_def.fields[1].rel_offset = 
        (char *) &out_grid_info.ny - (char *) &out_grid_info;
      tt->struct_def.fields[2].ftype = tdrpStrDup("double");
      tt->struct_def.fields[2].fname = tdrpStrDup("minx");
      tt->struct_def.fields[2].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[2].rel_offset = 
        (char *) &out_grid_info.minx - (char *) &out_grid_info;
      tt->struct_def.fields[3].ftype = tdrpStrDup("double");
      tt->struct_def.fields[3].fname = tdrpStrDup("miny");
      tt->struct_def.fields[3].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[3].rel_offset = 
        (char *) &out_grid_info.miny - (char *) &out_grid_info;
      tt->struct_def.fields[4].ftype = tdrpStrDup("double");
      tt->struct_def.fields[4].fname = tdrpStrDup("dx");
      tt->struct_def.fields[4].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[4].rel_offset = 
        (char *) &out_grid_info.dx - (char *) &out_grid_info;
      tt->struct_def.fields[5].ftype = tdrpStrDup("double");
      tt->struct_def.fields[5].fname = tdrpStrDup("dy");
      tt->struct_def.fields[5].ptype = DOUBLE_TYPE;
      tt->struct_def.fields[5].rel_offset = 
        (char *) &out_grid_info.dy - (char *) &out_grid_info;
    tt->n_struct_vals = 6;
    tt->struct_vals = (tdrpVal_t *)
        tdrpMalloc(tt->n_struct_vals * sizeof(tdrpVal_t));
      tt->struct_vals[0].i = 301;
      tt->struct_vals[1].i = 225;
      tt->struct_vals[2].d = -3332.14;
      tt->struct_vals[3].d = -588.89;
      tt->struct_vals[4].d = 20.318;
      tt->struct_vals[5].d = 20.318;
    tt++;
    
    // Parameter 'override_vlevels'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("override_vlevels");
    tt->descr = tdrpStrDup("Option to override the vlevels in the vlevel header of the specified level types.");
    tt->help = tdrpStrDup("If not empty, will replace the vlevels of variables with the specified vlevel type with those specified in 'vlevel_array'.\nNormal vlevel types to replace are: 'SIGL', 'SIGMA', or 'HYBL'.\nPlease note using this functionality can create incorrect levels, use carefully!");
    tt->val_offset = (char *) &override_vlevels - &_start_;
    tt->single_val.s = tdrpStrDup("");
    tt++;
    
    // Parameter 'vlevel_array'
    // ctype is 'double'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = DOUBLE_TYPE;
    tt->param_name = tdrpStrDup("vlevel_array");
    tt->descr = tdrpStrDup("vlevel values to override what is already in the file.");
    tt->help = tdrpStrDup("See 'override_vlevels'.");
    tt->array_offset = (char *) &_vlevel_array - &_start_;
    tt->array_n_offset = (char *) &vlevel_array_n - &_start_;
    tt->is_array = TRUE;
    tt->array_len_fixed = FALSE;
    tt->array_elem_size = sizeof(double);
    tt->array_n = 1;
    tt->array_vals = (tdrpVal_t *)
        tdrpMalloc(tt->array_n * sizeof(tdrpVal_t));
      tt->array_vals[0].d = 0;
    tt++;
    
    // Parameter 'Comment 4'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = COMMENT_TYPE;
    tt->param_name = tdrpStrDup("Comment 4");
    tt->comment_hdr = tdrpStrDup("INTERPOLATE INTO HEIGHT LEVELS (km MSL)");
    tt->comment_text = tdrpStrDup("Option to interpolate the model data into height levels. This requires that (a) the vertical coords are pressure levels and (b) the geopotential height field is included in the input data.");
    tt++;
    
    // Parameter 'interp_vlevels_to_height'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("interp_vlevels_to_height");
    tt->descr = tdrpStrDup("Option to interpolate onto height levels (km MSL).");
    tt->help = tdrpStrDup("(a) The vertical coords of the input data set MUST be PRESSURE levels. (b) Also, geopotential height must be available in the data set. This field is used for the interpolation.\n");
    tt->val_offset = (char *) &interp_vlevels_to_height - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'height_field_mdv_name'
    // ctype is 'char*'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = STRING_TYPE;
    tt->param_name = tdrpStrDup("height_field_mdv_name");
    tt->descr = tdrpStrDup("Name of geopotential height field in MDV file.");
    tt->help = tdrpStrDup("See output_fields array.\n");
    tt->val_offset = (char *) &height_field_mdv_name - &_start_;
    tt->single_val.s = tdrpStrDup("HGT");
    tt++;
    
    // Parameter 'height_levels'
    // ctype is 'double'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = DOUBLE_TYPE;
    tt->param_name = tdrpStrDup("height_levels");
    tt->descr = tdrpStrDup("Array of output height levels (km MSL).");
    tt->help = tdrpStrDup("The data fields are intepolated onto this set of height levels.");
    tt->array_offset = (char *) &_height_levels - &_start_;
    tt->array_n_offset = (char *) &height_levels_n - &_start_;
    tt->is_array = TRUE;
    tt->array_len_fixed = FALSE;
    tt->array_elem_size = sizeof(double);
    tt->array_n = 17;
    tt->array_vals = (tdrpVal_t *)
        tdrpMalloc(tt->array_n * sizeof(tdrpVal_t));
      tt->array_vals[0].d = 0;
      tt->array_vals[1].d = 1;
      tt->array_vals[2].d = 2;
      tt->array_vals[3].d = 3;
      tt->array_vals[4].d = 4;
      tt->array_vals[5].d = 5;
      tt->array_vals[6].d = 6;
      tt->array_vals[7].d = 7;
      tt->array_vals[8].d = 8;
      tt->array_vals[9].d = 9;
      tt->array_vals[10].d = 10;
      tt->array_vals[11].d = 11;
      tt->array_vals[12].d = 12;
      tt->array_vals[13].d = 13;
      tt->array_vals[14].d = 14;
      tt->array_vals[15].d = 15;
      tt->array_vals[16].d = 16;
    tt++;
    
    // Parameter 'compute_heights_from_pressure_levels'
    // ctype is 'tdrp_bool_t'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = BOOL_TYPE;
    tt->param_name = tdrpStrDup("compute_heights_from_pressure_levels");
    tt->descr = tdrpStrDup("Option to determine the heights from the pressure levels.");
    tt->help = tdrpStrDup("If TRUE, we use the ICAO standard atmosphere to compute the target heights from the pressure levels. In this case, the height_levels array is ignored.\n");
    tt->val_offset = (char *) &compute_heights_from_pressure_levels - &_start_;
    tt->single_val.b = pFALSE;
    tt++;
    
    // Parameter 'min_height_from_pressure_levels'
    // ctype is 'double'
    
    memset(tt, 0, sizeof(TDRPtable));
    tt->ptype = DOUBLE_TYPE;
    tt->param_name = tdrpStrDup("min_height_from_pressure_levels");
    tt->descr = tdrpStrDup("Minimum height when computing from pressure levels (km).");
    tt->help = tdrpStrDup("Any heights below this are removed when converting from pressure levels.");
    tt->val_offset = (char *) &min_height_from_pressure_levels - &_start_;
    tt->single_val.d = 0;
    tt++;
    
    // trailing entry has param_name set to NULL
    
    tt->param_name = NULL;
    
    return;
  
  }