/******************************************************************************
*
*  NSSDC/CDF						IDL/CDF interface.
*
*  Version 1.4d, 8-Sep-95, Hughes STX.
*
*  Modification history:
*
*   V1.0   4-Sep-92, H Leckner	Original version.
*   V1.1  24-Jan-94, J Love	CDF V2.4.
*   V1.1a  6-Feb-94, J Love	DEC Alpha/OpenVMS port.
*   V1.1b 22-Feb-94, J Love	Spelling lesson.
*   V1.2  21-Dec-94, J Love	CDF V2.5.
*   V1.3  19-Jan-95, J Love	IRIX 6.0 (64-bit) although IDL isn't supported
*				on the Iris yet.  Fixed bug in `StoreLongArray'
*				involving the allocation of zero bytes (which
*				causes unpredictable results from `malloc').
*   V1.4  13-Mar-95, J Love	Solaris 2.3.  Moved inclusion of library
*				source files to end of this file.  IDL 4.0.
*   V1.4a 23-Mar-95, J Love	Changed to the IDL 4.0 macros/functions.
*				IDL 3.x is now a special case.
*   V1.4b 25-May-95, J Love	Added `cdfmem.c' to library sources.
*   V1.4c 12-Jun-95, J Love	EPOCH custom format.
*   V1.4d  8-Sep-95, J Love	Compilation with non-ANSI C compilers.
*
******************************************************************************/

#include "cdf.h"

#if !defined(PROTOs_)
#define IDL_CC_NOT_ANSI
#endif

#if defined(unix)
#include <stdio.h>
#include "export.h"
#include "cdfdist.h"
#else
#include "cdfdist.h"
#include "export.h"
#endif

#if !defined(IDL_TYP_LONG)
#define IDL_STRING STRING
#define IDL_ALLTYPES ALLTYPES
#define IDL_STRING_STR STRING_STR
#define IDL_BARR_INI_NOP BASICARR_INI_NOP
#define IDL_LONG LONG
#define IDL_VPTR VPTR
#define IDL_VARIABLE VARIABLE
#define IDL_TYP_BYTE TYP_BYTE
#define IDL_TYP_INT TYP_INT
#define IDL_TYP_LONG TYP_LONG
#define IDL_TYP_FLOAT TYP_FLOAT
#define IDL_TYP_DOUBLE TYP_DOUBLE
#define IDL_TYP_STRING TYP_STRING
#define IDL_TYP_STRUCT TYP_STRUCT
#define IDL_TYP_COMPLEX TYP_COMPLEX
#define IDL_TYP_UNDEF TYP_UNDEF
#define IDL_V_ARR V_ARR
#define IDL_StoreScalar store_scalar
#define IDL_VarCopy var_copy
#define IDL_StrStore str_store
#define IDL_StrDelete del_str
#define IDL_MakeTempArray make_temp_array
#endif

/******************************************************************************
* Miscellaneous macros.
******************************************************************************/

#define RETURNx(status) { \
static IDL_VARIABLE rCode; \
StoreLong ((IDL_VPTR) &rCode, (long) status); \
return ((IDL_VPTR) &rCode); \
}

#define CSC(status,pStatus,rcode) { \
CDFstatus tStatus = status; \
if (tStatus != CDF_OK) \
  if (tStatus < CDF_WARN) { /* ERROR */ \
    RETURNx (tStatus) \
  } \
  else \
    if (tStatus > CDF_OK) {  /* INFO */ \
      if (pStatus >= CDF_OK) pStatus = tStatus; \
    } \
    else  /* WARNING */ \
      pStatus = tStatus; \
}

/******************************************************************************
* CastToCDFid.
******************************************************************************/

Logical CastToCDFid (idlVar, id)
IDL_VPTR idlVar;
CDFid *id;
{
  if ((idlVar->flags & IDL_V_ARR) != 0)
    return FALSE;
  else {
    switch (idlVar->type) {
      case IDL_TYP_LONG:
        *id = Int32toCDFid ((Int32) idlVar->value.l);
	break;
      default:
	return FALSE;
    }
  }
  return TRUE;
}

/******************************************************************************
* CastToLong.
******************************************************************************/

Logical CastToLong (idlVar, value)
IDL_VPTR idlVar;
long *value;
{
  if ((idlVar->flags & IDL_V_ARR) != 0)
    return FALSE;
  else {
    switch (idlVar->type) {
      case IDL_TYP_BYTE:
        *value = (long) idlVar->value.c;
	break;
      case IDL_TYP_INT:
        *value = (long) idlVar->value.i;
	break;
      case IDL_TYP_LONG:
        *value = (long) idlVar->value.l;
	break;
      case IDL_TYP_FLOAT:
        *value = (long) idlVar->value.f;
	break;
      case IDL_TYP_DOUBLE:
        *value = (long) idlVar->value.d;
	break;
      default:
	return FALSE;
    }
  }
  return TRUE;
}

/******************************************************************************
* CastToDouble.
******************************************************************************/

Logical CastToDouble (idlVar, value)
IDL_VPTR idlVar;
double *value;
{
  if ((idlVar->flags & IDL_V_ARR) != 0)
    return FALSE;
  else {
    switch (idlVar->type) {
      case IDL_TYP_BYTE:
        *value = (double) idlVar->value.c;
	break;
      case IDL_TYP_INT:
        *value = (double) idlVar->value.i;
	break;
      case IDL_TYP_LONG:
        *value = (double) idlVar->value.l;
	break;
      case IDL_TYP_FLOAT:
        *value = (double) idlVar->value.f;
	break;
      case IDL_TYP_DOUBLE:
        *value = (double) idlVar->value.d;
	break;
      default:
	return FALSE;
    }
  }
  return TRUE;
}

/******************************************************************************
* BuildLongArray.
******************************************************************************/

Logical BuildLongArray (idlVar, array, maxElems)
IDL_VPTR idlVar;
long array[];
int maxElems;
{
  int n, i;
  if ((idlVar->flags & IDL_V_ARR) == 0) return FALSE;
  switch (idlVar->type) {
    case IDL_TYP_COMPLEX:
    case IDL_TYP_STRING:
    case IDL_TYP_STRUCT:
    case IDL_TYP_UNDEF:
      return FALSE;
  }
  if (idlVar->value.arr->n_dim > 1) return FALSE;
  if (idlVar->value.arr->n_elts == 0) return FALSE;
  n = MINIMUM (maxElems, idlVar->value.arr->n_elts);
  for (i = 0; i < n; i++) {
     switch (idlVar->type) {
       case IDL_TYP_BYTE:
	 array[i] = (long) (((char *) (idlVar->value.arr->data))[i]);
	 break;
       case IDL_TYP_INT:
	 array[i] = (long) (((short *) (idlVar->value.arr->data))[i]);
	 break;
       case IDL_TYP_LONG:
	 array[i] = (long) (((IDL_LONG *) (idlVar->value.arr->data))[i]);
	 break;
       case IDL_TYP_FLOAT:
	 array[i] = (long) (((float *) (idlVar->value.arr->data))[i]);
	 break;
       case IDL_TYP_DOUBLE:
	 array[i] = (long) ((double *) (idlVar->value.arr->data))[i];
	 break;
     }     
  }
  return TRUE;
}

/******************************************************************************
* StringPtr.
******************************************************************************/

Logical StringPtr (idlVar, string)
IDL_VPTR idlVar;
char **string;
{
  if ((idlVar->flags & IDL_V_ARR) == 0 && idlVar->type == IDL_TYP_STRING) {
    *string = IDL_STRING_STR (&(idlVar->value.str));
    return TRUE;
  }
  return FALSE;
}

/******************************************************************************
* DataPtr.
******************************************************************************/

Logical DataPtr (idlVar, data)
IDL_VPTR idlVar;
void **data;
{
  if ((idlVar->flags & IDL_V_ARR) != 0)
    *data = idlVar->value.arr->data;
  else
    switch (idlVar->type) {
      case IDL_TYP_BYTE:
        *data = &(idlVar->value.c);
	break;
      case IDL_TYP_INT:
        *data = &(idlVar->value.i);
	break;
      case IDL_TYP_LONG:
        *data = &(idlVar->value.l);
	break;
      case IDL_TYP_FLOAT:
        *data = &(idlVar->value.f);
	break;
      case IDL_TYP_DOUBLE:
        *data = &(idlVar->value.d);
	break;
      case IDL_TYP_COMPLEX:
        *data = &(idlVar->value.cmp);
	break;
      case IDL_TYP_STRING:
        *data = idlVar->value.str.s;
	break;
      case IDL_TYP_STRUCT:
	*data = idlVar->value.s.arr;
	break;
      case IDL_TYP_UNDEF:
	return FALSE;
    }
  return TRUE;
}

/******************************************************************************
* IDLdataType.
******************************************************************************/

int IDLdataType (cdfDataType)
long cdfDataType;
{
  switch (cdfDataType) {
    case CDF_BYTE:
    case CDF_INT1:
    case CDF_UINT1:
      return IDL_TYP_BYTE;
    case CDF_INT2:
    case CDF_UINT2:
      return IDL_TYP_INT;
    case CDF_INT4:
    case CDF_UINT4:
      return IDL_TYP_LONG;
    case CDF_REAL4:
    case CDF_FLOAT:
      return IDL_TYP_FLOAT;
    case CDF_REAL8:
    case CDF_DOUBLE:
    case CDF_EPOCH:
      return IDL_TYP_DOUBLE;
    case CDF_CHAR:
    case CDF_UCHAR:
      return IDL_TYP_STRING;
    default:
      return IDL_TYP_UNDEF;
  }
}

/******************************************************************************
* StoreMultiArray.
******************************************************************************/

Logical StoreMultiArray (idlVar, dataType, numElems, numDims, dimSizes, buffer)
IDL_VPTR idlVar;
long dataType;
long numElems;
long numDims;
long dimSizes[];
void *buffer;
{
  IDL_VPTR tempVar;
  long nValues, valueN;
  void *data;
  int dimN;
  IDL_LONG dimSizesT[CDF_MAX_DIMS];
  /****************************************************************************
  * If there are zero dimensions or the size of one of the dimensions is zero,
  * return without creating/loading an array.
  ****************************************************************************/
  if (numDims == 0) return TRUE;
  for (dimN = 0; dimN < numDims; dimN++) if (dimSizes[dimN] == 0) return TRUE;
  /****************************************************************************
  * Count the number of values to be stored.
  ****************************************************************************/
  nValues = 1;
  for (dimN = 0; dimN < numDims; dimN++) {
     nValues *= dimSizes[dimN];
     dimSizesT[dimN] = (IDL_LONG) dimSizes[dimN];
  }
  /****************************************************************************
  * Allocate a temporary IDL variable.
  ****************************************************************************/
  data = IDL_MakeTempArray (IDLdataType(dataType), (int) numDims, dimSizesT,
			    IDL_BARR_INI_NOP, &tempVar);
  if (data == NULL) return FALSE;
  /****************************************************************************
  * Load the temporary IDL variable.
  ****************************************************************************/
  if (STRINGdataType(dataType)) {
    IDL_STRING *str = data;
    char *buf = buffer;
    char *tmp = (char *) malloc (numElems + 1);
    if (tmp == NULL) return FALSE;
    for (valueN = 0; valueN < nValues; valueN++, str++, buf += numElems) {
       memmove (tmp, buf, numElems);
       tmp[numElems] = NUL;
       IDL_StrStore (str, tmp);
    }
    free (tmp);
    IDL_VarCopy (tempVar, idlVar);
  }
  else {
    size_t nBytes = nValues * CDFelemSize(dataType);
    memmove (data, buffer, nBytes);
    IDL_VarCopy (tempVar, idlVar);
  }
  return TRUE;
}

/******************************************************************************
* StoreLongArray.
*   IMPORTANT: Note that `count' is assumed to be CDF_MAX_DIMS or less.
******************************************************************************/

Logical StoreLongArray (idlVar, count, buffer)
IDL_VPTR idlVar;	/* IDL variable to create/recreate. */
long count;	/* Assumed to be CDF_MAX_DIMS or less. */
long buffer[];	/* Values to be assigned to the array. */
{
  Int32 tBuffer[CDF_MAX_DIMS]; int i;
  for (i = 0; i < count; i++) tBuffer[i] = (Int32) buffer[i];
  return StoreMultiArray (idlVar, CDF_INT4, 1L, 1L, &count, tBuffer);
}

/******************************************************************************
* StoreCDFid.
******************************************************************************/

void StoreCDFid (idlVar, id)
IDL_VPTR idlVar;
CDFid id;
{
  IDL_ALLTYPES temp;
  temp.l = (IDL_LONG) CDFidToInt32 (id);
  IDL_StoreScalar (idlVar, IDL_TYP_LONG, &temp);
  return;
}

/******************************************************************************
* StoreLong.
******************************************************************************/

void StoreLong (idlVar, value)
IDL_VPTR idlVar;
long value;
{
  IDL_ALLTYPES temp;
  temp.l = (IDL_LONG) value;
  IDL_StoreScalar (idlVar, IDL_TYP_LONG, &temp);
  return;
}

/******************************************************************************
* StoreScalar.
******************************************************************************/

void StoreScalar(tmp, data_type, value)
IDL_VPTR tmp;
long data_type;
void *value;
{
  IDL_ALLTYPES temp;
  switch(data_type){
    case CDF_REAL4:
    case CDF_FLOAT:
      temp.f = *((float *) value);
      IDL_StoreScalar (tmp, IDL_TYP_FLOAT, &temp);
      break;
    case CDF_REAL8:
    case CDF_DOUBLE:
    case CDF_EPOCH:
      temp.d = *((double *) value);
      IDL_StoreScalar (tmp, IDL_TYP_DOUBLE, &temp);
      break;
    case CDF_INT4:
    case CDF_UINT4:
      temp.l = *((IDL_LONG *) value);
      IDL_StoreScalar (tmp, IDL_TYP_LONG, &temp);
      break;
    case CDF_INT2:
    case CDF_UINT2:
      temp.i = *((short *) value);
      IDL_StoreScalar (tmp, IDL_TYP_INT, &temp);
      break;
    case CDF_BYTE:
    case CDF_INT1:
    case CDF_UINT1:
      temp.c = *((UCHAR *) value);
      IDL_StoreScalar (tmp, IDL_TYP_BYTE, &temp);
      break;
  }
  return;
}

/******************************************************************************
* StoreString.
******************************************************************************/

void StoreString (idlVar, str)
IDL_VPTR idlVar;
char *str;
{
  IDL_ALLTYPES temp;
  IDL_StrStore (&temp.str, str);
  IDL_StoreScalar (idlVar, IDL_TYP_STRING, &temp);
  IDL_StrDelete (&temp.str, (IDL_LONG) 1);
}

/******************************************************************************
* idl_cdfopen.
******************************************************************************/

IDL_VPTR idl_cdfopen(argc, argv)
int argc;
IDL_VPTR argv[];
{
  char *CDF_name;
  CDFid CDF_id;
  CDFstatus status;
  if (!StringPtr(argv[0],&CDF_name)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (OPEN_, CDF_, CDF_name, &CDF_id, 
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreCDFid (argv[1], CDF_id);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfdelete.
******************************************************************************/

IDL_VPTR idl_cdfdelete(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
		   DELETE_, CDF_,
		   NULL_);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfinquire.
******************************************************************************/

IDL_VPTR idl_cdfinquire(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long num_dims, dim_sizes[CDF_MAX_DIMS], encoding, majority, max_record_num,
       num_vars, num_attrs;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
		   GET_, rVARs_NUMDIMS_, &num_dims,
		         rVARs_DIMSIZES_, dim_sizes,
		         CDF_ENCODING_, &encoding,
		         CDF_MAJORITY_, &majority,
		         rVARs_MAXREC_, &max_record_num,
		         CDF_NUMrVARS_, &num_vars,
		         CDF_NUMATTRS_, &num_attrs,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreLong (argv[1], num_dims);
  if (!StoreLongArray(argv[2],num_dims,dim_sizes)) RETURNx (BAD_MALLOC)
  StoreLong (argv[3], encoding);
  StoreLong (argv[4], majority);
  StoreLong (argv[5], max_record_num);
  StoreLong (argv[6], num_vars);
  StoreLong (argv[7], num_attrs);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfvarinq.
******************************************************************************/

IDL_VPTR idl_cdfvarinq(argc, argv)
int 		argc;
IDL_VPTR		argv[];
{
  CDFid CDF_id;
  char var_mnemonic[CDF_VAR_NAME_LEN+1];
  long var_num, data_type, num_bytes, record_variance,
       dim_variances[CDF_MAX_DIMS];
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&var_num)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    rVAR_, var_num,
		   GET_, rVAR_NAME_, var_mnemonic,
		         rVAR_DATATYPE_, &data_type,
		         rVAR_NUMELEMS_, &num_bytes,
		         rVAR_RECVARY_, &record_variance,
		         rVAR_DIMVARYS_, dim_variances,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreString (argv[2], var_mnemonic);
  StoreLong (argv[3], data_type);
  StoreLong (argv[4], num_bytes);
  StoreLong (argv[5], record_variance);
  if (!StoreLongArray(argv[6],(long)CDF_MAX_DIMS,
		      dim_variances)) RETURNx (BAD_MALLOC)
  RETURNx (status)
}

/******************************************************************************
* idl_cdfvarclose.
******************************************************************************/

IDL_VPTR idl_cdfvarclose(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long var_num;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&var_num)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    rVAR_, var_num,
		   CLOSE_,  rVAR_,
		   NULL_);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfclose.
******************************************************************************/

IDL_VPTR idl_cdfclose(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
		   CLOSE_, CDF_,
		   NULL_);
  RETURNx (status)
}

/******************************************************************************
* idl_cdferror.
******************************************************************************/

IDL_VPTR idl_cdferror(argc, argv)
int argc;
IDL_VPTR argv[];
{
  long error_code;
  char error_mes[CDF_STATUSTEXT_LEN+1];
  CDFstatus status;
  if (!CastToLong(argv[0],&error_code)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_STATUS_, (CDFstatus) error_code,
		   GET_,    STATUS_TEXT_, error_mes,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreString(argv[1], error_mes);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfdoc.
******************************************************************************/

IDL_VPTR idl_cdfdoc(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long version, release;
  char text[CDF_DOCUMENT_LEN+1];
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
		   GET_, CDF_VERSION_, &version,
		         CDF_RELEASE_, &release,
		         CDF_COPYRIGHT_, text,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreLong (argv[1], version);
  StoreLong (argv[2], release);
  StoreString(argv[3], text);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfattrinq.
******************************************************************************/

IDL_VPTR idl_cdfattrinq(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  char attr_mnemonic[CDF_ATTR_NAME_LEN+1];
  long attr_num, attr_scope, max_entry;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&attr_num)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_, attr_num,
		   GET_, ATTR_SCOPE_, &attr_scope,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_,  	   attr_num,
		   GET_, ATTR_NAME_, attr_mnemonic,
		         ATTR_SCOPE_, &attr_scope,
		         BOO(attr_scope == GLOBAL_SCOPE,
			     ATTR_MAXgENTRY_,ATTR_MAXrENTRY_), &max_entry,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreString(argv[2], attr_mnemonic);
  StoreLong (argv[3], attr_scope);
  StoreLong (argv[4], max_entry);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfattreinq.
******************************************************************************/

IDL_VPTR idl_cdfattreinq(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long attr_num, entry_num, data_type, num_elements, scope;
  CDFstatus 	status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&attr_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&entry_num)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_, attr_num,
		   GET_, ATTR_SCOPE_, &scope,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_, attr_num,
			    BOO(scope == GLOBAL_SCOPE,
			        gENTRY_,rENTRY_), entry_num,
		   GET_, BOO(scope == GLOBAL_SCOPE,
			     gENTRY_DATATYPE_,rENTRY_DATATYPE_), &data_type,
		         BOO(scope == GLOBAL_SCOPE,
			     gENTRY_NUMELEMS_,rENTRY_NUMELEMS_),&num_elements,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreLong (argv[3], data_type);
  StoreLong (argv[4], num_elements);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfvarnum.
******************************************************************************/

IDL_VPTR idl_cdfvarnum(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  char *var_mnemonic;
  long var_num;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!StringPtr(argv[1],&var_mnemonic)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id,
		   GET_, rVAR_NUMBER_, var_mnemonic, &var_num,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  RETURNx (var_num)
}

/******************************************************************************
* idl_cdfattrnum.
******************************************************************************/

IDL_VPTR idl_cdfattrnum(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  char *attr_mnemonic;
  long attr_num;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!StringPtr(argv[1],&attr_mnemonic)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id,
		   GET_, ATTR_NUMBER_, attr_mnemonic, &attr_num,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  RETURNx (attr_num)
}

/******************************************************************************
* idl_cdfattrget.
******************************************************************************/

IDL_VPTR idl_cdfattrget(argc, argv)
int argc;
IDL_VPTR argv[];
{
  void *value;
  CDFid CDF_id;
  void *data;
  long attr_num, entry_num, dataType, numElems, scope;
  CDFstatus status;
  char *tmp;
  size_t nBytes;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&attr_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&entry_num)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_, attr_num,
		   GET_, ATTR_SCOPE_, &scope,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_, attr_num,
			    BOO(scope == GLOBAL_SCOPE,
			        gENTRY_,rENTRY_), entry_num,
		   GET_, BOO(scope == GLOBAL_SCOPE,
			     gENTRY_DATATYPE_,rENTRY_DATATYPE_), &dataType,
		         BOO(scope == GLOBAL_SCOPE,
			     gENTRY_NUMELEMS_,rENTRY_NUMELEMS_), &numElems,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  nBytes = (CDFelemSize(dataType)*numElems) +
	   BOO(STRINGdataType(dataType),1,0);
  value = (void *) malloc (nBytes);
  if (value == NULL) RETURNx (BAD_MALLOC)
  status = CDFlib (GET_, BOO(scope == GLOBAL_SCOPE,
			     gENTRY_DATA_,rENTRY_DATA_), value,
		   NULL_);
  if (StatusBAD(status)) {
    free (value);
    RETURNx (status)
  }
  if (STRINGdataType(dataType)) {
    ((char *) value)[numElems] = NUL;
    StoreString (argv[3], value);
  }
  else
    if (numElems > 1) {
      if (!StoreMultiArray(argv[3],dataType,1L,1L,&numElems,value)) {
        free (value);
        RETURNx (BAD_MALLOC)
      }
    }
    else
      StoreScalar (argv[3], dataType, value);
  free (value);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfvarget.
******************************************************************************/

IDL_VPTR idl_cdfvarget(argc, argv)
int argc;
IDL_VPTR argv[];
{
  void *value;
  CDFid CDF_id;
  size_t nBytes;
  CDFstatus status;
  long var_num, record_num, indices[CDF_MAX_DIMS], data_type, num_elems;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&var_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&record_num)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[3],indices,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    rVAR_, var_num,
		   GET_, rVAR_DATATYPE_, &data_type,
		         rVAR_NUMELEMS_, &num_elems,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  nBytes = BOO(STRINGdataType(data_type),num_elems+1,CDFelemSize(data_type));
  value = (void *) malloc (nBytes);
  if (value == NULL) RETURNx (BAD_MALLOC)
  status = CDFlib (SELECT_, rVARs_RECNUMBER_,  record_num,
			    rVARs_DIMINDICES_, indices,
		   GET_, rVAR_DATA_, value,
		   NULL_);
  if (StatusBAD(status)) {
    free (value);
    RETURNx (status)
  }
  if (STRINGdataType(data_type)) {
    ((char *) value)[num_elems] = NUL;
    StoreString (argv[4], (char *) value);
  }
  else
    StoreScalar (argv[4], data_type, value);
  free (value);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfvarput.
******************************************************************************/

IDL_VPTR idl_cdfvarput(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long var_num, record_num, indices[CDF_MAX_DIMS];
  CDFstatus status;
  void *value;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&var_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&record_num)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[3],indices,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!DataPtr(argv[4],&value)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    rVAR_, var_num,
		            rVARs_RECNUMBER_, record_num,
			    rVARs_DIMINDICES_, indices,
		   PUT_, rVAR_DATA_, value,
		   NULL_);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfhypget.
******************************************************************************/

IDL_VPTR idl_cdfhypget(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long var_num, recStart, recCount, recInterval;
  long indices[CDF_MAX_DIMS], counts[CDF_MAX_DIMS], intervals[CDF_MAX_DIMS];
  void *buffer;
  CDFstatus status;
  long num_dims, data_type, num_elems;
  long nRecValues, nValueBytes, nRecBytes, nBytes, tCounts[CDF_MAX_DIMS+1];
  int dimN;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&var_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&recStart)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[3],&recCount)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&recInterval)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[5],indices,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[6],counts,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[7],intervals,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    rVAR_, var_num,
		   GET_, rVARs_NUMDIMS_, &num_dims,
		         rVAR_DATATYPE_, &data_type,
		         rVAR_NUMELEMS_, &num_elems,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  nRecValues = 1;
  for (dimN = 0; dimN < num_dims; dimN++) nRecValues *= counts[dimN];
  nValueBytes = CDFelemSize(data_type) * num_elems;
  nRecBytes = nRecValues * nValueBytes;
  nBytes = nRecBytes * recCount;
  buffer = (void *) malloc (nBytes);
  if (buffer == NULL) RETURNx (BAD_MALLOC)
  status = CDFlib (SELECT_, rVARs_RECNUMBER_, recStart,
		            rVARs_RECCOUNT_, recCount,
		            rVARs_RECINTERVAL_, recInterval,
			    rVARs_DIMINDICES_, indices,
			    rVARs_DIMCOUNTS_, counts,
			    rVARs_DIMINTERVALS_, intervals,
		   GET_, rVAR_HYPERDATA_, buffer,
		   NULL_);
  if (StatusBAD(status)) {
    free (buffer);
    RETURNx (status)
  }
  for (dimN = 0; dimN < num_dims; dimN++) tCounts[dimN] = counts[dimN];
  tCounts[(int)num_dims] = recCount;
  if (!StoreMultiArray(argv[8],data_type,num_elems,
		       num_dims+1,tCounts,buffer)) {
    free (buffer);
    RETURNx (BAD_MALLOC)
  }
  free (buffer);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfhypput.
******************************************************************************/

IDL_VPTR idl_cdfhypput(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid		CDF_id;
  long var_num, recStart, recCount, recInterval;
  long indices[CDF_MAX_DIMS], counts[CDF_MAX_DIMS], intervals[CDF_MAX_DIMS];
  void *buffer, *xBuffer;
  CDFstatus status;
  long num_dims, data_type, num_elems;
  long nRecValues, nValueBytes, nRecBytes, nBytes, valueN, nValues;
  int dimN;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&var_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&recStart)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[3],&recCount)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&recInterval)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[5],indices,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[6],counts,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[7],intervals,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!DataPtr(argv[8],&buffer)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    rVAR_, var_num,
		   GET_, rVARs_NUMDIMS_, &num_dims,
		         rVAR_DATATYPE_, &data_type,
		         rVAR_NUMELEMS_, &num_elems,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  nRecValues = 1;
  for (dimN = 0; dimN < num_dims; dimN++) nRecValues *= counts[dimN];
  nValues = nRecValues * recCount;
  nValueBytes = CDFelemSize(data_type) * num_elems;
  nRecBytes = nRecValues * nValueBytes;
  nBytes = nRecBytes * recCount;
  if (STRINGdataType(data_type)) {
    IDL_STRING *str; char *tBuffer;
    xBuffer = (char *) malloc (nBytes);
    if (xBuffer == NULL) RETURNx (BAD_MALLOC)
    str = (IDL_STRING *) buffer;
    tBuffer = xBuffer;
    for (valueN = 0; valueN < nValues;
         valueN++, str++, tBuffer += num_elems) {
       strcpyX (tBuffer, IDL_STRING_STR(str), num_elems);
    }
  }
  else
    xBuffer = buffer;
  status = CDFlib (SELECT_, rVARs_RECNUMBER_, recStart,
		            rVARs_RECCOUNT_, recCount,
		            rVARs_RECINTERVAL_, recInterval,
			    rVARs_DIMINDICES_, indices,
			    rVARs_DIMCOUNTS_, counts,
			    rVARs_DIMINTERVALS_, intervals,
		   PUT_, rVAR_HYPERDATA_, xBuffer,
		   NULL_);
  if (StatusBAD(status)) {
    if (xBuffer != buffer) free (xBuffer);
    RETURNx (status)
  }
  if (xBuffer != buffer) free (xBuffer);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfcreate.
******************************************************************************/

IDL_VPTR idl_cdfcreate(argc, argv)
int argc;
IDL_VPTR argv[];
{
  char *CDF_name;
  long num_dims, dim_sizes[CDF_MAX_DIMS], encoding, majority;
  CDFid CDF_id;
  CDFstatus status;
  if (!StringPtr(argv[0],&CDF_name)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&num_dims)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[2],dim_sizes,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[3],&encoding)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&majority)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (CREATE_, CDF_, CDF_name, num_dims, dim_sizes, &CDF_id,
		   PUT_, CDF_ENCODING_, encoding,
		         CDF_MAJORITY_, majority,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreCDFid (argv[5], CDF_id);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfvarcre.
******************************************************************************/

IDL_VPTR idl_cdfvarcre(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  char *var_mnemonic;
  long data_type, num_bytes, record_variance, dim_variances[CDF_MAX_DIMS],
       out_var_num;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!StringPtr(argv[1],&var_mnemonic)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&data_type)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[3],&num_bytes)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&record_variance)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[5],dim_variances,
		      CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
		   CREATE_, rVAR_, var_mnemonic, data_type, num_bytes,
		                   record_variance, dim_variances,
				   &out_var_num,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreLong (argv[6], out_var_num);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfvarren.
******************************************************************************/

IDL_VPTR idl_cdfvarren(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long var_num;
  char *var_mnemonic;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&var_num)) RETURNx (BAD_ARGUMENT)
  if (!StringPtr(argv[2],&var_mnemonic)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    rVAR_, var_num,
		   PUT_, rVAR_NAME_, var_mnemonic,
		   NULL_);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfattrren.
******************************************************************************/

IDL_VPTR idl_cdfattrren(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long attr_num;
  char *attr_mnemonic;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&attr_num)) RETURNx (BAD_ARGUMENT)
  if (!StringPtr(argv[2],&attr_mnemonic)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_, attr_num,
		   PUT_, ATTR_NAME_, attr_mnemonic,
		   NULL_);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfattrcre.
******************************************************************************/

IDL_VPTR idl_cdfattrcre(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  char *attr_mnemonic;
  long attr_scope, out_attr_num;
  CDFstatus status;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!StringPtr(argv[1],&attr_mnemonic)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&attr_scope)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_,  CDF_id, 
		   CREATE_, ATTR_, attr_mnemonic, attr_scope, &out_attr_num,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  StoreLong (argv[3], out_attr_num);
  RETURNx (status)
}

/******************************************************************************
* idl_cdfattrput.
******************************************************************************/

IDL_VPTR idl_cdfattrput(argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFid CDF_id;
  long attr_num, entry_num, data_type, num_elements, scope;
  CDFstatus status;
  void *value;
  if (!CastToCDFid(argv[0],&CDF_id)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&attr_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&entry_num)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[3],&data_type)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&num_elements)) RETURNx (BAD_ARGUMENT)
  if (!DataPtr(argv[5],&value)) RETURNx (BAD_ARGUMENT)
  status = CDFlib (SELECT_, CDF_, CDF_id, 
			    ATTR_, attr_num,
		   GET_, 	    ATTR_SCOPE_, &scope,
		   NULL_);
  if (StatusBAD(status)) RETURNx (status)
  status = CDFlib (SELECT_, BOO(scope == GLOBAL_SCOPE,
			        gENTRY_,rENTRY_), entry_num,
		   PUT_, BOO(scope == GLOBAL_SCOPE,
			     gENTRY_DATA_, rENTRY_DATA_), data_type,
							  num_elements, value,
		   NULL_);
  RETURNx (status)
}

/******************************************************************************
* row_2_col.
******************************************************************************/

IDL_VPTR row_2_col (argc, argv)
int argc;
IDL_VPTR argv[];
{
  void *iBuffer, *oBuffer;
  long numDims, dimSizes[CDF_MAX_DIMS], nValueBytes, num_records, nvalues,
       i, offset, bytes_per_record, record_num;
  if (!DataPtr(argv[0],&iBuffer)) RETURNx (BAD_ARGUMENT)
  if (!DataPtr(argv[1],&oBuffer)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&numDims)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[3],dimSizes,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&nValueBytes)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[5],&num_records)) RETURNx (BAD_ARGUMENT)
  nvalues = 1;
  for (i = 0; i < numDims; i++) nvalues = nvalues * dimSizes[i];
  bytes_per_record = nvalues * nValueBytes;
  offset = 0;
  for (record_num = 0; record_num < num_records; record_num++){
     ROWtoCOL ((Byte *)iBuffer+offset, (Byte *)oBuffer+offset, numDims, 
	       dimSizes, nValueBytes);
     offset += bytes_per_record;
  }
  RETURNx (CDF_OK)
}

/******************************************************************************
* col_2_row.
******************************************************************************/

IDL_VPTR col_2_row (argc, argv)
int argc;
IDL_VPTR argv[];
{
  void *iBuffer, *oBuffer;
  long numDims, dimSizes[CDF_MAX_DIMS], nValueBytes, num_records, nvalues,
       i, offset, bytes_per_record, record_num;
  if (!DataPtr(argv[0],&iBuffer)) RETURNx (BAD_ARGUMENT)
  if (!DataPtr(argv[1],&oBuffer)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&numDims)) RETURNx (BAD_ARGUMENT)
  if (!BuildLongArray(argv[3],dimSizes,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&nValueBytes)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[5],&num_records)) RETURNx (BAD_ARGUMENT)
  nvalues = 1;
  for (i = 0; i < numDims; i++) nvalues = nvalues * dimSizes[i];
  bytes_per_record = nvalues * nValueBytes;
  offset = 0;
  for (record_num = 0; record_num < num_records; record_num++){
     COLtoROW ((Byte *)iBuffer+offset, (Byte *)oBuffer+offset, numDims, 
	       dimSizes, nValueBytes);
     offset += bytes_per_record;
  }
  RETURNx (CDF_OK)
}

/******************************************************************************
* idl_cdflib.
*
* NOTES:
*   GET_,[r/z]VARs_RECDATA_ and PUT_,[r/z]VARs_RECDATA_ are not supported
* because different data types may be returned.  If IDL has something like
* a Fortran EQUIVALENCE then perhaps they could be supported.
******************************************************************************/

IDL_VPTR idl_cdflib (argc, argv)
int argc;
IDL_VPTR argv[];
{
  CDFstatus status, pStatus = CDF_OK;
  int argX = 0;
  long item, fnc;
  if (!CastToLong(argv[argX++],&fnc)) RETURNx (BAD_ARGUMENT)
  while (fnc != NULL_) {
    switch (fnc) {
      /************************************************************************
      * CREATE_, create an item.
      ************************************************************************/
      case CREATE_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * CREATE_,CDF_: create a CDF.
	     *****************************************************************/
	     case CDF_: {
	       CDFid id; char *CDFname;
	       long dimSizes[CDF_MAX_DIMS], numDims;
	       if (!StringPtr(argv[argX++],&CDFname)) RETURNx (BAD_ARGUMENT)
	       if (!CastToLong(argv[argX++],&numDims)) RETURNx (BAD_ARGUMENT)
	       if (!BuildLongArray(argv[argX++],
				   dimSizes,
				   CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (CREATE_, CDF_, CDFname, numDims, dimSizes, &id,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreCDFid (argv[argX++], id);
	       break;
	     }
	     /*****************************************************************
	     * CREATE_,rVAR_/zVAR_: create a variable.
	     *****************************************************************/
	     case rVAR_:
	     case zVAR_: {
	       Logical Zop = (item == zVAR_);
	       char *varName;
	       long dimSizes[CDF_MAX_DIMS], dimVarys[CDF_MAX_DIMS];
	       long dataType, numElems, recVary, varNum, numDims;
	       if (!StringPtr(argv[argX++],&varName)) RETURNx (BAD_ARGUMENT)
	       if (!CastToLong(argv[argX++],&dataType)) RETURNx (BAD_ARGUMENT)
	       if (!CastToLong(argv[argX++],&numElems)) RETURNx (BAD_ARGUMENT)
	       if (Zop) {
	         if (!CastToLong(argv[argX++],&numDims)) RETURNx (BAD_ARGUMENT)
		 if (!BuildLongArray(argv[argX++],
				     dimSizes,
				     CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
	       }
	       if (!CastToLong(argv[argX++],&recVary)) RETURNx (BAD_ARGUMENT)
	       if (!BuildLongArray(argv[argX++],
				   dimVarys,
				   CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
	       if (Zop)
		 status = CDFlib (CREATE_, zVAR_, varName, dataType, numElems,
						  numDims, dimSizes,
						  recVary, dimVarys, &varNum,
				  NULL_);
	       else
		 status = CDFlib (CREATE_, rVAR_, varName, dataType, numElems,
						  recVary, dimVarys, &varNum,
				  NULL_);
	       CSC (status, pStatus, rCode)
	       StoreLong (argv[argX++], varNum);
	       break;
	     }
	     /*****************************************************************
	     * CREATE_,ATTR_: create an attribute.
	     *****************************************************************/
	     case ATTR_: {
	       long attrNum, scope;
	       char *attrName;
	       if (!StringPtr(argv[argX++],&attrName)) RETURNx (BAD_ARGUMENT)
	       if (!CastToLong(argv[argX++],&scope)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (CREATE_, ATTR_, attrName, scope, &attrNum,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreLong (argv[argX++], attrNum);
	       break;
	     }
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * OPEN_, open an item.
      ************************************************************************/
      case OPEN_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * OPEN_,CDF_: open a CDF.
	     *****************************************************************/
	     case CDF_: {
	       CDFid id;
	       char *CDFname;
	       if (!StringPtr(argv[argX++],&CDFname)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (OPEN_, CDF_, CDFname, &id,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreCDFid (argv[argX++], id);
	       break;
	     }
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * DELETE_, delete an item.
      ************************************************************************/
      case DELETE_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * DELETE_,<object>:  Delete an object.
	     *****************************************************************/
	     case CDF_:
	     case zVAR_:
	     case rVAR_:
	     case ATTR_:
	     case gENTRY_:
	     case zENTRY_:
	     case rENTRY_:
	       status = CDFlib (DELETE_, item,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * CLOSE_, close an item.
      ************************************************************************/
      case CLOSE_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * CLOSE_,CDF_: close a CDF.
	     *****************************************************************/
	     case CDF_: {
	       status = CDFlib (CLOSE_, CDF_,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * CLOSE_,rVAR_/zVAR_: close a variable.
	     *****************************************************************/
	     case rVAR_:
	     case zVAR_: {
	       status = CDFlib (CLOSE_, item,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * SELECT_, select an item.
      ************************************************************************/
      case SELECT_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * SELECT_,<`long' value>
	     *****************************************************************/
	     case CDF_READONLY_MODE_:
	     case CDF_zMODE_:
	     case CDF_NEGtoPOSfp0_MODE_:
	     case CDF_DECODING_:
	     case CDF_CACHESIZE_:
	     case rVARs_CACHESIZE_:
	     case zVARs_CACHESIZE_:
	     case rVAR_CACHESIZE_:
	     case zVAR_CACHESIZE_:
	     case rVAR_:
	     case zVAR_:
	     case rVARs_RECNUMBER_:
	     case zVARs_RECNUMBER_:
	     case zVAR_RECNUMBER_:
	     case rVARs_RECCOUNT_:
	     case zVAR_RECCOUNT_:
	     case rVARs_RECINTERVAL_:
	     case zVAR_RECINTERVAL_:
	     case ATTR_:
	     case gENTRY_:
	     case rENTRY_:
	     case zENTRY_:
	     {
	       long value;
	       if (!CastToLong(argv[argX++],&value)) RETURNx (BAD_ARGUMENT);
	       status = CDFlib (SELECT_, item, value,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * SELECT_,<array of `long' values>
	     *****************************************************************/
	     case rVARs_DIMINDICES_:
	     case zVAR_DIMINDICES_:
	     case rVARs_DIMCOUNTS_:
	     case zVAR_DIMCOUNTS_:
	     case rVARs_DIMINTERVALS_:
	     case zVAR_DIMINTERVALS_:
	     {
	       long values[CDF_MAX_DIMS];
	       if (!BuildLongArray(argv[argX++],
				   values,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (SELECT_, item, values,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * SELECT_,<`long' value, array of `long' values>
	     *****************************************************************/
	     case rVAR_SEQPOS_:
	     case zVAR_SEQPOS_:
	     {
	       long value;
	       long values[CDF_MAX_DIMS];
	       if (!CastToLong(argv[argX++],&value)) RETURNx (BAD_ARGUMENT)
	       if (!BuildLongArray(argv[argX++],
				   values,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (SELECT_, item, value, values,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * SELECT_,<character string>
	     *****************************************************************/
	     case rVAR_NAME_:
	     case zVAR_NAME_:
	     case ATTR_NAME_:
	     case rENTRY_NAME_:
	     case zENTRY_NAME_:
	     {
	       char *string;
	       if (!StringPtr(argv[argX++],&string)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (SELECT_, item, string,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * SELECT_,CDF_: select the current CDF.
	     *****************************************************************/
	     case CDF_: {
	       CDFid id;
	       if (!CastToCDFid(argv[argX++],&id)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (SELECT_, CDF_, id,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * SELECT_,CDF_STATUS_: select the current CDF status code.
	     *****************************************************************/
	     case CDF_STATUS_: {
	       long cStatus;
	       if (!CastToLong(argv[argX++],&cStatus)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (SELECT_, CDF_STATUS_, (CDFstatus) cStatus,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * CONFIRM_, confirm an item.
      ************************************************************************/
      case CONFIRM_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * CONFIRM_,<no arguments>
	     *****************************************************************/
	     case CURgENTRY_EXISTENCE_:
	     case CURrENTRY_EXISTENCE_:
	     case CURzENTRY_EXISTENCE_:
	     {
	       status = CDFlib (CONFIRM_, item,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * CONFIRM_,<out: `long' value>
	     *****************************************************************/
	     case CDF_READONLY_MODE_:
	     case CDF_zMODE_:
	     case CDF_NEGtoPOSfp0_MODE_:
	     case CDF_DECODING_:
	     case CDF_CACHESIZE_:
	     case rVAR_CACHESIZE_:
	     case zVAR_CACHESIZE_:
	     case rVAR_:
	     case zVAR_:
	     case rVARs_RECNUMBER_:
	     case zVAR_RECNUMBER_:
	     case rVARs_RECCOUNT_:
	     case zVAR_RECCOUNT_:
	     case rVARs_RECINTERVAL_:
	     case zVAR_RECINTERVAL_:
	     case ATTR_:
	     case gENTRY_:
	     case rENTRY_:
	     case zENTRY_:
	     {
	       long value;
	       status = CDFlib (CONFIRM_, item, &value,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreLong (argv[argX++], value);
	       break;
	     }
	     /*****************************************************************
	     * CONFIRM_,<in: `long' value>
	     *****************************************************************/
	     case gENTRY_EXISTENCE_:
	     case rENTRY_EXISTENCE_:
	     case zENTRY_EXISTENCE_:
	     {
	       long value;
	       if (!CastToLong(argv[argX++],&value)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (CONFIRM_, item, value,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * CONFIRM_,<array of `long' values>
	     *****************************************************************/
	     case rVARs_DIMINDICES_:
	     case zVAR_DIMINDICES_:
	     case rVARs_DIMCOUNTS_:
	     case zVAR_DIMCOUNTS_:
	     case rVARs_DIMINTERVALS_:
	     case zVAR_DIMINTERVALS_:
	     {
	       long values[CDF_MAX_DIMS];	/* CDF_MAX_DIMS is only case.*/
	       status = CDFlib (CONFIRM_, item, values,
				NULL_);
	       CSC (status, pStatus, rCode)
	       if (!StoreLongArray(argv[argX++],
				   CDF_MAX_DIMS,values)) RETURNx (BAD_MALLOC)
	       break;
	     }
	     /*****************************************************************
	     * CONFIRM_,<`long' value, array of `long' values>
	     *****************************************************************/
	     case rVAR_SEQPOS_:
	     case zVAR_SEQPOS_:
	     {
	       long value;
	       long values[CDF_MAX_DIMS];	/* CDF_MAX_DIMS is only case.*/
	       status = CDFlib (CONFIRM_, item, &value, values,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreLong (argv[argX++], value);
	       if (!StoreLongArray(argv[argX++],
				   CDF_MAX_DIMS,values)) RETURNx (BAD_MALLOC)
	       break;
	     }
	     /*****************************************************************
	     * CONFIRM_,<out: character string>
	     *****************************************************************/
	     case CDF_NAME_:
	     {
	       char string[CDF_PATHNAME_LEN+1];	/* Currently the only case. */
	       status = CDFlib (CONFIRM_, item, string,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreString (argv[argX++], string);
	       break;
	     }
	     /*****************************************************************
	     * CONFIRM_,<in: character string>
	     *****************************************************************/
	     case rVAR_EXISTENCE_:
	     case zVAR_EXISTENCE_:
	     case ATTR_EXISTENCE_:
	     {
	       char *string;
	       if (!StringPtr(argv[argX++],&string)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (CONFIRM_, item, string,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * GET_, get an item.
      ************************************************************************/
      case GET_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * GET_,<longword value>
	     *****************************************************************/
	     case rVARs_NUMDIMS_:
	     case zVAR_NUMDIMS_:
	     case CDF_ENCODING_:
	     case CDF_MAJORITY_:
	     case CDF_FORMAT_:
	     case CDF_NUMrVARS_:
	     case CDF_NUMzVARS_:
	     case CDF_NUMATTRS_:
	     case CDF_NUMgATTRS_:
	     case CDF_NUMvATTRS_:
	     case CDF_VERSION_:
	     case CDF_RELEASE_:
	     case CDF_INCREMENT_:
	     case LIB_VERSION_:
	     case LIB_RELEASE_:
	     case LIB_INCREMENT_:
	     case rVARs_MAXREC_:
	     case zVARs_MAXREC_:
	     case rVAR_DATATYPE_:
	     case zVAR_DATATYPE_:
	     case rVAR_NUMELEMS_:
	     case zVAR_NUMELEMS_:
	     case rVAR_RECVARY_:
	     case zVAR_RECVARY_:
	     case rVAR_MAXREC_:
	     case zVAR_MAXREC_:
	     case rVAR_MAXallocREC_:
	     case zVAR_MAXallocREC_:
	     case rVAR_EXTENDRECS_:
	     case zVAR_EXTENDRECS_:
	     case rVAR_nINDEXRECORDS_:
	     case zVAR_nINDEXRECORDS_:
	     case rVAR_nINDEXENTRIES_:
	     case zVAR_nINDEXENTRIES_:
	     case ATTR_SCOPE_:
	     case ATTR_MAXgENTRY_:
	     case ATTR_MAXrENTRY_:
	     case ATTR_MAXzENTRY_:
	     case ATTR_NUMgENTRIES_:
	     case ATTR_NUMrENTRIES_:
	     case ATTR_NUMzENTRIES_:
	     case gENTRY_DATATYPE_:
	     case rENTRY_DATATYPE_:
	     case zENTRY_DATATYPE_:
	     case gENTRY_NUMELEMS_:
	     case rENTRY_NUMELEMS_:
	     case zENTRY_NUMELEMS_:
	     {
	       long value;
	       status = CDFlib (GET_, item, &value,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreLong (argv[argX++], value);
	       break;
	     }
	     /*****************************************************************
	     * GET_,<longword value In, longword value Out>
	     *****************************************************************/
	     case DATATYPE_SIZE_:
	     {
	       long value1, value2;
	       if (!CastToLong(argv[argX++],&value1)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (GET_, item, value1, &value2,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreLong (argv[argX++], value2);
	       break;
	     }
	     /*****************************************************************
	     * GET_,<longword array of values>
	     *****************************************************************/
	     case rVARs_DIMSIZES_:
	     case zVAR_DIMSIZES_:
	     case rVAR_DIMVARYS_:
	     case zVAR_DIMVARYS_:
	     {
	       long values[CDF_MAX_DIMS];	/* CDF_MAX_DIMS is only case.*/
	       status = CDFlib (GET_, item, values,
				NULL_);
	       CSC (status, pStatus, rCode)
	       if (!StoreLongArray(argv[argX++],
				   CDF_MAX_DIMS,values)) RETURNx (BAD_MALLOC)
	       break;
	     }
	     /*****************************************************************
	     * GET_,<character string>
	     *****************************************************************/
	     case CDF_COPYRIGHT_:
	     case LIB_COPYRIGHT_:
	     case rVAR_NAME_:
	     case zVAR_NAME_:
	     case ATTR_NAME_:
	     {
	       char *string;
	       size_t nChars;
	       switch (item) {
		 case CDF_COPYRIGHT_:
		 case LIB_COPYRIGHT_:
		   nChars = CDF_COPYRIGHT_LEN;
		   break;
		 case rVAR_NAME_:
		 case zVAR_NAME_:
		   nChars = CDF_VAR_NAME_LEN;
		   break;
		 case ATTR_NAME_:
		   nChars = CDF_ATTR_NAME_LEN;
		   break;
	       }
	       string = (char *) malloc (nChars + 1);
	       if (string == NULL) RETURNx (BAD_MALLOC)
	       status = CDFlib (GET_, item, string,
				 NULL_);
	       StoreString (argv[argX++], string);	/* Before checking */
	       free (string);				/* the status code. */
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * GET_,<character string in/longword out>
	     *****************************************************************/
	     case rVAR_NUMBER_:
	     case zVAR_NUMBER_:
	     case ATTR_NUMBER_:
	     {
	       char *valueIn;
	       long valueOut;
	       if (!StringPtr(argv[argX++],&valueIn)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (GET_, item, valueIn, &valueOut,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreLong (argv[argX++], valueOut);
	       break;
	     }
	     /*****************************************************************
	     * GET_,LIB_subINCREMENT_: get the library's sub-increment
	     * character.
	     *****************************************************************/
	     case LIB_subINCREMENT_: {
	       char subIncrement[1+1];
	       status = CDFlib (GET_, LIB_subINCREMENT_, &(subIncrement[0]),
				NULL_);
	       CSC (status, pStatus, rCode)
	       subIncrement[1] = NUL;
	       StoreString (argv[argX++], subIncrement);
	       break;
	     }
	     /*****************************************************************
	     * GET_,rVAR_PADVALUE_/zVAR_PADVALUE_: get the variable pad value.
	     *	    rVAR_DATA_/zVAR_DATA_:	   get a variable single value.
	     *	    rVAR_SEQDATA_/zVAR_SEQDATA_:   get a variable sequential
	     *					   value.
	     *****************************************************************/
	     case rVAR_PADVALUE_:
	     case zVAR_PADVALUE_:
	     case rVAR_DATA_:
	     case zVAR_DATA_:
	     case rVAR_SEQDATA_:
	     case zVAR_SEQDATA_: {
	       Logical Zop = (item == zVAR_PADVALUE_ || item == zVAR_DATA_ ||
			      item == zVAR_SEQDATA_);
	       long dataType, numElems;
	       long nBytes;
	       void *value;
	       status = CDFlib (GET_, Zq(Zop,zVAR_DATATYPE_,
					     rVAR_DATATYPE_), &dataType,
				      Zq(Zop,zVAR_NUMELEMS_,
					     rVAR_NUMELEMS_), &numElems,
				NULL_);
	       CSC (status, pStatus, rCode)
	       nBytes = (STRINGdataType(dataType) ?
			 numElems + 1 : CDFelemSize(dataType));
	       value = (void *) malloc (nBytes);
	       if (value == NULL) RETURNx (BAD_MALLOC)
	       status = CDFlib (GET_, item, value,
				NULL_);
	       if (STRINGdataType(dataType)) {
		 ((char *) value)[numElems] = NUL;
		 StoreString (argv[argX++], value);
	       }
	       else
		 StoreScalar (argv[argX++], dataType, value);
	       free (value);
	       CSC (status, pStatus, rCode)	/* Check after freeing. */
	       break;
	     }
	     /*****************************************************************
	     * GET_,rVAR_HYPERDATA_/zVAR_HYPERDATA_: get a variable hyper
	     * buffer of values.
	     *****************************************************************/
	     case rVAR_HYPERDATA_:
	     case zVAR_HYPERDATA_: {
	       Logical Zop = (item == zVAR_HYPERDATA_);
	       long numDims;
	       long dataType, numElems;
	       long recCount, dimCounts[CDF_MAX_DIMS], tCounts[CDF_MAX_DIMS+1];
	       long nRecValues, recX;
	       long nValueBytes, nRecBytes, nBytes;
	       int dimN;
	       void *buffer;
	       status = CDFlib (GET_, Zq(Zop,zVAR_NUMDIMS_,
					     rVARs_NUMDIMS_), &numDims,
				      Zq(Zop,zVAR_DATATYPE_,
					     rVAR_DATATYPE_), &dataType,
				      Zq(Zop,zVAR_NUMELEMS_,
					     rVAR_NUMELEMS_), &numElems,
				CONFIRM_, Zq(Zop,zVAR_RECCOUNT_,
					         rVARs_RECCOUNT_), &recCount,
					  Zq(Zop,zVAR_DIMCOUNTS_,
					         rVARs_DIMCOUNTS_), dimCounts,
				NULL_);
	       CSC (status, pStatus, rCode)
	       nRecValues = 1;
	       for (dimN = 0; dimN < numDims; dimN++)
		  nRecValues *= dimCounts[dimN];
	       nValueBytes = CDFelemSize(dataType) * numElems;
	       nRecBytes = nRecValues * nValueBytes;
	       nBytes = nRecBytes * recCount;
	       buffer = (void *) malloc (nBytes);
	       if (buffer == NULL) RETURNx (BAD_MALLOC)
	       status = CDFlib (GET_, item, buffer,
				NULL_);
	       for (dimN = 0; dimN < numDims; dimN++) {
		  tCounts[dimN] = dimCounts[dimN];
	       }
	       tCounts[numDims] = recCount;
	       if (!StoreMultiArray(argv[argX++],dataType,numElems,
				    numDims+1,tCounts,buffer)) {
		 free (buffer);
		 RETURNx (BAD_MALLOC)
	       }
	       free (buffer);
	       CSC (status, pStatus, rCode)	/* Check after freeing. */
	       break;
	     }
	     /*****************************************************************
	     * GET_,rVARs_RECDATA_/zVARs_RECDATA_: Unsupported.
	     *****************************************************************/
	     case rVARs_RECDATA_:
	     case zVARs_RECDATA_:
	     {
	       RETURNx (UNSUPPORTED_OPERATION)
	       break;
	     }
	     /*****************************************************************
	     * GET_,gENTRY_DATA_/rENTRY_DATA_/zENTRY_DATA_: get an entry value.
	     *****************************************************************/
	     case gENTRY_DATA_:
	     case rENTRY_DATA_:
	     case zENTRY_DATA_: {
	       int Et = E3p(item,gENTRY_DATA_,rENTRY_DATA_,zENTRY_DATA_);
	       long dataType, numElems; size_t nBytes; void *value;
	       status = CDFlib (GET_, E3(Et,gENTRY_DATATYPE_,
					    rENTRY_DATATYPE_,
					    zENTRY_DATATYPE_), &dataType,
				      E3(Et,gENTRY_NUMELEMS_,
					    rENTRY_NUMELEMS_,
					    zENTRY_NUMELEMS_), &numElems,
				NULL_);
	       CSC (status, pStatus, rCode)
	       nBytes = (CDFelemSize(dataType) * numElems) +
			(STRINGdataType(dataType) ? 1 : 0);
	       value = (void *) malloc (nBytes);
	       if (value == NULL) RETURNx (BAD_MALLOC)
	       status = CDFlib (GET_, item, value,
				NULL_);
	       if (STRINGdataType(dataType)) {
		 ((char *) value)[numElems] = NUL;
		 StoreString (argv[argX++], value);
	       }
	       else
		 if (numElems > 1) {
		   if (!StoreMultiArray(argv[argX++],dataType,1L,1L,
					&numElems,value)) {
		     free (value);
		     RETURNx (BAD_MALLOC)
		   }
		 }
		 else
		   StoreScalar (argv[argX++], dataType, value);
	       free (value);
	       CSC (status, pStatus, rCode)	/* Check after freeing. */
	       break;
	     }
	     /*****************************************************************
	     * GET_,STATUS_TEXT_: get text for a status code.
	     *****************************************************************/
	     case STATUS_TEXT_:
	     {
	       char text[CDF_STATUSTEXT_LEN+1];
	       status = CDFlib (GET_, STATUS_TEXT_, text,
				NULL_);
	       CSC (status, pStatus, rCode)
	       StoreString (argv[argX++], text);
	       break;
	     }
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * PUT_, put an item.
      ************************************************************************/
      case PUT_:
	for (;;) {
	   if (!CastToLong(argv[argX++],&item)) RETURNx (BAD_ARGUMENT)
	   switch (item) {
	     /*****************************************************************
	     * PUT_,<long value>
	     *****************************************************************/
	     case CDF_ENCODING_:
	     case CDF_MAJORITY_:
	     case CDF_FORMAT_:
	     case rVAR_RECVARY_:
	     case zVAR_RECVARY_:
	     case rVAR_ALLOCATERECS_:
	     case zVAR_ALLOCATERECS_:
	     case rVAR_INITIALRECS_:
	     case zVAR_INITIALRECS_:
	     case rVAR_EXTENDRECS_:
	     case zVAR_EXTENDRECS_:
	     case ATTR_SCOPE_:
	     {
	       long value;
	       if (!CastToLong(argv[argX++],&value)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (PUT_, item, value,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * PUT_,<2 long values>
	     *****************************************************************/
	     case rVAR_DATASPEC_:
	     case zVAR_DATASPEC_:
	     case gENTRY_DATASPEC_:
	     case rENTRY_DATASPEC_:
	     case zENTRY_DATASPEC_:
	     {
	       long value1, value2;
	       if (!CastToLong(argv[argX++],&value1)) RETURNx (BAD_ARGUMENT)
	       if (!CastToLong(argv[argX++],&value2)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (PUT_, item, value1, value2,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * PUT_,<array of long values>
	     *****************************************************************/
	     case rVAR_DIMVARYS_:
	     case zVAR_DIMVARYS_:
	     {
	       long values[CDF_MAX_DIMS];
	       if (!BuildLongArray(argv[argX++],
				   values,CDF_MAX_DIMS)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (PUT_, item, values,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * PUT_,<character string>
	     *****************************************************************/
	     case rVAR_NAME_:
	     case zVAR_NAME_:
	     case ATTR_NAME_:
	     {
	       char *string;
	       if (!StringPtr(argv[argX++],&string)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (PUT_, item, string,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * PUT_,rVAR_PADVALUE_/zVAR_PADVALUE_: put a variable pad value
	     *	    rVAR_DATA_/zVAR_DATA_: put a variable single value
	     *	    rVAR_SEQDATA_/zVAR_SEQDATA_: put a variable sequential
	     *					 value
	     *****************************************************************/
	     case rVAR_PADVALUE_:
	     case zVAR_PADVALUE_:
	     case rVAR_DATA_:
	     case zVAR_DATA_:
	     case rVAR_SEQDATA_:
	     case zVAR_SEQDATA_:
	     {
	       void *value;
	       if (!DataPtr(argv[argX++],&value)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (PUT_, item, value,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * PUT_,rVAR_HYPERDATA_/zVAR_HYPERDATA_: put a buffer of values.
	     *****************************************************************/
	     case rVAR_HYPERDATA_:
	     case zVAR_HYPERDATA_:
	     {
	       Logical Zop = (item == zVAR_HYPERDATA_);
	       void *buffer;
	       void *xBuffer;
	       long numDims;
	       long dataType, numElems;
	       long recCount, dimCounts[CDF_MAX_DIMS];
	       long nRecValues, recX, valueN, nValues;
	       long nValueBytes, nRecBytes, nBytes;
	       int dimN;
	       if (!DataPtr(argv[argX++],&buffer)) RETURNx (BAD_ARGUMENT)

	       status = CDFlib (GET_, Zq(Zop,zVAR_NUMDIMS_,
					     rVARs_NUMDIMS_), &numDims,
				      Zq(Zop,zVAR_DATATYPE_,
					     rVAR_DATATYPE_), &dataType,
				      Zq(Zop,zVAR_NUMELEMS_,
					     rVAR_NUMELEMS_), &numElems,
				CONFIRM_, Zq(Zop,zVAR_RECCOUNT_,
						 rVARs_RECCOUNT_), &recCount,
					  Zq(Zop,zVAR_DIMCOUNTS_,
						 rVARs_DIMCOUNTS_), dimCounts,
				NULL_);
	       CSC (status, pStatus, rCode)

	       nRecValues = 1;
	       for (dimN = 0; dimN < numDims; dimN++) {
		  nRecValues *= dimCounts[dimN];
	       }
	       nValues = nRecValues * recCount;
	       nValueBytes = CDFelemSize(dataType) * numElems;
	       nRecBytes = nRecValues * nValueBytes;
	       nBytes = nRecBytes * recCount;

	       if (STRINGdataType(dataType)) {
		 IDL_STRING *str = (IDL_STRING *) buffer; char *tBuffer;
		 xBuffer = (char *) malloc (nBytes);
		 if (xBuffer == NULL) RETURNx (BAD_MALLOC)
		 for (valueN = 0, tBuffer = xBuffer; valueN < nValues;
		      valueN++, str++, tBuffer += numElems) {
		    strcpyX (tBuffer, IDL_STRING_STR(str), numElems);
		 }
	       }
	       else
		 xBuffer = buffer;
	       status = CDFlib (PUT_, item, xBuffer,
				NULL_);
	       if (xBuffer != buffer) free (xBuffer);
	       CSC (status, pStatus, rCode)	/* Check after freeing. */
	       break;
	     }
	     /*****************************************************************
	     * PUT_,rVARs_RECDATA_/zVARs_RECDATA_: Unsupported.
	     *****************************************************************/
	     case rVARs_RECDATA_:
	     case zVARs_RECDATA_:
	     {
#if 0
	       /***************************************************************
	       * This doesn't work yet because the layout of the values in the
	       * buffer is not known (IDL won't tell us) if a structure is used
	       * by the caller...
	       ***************************************************************/
	       long nVars, *varNs;
	       void *value;
	       if (!CastToLong(argv[argX++],&nVars)) RETURNx (BAD_ARGUMENT)
	       if (nVars < 1) RETURNx (BAD_NUM_VARS)
	       varNs = (long *) malloc ((size_t) (nVars * sizeof(long)));
	       if (varNs == NULL) RETURNx (BAD_MALLOC)
	       if (!BuildLongArray(argv[argX++],varNs,(int)nVars)) {
		 free (varNs);
		 RETURNx (BAD_ARGUMENT)
	       }
	       if (!DataPtr(argv[argX++],&value)) {
		 free (varNs);
		 RETURNx (BAD_ARGUMENT)
	       }
	       status = CDFlib (PUT_, item, nVars, varNs, value,
				NULL_);
	       free (varNs);			/* Before checking status. */
	       CSC (status, pStatus, rCode)
	       break;
#else
	       RETURNx (UNSUPPORTED_OPERATION)
	       break;
#endif
	     }
	     /*****************************************************************
	     * PUT_,gENTRY_DATA_/rENTRY_DATA/zENTRY_DATA_: put an entry value
	     *****************************************************************/
	     case gENTRY_DATA_:
	     case rENTRY_DATA_:
	     case zENTRY_DATA_:
	     {
	       long dataType, numElems; void *value;
	       if (!CastToLong(argv[argX++],&dataType)) RETURNx (BAD_ARGUMENT)
	       if (!CastToLong(argv[argX++],&numElems)) RETURNx (BAD_ARGUMENT)
	       if (!DataPtr(argv[argX++],&value)) RETURNx (BAD_ARGUMENT)
	       status = CDFlib (PUT_, item, dataType, numElems, value,
				NULL_);
	       CSC (status, pStatus, rCode)
	       break;
	     }
	     /*****************************************************************
	     * Unknown item - hopefully the next operation.
	     *****************************************************************/
	     default: {
	       fnc = item;
	       break;
	     }
	   }
	   if (fnc == item) break;
        }
        break;
      /************************************************************************
      * Unknown function.
      ************************************************************************/
      default:
	RETURNx (BAD_FNC_OR_ITEM)
    }
  }
  RETURNx (pStatus)
}

/******************************************************************************
* idl_epochbreak.
******************************************************************************/

IDL_VPTR idl_epochbreak (argc, argv)
int argc;
IDL_VPTR argv[];
{
  long year, month, day, hour, minute, second, msec; double epoch;
  if (!CastToDouble(argv[0],&epoch)) RETURNx (BAD_ARGUMENT)
  EPOCHbreakdown (epoch, &year, &month, &day, &hour, &minute, &second, &msec);
  StoreLong (argv[1], year);
  StoreLong (argv[2], month);
  StoreLong (argv[3], day);
  StoreLong (argv[4], hour);
  StoreLong (argv[5], minute);
  StoreLong (argv[6], second);
  StoreLong (argv[7], msec);
  RETURNx (0)
}

/******************************************************************************
* idl_computepoch.
******************************************************************************/

IDL_VPTR idl_computepoch (argc, argv)
int argc;
IDL_VPTR argv[];
{
  static IDL_VARIABLE rEpoch; double epoch;
  long year, month, day, hour, minute, second, msec;
  if (!CastToLong(argv[0],&year)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[1],&month)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[2],&day)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[3],&hour)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[4],&minute)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[5],&second)) RETURNx (BAD_ARGUMENT)
  if (!CastToLong(argv[6],&msec)) RETURNx (BAD_ARGUMENT)
  epoch = computeEPOCH(year,month,day,hour,minute,second,msec);
  StoreScalar ((IDL_VPTR) &rEpoch, CDF_EPOCH, &epoch);
  return ((IDL_VPTR) &rEpoch);
}
/******************************************************************************
* idl_parseepoch.
******************************************************************************/

IDL_VPTR idl_parsepoch (argc, argv)
int argc;
IDL_VPTR argv[];
{
  static IDL_VARIABLE rEpoch; char *epString; double epoch;
  if (!StringPtr(argv[0],&epString)) RETURNx (BAD_ARGUMENT)
  epoch = parseEPOCH (epString);
  StoreScalar ((IDL_VPTR) &rEpoch, CDF_EPOCH, &epoch);
  return ((IDL_VPTR) &rEpoch);
}

/******************************************************************************
* idl_encodepoch.
******************************************************************************/

IDL_VPTR idl_encodepoch (argc, argv)
int argc;
IDL_VPTR argv[];
{
  double epoch; char epString[EPOCH_STRING_LEN+1];
  if (!CastToDouble(argv[0],&epoch)) RETURNx (BAD_ARGUMENT)
  encodeEPOCH (epoch, epString);
  StoreString (argv[1], epString);
  RETURNx (0)
}

/******************************************************************************
* idl_encodepoch1.
******************************************************************************/

IDL_VPTR idl_encodepoch1 (argc, argv)
int argc;
IDL_VPTR argv[];
{
  double epoch; char epString[EPOCH1_STRING_LEN+1];
  if (!CastToDouble(argv[0],&epoch)) RETURNx (BAD_ARGUMENT)
  encodeEPOCH1 (epoch, epString);
  StoreString (argv[1], epString);
  RETURNx (0)
}

/******************************************************************************
* idl_encodepoch2.
******************************************************************************/

IDL_VPTR idl_encodepoch2 (argc, argv)
int argc;
IDL_VPTR argv[];
{
  double epoch; char epString[EPOCH2_STRING_LEN+1];
  if (!CastToDouble(argv[0],&epoch)) RETURNx (BAD_ARGUMENT)
  encodeEPOCH2 (epoch, epString);
  StoreString (argv[1], epString);
  RETURNx (0)
}

/******************************************************************************
* idl_encodepoch3.
******************************************************************************/

IDL_VPTR idl_encodepoch3 (argc, argv)
int argc;
IDL_VPTR argv[];
{
  double epoch; char epString[EPOCH3_STRING_LEN+1];
  if (!CastToDouble(argv[0],&epoch)) RETURNx (BAD_ARGUMENT)
  encodeEPOCH3 (epoch, epString);
  StoreString (argv[1], epString);
  RETURNx (0)
}

/******************************************************************************
* idl_encodepochx.
******************************************************************************/

IDL_VPTR idl_encodepochx (argc, argv)
int argc;
IDL_VPTR argv[];
{
  double epoch; char epString[EPOCHx_STRING_MAX+1], *format;
  if (!CastToDouble(argv[0],&epoch)) RETURNx (BAD_ARGUMENT)
  if (!StringPtr(argv[1],&format)) RETURNx (BAD_ARGUMENT)
  encodeEPOCHx (epoch, format, epString);
  StoreString (argv[2], epString);
  RETURNx (0)
}

/******************************************************************************
* If on a UNIX machine, include CDF library source files.
******************************************************************************/

#if defined(unix)
#include "cdflib.c"
#include "cdfcre.c"
#include "cdfope.c"
#include "cdfclo.c"
#include "cdfdel.c"
#include "cdfget.c"
#include "cdfput1.c"
#include "cdfput2.c"
#include "cdfsel.c"
#include "cdfcon.c"
#include "cdfread.c"
#include "cdfwrite.c"
#include "cdftext.c"
#include "cdfed.c"
#include "cdfstr.c"
#include "cdfvalid.c"
#include "cdfhyper.c"
#include "cdfmisc1.c"
#include "cdfmisc2.c"
#include "cdfmem.c"
#include "vstream.c"
#include "epochu.c"
#include "dirutils.c"
#endif
