1 /******************************************************************************
2 *
3 *  NSSDC/CDF                     CDF library miscellaneous functions, part 2.
4 *
5 *  Version 1.3b, 4-Mar-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  15-Dec-94, J Love     Original version.
10 *   V1.1   6-Jan-95, J Love	Encode/decode changes.  More cache-residency.
11 *   V1.1a 20-Jan-95, J Love	IRIX 6.0 (64-bit).
12 *   V1.1b 15-Mar-95, J Love	Solaris 2.3 IDL i/f.  Fixed `recNum' parameter
13 *				of `LastAllocatedRecord'.  Gnu C on OSF/1.
14 *   V1.2  21-Mar-95, J Love	POSIX.
15 *   V1.2a 18-Apr-95, J Love	More POSIX.
16 *   V1.2b 13-Jun-95, J Love	Linux.
17 *   V1.2c  7-Sep-95, J Love	CDFexport-related changes.  Fixed possible
18 *				memory leak.
19 *   V1.3   5-Sep-96, J Love	CDF V2.6.
20 *   V1.3a 21-Feb-97, J Love	Removed RICE.
21 *   V1.3b  4-Mar-97, J Love	Windows NT for MS Visual C/C++ on an IBM PC.
22 *   V2.0  08-Apr-04, M Liu      Modified LocateCurrentVar function to save
23 *                               the current selected variable's offset.
24 *                               Modified FindVarByNumber and FindVarByName
25 *                               functions to start searching for the variable
26 *                               from the current selected variable, if it's
27 *                               cwselected, instead of always from the
28 *                               beginning. Remove the calls to FindVarByNumber
29 *                               if a variable is already selected.
30 *   V2.1  04-May-04, M Liu      Corrected Int32ToCDFid and CDFidToInt32 to
31 *                               handle 64-bit for Solaris/sparc.
32 *   V2.2  21-Jun-05, M Liu      Corrected Int32ToCDFid and CDFidToInt32 to
33 *                               handle 64-bit Intel/AMD running Linux.
34 *   V3.2  20-Jun-07, D Berger   Modified the "FindAttr...", "FindEntry..."
35 *                               routines, and the "SetCUR..." routines and
36 *                               added ResetReadOnlyState to handle READONLYon
37 *                               mode.
38 *
39 ******************************************************************************/
40 
41 #include "cdflib.h"
42 
43 /******************************************************************************
44 * sX.
45 *   Determine what should be done with a status code.  For each call to
46 * `CDFlib', status is returned as follows...
47 *
48 *  1. The first ERROR encountered terminates the call and is returned.  This
49 *     routine will not overwrite an existing error code.
50 *  2. The last WARNING encountered is returned.  INFOs encountered after a
51 *     WARNING are ignored.
52 *  3. In the absence of any WARNINGs, the last INFO is returned.
53 *  4. In the absence of any WARNINGs or INFOs, CDF_OK is returned.
54 *
55 * This routine returns FALSE if the pending status code is an ERROR; otherwise
56 * it returns TRUE.
57 *
58 ******************************************************************************/
59 
sX(cStatus,pStatus)60 STATICforIDL Logical sX (cStatus, pStatus)
61 CDFstatus cStatus;      /* Status code to be checked. */
62 CDFstatus *pStatus;     /* Pending status code. */
63 {
64   if (cStatus == CDF_OK) return TRUE;           /* Ok, do nothing. */
65   if (cStatus < CDF_WARN) {                     /* Error. */
66     if (*pStatus > CDF_WARN) *pStatus = cStatus;
67     return FALSE;
68   }
69   if (cStatus > CDF_OK) {                       /* Info. */
70     if (CDF_OK <= *pStatus) *pStatus = cStatus;
71     return TRUE;
72   }
73   *pStatus = cStatus;                           /* Warning. */
74   return TRUE;
75 }
76 
77 /******************************************************************************
78 * LocateCurrentVar.
79 ******************************************************************************/
80 
LocateCurrentVar(CDF,zOp,offset,zVar,Var)81 STATICforIDL CDFstatus LocateCurrentVar (CDF, zOp, offset, zVar, Var)
82 struct CDFstruct *CDF;          /* In: Pointer to CDF. */
83 Logical zOp;                    /* In: TRUE if current zVariable is to be
84 				   accessed; FALSE if current rVariable.  N/A
85 				   if zMode is on (since the current zVariable
86 				   number will always be used). */
87 Int32 *offset;                  /* Out: Offset of the current variable's VDR.
88 				   This may be a NULL pointer. */
89 Logical *zVar;                  /* Out: TRUE if a true zVariable; FALSE if
90 				   a true rVariable.  This may be a NULL
91 				   pointer. */
92 struct VarStruct **Var;         /* Out: Pointer to variable.  This will be NULL
93 				   if the variable has yet to be initialized.
94 				   This may be a NULL pointer. */
95 {
96   CDFstatus tStatus;
97   Int32 tOffset;
98   /****************************************************************************
99   * Pass back the offset of the VDR.
100   ****************************************************************************/
101   if (zModeON(CDF)) {
102     if (CDF->CURzVarNum < CDF->NrVars) {
103       ASSIGNnotNULL(zVar, FALSE)
104       tStatus = FindVarByNumber (CDF, CDF->CURzVarNum, FALSE, &tOffset);
105       if (StatusOK(tStatus)) {
106 	ASSIGNnotNULL (Var, CDF->rVars[(int)CDF->CURzVarNum])
107 	ASSIGNnotNULL (offset, tOffset)
108 	CDF->CURzVarOffset = tOffset;
109       }
110     }
111     else {
112       ASSIGNnotNULL(zVar, TRUE)
113       tStatus = FindVarByNumber (CDF, CDF->CURzVarNum - CDF->NrVars, TRUE,
114 				 &tOffset);
115       if (StatusOK(tStatus)) {
116 	ASSIGNnotNULL (Var, CDF->zVars[(int)(CDF->CURzVarNum - CDF->NrVars)])
117 	ASSIGNnotNULL (offset, tOffset)
118 	CDF->CURzVarOffset = tOffset;
119       }
120     }
121   }
122   else {
123     ASSIGNnotNULL (zVar, zOp)
124     tStatus = FindVarByNumber (CDF,BOO(zOp,CDF->CURzVarNum,
125 					   CDF->CURrVarNum),zOp,&tOffset);
126     if (StatusOK(tStatus)) {
127       ASSIGNnotNULL (Var, BOO(zOp,CDF->zVars[(int)CDF->CURzVarNum],
128 				  CDF->rVars[(int)CDF->CURrVarNum]))
129       ASSIGNnotNULL (offset, tOffset)
130       if (zOp)
131 	CDF->CURzVarOffset = tOffset;
132       else
133 	CDF->CURrVarOffset = tOffset;
134     }
135   }
136   return tStatus;
137 }
138 
139 /******************************************************************************
140 * CurrentVarMode.
141 ******************************************************************************/
142 
CurrentVarMode(CDF,zOp)143 STATICforIDL Logical CurrentVarMode (CDF, zOp)
144 struct CDFstruct *CDF;          /* In: Pointer to CDF. */
145 Logical zOp;                    /* In: TRUE if current zVariable is to be
146 				   accessed; FALSE if current rVariable.  N/A
147 				   if zMode is on (since the current zVariable
148 				   number will always be used). */
149 {
150 
151   if (zModeON(CDF)) {
152     if (CDF->CURzVarNum < CDF->NrVars)
153       return FALSE;
154     else
155       return TRUE;
156   }
157   else
158     return  zOp;
159 }
160 
161 /******************************************************************************
162 * InitCurrentVar.
163 ******************************************************************************/
164 
InitCurrentVar(CDF,zOp,Var)165 STATICforIDL CDFstatus InitCurrentVar (CDF, zOp, Var)
166 struct CDFstruct *CDF;          /* In: Pointer to CDF. */
167 Logical zOp;                    /* In: TRUE if current zVariable is to be
168 				   accessed; FALSE if current rVariable.  N/A
169 				   if zMode is on (since the current zVariable
170 				   number will always be used [even when a real
171 				   rVariable is being accessed]). */
172 struct VarStruct **Var;         /* Out: Pointer to variable. */
173 {
174   CDFstatus tStatus;
175   /****************************************************************************
176   * Pass back the pointer to its variable structure.  The variable will
177   * be initialized for access if necessary.
178   ****************************************************************************/
179   if (zModeON(CDF))
180     if (CDF->CURzVarNum < CDF->NrVars)
181       tStatus = InitVar (CDF, CDF->CURzVarNum, FALSE, Var);
182     else
183       tStatus = InitVar (CDF, CDF->CURzVarNum - CDF->NrVars, TRUE, Var);
184   else
185     tStatus = InitVar (CDF,BOO(zOp,CDF->CURzVarNum,CDF->CURrVarNum),zOp,Var);
186   return tStatus;
187 }
188 
189 /******************************************************************************
190 * InitVar.
191 ******************************************************************************/
192 
InitVar(CDF,varN,zVar,VarP)193 STATICforIDL CDFstatus InitVar (CDF, varN, zVar, VarP)
194 struct CDFstruct *CDF;          /* In: Pointer to CDF. */
195 Int32 varN;                     /* In: Real variable number (ignoring the
196 				   zMode). */
197 Logical zVar;                   /* In: TRUE if a real zVariable (ignoring
198 				   the zMode). */
199 struct VarStruct **VarP;        /* Out: Pointer to variable. */
200 {
201   CDFstatus pStatus = CDF_OK;
202   struct VarStruct *Var = BOO(zVar,CDF->zVars[(int)varN],
203 				   CDF->rVars[(int)varN]);
204   /****************************************************************************
205   * Check if the variable has already been initialized.  If not, allocate and
206   * initialize its variable structure.
207   ****************************************************************************/
208   if (Var == NULL) {
209     /**************************************************************************
210     * Allocate a variable structure.
211     **************************************************************************/
212     Var = (struct VarStruct *) cdf_AllocateMemory (sizeof(struct VarStruct), NULL);
213     if (Var == NULL) return BAD_MALLOC;
214     /**************************************************************************
215     * Determine offset of the VDR in the dotCDF file.
216     **************************************************************************/
217     if (!sX(FindVarByNumber(CDF,varN,zVar,&(Var->VDRoffset)),&pStatus)) {
218       cdf_FreeMemory (Var, NULL);
219       return pStatus;
220     }
221 
222     /**************************************************************************
223     * Initialize miscellaneous fields of the variable structure.
224     **************************************************************************/
225     Var->zVar = zVar;
226     Var->varN = varN;
227     Var->fp = NULL;
228     Var->varCacheSize = NUMcacheVAR;		/* N/A if single-file CDF. */
229     Var->accessed_at = CDF->pseudo_clock++;
230     Var->firstRecInVVR = NO_RECORD;
231     Var->lastRecInVVR = NO_RECORD;
232     Var->offsetOfVVR = NO_OFFSET;
233     /**************************************************************************
234     * Read fields to be held in memory for efficiency.
235     **************************************************************************/
236     if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
237 		    VDR_MAXREC,&(Var->maxRec),
238 		    VDR_NULL),&pStatus)) {
239       cdf_FreeMemory (Var, NULL);
240       return pStatus;
241     }
242     /**************************************************************************
243     * More initialization.
244     **************************************************************************/
245     if (!sX(InitVar2(CDF,Var),&pStatus)) {
246       cdf_FreeMemory (Var, NULL);
247       return pStatus;
248     }
249     /**************************************************************************
250     * Store pointer to variable structure.
251     **************************************************************************/
252     if (zVar)
253       CDF->zVars[(int)varN] = Var;
254     else
255       CDF->rVars[(int)varN] = Var;
256   }
257   /****************************************************************************
258   * Pass back pointer to variable.
259   ****************************************************************************/
260   ASSIGNnotNULL (VarP, Var)
261   return pStatus;
262 }
263 
264 /******************************************************************************
265 * InitVar2.
266 ******************************************************************************/
267 
InitVar2(CDF,Var)268 STATICforIDL CDFstatus InitVar2 (CDF, Var)
269 struct CDFstruct *CDF;
270 struct VarStruct *Var;
271 {
272   int dimN; CDFstatus pStatus = CDF_OK; struct CPRstruct CPR; int i;
273   Int32 flags, dataType, numElems, CPRoffset, sRecords;
274   /****************************************************************************
275   * Read necessary fields from the VDR.
276   ****************************************************************************/
277   if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
278 		  VDR_FLAGS,&flags,
279 		  VDR_DATATYPE,&dataType,
280 		  VDR_NUMELEMS,&numElems,
281 		  VDR_sRECORDS,&sRecords,
282 		  VDR_NULL),&pStatus)) return pStatus;
283   /****************************************************************************
284   * Determine if the variable has a known data type.
285   ****************************************************************************/
286   if (!ValidDataType(dataType)) return BAD_DATA_TYPE;
287   /****************************************************************************
288   * Calculate the dimensionality and variances of the variable based on the
289   * current zMode.
290   ****************************************************************************/
291   if (!sX(CalcDimParms(CDF,Var->VDRoffset,
292 		       Var->zVar,&(Var->numDims),
293 		       Var->dimSizes,Var->dimVarys),&pStatus)) return pStatus;
294   Var->recVary = BOO(RECvaryBITset(flags),VARY,NOVARY);
295   /****************************************************************************
296   * Calculate the number of values for each dimension.
297   ****************************************************************************/
298   CalcNumDimValues (CDF, Var);
299   /****************************************************************************
300   * Calculate the element and value sizes.
301   ****************************************************************************/
302   Var->NvalueElems = numElems;
303   Var->NelemBytes = CDFelemSize (dataType);
304   Var->NvalueBytes = Var->NvalueElems * Var->NelemBytes;
305   /****************************************************************************
306   * Calculate the number of physical and virtual values per record.
307   ****************************************************************************/
308   CalcRecValues (Var);
309   /****************************************************************************
310   * Calculate the number of elements and the size (in bytes) of physical and
311   * conceptual records.
312   ****************************************************************************/
313   Var->NphyRecElems = Var->NphyRecValues * Var->NvalueElems;
314   Var->NvirtRecElems = Var->NvirtRecValues * Var->NvalueElems;
315   Var->NphyRecBytes = Var->NphyRecValues * Var->NvalueBytes;
316   Var->NvirtRecBytes = Var->NvirtRecValues * Var->NvalueBytes;
317   /**************************************************************************
318   * Initialize current positioning.
319   **************************************************************************/
320   Var->seqValueOffset = 0;
321   Var->zRD.recNumber = 0;
322   Var->zRD.recCount = 1;
323   Var->zRD.recInterval = 1;
324   for (dimN = 0; dimN < Var->numDims; dimN++) {
325      Var->zRD.dimIndices[dimN] = 0;
326      Var->zRD.dimCounts[dimN] = Var->dimSizes[dimN];
327      Var->zRD.dimIntervals[dimN] = 1;
328   }
329   /****************************************************************************
330   * Determine variable type.
331   ****************************************************************************/
332   if (!sX(VariableType(CDF,Var->VDRoffset,
333 		       Var->zVar,&(Var->vType)),&pStatus)) return pStatus;
334   /**************************************************************************
335   * What to do if a record is missing.
336   **************************************************************************/
337   Var->prevIfMissing = (sRecords == PREV_SPARSERECORDS);
338   /**************************************************************************
339   * Based on the variable type...
340   **************************************************************************/
341   switch (Var->vType) {
342     case STANDARD_:
343     case SPARSE_RECORDS_:
344       if (!sX(LastRecord(CDF,Var->VDRoffset,Var->zVar,
345 			 &(Var->maxAllocated)),&pStatus)) return pStatus;
346       Var->maxWritten = Var->maxAllocated;
347       break;
348     case COMPRESSED_:
349     case SPARSE_COMPRESSED_RECORDS_:
350       if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
351 		      VDR_CPRorSPR,&CPRoffset,
352 		      VDR_NULL),&pStatus)) return pStatus;
353       if (!sX(ReadCPR(CDF->fp,CPRoffset,
354 		      CPR_RECORD,&CPR,
355 		      CPR_NULL),&pStatus)) return pStatus;
356       Var->cType = CPR.cType;
357       for (i = 0; i < CPR.pCount; i++) Var->cParms[i] = CPR.cParms[i];
358       Var->reservePct = 0;
359       break;
360     case SPARSE_ARRAYS_:
361     case SPARSE_RECORDS_AND_ARRAYS_:
362       return UNKNOWN_SPARSENESS;
363     case IN_MULTI_:
364       break;
365     default:
366       return CDF_INTERNAL_ERROR;
367   }
368   /**************************************************************************
369   * Initialize staging area (although n/a for most variable types).
370   **************************************************************************/
371   Var->stage.areaOffset = NO_OFFSET;
372   Var->stage.firstRec = NO_RECORD;
373   Var->stage.lastRec = NO_RECORD;
374   Var->stage.dotOffset = NO_OFFSET;
375   Var->stage.modified = FALSE;
376   /****************************************************************************
377   * Calculate the blocking factor based on variable type...
378   ****************************************************************************/
379   if (!sX(CalcBF(CDF,Var),&pStatus)) return pStatus;
380   /****************************************************************************
381   * Determine the encoding and decoding functions to be used.
382   ****************************************************************************/
383   if (!sX(ConversionFunction(dataType,HostEncoding(),
384 			     CDF->encoding,CDF->negToPosFp0,
385 			     &(Var->EncodeFunction)),&pStatus)) return pStatus;
386   if (!sX(ConversionFunction(dataType,CDF->encoding,
387 			     CDF->decoding,CDF->negToPosFp0,
388 			     &(Var->DecodeFunction)),&pStatus)) return pStatus;
389   return pStatus;
390 }
391 
392 /******************************************************************************
393 * CalcRecValues.
394 ******************************************************************************/
395 
CalcRecValues(Var)396 STATICforIDL void CalcRecValues (Var)
397 struct VarStruct *Var;
398 {
399   int dimN;
400   Var->NphyRecValues = 1;
401   Var->NvirtRecValues = 1;
402   for (dimN = 0; dimN < Var->numDims; dimN++) {
403      Var->NvirtRecValues *= Var->dimSizes[dimN];
404      if (Var->dimVarys[dimN]) Var->NphyRecValues *= Var->dimSizes[dimN];
405   }
406   return;
407 }
408 
409 /******************************************************************************
410 * CalcNumDimValues.
411 ******************************************************************************/
412 
CalcNumDimValues(CDF,Var)413 STATICforIDL void CalcNumDimValues (CDF, Var)
414 struct CDFstruct *CDF;
415 struct VarStruct *Var;
416 {
417   int dimN, dimNx;
418   if (!CDF->rowMajor) {
419      for (dimN = 0; dimN < Var->numDims; dimN++) {
420 	Var->nPhyDimValues[dimN] = 1;
421 	for (dimNx = 0; dimNx < dimN; dimNx++) {
422 	   if (Var->dimVarys[dimNx]) {
423 	     Var->nPhyDimValues[dimN] *= Var->dimSizes[dimNx];
424 	   }
425 	}
426      }
427   }
428   else {
429      for (dimN = 0; dimN < Var->numDims; dimN++) {
430 	Var->nPhyDimValues[dimN] = 1;
431 	for (dimNx = dimN + 1; dimNx < Var->numDims; dimNx++) {
432 	   if (Var->dimVarys[dimNx]) {
433 	     Var->nPhyDimValues[dimN] *= Var->dimSizes[dimNx];
434 	   }
435 	}
436      }
437   }
438   return;
439 }
440 
441 /******************************************************************************
442 * CalcBF.
443 ******************************************************************************/
444 
CalcBF(CDF,Var)445 STATICforIDL CDFstatus CalcBF (CDF, Var)
446 struct CDFstruct *CDF;
447 struct VarStruct *Var;
448 {
449   CDFstatus pStatus = CDF_OK; Int32 bF;
450   if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
451 		  VDR_BLOCKING,&bF,
452 		  VDR_NULL),&pStatus)) return pStatus;
453   switch (Var->vType) {
454     case STANDARD_:
455       if (Var->recVary)
456 	if (bF == 0) {
457 	  Int32 min = ((MIN_BLOCKING_BYTES_standard-1)/Var->NphyRecBytes)+1;
458 	  Var->blockingFactor = MAXIMUM(min,MIN_BLOCKING_RECS_standard);
459 	}
460 	else
461 	  Var->blockingFactor = bF;
462       else
463 	Var->blockingFactor = 1;
464       break;
465     case SPARSE_RECORDS_:
466       if (Var->recVary)
467 	if (bF == 0) {
468 	  Int32 min = ((MIN_BLOCKING_BYTES_sparse-1)/Var->NphyRecBytes)+1;
469 	  Var->blockingFactor = MAXIMUM(min,MIN_BLOCKING_RECS_sparse);
470 	}
471 	else
472 	  Var->blockingFactor = bF;
473       else
474 	Var->blockingFactor = 1;
475       break;
476     case COMPRESSED_:
477     case SPARSE_COMPRESSED_RECORDS_:
478       Var->blockingFactor = bF;
479       break;
480     case SPARSE_ARRAYS_:
481     case SPARSE_RECORDS_AND_ARRAYS_:
482       return UNKNOWN_SPARSENESS;
483     case IN_MULTI_:
484       Var->blockingFactor = 1;
485       break;
486     default:
487       return CDF_INTERNAL_ERROR;
488   }
489   return pStatus;
490 }
491 
492 /******************************************************************************
493 * UpdateConversions.
494 ******************************************************************************/
495 
UpdateConversions(CDF)496 STATICforIDL CDFstatus UpdateConversions (CDF)
497 struct CDFstruct *CDF;
498 {
499   CDFstatus pStatus = CDF_OK; Logical zVar;
500   for (zVar = 0; zVar <= 1; zVar++) {
501      int varN; Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
502      for (varN = 0; varN < nVars; varN++) {
503 	struct VarStruct *Var = BOO(zVar,CDF->zVars[varN],CDF->rVars[varN]);
504         if (Var != NULL) {
505 	  Int32 dataType;
506 	  if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
507 			  VDR_DATATYPE,&dataType,
508 			  VDR_NULL),&pStatus)) return pStatus;
509 	  if (!sX(ConversionFunction(dataType,HostEncoding(),
510 				     CDF->encoding,CDF->negToPosFp0,
511 				     &(Var->EncodeFunction)),&pStatus)) return
512 								       pStatus;
513 	  if (!sX(ConversionFunction(dataType,CDF->encoding,
514 				     CDF->decoding,CDF->negToPosFp0,
515 				     &(Var->DecodeFunction)),&pStatus)) return
516 								       pStatus;
517         }
518      }
519   }
520   return pStatus;
521 }
522 
523 /******************************************************************************
524 * UpdateNEWzMode.
525 ******************************************************************************/
526 
UpdateNEWzMode(CDF)527 STATICforIDL CDFstatus UpdateNEWzMode (CDF)
528 struct CDFstruct *CDF;
529 {
530   CDFstatus pStatus = CDF_OK; Logical zVar;
531   for (zVar = 0; zVar <= 1; zVar++) {
532      int varN; Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
533      for (varN = 0; varN < nVars; varN++) {
534 	struct VarStruct *Var = BOO(zVar,CDF->zVars[varN],CDF->rVars[varN]);
535         if (Var != NULL) {
536 	  if (!sX(CalcDimParms(CDF,Var->VDRoffset,
537 			       Var->zVar,&(Var->numDims),
538 			       Var->dimSizes,
539 			       Var->dimVarys),&pStatus)) return pStatus;
540 	  CalcNumDimValues (CDF, Var);
541 	  CalcRecValues (Var);
542 	  Var->NvirtRecElems = Var->NvirtRecValues * Var->NvalueElems;
543 	  Var->NvirtRecBytes = Var->NvirtRecValues * Var->NvalueBytes;
544         }
545      }
546   }
547   return pStatus;
548 }
549 
550 /******************************************************************************
551 * VarIdentity.
552 *    Returns information about the real identity of a variable.
553 ******************************************************************************/
554 
VarIdentity(CDF,varN,zOp,varNt,zVar,Var)555 STATICforIDL CDFstatus VarIdentity (CDF, varN, zOp, varNt, zVar, Var)
556 struct CDFstruct *CDF;          /* In: Pointer to CDF. */
557 Int32 varN;                      /* In: Variable number - zModed. */
558 Logical zOp;                    /* In: TRUE if zVariable; FALSE if rVariable.
559 				       This is also zModed. */
560 Int32 *varNt;                    /* Out: Real variable number. */
561 Logical *zVar;                  /* Out: Real variable type: TRUE if a
562 					zVariable; FALSE if an rVariable. */
563 struct VarStruct **Var;         /* Out: Pointer to variable. */
564 {
565   if (zModeON(CDF))
566     if (0 <= varN && varN < CDF->NrVars) {
567       ASSIGNnotNULL (varNt, varN)
568       ASSIGNnotNULL (zVar, FALSE)
569       ASSIGNnotNULL (Var, CDF->rVars[(int)varN])
570     }
571     else
572       if (varN < CDF->NrVars + CDF->NzVars) {
573 	ASSIGNnotNULL (varNt, varN - CDF->NrVars)
574 	ASSIGNnotNULL (zVar, TRUE)
575 	ASSIGNnotNULL (Var, CDF->zVars[(int)varN])
576       }
577       else
578 	return NO_SUCH_VAR;
579   else
580     if (0 <= varN && varN < BOO(zOp,CDF->NzVars,CDF->NrVars)) {
581       ASSIGNnotNULL (varNt, varN)
582       ASSIGNnotNULL (zVar, zOp)
583       ASSIGNnotNULL (Var, BOO(zOp,CDF->zVars[(int)varN],
584 				  CDF->rVars[(int)varN]))
585     }
586     else
587       return NO_SUCH_VAR;
588   return CDF_OK;
589 }
590 
591 /******************************************************************************
592 * OpenVar.
593 * Open a variable for read and/or write access (if this is a multi-file CDF
594 * and the variable file is closed).  It is assumed that the variable has been
595 * initialized for access and that the variable is closed (and in a multi-file
596 * CDF).
597 ******************************************************************************/
598 
OpenVar(CDF,Var)599 STATICforIDL CDFstatus OpenVar (CDF, Var)
600 struct CDFstruct *CDF;
601 struct VarStruct *Var;
602 {
603   CDFstatus pStatus = CDF_OK;
604   char a_mode[MAX_aMODE_LEN+1], pathname[DU_MAX_PATH_LEN+1];
605   /****************************************************************************
606   * Try to open the variable file.
607   ****************************************************************************/
608   BuildFilePath (BOO(Var->zVar,Zt,Vt), CDF->CDFname, CDF->no_append,
609 		 CDF->upper_case_ext, CDF->version_numbers, Var->varN,
610 		 pathname);
611   if (CDF->status == READ_WRITE)
612     strcpyX (a_mode, READ_PLUS_a_mode, MAX_aMODE_LEN);
613   else
614     strcpyX (a_mode, READ_ONLY_a_mode, MAX_aMODE_LEN);
615   Var->fp = V_open (pathname, a_mode);
616   /****************************************************************************
617   * If the open failed, close a variable file and try.  If that attempt fails
618   * return an error.
619   ****************************************************************************/
620   if (Var->fp == NULL) {
621     if (!sX(CloseLRUvar(CDF),&pStatus)) return pStatus;
622     Var->fp = V_open (pathname, a_mode);
623     if (Var->fp == NULL) return VAR_OPEN_ERROR;
624   }
625   /****************************************************************************
626   * The open was successful - try to set the proper cache size.
627   ****************************************************************************/
628   if (!CACHEv(Var->fp,Var->varCacheSize)) {
629     V_close (Var->fp, NULL, NULL);
630     Var->fp = NULL;
631     return BAD_CACHE_SIZE;
632   }
633   return pStatus;
634 }
635 
636 /******************************************************************************
637 * LastRecord.
638 ******************************************************************************/
639 
LastRecord(CDF,VDRoffset,zVar,recNum)640 STATICforIDL CDFstatus LastRecord (CDF, VDRoffset, zVar, recNum)
641 struct CDFstruct *CDF;  /* In: Pointer to CDF. */
642 Int32 VDRoffset;        /* In: Offset of VDR. */
643 Logical zVar;           /* In: TRUE if a real zVariable; FALSE if rVariable. */
644 Int32 *recNum;          /* Out: Last record allocated. */
645 {
646   CDFstatus pStatus = CDF_OK;
647   Int32 VXRoffset, nUsedEntries, lastRecs[MAX_VXR_ENTRIES];
648   if (!sX(ReadVDR(CDF,CDF->fp,VDRoffset,zVar,
649 		  VDR_VXRTAIL,&VXRoffset,
650 		  VDR_NULL),&pStatus)) return pStatus;
651   if (VXRoffset == 0)
652     *recNum = NO_RECORD;
653   else {
654     if (!sX(ReadVXR(CDF->fp,VXRoffset,
655 		    VXR_NUSEDENTRIES,&nUsedEntries,
656 		    VXR_LASTREC,lastRecs,
657 		    VXR_NULL),&pStatus)) return pStatus;
658     if ((int)nUsedEntries > MAX_VXR_ENTRIES) return CORRUPTED_V2_CDF;
659     *recNum = lastRecs[(int)(nUsedEntries-1)];
660   }
661   return pStatus;
662 }
663 
664 /******************************************************************************
665 * IndicesValueOffset.
666 ******************************************************************************/
667 
IndicesValueOffset(numDims,dimIndices,dimVarys,nPhyDimValues)668 STATICforIDL Int32 IndicesValueOffset (numDims, dimIndices, dimVarys,
669 				      nPhyDimValues)
670 Int32 numDims;
671 Int32 *dimIndices;
672 Int32 *dimVarys;
673 Int32 *nPhyDimValues;
674 {
675   Int32 offset = 0; int dimN;
676   for (dimN = 0; dimN < numDims; dimN++) {
677      if (dimVarys[dimN]) offset += (dimIndices[dimN] * nPhyDimValues[dimN]);
678   }
679   return offset;
680 }
681 
682 /******************************************************************************
683 * ValueOffsetIndices.
684 ******************************************************************************/
685 
ValueOffsetIndices(offset,rowMajor,numDims,dimVarys,nPhyDimValues,indices)686 STATICforIDL void ValueOffsetIndices (offset, rowMajor, numDims, dimVarys,
687 				      nPhyDimValues, indices)
688 Int32 offset;
689 Logical rowMajor;
690 Int32 numDims;
691 Int32 *dimVarys;
692 Int32 *nPhyDimValues;
693 Int32 *indices;
694 {
695   int dimN, i;
696   for (i = 0, dimN = BOO(rowMajor,0,(int)(numDims-1));
697        i < numDims; i++, BOO(rowMajor,dimN++,dimN--)) {
698      if (dimVarys[dimN]) {
699        indices[dimN] = offset / nPhyDimValues[dimN];
700        offset = offset % nPhyDimValues[dimN];
701      }
702      else
703        indices[dimN] = 0;
704   }
705   return;
706 }
707 
708 /******************************************************************************
709 * RecordByteOffset.
710 ******************************************************************************/
711 
RecordByteOffset(CDF,Var,phyRecN,offsetP)712 STATICforIDL CDFstatus RecordByteOffset (CDF, Var, phyRecN, offsetP)
713 struct CDFstruct *CDF;
714 struct VarStruct *Var;
715 Int32 phyRecN;
716 Int32 *offsetP;
717 {
718   CDFstatus pStatus = CDF_OK;
719   Int32 firstRec=-1, lastRec=-1, offset=-1;
720   switch (Var->vType) {
721     case STANDARD_:
722     case SPARSE_RECORDS_: {
723       if (Var->firstRecInVVR <= phyRecN && phyRecN <= Var->lastRecInVVR) {
724         *offsetP = (Int32) (Var->offsetOfVVR + VVR_BASE_SIZE +
725                            (Var->NphyRecBytes * (phyRecN - Var->firstRecInVVR)));
726 	break;
727       }
728       else {
729         if (!sX(SearchForRecord(CDF,Var->VDRoffset,Var->zVar,
730 	  		        phyRecN,&firstRec,&lastRec,
731 			        &offset,NULL),&pStatus)) return pStatus;
732         *offsetP = (Int32) (offset + VVR_BASE_SIZE +
733 	 	           (Var->NphyRecBytes * (phyRecN - firstRec)));
734 	Var->firstRecInVVR = firstRec;
735 	Var->lastRecInVVR = lastRec;
736 	Var->offsetOfVVR = offset;
737         break;
738       }
739     }
740     case COMPRESSED_:
741     case SPARSE_COMPRESSED_RECORDS_:
742     case SPARSE_ARRAYS_:
743     case SPARSE_RECORDS_AND_ARRAYS_:
744       return CDF_INTERNAL_ERROR;
745     case IN_MULTI_:
746       *offsetP = (Int32) (phyRecN * Var->NphyRecBytes);
747       break;
748     default:
749       return CDF_INTERNAL_ERROR;
750   }
751   return pStatus;
752 }
753 
754 /******************************************************************************
755 * ConfigureNEWzMode.
756 ******************************************************************************/
757 
ConfigureNEWzMode(CDF)758 STATICforIDL CDFstatus ConfigureNEWzMode (CDF)
759 struct CDFstruct *CDF;
760 {
761   CDFstatus pStatus = CDF_OK;
762   if (!sX(UpdateNEWzMode(CDF),&pStatus)) return pStatus;
763   InitCURobjectsStates (CDF);
764   return pStatus;
765 }
766 
767 /******************************************************************************
768 * InitCURobjectsStates.
769 *   Note that initializing is done regardless of the current zMode.
770 ******************************************************************************/
771 
InitCURobjectsStates(CDF)772 STATICforIDL void InitCURobjectsStates (CDF)
773 struct CDFstruct *CDF;
774 {
775   struct VarStruct *Var; int dimN, varNum;
776   /****************************************************************************
777   * Initialize current attributes/entries/variables.
778   ****************************************************************************/
779   CDF->CURattrOffset = RESERVED_ATTROFFSET;
780   CDF->CURattrOffset64 = (OFF_T) RESERVED_ATTROFFSET;
781   CDF->CURgrEntryNum = RESERVED_ENTRYNUM;
782   CDF->CURgrEntryOffset = RESERVED_ENTRYOFFSET;
783   CDF->CURgrEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET;
784   CDF->CURzEntryNum = RESERVED_ENTRYNUM;
785   CDF->CURzEntryOffset = RESERVED_ENTRYOFFSET;
786   CDF->CURzEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET;
787   CDF->CURrVarNum = RESERVED_VARNUM;
788   CDF->CURzVarNum = RESERVED_VARNUM;
789 
790   if (CDF->fp != NULL)
791   {
792       CDF->fp->CurADRIndex = RESERVED_ENTRYNUM;
793       CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
794   };
795 
796   /****************************************************************************
797   * Initialize current positioning for EACH rVariable.
798   ****************************************************************************/
799   for (varNum = 0; varNum < CDF->NrVars; varNum++) {
800      Var = CDF->rVars[varNum];
801      if (Var != NULL) {
802        Var->seqValueOffset = 0;
803        Var->seqValueOffset64 = (OFF_T) 0;
804        Var->zRD.recNumber = 0;
805        Var->zRD.recCount = 1;
806        Var->zRD.recInterval = 1;
807        for (dimN = 0; dimN < Var->numDims; dimN++) {
808 	  Var->zRD.dimIndices[dimN] = 0;
809 	  Var->zRD.dimCounts[dimN] = Var->dimSizes[dimN];
810 	  Var->zRD.dimIntervals[dimN] = 1;
811        }
812      }
813   }
814   /****************************************************************************
815   * Initialize current positioning for EACH zVariable.
816   ****************************************************************************/
817   for (varNum = 0; varNum < CDF->NzVars; varNum++) {
818      Var = CDF->zVars[varNum];
819      if (Var != NULL) {
820        Var->seqValueOffset = 0;
821        Var->seqValueOffset64 = (OFF_T) 0;
822        Var->zRD.recNumber = 0;
823        Var->zRD.recCount = 1;
824        Var->zRD.recInterval = 1;
825        for (dimN = 0; dimN < Var->numDims; dimN++) {
826 	  Var->zRD.dimIndices[dimN] = 0;
827 	  Var->zRD.dimCounts[dimN] = Var->dimSizes[dimN];
828 	  Var->zRD.dimIntervals[dimN] = 1;
829        }
830      }
831   }
832   /****************************************************************************
833   * Initialize current positioning for ALL rVariables.
834   ****************************************************************************/
835   CDF->rRD.recNumber = 0;
836   CDF->rRD.recCount = 1;
837   CDF->rRD.recInterval = 1;
838   for (dimN = 0; dimN < CDF->rNumDims; dimN++) {
839      CDF->rRD.dimIndices[dimN] = 0;
840      CDF->rRD.dimCounts[dimN] = CDF->rDimSizes[dimN];
841      CDF->rRD.dimIntervals[dimN] = 1;
842   }
843   return;
844 }
845 
846 /******************************************************************************
847 * FindAttrByName.
848 ******************************************************************************/
849 
FindAttrByName(CDF,searchName,offset)850 STATICforIDL CDFstatus FindAttrByName (CDF, searchName, offset)
851 struct CDFstruct *CDF;          /* In: Pointer to CDF. */
852 char *searchName;               /* In: Attribute name to find. */
853 Int32 *offset;                  /* Out: Offset of ADR that was found. */
854 {
855   Int32 numAttrs, tOffset, nextADR, fstADR;
856   char attrName[CDF_ATTR_NAME_LEN+1];
857   CDFstatus pStatus = CDF_OK;
858   int attrN;
859   long read_only_mode;
860 
861   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
862   if (pStatus != CDF_OK) return pStatus;
863 
864   /**************************************************************************
865   * If in READONLYon mode, set CurADRIndex to the referenced attribute number.
866   ***************************************************************************/
867   if (read_only_mode == READONLYon)
868   {
869       for (attrN = 0; attrN < CDF->fp->GDR->NumAttr; attrN++)
870       {
871          if (!strcmpITB(CDF->fp->ADRList[attrN]->Name,searchName))
872          {
873              CDF->fp->CurADRIndex = attrN;
874              ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET);
875              return CDF_OK;
876          };
877       };
878   }
879   else
880   {
881       /************************************************************************
882       * Read number of attributes and the offset of the first ADR from the GDR.
883       ************************************************************************/
884       if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
885                       GDR_NUMATTR,&numAttrs,
886                       GDR_ADRHEAD,&fstADR,
887                       GDR_NULL),&pStatus)) return pStatus;
888       /************************************************************************
889       * Read from ADRs until a matching attribute name is found.
890       *   Note that if this is a V2.0 CDF, the last ADR will not have an
891       * offset of zero for the next ADR.  For that reason, we will loop
892       * through the number of attributes read from the GDR (and then stop).
893       ************************************************************************/
894       if (CDF->CURattrOffset != RESERVED_ATTROFFSET)
895         tOffset = CDF->CURattrOffset;
896       else
897         tOffset = fstADR;
898 
899       for (attrN = 0; attrN < numAttrs; attrN++) {
900          if (!sX(ReadADR(CDF->fp,tOffset,
901 	                 ADR_NAME,attrName,
902                          ADR_ADRNEXT,&nextADR,
903                          ADR_NULL),&pStatus)) return pStatus;
904          if (!strcmpITB(attrName,searchName)) {
905            ASSIGNnotNULL (offset, tOffset)
906            return CDF_OK;
907          }
908          if (nextADR != 0)
909            tOffset = nextADR;
910          else
911            tOffset = fstADR;
912       }
913   };
914   /****************************************************************************
915   * Attribute name not found, return error.
916   ****************************************************************************/
917   return NO_SUCH_ATTR;
918 }
919 
920 /******************************************************************************
921 * FindAttrByNumber.
922 ******************************************************************************/
923 
FindAttrByNumber(CDF,searchNum,offset)924 STATICforIDL CDFstatus FindAttrByNumber (CDF, searchNum, offset)
925 struct CDFstruct *CDF;          /* In: Pointer to the CDF. */
926 Int32 searchNum;                /* In: The attribute number to be found. */
927 Int32 *offset;                  /* Out: The offset of the located ADR. */
928 {
929   Int32 numAttrs, tOffset, attrNum, nextADR, fstADR;
930   CDFstatus pStatus = CDF_OK;
931   Int32 attrN;
932   long read_only_mode;
933   /****************************************************************************
934   * Validate.
935   ****************************************************************************/
936   if (searchNum < 0) return BAD_ATTR_NUM;
937   /****************************************************************************
938   * First check if the next attribute is the one being searched for.  For this
939   * to be the case, an attribute must currently be selected, the next attribute
940   * must exist, and the next attribute's number must be the attribute number
941   * being searched for.  But don't try this if a V2.0 CDF because of the bad
942   * terminating offset of the ADR linked list in those CDFs.
943   ****************************************************************************/
944 /*
945   if (!CDF->badTerminatingOffsets) {
946     if (CDF->CURattrOffset != RESERVED_ATTROFFSET) {
947       Int32 nextOffset;
948       if (!sX(ReadADR(CDF->fp,CDF->CURattrOffset,
949 		      ADR_ADRNEXT,&nextOffset,
950 		      ADR_NULL),&pStatus)) return pStatus;
951       if (nextOffset != 0) {
952 	Int32 nextNum;
953 	if (!sX(ReadADR(CDF->fp,nextOffset,
954 			ADR_NUM,&nextNum,
955 			ADR_NULL),&pStatus)) return pStatus;
956 	if (nextNum == searchNum) {
957 	  *offset = nextOffset;
958 	  return pStatus;
959 	}
960       }
961     }
962   }
963 */
964   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
965   if (pStatus != CDF_OK) return pStatus;
966 
967   /***************************************************************************
968   * If in read only mode, set CurADRIndex to the searched for atribute number.
969   ***************************************************************************/
970   if (read_only_mode == READONLYon)
971   {
972       if (CDF->fp->GDR->NumAttr <= searchNum) return NO_SUCH_ATTR;
973       if (searchNum < 0 || searchNum >= CDF->fp->GDR->NumAttr)
974                                                             return NO_SUCH_ATTR;
975       CDF->fp->CurADRIndex = searchNum;
976       ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET);
977       return CDF_OK;
978   }
979   else
980   {
981       /************************************************************************
982       * The next attribute isn't the one being searched for.  First read the
983       * number of attributes and the offset of the first ADR from the GDR.
984       ************************************************************************/
985       if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
986                       GDR_NUMATTR,&numAttrs,
987                       GDR_ADRHEAD,&fstADR,
988                       GDR_NULL),&pStatus)) return pStatus;
989       if (numAttrs <= searchNum) return NO_SUCH_ATTR;
990 
991       if (CDF->CURattrOffset != RESERVED_ATTROFFSET)
992         tOffset = CDF->CURattrOffset;
993       else
994         tOffset = fstADR;
995       /************************************************************************
996       * Read from ADRs until a matching attribute number is found.
997       *   Note that if this is a V2.0 CDF, the last ADR will not have an
998       * offset of zero for the next ADR.  For that reason, we will loop
999       * through the number of attributes read from the GDR (and then stop).
1000       ************************************************************************/
1001       for (attrN = 0; attrN < numAttrs; attrN++) {
1002          if (!sX(ReadADR(CDF->fp,tOffset,
1003                          ADR_NUM,&attrNum,
1004                          ADR_ADRNEXT,&nextADR,
1005                          ADR_NULL),&pStatus)) return pStatus;
1006          if (attrNum == searchNum) {
1007            ASSIGNnotNULL (offset, tOffset)
1008            return CDF_OK;
1009          }
1010          if (nextADR != 0)
1011            tOffset = nextADR;
1012          else
1013            tOffset = fstADR;
1014       }
1015       /************************************************************************
1016       * Attribute number not found, internal error or corrupted CDF.
1017       ************************************************************************/
1018       return CORRUPTED_V2_CDF;
1019   }
1020 }
1021 
1022 /******************************************************************************
1023 * FindEntryByNumber.
1024 ******************************************************************************/
1025 
FindEntryByNumber(CDF,ADRoffset,zEntry,entryN,offset)1026 STATICforIDL CDFstatus FindEntryByNumber (CDF, ADRoffset, zEntry, entryN,
1027 					  offset)
1028 struct CDFstruct *CDF;          /* In: Pointer to the CDF. */
1029 Int32 ADRoffset;                /* In: Offset of attribute's ADR. */
1030 Logical zEntry;			/* In: TRUE if AzEDR list to be searched.
1031 				       FALSE if AgrEDR list to be searched. */
1032 Int32 entryN;                    /* In: The entry number being searched for. */
1033 Int32 *offset;                  /* Out: The offset of the located AEDR. */
1034 {
1035   Int32 numEntries, tOffset, entryNum, nextADR;
1036   CDFstatus pStatus = CDF_OK;
1037   Int32 entryX;
1038   long read_only_mode;
1039   /****************************************************************************
1040   * Read number of entries and the offset of the first AEDR from the ADR.
1041   ****************************************************************************/
1042   if (!sX(ReadADR(CDF->fp,ADRoffset,
1043 		  BOO(zEntry,ADR_NzENTRIES,ADR_NgrENTRIES),&numEntries,
1044 		  BOO(zEntry,ADR_AzEDRHEAD,ADR_AgrEDRHEAD),&tOffset,
1045 		  ADR_NULL),&pStatus)) return pStatus;
1046   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
1047   if (pStatus != CDF_OK) return pStatus;
1048   if (read_only_mode == READONLYon)
1049   {
1050       /***********************************************************************
1051       * If the requested entry exists, set CurAEDRIndex to the entry number and
1052       * set CURzEntrySel to reflect if the entry is in the z list or the gr
1053       * list.
1054       ************************************************************************/
1055       if (zEntry && entryN <= CDF->fp->ADRList[CDF->fp->CurADRIndex]->MAXzEntry)
1056       {
1057           if (CDF->fp->ADRList[CDF->fp->CurADRIndex]->zAEDRList[entryN] != NULL)
1058           {
1059               CDF->fp->CURzEntrySel = TRUE;
1060               CDF->fp->CurAEDRIndex = entryN;
1061               ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET);
1062               return pStatus;
1063           }
1064           else
1065           {
1066               return NO_SUCH_ENTRY;
1067           }
1068       }
1069       else if (!zEntry && entryN <= CDF->fp->ADRList[CDF->fp->CurADRIndex]->
1070                MAXgrEntry)
1071       {
1072           if (CDF->fp->ADRList[CDF->fp->CurADRIndex]->grAEDRList[entryN]
1073               != NULL)
1074           {
1075               CDF->fp->CURzEntrySel = FALSE;
1076               CDF->fp->CurAEDRIndex = entryN;
1077               ASSIGNnotNULL (offset, DUMMY_ENTRYOFFSET);
1078               return pStatus;
1079           }
1080           else
1081           {
1082               return NO_SUCH_ENTRY;
1083           };
1084       }
1085 
1086       else
1087       {
1088           return NO_SUCH_ENTRY;
1089       };
1090   };
1091   /****************************************************************************
1092   * Read from AEDRs until a matching entry number is found.
1093   *   Note that if this is a V2.0 CDF, the last AEDR will not have an
1094   * offset of zero for the next AEDR.  For that reason, we will loop
1095   * through the number of entries read from the ADR (and then stop).
1096   ****************************************************************************/
1097   for (entryX = 0; entryX < numEntries; entryX++) {
1098      if (!sX(ReadAEDR(CDF->fp,tOffset,
1099 		      AEDR_NUM,&entryNum,
1100 		      AEDR_AEDRNEXT,&nextADR,
1101 		      AEDR_NULL),&pStatus)) return pStatus;
1102      if (entryNum == entryN) {
1103        ASSIGNnotNULL (offset, tOffset)
1104        return CDF_OK;
1105      }
1106      tOffset = nextADR;
1107   }
1108   /****************************************************************************
1109   * Entry number not found.
1110   ****************************************************************************/
1111   return NO_SUCH_ENTRY;
1112 }
1113 
1114 /******************************************************************************
1115 * FindLastAttr.
1116 ******************************************************************************/
1117 
FindLastAttr(CDF,lastOffset)1118 STATICforIDL CDFstatus FindLastAttr (CDF, lastOffset)
1119 struct CDFstruct *CDF;          /* In: Pointer to the CDF. */
1120 Int32 *lastOffset;              /* Out: Offset of last attribute's ADR. */
1121 {
1122   CDFstatus pStatus = CDF_OK;
1123   Int32 nAttrs, offset;
1124   Int32 attrN;
1125   long read_only_mode;
1126 
1127   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
1128   if (pStatus != CDF_OK) return pStatus;
1129 
1130   /*************************************************************************
1131   * If in READONLYon mode, set CurADRIndex to the index of the last
1132   * attribute in menmory.
1133   *************************************************************************/
1134   if (read_only_mode == READONLYon)
1135   {
1136       *lastOffset = DUMMY_ATTROFFSET;
1137       CDF->fp->CurADRIndex = CDF->fp->GDR->NumAttr - 1;
1138   }
1139   else
1140   {
1141       /************************************************************************
1142       * Read number of attributes and the offset of the first ADR.  If there are
1143       * no attributes, return an offset of zero.
1144       ************************************************************************/
1145       if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1146                       GDR_NUMATTR,&nAttrs,
1147                       GDR_NULL),&pStatus)) return pStatus;
1148       if (nAttrs == 0) {
1149         *lastOffset = 0;
1150         return pStatus;
1151       }
1152       /************************************************************************
1153       * There is at least one attribute.
1154       * Note that if this is a V2.0 CDF, the last ADR will not have an offset of
1155       * zero for the next ADR.  For that reason, we will loop through the number
1156       * of attributes read from the GDR (and then stop).
1157       ************************************************************************/
1158       if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1159                       GDR_ADRHEAD,&offset,
1160                       GDR_NULL),&pStatus)) return pStatus;
1161       for (attrN = 0; attrN < nAttrs - 1; attrN++) {
1162          if (!sX(ReadADR(CDF->fp,offset,
1163                          ADR_ADRNEXT,&offset,
1164                          ADR_NULL),&pStatus)) return pStatus;
1165       }
1166       *lastOffset = offset;
1167   };
1168   return pStatus;
1169 }
1170 
1171 /******************************************************************************
1172 * FindLastEntry.
1173 ******************************************************************************/
1174 
FindLastEntry(CDF,ADRoffset,zEntry,lastOffset)1175 STATICforIDL CDFstatus FindLastEntry (CDF, ADRoffset, zEntry, lastOffset)
1176 struct CDFstruct *CDF;          /* In: Pointer to the CDF. */
1177 Int32 ADRoffset;                /* In: Offset of attribute's ADR. */
1178 Logical zEntry;                 /* In: TRUE if (real) zEntry is being searched
1179 				   for; FALSE if gEntry/rEntry. */
1180 Int32 *lastOffset;              /* Out: The offset of the last AEDR. */
1181 {
1182   CDFstatus pStatus = CDF_OK;
1183   Int32 offset, nEntries;
1184   Int32 entryX;
1185   long read_only_mode;
1186 
1187   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
1188   if (pStatus != CDF_OK) return pStatus;
1189 
1190   /***********************************************************************
1191   * If in READONLYon mode, set CurAEDRIndex to MAXzEntry or MAXgrEntry, as
1192   * appropriate.
1193   ***********************************************************************/
1194   if (read_only_mode == READONLYon)
1195   {
1196       *lastOffset = DUMMY_ENTRYOFFSET;
1197       if (zEntry == TRUE)
1198       {
1199           CDF->fp->CurAEDRIndex =
1200                            CDF->fp->ADRList[CDF->fp->CurADRIndex]->MAXzEntry;
1201       }
1202       else
1203       {
1204           CDF->fp->CurAEDRIndex =
1205                            CDF->fp->ADRList[CDF->fp->CurADRIndex]->MAXgrEntry;      };
1206   }
1207   else
1208   {
1209       /************************************************************************
1210       * Read offset of first AEDR and determine if there are any entries (of the
1211       * specified type).  If there are none, pass back an offset of zero.
1212       ************************************************************************/
1213       if (!sX(ReadADR(CDF->fp,ADRoffset,
1214                       BOO(zEntry,ADR_AzEDRHEAD,ADR_AgrEDRHEAD),
1215                       &offset,ADR_NULL),&pStatus)) return pStatus;
1216       if (offset == 0) {
1217         *lastOffset = 0;
1218         return pStatus;
1219       }
1220       /************************************************************************
1221       * There is at least one entry.  Read the actual number of entries and then
1222       * scan through to the last one.
1223       *   Note that if this is a V2.0 CDF, the last AEDR will not have an
1224       * offset of zero for the next AEDR.  For that reason, we will loop
1225       * through the number of entries (minus one) read from the ADR (and then
1226       * stop).
1227       ************************************************************************/
1228       if (!sX(ReadADR(CDF->fp,ADRoffset,
1229                       BOO(zEntry,ADR_NzENTRIES,ADR_NgrENTRIES),&nEntries,
1230                       ADR_NULL),&pStatus)) return pStatus;
1231       for (entryX = 0; entryX < nEntries - 1; entryX++) {
1232          if (!sX(ReadAEDR(CDF->fp,offset,
1233                           AEDR_AEDRNEXT,&offset,
1234                           AEDR_NULL),&pStatus)) return pStatus;
1235       }
1236       *lastOffset = offset;
1237   }
1238   return pStatus;
1239 }
1240 
1241 /******************************************************************************
1242 * FindPrevEntry.
1243 ******************************************************************************/
1244 
FindPrevEntry(CDF,ADRoffset,searchOffset,zEntry,prevOffset)1245 STATICforIDL CDFstatus FindPrevEntry (CDF, ADRoffset, searchOffset, zEntry,
1246 				      prevOffset)
1247 struct CDFstruct *CDF;          /* Pointer to the CDF. */
1248 Int32 ADRoffset;                /* Offset of attribute's ADR. */
1249 Int32 searchOffset;             /* The entry offset being searched for. */
1250 Logical zEntry;                 /* TRUE if (real) zEntry is being searched for;
1251 				   FALSE if gEntry/rEntry. */
1252 Int32 *prevOffset;              /* The offset of the previous AEDR. */
1253 {
1254   CDFstatus pStatus = CDF_OK;
1255   Int32 offset, nEntries, nextOffset;
1256   Int32 entryX;
1257   /****************************************************************************
1258   * Read the offset of the first AEDR.  If that offset is the same as the
1259   * search offset, return an offset of zero.
1260   ****************************************************************************/
1261   if (!sX(ReadADR(CDF->fp,ADRoffset,
1262 		  BOO(zEntry,ADR_AzEDRHEAD,ADR_AgrEDRHEAD),&offset,
1263 		  ADR_NULL),&pStatus)) return pStatus;
1264   if (offset == searchOffset) {
1265     *prevOffset = 0;
1266     return pStatus;
1267   }
1268   /****************************************************************************
1269   * The first AEDR is not at the search offset.  Read the actual number of
1270   * entries and then scan through them looking for the AEDR offset being
1271   * searched for.  If the search offset is not found, then either the CDF is
1272   * corrupted or an internal logic error has occurred.
1273   *   Note that if this is a V2.0 CDF, the last AEDR will not have an
1274   * offset of zero for the next AEDR.  For that reason, we will loop
1275   * through the number of entries read from the ADR (and then stop).
1276   ****************************************************************************/
1277   if (!sX(ReadADR(CDF->fp,ADRoffset,
1278 		  BOO(zEntry,ADR_NzENTRIES,ADR_NgrENTRIES),&nEntries,
1279 		  ADR_NULL),&pStatus)) return pStatus;
1280   for (entryX = 0; entryX < nEntries; entryX++) {
1281      if (!sX(ReadAEDR(CDF->fp,offset,
1282 		      AEDR_AEDRNEXT,&nextOffset,
1283 		      AEDR_NULL),&pStatus)) return pStatus;
1284      if (nextOffset == searchOffset) {
1285        *prevOffset = offset;
1286        return pStatus;
1287      }
1288      offset = nextOffset;
1289   }
1290   return CORRUPTED_V2_CDF;
1291 }
1292 
1293 /******************************************************************************
1294 * FindVarByName.
1295 *    Both the rVariable and zVariable lists are searched (since variable names
1296 * are unique in a CDF).
1297 ******************************************************************************/
1298 
FindVarByName(CDF,searchName,offset,zVar,Var)1299 STATICforIDL CDFstatus FindVarByName (CDF, searchName, offset, zVar, Var)
1300 struct CDFstruct *CDF;  /* In: Pointer to the CDF. */
1301 char *searchName;       /* In: The variable name being searched for. */
1302 Int32 *offset;          /* Out: Offset of the zVDR/rVDR. */
1303 Logical *zVar;          /* Out: TRUE if a zVariable. */
1304 struct VarStruct **Var; /* Out: Pointer to variable structure. */
1305 {
1306   int varN;
1307   char varName[CDF_VAR_NAME_LEN+1];
1308   CDFstatus pStatus = CDF_OK;
1309   Int32 tOffset, nextVDR;
1310   Int32 headOffset;
1311   /****************************************************************************
1312   * Read from rVDRs until a matching variable name is found.
1313   *   Note that if this is a V2.0 CDF, the last rVDR will not have an
1314   * offset of zero for the next rVDR.  For that reason, we will loop
1315   * through the number of rVariables (and then stop).
1316   ****************************************************************************/
1317   if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1318 		  GDR_rVDRHEAD,&headOffset,
1319 		  GDR_NULL),&pStatus)) return pStatus;
1320 
1321   if (CDF->CURrVarNum != RESERVED_VARNUM)
1322     tOffset = CDF->CURrVarOffset;
1323   else
1324     tOffset = headOffset;
1325 
1326   for (varN = 0; varN < CDF->NrVars; varN++) {
1327      if (!sX(ReadVDR(CDF,CDF->fp,tOffset,FALSE,
1328 		     VDR_NAME,varName,
1329 		     VDR_VDRNEXT,&nextVDR,
1330 		     VDR_NULL),&pStatus)) return pStatus;
1331      if (!strcmpITB(varName,searchName)) {
1332        ASSIGNnotNULL (offset, tOffset)
1333        ASSIGNnotNULL (zVar, FALSE)
1334        ASSIGNnotNULL (Var, CDF->rVars[varN])
1335        return CDF_OK;
1336      }
1337      if (nextVDR == 0) tOffset = headOffset;
1338      else tOffset = nextVDR;
1339   }
1340   /****************************************************************************
1341   * Read from zVDRs until a matching variable name is found.
1342   ****************************************************************************/
1343   if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1344 		  GDR_zVDRHEAD,&headOffset,
1345 		  GDR_NULL),&pStatus)) return pStatus;
1346 /*
1347   if (CDF->CURzVarNum != RESERVED_VARNUM)
1348     tOffset = CDF->CURzVarOffset;
1349   else
1350 */
1351   tOffset = headOffset;
1352 
1353   for (varN = 0; varN < CDF->NzVars; varN++) {
1354      if (!sX(ReadVDR(CDF,CDF->fp,tOffset,TRUE,
1355 		     VDR_NAME,varName,
1356 		     VDR_VDRNEXT,&nextVDR,
1357 		     VDR_NULL),&pStatus)) return pStatus;
1358      if (!strcmpITB(varName,searchName)) {
1359        ASSIGNnotNULL (offset, tOffset)
1360        ASSIGNnotNULL (zVar, TRUE)
1361        ASSIGNnotNULL (Var, CDF->zVars[varN])
1362        return CDF_OK;
1363      }
1364      if (nextVDR == 0) tOffset = headOffset;
1365      else tOffset = nextVDR;
1366   }
1367   /****************************************************************************
1368   * Variable name not found, return error.
1369   ****************************************************************************/
1370   return NO_SUCH_VAR;
1371 }
1372 
1373 /******************************************************************************
1374 * FindVarByNumber.
1375 ******************************************************************************/
1376 
FindVarByNumber(CDF,searchNum,zVar,offset)1377 STATICforIDL CDFstatus FindVarByNumber (CDF, searchNum, zVar, offset)
1378 struct CDFstruct *CDF;  /* In: Pointer to CDF. */
1379 Int32 searchNum;        /* In: Variable number to be searched for. */
1380 Logical zVar;           /* In: TRUE if a (real) zVariable number should be
1381 			   found. */
1382 Int32 *offset;          /* Out: offset of the VDR. */
1383 {
1384   CDFstatus pStatus = CDF_OK;
1385   Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
1386   Int32 tOffset, varNum, nextVDR, fstOffset;
1387   int varN;
1388   /****************************************************************************
1389   * Read offset of first VDR.
1390   ****************************************************************************/
1391   if (searchNum < 0) return BAD_VAR_NUM;
1392   if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1393 		  BOO(zVar,GDR_zVDRHEAD,GDR_rVDRHEAD),&fstOffset,
1394 		  GDR_NULL),&pStatus)) return pStatus;
1395   if (nVars <= searchNum) return NO_SUCH_VAR;
1396   /****************************************************************************
1397   * Read from VDRs until a matching variable number is found.
1398   *   Note that if this is a V2.0 CDF, the last VDR will not have an
1399   * offset of zero for the next VDR.  For that reason, we will loop
1400   * through the number of variables (and then stop).
1401   ****************************************************************************/
1402 
1403   if (zModeON(CDF)) {
1404     tOffset = fstOffset;
1405     if (CDF->CURzVarNum != RESERVED_VARNUM) {
1406       long numT = BOO(zVar, CDF->CURzVarNum-CDF->NrVars, CDF->CURzVarNum);
1407       if (numT > -1 && numT <= searchNum) tOffset = CDF->CURzVarOffset;
1408     }
1409   }
1410   else {
1411     if (zVar) {
1412       if (CDF->CURzVarNum != RESERVED_VARNUM && CDF->CURzVarNum < searchNum)
1413         tOffset = CDF->CURzVarOffset;
1414       else
1415         tOffset = fstOffset;
1416     } else {
1417       if (CDF->CURrVarNum != RESERVED_VARNUM && CDF->CURrVarNum < searchNum)
1418         tOffset = CDF->CURrVarOffset;
1419       else
1420         tOffset = fstOffset;
1421     }
1422   }
1423 
1424   /****************************************************************************
1425   * Search for the variable from the current selected variabale, instead of
1426   * the top of the variable list. It will speed up the search process if the
1427   * variables are accessed in a orderly sequence.
1428   ****************************************************************************/
1429   for (varN = 0; varN < nVars; varN++) {
1430      if (!sX(ReadVDR(CDF,CDF->fp,tOffset,zVar,
1431 		     VDR_NUM,&varNum,
1432 		     VDR_VDRNEXT, &nextVDR,
1433 		     VDR_NULL),&pStatus)) return pStatus;
1434      if (varNum == searchNum) {
1435        ASSIGNnotNULL (offset, tOffset)
1436        return CDF_OK;
1437      }
1438      if (nextVDR != 0) 			/* Reaching the end of the list? */
1439        tOffset = nextVDR;		/* No.... Continue.              */
1440      else
1441        tOffset = fstOffset;		/* Yes... Go back to the top.    */
1442   }
1443   /****************************************************************************
1444   * Variable number not found, return error.
1445   ****************************************************************************/
1446   return CORRUPTED_V2_CDF;
1447 }
1448 
1449 /******************************************************************************
1450 * VerifyNoRecordsWritten.
1451 *    Verifies that no records have been written.  Both the rVariable and
1452 * zVariable lists are searched.
1453 ******************************************************************************/
1454 
VerifyNoRecordsWritten(CDF,no)1455 STATICforIDL CDFstatus VerifyNoRecordsWritten (CDF, no)
1456 struct CDFstruct *CDF;          /* In: Pointer to the CDF. */
1457 Logical *no;                    /* Out: If TRUE, no records written. */
1458 {
1459   CDFstatus pStatus = CDF_OK; Int32 tOffset, maxRec; int varN; Logical zVar;
1460   /****************************************************************************
1461   * Read from r/zVDRs until a maximum record greater than NO_RECORD is found.
1462   *   Note that if this is a V2.0 CDF, the last rVDR will not have an
1463   * offset of zero for the next rVDR.  For that reason, we will loop
1464   * through the number of variables (and then stop).
1465   ****************************************************************************/
1466   for (zVar = 0; zVar <= 1; zVar++) {
1467      if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1468                      BOO(zVar,GDR_zVDRHEAD,GDR_rVDRHEAD),&tOffset,
1469                      GDR_NULL),&pStatus)) return pStatus;
1470      for (varN = 0; varN < BOO(zVar,CDF->NzVars,CDF->NrVars); varN++) {
1471         if (!sX(ReadVDR(CDF,CDF->fp,tOffset,zVar,
1472                         VDR_MAXREC,&maxRec,
1473                         VDR_VDRNEXT,&tOffset,
1474                         VDR_NULL),&pStatus)) return pStatus;
1475         if (maxRec > NO_RECORD) {
1476           *no = FALSE;
1477           return pStatus;
1478         }
1479      }
1480   }
1481   /****************************************************************************
1482   * No records written.
1483   ****************************************************************************/
1484   *no = TRUE;
1485   return pStatus;
1486 }
1487 
1488 /******************************************************************************
1489 * VerifyNoPadsSpecified.
1490 *    Verifies that no pad values have been specified.  Both the rVariable
1491 * and zVariable lists are searched.
1492 ******************************************************************************/
1493 
VerifyNoPadsSpecified(CDF,no)1494 STATICforIDL CDFstatus VerifyNoPadsSpecified (CDF, no)
1495 struct CDFstruct *CDF;          /* In: Pointer to the CDF. */
1496 Logical *no;                    /* Out: If TRUE, no pad values written. */
1497 {
1498   CDFstatus pStatus = CDF_OK;
1499   Int32 tOffset, flags32;
1500   int varN;
1501   /****************************************************************************
1502   * Read from rVDRs until a pad value is found.
1503   *   Note that if this is a V2.0 CDF, the last rVDR will not have an
1504   * offset of zero for the next rVDR.  For that reason, we will loop
1505   * through the number of rVariables (and then stop).
1506   ****************************************************************************/
1507   if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1508                   GDR_rVDRHEAD,&tOffset,
1509                   GDR_NULL),&pStatus)) return pStatus;
1510   for (varN = 0; varN < CDF->NrVars; varN++) {
1511      if (!sX(ReadVDR(CDF,CDF->fp,tOffset,FALSE,
1512                      VDR_FLAGS,&flags32,
1513                      VDR_NULL),&pStatus)) return pStatus;
1514      if (PADvalueBITset(flags32)) {
1515        *no = FALSE;
1516        return pStatus;
1517      }
1518      if (!sX(ReadVDR(CDF,CDF->fp,tOffset,FALSE,
1519                      VDR_VDRNEXT,&tOffset,
1520                      VDR_NULL),&pStatus)) return pStatus;
1521   }
1522   /****************************************************************************
1523   * Read from zVDRs until a pad value is found.
1524   ****************************************************************************/
1525   if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1526                   GDR_zVDRHEAD,&tOffset,
1527                   GDR_NULL),&pStatus)) return pStatus;
1528   for (varN = 0; varN < CDF->NzVars; varN++) {
1529      if (!sX(ReadVDR(CDF,CDF->fp,tOffset,TRUE,
1530                      VDR_FLAGS,&flags32,
1531                      VDR_NULL),&pStatus)) return pStatus;
1532      if (PADvalueBITset(flags32)) {
1533        *no = FALSE;
1534        return pStatus;
1535      }
1536      if (!sX(ReadVDR(CDF,CDF->fp,tOffset,TRUE,
1537                      VDR_VDRNEXT,&tOffset,
1538                      VDR_NULL),&pStatus)) return pStatus;
1539   }
1540   /****************************************************************************
1541   * No pad values specified.
1542   ****************************************************************************/
1543   *no = TRUE;
1544   return pStatus;
1545 }
1546 
1547 /******************************************************************************
1548 * VerifyNoEntriesWritten.
1549 ******************************************************************************/
1550 
VerifyNoEntriesWritten(CDF,no)1551 STATICforIDL CDFstatus VerifyNoEntriesWritten (CDF, no)
1552 struct CDFstruct *CDF;
1553 Logical *no;
1554 {
1555   CDFstatus pStatus = CDF_OK;
1556   Int32 numAttrs, tOffset, nEntries;
1557   int attrN;
1558   /****************************************************************************
1559   * Read number of attributes and the offset of the first ADR from the GDR.
1560   ****************************************************************************/
1561   if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1562                   GDR_NUMATTR,&numAttrs,
1563                   GDR_ADRHEAD,&tOffset,
1564                   GDR_NULL),&pStatus)) return pStatus;
1565   /****************************************************************************
1566   * Read from ADRs until an entry is found.
1567   *   Note that if this is a V2.0 CDF, the last ADR will not have an
1568   * offset of zero for the next ADR.  For that reason, we will loop
1569   * through the number of attributes read from the GDR (and then stop).
1570   ****************************************************************************/
1571   for (attrN = 0; attrN < numAttrs; attrN++) {
1572      if (!sX(ReadADR(CDF->fp,tOffset,
1573                      ADR_NgrENTRIES,&nEntries,
1574                      ADR_NULL),&pStatus)) return pStatus;
1575      if (nEntries > 0) {
1576        *no = FALSE;
1577        return pStatus;
1578      }
1579      if (!sX(ReadADR(CDF->fp,tOffset,
1580                      ADR_NzENTRIES,&nEntries,
1581                      ADR_NULL),&pStatus)) return pStatus;
1582      if (nEntries > 0) {
1583        *no = FALSE;
1584        return pStatus;
1585      }
1586      if (!sX(ReadADR(CDF->fp,tOffset,
1587                      ADR_ADRNEXT,&tOffset,
1588                      ADR_NULL),&pStatus)) return pStatus;
1589   }
1590   /****************************************************************************
1591   * No entries detected.
1592   ****************************************************************************/
1593   *no = TRUE;
1594   return pStatus;
1595 }
1596 
1597 /******************************************************************************
1598 * DefaultPadValue.
1599 *    `memmove' is used rather than an assignment statement (for the data
1600 * types greater in size than one byte) because there is no guarantee that the
1601 * address which receives the pad value is aligned properly.  If it isn't, a
1602 * bus error could occur on some computers.
1603 ******************************************************************************/
1604 
DefaultPadValue(dataType,numElems,padValue)1605 STATICforIDL void DefaultPadValue (dataType, numElems, padValue)
1606 Int32 dataType;
1607 Int32 numElems;
1608 void *padValue;
1609 {
1610   size_t nBytes = CDFelemSize (dataType);
1611   Byte *ptr = padValue;
1612   double padE[2];                  /* The "largest" data type element. */
1613   int i;
1614   switch (dataType) {
1615     case CDF_BYTE:
1616       *((sChar *) &padE) = (sChar) DEFAULT_BYTE_PADVALUE;
1617       break;
1618     case CDF_INT1:
1619       *((sChar *) &padE) = (sChar) DEFAULT_INT1_PADVALUE;
1620       break;
1621     case CDF_UINT1:
1622       *((uChar *) &padE) = (uChar) DEFAULT_UINT1_PADVALUE;
1623       break;
1624     case CDF_INT2:
1625       *((Int16 *) &padE) = (Int16) DEFAULT_INT2_PADVALUE;
1626       break;
1627     case CDF_UINT2:
1628       *((uInt16 *) &padE) = (uInt16) DEFAULT_UINT2_PADVALUE;
1629       break;
1630     case CDF_INT4:
1631       *((Int32 *) &padE) = (Int32) DEFAULT_INT4_PADVALUE;
1632       break;
1633     case CDF_UINT4:
1634       *((uInt32 *) &padE) = (uInt32) DEFAULT_UINT4_PADVALUE;
1635       break;
1636     case CDF_REAL4:
1637       *((float *) &padE) = (float) DEFAULT_REAL4_PADVALUE;
1638       break;
1639     case CDF_FLOAT:
1640       *((float *) &padE) = (float) DEFAULT_FLOAT_PADVALUE;
1641       break;
1642     case CDF_REAL8:
1643       *((double *) &padE) = (double) DEFAULT_REAL8_PADVALUE;
1644       break;
1645     case CDF_DOUBLE:
1646       *((double *) &padE) = (double) DEFAULT_DOUBLE_PADVALUE;
1647       break;
1648     case CDF_EPOCH:
1649       *((double *) &padE) = (double) DEFAULT_EPOCH_PADVALUE;
1650       break;
1651     case CDF_EPOCH16:
1652       *((double *) &padE) = (double) DEFAULT_EPOCH_PADVALUE;
1653       *(((double *) &padE) + 1) = (double) DEFAULT_EPOCH_PADVALUE;
1654       break;
1655     case CDF_CHAR:
1656       *((sChar *) &padE) = (sChar) DEFAULT_CHAR_PADVALUE;
1657       break;
1658     case CDF_UCHAR:
1659       *((uChar *) &padE) = (uChar) DEFAULT_UCHAR_PADVALUE;
1660       break;
1661   }
1662   for (i = 0; i < numElems; i++, ptr += nBytes) memmove (ptr, &padE, nBytes);
1663   return;
1664 }
1665 
1666 /******************************************************************************
1667 * DefaultPadBuffer.
1668 ******************************************************************************/
1669 
DefaultPadBuffer(CDF,Var,nValues,buffer)1670 STATICforIDL CDFstatus DefaultPadBuffer (CDF, Var, nValues, buffer)
1671 struct CDFstruct *CDF;
1672 struct VarStruct *Var;
1673 Int32 nValues;
1674 void *buffer;
1675 {
1676   CDFstatus pStatus = CDF_OK;
1677   Byte *tBuffer = buffer; Int32 i; Int32 dataType, numElems;
1678   if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
1679 		  VDR_DATATYPE,&dataType,
1680 		  VDR_NUMELEMS,&numElems,
1681 		  VDR_NULL),&pStatus)) return pStatus;
1682   for (i = 0; i < nValues; i++, tBuffer += (int) Var->NvalueBytes) {
1683      DefaultPadValue (dataType, numElems, tBuffer);
1684   }
1685   return pStatus;
1686 }
1687 
1688 /******************************************************************************
1689 * PadBuffer.
1690 ******************************************************************************/
1691 
PadBuffer(CDF,Var,nValues,buffer)1692 STATICforIDL CDFstatus PadBuffer (CDF, Var, nValues, buffer)
1693 struct CDFstruct *CDF;          /* Pointer to CDF. */
1694 struct VarStruct *Var;          /* Pointer to variable. */
1695 Int32 nValues;                   /* Number of values in buffer. */
1696 void *buffer;                   /* Buffer to pad. */
1697 {
1698   CDFstatus pStatus = CDF_OK;
1699   Int32 flags, dataType, numElems;
1700   /****************************************************************************
1701   * Read the flags, data type, and number of elements fields of the VDR.
1702   ****************************************************************************/
1703   if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
1704 		  VDR_FLAGS,&flags,
1705 		  VDR_DATATYPE,&dataType,
1706 		  VDR_NUMELEMS,&numElems,
1707 		  VDR_NULL),&pStatus)) return pStatus;
1708   /****************************************************************************
1709   * If a pad value has been specified for the variable, read the pad value
1710   * from the VDR and duplicate for the desired number of values.  Otherwise,
1711   * copy the desired number of default pad values into the buffer.  Then
1712   * convert the padded buffer into the desired decoding.
1713   ****************************************************************************/
1714   if (PADvalueBITset(flags)) {
1715     Byte *tBuffer = buffer; Int32 valueN;
1716     if (!sX(ReadVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
1717 		    VDR_PADVALUE,tBuffer,
1718 		    VDR_NULL),&pStatus)) return pStatus;
1719     for (valueN = 1; valueN < nValues; valueN++) {
1720        memmove (tBuffer + ((size_t) Var->NvalueBytes), tBuffer,
1721 		(size_t) Var->NvalueBytes);
1722        tBuffer += (size_t) Var->NvalueBytes;
1723     }
1724     if (!sX(ConvertBuffer(CDF->encoding,CDF->decoding,
1725 			  CDF->negToPosFp0,dataType,
1726 			  (nValues * numElems),
1727 			  buffer,buffer),&pStatus)) return pStatus;
1728   }
1729   else {
1730     if (!sX(DefaultPadBuffer(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
1731     if (!sX(ConvertBuffer(HostEncoding(),CDF->decoding,
1732 			  CDF->negToPosFp0,dataType,
1733 			  (nValues * numElems),
1734 			  buffer,buffer),&pStatus)) return pStatus;
1735   }
1736   return pStatus;
1737 }
1738 
1739 /******************************************************************************
1740 * HostEncoding.
1741 *    Returns encoding type of host machine.
1742 ******************************************************************************/
1743 
HostEncoding()1744 STATICforIDL Int32 HostEncoding ()
1745 {
1746 #if defined(sun)
1747   return ((Int32) SUN_ENCODING);
1748 #endif
1749 #if defined(vax)
1750   return ((Int32) VAX_ENCODING);
1751 #endif
1752 #if defined(MIPSEL)
1753   return ((Int32) DECSTATION_ENCODING);
1754 #endif
1755 #if defined(MIPSEB)
1756   return ((Int32) SGi_ENCODING);
1757 #endif
1758 #if defined(IBMPC) || defined(macosXintel)
1759   return ((Int32) IBMPC_ENCODING);
1760 #endif
1761 #if defined(IBMRS)
1762   return ((Int32) IBMRS_ENCODING);
1763 #endif
1764 #if defined(HP)
1765   return ((Int32) HP_ENCODING);
1766 #endif
1767 #if defined(NeXT)
1768   return ((Int32) NeXT_ENCODING);
1769 #endif
1770 #if defined(alphaosf)
1771   return ((Int32) ALPHAOSF1_ENCODING);
1772 #endif
1773 #if defined(alphavmsD) || defined(posixSHELLalphaD)
1774   return ((Int32) ALPHAVMSd_ENCODING);
1775 #endif
1776 #if defined(alphavmsG) || defined(posixSHELLalphaG)
1777   return ((Int32) ALPHAVMSg_ENCODING);
1778 #endif
1779 #if defined(alphavmsI) || defined(posixSHELLalphaI)
1780   return ((Int32) ALPHAVMSi_ENCODING);
1781 #endif
1782 #if defined(mac) || defined(POWERPC) || defined(macosXppc)
1783   return ((Int32) PPC_ENCODING);
1784 #endif
1785 }
1786 
1787 /******************************************************************************
1788 * HostDecoding.
1789 *    Returns decoding type of host machine.
1790 ******************************************************************************/
1791 
HostDecoding()1792 STATICforIDL Int32 HostDecoding ()
1793 {
1794 #if defined(sun)
1795   return ((Int32) SUN_DECODING);
1796 #endif
1797 #if defined(vax)
1798   return ((Int32) VAX_DECODING);
1799 #endif
1800 #if defined(MIPSEL)
1801   return ((Int32) DECSTATION_DECODING);
1802 #endif
1803 #if defined(MIPSEB)
1804   return ((Int32) SGi_DECODING);
1805 #endif
1806 #if defined(IBMPC) || defined(macosXintel)
1807   return ((Int32) IBMPC_DECODING);
1808 #endif
1809 #if defined(IBMRS)
1810   return ((Int32) IBMRS_DECODING);
1811 #endif
1812 #if defined(HP)
1813   return ((Int32) HP_DECODING);
1814 #endif
1815 #if defined(NeXT)
1816   return ((Int32) NeXT_DECODING);
1817 #endif
1818 #if defined(alphaosf)
1819   return ((Int32) ALPHAOSF1_DECODING);
1820 #endif
1821 #if defined(alphavmsD) || defined(posixSHELLalphaD)
1822   return ((Int32) ALPHAVMSd_DECODING);
1823 #endif
1824 #if defined(alphavmsG) || defined(posixSHELLalphaG)
1825   return ((Int32) ALPHAVMSg_DECODING);
1826 #endif
1827 #if defined(alphavmsI)
1828   return ((Int32) ALPHAVMSi_DECODING);
1829 #endif
1830 #if defined(mac) || defined(POWERPC) || defined(macosXppc)
1831   return ((Int32) PPC_DECODING);
1832 #endif
1833 }
1834 
1835 /******************************************************************************
1836 * IntegerOrder.
1837 *    Returns integer order based on encoding (decoding).
1838 ******************************************************************************/
1839 
IntegerOrder(ed)1840 STATICforIDL int IntegerOrder (ed)
1841 Int32 ed;                /* Encoding/decoding. */
1842 {
1843   switch (ed) {
1844     case NETWORK_ENCODING:
1845     case SUN_ENCODING:
1846     case SGi_ENCODING:
1847     case IBMRS_ENCODING:
1848     case HP_ENCODING:
1849     case NeXT_ENCODING:
1850     case PPC_ENCODING:
1851       return BIGendianORDER;
1852     case DECSTATION_ENCODING:
1853     case ALPHAOSF1_ENCODING:
1854     case ALPHAVMSd_ENCODING:
1855     case ALPHAVMSg_ENCODING:
1856     case ALPHAVMSi_ENCODING:
1857     case IBMPC_ENCODING:
1858     case VAX_ENCODING:
1859       return LITTLEendianORDER;
1860     default:
1861       return 0;                 /* Internal error. */
1862   }
1863 }
1864 
1865 /******************************************************************************
1866 * FpType.
1867 *    Returns floating-point type based on encoding (decoding).
1868 ******************************************************************************/
1869 
FpType(ed)1870 STATICforIDL int FpType (ed)
1871 Int32 ed;                /* Encoding/decoding. */
1872 {
1873   switch (ed) {
1874     case NETWORK_ENCODING:
1875     case SUN_ENCODING:
1876     case SGi_ENCODING:
1877     case IBMRS_ENCODING:
1878     case HP_ENCODING:
1879     case NeXT_ENCODING:
1880     case PPC_ENCODING:
1881       return FP_1;
1882     case DECSTATION_ENCODING:
1883     case ALPHAOSF1_ENCODING:
1884     case IBMPC_ENCODING:
1885     case ALPHAVMSi_ENCODING:
1886       return FP_2;
1887     case VAX_ENCODING:
1888     case ALPHAVMSd_ENCODING:
1889       return FP_3;
1890     case ALPHAVMSg_ENCODING:
1891       return FP_4;
1892     default:
1893       return 0;
1894   }
1895 }
1896 
1897 /******************************************************************************
1898 * CDFelemSize.
1899 ******************************************************************************/
1900 
CDFelemSize(dataType)1901 STATICforIDL int CDFelemSize (dataType)
1902 long dataType;
1903 {
1904   switch (dataType) {
1905     case CDF_BYTE: return 1;
1906     case CDF_INT1: return 1;
1907     case CDF_INT2: return 2;
1908     case CDF_INT4: return 4;
1909     case CDF_UINT1: return 1;
1910     case CDF_UINT2: return 2;
1911     case CDF_UINT4: return 4;
1912     case CDF_REAL4: return 4;
1913     case CDF_REAL8: return 8;
1914     case CDF_FLOAT: return 4;
1915     case CDF_DOUBLE: return 8;
1916     case CDF_EPOCH: return 8;
1917     case CDF_EPOCH16: return 16;
1918     case CDF_CHAR: return 1;
1919     case CDF_UCHAR: return 1;
1920   }
1921   return 0;
1922 }
1923 
1924 /******************************************************************************
1925 * EquivDataTypes.
1926 ******************************************************************************/
1927 
EquivDataTypes(dataType1,dataType2)1928 STATICforIDL Logical EquivDataTypes (dataType1, dataType2)
1929 Int32 dataType1;
1930 Int32 dataType2;
1931 {
1932   switch (dataType1) {
1933     case CDF_BYTE:
1934     case CDF_INT1:
1935     case CDF_UINT1:
1936     case CDF_CHAR:
1937     case CDF_UCHAR:
1938       switch (dataType2) {
1939         case CDF_BYTE:
1940         case CDF_INT1:
1941         case CDF_UINT1:
1942         case CDF_CHAR:
1943         case CDF_UCHAR:
1944 	  return TRUE;
1945         default:
1946 	  return FALSE;
1947       }
1948     case CDF_INT2:
1949     case CDF_UINT2:
1950       switch (dataType2) {
1951         case CDF_INT2:
1952         case CDF_UINT2:
1953 	  return TRUE;
1954         default:
1955 	  return FALSE;
1956       }
1957     case CDF_INT4:
1958     case CDF_UINT4:
1959       switch (dataType2) {
1960         case CDF_INT4:
1961         case CDF_UINT4:
1962 	  return TRUE;
1963         default:
1964 	  return FALSE;
1965       }
1966     case CDF_REAL4:
1967     case CDF_FLOAT:
1968       switch (dataType2) {
1969         case CDF_REAL4:
1970         case CDF_FLOAT:
1971 	  return TRUE;
1972         default:
1973 	  return FALSE;
1974       }
1975     case CDF_REAL8:
1976     case CDF_DOUBLE:
1977     case CDF_EPOCH:
1978       switch (dataType2) {
1979         case CDF_REAL8:
1980         case CDF_DOUBLE:
1981         case CDF_EPOCH:
1982 	  return TRUE;
1983         default:
1984 	  return FALSE;
1985       }
1986     case CDF_EPOCH16:
1987       switch (dataType2) {
1988         case CDF_EPOCH16:
1989           return TRUE;
1990         default:
1991           return FALSE;
1992       }
1993   }
1994   return FALSE;			/* CDF_INTERNAL_ERROR or CORRUPTED_V2_CDF? */
1995 }
1996 
1997 /******************************************************************************
1998 * strcmpITB.  Do a STRing CoMPare Ignoring any Trailing Blanks.
1999 ******************************************************************************/
2000 
strcmpITB(string1,string2)2001 STATICforIDL int strcmpITB (string1, string2)
2002 char *string1;
2003 char *string2;
2004 {
2005   size_t len1 = strlen(string1);
2006   size_t len2 = strlen(string2);
2007   while (len1 > 0 && string1[len1-1] == ' ') len1--;
2008   while (len2 > 0 && string2[len2-1] == ' ') len2--;
2009   if (len1 == len2)
2010     return strncmp (string1, string2, len1);
2011   else
2012     return strcmp (string1, string2);
2013 }
2014 
2015 
2016 /******************************************************************************
2017 * FreeCDFid.
2018 * Free a CDF's dynamically allocated memory.
2019 ******************************************************************************/
2020 
FreeCDFid(CDF,aborting)2021 STATICforIDL void FreeCDFid (CDF, aborting)
2022 struct CDFstruct *CDF;
2023 Logical aborting;
2024 {
2025   /****************************************************************************
2026   * Free file names/paths.
2027   ****************************************************************************/
2028   if (CDF->CDFname != NULL) cdf_FreeMemory (CDF->CDFname, NULL);
2029   if (CDF->scratchDir != NULL) cdf_FreeMemory (CDF->scratchDir, NULL);
2030   /****************************************************************************
2031   * Free rVariable structures.
2032   ****************************************************************************/
2033   if (CDF->rVars != NULL) {
2034     int varNum;
2035     for (varNum = 0; varNum < CDF->NrVars; varNum++) {
2036        if (CDF->rVars[varNum] != NULL) cdf_FreeMemory (CDF->rVars[varNum], NULL);
2037     }
2038     cdf_FreeMemory (CDF->rVars, NULL);
2039   }
2040   /****************************************************************************
2041   * Free zVariable structures.
2042   ****************************************************************************/
2043   if (CDF->zVars != NULL) {
2044     int varNum;
2045     for (varNum = 0; varNum < CDF->NzVars; varNum++) {
2046        if (CDF->zVars[varNum] != NULL) cdf_FreeMemory (CDF->zVars[varNum], NULL);
2047     }
2048     cdf_FreeMemory (CDF->zVars, NULL);
2049   }
2050   /****************************************************************************
2051   * Free CDF structure.  The CDF structure's magic number is "killed" just in
2052   * case the application tries to use the CDFid again.
2053   ****************************************************************************/
2054   if (aborting)
2055     CDF->magic = ABORTEDid_MAGIC_NUMBER;
2056   else {
2057     CDF->magic = KILLEDid_MAGIC_NUMBER;
2058     cdf_FreeMemory (CDF, NULL);
2059   }
2060   return;
2061 }
2062 
2063 /******************************************************************************
2064 * CloseLRUvar.
2065 * Close a variable/zVariable file to free a file pointer.
2066 ******************************************************************************/
2067 
CloseLRUvar(CDF)2068 STATICforIDL CDFstatus CloseLRUvar (CDF)
2069 struct CDFstruct *CDF;
2070 {
2071   struct VarStruct *Var, *oldestVar = NULL;
2072   uLong oldest_access = CDF->pseudo_clock; int varNum;
2073   /****************************************************************************
2074   * Scan through rVariables looking for oldest access.
2075   ****************************************************************************/
2076   for (varNum = 0; varNum < CDF->NrVars; varNum++) {
2077     Var = CDF->rVars[varNum];
2078     if (Var != NULL) {
2079       if (Var->fp != NULL) {
2080 	if (Var->accessed_at < oldest_access) {
2081 	  oldest_access = Var->accessed_at;
2082 	  oldestVar = Var;
2083 	}
2084       }
2085     }
2086   }
2087   /****************************************************************************
2088   * Scan through zVariables looking for oldest access.
2089   ****************************************************************************/
2090   for (varNum = 0; varNum < CDF->NzVars; varNum++) {
2091     Var = CDF->zVars[varNum];
2092     if (Var != NULL) {
2093       if (Var->fp != NULL) {
2094 	if (Var->accessed_at < oldest_access) {
2095 	  oldest_access = Var->accessed_at;
2096 	  oldestVar = Var;
2097 	}
2098       }
2099     }
2100   }
2101   /****************************************************************************
2102   * If a variable was found, close the associated file.
2103   ****************************************************************************/
2104   if (oldestVar != NULL) {
2105     if (!CLOSEv(oldestVar->fp,NULL,NULL)) {
2106       oldestVar->fp = NULL;
2107       return VAR_CLOSE_ERROR;
2108     }
2109     oldestVar->fp = NULL;
2110   }
2111   return CDF_OK;
2112 }
2113 
2114 /******************************************************************************
2115 * CheckEntryOp.
2116 ******************************************************************************/
2117 
CheckEntryOp(CDF,entryType)2118 STATICforIDL CDFstatus CheckEntryOp (CDF, entryType)
2119 struct CDFstruct *CDF;
2120 int entryType;
2121 {
2122   Int32 scope; CDFstatus pStatus = CDF_OK;
2123   if (!sX(ReadADR(CDF->fp,CDF->CURattrOffset,
2124                   ADR_SCOPE,&scope,
2125                   ADR_NULL),&pStatus)) {
2126     AbortAccess (CDF, UPDATE, noDELETE);
2127     return pStatus;
2128   }
2129   if (GLOBALscope(scope)) {
2130     if (entryType != gENTRYt) return ILLEGAL_FOR_SCOPE;
2131   }
2132   else {
2133     if (entryType == gENTRYt) return ILLEGAL_FOR_SCOPE;
2134     if (BADzOP(CDF,entryType == rENTRYt)) return ILLEGAL_IN_zMODE;
2135   }
2136   return pStatus;
2137 }
2138 
2139 /******************************************************************************
2140 * SetCURgrEntry.
2141 ******************************************************************************/
2142 
SetCURgrEntry(CDF,useCurrent,entryNum)2143 STATICforIDL CDFstatus SetCURgrEntry (CDF, useCurrent, entryNum)
2144 struct CDFstruct *CDF;
2145 Logical useCurrent;	/* TRUE if current g/rEntry offset can be used to speed
2146 			   up the search. */
2147 Int32 entryNum;		/* The new g/rEntry number. */
2148 {
2149   CDFstatus pStatus = CDF_OK, tStatus;
2150   Int32 scope, offset, attrNum, attrNumX, entryNumX, nextOffset;
2151   long read_only_mode;
2152   /****************************************************************************
2153   * Check if the new g/rEntry number is the reserved entry number.
2154   ****************************************************************************/
2155   if (entryNum == RESERVED_ENTRYNUM) {
2156     CDF->CURgrEntryNum = RESERVED_ENTRYNUM;
2157     CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
2158     CDF->CURgrEntryOffset = RESERVED_ENTRYOFFSET;
2159     return pStatus;
2160   }
2161   /****************************************************************************
2162   * Check that a current attribute is selected.
2163   ****************************************************************************/
2164   if (CDF->CURattrOffset == RESERVED_ATTROFFSET) {
2165     CDF->CURgrEntryNum = entryNum;
2166     CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
2167     CDF->CURgrEntryOffset = RESERVED_ENTRYOFFSET;
2168     return pStatus;
2169   }
2170   /****************************************************************************
2171   * Get the scope and number of the current attribute. If READONLYon, the
2172   * scope and number are already in th mteadata structures.
2173   ****************************************************************************/
2174   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
2175   if (pStatus != CDF_OK) return pStatus;
2176   if (read_only_mode == READONLYon)
2177   {
2178       scope = CDF->fp->ADRList[CDF->fp->CurADRIndex]->Scope;
2179       attrNum = CDF->fp->CurADRIndex;
2180   }
2181   else
2182   {
2183       if (!sX(ReadADR(CDF->fp,CDF->CURattrOffset,
2184                       ADR_SCOPE,&scope,
2185                       ADR_NUM,&attrNum,
2186                       ADR_NULL),&pStatus)) return pStatus;
2187   };
2188   /****************************************************************************
2189   * If the current attribute is variable-scoped and zMode is on, then the
2190   * current g/rEntry offset is n/a.
2191   ****************************************************************************/
2192   if (VARIABLEscope(scope) && zModeON(CDF)) {
2193     CDF->CURgrEntryNum = entryNum;
2194     CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
2195     CDF->CURgrEntryOffset = RESERVED_ENTRYOFFSET;
2196     return pStatus;
2197   }
2198   /****************************************************************************
2199   * IF READONLYoff, check if the next entry is the one being searched for.
2200   * For this to be the case, an entry must currently be selected and must be
2201   * associated with the current attribute, the next entry must exist, and the
2202   * next entry's number must be the entry number being searched for.  But
2203   * don't try this if a V2.0 CDF because of the bad terminating offset of the
2204   * AEDR linked lists in those CDFs.
2205   ****************************************************************************/
2206   if (read_only_mode == READONLYoff && useCurrent &&
2207       !CDF->badTerminatingOffsets) {
2208     if (CDF->CURgrEntryOffset != RESERVED_ENTRYOFFSET) {
2209       if (!sX(ReadAEDR(CDF->fp,CDF->CURgrEntryOffset,
2210 		       AEDR_ATTRNUM,&attrNumX,
2211 		       AEDR_AEDRNEXT,&nextOffset,
2212 		       AEDR_NULL),&pStatus)) return pStatus;
2213       if (attrNumX == attrNum && nextOffset != 0) {
2214 	if (!sX(ReadAEDR(CDF->fp,nextOffset,
2215 			 AEDR_NUM,&entryNumX,
2216 			 AEDR_NULL),&pStatus)) return pStatus;
2217 	if (entryNumX == entryNum) {
2218 	  CDF->CURgrEntryNum = entryNum;
2219 	  CDF->CURgrEntryOffset = nextOffset;
2220 	  return pStatus;
2221 	}
2222       }
2223     }
2224   }
2225   /****************************************************************************
2226   * Search the list of AEDRs for the entry.
2227   ****************************************************************************/
2228   tStatus = FindEntryByNumber (CDF, CDF->CURattrOffset, FALSE, entryNum,
2229 			       &offset);
2230   switch (tStatus) {
2231     case CDF_OK:
2232       break;
2233     case NO_SUCH_ENTRY:
2234       offset = RESERVED_ENTRYOFFSET;
2235       break;
2236     default:
2237       return tStatus;
2238   }
2239   CDF->CURgrEntryNum = entryNum;
2240   CDF->CURgrEntryOffset = offset;
2241   return pStatus;
2242 }
2243 
2244 /******************************************************************************
2245 * SetCURzEntry.
2246 ******************************************************************************/
2247 
SetCURzEntry(CDF,useCurrent,entryNum)2248 STATICforIDL CDFstatus SetCURzEntry (CDF, useCurrent, entryNum)
2249 struct CDFstruct *CDF;
2250 Logical useCurrent;	/* TRUE if current zEntry offset can be used to speed
2251 			   up the search. */
2252 Int32 entryNum;		/* The new zEntry number. */
2253 {
2254   CDFstatus pStatus = CDF_OK, tStatus;
2255   Int32 scope, offset, attrNum, attrNumX, entryNumX, nextOffset;
2256   Logical zEntry;
2257   Int32 entryN;
2258   long read_only_mode;
2259   /****************************************************************************
2260   * Check if the new zEntry number is the reserved entry number.
2261   ****************************************************************************/
2262   if (entryNum == RESERVED_ENTRYNUM) {
2263     CDF->CURzEntryNum = RESERVED_ENTRYNUM;
2264     CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
2265     CDF->CURzEntryOffset = RESERVED_ENTRYOFFSET;
2266     return pStatus;
2267   }
2268   /****************************************************************************
2269   * Check that a current attribute is selected.
2270   ****************************************************************************/
2271   if (CDF->CURattrOffset == RESERVED_ATTROFFSET) {
2272     CDF->CURzEntryNum = entryNum;
2273     CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
2274     CDF->CURzEntryOffset = RESERVED_ENTRYOFFSET;
2275     return pStatus;
2276   }
2277   /****************************************************************************
2278   * Read the scope and number of the current attribute. If READONLYon, they
2279   * are already in memory.
2280   ****************************************************************************/
2281   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
2282   if (pStatus != CDF_OK) return pStatus;
2283   if (read_only_mode == READONLYon)
2284   {
2285       scope = CDF->fp->ADRList[CDF->fp->CurADRIndex]->Scope;
2286       attrNum = CDF->fp->CurADRIndex;
2287   }
2288   else
2289   {
2290       if (!sX(ReadADR(CDF->fp,CDF->CURattrOffset,
2291                       ADR_SCOPE,&scope,
2292                       ADR_NUM,&attrNum,
2293                       ADR_NULL),&pStatus)) return pStatus;
2294   };
2295   /****************************************************************************
2296   * If the current attribute is global-scoped, then the current zEntry offset
2297   * is n/a.
2298   ****************************************************************************/
2299   if (GLOBALscope(scope)) {
2300     CDF->CURzEntryNum = entryNum;
2301     CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
2302     CDF->CURzEntryOffset = RESERVED_ENTRYOFFSET;
2303     return pStatus;
2304   }
2305   /****************************************************************************
2306   * Determine if a AgrEDR or AzEDR and the true entry number.
2307   ****************************************************************************/
2308   if (zModeON(CDF)) {
2309     if (entryNum < CDF->NrVars) {
2310       zEntry = FALSE;
2311       entryN = entryNum;
2312     }
2313     else {
2314       zEntry = TRUE;
2315       entryN = entryNum - CDF->NrVars;
2316     }
2317   }
2318   else {
2319     zEntry = TRUE;
2320     entryN = entryNum;
2321   }
2322   /****************************************************************************
2323   * IF READONLYoff, check if the next entry is the one being searched for.
2324   * For this to be the case, an entry must currently be selected and must be
2325   * associated with the current attribute, the next entry must exist, and the
2326   * next entry's number must be the entry number being searched for.  But don't
2327   * try this if a V2.0 CDF because of the bad terminating offset of the AEDR
2328   * linked lists in those CDFs.
2329   ****************************************************************************/
2330   if (read_only_mode == READONLYoff && useCurrent &&
2331       !CDF->badTerminatingOffsets) {
2332     if (CDF->CURzEntryOffset != RESERVED_ENTRYOFFSET) {
2333       if (!sX(ReadAEDR(CDF->fp,CDF->CURzEntryOffset,
2334 		       AEDR_ATTRNUM,&attrNumX,
2335 		       AEDR_AEDRNEXT,&nextOffset,
2336 		       AEDR_NULL),&pStatus)) return pStatus;
2337       if (attrNumX == attrNum && nextOffset != 0) {
2338 	if (!sX(ReadAEDR(CDF->fp,nextOffset,
2339 			 AEDR_NUM,&entryNumX,
2340 			 AEDR_NULL),&pStatus)) return pStatus;
2341 	if (entryNumX == entryN) {
2342 	  CDF->CURzEntryNum = entryNum;
2343 	  CDF->CURzEntryOffset = nextOffset;
2344 	  return pStatus;
2345 	}
2346       }
2347     }
2348   }
2349   /****************************************************************************
2350   * Search the list of AEDRs for the entry.
2351   ****************************************************************************/
2352   tStatus = FindEntryByNumber (CDF, CDF->CURattrOffset, zEntry, entryN,
2353 			       &offset);
2354   switch (tStatus) {
2355     case CDF_OK:
2356       break;
2357     case NO_SUCH_ENTRY:
2358       offset = RESERVED_ENTRYOFFSET;
2359       break;
2360     default:
2361       return tStatus;
2362   }
2363   CDF->CURzEntryNum = entryNum;
2364   CDF->CURzEntryOffset = offset;
2365   return pStatus;
2366 }
2367 
2368 /******************************************************************************
2369 * Int32ToCDFid.
2370 ******************************************************************************/
2371 
Int32ToCDFid(id)2372 STATICforIDL CDFid Int32ToCDFid (id)
2373 Int32 id;
2374 {
2375 #if defined(alphaosf) || defined(IRIX64bit) || defined(SOLARIS64) || \
2376     defined(__amd64) || defined(__x86_64__) || defined(__ia64__) || \
2377     defined(__PPC64__) || defined(__ppc64__)
2378 # if defined(alphaosf)
2379    if (id == 0)
2380      return RESERVED_CDFID;
2381    else
2382      return ((CDFid) ((long) id | (long) 0x100000000));
2383 # else
2384    union {
2385      CDFid id;
2386      Int32 i[2];
2387    } u;
2388 #   if defined(IRIX64bit) || defined(SOLARIS64) || defined(__PPC64__) || \
2389        defined(__ppc64__)
2390 #      if defined(IRIX64bit)
2391          u.i[0] = 0;
2392 #      else
2393          u.i[0] = 1;
2394 #      endif
2395        u.i[1] = id;
2396 #   else
2397 #      if defined(__MACH__) /* Mac on Intel */
2398          u.i[1] = 1;
2399          u.i[0] = id;
2400 #      else
2401          u.i[1] = 0;
2402          u.i[0] = id;
2403 #      endif
2404 #   endif
2405     return u.id;
2406 # endif
2407 #else
2408   return ((CDFid) id);
2409 #endif
2410 }
2411 
2412 /******************************************************************************
2413 * CDFidToInt32.
2414 *    On 64-bit machines (OSF/1, IRIX 6.x and Solaris in 64-bit mode),
2415 *    truncation may occur when the pointer (CDFid) is assigned to a 32-bit
2416 *    integer.
2417 ******************************************************************************/
2418 
CDFidToInt32(id)2419 STATICforIDL Int32 CDFidToInt32 (id)
2420 CDFid id;
2421 {
2422 #if defined(alphaosf) || defined(IRIX64bit) || defined(SOLARIS64) || \
2423     defined(__amd64) || defined(__x86_64__) || defined(__ia64__) || \
2424     defined(__PPC64__) || defined(__ppc64__)
2425   union {
2426     CDFid id;
2427     Int32 i[2];
2428   } u;
2429   u.id = id;
2430 # if defined(alphaosf) || defined(__amd64) || defined(__x86_64__) || \
2431      defined(__ia64__)
2432     return u.i[0];
2433 # endif
2434 # if defined(IRIX64bit) || defined(SOLARIS64) || defined(__PPC64__) || \
2435      defined(__ppc64__)
2436     return u.i[1];
2437 # endif
2438 #else
2439   return ((Int32) id);
2440 #endif
2441 }
2442 
2443 /******************************************************************************
2444 * VariableType.
2445 ******************************************************************************/
2446 
VariableType(CDF,vdrOffset,zVar,vType)2447 STATICforIDL CDFstatus VariableType (CDF, vdrOffset, zVar, vType)
2448 struct CDFstruct *CDF;
2449 Int32 vdrOffset;
2450 Logical zVar;
2451 int *vType;
2452 {
2453   CDFstatus pStatus = CDF_OK; Int32 flags, sRecords;
2454   if (!sX(ReadVDR(CDF,CDF->fp,vdrOffset,zVar,
2455 		  VDR_FLAGS,&flags,
2456 		  VDR_sRECORDS,&sRecords,
2457 		  VDR_NULL),&pStatus)) return pStatus;
2458   if (CDF->singleFile) {
2459     if (VARcompressionBITset(flags) && SPARSEarraysBITset(flags)) {
2460       return CORRUPTED_V2_CDF;
2461     }
2462     if (sRecords == NO_SPARSERECORDS) {
2463       *vType = STANDARD_;
2464       if (VARcompressionBITset(flags)) *vType = COMPRESSED_;
2465       if (SPARSEarraysBITset(flags)) *vType = SPARSE_ARRAYS_;
2466     }
2467     else {
2468       *vType = SPARSE_RECORDS_;
2469       if (VARcompressionBITset(flags)) *vType = SPARSE_COMPRESSED_RECORDS_;
2470       if (SPARSEarraysBITset(flags)) *vType = SPARSE_RECORDS_AND_ARRAYS_;
2471     }
2472   }
2473   else {
2474     *vType = IN_MULTI_;
2475     if (VARcompressionBITset(flags)) return CORRUPTED_V2_CDF;
2476     if (SPARSEarraysBITset(flags)) return CORRUPTED_V2_CDF;
2477     if (sRecords != NO_SPARSERECORDS) return CORRUPTED_V2_CDF;
2478   }
2479   return pStatus;
2480 }
2481 
2482 /******************************************************************************
2483 * CompressionParmsCount.
2484 ******************************************************************************/
2485 
CompressionParmsCount(cType)2486 STATICforIDL int CompressionParmsCount (cType)
2487 Int32 cType;
2488 {
2489   switch (cType) {
2490     case NO_COMPRESSION: return 0;
2491     case RLE_COMPRESSION: return NUM_RLE_PARMS;
2492     case HUFF_COMPRESSION: return NUM_HUFF_PARMS;
2493     case AHUFF_COMPRESSION: return NUM_AHUFF_PARMS;
2494     case GZIP_COMPRESSION: return NUM_GZIP_PARMS;
2495 /*    case ZLIB_COMPRESSION: return NUM_ZLIB_PARMS; */
2496   }
2497   return 0;	/* CORRUPTED_V2_CDF or CDF_INTERNAL_ERROR? */
2498 }
2499 
2500 /******************************************************************************
2501 * SparsenessParmsCount.
2502 ******************************************************************************/
2503 
SparsenessParmsCount(sArraysType)2504 STATICforIDL int SparsenessParmsCount (sArraysType)
2505 Int32 sArraysType;
2506 {
2507   switch (sArraysType) {
2508     case NO_SPARSEARRAYS:
2509       return 0;
2510   }
2511   return 0;	/* CORRUPTED_V2_CDF or CDF_INTERNAL_ERROR? */
2512 }
2513 
2514 /******************************************************************************
2515 * Compress.
2516 ******************************************************************************/
2517 
Compress(iFp,iOffset,iSize,iError,cType,cParms,oFp,oOffset,oSize,oError)2518 STATICforIDL CDFstatus Compress (iFp, iOffset, iSize, iError, cType, cParms,
2519 				 oFp, oOffset, oSize, oError)
2520 vFILE *iFp;
2521 Int32 iOffset;
2522 Int32 iSize;
2523 CDFstatus iError;
2524 Int32 cType;
2525 Int32 cParms[];
2526 vFILE *oFp;
2527 Int32 oOffset;
2528 Int32 *oSize;
2529 CDFstatus oError;
2530 {
2531   CDFstatus pStatus = CDF_OK;
2532   switch (cType) {
2533     case RLE_COMPRESSION: {
2534       if (cParms[0] != RLE_OF_ZEROs) return UNKNOWN_COMPRESSION;
2535       if (!sX(CompressRLE0(iFp,iOffset,iSize,iError,
2536 			   oFp,oOffset,oSize,oError),&pStatus)) return pStatus;
2537       break;
2538     }
2539     case HUFF_COMPRESSION:
2540       if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION;
2541       if (!sX(CompressHUFF0(iFp,iOffset,
2542 			    iSize,iError,oFp,
2543 			    oOffset,oSize,oError),&pStatus)) return pStatus;
2544       break;
2545     case AHUFF_COMPRESSION:
2546       if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION;
2547       if (!sX(CompressAHUFF0(iFp,iOffset,
2548 			     iSize,iError,oFp,
2549 			     oOffset,oSize,oError),&pStatus)) return pStatus;
2550       break;
2551     case GZIP_COMPRESSION:
2552       if (!INCLUSIVE(1,cParms[0],9)) return UNKNOWN_COMPRESSION;
2553       if (!sX(CompressGZIP(iFp,iOffset,iSize,iError,
2554 			   oFp,oOffset,oSize,
2555 			   oError,cParms[0]),&pStatus)) return pStatus;
2556       break;
2557     default:
2558       return UNKNOWN_COMPRESSION;
2559   }
2560   return pStatus;
2561 }
2562 
2563 /******************************************************************************
2564 * Decompress.
2565 ******************************************************************************/
2566 
Decompress(iFp,iOffset,iSize,iError,cType,cParms,oFp,oOffset,oError)2567 STATICforIDL CDFstatus Decompress (iFp, iOffset, iSize, iError, cType, cParms,
2568 				   oFp, oOffset, oError)
2569 vFILE *iFp;
2570 Int32 iOffset;
2571 Int32 iSize;
2572 CDFstatus iError;
2573 Int32 cType;
2574 Int32 cParms[];
2575 vFILE *oFp;
2576 Int32 oOffset;
2577 CDFstatus oError;
2578 {
2579   CDFstatus pStatus = CDF_OK;
2580   switch (cType) {
2581     case RLE_COMPRESSION: {
2582       if (cParms[0] != RLE_OF_ZEROs) return UNKNOWN_COMPRESSION;
2583       if (!sX(DecompressRLE0(iFp,iOffset,iSize,iError,
2584 			     oFp,oOffset,oError),&pStatus)) return pStatus;
2585       break;
2586     }
2587     case HUFF_COMPRESSION:
2588       if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION;
2589       if (!sX(DecompressHUFF0(iFp,iOffset,iError,
2590 			      oFp,oOffset,oError),&pStatus)) return pStatus;
2591       break;
2592     case AHUFF_COMPRESSION:
2593       if (cParms[0] != OPTIMAL_ENCODING_TREES) return UNKNOWN_COMPRESSION;
2594       if (!sX(DecompressAHUFF0(iFp,iOffset,iError,
2595 			       oFp,oOffset,oError),&pStatus)) return pStatus;
2596       break;
2597     case GZIP_COMPRESSION:
2598       if (!INCLUSIVE(1,cParms[0],9)) return UNKNOWN_COMPRESSION;
2599       if (!sX(DecompressGZIP(iFp,iOffset,iError,
2600 			     oFp,oOffset,oError),&pStatus)) return pStatus;
2601       break;
2602     default:
2603       return UNKNOWN_COMPRESSION;
2604   }
2605   return pStatus;
2606 }
2607 
2608 /******************************************************************************
2609 * DecompressToStage.
2610 ******************************************************************************/
2611 
DecompressToStage(CDF,Var,offset,uSize)2612 STATICforIDL CDFstatus DecompressToStage (CDF, Var, offset, uSize)
2613 struct CDFstruct *CDF;
2614 struct VarStruct *Var;
2615 Int32 offset;
2616 Int32 uSize;
2617 {
2618   CDFstatus pStatus = CDF_OK; Int32 irType, tOffset;
2619   if (!sX(ReadIrType(CDF->fp,offset,&irType),&pStatus)) return pStatus;
2620   switch (irType) {
2621     case VVR_: {
2622       tOffset = offset + VVR_BASE_SIZE;
2623       if (!sX(CopyBytes(CDF->fp,tOffset,
2624 			CDF_READ_ERROR,
2625 			uSize,CDF->stage.fp,
2626 			Var->stage.areaOffset,
2627 			SCRATCH_WRITE_ERROR),&pStatus)) return pStatus;
2628       break;
2629     }
2630     case CVVR_: {
2631       struct CVVRstruct CVVR;
2632       if (!sX(ReadCVVR(CDF->fp,offset,
2633 		       CVVR_RECORDx,&CVVR,
2634 		       CVVR_NULL),&pStatus)) return pStatus;
2635       tOffset = offset + CVVR_BASE_SIZE;
2636       if (!sX(Decompress(CDF->fp,tOffset,
2637 			 CVVR.cSize,CDF_READ_ERROR,
2638 			 Var->cType,Var->cParms,CDF->stage.fp,
2639 			 Var->stage.areaOffset,
2640 			 SCRATCH_WRITE_ERROR),&pStatus)) return pStatus;
2641       break;
2642     }
2643     default:
2644       return CORRUPTED_V2_CDF;
2645   }
2646   return pStatus;
2647 }
2648 
2649 /******************************************************************************
2650 * ResetReadOnlyState.
2651 ******************************************************************************/
2652 
ResetReadOnlyState(CDF)2653 STATICforIDL void ResetReadOnlyState (CDF)
2654 struct CDFstruct *CDF;
2655 {
2656     Int32 i, j;
2657     /*************************************************************************
2658     * Free all allocated memory associated with the metadata READONLYon data
2659     * structures and clear all the state variables.
2660     *************************************************************************/
2661     if (CDF->fp != NULL && CDF->fp->GDR != NULL)
2662     {
2663         for (i = 0; i < CDF->fp->GDR->NumAttr; i++)
2664         {
2665             if (CDF->fp->ADRList[i] != NULL)
2666             {
2667                 for (j = 0; j <= CDF->fp->ADRList[i]->MAXgrEntry; j++)
2668                 {
2669                     if (CDF->fp->ADRList[i]->grAEDRList[j] != NULL)
2670                     {
2671                         cdf_FreeMemory(
2672                            CDF->fp->ADRList[i]->grAEDRList[j]->Value, NULL);
2673                         CDF->fp->ADRList[i]->grAEDRList[j]->Value = NULL;
2674                         cdf_FreeMemory(CDF->fp->ADRList[i]->grAEDRList[j],
2675                                        NULL);
2676                         CDF->fp->ADRList[i]->grAEDRList[j] = NULL;
2677                     };
2678                 };
2679                 for (j = 0; j <= CDF->fp->ADRList[i]->MAXzEntry; j++)
2680                 {
2681                     if (CDF->fp->ADRList[i]->zAEDRList[j] != NULL)
2682                     {
2683                         cdf_FreeMemory(
2684                            CDF->fp->ADRList[i]->zAEDRList[j]->Value, NULL);
2685                         CDF->fp->ADRList[i]->zAEDRList[j]->Value = NULL;
2686                         cdf_FreeMemory(CDF->fp->ADRList[i]->zAEDRList[j], NULL);
2687                         CDF->fp->ADRList[i]->zAEDRList[j] = NULL;
2688                     };
2689                 };
2690             };
2691             cdf_FreeMemory(CDF->fp->ADRList[i], NULL);
2692             CDF->fp->ADRList[i] = NULL;
2693         };
2694         if (CDF->fp->ADRList != NULL)
2695         {
2696             cdf_FreeMemory(CDF->fp->ADRList, NULL);
2697             CDF->fp->ADRList = NULL;
2698         };
2699         cdf_FreeMemory(CDF->fp->GDR, NULL);
2700         CDF->fp->GDR = NULL;
2701         CDF->fp->CurADRIndex = RESERVED_ENTRYNUM;
2702         CDF->fp->CurAEDRIndex = RESERVED_ENTRYNUM;
2703         CDF->CURattrOffset = RESERVED_ATTROFFSET;
2704         CDF->CURgrEntryOffset = RESERVED_ENTRYOFFSET;
2705         CDF->CURzEntryOffset = RESERVED_ENTRYOFFSET;
2706     };
2707 }
2708