home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / hdf / unix / hdf3_2r2 / src / dfstubs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-29  |  41.9 KB  |  1,684 lines

  1. /***************************************************************************
  2. *
  3. *
  4. *                         NCSA HDF version 3.2r2
  5. *                            October 30, 1992
  6. *
  7. * NCSA HDF Version 3.2 source code and documentation are in the public
  8. * domain.  Specifically, we give to the public domain all rights for future
  9. * licensing of the source code, all resale rights, and all publishing rights.
  10. *
  11. * We ask, but do not require, that the following message be included in all
  12. * derived works:
  13. *
  14. * Portions developed at the National Center for Supercomputing Applications at
  15. * the University of Illinois at Urbana-Champaign, in collaboration with the
  16. * Information Technology Institute of Singapore.
  17. *
  18. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  19. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  20. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  21. *
  22. ****************************************************************************
  23. */
  24.  
  25. #ifdef RCSID
  26. static char RcsId[] = "@(#)$Revision: 1.3 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/src/RCS/dfstubs.c,v 1.3 1992/10/23 00:14:11 koziol beta koziol $
  30.  
  31. $Log: dfstubs.c,v $
  32.  * Revision 1.3  1992/10/23  00:14:11  koziol
  33.  * Changed all DFIstr*() and DFImem*() calls to HDstr*() and HDmem*() calls
  34.  * #ifdef'd out the macros Jason defined for Hopen, Hclose, etc. for Vsets
  35.  * Replaced Vset VFREESPACE and VGETSPACE calls with actual calls to HDfreespace
  36.  * and HDgetspace
  37.  * Added a MS-Windows lower lower for file I/O (which may not be completely working
  38.  *
  39.  * Revision 1.2  1992/10/12  18:11:51  koziol
  40.  * Updated for v3.2r2 release
  41.  *
  42.  * Revision 1.1  1992/08/25  21:40:44  koziol
  43.  * Initial revision
  44.  *
  45. */
  46. /*
  47. ** FILE
  48. **    dfstubs.c
  49. **    V3.X stubs for V4.0 "H-level" I/O routines.  First implemented: V3.2
  50. ** EXPORTED ROUTINES
  51. **    *DFopen -- open HDF file
  52. **    *DFclose -- close HDF file
  53. **    *DFdescriptors -- return a list of the data descriptors in the HDF file
  54. **    *DFnumber -- count the number of occurrances of a given tag in HDF file
  55. **    *DFsetfind -- set up a search
  56. **    *DFfind -- search for tag/ref combination
  57. **    DFaccess -- set up a read/write on a data element
  58. **    DFstart -- set up a read/write on a data element
  59. **    DFread -- read a portion of a data element
  60. **    DFseek -- seek a new position within a data element
  61. **    DFwrite -- write a portion of a data element
  62. **    DFupdate -- write out updated DDs to HDF file
  63. **    *DFstat -- provide status information about HDF file
  64. **    *DFgetelement -- read an entire data element
  65. **    *DFputelement -- write an entire data element
  66. **    *DFdup -- create an additional descriptor for a data element
  67. **    *DFdel -- delete a data element
  68. **    *DFnewref -- get an unused reference number
  69. **    *DFishdf -- is this an HDF file?
  70. **    *DFerrno -- return value of DFerror
  71. ** AUTHOR
  72. **    Doug Ilg
  73. */
  74. #include "dfstubs.h"
  75. #include "df.h"
  76.  
  77. #define CKMALLOC( x, ret) { if (!x) { DFerror = DFE_NOSPACE; return(ret); } }
  78.  
  79. #define CKSEEK(x,y,z, ret)  {  if (DF_SEEK( x,(long)y,z) <0) \
  80.                 {DFerror = DFE_SEEKERROR; return(ret); } }
  81.  
  82. #define CKSEEKEND(x,y,z, ret)   {  if (DF_SKEND( x,(long)y,z) <0) \
  83.                 {DFerror = DFE_SEEKERROR; return(ret); } }
  84.  
  85. #ifdef VMS
  86. #define CKREAD(x,y,z,f, ret)    { \
  87.                 int32 currfileposn; \
  88.                 currfileposn = DF_TELL(f); \
  89.                 if (DF_READ( (char*)x, (int)(y), (int)(z), (f))<0) \
  90.                 { DFerror = DFE_READERROR; return(ret); } \
  91.                 DF_SEEK(f, (long) (currfileposn + y*z), 0); \
  92.                 }
  93. #else /*VMS*/
  94. #define CKREAD(x,y,z,f, ret)    { \
  95.                 if (DF_READ( (char*)x, (int)(y), (int)(z), (f))<0) \
  96.                 { DFerror = DFE_READERROR; return(ret); } \
  97.                 }
  98. #endif /*VMS*/
  99.  
  100. #define CKWRITE(x,y,z,f, ret)   { if (DF_WRITE( (char*)x, (int)y, (int)z,f)<0) \
  101.                 {DFerror = DFE_WRITEERROR; return(ret); } }
  102.  
  103. /*
  104.  *  Important Internal Variables
  105.  */
  106. static DF *DFlist=NULL;         /* pointer to list of open DFs */
  107. #ifdef PERM_OUT
  108. static int DFinuse=0;           /* How many are currently in use */
  109. static uint16 DFmaxref;         /* which is the largest ref used? */
  110. static unsigned char *DFreflist=NULL; /* list of refs in use */
  111. static char patterns[] = {0x80, 0x40, 0x20, 0x10, 0x08,
  112.                                        0x04, 0x02, 0x01};
  113. #endif /* PERM_OUT */
  114.  
  115. /*
  116. ** NAME
  117. **    DFopen -- open HDF file
  118. ** USAGE
  119. **    DF *DFopen(name, access, ndds)
  120. **    char* name;        IN: name of file to open
  121. **    int access;        IN: DFACC_READ, DFACC_WRITE, DFACC_CREATE,
  122. **                    DFACC_ALL
  123. **    int ndds;        IN: number of DDs in a block
  124. ** RETURNS
  125. **    DF ptr to open file on success, NULL on failure with DFerror set
  126. ** DESCRIPTION
  127. **    Open an HDF file, if it exists.  If file does not exist and write
  128. **    access requested, create file.
  129. ** GLOBAL VARIABLES
  130. ** COMMENTS, BUGS, ASSUMPTIONS
  131. **    The pointer returned by DFopen is NOT a reference to a DF.  It is
  132. **    just a place keeper for the new type of file handle.  Any program that
  133. **    relies on the contents of a DF returned by DFopen must be re-written.
  134. ** EXAMPLES
  135. ** REVISION LOG
  136. */
  137. #ifdef PROTOTYPE
  138. DF *DFopen(char *name, int access, int ndds)
  139. #else
  140.     DF *
  141. DFopen(name, access, ndds)
  142.     char *name;
  143.     int access;
  144.     int ndds;
  145. #endif /* PROTOTYPE */
  146. {
  147.     if (DFIcheck(DFlist) == 0) {
  148.         DFerror = DFE_TOOMANY;
  149.         return(NULL);
  150.     }
  151.     else
  152.         DFerror = DFE_NONE;
  153.  
  154.     DFaccmode = access | DFACC_READ;
  155.     DFid = Hopen(name, DFaccmode, ndds);
  156.  
  157.     if(DFid == -1) {
  158.         DFerror = HEvalue(1);
  159.         return(NULL);
  160.     }
  161.     else {
  162.         /*
  163.         DFlist = makedf(DFid);
  164.     */
  165.         DFlist = (DF *)&DFid;
  166.         return(DFlist);
  167.     }
  168. }
  169.  
  170. /*
  171. ** NAME
  172. **    DFclose -- close HDF file
  173. ** USAGE
  174. **    int DFclose(dfile)
  175. **    DF *dfile;        IN: pointer to an open DF file
  176. ** RETURNS
  177. **    0 on success, -1 on failure with DFerror set
  178. ** DESCRIPTION
  179. **    Write out updated DDs; close DF file.
  180. ** GLOBAL VARIABLES
  181. ** COMMENTS, BUGS, ASSUMPTIONS
  182. ** EXAMPLES
  183. ** REVISION LOG
  184. */
  185. #ifdef PROTOTYPE
  186. int DFclose(DF *dfile)
  187. #else
  188.     int
  189. DFclose(dfile)
  190.     DF *dfile;
  191. #endif /* PROTOTYPE */
  192. {
  193.     int stat;
  194.  
  195.     if (DFIcheck(dfile) != 0) {
  196.         DFerror = DFE_NOTOPEN;
  197.         return(FAIL);
  198.     }
  199.     else
  200.         DFerror = DFE_NONE;
  201.  
  202.     if (DFelstat == DFEL_RESIDENT) {
  203.         Hputelement(DFid, acc_tag, acc_ref, (unsigned char *)DFelement, DFelsize);
  204.         free(DFelement);
  205.     }
  206.     else
  207.         Hendaccess(DFaid);
  208.  
  209.     if (search_stat == DFSRCH_OLD) {
  210.         Hendaccess(search_aid);
  211.         search_aid = 0;
  212.     }
  213.  
  214.     stat = Hclose(DFid);
  215.     if(stat == 0) {
  216.         dfile = 0;
  217.         DFlist = (DF *)NULL;
  218.         DFid = 0;
  219.         DFaccmode = 0;
  220.     } else {
  221.         DFerror = HEvalue(1);
  222.     }
  223.  
  224.     return(stat);
  225. }
  226.  
  227. /*
  228. ** NAME
  229. **    DFdescriptors -- return a list of the data descriptors in the file
  230. ** USAGE
  231. **    int DFdescriptors(dfile, ptr, begin, num)
  232. **    DF *dfile;        IN: pointer to an open DF file
  233. **    DFdesc ptr[];        IN: pointer to space for the list of DDs
  234. **    int begin;        IN: starting DD number
  235. **    int num;        IN: number of entries
  236. ** RETURNS
  237. **    number of DDs returned in the list
  238. ** DESCRIPTION
  239. **    Fills in a list of all DDs in the file beginning with DD begin and
  240. **    including a maximum of num entries.  The number of DDs actually entered
  241. **    into the list is returned.
  242. ** GLOBAL VARIABLES
  243. ** COMMENTS, BUGS, ASSUMPTIONS
  244. ** EXAMPLES
  245. ** REVISION LOG
  246. */
  247. #ifdef PROTOTYPE
  248. int DFdescriptors(DF *dfile, DFdesc ptr[], int begin, int num)
  249. #else
  250.     int
  251. DFdescriptors(dfile, ptr, begin, num)
  252.     DF *dfile;
  253.     DFdesc ptr[];
  254.     int begin;
  255.     int num;
  256. #endif /* PROTOTYPE */
  257. {
  258.     int i, stat;
  259.     int32 aid;
  260.  
  261.     if (DFIcheck(dfile) != 0) {
  262.         DFerror = DFE_NOTOPEN;
  263.         return(-1);
  264.     }
  265.     else
  266.         DFerror = DFE_NONE;
  267.     
  268.     aid = Hstartread(DFid, DFTAG_WILDCARD, DFREF_WILDCARD);
  269.  
  270.     if (aid == FAIL) {
  271.         DFerror = HEvalue(1);
  272.         return(-1);
  273.     }
  274.     
  275.     for (i = 2; i <= begin; i++) {
  276.         stat = Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD, DF_CURRENT);
  277.         if (stat == FAIL) {
  278.             DFerror = HEvalue(1);
  279.             return(-1);
  280.         }
  281.     }
  282.     
  283.     Hinquire(aid, NULL, &ptr[0].tag, &ptr[0].ref, &ptr[0].length,
  284.          &ptr[0].offset, NULL, NULL, NULL);
  285.  
  286.     for (i = 1; i < num; i++) {
  287.         stat = Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD,  DF_CURRENT);
  288.         if (stat == FAIL)
  289.             return (i);
  290.         Hinquire(aid, NULL, &ptr[i].tag, &ptr[i].ref, &ptr[i].length,
  291.              &ptr[i].offset, NULL, NULL, NULL);
  292.     }
  293.     Hendaccess(aid);
  294.  
  295.     return(i);
  296. }
  297.  
  298.  
  299.  
  300. /*
  301. ** NAME
  302. **    DFnumber -- return number of occurrences of given tag in the HDF file
  303. ** USAGE
  304. **    DFnumber(dfile, tag)
  305. **    DF *dfile;        IN: pointer to open DF file
  306. **    uint16 tag;        IN: tag to count occurrences of
  307. ** RETURNS
  308. **    Number of occurrences on success, -1 on failure with DFerror set.
  309. ** DESCRIPTION
  310. **    Returns the number of occurrences of the specified tag in the HDF file.
  311. **    If tag is DFTAG_WILDCARD, all tags are counted.
  312. ** GLOBAL VARIABLES
  313. ** COMMENTS, BUGS, ASSUMPTIONS
  314. ** EXAMPLES
  315. ** REVISION LOG
  316. */
  317. #ifdef PROTOTYPE
  318. int DFnumber(DF *dfile, uint16 tag)
  319. #else
  320.     int
  321. DFnumber(dfile, tag)
  322.     DF *dfile;
  323.     uint16 tag;
  324. #endif /* PROTOTYPE */
  325. {
  326.     int32 aid;
  327.     int num, stat;
  328.  
  329.     if (DFIcheck(dfile) != 0) {
  330.         DFerror = DFE_NOTOPEN;
  331.         return(-1);
  332.     }
  333.     else
  334.         DFerror = DFE_NONE;
  335.     
  336.     aid = Hstartread(DFid, tag, DFREF_WILDCARD);
  337.     if (aid == FAIL)
  338.         return(0);
  339.     
  340.     num = 0;
  341.     for (stat = 0; stat == 0; num++)
  342.         stat = Hnextread(aid, tag, DFREF_WILDCARD, DF_CURRENT);
  343.     Hendaccess(aid);
  344.     return(num);
  345. }
  346.  
  347.  
  348. /*
  349. ** NAME
  350. **    DFsetfind -- set up parameters for a wildcard find
  351. ** USAGE
  352. **    int DFsetfind(dfile, tag, ref)
  353. **    DF *dfile;        IN: pointer to open DF file
  354. **    uint16 tag;        IN: tag of element to search for (0 is wild)
  355. **    uint16 ref;        IN: ref of element to search for (0 is wild)
  356. ** RETURNS
  357. **    0 on success, -1 on failure
  358. ** DESCRIPTION
  359. **    Sets up parameters for a wildcard find on a tag/ref pair.
  360. ** GLOBAL VARIABLES
  361. ** COMMENTS, BUGS, ASSUMPTIONS
  362. ** EXAMPLES
  363. ** REVISION LOG
  364. */
  365. #ifdef PROTOTYPE
  366. int DFsetfind(DF *dfile, uint16 tag, uint16 ref)
  367. #else
  368.     int
  369. DFsetfind(dfile, tag, ref)
  370.     DF *dfile;
  371.     uint16 tag;
  372.     uint16 ref;
  373. #endif /* PROTOTYPE */
  374. {
  375.     if (DFIcheck(dfile) != 0) {
  376.         DFerror = DFE_NOTOPEN;
  377.         return(-1);
  378.     }
  379.     else
  380.         DFerror = DFE_NONE;
  381.  
  382.     search_tag = tag;
  383.     search_ref = ref;
  384.  
  385.     search_stat = DFSRCH_NEW;
  386.  
  387.     return(0);
  388. }
  389.  
  390.  
  391. /*
  392. ** NAME
  393. **    DFfind -- perform wildcard searches
  394. ** USAGE
  395. **    int DFfind(dfile, ptr)
  396. **    DF *dfile;        IN: pointer to an open DF file
  397. **    DFdesc *ptr;        IN: pointer to put in DD when found
  398. ** RETURNS
  399. **    0 on success, -1 on failure
  400. ** DESCRIPTION
  401. **    If desired tag/ref is found, its DD is copied to *ptr.
  402. ** GLOBAL VARIABLES
  403. ** COMMENTS, BUGS, ASSUMPTIONS
  404. ** EXAMPLES
  405. ** REVISION LOG
  406. */
  407. #ifdef PROTOTYPE
  408. int DFfind(DF *dfile, DFdesc *ptr)
  409. #else
  410.     int
  411. DFfind(dfile, ptr)
  412.     DF *dfile;
  413.     DFdesc *ptr;
  414. #endif /* PROTOTYPE */
  415. {
  416.     int stat;
  417.  
  418.     if (DFIcheck(dfile) != 0) {
  419.         DFerror = DFE_NOTOPEN;
  420.         return(-1);
  421.     }
  422.     else
  423.         DFerror = DFE_NONE;
  424.  
  425.     if (search_stat == DFSRCH_NEW) {
  426.         search_aid = Hstartread(DFid, search_tag, search_ref);
  427.         search_stat = DFSRCH_OLD;
  428.         stat = 0;
  429.     } else {
  430.         stat = Hnextread(search_aid, search_tag, search_ref, DF_CURRENT);
  431.     }
  432.  
  433.     if ((search_aid == FAIL) || (stat == FAIL)) {
  434.         DFerror = DFE_NOMATCH;
  435.         ptr->tag = 0;
  436.         ptr->ref = 0;
  437.         return(-1);
  438.     }
  439.  
  440.     Hinquire(search_aid, NULL, &ptr->tag, &ptr->ref, &ptr->length, &ptr->offset,
  441.          NULL, NULL, NULL);
  442.  
  443.     return(0);
  444. }
  445.  
  446.  
  447. /*
  448. ** NAME
  449. **    DFaccess -- set up a read/write on a data element
  450. ** USAGE
  451. **    int DFaccess(dfile, tag, ref, access)
  452. **    DF *dfile;        IN: pointer to open HDF file
  453. **    uint16 tag;        IN: tag of element
  454. **    uint16 ref;        IN: ref number of element
  455. **    char *access;        IN: "r", "w", or "a" (read, write, append)
  456. ** RETURNS
  457. **    0 on success, -1 on failure
  458. ** DESCRIPTION
  459. **    Set up read or write access on data element.
  460. ** GLOBAL VARIABLES
  461. ** COMMENTS, BUGS, ASSUMPTIONS
  462. **    This function needs to call DFupdate and Hendaccess if there is already
  463. **    an active access element with a different tag/ref.
  464. **    Also, set up globals "acc_tag" and "acc_ref" to keep tabs on the data
  465. **    being referenced, and "in_mem" to keep track of whether the data for
  466. **    an element to be appended to has been read into memory.
  467. ** EXAMPLES
  468. ** REVISION LOG
  469. */
  470. #ifdef PROTOTYPE
  471. int DFaccess(DF *dfile, uint16 tag, uint16 ref, char *access)
  472. #else
  473.     int
  474. DFaccess(dfile, tag, ref, access)
  475.     DF *dfile;
  476.     uint16 tag;
  477.     uint16 ref;
  478.     char *access;
  479. #endif /* PROTOTYPE */
  480. {
  481.     int accmode;
  482.     /*
  483.     DFdle *ptr;
  484.     int dle_num, index, i;
  485.     */
  486.  
  487.     if (DFIcheck(dfile) != 0) {
  488.         DFerror = DFE_NOTOPEN;
  489.         return(-1);
  490.     }
  491.     else
  492.         DFerror = DFE_NONE;
  493.  
  494.     switch(*access) {
  495.     case 'r': accmode = DFACC_READ;
  496.           break;
  497.     case 'w': accmode = DFACC_WRITE;
  498.           if (((DFaccmode & DFACC_WRITE) == 0) &&
  499.               ((DFaccmode & DFACC_CREATE) == 0)) {
  500.               DFerror = DFE_BADACC;
  501.               return(-1);
  502.           }
  503.           break;
  504.     case 'a': accmode = DFACC_APPEND;
  505.           if (((DFaccmode & DFACC_WRITE) == 0) &&
  506.               ((DFaccmode & DFACC_CREATE) == 0)) {
  507.               DFerror = DFE_BADACC;
  508.               return(-1);
  509.           }
  510.           break;
  511.     default:  DFerror = DFE_BADACC;
  512.           return(-1);
  513.     }
  514.  
  515. /* test
  516.     if (((tag != acc_tag) || (ref != acc_ref)) || (accmode != DFelaccmode))
  517.         if (DFelstat == DFEL_RESIDENT) {
  518.         Hputelement(DFid, acc_tag, acc_ref, DFelement, DFelsize);
  519.         free(DFelement);
  520.         }
  521.     else
  522.         Hendaccess(DFaid);
  523. test */
  524.  
  525.     acc_tag = tag;
  526.     acc_ref = ref;
  527.     DFelaccmode = accmode;
  528.     DFelstat = DFEL_ABSENT;
  529.     DFelseekpos = 0;
  530.     DFelsize = 0;
  531.  
  532.     switch(*access) {
  533.     case 'r': 
  534.           DFelsize = Hlength(DFid, acc_tag, acc_ref);
  535.           if (DFelsize <= 0) {
  536.               DFIclearacc();
  537.                       DFerror = HEvalue(1);
  538.               return(-1);
  539.           }
  540.           /* test
  541.           DFaid = Hstartread(DFid, acc_tag, acc_ref);
  542.           if (DFaid != FAIL) {
  543.               Hinquire(DFaid, (int32*)NULL, (uint16*)NULL, (uint16*)NULL,
  544.                    &DFelsize, (int32*)NULL, (int32*)NULL,
  545.                    (int32*)NULL, (int32*)NULL);
  546.               inq_accid(DFaid, &dle_num, &index, &(dfile->up_access));
  547.               Hendaccess(DFaid);
  548.               ptr = dfile->list;
  549.               for (i=0; i<dle_num; i++)
  550.               ptr = ptr->next;
  551.               dfile->up_dd = &(ptr->dd[index]);
  552.           } else {
  553.               DFIclearacc();
  554.                       DFerror = HEvalue(1);
  555.               return(-1);
  556.           }
  557.           test */
  558.           break;
  559.     /* _maybe_ treat 'w' and 'a' in the same general 'a'-way */
  560.     case 'w':
  561.           DFelsize = Hlength(DFid, acc_tag, acc_ref);
  562.           if (DFelsize == FAIL) {
  563.               DFelsize = 0;
  564.           } else
  565.               DFelstat = DFEL_RESIDENT;
  566.           break;
  567.     case 'a': 
  568.           DFelsize = Hlength(DFid, acc_tag, acc_ref);
  569.           if (DFelsize == FAIL) {
  570.               DFIclearacc();
  571.                       DFerror = HEvalue(1);
  572.               return(-1);
  573.           }
  574.           DFelseekpos = DFelsize;
  575.           break;
  576.     }
  577.  
  578.     return(0);
  579. }
  580.  
  581.  
  582.  
  583. #ifdef PROTOTYPE
  584. PRIVATE int DFIclearacc(void)
  585. #else
  586.     PRIVATE int
  587. DFIclearacc()
  588. #endif /* PROTOTYPE */
  589. {
  590.     Hendaccess(DFaid);
  591.     DFaid = 0;
  592.     acc_tag = 0;
  593.     acc_ref = 0;
  594.     DFelsize = 0;
  595.     DFelseekpos = 0;
  596.     DFelstat = DFEL_ABSENT;
  597.     DFelement = NULL;
  598.  
  599.     return(0);
  600. }
  601.  
  602.  
  603. /*
  604. ** NAME
  605. **    DFstart -- set up a read/write on an access element
  606. ** USAGE
  607. **    int DFstart(dfile, tag, ref, access)
  608. **    DF *dfile;        IN: pointer to open  DF file
  609. **    uint16 tag;        IN: tag of element
  610. **    uint16 ref;        IN: ref number of element
  611. **    char *access;        IN: "r", "w", ro "a" (read, write, append)
  612. ** RETURNS
  613. **    0 on success, -1 on failure
  614. ** DESCRIPTION
  615. **    Set up a read or write access on data element.
  616. ** GLOBAL VARIABLES
  617. ** COMMENTS, BUGS, ASSUMPTIONS
  618. ** EXAMPLES
  619. ** REVISION LOG
  620. */
  621. #ifdef PROTOTYPE
  622. int DFstart(DF *dfile, uint16 tag, uint16 ref, char *access)
  623. #else
  624.     int
  625. DFstart(dfile, tag, ref, access)
  626.     DF *dfile;
  627.     uint16 tag;
  628.     uint16 ref;
  629.     char *access;
  630. #endif /* PROTOTYPE */
  631. {
  632.     return(DFaccess(dfile, tag, ref, access));
  633. }
  634.     
  635.  
  636.  
  637. /*
  638. ** NAME
  639. **    DFread -- read a portion of a data element
  640. ** USAGE
  641. **    int32 DFread(dfile, ptr, len)
  642. **    DF *dfile;        IN: pointer to open DF file
  643. **    char *ptr;        IN: pointer to space to read data into
  644. **    int32 len;        IN: number of bytes to read
  645. ** RETURNS
  646. **    number of bytes read on success, -1 on failure
  647. ** DESCRIPTION
  648. **    Read bytes from a DF file (part of element specified by DFaccess)
  649. ** GLOBAL VARIABLES
  650. ** COMMENTS, BUGS, ASSUMPTIONS
  651. **    Space for data is assumed to be pre-allocated.
  652. ** EXAMPLES
  653. ** REVISION LOG
  654. */
  655. #ifdef PROTOTYPE
  656. int32 DFread(DF *dfile, char *ptr, int32 len)
  657. #else
  658.     int32
  659. DFread(dfile, ptr, len)
  660.     DF *dfile;
  661.     char *ptr;
  662.     int32 len;
  663. #endif /* PROTOTYPE */
  664. {
  665.     int32 stat;
  666.  
  667.     if (DFIcheck(dfile) != 0) {
  668.         DFerror = DFE_NOTOPEN;
  669.         return(-1);
  670.     }
  671.     else
  672.         DFerror = DFE_NONE;
  673.  
  674.     DFaid = Hstartread(DFid, acc_tag, acc_ref);
  675.     stat = Hseek(DFaid, DFelseekpos, 0);
  676.     if (stat == FAIL) {
  677.         DFerror = HEvalue(1);
  678.         return(-1);
  679.     }
  680.  
  681.     stat = Hread(DFaid, len, (unsigned char *)ptr);
  682.     Hendaccess(DFaid);
  683.  
  684.     if (stat == FAIL) {
  685.         DFerror = HEvalue(1);
  686.         return(-1);
  687.     }
  688.     else {
  689.         DFelseekpos += stat;
  690.         return(stat);
  691.     }
  692. }
  693.  
  694.  
  695.  
  696. /*
  697. ** NAME
  698. **    DFseek -- seek a new position within a data element
  699. ** USAGE
  700. **    int32 DFseek(dfile, offset)
  701. **    DF *dfile;        IN: pointer to open DF file
  702. **    int32 offset;        IN: offset from beginning of element
  703. ** RETURNS
  704. **    offset of actual position seek'ed to from beginning of element
  705. ** DESCRIPTION
  706. **    Seek position within element specified by DFaccess.
  707. ** GLOBAL VARIABLES
  708. ** COMMENTS, BUGS, ASSUMPTIONS
  709. ** EXAMPLES
  710. ** REVISION LOG
  711. */
  712. #ifdef PROTOTYPE
  713. int32 DFseek(DF *dfile, int32 offset)
  714. #else
  715.     int32
  716. DFseek(dfile, offset)
  717.     DF *dfile;
  718.     int32 offset;
  719. #endif /* PROTOTYPE */
  720. {
  721.     int stat;
  722.  
  723.     if (DFIcheck(dfile) != 0) {
  724.         DFerror = DFE_NOTOPEN;
  725.         return(-1);
  726.     }
  727.     else
  728.         DFerror = DFE_NONE;
  729.     
  730.     /* assuming no blank space can be forced by seeking past end of element
  731.        and writing more data */
  732.     if (offset > DFelsize) {
  733.         DFerror = DFE_BADSEEK;
  734.         return(-1);
  735.     } else {
  736.         stat = Hseek(DFaid, offset, DF_START);
  737.         if (stat == FAIL) {
  738.             DFerror = HEvalue(1);
  739.             return(-1);
  740.         }
  741.         DFelseekpos = offset;
  742.     }
  743.  
  744.     return(0);
  745. }
  746.  
  747.  
  748. /*
  749. ** NAME
  750. **    DFwrite -- write a portion of a data element
  751. ** USAGE
  752. **    int32 DFwrite(dfile, ptr, len)
  753. **    DF *dfile;        IN: pointer to open DF file
  754. **    char *ptr;        IN: pointer to data to be written
  755. **    int32 len;        IN: number of bytes to be written
  756. ** RETURNS
  757. **    number of bytes written on success, -1 on failure
  758. ** DESCRIPTION
  759. **    Write bytes to DF file (part of element specified by DFaccess)
  760. ** GLOBAL VARIABLES
  761. ** COMMENTS, BUGS, ASSUMPTIONS
  762. **    This function should check the access mode in DFaccmode.  On write
  763. **    access, if(!in_mem) Hstartwrite, Hwrite, and set in_mem, otherwise just
  764. **    Hwrite.  On append access, if(!in_mem) Hstartread, Hinquire(oldsize),
  765. **    malloc(oldsize+writesize), Hread to malloc'd area, copy write request
  766. **    to end of malloc'd area, set in_mem, otherwise, realloc(area+writesize)
  767. **    copy write request to end of area.
  768. ** EXAMPLES
  769. ** REVISION LOG
  770. */
  771. #ifdef PROTOTYPE
  772. int32 DFwrite(DF *dfile, char *ptr, int32 len)
  773. #else
  774.     int32
  775. DFwrite(dfile, ptr, len)
  776.     DF *dfile;
  777.     char *ptr;
  778.     int32 len;
  779. #endif /* PROTOTYPE */
  780. {
  781.     int32 size, ret, newlen;
  782.  
  783.     if (DFIcheck(dfile) != 0) {
  784.         DFerror = DFE_NOTOPEN;
  785.         return(-1);
  786.     }
  787.     if ((DFelaccmode != DFACC_WRITE) && (DFelaccmode != DFACC_APPEND)) {
  788.         DFerror = DFE_BADACC;
  789.         return(-1);
  790.     }
  791.     else
  792.         DFerror = DFE_NONE;
  793.  
  794.     size = DFelseekpos + len;
  795.     if (DFelaccmode == DFACC_WRITE) {
  796.         if (DFelstat == DFEL_ABSENT) {
  797.             Hendaccess(DFaid);
  798.             DFaid = Hstartwrite(DFid, acc_tag, acc_ref, len);
  799.             Hseek(DFaid, DFelseekpos, DF_START);
  800.             ret = Hwrite(DFaid, len, (unsigned char *)ptr);
  801.         } else {
  802.             if (size <= DFelsize) {
  803.                 Hendaccess(DFaid);
  804.                 DFaid = Hstartwrite(DFid, acc_tag, acc_ref, len);
  805.                 Hseek(DFaid, DFelseekpos, DF_START);
  806.                 ret = Hwrite(DFaid, len, (unsigned char *)ptr);
  807.             } else {
  808.                 DFerror = DFE_NOTENOUGH;
  809.                 return(-1);
  810.             }
  811.         }
  812.     } else {
  813.         newlen = size - Hlength(DFid, acc_tag, acc_ref);
  814.         Hendaccess(DFaid);
  815.         DFaid = HLcreate(DFid, acc_tag, acc_ref, newlen, (int32)4);
  816.         Hseek(DFaid, DFelseekpos, DF_START);
  817.         ret = Hwrite(DFaid, len, (unsigned char *)ptr);
  818.     }
  819.  
  820.     Hendaccess(DFaid);
  821.     DFelseekpos += len;
  822.     DFelsize = size;
  823.     DFelstat = DFEL_RESIDENT;
  824.  
  825.     return(ret);
  826. }
  827.  
  828.  
  829. /*
  830. ** NAME
  831. **    DFupdate -- write out updated DDs to HDF file
  832. ** USAGE
  833. **    int DFupdate(dfile)
  834. **    DF *dfile;        IN: pointer to open DF file
  835. ** RETURNS
  836. **    0 on success, -1 on failure with DFerror set.
  837. ** DESCRIPTION
  838. **    This function only checks for valid input and returns.  It is included
  839. **    solely for compatibility with older programs.
  840. ** GLOBAL VARIABLES
  841. ** COMMENTS, BUGS, ASSUMPTIONS
  842. **    This function does nothing but check for valid input.
  843. **    However, this function should check to see if an appended-to data
  844. **    element is in memory and, if it is, write it out.
  845. ** EXAMPLES
  846. ** REVISION LOG
  847. */
  848. #ifdef PROTOTYPE
  849. int DFupdate(DF *dfile)
  850. #else
  851.     int
  852. DFupdate(dfile)
  853.     DF *dfile;
  854. #endif /* PROTOTYPE */
  855. {
  856.     if (DFIcheck(dfile) != 0) {
  857.         DFerror = DFE_NOTOPEN;
  858.         return(-1);
  859.     }
  860.     else
  861.         DFerror = DFE_NONE;
  862.  
  863.     /* test
  864.     if (DFelstat == DFEL_RESIDENT) {
  865.     Hputelement(DFid, acc_tag, acc_ref, DFelement, DFelsize);
  866.     free(DFelement);
  867.     DFIclearacc();
  868.     }
  869.     test */
  870.  
  871.     return(0);
  872. }
  873.  
  874.  
  875. /*
  876. ** NAME
  877. **    DFstat -- provide status information about HDF file
  878. ** USAGE
  879. **    int DFstat(dfile, dfinfo)
  880. **    DF *dfile;        IN: pointer to open DF file
  881. **    struct DFdata *dfinfo;    IN: pointer to space for info
  882. ** RETURNS
  883. **    0 on success, -1 on failure
  884. ** DESCRIPTION
  885. **    Fill dfinfo with status information about the HDF file.
  886. ** GLOBAL VARIABLES
  887. ** COMMENTS, BUGS, ASSUMPTIONS
  888. **    Currently, only the HDF version number is returned in dfinfo.
  889. **    Actually, nothing happens here now.
  890. ** EXAMPLES
  891. ** REVISION LOG
  892. */
  893. #ifdef PROTOTYPE
  894. int DFstat(DF *dfile, DFdata *dfinfo)
  895. #else
  896.     int
  897. DFstat(dfile, dfinfo)
  898.     DF *dfile;
  899.     DFdata *dfinfo;
  900. #endif /* PROTOTYPE */
  901. {
  902.     if (DFIcheck(dfile) != 0) {
  903.         DFerror = DFE_NOTOPEN;
  904.         return(-1);
  905.     }
  906.     else
  907.         DFerror = DFE_NONE;
  908.  
  909.     dfinfo = dfinfo;
  910.  
  911.     return(0);
  912. }
  913.  
  914.  
  915.  
  916.  
  917. /*
  918. ** NAME
  919. **    DFgetelement -- read an entire data element
  920. ** USAGE
  921. **  int32 DFgetelement(dfile, tag, ref, ptr)
  922. **    DF *dfile;        IN: pointer to open DF file
  923. **    uint16 tag;        IN: tag of element
  924. **    uint16 ref;        IN: ref number of element
  925. **    char *ptr;        IN: pointer to space for data element
  926. ** RETURNS
  927. **    number of bytes read on success, -1 on failure
  928. ** DESCRIPTION
  929. **    Reads in a data element from an HDF file.
  930. ** GLOBAL VARIABLES
  931. ** COMMENTS, BUGS, ASSUMPTIONS
  932. **    Currently, this function returns 0 on success, not #bytes read.
  933. ** EXAMPLES
  934. ** REVISION LOG
  935. */
  936. #ifdef PROTOTYPE
  937. int32 DFgetelement(DF *dfile, uint16 tag, uint16 ref, char *ptr)
  938. #else
  939. int32 DFgetelement(dfile, tag, ref, ptr)
  940.     DF *dfile;
  941.     uint16 tag;
  942.     uint16 ref;
  943.     char *ptr;
  944. #endif /* PROTOTYPE */
  945. {
  946.     if (DFIcheck(dfile) != 0) {
  947.         DFerror = DFE_NOTOPEN;
  948.         return(-1);
  949.     }
  950.     else
  951.         DFerror = DFE_NONE;
  952.  
  953.     /* test
  954.     if (DFelstat == DFEL_RESIDENT) {
  955.     Hputelement(DFid, acc_tag, acc_ref, DFelement, DFelsize);
  956.     free(DFelement);
  957.     DFIclearacc();
  958.     }
  959.     test */
  960.  
  961.     if (Hgetelement(DFid, tag, ref, (unsigned char *)ptr) == -1) {
  962.         DFerror = HEvalue(1);
  963.         return(-1);
  964.     }
  965.     else
  966.     return(Hlength(DFid, tag, ref));
  967. }
  968.  
  969.  
  970. /*
  971. ** NAME
  972. **    DFputelement -- write an entire data element
  973. ** USAGE
  974. **    int DFputelement(dfile, tag, ref, ptr, len)
  975. **    DF *dfile;        IN: pointer to open DF file
  976. **    uint16 tag;        IN: tag of data element
  977. **    uint16 ref;        IN: ref number of data element
  978. **    char *ptr;        IN: pointer to data element
  979. **    int32 len;        IN: length of data element
  980. ** RETURNS
  981. **    Number of bytes written on success, -1 on failure
  982. ** DESCRIPTION
  983. **    Write an entire data element to HDF file.
  984. ** GLOBAL VARIABLES
  985. ** COMMENTS, BUGS, ASSUMPTIONS
  986. ** EXAMPLES
  987. ** REVISION LOG
  988. */
  989. #ifdef PROTOTYPE
  990. int32 DFputelement(DF *dfile, uint16 tag, uint16 ref, char *ptr, int32 len)
  991. #else
  992.     int32
  993. DFputelement(dfile, tag, ref, ptr, len)
  994.     DF *dfile;
  995.     uint16 tag;
  996.     uint16 ref;
  997.     char *ptr;
  998.     int32 len;
  999. #endif /* PROTOTYPE */
  1000. {
  1001.     if (DFIcheck(dfile) != 0) {
  1002.         DFerror = DFE_NOTOPEN;
  1003.         return(-1);
  1004.     }
  1005.     else
  1006.         DFerror = DFE_NONE;
  1007.  
  1008.     /* test
  1009.     if (DFelstat == DFEL_RESIDENT) {
  1010.     Hputelement(DFid, acc_tag, acc_ref, DFelement, DFelsize);
  1011.     free(DFelement);
  1012.     DFIclearacc();
  1013.     }
  1014.     test */
  1015.  
  1016.     if (Hputelement(DFid, tag, ref, (unsigned char *)ptr, len) == FAIL) {
  1017.         DFerror = HEvalue(1);
  1018.         return(-1);
  1019.     }
  1020.     else
  1021.         return(Hlength(DFid, tag, ref));
  1022. }
  1023.  
  1024.  
  1025. /*
  1026. ** NAME
  1027. **    DFdup -- create an additional descriptor for a data element
  1028. ** USAGE
  1029. **    int DFdup(dfile, itag, iref, otag, oref)
  1030. **    DF *dfile;        IN: pointer to open DF file
  1031. **    uint16 itag;        IN: new tag of data element
  1032. **    uint16 iref;        IN: new ref number of data element
  1033. **    uint16 otag;        IN: current tag of data element
  1034. **    uint16 oref;        IN: current ref number of data element
  1035. ** RETURNS
  1036. **    0 on success, -1 on failure
  1037. ** DESCRIPTION
  1038. **    Add a new tag/ref for existing data.
  1039. ** GLOBAL VARIABLES
  1040. ** COMMENTS, BUGS, ASSUMPTIONS
  1041. ** EXAMPLES
  1042. ** REVISION LOG
  1043. */
  1044. #ifdef PROTOTYPE
  1045. int DFdup(DF *dfile, uint16 itag, uint16 iref, uint16 otag, uint16 oref)
  1046. #else
  1047.     int
  1048. DFdup(dfile, itag, iref, otag, oref)
  1049.     DF *dfile;
  1050.     uint16 itag;
  1051.     uint16 iref;
  1052.     uint16 otag;
  1053.     uint16 oref;
  1054. #endif /* PROTOTYPE */
  1055. {
  1056.     if (DFIcheck(dfile) != 0) {
  1057.         DFerror = DFE_NOTOPEN;
  1058.         return(-1);
  1059.     }
  1060.     else
  1061.         DFerror = DFE_NONE;
  1062.  
  1063.     if (Hdupdd(DFid, itag, iref, otag, oref) != 0) {
  1064.         DFerror = HEvalue(1);
  1065.         return(-1);
  1066.     }
  1067.     else
  1068.         return(0);
  1069. }
  1070.  
  1071.  
  1072. /*
  1073. ** NAME
  1074. **    DFdel -- delete a data element
  1075. ** USAGE
  1076. **    int DFdel(dfile, tag, ref)
  1077. **    DF *dfile;        IN: pointer to open DF file
  1078. **    uint16 tag;        IN: tag of element
  1079. **    uint16 ref;        IN: ref number of element
  1080. ** RETURNS
  1081. **    0 on success, -1 on failure
  1082. ** DESCRIPTION
  1083. **    Delete a data element from HDF file.
  1084. ** GLOBAL VARIABLES
  1085. ** COMMENTS, BUGS, ASSUMPTIONS
  1086. **    The data element is not actually deleted; it simply loses its DD.
  1087. ** EXAMPLES
  1088. ** REVISION LOG
  1089. */
  1090. #ifdef PROTOTYPE
  1091. int DFdel(DF *dfile, uint16 tag, uint16 ref)
  1092. #else
  1093.     int
  1094. DFdel(dfile, tag, ref)
  1095.     DF *dfile;
  1096.     uint16 tag;
  1097.     uint16 ref;
  1098. #endif /* PROTOTYPE */
  1099. {
  1100.     if (DFIcheck(dfile) != 0) {
  1101.         DFerror = DFE_NOTOPEN;
  1102.         return(-1);
  1103.     }
  1104.     else
  1105.         DFerror = DFE_NONE;
  1106.  
  1107.     if (Hdeldd(DFid, tag, ref) != 0) {
  1108.         DFerror = HEvalue(1);
  1109.         return(-1);
  1110.     }
  1111.     else
  1112.         return(0);
  1113. }
  1114.  
  1115.  
  1116. /*
  1117. ** NAME
  1118. **    DFnewref -- get an unused reference number
  1119. ** USAGE
  1120. **    uint16 DFnewref(dfile)
  1121. **    DF *dfile;        IN: pointer to open DF file
  1122. ** RETURNS
  1123. **    unused reference number, or 0 if no reference numbers are free
  1124. ** DESCRIPTION
  1125. **    Get an unused reference number.
  1126. ** GLOBAL VARIABLES
  1127. ** COMMENTS, BUGS, ASSUMPTIONS
  1128. ** EXAMPLES
  1129. ** REVISION LOG
  1130. */
  1131. #ifdef PROTOTYPE
  1132. uint16 DFnewref(DF *dfile)
  1133. #else
  1134.     uint16
  1135. DFnewref(dfile)
  1136.     DF *dfile;
  1137. #endif /* PROTOTYPE */
  1138. {
  1139.     uint16 stat;
  1140.  
  1141.     if (DFIcheck(dfile) != 0) {
  1142.         DFerror = DFE_NOTOPEN;
  1143.         return(0);
  1144.     }
  1145.     else
  1146.         DFerror = DFE_NONE;
  1147.  
  1148.     stat = Hnewref(DFid);
  1149.     if (stat == 0xffff) {
  1150.         DFerror = HEvalue(1);
  1151.         return(0);
  1152.     }
  1153.  
  1154.     return(stat);
  1155. }
  1156.  
  1157.  
  1158. /*
  1159. ** NAME
  1160. **    DFishdf -- is this an HDF file?
  1161. ** USAGE
  1162. **    int DFishdf(filename)
  1163. **    char *filename;        IN: name of file to check
  1164. ** RETURNS
  1165. **    0 if it is an HDF file, -1 if it is not.
  1166. ** DESCRIPTION
  1167. **    Determine whether file is an HDF file.
  1168. ** GLOBAL VARIABLES
  1169. ** COMMENTS, BUGS, ASSUMPTIONS
  1170. ** EXAMPLES
  1171. ** REVISION LOG
  1172. */
  1173. #ifdef PROTOTYPE
  1174. int DFishdf(char *filename)
  1175. #else
  1176.     int
  1177. DFishdf(filename)
  1178.     char *filename;
  1179. #endif /* PROTOTYPE */
  1180. {
  1181.     int32 dummy;
  1182.  
  1183.     DFerror = DFE_NONE;
  1184.  
  1185.     dummy = Hopen(filename, DFACC_READ, 0);
  1186.     if (dummy == -1) {
  1187.         DFerror = HEvalue(1);
  1188.         return(-1);
  1189.     }
  1190.     else {
  1191.         Hclose(dummy);
  1192.         return(0);
  1193.     }
  1194. }
  1195.  
  1196.  
  1197. /*
  1198. ** NAME
  1199. **    DFerrno -- return value of DFerror
  1200. ** USAGE
  1201. **    int DFerrno()
  1202. ** RETURNS
  1203. **    Value of DFerror.
  1204. ** DESCRIPTION
  1205. **    Return value of DFerror.
  1206. ** GLOBAL VARIABLES
  1207. ** COMMENTS, BUGS, ASSUMPTIONS
  1208. ** EXAMPLES
  1209. ** REVISION LOG
  1210. */
  1211. #ifdef PROTOTYPE
  1212. int DFerrno(void)
  1213. #else
  1214.     int
  1215. DFerrno()
  1216. #endif /* PROTOTYPE */
  1217. {
  1218.     return(DFerror);
  1219. }
  1220.  
  1221. #ifdef PERM_OUT
  1222. /*-----------------------------------------------------------------------------
  1223.  * Name:    DFIseedDDs
  1224.  * Purpose: read DDs in file into memory
  1225.  * Inputs:  dfile: pointer to open DF file
  1226.  * Returns: 0 on success, -1 on failure with DFerror set
  1227.  * Users:   HDF systems programmers, DFopen
  1228.  *---------------------------------------------------------------------------*/
  1229.  
  1230. int DFIseedDDs(dfile)
  1231. DF *dfile;
  1232. {
  1233.     DFdle *list;
  1234.     DFddh ddh;
  1235.     int i,n;                        /* n = no. of DDs in block */
  1236.  
  1237.     DFerror = DFE_NONE;
  1238.  
  1239.     if (dfile->list) {
  1240.         DFerror = DFE_SEEDTWICE;    /* ### NOTE: Internal error! */
  1241.         return(-1);
  1242.     }
  1243.  
  1244.     dfile->list= (DFdle *) DFIgetspace(sizeof(DFdle));
  1245.     /* includes one DD - unused */
  1246.     CKMALLOC( dfile->list, -1);
  1247.  
  1248.     list=dfile->list;
  1249.     list->next=NULL;                /* No other lists (yet) */
  1250.     list->ddh.next= (int32)4L;      /* next is at 4 in file */
  1251.     list->ddh.dds= -1;              /* flag so this is not written */
  1252.  
  1253.     DFmaxref = 0;                   /* largest ref found till now is 0 */
  1254.  
  1255.     while (list->ddh.next) {        /* while more headers to read */
  1256.         CKSEEK( dfile->file, list->ddh.next, 0, -1);
  1257.  
  1258.                             /* read headers */
  1259. #ifdef DF_STRUCTOK
  1260.         CKREAD( &ddh, sizeof(DFddh), 1, dfile->file, -1);
  1261. #else /*DF_STRUCTOK*/
  1262.         {
  1263.             register  char *p;
  1264.             p = DFtbuf;
  1265.             CKREAD( DFtbuf, 6, 1, dfile->file, -1);     /* 6 = size of header */
  1266.             INT16READ( p, ddh.dds);
  1267.             INT32READ( p, ddh.next);
  1268.         }
  1269. #endif /*DF_STRUCTOK*/
  1270.         n   =ddh.dds;
  1271.  
  1272.         /* read in DDs */
  1273.         list->next= (DFdle *)
  1274.             DFIgetspace((unsigned)
  1275.                         (sizeof(DFdle)+ (n-1)* sizeof(DFdd)));
  1276.                                 /* note space for 1 DD included in DLE */
  1277.         CKMALLOC( list->next, -1);
  1278.         list=list->next;
  1279.         list->next=NULL;
  1280.  
  1281.         DFmovmem((char*)&ddh, (char*)&(list->ddh),
  1282.                  sizeof(DFddh) ); /* Copy ddh */
  1283.  
  1284.         if (n) {
  1285. #ifdef DF_STRUCTOK
  1286.             CKREAD( &list->dd[0], sizeof(DFdd), n, dfile->file, -1);
  1287.             /* load DD's */
  1288. #else /*DF_STRUCTOK*/
  1289.             {
  1290.                 register  char *p;
  1291.                 p = DFtbuf;
  1292.                 CKREAD( DFtbuf, n*12, 1, dfile->file, -1);  /* 12=size of DD */
  1293.                 for (i=0; i<n; i++) {
  1294.                     UINT16READ( p, list->dd[i].tag);
  1295.                     UINT16READ( p, list->dd[i].ref);
  1296.                     INT32READ( p, list->dd[i].offset);
  1297.                     INT32READ( p, list->dd[i].length);
  1298.                 }
  1299.             }
  1300. #endif /*DF_STRUCTOK*/
  1301.         }
  1302.                 /* Remember highest ref found - ignore MTs */
  1303.         for (i=0; i<n; i++)
  1304.             if ((list->dd[i].ref > DFmaxref) && (list->dd[i].tag != DFTAG_MT))
  1305.                                      DFmaxref = list->dd[i].ref;
  1306.     }
  1307.     return(0);
  1308. }
  1309. #endif /* PERM_OUT */
  1310.  
  1311. /*-----------------------------------------------------------------------------
  1312.  * Name:    DFIcheck
  1313.  * Purpose: check if dfile argument represents a valid DF file
  1314.  * Inputs:  dfile: pointer to open DF file
  1315.  * Returns: 0 on success, -1 on failure with DFerror set
  1316.  * Users:   HDF systems programmers, several routines in this file
  1317.  *---------------------------------------------------------------------------*/
  1318.  
  1319. #ifdef PROTOTYPE
  1320. PRIVATE int DFIcheck(DF *dfile)
  1321. #else
  1322. PRIVATE int DFIcheck( dfile)
  1323. DF *dfile;
  1324. #endif  /* PROTOTYPE */
  1325. {
  1326.     DFerror = DFE_NONE;
  1327.  
  1328.     if ((dfile != (DF *)&DFid) || (DFid == 0)) {
  1329.         DFerror = DFE_DFNULL;
  1330.         return(-1);
  1331.     }
  1332.  
  1333.     if ((DFaccmode & DFACC_ALL) != DFaccmode) {
  1334.         DFerror = DFE_BADACC;
  1335.         return(-1);
  1336.     }
  1337.     else
  1338.         return(0);
  1339.  
  1340.     /* test
  1341.     if (!dfile) {
  1342.         DFerror = DFE_DFNULL;
  1343.         return(-1);
  1344.     }
  1345.  
  1346.     if ((dfile->access & DFACC_ALL) != dfile->access)
  1347.         DFerror = DFE_BADACC;
  1348.  
  1349.     if ((dfile->type >1) || (dfile->type <-1))
  1350.         DFerror = DFE_ILLTYPE;
  1351.  
  1352.     if (!dfile->list)
  1353.         DFerror= DFE_BADDDLIST;
  1354.  
  1355.     if (DFerror)
  1356.         return(-1);
  1357.     else
  1358.         return(0);
  1359.     test */
  1360.  
  1361. }
  1362.  
  1363. #ifdef PERM_OUT
  1364. /*-----------------------------------------------------------------------------
  1365.  * Name:    DFIfind
  1366.  * Purpose: perform wildcard searches
  1367.  * Inputs:  dfile: pointer to open DF file
  1368.  *          tag, ref: tag, ref (possibly wildcard) being searched for
  1369.  *          isfirst: 1 if first call to DFIfind for this tag/ref, else 0
  1370.  *          ltag, lref: last tag and ref returned for this search,
  1371.  *              don't care if isfirst set
  1372.  *          cDLEp, cddp: pointers to DLE and DD number to return matched DD in
  1373.  * Returns: 0 on success, -1 on failure
  1374.  *          if success, cDLEp and cddp are set to point to matched DD
  1375.  * Users:   HDF system programmers, DFfind, HDF utilities, many routines
  1376.  * Remarks: The searching algorithm is a little complex.  It returns entries
  1377.  *          in the sorting order of refs, then tags.  Even after a candidate
  1378.  *          is found, searching continues till best candidate found.  Best way
  1379.  *          to check if conditions: work it out independently for yourself!
  1380.  *---------------------------------------------------------------------------*/
  1381.  
  1382. int DFIfind( dfile, tag, ref, isfirst, ltag, lref, cDLEp, cddp)
  1383. DF *dfile;
  1384. DFdle **cDLEp;
  1385. int *cddp;
  1386. int isfirst;                            /* 1 if no prev search, 0 otherwise */
  1387. uint16 tag, ref, ltag, lref;
  1388. {
  1389.     DFdle *DLEp;
  1390.     int i, found=0;
  1391.     uint16 ctag=0, cref=0, wtag,wref; /* ctag, cref: tag, ref found so far */
  1392.                                       /* wtag, wref: tag, ref being checked */
  1393.  
  1394.  
  1395.     if (isfirst) {
  1396.         search_tag = tag;
  1397.         search_ref = ref;
  1398.     }
  1399.  
  1400.     DLEp=dfile->list;               /* start of DLE list */
  1401.  
  1402.     if (tag && ref) {               /* No wildcards */
  1403.         if (isfirst) {              /* if not already found */
  1404.             while (DLEp) {          /* go through list */
  1405.                 for (i=0; i<DLEp->ddh.dds; i++) {       /* for all DDs */
  1406.                     if (DLEp->dd[i].tag==tag &&
  1407.                             DLEp->dd[i].ref==ref)
  1408.                         {*cDLEp=DLEp; *cddp=i; return(0);}
  1409.                     }
  1410.                 DLEp=DLEp->next;
  1411.                 }
  1412.             }
  1413.         }
  1414.     else if (tag && !ref)           /* wildcard ref */
  1415.         while (DLEp) {
  1416.             for (i=0; i<DLEp->ddh.dds; i++) {
  1417.                 wtag=DLEp->dd[i].tag;
  1418.                 wref=DLEp->dd[i].ref;
  1419.         /* condition = tag match, better than found so far (if any),
  1420.             follows what was returned last time (if any) */
  1421.                 if ( (wtag==tag) && (!found || (wref<cref)) &&
  1422.                     (isfirst || (wref>lref)))
  1423.                     { ctag=wtag; cref=wref; *cDLEp=DLEp; *cddp=i;found=1;}
  1424.                 }
  1425.             DLEp=DLEp->next;
  1426.             }
  1427.     else if (!tag && ref)           /* wildcard tag */
  1428.         while (DLEp) {
  1429.             for (i=0; i<DLEp->ddh.dds; i++) {
  1430.                 wtag=DLEp->dd[i].tag;
  1431.                 wref=DLEp->dd[i].ref;
  1432.                 if ((wref==ref) && (isfirst || (wtag>ltag)) &&
  1433.                     (!found || (wtag<ctag)) )
  1434.                     { ctag=wtag; cref=wref; *cDLEp=DLEp; *cddp=i;found=1;}
  1435.                 }
  1436.             DLEp=DLEp->next;
  1437.             }
  1438.     else if (!tag && !ref)          /* wildcard tag & ref */
  1439.         while (DLEp) {
  1440.             for (i=0; i<DLEp->ddh.dds; i++) {
  1441.                 wtag=DLEp->dd[i].tag;
  1442.                 wref=DLEp->dd[i].ref;
  1443.                 if ((isfirst || (wref>lref) || (wref==lref && wtag>ltag)) &&
  1444.                     (!found || (wref<cref) || (wref==cref && wtag<ctag)) &&
  1445.                     (wtag!=DFTAG_NULL))         /* empty DDs are invisible */
  1446.                     { ctag=wtag; cref=wref; *cDLEp=DLEp; *cddp=i;found=1;}
  1447.                 }
  1448.             DLEp=DLEp->next;
  1449.             }
  1450.     return(found-1);            /* 0 or -1 */
  1451. }
  1452.  
  1453.  
  1454. /*-----------------------------------------------------------------------------
  1455.  * Name:    DFIemptyDD
  1456.  * Purpose: find an empty DD to use, or create a block of DDs if necessary
  1457.  * Inputs:  dfile: pointer to open DF file
  1458.  * Returns: pointer to an empty DD
  1459.  * Invokes: DFIfind
  1460.  * Users:   HDF system programmers, DFaccess, DFdup
  1461.  *---------------------------------------------------------------------------*/
  1462.  
  1463.  
  1464. DFdd *DFIemptyDD(dfile)
  1465. DF *dfile;
  1466. {
  1467.     DFdle *cDLEp;
  1468.     int cdd;
  1469.  
  1470.     if (!DFIfind( dfile, DFTAG_NULL, DFREF_WILDCARD, 1, 0, 0, &cDLEp, &cdd))
  1471.         return(&(cDLEp->dd[cdd]));      /* there is an empty DD */
  1472.  
  1473.     else {          /* add new DDH block */
  1474.         int32 fpos;
  1475.         DFdle *p, *dle;
  1476.         DFddh ddh;
  1477.         DFdd dd;
  1478.         int j;
  1479.         char MYtbuf[12];                /* My own tbuf so that the content
  1480.                                            of DFtbuf will be preserved */
  1481.  
  1482.         CKSEEKEND( dfile->file, (long) 0, 2, NULL); /* go to end of df */
  1483.         fpos= (int32) DF_TELL(dfile->file);
  1484.         ddh.dds= dfile->defdds;             /* Initialize ddh */
  1485.         ddh.next= 0;
  1486.         dd.tag=DFTAG_NULL;                  /* and all DD's */
  1487.         dd.ref=0;
  1488. #ifdef DF_STRUCTOK
  1489.         CKWRITE( &ddh, sizeof(DFddh), 1, dfile->file, NULL);
  1490. #else /*DF_STRUCTOK*/
  1491.         {
  1492.             register  char *p;
  1493.             p = MYtbuf;
  1494.             INT16WRITE( p, ddh.dds);
  1495.             INT32WRITE( p, ddh.next);
  1496.             CKWRITE( MYtbuf, 6, 1, dfile->file, NULL);  /* 6 = size of header */
  1497.         }
  1498. #endif /*DF_STRUCTOK*/
  1499.         for (j=0; j<ddh.dds; j++) {
  1500. #ifdef DF_STRUCTOK
  1501.             CKWRITE( &dd, sizeof(DFdd),1, dfile->file, NULL);
  1502. #else /*DF_STRUCTOK*/
  1503.             {
  1504.                 register  char *p;
  1505.                 p = MYtbuf;
  1506.                 UINT16WRITE( p, dd.tag);
  1507.                 UINT16WRITE( p, dd.tag);
  1508.                 INT32WRITE( p, dd.offset);
  1509.                 INT32WRITE( p, dd.length);
  1510.                 CKWRITE( MYtbuf, 12, 1, dfile->file, NULL); /* 12=size of dd */
  1511.             }
  1512. #endif /*DF_STRUCTOK*/
  1513.         }
  1514.  
  1515.         p=dfile->list;                      /* find end of list */
  1516.         while (p->next) p= p->next;
  1517.  
  1518.         p->ddh.next=fpos;                   /* new dd goes at end of file */
  1519.         dle=(DFdle *)
  1520.             DFIgetspace((unsigned)
  1521.                         (sizeof(DFdle)+(ddh.dds-1)*sizeof(DFdd)));
  1522.                             /* one dd included in dle */
  1523.         CKMALLOC(dle, NULL);
  1524.         p->next=dle;                        /* insert dle at end of list */
  1525.         dle->next=NULL;
  1526.         DFmovmem((char*)&ddh, (char*)&dle->ddh,sizeof(DFddh));
  1527.         for (j=0; j<ddh.dds; j++)
  1528.             DFmovmem( (char*)&dd, (char*)&dle->dd[j], sizeof(DFdd));
  1529.         return(&(dle->dd[0]));
  1530.     }
  1531. #ifdef PC
  1532.     return(NULL);           /* dummy, for return value checking */
  1533. #endif /*PC*/
  1534. }
  1535.  
  1536.  
  1537. /* Simplified version without the overhead.  This is useful if you */
  1538.  /* know that the args are okay, and if you need to read many time */
  1539.  /* (like in a loop in DFSDIgetslice()) */
  1540. int32 DFIread( dfile, ptr, len)
  1541. DF *dfile;
  1542. char *ptr;
  1543. int32 len;
  1544. {
  1545.     int32 maxlen;
  1546. #ifdef VMS
  1547.     int32 totalread;
  1548.     int32 readsize;
  1549. #endif /*VMS*/
  1550.     maxlen = dfile->up_dd->length -
  1551.                 ((int32) DF_TELL(dfile->file) - dfile->up_dd->offset);
  1552.     if (len>maxlen) len = maxlen;
  1553.     if (len<0) {            /* will also catch reads from beyond element */
  1554.         DFerror = DFE_BADLEN;
  1555.         return(-1);
  1556.     }
  1557.  
  1558. #ifdef VMS
  1559.     totalread = 0;
  1560.     while (totalread<len) {
  1561.         readsize = len - totalread;
  1562.         if (readsize>512) readsize = 512;
  1563.         CKREAD( &ptr[totalread], (int)readsize, 1, dfile->file, -1);
  1564.         totalread += readsize;
  1565.     }
  1566.  
  1567. #else /*VMS*/
  1568.     if (len) {      /* NOTE: cast to (int) will limit to 64K on 16 bit m/cs */
  1569.         CKREAD( ptr, (int) len, 1, dfile->file, -1);
  1570.     }
  1571. #endif /*VMS*/
  1572.  
  1573.     return(len);
  1574. }
  1575.  
  1576. /* Simplified version without the overhead.  This is useful if you */
  1577.  /* know that the args are okay, and if you need to seek many time */
  1578.  /* (like in a loop in DFSDIgetslice()) */
  1579. int32 DFIseek( dfile, offset)
  1580. DF *dfile;
  1581. int32 offset;
  1582. {
  1583.     CKSEEK( dfile->file, (long) dfile->up_dd->offset + offset, 0, -1);
  1584.     return(offset);
  1585. }
  1586. #endif /* PERM_OUT */
  1587.  
  1588. /*-----------------------------------------------------------------------------
  1589.  * Name:    DFIerr
  1590.  * Purpose: Close a file and return on error. save DFerror
  1591.  * Inputs:  dfile: pointer to HDF file to close
  1592.  * Returns: -1
  1593.  * Users:   HDF systems programmers, for error handling
  1594.  * Invokes: DFclose
  1595.  * Remarks: Used to centralize some error handling
  1596.  *---------------------------------------------------------------------------*/
  1597.  
  1598. #ifdef PROTOTYPE
  1599. int DFIerr(DF *dfile)
  1600. #else
  1601. int DFIerr(dfile)
  1602. DF *dfile;
  1603. #endif  /* PROTOTYPE */
  1604. {
  1605.     int saveerror;
  1606.  
  1607.     saveerror = DFerror;
  1608.     if (dfile!=NULL) (void) DFclose(dfile);
  1609.     DFerror = saveerror;
  1610.     return(-1);
  1611. }
  1612.  
  1613.  
  1614. /*-----------------------------------------------------------------------------
  1615.  * The following functions are stubs for the old routines from "dfkit.c".
  1616.  *---------------------------------------------------------------------------*/
  1617.  
  1618. #ifndef IBM6000
  1619. #include <ctype.h>
  1620. #endif
  1621.  
  1622. #ifdef PC
  1623. #ifdef WIN3
  1624. int32 DFIspaceleft(void)
  1625. {
  1626. /* return the largest amount of memory Windows can give us */
  1627.    return(GlobalCompact(0));
  1628. }
  1629. #else /* WIN3 */
  1630. int32 DFIspaceleft(void)
  1631. {
  1632.     return(HDspaceleft());
  1633. }
  1634. #endif /* WIN3 */
  1635. #endif /* PC */
  1636.  
  1637.  
  1638. #if defined PROTOTYPE
  1639. void *DFIgetspace(uint32 qty)
  1640. #else
  1641. void *DFIgetspace(qty)
  1642. uint32 qty;
  1643. #endif /* PROTOTYPE */
  1644. {
  1645.     void *ret;
  1646.  
  1647.     ret = HDgetspace(qty);
  1648.     DFerror = HEvalue(1);
  1649.     return(ret);
  1650. }
  1651.  
  1652. #if defined PROTOTYPE
  1653. void *DFIfreespace(void *ptr)
  1654. #else
  1655. void *DFIfreespace(ptr)
  1656. char *ptr;
  1657. #endif /* PROTOTYPE */
  1658. {
  1659.     return(HDfreespace(ptr));
  1660. }
  1661.  
  1662.  
  1663. #if defined PROTOTYPE
  1664. intn DFIc2fstr(char *str, int len)
  1665. #else
  1666. intn DFIc2fstr(str, len)
  1667. char* str;
  1668. int len;
  1669. #endif /* PROTOTYPE */
  1670. {
  1671.     return(HDc2fstr(str, len));
  1672. }
  1673.  
  1674. #if defined PROTOTYPE
  1675. char *DFIf2cstring(_fcd fdesc, intn len)
  1676. #else
  1677. char *DFIf2cstring(fdesc, len)
  1678.     _fcd fdesc;
  1679.     intn len;
  1680. #endif /* PROTOTYPE */
  1681. {
  1682.     return(HDf2cstring(fdesc, len));
  1683. }
  1684.