Commit c8f4ea1d2f889283f37c6d79f5180db0a5317439

Authored by Elena.Budnik
1 parent 0fb01225

new cdf2nc, updateRemoteStart

src/CALLEXT/createVI.php
... ... @@ -80,8 +80,7 @@
80 80 $infoFile = $center->getDatasetInfo($remSetID);
81 81  
82 82 if ($infoFile)
83   - {
84   - echo "INFO ".$infoFile.PHP_EOL;
  83 + {
85 84 $baseMgr->setInfo($infoFile);
86 85 }
87 86  
... ... @@ -89,12 +88,13 @@
89 88  
90 89 if (!$infoFile && $ncFiles)
91 90 {
92   - echo "INFO ".$ncFiles[0].PHP_EOL;
93 91 $baseMgr->setInfo($ncFiles[0]);
94 92 }
95 93  
96   - $baseMgr->addRemoteData($remSetID, $ncFiles, $startIso, $stopIso);
97   -
  94 + $baseMgr->addRemoteData($remSetID, $ncFiles, $startIso, $stopIso);
  95 + // put real Global Start from file - IMPORTANT for new AMDA Kernel
  96 + $baseMgr->updateRemoteStart();
  97 +
98 98 // if ($verbose) error_log("Get dataset info for ".$remSetID." from ".$dataBaseID." returns ".$res.PHP_EOL, 3, log);
99 99  
100 100  
... ...
src/DATA/MANAGER/DDBaseMgr.php
... ... @@ -8,12 +8,12 @@
8 8 class DDBaseMgr
9 9 {
10 10  
11   - private $brief, $times, $info, $info_xml, $cache;
  11 + public $brief, $times, $info, $info_xml, $cache;
12 12 private $ViId, $remoteViId;
13 13 private $DDsysDoc, $DDsys;
14 14 private $base, $mission, $instrument;
15 15 private $min_sampling, $max_sampling;
16   - private $location, $ViDir;
  16 + public $location, $ViDir;
17 17 public $globalStart = null, $globalStop = null;
18 18  
19 19 function __construct()
... ... @@ -212,8 +212,7 @@ class DDBaseMgr
212 212  
213 213 protected function lockVi()
214 214 {
215   - // Stamp -> this directory is being updated
216   -
  215 + // Stamp -> this directory is being updated
217 216 touch($this->ViDir."/LOCK");
218 217  
219 218 // fprintf($STDERR,$ViDir." is LOCKED\n");
... ... @@ -260,6 +259,24 @@ class DDBaseMgr
260 259  
261 260 //system("gunzip -c ".$this->ViDir."/$ncFile.gz > $fullAliasName");
262 261 }
  262 +
  263 + public function updateRemoteStart()
  264 + {
  265 + $startStamp = shell_exec("GetStartTime ".$this->location.$this->times);
  266 + $startIso = date("Y-m-d\TH:i:s", $startStamp).substr(fmod($startStamp, 1),1,4)."Z";
  267 +
  268 + $xml_dom = new DomDocument("1.0");
  269 + $xml_dom->load($this->location."/".$this->info_xml);
  270 + $startNode = $xml_dom->getElementsByTagName("GlobalStart")->item(0);
  271 + $startNode->nodeValue = $startIso;
  272 +
  273 + $xml_dom->save($this->location."/".$this->info_xml);
  274 +
  275 + $currDir = getcwd();
  276 + chdir($this->location);
  277 + system("infoLocal2nc ".$this->info_xml." ".$this->info);
  278 + chdir($currDir);
  279 + }
263 280 }
264 281 ?>
265 282  
266 283 \ No newline at end of file
... ...
src/DATA/TOOLS/GetStartTime.c 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +
  2 +/** @file GetStartTime.c
  3 +* @brief Stand-alone executable <br> Returns real Start for given VI in DDBase <br>
  4 +*
  5 +* @details GetStartTime(string *) <br>
  6 +* @arg \c argv[1] Full name of *_times.nc
  7 +*
  8 +*/
  9 +
  10 +
  11 +#include <stdlib.h>
  12 +#include <stdio.h>
  13 +#include <string.h>
  14 +#include <time.h>
  15 +#include <math.h>
  16 +#include <netcdf.h>
  17 +#include <DD.h>
  18 +
  19 +
  20 +int DataID, StartID;
  21 +double StartStamp;
  22 +char StartT[TIMELENGTH];
  23 +size_t count[2] = {1L,TIMELENGTH};
  24 +size_t start[2] = {0L,0L};
  25 +
  26 +/*---------------- NC ERROR --------------------------------------*/
  27 +void nc_handle_error(int status)
  28 +{
  29 + fprintf(stderr, "%s\n", nc_strerror(status));
  30 + exit(1);
  31 +}
  32 +
  33 +/* ----------------------- MAIN ------------------------------------*/
  34 +int main(int argc, char *argv[])
  35 +{
  36 + int status, len;
  37 +
  38 + if (argc < 2){
  39 + fprintf(stderr,"Usage: GetStartTime *_times.nc\n");
  40 + exit(1);
  41 + }
  42 +
  43 + // Open VI_times.nc
  44 + if ((status = nc_open(argv[1], NC_NOWRITE, &DataID)) != NC_NOERR)
  45 + nc_handle_error(status);
  46 +
  47 + if ((status = nc_inq_varid(DataID, "StartTime", &StartID)) != NC_NOERR)
  48 + nc_handle_error(status);
  49 +
  50 + // Get The First Start
  51 + if((status = nc_get_vara_text(DataID, StartID, start, count, StartT)) != NC_NOERR)
  52 + nc_handle_error(status);
  53 +
  54 + StartStamp = DD_Time2Double(StartT);
  55 +
  56 + printf("%f\n", StartStamp);
  57 + if ((status = nc_close(DataID)) != NC_NOERR) nc_handle_error(status);
  58 +}
... ...
src/DATA/TOOLS/StartStop.c 0 → 100644
... ... @@ -0,0 +1,104 @@
  1 +
  2 +/** @file StartStop.c
  3 +* @brief Stand-alone executable <br> Returns real Start-Stop for VI in DDBase <br>
  4 +* Is used in DD Server WebServices <br>
  5 +* @details StartStop(string *, string *) <br>
  6 +* @arg \c argv[1] Full name of DDBase reference file <br>
  7 +* @arg \c argv[2] Virtual Instrument ID (DD notation) <br>
  8 +* Output: YYYYDDdayHHMMSSMLS-YYYYDDdayHHMMSSMLS
  9 +*
  10 +* @date 10.10.2007
  11 +* @version $Id: StartStop.c,v 1.3 2011/09/05 11:27:34 budnik Exp $
  12 +*/
  13 +
  14 +
  15 +#include <stdlib.h>
  16 +#include <stdio.h>
  17 +#include <string.h>
  18 +#include <time.h>
  19 +#include <math.h>
  20 +#include <netcdf.h>
  21 +#include <DD.h>
  22 +
  23 +
  24 +int DataID, RecID, VarID, StartID, StopID;
  25 +size_t RecNum;
  26 +char StartT[TIMELENGTH], StopT[TIMELENGTH], Var[128];
  27 +size_t count[2] = {1L,TIMELENGTH};
  28 +size_t start[2] = {0L,0L};
  29 +size_t countVar[2] = {1L,128L};
  30 +
  31 +/*---------------- NC ERROR --------------------------------------*/
  32 +void nc_handle_error(int status)
  33 +{
  34 + fprintf(stderr, "%s\n", nc_strerror(status));
  35 + exit(1);
  36 +}
  37 +
  38 +/* ----------------------- MAIN ------------------------------------*/
  39 + int main(int argc, char *argv[])
  40 +{
  41 +
  42 + int status, len;
  43 +
  44 + char Project[50],Instrument[50],Mode[50], RInstrName[100];
  45 +
  46 +
  47 + if (argc < 3)
  48 + {
  49 + fprintf(stderr,"Usage: StartStop reference_file_name DD_VI_ID\n");
  50 + exit(0);
  51 + }
  52 +
  53 +
  54 + if ((status = nc_open(argv[1], NC_NOWRITE, &DataID)) != NC_NOERR)
  55 + nc_handle_error(status);
  56 +
  57 + sscanf(argv[2], "%[^:]%*c%[^:]%*c%[^:]%*c",Project,
  58 + Instrument,
  59 + Mode);
  60 + sprintf(RInstrName,"%s_%s_%s\0",Project,Instrument,Mode);
  61 +
  62 + if ((status = nc_inq_varid(DataID,RInstrName,&VarID)) != NC_NOERR)
  63 + nc_handle_error(status);
  64 +
  65 + start[0] = 1;
  66 + if((status = nc_get_vara_text(DataID, VarID, start, countVar, Var)) != NC_NOERR)
  67 + nc_handle_error(status);
  68 +
  69 + len = strcspn(Var," "); Var[len] = '\0';
  70 +
  71 + if ((status = nc_close(DataID)) != NC_NOERR) nc_handle_error(status);
  72 +
  73 +// Open VI_times.nc
  74 +
  75 + if ((status = nc_open(Var, NC_NOWRITE, &DataID)) != NC_NOERR)
  76 + nc_handle_error(status);
  77 +
  78 + if ((status = nc_inq_dimid(DataID, "record", &RecID)) != NC_NOERR)
  79 + nc_handle_error(status);
  80 +
  81 +// Get Number of Records
  82 +
  83 + if ((status = nc_inq_dimlen(DataID, RecID, &RecNum)) != NC_NOERR)
  84 + nc_handle_error(status);
  85 +
  86 + if ((status = nc_inq_varid(DataID, "StartTime", &StartID)) != NC_NOERR)
  87 + nc_handle_error(status);
  88 + if ((status = nc_inq_varid(DataID, "StopTime", &StopID)) != NC_NOERR)
  89 + nc_handle_error(status);
  90 +
  91 +// Get The First Start and The Last Stop Times
  92 + start[0] = 0;
  93 +
  94 + if((status = nc_get_vara_text(DataID, StartID, start, count, StartT)) != NC_NOERR)
  95 + nc_handle_error(status);
  96 +
  97 + start[0] = RecNum-1;
  98 + if((status = nc_get_vara_text(DataID, StopID, start, count, StopT)) != NC_NOERR)
  99 + nc_handle_error(status);
  100 +
  101 + printf("%s-%s\n", StartT, StopT);
  102 + if ((status = nc_close(DataID)) != NC_NOERR) nc_handle_error(status);
  103 +
  104 +}
... ...
src/DECODERS/cdfnew2nc/CMakeLists.txt 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +
  2 +PROJECT(cdfnew2nc)
  3 +
  4 +include_directories(
  5 + ${DDCLIENTINCLUDE_DIR}
  6 + ${NETCDFINCLUDE_DIR}
  7 + ${libcdf_INCLUDE_DIR}
  8 +)
  9 +
  10 +#Configuration de l'exécutable
  11 +file(
  12 + GLOB_RECURSE
  13 + source_files
  14 + ./*
  15 +)
  16 +
  17 +ADD_EXECUTABLE (cdfnew2nc ${source_files} )
  18 +
  19 +target_link_libraries(
  20 + cdfnew2nc
  21 + ${DDCLIENTLIBRARY}
  22 + ${NETCDFLIBRARY}
  23 + ${libcdf_LIBRARIES}
  24 +)
  25 +
  26 +install (TARGETS cdfnew2nc DESTINATION bin)
... ...
src/DECODERS/cdfnew2nc/cdfnew2nc.c 0 → 100644
... ... @@ -0,0 +1,1994 @@
  1 +/**********************************************************
  2 + * Usage : amda-cdf-to-netcdf-w-false FileName [varToKeep1 varToKeep2 .....]
  3 + * No 'false dims' suppression
  4 + *********************************************************/
  5 +
  6 +#include <stdio.h>
  7 +#include <string.h>
  8 +#include <stdlib.h>
  9 +#include "netcdf.h"
  10 +#include "cdf.h"
  11 +
  12 +#define MAX_FILE_NAME_LEN 120 /* Max. file name length */
  13 +#define MAX_ATTRS 3000 /* Max # of CDF attributes */
  14 +#define UNKNOWN_DT -99 /* Unsupported CDF datatype indicator */
  15 +
  16 +#define DEFAULT_MAPPING_FILE "cdf_to_netcdf_mapping.dat"
  17 +#define MAX_REC_LENGTH NC_MAX_NAME+CDF_ATTR_NAME_LEN256+2
  18 + /* Max record length of DEFAULT_MAPPING_FILE */
  19 +
  20 +#define TRUE 1
  21 +#define FALSE 0
  22 +
  23 +/*************************************
  24 + Global variables and structures
  25 +**************************************/
  26 +CDFid id; /* CDF file ID */
  27 +int ncid; /* netCDF file ID */
  28 +
  29 +long nZvars, /* Number of zVariables in a CDF file */
  30 + nAttrs; /* Number of attributes (global & variable) in a CDF file */
  31 +
  32 +typedef struct ncdim { /* netCDF dimension structure */
  33 + char name[NC_MAX_NAME+1]; /* Dimension name */
  34 + int size; /* Dimension size */
  35 + int id; /* Dimension id */
  36 +} netcdfDimension;
  37 +
  38 +netcdfDimension ncDims[NC_MAX_DIMS]; /* max dimensions per netCDF file */
  39 +int totNCdims = 0; /* Total # of netCDF dimensions created */
  40 +
  41 +typedef struct cdfvar { /* CDF variable structure */
  42 + char name[CDF_VAR_NAME_LEN256+1];
  43 + long datatype;
  44 + long numElements; /* string length for CDF_CHAR, 1 otherwise */
  45 + long dimensionality; /* variable dimensionality */
  46 + long dimSizes[CDF_MAX_DIMS]; /* variable dimension sizes */
  47 + long recVariance; /* record variance */
  48 + long numRecs; /* # of records this variable contains */
  49 +} CDFvar;
  50 +
  51 +/****************************************************************************
  52 + * Arrays to hold the CDF-to-netCDF mapping information that are loaded
  53 + * from the default or user-define mapping file.
  54 + ****************************************************************************/
  55 +char netcdfAttrNames[MAX_ATTRS][NC_MAX_NAME];
  56 +char cdfAttrNames[MAX_ATTRS][CDF_ATTR_NAME_LEN256+1];
  57 +char comments[MAX_ATTRS][CDF_ATTR_NAME_LEN256+1];
  58 +
  59 +int totAttrsInMappingFile; /* # of attributes in the mapping file */
  60 +char mappingFile[CDF_PATHNAME_LEN]; /* Mapping file name */
  61 +
  62 +int DEBUG = FALSE;
  63 +
  64 +
  65 +
  66 +/**************************
  67 + Function prototypes
  68 +**************************/
  69 +int endsWith(char *, char *);
  70 +char * strlaststr(char *, char *);
  71 +void get_cdf_attribute(long, long, long, int);
  72 +void get_cdf_attr_data(char *, long, long, long, int);
  73 +char * cdf_str_datatype (long);
  74 +char * NC_datatype (nc_type);
  75 +nc_type get_netcdf_datatype (long);
  76 +void usage();
  77 +CDFid cdf_open(char *);
  78 +void read_cdf_file_info();
  79 +void get_zVariables(long *, int);
  80 +int create_netcdf_dimensions_attribute (int *);
  81 +void create_netcdf_dimensions_variable (CDFvar, long, int *, int *);
  82 +int create_netcdf_variable (CDFvar, long, int);
  83 +void get_cdf_variable_data (long, CDFvar, long);
  84 +void read_cdf_variable_data (long, long, long, long, long [], void *);
  85 +void removeFilepath();
  86 +void handle_netcdf_error (int);
  87 +void memory_error(char *, char *);
  88 +void cdf_status_handler (CDFstatus, char *);
  89 +void insufficient_memory(); /* used for debug */
  90 +char * getNextArgument (int, char *[], int);
  91 +void parseCmdLine (int, char *[]);
  92 +void errorMsg (char *);
  93 +void map_CDF_attr_to_netCDF (char *, char *);
  94 +void breakdown_DIMENSIONS_entry (char *, char **);
  95 +
  96 +#define AMDA
  97 +#ifdef AMDA
  98 +
  99 +#include "tools.h"
  100 +
  101 +char start_time [DD_TIME_STRING_LEN+1];
  102 +char stop_time [DD_TIME_STRING_LEN+1];
  103 +
  104 +#endif
  105 +
  106 +/****************************************************************************
  107 + NOTE:
  108 +
  109 + CDF has the following features that are not supported by netCDF:
  110 +
  111 + - CDF_EPOCH datatype (8-byte real number) that is used to store time
  112 + values referenced from a particular epoch that is
  113 + 01-Jan-0000 00:00:00.000. CDF_EPOCH values are the number of
  114 + milliseconds since the epoch described above.
  115 +
  116 + - CDF_EPOCH16 datatype (16-byte real number) that is used to store time
  117 + values referenced from a particular epoch that is
  118 + 01-Jan-0000 00:00:00.000.000.000.000. CDF_EPOCH16 values are the
  119 + number of milliseconds since the epoch described above.
  120 +
  121 + - CDF global attribute (not variable attribute) can have multiple
  122 + attribute entries and each entry can have a different datatype.
  123 +*****************************************************************************/
  124 +int main(int argc, char *argv[])
  125 +{
  126 + FILE *inFile; /* Pointer to the CDF-to-netCDF mapping file */
  127 + char rec[MAX_REC_LENGTH]; /* CDF-to-netCDF mapping record */
  128 +
  129 + /************************/
  130 + /* netCDF declaration */
  131 + /************************/
  132 + int status, /* netCDF status code */
  133 + dummy, i;
  134 +
  135 + char *ptr, fileName[CDF_PATHNAME_LEN];
  136 +
  137 + /**********************/
  138 + /* CDF declaration */
  139 + /**********************/
  140 + CDFstatus cstatus; /* CDF status code */
  141 + long attrId; /* CDF attribute ID */
  142 + long varId;
  143 + long *varsToGet;
  144 + int nVarsToGet;
  145 +
  146 + if (argc <= 1)
  147 + usage(); /* CDF input file name not specified */
  148 + else {
  149 + strcpy(fileName, argv[1]); /* Get the input file name */
  150 + strcpy(mappingFile, "UNSPECIFIED");
  151 + parseCmdLine(argc, argv);
  152 + if (strcmp(mappingFile, fileName) == 0)
  153 + errorMsg("** Error - either input file or mapping file is missing");
  154 + if (strcmp(mappingFile,"UNSPECIFIED") == 0)
  155 + strcpy(mappingFile, DEFAULT_MAPPING_FILE);
  156 + }
  157 +
  158 +#ifdef AMDA
  159 +
  160 +
  161 + status = check_version();
  162 +#endif
  163 + /***********************************************/
  164 + /* Load the CDF-to-netCDF mapping information */
  165 + /***********************************************/
  166 + if ((inFile = fopen(mappingFile, "r")) == NULL) {
  167 + printf ("WARNING : Cannot open file: %s **\n", mappingFile);
  168 + totAttrsInMappingFile = 0;
  169 + }
  170 + else {
  171 + totAttrsInMappingFile = 0;
  172 + while (fgets(rec, MAX_REC_LENGTH, inFile) != NULL) {
  173 + rec[strlen(rec)-1] = '\0'; /* Remove the newline character */
  174 +
  175 + /* Process the mapping record if it's not a comment */
  176 + if (rec[0] != '#' && rec[0] != ' ' && strlen(rec) > 0) {
  177 + sscanf(rec, "%s %s",
  178 + netcdfAttrNames[totAttrsInMappingFile],
  179 + cdfAttrNames[totAttrsInMappingFile]);
  180 + ptr = (char *) strstr(rec, "//");
  181 + if (ptr != NULL) {
  182 + ptr += 3;
  183 + strcpy (comments[totAttrsInMappingFile], ptr);
  184 + }
  185 + if (DEBUG)
  186 + printf("%s %s %s\n",
  187 + netcdfAttrNames[totAttrsInMappingFile],
  188 + cdfAttrNames[totAttrsInMappingFile],
  189 + comments[totAttrsInMappingFile]);
  190 + totAttrsInMappingFile++;
  191 + }
  192 + }
  193 + }
  194 + /***********************************************************
  195 + * Process the CDF information and create a netCDF file
  196 + ***********************************************************/
  197 +/* printf ("\nInput file name: %s\n", fileName); */
  198 + id = cdf_open (fileName);
  199 +
  200 + /* Remove the file path if it exists (/home/mydata.cdf => mydata.cdf). */
  201 + removeFilepath(fileName);
  202 +
  203 + if (endsWith(fileName,".cdf")) {
  204 + /* Strip off the .cdf file extension. */
  205 + ptr = (char *) strlaststr(fileName, ".cdf");
  206 + if (ptr != NULL) *ptr = '\0';
  207 + }
  208 + strcat(fileName, ".nc");
  209 + status = nc_create(fileName, NC_CLOBBER, &ncid);
  210 + if (status != NC_NOERR) handle_netcdf_error(status);
  211 + printf ("Output file name: %s\n", fileName);
  212 +
  213 + /***********************************************************************
  214 + * Get the number of dimensions, number of variables, number of global
  215 + * attributes.
  216 + *
  217 + * Note that the information retrieved from read_cdf_file_info are stored
  218 + * into the global variables defined at the top.
  219 + ***********************************************************************/
  220 + read_cdf_file_info ();
  221 + if (DEBUG) printf ("nAttrs=%ld, nZvars=%ld\n", nAttrs, nZvars);
  222 +
  223 + /* Get the CDF global attributes and create netCDF global attributes. */
  224 + if (DEBUG) printf ("Global attributes:\n");
  225 + dummy = -1;
  226 + for (attrId = 0; attrId < nAttrs; attrId++)
  227 + get_cdf_attribute(attrId, GLOBAL_SCOPE, (long) dummy, dummy);
  228 +
  229 + /* Write the placeholder attributes. */
  230 + for (i=0; i < totAttrsInMappingFile; i++) {
  231 + if (strcmp(cdfAttrNames[i],"*") == 0) {
  232 + status = nc_put_att_text (ncid,
  233 + NC_GLOBAL, /* vavriable ID */
  234 + netcdfAttrNames[i], /* Attribute name */
  235 + strlen(comments[i]), /* # of attr values */
  236 + comments[i]);
  237 + }
  238 + }
  239 +
  240 +
  241 + /* Process CDF variables and create netCDF variables */
  242 + if (argc > 2) {
  243 + varsToGet = (long *) malloc(sizeof(long)*(argc-2));
  244 + for (i = 2; i < argc; i++ ) {
  245 + status = CDFlib ( GET_, zVAR_NUMBER_, argv[i], &varId);
  246 + varsToGet[i-2] = varId;
  247 + }
  248 + nVarsToGet = argc-2;
  249 + }
  250 + else {
  251 + varsToGet = (long *) malloc(sizeof(long)*nZvars);
  252 + for (i = 0; i < nZvars; i++) varsToGet[i] = (long)i;
  253 + nVarsToGet = nZvars;
  254 + }
  255 + printf("NVARS %d\n",nVarsToGet);
  256 + if (nZvars > 0) get_zVariables(varsToGet, nVarsToGet);
  257 +
  258 +
  259 + /* Close the netCDF and CDF files */
  260 + cstatus = CDFlib (CLOSE_, CDF_, NULL_);
  261 + if (cstatus != CDF_OK) cdf_status_handler (cstatus, "CLOSE_, CDF_");
  262 +
  263 + status = nc_close(ncid);
  264 + if (status != NC_NOERR) handle_netcdf_error(status);
  265 +}
  266 +
  267 +
  268 +/*----------------------------------------------------------------------------
  269 + * TRUE if s1 ends with s2. Otherwise, FALSE is returned.
  270 + *---------------------------------------------------------------------------*/
  271 +int endsWith (char *s1, char *s2)
  272 +{
  273 + int i;
  274 + char *ps1, *ps2;
  275 +
  276 + if (strlen(s2) > strlen(s1))
  277 + return FALSE;
  278 +
  279 + ps1 = s1 + strlen(s1) - strlen(s2);
  280 + ps2 = s2;
  281 +
  282 + for (i=0; i < strlen(s2); i++)
  283 + if (*(ps1++) != *(ps2++))
  284 + return FALSE;
  285 +
  286 + return TRUE;
  287 +}
  288 +
  289 +
  290 +/*---------------------------------------------------------------------------------
  291 + * Find the last occurence of s2 in s1. If s21 is not found, s1 is returned.
  292 + *--------------------------------------------------------------------------------*/
  293 +char * strlaststr (char *s1, char *s2)
  294 +{
  295 + char *sc2, *psc1, *ps1;
  296 +
  297 + if (*s2 == '\0')
  298 + return((char *)s1);
  299 +
  300 + ps1 = s1 + strlen(s1);
  301 +
  302 + while(ps1 != s1) {
  303 + --ps1;
  304 + for (psc1 = ps1, sc2 = s2; ; )
  305 + if (*(psc1++) != *(sc2++))
  306 + break;
  307 + else if (*sc2 == '\0')
  308 + return ((char *)ps1);
  309 + }
  310 + return ((char *)NULL);
  311 +}
  312 +
  313 +
  314 +/*--------------------------------------------------------------------------
  315 + * This routine opens a CDF file
  316 + *-------------------------------------------------------------------------*/
  317 +CDFid cdf_open (char *fileName)
  318 +{
  319 + CDFstatus status;
  320 + CDFid id;
  321 + char msg[500];
  322 +
  323 + status = CDFlib (OPEN_, CDF_, fileName, /* in - file name to be opened */
  324 + &id, /* out - CDF file ID */
  325 + NULL_);
  326 +
  327 + if (status != CDF_OK) {
  328 + strcpy(msg, "OPEN_, CDF_, ");
  329 + strcat(msg, fileName);
  330 + cdf_status_handler (status, msg);
  331 + }
  332 + return id;
  333 +}
  334 +
  335 +
  336 +/*---------------------------------------------------------------------------
  337 + * This routine retrievs the following information:
  338 + *
  339 + * nAttr - number of attributes (including global and variable)
  340 + * nZvars - number of zVariables
  341 + *
  342 + * CDF file can have both rVariables (old style) and zVariables (new style)
  343 + * simultaneously. zVariable is a superset of rVariable, and it is a lot
  344 + * more efficient and offers all the functionality a rVariable offers and
  345 + * more. Treat all CDF variables as zVariables.
  346 + *--------------------------------------------------------------------------*/
  347 +void read_cdf_file_info ()
  348 +{
  349 + CDFstatus status;
  350 +
  351 + status = CDFlib (SELECT_, CDF_zMODE_, zMODEon2,
  352 + GET_, CDF_NUMATTRS_, &nAttrs,
  353 + CDF_NUMzVARS_, &nZvars,
  354 + NULL_);
  355 + if (status != CDF_OK) cdf_status_handler (status, "GET_, CDF_FILEINFO_");
  356 +}
  357 +
  358 +
  359 +/*----------------------------------------------------------------------------
  360 + * This routine retrieves the CDF attribute (global or variable) name
  361 + * and its data for the given CDF attribute ID.
  362 + *---------------------------------------------------------------------------*/
  363 +void get_cdf_attribute(long attrNum, /* in - CDF attribute number/id */
  364 + long scope, /* in - CDF attribute scope */
  365 + long cdfVarId, /* in - CDF variable number/id */
  366 + int netcdfVarId) /* in - netCDF variable ID */
  367 +{
  368 + int ncstatus, i, len;
  369 + long status, numEntries, datatype, attrScope, entryNum,
  370 + numElements;
  371 + nc_type ncDatatype; /* netCDF datatype */
  372 +
  373 + char *cPtr, attrName[CDF_ATTR_NAME_LEN256+1],
  374 + mappedAttrName[CDF_ATTR_NAME_LEN256+1];
  375 +
  376 + status = CDFlib (SELECT_, ATTR_, attrNum,
  377 + GET_, ATTR_NAME_, attrName,
  378 + ATTR_SCOPE_, &attrScope,
  379 + NULL_);
  380 + if (status != CDF_OK) cdf_status_handler (status, "SELECT_, ATTR_");
  381 +
  382 + /****************************************************************/
  383 + /* If the attribute scope is not the requested attribute scope */
  384 + /* (VARIABLE_SCOPE or GLOBAL_SCOPE), do not process the current */
  385 + /* attribute. */
  386 + /****************************************************************/
  387 + if (attrScope != scope) return;
  388 + if (strcmp(attrName, "DIMENSIONS_G") == 0 ||
  389 + strcmp(attrName, "DIMENSIONS_V") == 0) return;
  390 + map_CDF_attr_to_netCDF(attrName, mappedAttrName);
  391 + strcpy(attrName, mappedAttrName);
  392 +
  393 + if (attrScope == GLOBAL_SCOPE) {
  394 + status = CDFlib (GET_, ATTR_NUMgENTRIES_, &numEntries, NULL_);
  395 + if (status != CDF_OK)
  396 + cdf_status_handler (status, "GET_, ATTR_NUMgENTRIES_");
  397 + if (DEBUG) printf ("\t%s", attrName);
  398 +
  399 + /*********************************************************************
  400 + * While the CDF global attribute can have multiple entries of
  401 + * of different datatypes, the CDF variable attribute can only have
  402 + * one attribute entry. netCDF doesn't allow more than 1 attribute
  403 + * entry - handle this case
  404 + ********************************************************************/
  405 + for (entryNum=0; entryNum < numEntries; entryNum++) {
  406 + if (entryNum > 0) /* Attribute has more than 1 entry */
  407 + sprintf (attrName, "%s_%ld", mappedAttrName, entryNum);
  408 + status = CDFlib (SELECT_, gENTRY_, entryNum,
  409 + GET_, gENTRY_DATATYPE_, &datatype,
  410 + gENTRY_NUMELEMS_, &numElements,
  411 + NULL_);
  412 + if (status == NO_SUCH_ENTRY) return;
  413 + if (status != CDF_OK) cdf_status_handler(status,"GET_ATTR_INFO_");
  414 + get_cdf_attr_data (attrName, gENTRY_DATA_, datatype, numElements,
  415 + netcdfVarId);
  416 + }
  417 + }
  418 + else {
  419 + /*********************************************************************
  420 + * IMPORTANT NOTE:
  421 + * For the variable attribute, entry number is the variable ID.
  422 + *********************************************************************/
  423 + status = CDFlib (SELECT_, zENTRY_, cdfVarId,
  424 + GET_, zENTRY_DATATYPE_, &datatype,
  425 + zENTRY_NUMELEMS_, &numElements,
  426 + NULL_);
  427 + /******************************************************************/
  428 + /* If there's no attribute entry for the current attribute number */
  429 + /* selected, process the next attribute. */
  430 + /******************************************************************/
  431 + if (status == NO_SUCH_ENTRY) return;
  432 +
  433 + if (status != CDF_OK) cdf_status_handler (status,"GET_ATTR_INFO_");
  434 + if (DEBUG) printf ("\t%s", attrName);
  435 + if (attrName[strlen(attrName)-1] == (char) '_') {
  436 + char name2[CDF_ATTR_NAME_LEN256+1];
  437 + strcpy(name2, attrName);
  438 + name2[strlen(name2)-1] = (char) '\0';
  439 + status = CDFlib (GET_, ATTR_NUMBER_, name2, &attrNum,
  440 + NULL_);
  441 + if (status == CDF_OK) {
  442 + strcpy(attrName, name2);
  443 + map_CDF_attr_to_netCDF(attrName, mappedAttrName);
  444 + strcpy(attrName, mappedAttrName);
  445 + }
  446 + }
  447 + get_cdf_attr_data (attrName, zENTRY_DATA_, datatype, numElements,
  448 + netcdfVarId);
  449 + }
  450 +}
  451 +
  452 +
  453 +/*--------------------------------------------------------------------------
  454 + * This routine retrieves the CDF attribute data (a.k.a. attribute entries)
  455 + * and write its values to the target netCDF file.
  456 + *--------------------------------------------------------------------------*/
  457 +void get_cdf_attr_data (char *attrName, /* in - attribute name */
  458 + long entryData, /* in - type of attr entry data */
  459 + long datatype, /* in - attribute datatype */
  460 + long numElements, /* in - # of attribute values */
  461 + int netcdfVarId) /* in - netCDF variable ID */
  462 +{
  463 + char entryDataType[20], msg[100],
  464 + epString[EPOCH4_STRING_LEN+1],
  465 + ep16String[EPOCH16_4_STRING_LEN+1],
  466 + mappedAttrName[CDF_ATTR_NAME_LEN256+1],
  467 + tt2000String[TT2000_3_STRING_LEN+1];
  468 + double epoch16[2];
  469 +
  470 + nc_type ncDatatype; /* netCDF datatype */
  471 + int nc_status, /* netCDF status code */
  472 + varId; /* netCDF variable ID */
  473 + long status; /* CDF status code */
  474 +
  475 + char *cPtr;
  476 + signed char *scPtr;
  477 + unsigned char *uscPtr;
  478 + short *sPtr;
  479 + unsigned short *usPtr;
  480 + int *iPtr, i;
  481 + unsigned int *uiPtr;
  482 + long long *jPtr, aLonglong;
  483 + float *fPtr;
  484 + double *dPtr;
  485 +
  486 + /*************************************************
  487 + * entryData has one of following values:
  488 + *
  489 + * gENTRY_DATA_ - global attribute entry
  490 + * rENTRY_DATA_ - rVariable attribute entry
  491 + * zENTRY_DATA_ - zVariable attribute entry
  492 + *************************************************/
  493 + if (entryData == gENTRY_DATA_) {
  494 + varId = NC_GLOBAL;
  495 + strcpy(entryDataType, "gENTRY_DATA_");
  496 + }
  497 + else {
  498 + varId = netcdfVarId;
  499 + strcpy(entryDataType, "zENTRY_DATA_");
  500 + }
  501 + strcpy (msg, "get_cdf_attr_data, GET_, ");
  502 + strcat (msg, entryDataType);
  503 + strcat (msg, cdf_str_datatype(datatype));
  504 +
  505 + /* Map the CDF datatype to an appropriate netCDF datatype. */
  506 + ncDatatype = get_netcdf_datatype (datatype);
  507 +
  508 + /* Remove trailing blank spaces if there are any */
  509 + for (i=strlen(attrName)-1; i >= 0; i--) {
  510 + if (attrName[i] != ' ') {
  511 + attrName[i+1] = '\0';
  512 + break;
  513 + }
  514 + }
  515 + /* Replace blanks space(s) with underscore(s). */
  516 + for (i=0; i < strlen(attrName); i++) {
  517 + if (attrName[i] == ' ') attrName[i] = '_';
  518 + }
  519 +
  520 + switch (datatype) {
  521 + case CDF_CHAR:
  522 + case CDF_UCHAR:
  523 + cPtr = (char *) malloc(numElements * sizeof(char) + 1);
  524 + if (cPtr == NULL) memory_error("get_cdf_attr_data", "NC_CHAR");
  525 + status = CDFlib (GET_, entryData, cPtr, NULL_);
  526 + if (status != CDF_OK) cdf_status_handler (status, msg);
  527 + *(cPtr+numElements) = '\0'; /* End of string mark */
  528 + if (DEBUG) printf (" = \"%s\"", cPtr);
  529 + nc_status = nc_put_att_text(ncid, varId, attrName, numElements, cPtr);
  530 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  531 + free(cPtr);
  532 + break;
  533 +
  534 + case CDF_BYTE:
  535 + case CDF_INT1:
  536 + scPtr = (signed char *) malloc (sizeof(signed char) * numElements);
  537 + if (scPtr == NULL) memory_error("get_cdf_attr_data", "NC_BYTE");
  538 + status = CDFlib (GET_, entryData, scPtr, NULL_);
  539 + if (status != CDF_OK) cdf_status_handler (status, msg);
  540 + if (DEBUG) {
  541 + printf (" = ");
  542 + for (i=0; i < numElements; i++) {
  543 + if (i > 0) printf (", ");
  544 + printf ("%d", *(scPtr+i));
  545 + }
  546 + }
  547 + nc_status = nc_put_att_schar(ncid, varId, attrName, ncDatatype,
  548 + numElements, scPtr);
  549 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  550 + free (scPtr);
  551 + break;
  552 +
  553 + case CDF_UINT1:
  554 + uscPtr = (unsigned char *) malloc (sizeof(unsigned char) * numElements);
  555 + if (uscPtr == NULL) memory_error("get_cdf_attr_data", "NC_BYTE");
  556 + sPtr = (short *) malloc (sizeof(short) * numElements);
  557 + if (sPtr == NULL) memory_error("get_cdf_attr_data", "NC_SHORT");
  558 + status = CDFlib (GET_, entryData, uscPtr, NULL_);
  559 + if (status != CDF_OK) cdf_status_handler (status, msg);
  560 + if (DEBUG) {
  561 + printf (" = ");
  562 + for (i=0; i < numElements; i++) {
  563 + if (i > 0) printf (", ");
  564 + printf ("%d", *(uscPtr+i));
  565 + }
  566 + }
  567 + for (i = 0; i < numElements; ++i) {
  568 + *(sPtr+i) = (short) *(uscPtr+i);
  569 + }
  570 + nc_status = nc_put_att_short(ncid, varId, attrName, ncDatatype,
  571 + numElements, sPtr);
  572 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  573 + free (uscPtr);
  574 + free (sPtr);
  575 + break;
  576 +
  577 + case CDF_INT2:
  578 + sPtr = (short *) malloc (sizeof(short) * numElements);
  579 + if (sPtr == NULL) memory_error("get_cdf_attr_data", "NC_SHORT");
  580 + status = CDFlib (GET_, entryData, sPtr, NULL_);
  581 + if (status != CDF_OK) cdf_status_handler (status, msg);
  582 + if (DEBUG) {
  583 + printf (" = ");
  584 + for (i=0; i < numElements; i++) {
  585 + if (i > 0) printf (", ");
  586 + printf ("%hd", *(sPtr+i));
  587 + }
  588 + }
  589 + nc_status = nc_put_att_short(ncid, varId, attrName, ncDatatype,
  590 + numElements, sPtr);
  591 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  592 + free (sPtr);
  593 + break;
  594 +
  595 + case CDF_UINT2:
  596 + usPtr = (unsigned short *) malloc (sizeof(unsigned short) * numElements);
  597 + if (usPtr == NULL) memory_error("get_cdf_attr_data", "NC_SHORT");
  598 + iPtr = (int *) malloc (sizeof(int) * numElements);
  599 + if (iPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT");
  600 + status = CDFlib (GET_, entryData, usPtr, NULL_);
  601 + if (status != CDF_OK) cdf_status_handler (status, msg);
  602 + if (DEBUG) {
  603 + printf (" = ");
  604 + for (i=0; i < numElements; i++) {
  605 + if (i > 0) printf (", ");
  606 + printf ("%hu", *(usPtr+i));
  607 + }
  608 + }
  609 + for (i = 0; i < numElements; ++i) {
  610 + *(iPtr+i) = (int) *(usPtr+i);
  611 + }
  612 + nc_status = nc_put_att_int(ncid, varId, attrName, ncDatatype,
  613 + numElements, iPtr);
  614 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  615 + free (usPtr);
  616 + free (iPtr);
  617 + break;
  618 +
  619 + case CDF_INT4:
  620 + iPtr = (int *) malloc (sizeof(int) * numElements);
  621 + if (iPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT");
  622 + status = CDFlib (GET_, entryData, iPtr, NULL_);
  623 + if (status != CDF_OK) cdf_status_handler (status, msg);
  624 + if (DEBUG) {
  625 + printf (" = ");
  626 + for (i=0; i < numElements; i++) {
  627 + if (i > 0) printf (", ");
  628 + printf ("%d", *(iPtr+i));
  629 + }
  630 + }
  631 + nc_status = nc_put_att_int(ncid, varId, attrName, ncDatatype,
  632 + numElements, iPtr);
  633 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  634 + free (iPtr);
  635 + break;
  636 +
  637 + case CDF_UINT4:
  638 + uiPtr = (unsigned int *) malloc (sizeof(unsigned int) * numElements);
  639 + if (uiPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT");
  640 + dPtr = (double *) malloc (sizeof(double) * numElements);
  641 + if (dPtr == NULL) memory_error("get_cdf_attr_data", "NC_DOUBLE");
  642 + status = CDFlib (GET_, entryData, uiPtr, NULL_);
  643 + if (status != CDF_OK) cdf_status_handler (status, msg);
  644 + if (DEBUG) {
  645 + printf (" = ");
  646 + for (i=0; i < numElements; i++) {
  647 + if (i > 0) printf (", ");
  648 + printf ("%ud", *(uiPtr+i));
  649 + }
  650 + }
  651 + for (i = 0; i < numElements; ++i) {
  652 + *(dPtr+i) = (double) *(uiPtr+i);
  653 + }
  654 + nc_status = nc_put_att_double(ncid, varId, attrName, ncDatatype,
  655 + numElements, dPtr);
  656 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  657 + free (uiPtr);
  658 + free (dPtr);
  659 + break;
  660 +
  661 + case CDF_INT8:
  662 + jPtr = (long long *) malloc (sizeof(long long) * numElements);
  663 + if (jPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT64");
  664 + dPtr = (double *) malloc (sizeof(double) * numElements);
  665 + if (dPtr == NULL) memory_error("get_cdf_attr_data", "NC_DOUBLE");
  666 + status = CDFlib (GET_, entryData, jPtr, NULL_);
  667 + if (status != CDF_OK) cdf_status_handler (status, msg);
  668 + if (DEBUG) {
  669 + printf (" = ");
  670 + for (i=0; i < numElements; i++) {
  671 + if (i > 0) printf (", ");
  672 + printf ("%lld", *(jPtr+i));
  673 + }
  674 + }
  675 + for (i = 0; i < numElements; ++i) {
  676 + *(dPtr+i) = (double) *(jPtr+i);
  677 + }
  678 + nc_status = nc_put_att_double(ncid, varId, attrName, ncDatatype,
  679 + numElements, dPtr);
  680 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  681 + free (jPtr);
  682 + free (dPtr);
  683 + break;
  684 +
  685 + case CDF_FLOAT:
  686 + case CDF_REAL4:
  687 + fPtr = (float *) malloc (sizeof(float) * numElements);
  688 + if (fPtr == NULL) memory_error("get_cdf_attr_data", "NC_FLOAT");
  689 + status = CDFlib (GET_, entryData, fPtr, NULL_);
  690 + if (status != CDF_OK) cdf_status_handler (status, msg);
  691 + if (DEBUG) {
  692 + printf (" = ");
  693 + for (i=0; i < numElements; i++) {
  694 + if (i > 0) printf (", ");
  695 + printf ("%g", *(fPtr+i));
  696 + }
  697 + }
  698 + nc_status = nc_put_att_float(ncid, varId, attrName, ncDatatype,
  699 + numElements, fPtr);
  700 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  701 + free (fPtr);
  702 + break;
  703 +
  704 + case CDF_DOUBLE:
  705 + case CDF_REAL8:
  706 + dPtr = (double *) malloc (sizeof(double) * numElements);
  707 + if (dPtr == NULL) memory_error("get_cdf_attr_data", "NC_DOUBLE");
  708 + status = CDFlib (GET_, entryData, dPtr, NULL_);
  709 + if (status != CDF_OK) cdf_status_handler (status, msg);
  710 + if (DEBUG) {
  711 + printf (" = ");
  712 + for (i=0; i < numElements; i++) {
  713 + if (i > 0) printf (", ");
  714 + printf ("%g", *(dPtr+i));
  715 + }
  716 + }
  717 + nc_status = nc_put_att_double(ncid, varId, attrName,
  718 + ncDatatype, numElements, dPtr);
  719 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  720 + free (dPtr);
  721 + break;
  722 +
  723 + case CDF_EPOCH: /* 8-byte real number */
  724 + dPtr = (double *) malloc (sizeof(double) * numElements);
  725 + if (dPtr == NULL) memory_error("get_cdf_attr_data", "CDF_EPOCH");
  726 + status = CDFlib (GET_, entryData, dPtr, NULL_);
  727 + if (status != CDF_OK) cdf_status_handler (status, msg);
  728 + if (DEBUG) printf (" = ");
  729 + for (i=0; i < numElements; i++) {
  730 + encodeEPOCH4 (* (dPtr+i), epString);
  731 + nc_status = nc_put_att_text(ncid, varId, attrName, EPOCH4_STRING_LEN, epString);
  732 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  733 + if (DEBUG) {
  734 + if (i > 0) printf (", ");
  735 + printf ("%s", epString);
  736 + if (i == (numElements -1)) printf ("\n");
  737 + }
  738 + }
  739 + free (dPtr);
  740 + break;
  741 +
  742 + case CDF_EPOCH16: /* 16-byte real number */
  743 + dPtr = (double *) malloc (sizeof(double) * numElements * 2);
  744 + if (dPtr == NULL) memory_error("get_cdf_attr_data", "CDF_EPOCH16");
  745 + status = CDFlib (GET_, entryData, dPtr, NULL_);
  746 + if (status != CDF_OK) cdf_status_handler (status, msg);
  747 + if (DEBUG) printf (" = ");
  748 + for (i=0; i < numElements; i++) {
  749 + epoch16[0] = *(dPtr+i*2);
  750 + epoch16[1] = *(dPtr+i*2+1);
  751 + encodeEPOCH16_4 (epoch16, ep16String);
  752 + nc_status = nc_put_att_text(ncid, varId, attrName,
  753 + strlen(ep16String), ep16String);
  754 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  755 + if (DEBUG) {
  756 + if (i > 0) printf (", ");
  757 + printf ("%s", ep16String);
  758 + if (i == (numElements -1)) printf ("\n");
  759 + }
  760 + }
  761 + free (dPtr);
  762 + break;
  763 +
  764 + case CDF_TIME_TT2000: /* 8-byte integer number */
  765 + jPtr = (long long *) malloc (sizeof(long long) * numElements);
  766 + if (jPtr == NULL) memory_error("get_cdf_attr_data", "CDF_TIME_TT2000");
  767 + status = CDFlib (GET_, entryData, jPtr, NULL_);
  768 + if (status != CDF_OK) cdf_status_handler (status, msg);
  769 + if (DEBUG) printf (" = ");
  770 + for (i=0; i < numElements; i++) {
  771 + encodeTT2000 (*(jPtr+i), tt2000String);
  772 + nc_status = nc_put_att_text(ncid, varId, attrName,
  773 + TT2000_3_STRING_LEN, tt2000String);
  774 + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status);
  775 + if (DEBUG) {
  776 + if (i > 0) printf (", ");
  777 + printf ("%s", tt2000String);
  778 + if (i == (numElements -1)) printf ("\n");
  779 + }
  780 + }
  781 + free (jPtr);
  782 + break;
  783 +
  784 + default:
  785 + printf ("** Error in get_cdf_attribute: bad data type");
  786 + }
  787 + if (DEBUG) printf (" ;\n");
  788 +}
  789 +
  790 +
  791 +/*--------------------------------------------------------------------------
  792 + * Get the zVariables in the CDF file.
  793 + *--------------------------------------------------------------------------*/
  794 +void get_zVariables(long *vars, int nvars)
  795 +{
  796 + CDFstatus status;
  797 + int i, ncstatus, createUnlimitedDim, unlimitedDimId,
  798 + attrId, netcdfVarId, bypass;
  799 + char netcdfDimName[NC_MAX_NAME+1]; /* netCDF dimension name */
  800 + long holdDim, holdDim0;
  801 + long varId, ncVarId;
  802 + CDFvar var;
  803 +
  804 + if (DEBUG) printf ("\n");
  805 +
  806 + createUnlimitedDim = TRUE;
  807 + bypass = FALSE;
  808 +
  809 + for (i = 0; i < nvars; i++) {
  810 +
  811 + varId = vars[i];
  812 + ncVarId = (long)i;
  813 + status = CDFlib (SELECT_,zVAR_, varId,
  814 + GET_, zVAR_NAME_, var.name,
  815 + zVAR_DATATYPE_, &var.datatype,
  816 + zVAR_NUMELEMS_, &var.numElements,
  817 + zVAR_NUMDIMS_, &var.dimensionality,
  818 + zVAR_DIMSIZES_, var.dimSizes,
  819 + zVAR_NUMRECS_, &var.numRecs,
  820 + zVAR_RECVARY_, &var.recVariance,
  821 + NULL_);
  822 + if (status != CDF_OK) cdf_status_handler (status, "GET_, zVARS_");
  823 +
  824 + if (DEBUG) {
  825 + printf ("var name = %s, %s/%ld, %ld:[",
  826 + var.name, cdf_str_datatype(var.datatype),
  827 + var.numElements, var.dimensionality);
  828 + for (i=0; i < var.dimensionality; i++) {
  829 + if (i > 0) printf (",");
  830 + printf ("%ld", var.dimSizes[i]);
  831 + }
  832 + printf("], numRecs = %ld\n", var.numRecs);
  833 + }
  834 +
  835 + if (varId == 0)
  836 + bypass = create_netcdf_dimensions_attribute (&unlimitedDimId);
  837 + if (!bypass)
  838 + create_netcdf_dimensions_variable (var, ncVarId, &createUnlimitedDim,
  839 + &unlimitedDimId);
  840 + netcdfVarId = create_netcdf_variable (var, ncVarId, unlimitedDimId);
  841 +
  842 + /* Leave the define mode before adding data */
  843 + ncstatus = nc_enddef(ncid);
  844 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  845 +
  846 + get_cdf_variable_data (varId, var, ncVarId);
  847 +
  848 + /* Enter the define mode before writing netCDF variable attributes */
  849 + /* and creating a variable. */
  850 + ncstatus = nc_redef(ncid);
  851 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  852 +
  853 + /* Get the variable attributes */
  854 + for (attrId = 0; attrId < nAttrs; attrId++)
  855 + get_cdf_attribute(attrId, VARIABLE_SCOPE, varId, netcdfVarId);
  856 + }
  857 +#ifdef AMDA
  858 +
  859 + if (set_file_time_coverage() == -1) {
  860 +
  861 + printf ("ERROR : unable to compute file time coverage\n");
  862 + }
  863 +
  864 + if (rename_time_variable () == -1) {
  865 +
  866 + printf ("ERROR : uname to rename time variable\n");
  867 + }
  868 +
  869 +
  870 +#endif
  871 +}
  872 +
  873 +
  874 +/*--------------------------------------------------------------------------
  875 + * This routine creates all netCDF dimensions from a global attribute if
  876 + * such attribute exists (likely the CDF is created by netcdf-to-cdf
  877 + * converter). It returns TRUE if dimensions are creaated, FLASE otherwise.
  878 + *--------------------------------------------------------------------------*/
  879 +int create_netcdf_dimensions_attribute (int *unlimitedDimId)
  880 +{
  881 + int status, /* netCDF status code */
  882 + i, id, value, len;
  883 + long numElems, numEntries;
  884 + char netcdfDimName[NC_MAX_NAME+1]; /* netCDF dimension name */
  885 + char valueStr[20+1];
  886 + char *ptr, entry[NC_MAX_NAME + 20 + 1];
  887 + CDFstatus statusC;
  888 +
  889 + statusC = CDFlib (SELECT_, ATTR_NAME_, "DIMENSIONS_G",
  890 + GET_, ATTR_NUMgENTRIES_, &numEntries,
  891 + NULL_);
  892 + if (statusC != CDF_OK) return FALSE;
  893 + /* A CDF file that was created by netCDF-to-cdf */
  894 + for (i = 0; i < (int) numEntries; ++i) {
  895 + statusC = CDFlib (SELECT_, ATTR_NAME_, "DIMENSIONS_G",
  896 + gENTRY_, (long) i,
  897 + GET_, gENTRY_DATA_, entry,
  898 + gENTRY_NUMELEMS_, &numElems,
  899 + NULL_);
  900 + if (statusC != CDF_OK) continue;
  901 + entry[numElems] = (char) '\0';
  902 + ptr = strstr(entry, "=");
  903 + if (ptr == NULL) continue;
  904 + len = (int) (ptr - entry);
  905 + strncpy(netcdfDimName, entry, len);
  906 + strcpy(valueStr, ptr+1);
  907 + netcdfDimName[len] = (char) '\0';
  908 + if (strcmp(valueStr, "UNLIMITED") == 0) {
  909 + status = nc_def_dim(ncid, /* in */
  910 + netcdfDimName, /* in */
  911 + NC_UNLIMITED, /* in */
  912 + unlimitedDimId); /* out */
  913 + } else {
  914 + if (sscanf(valueStr, "%d", &value) != 1) continue;
  915 + status = nc_def_dim(ncid, /* in */
  916 + netcdfDimName, /* in */
  917 + value, /* in */
  918 + &id); /* out */
  919 + }
  920 + if (status != NC_NOERR) handle_netcdf_error(status);
  921 + }
  922 + return TRUE;
  923 +}
  924 +
  925 +
  926 +/*--------------------------------------------------------------------------
  927 + * This routine creates a netCDF dimension(s) from a variable.
  928 + *--------------------------------------------------------------------------*/
  929 +void create_netcdf_dimensions_variable (CDFvar var, long varNum,
  930 + int *createUnlimitedDim,
  931 + int *unlimitedDimId)
  932 +{
  933 + int status, /* netCDF status code */
  934 + i, j, dimensionCreated, id;
  935 + long dimensionality;
  936 + char netcdfDimName[NC_MAX_NAME+1]; /* netCDF dimension name */
  937 + CDFstatus statusC;
  938 +
  939 + dimensionality = var.dimensionality;
  940 +
  941 + if (var.datatype == CDF_CHAR) {
  942 + var.dimSizes[dimensionality] = var.numElements;
  943 + dimensionality++;
  944 + }
  945 + else if (var.datatype == CDF_EPOCH) {
  946 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  947 + dimensionality++;
  948 + }
  949 + else if (var.datatype == CDF_EPOCH16) {
  950 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  951 + dimensionality++;
  952 + }
  953 + else if (var.datatype == CDF_TIME_TT2000) {
  954 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  955 + dimensionality++;
  956 + }
  957 +
  958 + if (*createUnlimitedDim) {
  959 + if (var.recVariance == VARY) {
  960 + status = nc_def_dim(ncid, "Time", NC_UNLIMITED,unlimitedDimId);
  961 + if (status != NC_NOERR) handle_netcdf_error(status);
  962 + *createUnlimitedDim = FALSE;
  963 + }
  964 + }
  965 + for (i=0; i < dimensionality; i++) {
  966 + dimensionCreated = FALSE;
  967 + for (j=0; j < totNCdims; j++) {
  968 + if (ncDims[j].size == var.dimSizes[i]) {
  969 + dimensionCreated = TRUE;
  970 + break;
  971 + }
  972 + }
  973 + if (!dimensionCreated && var.dimSizes[i] > 1) {
  974 + ncDims[totNCdims].size = var.dimSizes[i];
  975 + sprintf (netcdfDimName, "dim%d", totNCdims);
  976 + strcpy(ncDims[totNCdims].name, netcdfDimName);
  977 + status = nc_def_dim(ncid, /* in */
  978 + ncDims[totNCdims].name, /* in */
  979 + ncDims[totNCdims].size, /* in */
  980 + &ncDims[totNCdims].id); /* out */
  981 + if (status != NC_NOERR) handle_netcdf_error(status);
  982 + totNCdims++;
  983 + }
  984 + }
  985 +}
  986 +
  987 +
  988 +/*--------------------------------------------------------------------------
  989 + * This routine creates a netCDF variable.
  990 + *--------------------------------------------------------------------------*/
  991 +int create_netcdf_variable (CDFvar var, /* in - CDF variable */
  992 + long varNum, /* in - CDF variable id */
  993 + int unlimitedDimId) /* in - unlimited dim ID */
  994 +{
  995 + int status, /* netCDF status code */
  996 + i, j, k, id,
  997 + varId, /* netCDF variable ID */
  998 + nc_dimensionality,
  999 + dimensionality, /* netCDF dimensionality */
  1000 + dims[NC_MAX_DIMS]; /* netCDF dimensions */
  1001 + nc_type datatype;
  1002 + char *entry;
  1003 + char **dimStrings;
  1004 + int count = 0;
  1005 + long numElems;
  1006 + CDFstatus statusC;
  1007 +
  1008 + dimensionality = var.dimensionality;
  1009 + datatype = get_netcdf_datatype (var.datatype);
  1010 +
  1011 + /*********************************************************************
  1012 + * While the string value is treated as 0-d in CDF, it is treated as
  1013 + * 1-D in netCDF.
  1014 + *********************************************************************/
  1015 + if (var.datatype == CDF_CHAR) {
  1016 + var.dimSizes[dimensionality] = var.numElements;
  1017 + dimensionality++;
  1018 + }
  1019 +
  1020 + /*********************************************************************
  1021 + * In CDF, CDF_EPOCH, CDF_EPOCH16 and CDF_TIME_TT2000 are used to
  1022 + * store a date and time value into a 8-byte real, 16-byte real or
  1023 + * 8-byte integer value, respectively. Since netCDF
  1024 + * doesn't support EPOCH, the CDF EPOCH variable needs to be translated
  1025 + * as a string value.
  1026 + *********************************************************************/
  1027 + else if (var.datatype == CDF_EPOCH) {
  1028 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  1029 + dimensionality++;
  1030 + }
  1031 + else if (var.datatype == CDF_EPOCH16) {
  1032 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  1033 + dimensionality++;
  1034 + }
  1035 + else if (var.datatype == CDF_TIME_TT2000) {
  1036 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  1037 + dimensionality++;
  1038 + }
  1039 +
  1040 + /************************************************************************
  1041 + * If CDF's record variance is true, then the netCDF's first dimension
  1042 + * reflects the record number.
  1043 + ************************************************************************/
  1044 + k = 0;
  1045 + if (var.recVariance == VARY) {
  1046 + dims[k++] = unlimitedDimId;
  1047 + dimensionality++;
  1048 + }
  1049 +
  1050 + entry = (char *) malloc ((size_t) (dimensionality+1) * NC_MAX_NAME +
  1051 + dimensionality + 1 );
  1052 + statusC = CDFlib (SELECT_, ATTR_NAME_, "DIMENSIONS_V",
  1053 + zENTRY_, varNum,
  1054 + GET_, zENTRY_DATA_, entry,
  1055 + zENTRY_NUMELEMS_, &numElems,
  1056 + NULL_);
  1057 + if (statusC == CDF_OK) { /* A CDF converted from netCDF-to-cdf. */
  1058 + entry[numElems] = (char) '\0';
  1059 + for (i = 0; i < strlen(entry); ++i) if (entry[i] == (char) ',') ++ count;
  1060 + ++count;
  1061 + dimStrings = (char **) malloc (sizeof(char *) * count);
  1062 + for (i = 0; i < count; ++i) {
  1063 + dimStrings[i] = (char *) malloc(NC_MAX_NAME + 1);
  1064 + }
  1065 + breakdown_DIMENSIONS_entry(entry, dimStrings);
  1066 + k = 0;
  1067 + for (j = 0; j < count; ++j) {
  1068 + status = nc_inq_dimid(ncid, dimStrings[j], &id);
  1069 + if (status != NC_NOERR) handle_netcdf_error(status);
  1070 + dims[k++] = id;
  1071 + }
  1072 + for (i = 0; i < count; ++i) free (dimStrings[i]);
  1073 + free (dimStrings);
  1074 + } else {
  1075 + for (i=0; i < dimensionality; i++) {
  1076 + for (j=0; j < totNCdims; j++) {
  1077 + if (ncDims[j].size == var.dimSizes[i]) {
  1078 + dims[k++] = ncDims[j].id;
  1079 + break;
  1080 + }
  1081 + }
  1082 + }
  1083 + }
  1084 + free (entry);
  1085 + /* Remove trailing blank spaces if there are any */
  1086 + for (i=strlen(var.name)-1; i >= 0; i--) {
  1087 + if (var.name[i] != ' ') {
  1088 + var.name[i+1] = '\0';
  1089 + break;
  1090 + }
  1091 + }
  1092 +
  1093 + /* Replace blank space(s) with underscore(s). */
  1094 + for (i=0; i < strlen(var.name); i++) {
  1095 + if (var.name[i] == ' ') var.name[i] = '_';
  1096 + }
  1097 +
  1098 +/* Exclude "false" dimension */
  1099 + nc_dimensionality = dimensionality;
  1100 +// for (i=0; i < dimensionality; i++) {
  1101 +// if ( var.dimSizes[i] == 1 ) {
  1102 +// nc_dimensionality--;
  1103 +// j = i;
  1104 +// break;
  1105 +// }
  1106 +// }
  1107 +
  1108 + /* Create a netCDF variable. */
  1109 + status = nc_def_var(ncid, var.name, datatype, nc_dimensionality, dims, &varId);
  1110 + if (status != NC_NOERR) handle_netcdf_error(status);
  1111 + return varId;
  1112 +}
  1113 +
  1114 +
  1115 +/*--------------------------------------------------------------------------
  1116 + * Get the CDF variable data and write the data just read into the
  1117 + * netCDF variable created in create_netcdf_variable.
  1118 + *--------------------------------------------------------------------------*/
  1119 +void get_cdf_variable_data (long varId, /* in - variable ID/number */
  1120 + CDFvar var, /* in - CDF variable structure */
  1121 + long ncVarId) /* in - netCDF variable ID/number */
  1122 +{
  1123 + CDFstatus status; /* CDF status code */
  1124 + int ncstatus; /* netCDF status code */
  1125 + char epString[EPOCH4_STRING_LEN+1];
  1126 + char ep16String[EPOCH16_4_STRING_LEN+1];
  1127 + char tt2000String[TT2000_3_STRING_LEN+1];
  1128 + double epoch16[2];
  1129 +
  1130 + size_t start[NC_MAX_DIMS], /* index for where to read first */
  1131 + count[NC_MAX_DIMS]; /* # of values to read */
  1132 +
  1133 + int i, j, k, divide,
  1134 + dimensionality,
  1135 + numValues; /* # of values on each record */
  1136 +char * ptr;
  1137 + char *cPtr;
  1138 + signed char *scPtr;
  1139 + unsigned char *ucPtr;
  1140 + short *sPtr;
  1141 + unsigned short *usPtr;
  1142 + int *iPtr;
  1143 + unsigned int *uiPtr;
  1144 + long long *jPtr, aLonglong;
  1145 + float *fPtr;
  1146 + double *dPtr;
  1147 + long recNo,
  1148 + totRecs, /* total # of records to read */
  1149 + numRecsLeftToRead,
  1150 + numRecs; /* # of records to read and write at a time */
  1151 +
  1152 + j = 0;
  1153 + start[0] = 0;
  1154 + numValues = 1; /* # of values on each CDF record */
  1155 +
  1156 + if (var.recVariance == VARY) { /* Treat it as a netCDF record variable */
  1157 + start[j] = 0; /* start record # */
  1158 + count[j++] = var.numRecs; /* # of records to write */
  1159 + }
  1160 +
  1161 + dimensionality = var.dimensionality;
  1162 +
  1163 + if (var.datatype == CDF_CHAR) {
  1164 + var.dimSizes[dimensionality] = var.numElements;
  1165 + dimensionality++;
  1166 + }
  1167 +
  1168 + /*********************************************************************
  1169 + * In CDF, CDF_EPOCH and CDF_EPOCH16 are used to store a date and time
  1170 + * value into a 8-byte and 16-byte real value, respectively. Since netCDF
  1171 + * doesn't support EPOCH, the CDF EPOCH variable needs to be translated
  1172 + * as a string value. Added newer 8-byte integer CDF_TIME_TT2000 data.
  1173 + *********************************************************************/
  1174 + else if (var.datatype == CDF_EPOCH) {
  1175 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  1176 + dimensionality++;
  1177 + }
  1178 + else if (var.datatype == CDF_EPOCH16) {
  1179 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  1180 + dimensionality++;
  1181 + }
  1182 + else if (var.datatype == CDF_TIME_TT2000) {
  1183 + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN;
  1184 + dimensionality++;
  1185 + }
  1186 +
  1187 + for (i=0; i < dimensionality; i++) {
  1188 + start[j] = 0;
  1189 + if (var.dimSizes[i] > 1) count[j++] = var.dimSizes[i];
  1190 + numValues *= var.dimSizes[i];
  1191 + }
  1192 +
  1193 + if (var.datatype == CDF_EPOCH)
  1194 + numValues /= DD_TIME_STRING_LEN;
  1195 + else if (var.datatype == CDF_EPOCH16)
  1196 + numValues /= DD_TIME_STRING_LEN;
  1197 + else if (var.datatype == CDF_TIME_TT2000)
  1198 + numValues /= DD_TIME_STRING_LEN;
  1199 +
  1200 + totRecs = var.numRecs; /* total # of records for this var */
  1201 + numRecsLeftToRead = var.numRecs;
  1202 +
  1203 + while (numRecsLeftToRead > 0) {
  1204 + recNo = start[0]; /* record # to start reading */
  1205 + divide = 1;
  1206 + numRecs = numRecsLeftToRead; /* # of records to read at a time */
  1207 +
  1208 + switch (var.datatype) {
  1209 + case CDF_CHAR:
  1210 + case CDF_UCHAR:
  1211 + cPtr = NULL;
  1212 + while (cPtr == NULL) {
  1213 + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs);
  1214 + if (cPtr == NULL) {
  1215 + if (DEBUG) insufficient_memory();
  1216 + divide *= 2;
  1217 + numRecs = totRecs / divide;
  1218 + }
  1219 + }
  1220 + read_cdf_variable_data (varId,
  1221 + recNo, /* starting record # */
  1222 + numRecs, /* # of records to read */
  1223 + var.dimensionality,
  1224 + var.dimSizes, /* dimesion sizes */
  1225 + cPtr); /* data pointer */
  1226 + if (DEBUG) {
  1227 + printf (" retrieved CDF data = \n");
  1228 + for (k=0; k < numRecs; k++) {
  1229 + printf("\"");
  1230 + for (i=0; i < numValues; i++)
  1231 + printf ("%c", *(cPtr+(k*numValues+i)));
  1232 + printf("\"\n");
  1233 + }
  1234 + }
  1235 +
  1236 + start[0] = 0;
  1237 + start[1] = 0;
  1238 + if (var.recVariance == VARY) {
  1239 + count[0] = numRecs;
  1240 + }
  1241 +
  1242 + if (DEBUG) {
  1243 + for (i=0; i < dimensionality; i++)
  1244 + printf (" start[%d] = %ld, count[%d] = %ld\n",
  1245 + i, start[i], i, count[i]);
  1246 + }
  1247 + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr);
  1248 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1249 + if (DEBUG && ncstatus != NC_NOERR) {
  1250 + if (ncstatus != NC_NOERR)
  1251 + printf (" Error putting data...\n");
  1252 + else
  1253 + printf (" Done putting data...\n");
  1254 + }
  1255 + free (cPtr);
  1256 + break;
  1257 +
  1258 + case CDF_BYTE:
  1259 + case CDF_INT1:
  1260 + scPtr = NULL;
  1261 + while (scPtr == NULL) {
  1262 + scPtr =
  1263 + (signed char *) malloc (sizeof(signed char)*numValues*numRecs);
  1264 + if (scPtr == NULL) {
  1265 + if (DEBUG) insufficient_memory();
  1266 + divide *= 2;
  1267 + numRecs = totRecs / divide;
  1268 + }
  1269 + }
  1270 + read_cdf_variable_data (varId,
  1271 + recNo, /* starting record # */
  1272 + numRecs, /* # of records to read */
  1273 + var.dimensionality,
  1274 + var.dimSizes, /* dimesion sizes */
  1275 + scPtr); /* data pointer */
  1276 + if (var.recVariance == VARY)
  1277 + count[0] = numRecs;
  1278 + ncstatus = nc_put_vara_schar(ncid, ncVarId, start, count, scPtr);
  1279 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1280 + free (scPtr);
  1281 + break;
  1282 +
  1283 + case CDF_UINT1:
  1284 + ucPtr = NULL;
  1285 + sPtr = NULL;
  1286 + while (ucPtr == NULL || sPtr == NULL) {
  1287 + ucPtr =
  1288 + (unsigned char *) malloc (sizeof(unsigned char)*numValues*numRecs);
  1289 + sPtr =
  1290 + (short *) malloc (sizeof(short)*numValues*numRecs);
  1291 + if (ucPtr == NULL || sPtr == NULL) {
  1292 + if (DEBUG) insufficient_memory();
  1293 + divide *= 2;
  1294 + numRecs = totRecs / divide;
  1295 + }
  1296 + }
  1297 + read_cdf_variable_data (varId,
  1298 + recNo, /* starting record # */
  1299 + numRecs, /* # of records to read */
  1300 + var.dimensionality,
  1301 + var.dimSizes, /* dimesion sizes */
  1302 + ucPtr); /* data pointer */
  1303 + if (var.recVariance == VARY)
  1304 + count[0] = numRecs;
  1305 + for (j = 0; j < numValues*numRecs; ++j) {
  1306 + *(sPtr+j) = (short) *(ucPtr+j);
  1307 + }
  1308 + ncstatus = nc_put_vara_short(ncid, ncVarId, start, count, sPtr);
  1309 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1310 + free (ucPtr);
  1311 + free (sPtr);
  1312 + break;
  1313 +
  1314 + case CDF_INT2:
  1315 + sPtr = NULL;
  1316 + while (sPtr == NULL) {
  1317 + sPtr = (short *) malloc (sizeof(short) * numValues * numRecs);
  1318 + if (sPtr == NULL) {
  1319 + if (DEBUG) insufficient_memory();
  1320 + divide *= 2;
  1321 + numRecs = totRecs / divide;
  1322 + }
  1323 + }
  1324 + read_cdf_variable_data (varId,
  1325 + recNo, /* starting record # */
  1326 + numRecs, /* # of records to read */
  1327 + var.dimensionality,
  1328 + var.dimSizes, /* dimesion sizes */
  1329 + sPtr); /* data pointer */
  1330 + if (var.recVariance == VARY)
  1331 + count[0] = numRecs;
  1332 + ncstatus = nc_put_vara_short(ncid, ncVarId, start, count, sPtr);
  1333 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1334 + free (sPtr);
  1335 + break;
  1336 +
  1337 + case CDF_UINT2:
  1338 + usPtr = NULL;
  1339 + iPtr = NULL;
  1340 + while (usPtr == NULL || iPtr == NULL) {
  1341 + usPtr = (unsigned short *) malloc (sizeof(unsigned short) * numValues * numRecs);
  1342 + iPtr = (int *) malloc (sizeof(int) * numValues * numRecs);
  1343 + if (usPtr == NULL || iPtr == NULL) {
  1344 + if (DEBUG) insufficient_memory();
  1345 + divide *= 2;
  1346 + numRecs = totRecs / divide;
  1347 + }
  1348 + }
  1349 + read_cdf_variable_data (varId,
  1350 + recNo, /* starting record # */
  1351 + numRecs, /* # of records to read */
  1352 + var.dimensionality,
  1353 + var.dimSizes, /* dimesion sizes */
  1354 + usPtr); /* data pointer */
  1355 + if (var.recVariance == VARY)
  1356 + count[0] = numRecs;
  1357 + for (j = 0; j < numValues*numRecs; ++j) {
  1358 + *(iPtr+j) = (int) *(usPtr+j);
  1359 + }
  1360 + ncstatus = nc_put_vara_int(ncid, ncVarId, start, count, iPtr);
  1361 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1362 + free (usPtr);
  1363 + free (iPtr);
  1364 + break;
  1365 +
  1366 + case CDF_INT4:
  1367 + iPtr = NULL;
  1368 + while (iPtr == NULL) {
  1369 + iPtr = (int *) malloc (sizeof(int) * numValues * numRecs);
  1370 + if (iPtr == NULL) {
  1371 + if (DEBUG) insufficient_memory();
  1372 + divide *= 2;
  1373 + numRecs = totRecs / divide;
  1374 + }
  1375 + }
  1376 + read_cdf_variable_data (varId,
  1377 + recNo, /* starting record # */
  1378 + numRecs, /* # of records to read */
  1379 + var.dimensionality,
  1380 + var.dimSizes, /* dimesion sizes */
  1381 + iPtr); /* data pointer */
  1382 + if (var.recVariance == VARY)
  1383 + count[0] = numRecs;
  1384 + ncstatus = nc_put_vara_int(ncid, ncVarId, start, count, iPtr);
  1385 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1386 + free (iPtr);
  1387 + break;
  1388 +
  1389 + case CDF_UINT4:
  1390 + uiPtr = NULL;
  1391 + dPtr = NULL;
  1392 + while (uiPtr == NULL || dPtr == NULL) {
  1393 + uiPtr = (unsigned int *) malloc (sizeof(unsigned int) * numValues * numRecs);
  1394 + dPtr = (double *) malloc (sizeof(double) * numValues * numRecs);
  1395 + if (iPtr == NULL) {
  1396 + if (DEBUG) insufficient_memory();
  1397 + divide *= 2;
  1398 + numRecs = totRecs / divide;
  1399 + }
  1400 + }
  1401 + read_cdf_variable_data (varId,
  1402 + recNo, /* starting record # */
  1403 + numRecs, /* # of records to read */
  1404 + var.dimensionality,
  1405 + var.dimSizes, /* dimesion sizes */
  1406 + uiPtr); /* data pointer */
  1407 + if (var.recVariance == VARY)
  1408 + count[0] = numRecs;
  1409 + for (j = 0; j < numValues*numRecs; ++j) {
  1410 + *(dPtr+j) = (double) *(uiPtr+j);
  1411 + }
  1412 + ncstatus = nc_put_vara_double(ncid, ncVarId, start, count, dPtr);
  1413 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1414 + free (uiPtr);
  1415 + free (dPtr);
  1416 + break;
  1417 +
  1418 + case CDF_INT8:
  1419 + jPtr = NULL;
  1420 + dPtr = NULL;
  1421 + while (jPtr == NULL || dPtr == NULL) {
  1422 + jPtr = (long long *) malloc (sizeof(long long) * numValues * numRecs);
  1423 + dPtr = (double *) malloc (sizeof(double) * numValues * numRecs);
  1424 + if (jPtr == NULL || dPtr == NULL) {
  1425 + if (DEBUG) insufficient_memory();
  1426 + divide *= 2;
  1427 + numRecs = totRecs / divide;
  1428 + }
  1429 + }
  1430 + read_cdf_variable_data (varId,
  1431 + recNo, /* starting record # */
  1432 + numRecs, /* # of records to read */
  1433 + var.dimensionality,
  1434 + var.dimSizes, /* dimesion sizes */
  1435 + jPtr); /* data pointer */
  1436 + if (var.recVariance == VARY)
  1437 + count[0] = numRecs;
  1438 + for (j = 0; j < numValues*numRecs; ++j) {
  1439 + *(dPtr+j) = (double) *(jPtr+j);
  1440 + }
  1441 + ncstatus = nc_put_vara_double(ncid, ncVarId, start, count, dPtr);
  1442 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1443 + free (jPtr);
  1444 + free (dPtr);
  1445 + break;
  1446 +
  1447 + case CDF_FLOAT:
  1448 + case CDF_REAL4:
  1449 + fPtr = NULL;
  1450 + while (fPtr == NULL) {
  1451 + fPtr = (float *) malloc (sizeof(float) * numValues * numRecs);
  1452 + if (fPtr == NULL) {
  1453 + if (DEBUG) insufficient_memory();
  1454 + divide *= 2;
  1455 + numRecs = totRecs / divide;
  1456 + }
  1457 + }
  1458 + read_cdf_variable_data (varId,
  1459 + recNo, /* starting record # */
  1460 + numRecs, /* # of records to read */
  1461 + var.dimensionality,
  1462 + var.dimSizes, /* dimesion sizes */
  1463 + fPtr); /* data pointer */
  1464 + if (var.recVariance == VARY)
  1465 + count[0] = numRecs;
  1466 + ncstatus = nc_put_vara_float(ncid, ncVarId, start, count, fPtr);
  1467 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1468 + free (fPtr);
  1469 + break;
  1470 +
  1471 + case CDF_DOUBLE:
  1472 + case CDF_REAL8:
  1473 + dPtr = NULL;
  1474 + while (dPtr == NULL) {
  1475 + dPtr = (double *) malloc (sizeof(double) * numValues * numRecs);
  1476 + if (dPtr == NULL) {
  1477 + if (DEBUG) insufficient_memory();
  1478 + divide *= 2;
  1479 + numRecs = totRecs / divide;
  1480 + }
  1481 + }
  1482 + read_cdf_variable_data (varId,
  1483 + recNo, /* starting record # */
  1484 + numRecs, /* # of records to read */
  1485 + var.dimensionality,
  1486 + var.dimSizes, /* dimesion sizes */
  1487 + dPtr); /* data pointer */
  1488 + if (var.recVariance == VARY)
  1489 + count[0] = numRecs;
  1490 +
  1491 + ncstatus = nc_put_vara_double(ncid, ncVarId, start, count, dPtr);
  1492 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1493 + free (dPtr);
  1494 + break;
  1495 +
  1496 + case CDF_EPOCH:
  1497 + dPtr = NULL;
  1498 + while (dPtr == NULL) {
  1499 + dPtr = (double *) malloc (sizeof(double)*numValues*numRecs);
  1500 + if (dPtr == NULL) {
  1501 + if (DEBUG) insufficient_memory();
  1502 + divide *= 2;
  1503 + numRecs = totRecs / divide;
  1504 + }
  1505 + }
  1506 + read_cdf_variable_data (varId,
  1507 + recNo, /* starting record # */
  1508 + numRecs, /* # of records to read */
  1509 + var.dimensionality,
  1510 + var.dimSizes, /* dimesion sizes */
  1511 + dPtr); /* data pointer */
  1512 + if (var.recVariance == VARY)
  1513 + count[0] = numRecs;
  1514 +
  1515 + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs *
  1516 + DD_TIME_STRING_LEN + 1);
  1517 + if (cPtr == NULL)
  1518 + memory_error("get_cdf_variable_data", "CDF_EPOCH");
  1519 +
  1520 + ptr = cPtr;
  1521 +
  1522 + /* Get all the EPOCH values into a single string. */
  1523 + for (i=0; i < numRecs * numValues; i++) {
  1524 + encodeEPOCH4 (*(dPtr+i), epString);
  1525 + strcpy (ptr, isotime_to_dd_time (epString));
  1526 + ptr += DD_TIME_STRING_LEN;
  1527 + }
  1528 + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr);
  1529 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1530 + free (cPtr);
  1531 + free (dPtr);
  1532 + break;
  1533 +
  1534 + case CDF_EPOCH16:
  1535 + dPtr = NULL;
  1536 + while (dPtr == NULL) {
  1537 + dPtr = (double *) malloc (sizeof(double) * numValues*numRecs*2);
  1538 + if (dPtr == NULL) {
  1539 + if (DEBUG) insufficient_memory();
  1540 + divide *= 2;
  1541 + numRecs = totRecs / divide;
  1542 + }
  1543 + }
  1544 + read_cdf_variable_data (varId,
  1545 + recNo, /* starting record # */
  1546 + numRecs, /* # of records to read */
  1547 + var.dimensionality,
  1548 + var.dimSizes, /* dimesion sizes */
  1549 + dPtr); /* data pointer */
  1550 + if (var.recVariance == VARY)
  1551 + count[0] = numRecs;
  1552 +
  1553 + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs *
  1554 + DD_TIME_STRING_LEN + 1);
  1555 + if (cPtr == NULL)
  1556 + memory_error("get_cdf_variable_data", "CDF_EPOCH16");
  1557 +
  1558 + ptr = cPtr;
  1559 +
  1560 + /* Get all the EPOCH16 values into a single string. */
  1561 + for (i=0; i < numRecs * numValues; i++) {
  1562 + epoch16[0] = *(dPtr+i*2);
  1563 + epoch16[1] = *(dPtr+i*2+1);
  1564 + encodeEPOCH16_4 (epoch16, ep16String);
  1565 + strcpy (ptr, isotime_to_dd_time (ep16String));
  1566 + ptr += DD_TIME_STRING_LEN;
  1567 + }
  1568 + printf(" %d %d\n", count[0], count[1]);
  1569 + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr);
  1570 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1571 + free (cPtr);
  1572 + free (dPtr);
  1573 + break;
  1574 +
  1575 + case CDF_TIME_TT2000:
  1576 + jPtr = NULL;
  1577 + while (jPtr == NULL) {
  1578 + jPtr = (long long *) malloc (sizeof(long long)*numValues*numRecs);
  1579 + if (jPtr == NULL) {
  1580 + if (DEBUG) insufficient_memory();
  1581 + divide *= 2;
  1582 + numRecs = totRecs / divide;
  1583 + }
  1584 + }
  1585 + read_cdf_variable_data (varId,
  1586 + recNo, /* starting record # */
  1587 + numRecs, /* # of records to read */
  1588 + var.dimensionality,
  1589 + var.dimSizes, /* dimesion sizes */
  1590 + jPtr); /* data pointer */
  1591 + if (var.recVariance == VARY)
  1592 + count[0] = numRecs;
  1593 +
  1594 + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs *
  1595 + DD_TIME_STRING_LEN + 1);
  1596 + if (cPtr == NULL)
  1597 + memory_error("get_cdf_variable_data", "CDF_EPOCH");
  1598 +
  1599 + ptr = cPtr;
  1600 +
  1601 + /* Get all the TT2000 values into a single string. */
  1602 + for (i=0; i < numRecs * numValues; i++) {
  1603 + // encodeTT2000 (*(jPtr+i), tt2000String);
  1604 + CDF_TT2000_to_UTC_string(*(jPtr+i), tt2000String, 3);
  1605 + strcpy (ptr, isotime_to_dd_time (tt2000String));
  1606 + ptr += DD_TIME_STRING_LEN;
  1607 + }
  1608 + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr);
  1609 + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus);
  1610 + free (cPtr);
  1611 + free (jPtr);
  1612 + break;
  1613 +
  1614 + default:
  1615 + printf ("** Error in getVarData: bad type");
  1616 + }
  1617 +
  1618 + numRecsLeftToRead = totRecs - numRecs;
  1619 + if (numRecsLeftToRead > 0) {
  1620 + totRecs = numRecsLeftToRead;
  1621 + start[0] = numRecs;
  1622 + }
  1623 + } /* end of the 'while' loop */
  1624 +
  1625 +}
  1626 +
  1627 +
  1628 +/*--------------------------------------------------------------------------
  1629 + * This routine returns the string representation of the given CDF
  1630 + * datatype.
  1631 + *--------------------------------------------------------------------------*/
  1632 +char * cdf_str_datatype (long type)
  1633 +{
  1634 + switch (type) {
  1635 + case CDF_BYTE:
  1636 + return "CDF_BYTE";
  1637 +
  1638 + case CDF_INT1:
  1639 + return "CDF_INT1";
  1640 +
  1641 + case CDF_CHAR:
  1642 + return "CDF_CHAR";
  1643 +
  1644 + case CDF_INT2:
  1645 + return "CDF_INT2";
  1646 +
  1647 + case CDF_UCHAR:
  1648 + return "CDF_UCHAR";
  1649 +
  1650 + case CDF_UINT1:
  1651 + return "CDF_UINT1";
  1652 +
  1653 + case CDF_INT4:
  1654 + return "CDF_INT4";
  1655 +
  1656 + case CDF_INT8:
  1657 + return "CDF_INT8";
  1658 +
  1659 + case CDF_UINT2:
  1660 + return "CDF_UINT2";
  1661 +
  1662 + case CDF_FLOAT:
  1663 + return "CDF_FLOAT";
  1664 +
  1665 + case CDF_REAL4:
  1666 + return "CDF_REAL4";
  1667 +
  1668 + case CDF_DOUBLE:
  1669 + return "CDF_DOUBLE";
  1670 +
  1671 + case CDF_REAL8:
  1672 + return "CDF_REAL8";
  1673 +
  1674 + case CDF_UINT4:
  1675 + return "CDF_UINT4";
  1676 +
  1677 + case CDF_EPOCH:
  1678 + return "CDF_EPOCH";
  1679 +
  1680 + case CDF_EPOCH16:
  1681 + return "CDF_EPOCH16";
  1682 +
  1683 + case CDF_TIME_TT2000:
  1684 + return "CDF_TIME_TT2000";
  1685 +
  1686 + default:
  1687 + return "BAD_CDF_TYPE";
  1688 +
  1689 + }
  1690 +}
  1691 +
  1692 +
  1693 +/*--------------------------------------------------------------------------
  1694 + * This routine returns the string representation of the given netCDF
  1695 + * datatype.
  1696 + *--------------------------------------------------------------------------*/
  1697 +char * NC_datatype (nc_type type)
  1698 +{
  1699 + switch (type) {
  1700 + case NC_BYTE:
  1701 + return "byte";
  1702 + case NC_CHAR:
  1703 + return "char";
  1704 + case NC_SHORT:
  1705 + return "short";
  1706 + case NC_INT:
  1707 + return "int";
  1708 + case NC_FLOAT:
  1709 + return "float";
  1710 + case NC_DOUBLE:
  1711 + return "double";
  1712 + default:
  1713 + return "UNKNOWN";
  1714 + }
  1715 +}
  1716 +
  1717 +
  1718 +/*--------------------------------------------------------------------------
  1719 + * This routine returns the netCDF datatype for the given CDF datatype.
  1720 + * All unsigned types are bumped up, either to double the size, or to
  1721 + * a double. CDF's epoch types are converted to string.
  1722 + *--------------------------------------------------------------------------*/
  1723 +nc_type get_netcdf_datatype (long type)
  1724 +{
  1725 + nc_type netcdf_type;
  1726 +
  1727 + switch (type) {
  1728 + case CDF_BYTE:
  1729 + case CDF_INT1:
  1730 + netcdf_type = NC_BYTE;
  1731 + break;
  1732 +
  1733 + case CDF_CHAR:
  1734 + case CDF_UCHAR:
  1735 + case CDF_EPOCH:
  1736 + case CDF_EPOCH16:
  1737 + case CDF_TIME_TT2000:
  1738 + netcdf_type = NC_CHAR;
  1739 + break;
  1740 +
  1741 + case CDF_UINT1:
  1742 + netcdf_type = NC_SHORT;
  1743 + break;
  1744 +
  1745 + case CDF_INT2:
  1746 + netcdf_type = NC_SHORT;
  1747 + break;
  1748 +
  1749 + case CDF_UINT2:
  1750 + netcdf_type = NC_INT;
  1751 + break;
  1752 +
  1753 + case CDF_INT4:
  1754 + netcdf_type = NC_INT;
  1755 + break;
  1756 +
  1757 + case CDF_UINT4:
  1758 + netcdf_type = NC_DOUBLE;
  1759 + break;
  1760 +
  1761 + case CDF_INT8:
  1762 + netcdf_type = NC_DOUBLE;
  1763 + break;
  1764 +
  1765 + case CDF_FLOAT:
  1766 + case CDF_REAL4:
  1767 + netcdf_type = NC_FLOAT;
  1768 + break;
  1769 +
  1770 + case CDF_DOUBLE:
  1771 + case CDF_REAL8:
  1772 + netcdf_type = NC_DOUBLE;
  1773 + break;
  1774 +
  1775 + default: {
  1776 + printf ("** ERROR: Unknown CDF datatype\n");
  1777 + exit (1);
  1778 + }
  1779 + }
  1780 + return netcdf_type;
  1781 +}
  1782 +
  1783 +
  1784 +/*---------------------------------------------------------------------------
  1785 + * Read the CDF variable data for the given CDF variable number.
  1786 + *---------------------------------------------------------------------------*/
  1787 +void read_cdf_variable_data (long varNum, /* CDF variable number */
  1788 + long recNo, /* record # for start reading */
  1789 + long recCount, /* # of records to read */
  1790 + long dim, /* CDF dimensionality */
  1791 + long dimSizes[], /* CDF dimesion sizes */
  1792 + void *data) /* data pointer */
  1793 +{
  1794 + CDFstatus status;
  1795 + int i;
  1796 + long recInterval, /* No. of recors to skip */
  1797 + dimIndices[CDF_MAX_DIMS], /* Beginning location of the array */
  1798 + /* to be dumped */
  1799 + dimIntervals[CDF_MAX_DIMS]; /* No. of elements to skip */
  1800 +
  1801 + recInterval = 1L; /* # of records to skip between writes */
  1802 +
  1803 + for (i=0; i < dim; i++) {
  1804 + dimIndices[i] = 0; /* Dump data from the beginning of array */
  1805 + dimIntervals[i] = 1; /* Dump all the elements in the array */
  1806 + }
  1807 +
  1808 + status = CDFlib (SELECT_,zVAR_, varNum,
  1809 + zVAR_RECNUMBER_, recNo,
  1810 + zVAR_RECCOUNT_, recCount,
  1811 + zVAR_RECINTERVAL_, recInterval,
  1812 + zVAR_DIMINDICES_, dimIndices,
  1813 + zVAR_DIMCOUNTS_, dimSizes,
  1814 + zVAR_DIMINTERVALS_, dimIntervals,
  1815 + GET_, zVAR_HYPERDATA_, data,
  1816 + NULL_);
  1817 + if (status != CDF_OK) cdf_status_handler (status, "GET_, zVAR_HYPERDATA_");
  1818 +}
  1819 +
  1820 +
  1821 +
  1822 +/*--------------------------------------------------------------------------
  1823 + * Remove the filepath from a file name.
  1824 + *
  1825 + * Example:
  1826 + * /home/data/mydata.txt => mydata.txt
  1827 + *--------------------------------------------------------------------------*/
  1828 +void removeFilepath (char *fileName) {
  1829 + char *ptr;
  1830 +
  1831 + ptr = (char *) strrchr(fileName, '/'); /* Unix file path separator */
  1832 + if (ptr != NULL) {
  1833 + ptr++;
  1834 + strcpy(fileName, ptr);
  1835 + }
  1836 + else {
  1837 + ptr = (char *) strrchr(fileName, '\\'); /* Windows file separator */
  1838 + if (ptr != NULL) {
  1839 + ptr++;
  1840 + strcpy(fileName, ptr);
  1841 + }
  1842 + }
  1843 +}
  1844 +
  1845 +
  1846 +/*--------------------------------------------------------------------------
  1847 + * Handles a CDF error.
  1848 + *--------------------------------------------------------------------------*/
  1849 +void cdf_status_handler (CDFstatus status, char *source)
  1850 +{
  1851 + char message[CDF_STATUSTEXT_LEN+1];
  1852 +
  1853 + CDFerror (status, message); /* Get the appropriate message */
  1854 +
  1855 + if (status < CDF_WARN) {
  1856 + printf ("An error has occurred, halting...\n");
  1857 + printf ("%s\n", message);
  1858 + printf ("** Error source: %s\n", source);
  1859 + exit (status);
  1860 + }
  1861 + else if (status < CDF_OK) {
  1862 + printf ("Warning, function may not have compeleted as expected...\n");
  1863 + printf ("%s\n", message);
  1864 + }
  1865 + else if (status > CDF_OK) {
  1866 + printf ("Function compeleted successfully, but be advised that...\n");
  1867 + printf ("%s\n", message);
  1868 + }
  1869 +}
  1870 +
  1871 +
  1872 +/*--------------------------------------------------------------------------
  1873 + * Handles a netCDF error.
  1874 + *--------------------------------------------------------------------------*/
  1875 +void handle_netcdf_error(int status) {
  1876 + fprintf(stderr, "%s\n", nc_strerror(status));
  1877 +}
  1878 +
  1879 +
  1880 +/*--------------------------------------------------------------------------
  1881 + * Handles a memory allocation error.
  1882 + *--------------------------------------------------------------------------*/
  1883 +void memory_error(char *source, char *datatype) {
  1884 + printf ("** Memory allocation error occurred in %s. data type = %s",
  1885 + source, datatype);
  1886 + exit (1);
  1887 +}
  1888 +
  1889 +void insufficient_memory () {
  1890 + printf("Insufficient memory to load all the records at once");
  1891 +}
  1892 +
  1893 +
  1894 +/*--------------------------------------------------------------------------*/
  1895 +void usage()
  1896 +{
  1897 + printf ("\nDescription:\n");
  1898 + printf (" This program converts a CDF file into a netCDF file.");
  1899 + printf ("\n");
  1900 + printf ("Usage: cdf-to-netCDF -[Options] <CDF file name>\n");
  1901 + printf ("\n");
  1902 + printf ("Options:\n");
  1903 + printf (" -map <mapfile> Use the user-supplied mapping file.\n");
  1904 + printf (" -debug Show debug information.\n");
  1905 + printf ("\n");
  1906 + printf ("Examples of usage: \n");
  1907 + printf ("1) cdf-to-netCDF test.cdf\n");
  1908 + printf (" will convert the test.cdf file into the test.nc file.\n\n");
  1909 + printf ("2) cdf-to-netCDF -map mymap.dat test.cdf\n");
  1910 + printf (" will convert the test.cdf file into the test.nc file using\n");
  1911 + printf (" the user-supplied mapping file called 'mymap.dat' instead\n");
  1912 + printf (" of using the default cdf-to-netCDF mapping file.\n");
  1913 + printf ("\n");
  1914 + exit(1);
  1915 +}
  1916 +
  1917 +void parseCmdLine (int argc, char *argv[])
  1918 +{
  1919 + int i;
  1920 + char *nextArg;
  1921 +
  1922 + for (i=0; i < argc; i++) {
  1923 + if (strcmp(argv[i],"-map") == 0) {
  1924 + nextArg = getNextArgument(argc, argv, i);
  1925 + if (strcmp(nextArg, "No next argument") == 0 ||
  1926 + *(nextArg+0) == '-')
  1927 + errorMsg("** Error - mapping file is not defined");
  1928 + else
  1929 + strcpy(mappingFile, nextArg);
  1930 + }
  1931 + else if (strcmp(argv[i],"-debug") == 0)
  1932 + DEBUG = TRUE;
  1933 + }
  1934 +}
  1935 +
  1936 +
  1937 +char * getNextArgument (int argc, char *argv[], int currentIndex)
  1938 +{
  1939 + char *nextArg, msg[30];
  1940 + int nextIndex;
  1941 +
  1942 + nextIndex = currentIndex+1;
  1943 + if (nextIndex == argc) {
  1944 + strcpy (msg, "No next argument");
  1945 + nextArg = msg;
  1946 + }
  1947 + else
  1948 + nextArg = argv[nextIndex];
  1949 +
  1950 + return nextArg;
  1951 +}
  1952 +
  1953 +void errorMsg (char *msg)
  1954 +{
  1955 + printf ("%s\n", msg);
  1956 + exit (1);
  1957 +}
  1958 +
  1959 +
  1960 +void map_CDF_attr_to_netCDF (char *searchAttr, /* in - CDF attr name */
  1961 + char *mappedAttrName) /* out - netCDF attr name */
  1962 +{
  1963 + int i;
  1964 +
  1965 + strcpy(mappedAttrName, searchAttr);
  1966 +
  1967 + for (i=0; i < totAttrsInMappingFile; i++) {
  1968 + if (strcmp(cdfAttrNames[i], searchAttr) == 0) {
  1969 + strcpy(mappedAttrName, netcdfAttrNames[i]);
  1970 + break;
  1971 + }
  1972 + }
  1973 +}
  1974 +
  1975 +void breakdown_DIMENSIONS_entry (char *entry, /* in - a DIMENSIONS entry */
  1976 + char **dimStrings) /* out - dimesion names */
  1977 +{
  1978 + char *ptr, *ptr1;
  1979 + int i = 0, j;
  1980 +
  1981 + ptr = entry;
  1982 + ptr1 = strstr(ptr, ",");
  1983 + i = 0;
  1984 + while (ptr1 != NULL) {
  1985 + j = ptr1 - ptr;
  1986 + strncpy (dimStrings[i], ptr, (size_t)j);
  1987 + dimStrings[i][j] = (char) '\0';
  1988 + ptr = ptr1 + 1;
  1989 + ptr1 = strstr(ptr, ",");
  1990 + ++i;
  1991 + }
  1992 + if (ptr != NULL) strcpy (dimStrings[i], ptr);
  1993 +}
  1994 +
... ...
src/DECODERS/cdfnew2nc/tools.c 0 → 100644
... ... @@ -0,0 +1,391 @@
  1 +/*******************************************************************************
  2 + *
  3 + * tools.c - 2014/01/29
  4 + *
  5 + * Some specific functions requiered for AMDA converter
  6 + *
  7 + */
  8 +#include <stdio.h>
  9 +#include <string.h>
  10 +
  11 +#include "tools.h"
  12 +#include "netcdf.h"
  13 +#include "cdf.h"
  14 +
  15 +#ifndef TRUE
  16 +#define TRUE 1
  17 +#define FALSE (! TRUE)
  18 +#endif
  19 +
  20 +#define VERSION_MIN "3.4.0"
  21 +
  22 +#define START_TIME "StartTime"
  23 +#define STOP_TIME "StopTime"
  24 +#define TIME_VAR "Time"
  25 +
  26 +extern CDFid id; /* CDF file identifier */
  27 +
  28 +extern int ncid; /* netCDF file identifier */
  29 +
  30 +extern long nZvars; /* Number of CDF zVariables */
  31 +
  32 +/*******************************************************************************
  33 + *
  34 + * Check version of CDFlib greated or equal to 3.5 (needed for TT2000)
  35 + */
  36 +int check_version (void)
  37 +{
  38 + long version, release, increment;
  39 + char subincrement;
  40 + int status;
  41 + char str_version [30];
  42 +
  43 + status = CDFgetLibraryVersion (& version, & release, & increment, & subincrement);
  44 +
  45 + if (status < CDF_OK) {
  46 +
  47 + printf ("ERROR : unable to get CDFlib version\n");
  48 + goto EXIT;
  49 + }
  50 +
  51 + sprintf (str_version, "%d.%d.%d-%c", version, release, increment, subincrement);
  52 +
  53 + printf ("CDFlib version : %s\n", str_version);
  54 +
  55 + if (strcmp (str_version, VERSION_MIN) < 0) {
  56 +
  57 + printf ("ERROR : version %s < %s", str_version, VERSION_MIN);
  58 + }
  59 +
  60 +EXIT: return status;
  61 +}
  62 +
  63 +
  64 +
  65 +/*******************************************************************************
  66 + *
  67 + * Check if the given year is a leap one
  68 + */
  69 +int leap_year (int year)
  70 +{
  71 + if ((year % 400) == 0) return TRUE;
  72 + if ((year % 100) == 0) return FALSE;
  73 + if ((year % 4) == 0) return TRUE;
  74 + return FALSE;
  75 +}
  76 +
  77 +
  78 +/*******************************************************************************
  79 + *
  80 + * Convert an ISO 8601 date time to a DD Time string
  81 + */
  82 +char * isotime_to_dd_time (char * input)
  83 +{
  84 + static char output [DD_TIME_STRING_LEN + 1];
  85 + int i, count, ddd;
  86 + int yy, mm, dd, h, m, s, ms;
  87 + int duration[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  88 +
  89 + count = sscanf (input, "%d-%d-%dT%d:%d:%d.%3d", & yy, & mm, & dd, & h, & m, & s, &ms);
  90 +
  91 + if (count != 7) {
  92 + printf ("Unexpected time format: %s\n", input);
  93 + strcpy (output, "ERROR ");
  94 + goto EXIT;
  95 + }
  96 +
  97 + if (leap_year (yy)) duration [2] = 29;
  98 +
  99 + ddd = dd - 1; /* Jan-01 : 0 => ddd in [0, 366[ */
  100 +
  101 + for (i = 1; i < mm; i++) ddd += duration [i];
  102 +
  103 + sprintf (output, "%04.4d%03.3d%02.2d%02.2d%02.2d%03.3d",
  104 + yy, ddd, h, m, s, ms);
  105 +
  106 +EXIT: return output;
  107 +}
  108 +
  109 +
  110 +/*******************************************************************************
  111 + *
  112 + * Parse variables metadata to define time variable ID :
  113 + *
  114 + * ID of a variable that appears in DEPEND_0 attribute of other variables
  115 + */
  116 +char * get_time_variable()
  117 +{
  118 + long timeVarId = -1;
  119 + long varId;
  120 + CDFstatus status;
  121 + long attrNum = CDFgetAttrNum (id, "DEPEND_0");
  122 + char * timeVarName = NULL;
  123 +
  124 + if (attrNum < CDF_OK) {
  125 + printf ("ERROR : no DEPEND_0 attribute\n");
  126 + attrNum = CDFgetAttrNum (id, "Depend_0");
  127 + if (attrNum < CDF_OK) {
  128 + printf ("ERROR : no Depend_0 attribute\n");
  129 + goto EXIT;
  130 + }
  131 + }
  132 +
  133 + for (varId = 0; varId < nZvars; varId++) {
  134 +
  135 + char name [CDF_VAR_NAME_LEN256+1];
  136 + long dataType;
  137 + long numElems;
  138 + char buffer [CDF_VAR_NAME_LEN256+1];
  139 +
  140 + status = CDFgetzVarName (id, varId, name);
  141 +
  142 + if (status != CDF_OK)
  143 + cdf_status_handler (status, "Get var name");
  144 +
  145 + status = CDFinquireAttrzEntry (id, attrNum, varId, & dataType, & numElems);
  146 +
  147 + if (status == NO_SUCH_ENTRY) continue;
  148 +
  149 + if (status != CDF_OK)
  150 + cdf_status_handler (status, "Get DEPEND_0");
  151 + else {
  152 + if (dataType == CDF_CHAR) {
  153 +
  154 + status = CDFgetAttrzEntry (id, attrNum, varId, buffer);
  155 + buffer [numElems] = 0;
  156 +
  157 + if (timeVarName == NULL) {
  158 + timeVarName = strdup (buffer);
  159 + }
  160 + else if (strcmp (timeVarName, buffer) != 0) {
  161 +
  162 + printf ("WARNING : Search time variable conflict between %s and %s\n %s is taken as Time\n",
  163 + timeVarName,
  164 + buffer,
  165 + timeVarName);
  166 + // EB: select the first time variable
  167 + // timeVarName = NULL;
  168 + // goto EXIT;
  169 + }
  170 + }
  171 + }
  172 + }
  173 +
  174 + if (timeVarName != NULL)
  175 + printf ("Identified time variable : %s\n", timeVarName);
  176 +
  177 +EXIT: return timeVarName;
  178 +}
  179 +
  180 +
  181 +/*******************************************************************************
  182 + *
  183 + * Compute time coverage (DD_TIME strings) of a currently opened CDF file
  184 + */
  185 +int get_file_coverage (char * start_coverage, char * stop_coverage)
  186 +{
  187 + int error = -1;
  188 + long varId = -1;
  189 + CDFstatus status;
  190 + char varName [CDF_VAR_NAME_LEN256+1];
  191 + long dataType, numElems, numDims, recVary, numRecs;
  192 + long dimSizes [CDF_MAX_DIMS];
  193 + long dimVarys [CDF_MAX_DIMS];
  194 + long indices [CDF_MAX_DIMS];
  195 + double d_buffer [2];
  196 + long long l_buffer [2];
  197 + char * timeVar = NULL;
  198 + char str1 [EPOCH16_4_STRING_LEN+1];
  199 + char str2 [EPOCH16_4_STRING_LEN+1];
  200 +
  201 + strcpy (start_coverage, "");
  202 + strcpy (stop_coverage, "");
  203 +
  204 + timeVar = get_time_variable ();
  205 +
  206 + if (timeVar == NULL) {
  207 + printf ("Error : no time variable identified\n");
  208 + goto EXIT;
  209 + }
  210 +
  211 + varId = CDFvarNum (id, timeVar);
  212 +
  213 + if (varId == -1) {
  214 +
  215 + printf ("Error : no time variable identified\n");
  216 + goto EXIT;
  217 + }
  218 +
  219 + status = CDFinquirezVar (id, varId,
  220 + varName,
  221 + & dataType,
  222 + & numElems,
  223 + & numDims,
  224 + dimSizes,
  225 + & recVary,
  226 + dimVarys);
  227 +
  228 + if (status != CDF_OK) cdf_status_handler (status, "CDF inquire zVar");
  229 +
  230 + if (recVary != VARY) {
  231 + printf ("ERROR : variable %s not record varying\n", varName);
  232 + goto EXIT;
  233 + }
  234 +
  235 + if (numDims > 1) {
  236 + printf ("Error : variable %s numDims > 1\n", varName);
  237 + goto EXIT;
  238 + }
  239 +
  240 + status = CDFgetzVarNumRecsWritten (id, varId, & numRecs);
  241 +
  242 + if (status != CDF_OK) cdf_status_handler (status, "CDF get zVar num recs");
  243 +
  244 + indices [0] = 0;
  245 + indices [1] = 0;
  246 + indices [3] = 0;
  247 +
  248 + switch (dataType) {
  249 +
  250 + case CDF_EPOCH:
  251 +
  252 + status = CDFgetzVarData (id, varId, 0L, indices, d_buffer);
  253 +
  254 + encodeEPOCH4 (d_buffer [0], str1);
  255 +
  256 + status = CDFgetzVarData (id, varId, numRecs -1, indices, d_buffer);
  257 +
  258 + encodeEPOCH4 (d_buffer [0], str2);
  259 +
  260 + break;
  261 +
  262 + case CDF_EPOCH16:
  263 +
  264 + status = CDFgetzVarData (id, varId, 0L, indices, d_buffer);
  265 +
  266 + encodeEPOCH16_4 (d_buffer, str1);
  267 +
  268 + status = CDFgetzVarData (id, varId, numRecs -1, indices, d_buffer);
  269 +
  270 + encodeEPOCH16_4 (d_buffer, str2);
  271 +
  272 + break;
  273 +
  274 + case CDF_TIME_TT2000:
  275 +
  276 + status = CDFgetzVarData (id, varId, 0L, indices, l_buffer);
  277 +
  278 + encodeTT2000 (l_buffer [0], str1, 3);
  279 +
  280 + status = CDFgetzVarData (id, varId, numRecs -1, indices, l_buffer);
  281 +
  282 + encodeTT2000 (l_buffer [0], str2, 3);
  283 +
  284 + break;
  285 + default:
  286 + printf ("Error : variable %d is not a Time variable\n");
  287 + goto EXIT;
  288 + }
  289 +
  290 + strcpy (start_coverage, isotime_to_dd_time (str1));
  291 + strcpy (stop_coverage, isotime_to_dd_time (str2));
  292 + error = 0;
  293 +
  294 +EXIT: return error;
  295 +}
  296 +
  297 +
  298 +#define NDIM 2
  299 +
  300 +/*******************************************************************************
  301 + *
  302 + * Set file time coverage metadata
  303 + */
  304 +int set_file_time_coverage ()
  305 +{
  306 + int error = 0;
  307 + char start_time [DD_TIME_STRING_LEN + 1];
  308 + char stop_time [DD_TIME_STRING_LEN + 1];
  309 + int time_dim;
  310 + int start_id, stop_id;
  311 + int nc_status = NC_NOERR;
  312 + size_t start [NDIM];
  313 + size_t count [NDIM];
  314 +
  315 + error = get_file_coverage (start_time, stop_time);
  316 +
  317 + if (error != 0) goto EXIT;
  318 +
  319 + printf ("CDF time coverage : %s - %s\n", start_time, stop_time);
  320 +
  321 + nc_status = nc_def_dim (ncid, "TimeLength", DD_TIME_STRING_LEN, & time_dim);
  322 +
  323 + if (nc_status != NC_NOERR) goto EXIT;
  324 +
  325 + nc_status = nc_def_var (ncid, START_TIME, NC_CHAR, 1, & time_dim, & start_id);
  326 +
  327 + if (nc_status != NC_NOERR) goto EXIT;
  328 +
  329 + nc_status = nc_def_var (ncid, STOP_TIME, NC_CHAR, 1, & time_dim, & stop_id);
  330 +
  331 + if (nc_status != NC_NOERR) goto EXIT;
  332 +
  333 + start [0] = 0;
  334 + count [0] = DD_TIME_STRING_LEN;
  335 +
  336 + nc_enddef (ncid);
  337 +
  338 + nc_status = nc_put_vara_text (ncid, start_id, start, count, start_time);
  339 +
  340 + if (nc_status != NC_NOERR) goto EXIT;
  341 +
  342 + nc_status = nc_put_vara_text (ncid, stop_id, start, count, stop_time);
  343 +
  344 + if (nc_status != NC_NOERR) goto EXIT;
  345 +
  346 +EXIT: printf ("NC status = %d\n", nc_status);
  347 + return error;
  348 +}
  349 +
  350 +
  351 +/*******************************************************************************
  352 + *
  353 + * Rename time_variable to "Time" (necessary for AMDA DD server usage)
  354 + */
  355 +int rename_time_variable ()
  356 +{
  357 + int error = -1;
  358 + char * timeVar = NULL;
  359 + int varId;
  360 + int nc_status;
  361 +
  362 + timeVar = get_time_variable ();
  363 +
  364 + if (timeVar == NULL) {
  365 +
  366 + printf ("ERROR : no time variable identified\n");
  367 + goto EXIT;
  368 + }
  369 +
  370 + nc_status = nc_redef (ncid);
  371 +
  372 + if (nc_status != NC_NOERR) goto EXIT;
  373 +
  374 + nc_status = nc_inq_varid (ncid, timeVar, & varId);
  375 +
  376 + if (nc_status != NC_NOERR) goto EXIT;
  377 +
  378 + nc_status = nc_rename_var (ncid, varId, TIME_VAR);
  379 +
  380 + if (nc_status != NC_NOERR) goto EXIT;
  381 +
  382 + nc_status = nc_enddef (ncid);
  383 +
  384 + if (nc_status != NC_NOERR) goto EXIT;
  385 +
  386 + error = 0;
  387 +
  388 +EXIT: return error;
  389 +
  390 +}
  391 +
... ...
src/DECODERS/cdfnew2nc/tools.h 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +#ifndef TOOLS_H
  2 +#define TOOLS_H
  3 +
  4 +#define DD_TIME_STRING_LEN 17
  5 +
  6 +int set_file_time_coverage ();
  7 +
  8 +char * isotime_to_dd_time (char * str_isotime);
  9 +
  10 +#endif
... ...