/******************************************************************************
*
*  NSSDC/CDF                                        CDF `confirm' operations.
*
*  Version 1.4b, 4-Aug-95, Hughes STX.
*
*  Modification history:
*
*   V1.0  20-May-92, J Love     Original version (was part of `cdflib.c').
*   V1.1  21-Aug-92, J Love     CDF V2.3 (shareable/NeXT/zVar).
*   V1.2  21-Dec-93, J Love     CDF V2.4.
*   V1.2a 22-Feb-94, J Love     Spelling lesson.
*   V1.3  19-Dec-94, J Love     CDF V2.5.
*   V1.3a 24-Feb-95, J Love	Solaris 2.3 IDL i/f.
*   V1.4  15-May-95, J Love	Added <CONFIRM_,CDF_>.
*   V1.4a  8-Jun-95, J Love	Added <CONFIRM_,r/zVAR_PADVALUE_>.
*   V1.4b  4-Aug-95, J Love	CDFexport-related changes.
*
******************************************************************************/

#include "cdflib.h"

/******************************************************************************
* CDFcon.
******************************************************************************/

STATICforIDL CDFstatus CDFcon (Va, Cur)
struct VAstruct *Va;
struct CURstruct *Cur;
{
CDFstatus tStatus, pStatus = CDF_OK;

switch (Va->item) {
  /****************************************************************************
  * CDF_
  ****************************************************************************/
  case CDF_: {
    struct cdfSTRUCT *CDF;
    CDFid *id = va_arg (Va->ap, CDFid *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    *id = CDF;
    break;
  }
  /****************************************************************************
  * CDF_NAME_
  ****************************************************************************/
  case CDF_NAME_: {
    struct cdfSTRUCT *CDF;
    char *cdfname = va_arg (Va->ap, char *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    strcpyX (cdfname, CDF->cdfname, CDF_PATHNAME_LEN);
    break;
  }
  /****************************************************************************
  * CDF_READONLY_MODE_
  ****************************************************************************/
  case CDF_READONLY_MODE_: {
    struct cdfSTRUCT *CDF;
    long *mode = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    *mode = CDF->readonlyMode;
    break;
  }
  /****************************************************************************
  * CDF_zMODE_
  ****************************************************************************/
  case CDF_zMODE_: {
    struct cdfSTRUCT *CDF;
    long *mode = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    *mode = CDF->zMode;
    break;
  }
  /****************************************************************************
  * CDF_NEGtoPOSfp0_MODE_
  ****************************************************************************/
  case CDF_NEGtoPOSfp0_MODE_: {
    struct cdfSTRUCT *CDF;
    long *mode = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    *mode = CDF->negToPosFp0mode;
    break;
  }
  /****************************************************************************
  * CDF_DECODING_
  ****************************************************************************/
  case CDF_DECODING_: {
    struct cdfSTRUCT *CDF;
    long *decoding = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    *decoding = CDF->decoding;
    break;
  }
  /****************************************************************************
  * CDF_CACHESIZE_
  ****************************************************************************/
  case CDF_CACHESIZE_: {
    struct cdfSTRUCT *CDF;
    long *nBuffers = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    *nBuffers = (long) CDF->nCacheBuffers;
    break;
  }
  /****************************************************************************
  * rVAR_CACHESIZE_/zVAR_CACHESIZE_
  ****************************************************************************/
  case rVAR_CACHESIZE_:
  case zVAR_CACHESIZE_: {
    Logical zOp = (Va->item == zVAR_CACHESIZE_);
    struct cdfSTRUCT *CDF;
    struct varSTRUCT *Var;
    long *nBuffers = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
    if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
    if (!CDF->singleFile) {
      if (!sX(InitCurrentVar(CDF,zOp,&Var),&pStatus)) {
	AbortAccess (CDF, FALSE, Cur);
	return pStatus;
      }
      *nBuffers = (long) Var->nCacheBuffers;
    }
    else {
      sX (SINGLE_FILE_FORMAT, &pStatus);
    }
    break;
  }
  /****************************************************************************
  * rVAR_/zVAR_
  ****************************************************************************/
  case rVAR_:
  case zVAR_: {
    Logical zOp = (Va->item == zVAR_);
    struct cdfSTRUCT *CDF;
    long *varNum = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
    if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
    *varNum = BOO(zOp,CDF->CURzVarNum,CDF->CURrVarNum);
    break;
  }
  /****************************************************************************
  * rVAR_PADVALUE_/zVAR_PADVALUE_
  ****************************************************************************/
  case rVAR_PADVALUE_:
  case zVAR_PADVALUE_: {
    Logical zOp = (Va->item == zVAR_PADVALUE_), zVar;
    struct cdfSTRUCT *CDF;
    Int32 offset, flags;
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
    if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
    if (!sX(LocateCurrentVar(CDF,zOp,&offset,&zVar,NULL),&pStatus)) {
      AbortAccess (CDF, FALSE, Cur);
      return pStatus;
    }
    if (!sX(ReadVDR(CDF,offset,zVar,VDR_FLAGS,&flags,
				    VDR_NULL),&pStatus)) {
      AbortAccess (CDF, FALSE, Cur);
      return pStatus;
    }
    if (!PADvalueBITset(flags)) sX (NO_PADVALUE_SPECIFIED, &pStatus);
    break;
  }
  /****************************************************************************
  * rVAR_EXISTENCE_/zVAR_EXISTENCE_, confirm the existence of a named variable.
  ****************************************************************************/
  case rVAR_EXISTENCE_:
  case zVAR_EXISTENCE_: {
    Logical zOp = (Va->item == zVAR_EXISTENCE_), zVar;
    struct cdfSTRUCT *CDF;
    char *varName = va_arg (Va->ap, char *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
    tStatus = FindVarByName (CDF, varName, NULL, &zVar, NULL);
    switch (tStatus) {
      case CDF_OK:
	break;
      case NO_SUCH_VAR:
	return tStatus;
      default:
	AbortAccess (CDF, FALSE, Cur);
	return tStatus;
    }
    if (!zModeON(CDF)) {
      if ((zVar && !zOp) || (!zVar && zOp)) return NO_SUCH_VAR; /*Wrong type*/
    }
    break;
  }
  /****************************************************************************
  * rVARs_RECNUMBER_/rVARs_RECCOUNT_/rVARs_RECINTERVAL_
  ****************************************************************************/
  case rVARs_RECNUMBER_:
  case rVARs_RECCOUNT_:
  case rVARs_RECINTERVAL_: {
    struct cdfSTRUCT *CDF;
    long *value = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,TRUE)) return ILLEGAL_IN_zMODE;
    if (CDF->NrVars == 0) {
      if (!sX(NO_VARS_IN_CDF,&pStatus)) return pStatus;
    }
    switch (Va->item) {
      case rVARs_RECNUMBER_:
	*value = CDF->rRD.recNumber;
	break;
      case rVARs_RECCOUNT_:
	*value = CDF->rRD.recCount;
	break;
      case rVARs_RECINTERVAL_:
	*value = CDF->rRD.recInterval;
	break;
    }
    break;
  }
  /****************************************************************************
  * zVAR_RECNUMBER_/zVAR_RECCOUNT_/zVAR_RECINTERVAL_
  ****************************************************************************/
  case zVAR_RECNUMBER_:
  case zVAR_RECCOUNT_:
  case zVAR_RECINTERVAL_: {
    struct cdfSTRUCT *CDF;
    struct varSTRUCT *Var;
    long *value = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (!CURRENTvarSELECTED(CDF,TRUE)) return NO_VAR_SELECTED;
    if (!sX(InitCurrentVar(CDF,TRUE,&Var),&pStatus)) {
      AbortAccess (CDF, FALSE, Cur);
      return pStatus;
    }
    switch (Va->item) {
      case zVAR_RECNUMBER_:
	*value = Var->zRD.recNumber;
	break;
      case zVAR_RECCOUNT_:
	*value = Var->zRD.recCount;
	break;
      case zVAR_RECINTERVAL_:
	*value = Var->zRD.recInterval;
	break;
    }
    break;
  }
  /****************************************************************************
  * rVARs_DIMINDICES_/rVARs_DIMCOUNTS_/rVARs_DIMINTERVALS_
  ****************************************************************************/
  case rVARs_DIMINDICES_:
  case rVARs_DIMCOUNTS_:
  case rVARs_DIMINTERVALS_: {
    struct cdfSTRUCT *CDF;
    int dimN;
    long *values = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,TRUE)) return ILLEGAL_IN_zMODE;
    if (CDF->NrVars == 0) {
      if (!sX(NO_VARS_IN_CDF,&pStatus)) return pStatus;
    }
    switch (Va->item) {
      case rVARs_DIMINDICES_:
	for (dimN = 0; dimN < CDF->rNumDims; dimN++)
	   values[dimN] = CDF->rRD.dimIndices[dimN];
	break;
      case rVARs_DIMCOUNTS_:
	for (dimN = 0; dimN < CDF->rNumDims; dimN++)
	   values[dimN] = CDF->rRD.dimCounts[dimN];
	break;
      case rVARs_DIMINTERVALS_:
	for (dimN = 0; dimN < CDF->rNumDims; dimN++)
	   values[dimN] = CDF->rRD.dimIntervals[dimN];
	break;
    }
    break;
  }
  /****************************************************************************
  * zVAR_DIMINDICES_/zVAR_DIMCOUNTS_/zVAR_DIMINTERVALS_
  ****************************************************************************/
  case zVAR_DIMINDICES_:
  case zVAR_DIMCOUNTS_:
  case zVAR_DIMINTERVALS_: {
    struct cdfSTRUCT *CDF;
    struct varSTRUCT *Var;
    int dimN;
    long *values = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (!CURRENTvarSELECTED(CDF,TRUE)) return NO_VAR_SELECTED;
    if (!sX(InitCurrentVar(CDF,TRUE,&Var),&pStatus)) {
      AbortAccess (CDF, FALSE, Cur);
      return pStatus;
    }
    switch (Va->item) {
      case zVAR_DIMINDICES_:
	for (dimN = 0; dimN < Var->numDims; dimN++)
	   values[dimN] = Var->zRD.dimIndices[dimN];
	break;
      case zVAR_DIMCOUNTS_:
	for (dimN = 0; dimN < Var->numDims; dimN++)
	   values[dimN] = Var->zRD.dimCounts[dimN];
	break;
      case zVAR_DIMINTERVALS_:
	for (dimN = 0; dimN < Var->numDims; dimN++)
	   values[dimN] = Var->zRD.dimIntervals[dimN];
	break;
    }
    break;
  }
  /****************************************************************************
  * rVAR_SEQPOS_/zVAR_SEQPOS_
  ****************************************************************************/
  case rVAR_SEQPOS_:
  case zVAR_SEQPOS_: {
    Logical zOp = (Va->item == zVAR_SEQPOS_);
    struct cdfSTRUCT *CDF;
    struct varSTRUCT *Var;
    long Voffset;               /* Value offset within record. */
    long *recNumber = va_arg (Va->ap, long *);
    long *dimIndices = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
    if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
    if (!sX(InitCurrentVar(CDF,zOp,&Var),&pStatus)) {
      AbortAccess (CDF, FALSE, Cur);
      return pStatus;
    }
    *recNumber = Var->seqValueOffset / Var->NphyRecValues;
    Voffset = Var->seqValueOffset % Var->NphyRecValues;
    ValueOffsetIndices (Voffset, CDF->rowMajor, Var->numDims, Var->dimVarys,
			Var->nPhyDimValues, dimIndices);
    break;
  }
  /****************************************************************************
  * ATTR_
  ****************************************************************************/
  case ATTR_: {
    struct cdfSTRUCT *CDF; Int32 tAttrNum;
    long *attrNum = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (!CURRENTattrSELECTED(CDF)) return NO_ATTR_SELECTED;
    if (!sX(ReadADR(CDF,CDF->CURattrOffset,
		    ADR_NUM,&tAttrNum,ADR_NULL),&pStatus)) {
      AbortAccess (CDF, FALSE, Cur);
      return pStatus;
    }
    *attrNum = (long) tAttrNum;
    break;
  }
  /****************************************************************************
  * ATTR_EXISTENCE_, confirms the existence of a named attribute.
  ****************************************************************************/
  case ATTR_EXISTENCE_: {
    struct cdfSTRUCT *CDF;
    char *attrName = va_arg (Va->ap, char *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    tStatus = FindAttrByName (CDF, attrName, NULL);
    switch (tStatus) {
      case CDF_OK:
	break;
      case NO_SUCH_ATTR:
	return tStatus;;
      default:
	AbortAccess (CDF, FALSE, Cur);
	return tStatus;
    }
    break;
  }
  /****************************************************************************
  * gENTRY_/rENTRY_/zENTRY_
  ****************************************************************************/
  case rENTRY_:
  case gENTRY_:
  case zENTRY_: {
    Logical zOp = (Va->item == zENTRY_);
    struct cdfSTRUCT *CDF;
    long *entryNum = va_arg (Va->ap, long *);
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (BADzOP(CDF,Va->item==rENTRY_)) return ILLEGAL_IN_zMODE;
    if (BOO(zOp,CDF->CURzEntryNum,CDF->CURgrEntryNum) == RESERVED_ENTRYNUM)
      return NO_ENTRY_SELECTED;
    *entryNum = BOO(zOp,CDF->CURzEntryNum,CDF->CURgrEntryNum);
    break;
  }
  /****************************************************************************
  * gENTRY_EXISTENCE_/rENTRY_EXISTENCE_/zENTRY_EXISTENCE_, confirms the
  * existence of a numbered entry for the current attribute.
  ****************************************************************************/
  case gENTRY_EXISTENCE_:
  case rENTRY_EXISTENCE_:
  case zENTRY_EXISTENCE_: {
    int entryType = E3p(Va->item,gENTRY_EXISTENCE_,
				 rENTRY_EXISTENCE_,
				 zENTRY_EXISTENCE_);
    struct cdfSTRUCT *CDF; Logical zEntry;
    long entryNum = va_arg (Va->ap, long), entryN;
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (!CURRENTattrSELECTED(CDF)) return NO_ATTR_SELECTED;
    if (!sX(CheckEntryOp(CDF,entryType,Cur),&pStatus)) return pStatus;
    if (entryNum < 0) return BAD_ENTRY_NUM;
    switch (entryType) {
      case gENTRYt:
      case rENTRYt:
	zEntry = FALSE;
	entryN = entryNum;
	break;
      case zENTRYt:
	zEntry = BOO(zModeON(CDF),BOO(entryNum < CDF->NrVars,FALSE,TRUE),TRUE);
	entryN = BOO(zModeON(CDF),BOO(entryNum < CDF->NrVars,entryNum,
				      entryNum - CDF->NrVars),entryNum);
	break;
    }
    tStatus = FindEntryByNumber(CDF,CDF->CURattrOffset,zEntry,entryN,NULL);
    switch (tStatus) {
      case CDF_OK:
	break;
      case NO_SUCH_ENTRY:
	return tStatus;
      default:
	AbortAccess (CDF, FALSE, Cur);
	return tStatus;
    }
    break;
  }
  /****************************************************************************
  * CURgENTRY_EXISTENCE_/CURrENTRY_EXISTENCE_/CURzENTRY_EXISTENCE_, confirms
  * the existence of the current entry number for the current attribute.
  ****************************************************************************/
  case CURgENTRY_EXISTENCE_:
  case CURrENTRY_EXISTENCE_:
  case CURzENTRY_EXISTENCE_: {
    int entryType = E3p(Va->item,CURgENTRY_EXISTENCE_,
				 CURrENTRY_EXISTENCE_,
				 CURzENTRY_EXISTENCE_);
    struct cdfSTRUCT *CDF; Int32 offset;
    SelectCDF (Cur->cdf, CDF, NO_CDF_SELECTED)
    if (!CURRENTattrSELECTED(CDF)) return NO_ATTR_SELECTED;
    if (E3(entryType,
	   CDF->CURgrEntryNum,
	   CDF->CURgrEntryNum,
	   CDF->CURzEntryNum) == RESERVED_ENTRYNUM) return NO_ENTRY_SELECTED;
    if (!sX(CheckEntryOp(CDF,entryType,Cur),&pStatus)) return pStatus;
    offset = E3(entryType,CDF->CURgrEntryOffset,
			  CDF->CURgrEntryOffset,
			  CDF->CURzEntryOffset);
    if (offset == RESERVED_ENTRYOFFSET) return NO_SUCH_ENTRY;
    break;
  }
  /****************************************************************************
  * Unknown item, must be the next function.
  ****************************************************************************/
  default: {
    Va->fnc = Va->item;
    break;
  }
}
return pStatus;
}
