home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / hdf / unix / hdf3_2r2 / src / vio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-29  |  25.3 KB  |  1,052 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.4 $";
  27. #endif
  28. /*
  29. $Header: /hdf/hdf/v3.2r2/src/RCS/vio.c,v 1.4 1992/10/23 00:14:11 koziol beta koziol $
  30.  
  31. $Log: vio.c,v $
  32.  * Revision 1.4  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. *
  48. * vio.c
  49. * Part of the HDF Vset interface.
  50. *
  51. * VDATAs are handled by routines in here.
  52. * PRIVATE functions manipulate vsdir and are used only within this file.
  53. * PRIVATE data structures in here pertain to vdatas in vsdir only.
  54. *
  55. *************************************************************************/
  56.  
  57. #include "vg.h"
  58. extern vfile_t vfile[];
  59.  
  60. /* ---------------------- DFvsetopen --------------------------------------- */
  61. /*
  62.     DFvsetopen and DFvsetclose
  63. */
  64. #ifdef OLD_WAY
  65. #undef Hopen
  66. #undef Hclose
  67.  
  68. #undef DFopen
  69. #undef DFclose
  70.  
  71. #ifdef VMS /* Redefine Hopen and Hclose for VMS linker */
  72. #define Hclose _Hclose
  73. #define Hopen _Hopen 
  74. #endif /* VMS */
  75. #endif  /* OLD_WAY */
  76.  
  77. #ifdef PROTOTYPE
  78. PUBLIC HFILEID  DFvsetopen (char *fname, int16 access, int16 defDDs)
  79. #else
  80.  
  81. PUBLIC HFILEID  DFvsetopen (fname, access, defDDs)
  82.     char         *fname;
  83.     int16        access, defDDs;
  84.  
  85. #endif
  86.  
  87. {
  88.     HFILEID    f;
  89.     char * FUNC = "DFvsetopen";
  90.  
  91.     f = Hopen (fname, access, defDDs);
  92.     if(f == FAIL) return f;
  93.     Vinitialize (f);
  94.     return (f);
  95. }
  96. /* --------------------- DFvsetclose --------------------------------------- */
  97. #ifdef PROTOTYPE
  98. PUBLIC int32 DFvsetclose (HFILEID f)
  99. #else
  100.  
  101. PUBLIC int32 DFvsetclose (f)
  102.     HFILEID    f;
  103.  
  104. #endif
  105.  
  106. {
  107.     int32 s;
  108.     char * FUNC = "DFvsetclose";
  109.  
  110.     Vfinish(f);
  111.     s = Hclose(f);
  112.     return (s);
  113. }
  114.  
  115. /* ------------------------------------------------------------------ */
  116. /*
  117. * Looks thru vstab for vsid and return the addr of the vdata instance
  118. * where vsid is found.
  119. * RETURNS NULL if error or not found.
  120. * RETURNS vsinstance_t pointer if ok.
  121. *
  122. */
  123.  
  124. #ifdef PROTOTYPE
  125. vsinstance_t * vsinstance (HFILEID f, uint16 vsid)
  126. #else
  127.  
  128. vsinstance_t * vsinstance (f,vsid)
  129.     HFILEID    f;
  130.     uint16 vsid;
  131.  
  132. #endif
  133.  
  134. {
  135.   register uintn ref;
  136.   register vsinstance_t * w;
  137.   register vfile_t      * vf;
  138.   char * FUNC = "vsinstance";
  139.   
  140.   if (!(vf = Get_vfile(f))) HRETURN_ERROR(DFE_FNF, NULL);
  141.   
  142.   ref = (uintn) vsid;
  143.   for(w = vf->vstab.next; w; w = w->next) 
  144.     if (w->ref == ref) return(w);
  145.   
  146.   return(NULL);
  147.   
  148. } /* vsinstance */
  149.  
  150. /* --------------------------- vexists --------------------------------------- */
  151. /*
  152. * Tests if a vdata with id vsid is in the file's vstab.
  153. * returns FAIL if not found,
  154. * returns TRUE if found.
  155. */
  156.  
  157. #ifdef PROTOTYPE
  158. int32 vexistvs (HFILEID f, uint16 vsid)         
  159. #else
  160.  
  161. int32 vexistvs (f, vsid)         
  162.     HFILEID    f;
  163.     uint16 vsid;
  164.  
  165. #endif
  166.  
  167. {
  168.   char * FUNC = "vexistvs";
  169.   
  170.   if (NULL== vsinstance(f,vsid))
  171.     return(FAIL);
  172.   else
  173.     return (TRUE);
  174.   
  175. } /* vexistvs */
  176.  
  177. /* ------------------------------------------------------------------ */
  178. /*
  179. The following 2 routines, vpackvs and vunpackvs, packs and unpacks
  180. a VDATA structure into a compact form suitable for storing in the HDF file.
  181. */
  182.  
  183. /****
  184. CONTENTS of VS stored in HDF file with tag VSDESCTAG:
  185.     int16        interlace
  186.     int32        nvertices
  187.     int16        vsize
  188.     int16        nfields
  189.  
  190.     int16        isize[1..nfields] (internal size of each field)
  191.     int16        off[1..nfields] (internal offset of each field)
  192.     char        fname[1..nfields][FIELDNAMELENMAX]
  193.     char        vsname[VSNAMELENMAX]
  194. ****/
  195.  
  196.  
  197. #define INT16SIZE 2
  198. #define UINT16SIZE 2
  199. #define INT32SIZE 4
  200.  
  201. /* ------------------------------- vpackvs ----------------------------------- */
  202. /*
  203. The following 2 PRIVATE routines, vpackvs and vunpackvs, packs and unpacks
  204. a VDATA structure into a compact form suitable for storing in the HDF file.
  205. */
  206.  
  207. /****
  208. CONTENTS of VS stored in HDF file with tag VSDESCTAG:
  209.     int16        interlace
  210.     int32        nvertices
  211.     int16        vsize
  212.     int16        nfields
  213.  
  214.     int16        isize[1..nfields] (internal size of each field)
  215.     int16        off[1..nfields] (internal offset of each field)
  216.     char        fname[1..nfields][FIELDNAMELENMAX]
  217.     char        vsname[VSNAMELENMAX]
  218.     char     vsclass[VSNAMELENMAX]
  219.  
  220. ****/
  221.  
  222. /* 
  223. convert a vs struct to a vspack suitable for storage in a HDF file 
  224. */
  225.  
  226. #ifdef PROTOTYPE
  227. void vpackvs (VDATA *vs, BYTE buf[], int32 *size)
  228. #else
  229.  
  230. void vpackvs (vs, buf, size)
  231.     VDATA     *vs;
  232.     int32       *size;
  233.     BYTE        buf[];
  234.  
  235. #endif
  236.  
  237. {
  238.     register int32          i;
  239.     register BYTE        *b, *bb;
  240.     register int16         int16var;
  241.     char * FUNC = "vpackvs";
  242.  
  243.     bb = &buf[0];
  244.  
  245.     /* save the interlace */
  246.     b = bb;
  247.     INT16ENCODE(b,vs->interlace);
  248.     bb+=INT16SIZE;
  249.  
  250.     /* save nvertices */
  251.     b = bb;
  252.     INT32ENCODE(b,vs->nvertices);
  253.     bb+=INT32SIZE;
  254.  
  255.     /* save ivsize */
  256.     b = bb;
  257.     INT16ENCODE(b,vs->wlist.ivsize);
  258.     bb+=INT16SIZE;
  259.  
  260.     /* save nfields */
  261.     b = bb;
  262.     INT16ENCODE(b,vs->wlist.n);
  263.     bb+=INT16SIZE;
  264.  
  265.     for (i=0;i<vs->wlist.n;i++) { /* save the type */
  266.         b = bb;
  267.         INT16ENCODE(b,vs->wlist.type[i]);
  268.         bb+=INT16SIZE;
  269.     }
  270.     for (i=0;i<vs->wlist.n;i++) { /* save the isize */
  271.         b = bb;
  272.         INT16ENCODE(b,vs->wlist.isize[i]);
  273.         bb+=INT16SIZE;
  274.     }
  275.     for (i=0;i<vs->wlist.n;i++) { /* save the offset */
  276.         b = bb;
  277.         INT16ENCODE(b,vs->wlist.off[i]);
  278.         bb+=INT16SIZE;
  279.     }
  280.     for (i=0;i<vs->wlist.n;i++)  { /* save the order */
  281.         b = bb;
  282.         INT16ENCODE(b,vs->wlist.order[i]);
  283.         bb+=INT16SIZE;
  284.     }
  285.  
  286.     /* save each field length and name - omit the null */
  287.     for (i=0;i<vs->wlist.n;i++) {
  288.         b = bb;
  289.         int16var = HDstrlen(vs->wlist.name[i]);
  290.         INT16ENCODE(b,int16var);
  291.         bb+=INT16SIZE;
  292.  
  293.         HDstrcpy((char*) bb, vs->wlist.name[i]);
  294.         bb += HDstrlen(vs->wlist.name[i]);
  295.     }
  296.  
  297.     /* save the vsnamelen and vsname - omit the null */
  298.     b = bb;
  299.     int16var = HDstrlen(vs->vsname);
  300.     INT16ENCODE(b,int16var);
  301.     bb+=INT16SIZE;
  302.  
  303.     HDstrcpy((char*) bb,vs->vsname);
  304.     bb += HDstrlen(vs->vsname);
  305.  
  306.     /* save the vsclasslen and vsclass- omit the null */
  307.     b = bb;
  308.     int16var = HDstrlen(vs->vsclass);
  309.     INT16ENCODE(b,int16var);
  310.     bb+=INT16SIZE;
  311.  
  312.     HDstrcpy((char*) bb,vs->vsclass);
  313.     bb += HDstrlen(vs->vsclass);
  314.  
  315.     /* save the expansion tag/ref pair */
  316.     b= bb;
  317.     UINT16ENCODE(b,vs->extag);
  318.     bb +=UINT16SIZE;
  319.  
  320.     b= bb;
  321.     UINT16ENCODE(b,vs->exref);
  322.     bb +=UINT16SIZE;
  323.  
  324.     /* save the version field - init to version_2 now */
  325.     b= bb;
  326.     INT16ENCODE(b,vs->version);
  327.     bb +=INT16SIZE;
  328.  
  329.     /* save the 'more' field - NONE now */
  330.     b= bb;
  331.     INT16ENCODE(b,vs->more);
  332.     bb +=INT16SIZE;
  333.  
  334.     *size = (int32) (bb - buf) + 1;
  335.  
  336. } /* vpackvs */
  337.  
  338.  
  339. /* ----------------------- map_from_old_types ------------------------------- */
  340. /*
  341. Convert an old type (i.e. LOCAL_INT to DFNT_ based types
  342. */
  343. PRIVATE
  344. #ifdef PROTOTYPE
  345. int16 map_from_old_types(int16 type)
  346. #else
  347. int16 map_from_old_types(type)
  348.      int16 type;
  349. #endif
  350. {
  351.  
  352.   switch(type) {
  353.   case LOCAL_CHARTYPE:
  354.     return DFNT_CHAR;
  355.   case LOCAL_BYTETYPE:
  356.     return DFNT_INT8;
  357.   case LOCAL_SHORTTYPE:
  358.   case LOCAL_INTTYPE:
  359.     return DFNT_INT16;
  360.   case LOCAL_LONGTYPE:
  361.     return DFNT_INT32;
  362.   case LOCAL_FLOATTYPE:
  363.     return DFNT_FLOAT32;
  364.   case LOCAL_DOUBLETYPE:
  365.     return DFNT_FLOAT32;
  366.   default:
  367.     return type;
  368.   }
  369.  
  370. } /* map_from_old_types */
  371.  
  372.  
  373. /* ----------------------------- vunpackvs ------------------------------------- */
  374. /* 
  375. Convert a packed form(from HDF file)  to a VDATA structure.
  376. This routine will also initalize the VDATA structure as much as it can.
  377. */
  378.  
  379. #ifdef PROTOTYPE
  380. void vunpackvs (VDATA *vs, BYTE buf[], int32 *size)
  381. #else
  382.  
  383. void vunpackvs (vs, buf, size)
  384.     VDATA     *vs;
  385.     BYTE        buf[];
  386.     int32       *size;    /* UNUSED, but retained for compatibility with vpackvs */
  387. #endif
  388.  
  389. {
  390.     BYTE        *b, *bb;
  391.     int32    i;
  392.     int16        int16var;
  393.     char * FUNC = "vunpackvs";
  394.  
  395.     i = *size; /* dum */
  396.  
  397.     bb = &buf[0];
  398.  
  399.     /* retrieve interlace */
  400.     b = bb;
  401.     INT16DECODE(b,vs->interlace);
  402.     bb += INT16SIZE;
  403.  
  404.     /* retrieve nvertices */
  405.     b = bb;
  406.     INT32DECODE(b,vs->nvertices);
  407.     bb += INT32SIZE;
  408.  
  409.     /* retrieve tore ivsize */
  410.     b = bb;
  411.     INT16DECODE(b,vs->wlist.ivsize);
  412.     bb += INT16SIZE;
  413.  
  414.     /* retrieve nfields */
  415.     b = bb;
  416.     INT16DECODE(b,vs->wlist.n);
  417.     bb += INT16SIZE;
  418.  
  419.     for (i=0;i<vs->wlist.n;i++)  { /* retrieve the type */
  420.         b = bb;
  421.         INT16DECODE(b,vs->wlist.type[i]);
  422.         bb += INT16SIZE;
  423.     }
  424.  
  425.     for (i=0;i<vs->wlist.n;i++)  { /* retrieve the isize */
  426.         b = bb;
  427.         INT16DECODE(b,vs->wlist.isize[i]);
  428.         bb += INT16SIZE;
  429.     }
  430.  
  431.     for (i=0;i<vs->wlist.n;i++)  { /* retrieve the offset */
  432.         b = bb;
  433.         INT16DECODE(b,vs->wlist.off[i]);
  434.         bb += INT16SIZE;
  435.     }
  436.  
  437.     for (i=0;i<vs->wlist.n;i++)  { /* retrieve the order */
  438.         b = bb;
  439.         INT16DECODE(b,vs->wlist.order[i]);
  440.         bb += INT16SIZE;
  441.     }
  442.  
  443.     /* retrieve the field names (and each field name's length)  */
  444.     for (i=0;i<vs->wlist.n;i++) {
  445.         b = bb;
  446.         INT16DECODE(b,int16var); /* this gives the length */
  447.         bb += INT16SIZE;
  448.  
  449.                 HIstrncpy(vs->wlist.name[i], (char*) bb, int16var + 1);
  450.         bb += int16var;
  451.     }
  452.  
  453.     /* retrieve the vsname (and vsnamelen)  */
  454.     b = bb;
  455.     INT16DECODE(b, int16var); /* this gives the length */
  456.     bb += INT16SIZE;
  457.  
  458.         HIstrncpy(vs->vsname, (char*) bb, int16var + 1);
  459.     bb += int16var;
  460.  
  461.     /* retrieve the vsclass (and vsclasslen)  */
  462.     b = bb;
  463.     INT16DECODE(b, int16var); /* this gives the length */
  464.     bb += INT16SIZE;
  465.  
  466.         HIstrncpy(vs->vsclass, (char*) bb, int16var + 1);
  467.     bb += int16var;
  468.  
  469.     /* retrieve the expansion tag and ref */
  470.     b = bb;
  471.     UINT16DECODE(b, vs->extag);
  472.     bb += UINT16SIZE;
  473.  
  474.     b = bb;
  475.     UINT16DECODE(b, vs->exref);
  476.     bb += UINT16SIZE;
  477.  
  478.     /* retrieve the version field */
  479.     b = bb;
  480.     INT16DECODE(b, vs->version);
  481.     bb += INT16SIZE;
  482.  
  483.     /* retrieve the 'more' field */
  484.     b = bb;
  485.     INT16DECODE(b, vs->more);
  486.     bb += INT16SIZE;
  487.  
  488.         if(vs->version <= VSET_OLD_TYPES)
  489.           for (i = 0; i < vs->wlist.n; i++) { /* save the type */
  490.             vs->wlist.type[i] = map_from_old_types(vs->wlist.type[i]);
  491.           }
  492.         
  493.     /* --- EXTRA --- fill in the machine-dependent size fields */
  494.     for (i = 0; i < vs->wlist.n; i++) {
  495.           vs->wlist.esize[i] = vs->wlist.order[i] * DFKNTsize(vs->wlist.type[i] | DFNT_NATIVE);
  496.     }
  497.         
  498. } /* vunpackvs */
  499.  
  500. /* ------------------------------------------------------------------ */
  501.  
  502.  
  503. /* ***************************************************************
  504.    NEW VSattach: 
  505.     (a)    if vsid == -1 
  506.             if "r" access return error.
  507.             if "w" access 
  508.                 create a new vs in vg and attach it.
  509.                 add to vsdir, set nattach= 1, nvertices = 0.
  510.  
  511.     (b)    if (vsid > 0)  
  512.             if "r" access => look in vsdir
  513.                 if not found,
  514.                     fetch  vs from file, add to vsdir,  
  515.                     set nattach= 1, nvertices = val from file.
  516.                 if found,
  517.                     check access of found vs
  518.                     if "w" => being written, unstable! forbidden
  519.                     if "r" => ok. incr nattach.
  520.  
  521.             if "w" access => new data may be added BUT must be same format
  522.                     as existing vdata.
  523.                     (ie. VSsetfields must match old format exactly!!)
  524.  
  525.                     Allows for seeks to write.
  526.  
  527.     in all cases, set the marked flag to 0.
  528.     returns NULL if error.
  529.  
  530.    OLD VSattach: 
  531.     if vsid == -1, then
  532.     (a) if vg is "w", create a new vs in vg and attach it.
  533.                     add to vsdir, set nattach= 1, nvertices = 0.
  534.     (b) if vg is "r", forbidden.
  535.    if vsid is +ve, then
  536.     (a) if vg is "w"  => new data may be added BUT must be same format
  537.                 as existing vdata.
  538.                 (ie. VSsetfields must match old format exactly!!)
  539.  
  540.     (b) if vg is "r"  => look in vsdir
  541.                 if not found,
  542.                     fetch  vs from file, add to vsdir,  
  543.                     set nattach= 1, nvertices = val from file.
  544.                 if found,
  545.                     check access of found vs
  546.                     if "w" => being written, unstable! forbidden
  547.                     if "r" => ok. incr nattach.
  548.     
  549.     in all cases, set the marked flag to 0.
  550.     returns NULL if error.
  551.    *************************************************************** */
  552.  
  553. #ifdef PROTOTYPE
  554. PUBLIC VDATA * VSattach (HFILEID f, int32 vsid, char *accesstype) 
  555. #else
  556.  
  557. PUBLIC VDATA * VSattach (f, vsid, accesstype) 
  558.     HFILEID    f;
  559.     int32     vsid;
  560.     char *    accesstype;
  561.  
  562. #endif
  563.  
  564. {
  565.     VDATA         *vs;               /* new vdata to be returned */
  566.     int32         vspacksize;
  567.     BYTE            vspack[sizeof(VWRITELIST)];
  568.     int32            access;
  569.     vsinstance_t    * w;
  570.     vfile_t            * vf;
  571.     char * FUNC = "VSattach";
  572.  
  573.     if ((f == FAIL)  || (vsid < -1)) HRETURN_ERROR(DFE_ARGS, NULL);
  574.     if (!(vf = Get_vfile(f)))        HRETURN_ERROR(DFE_FNF, NULL);
  575.  
  576.     if      ( accesstype[0]=='R' || accesstype[0]=='r') { access = 'r'; }
  577.     else if ( accesstype[0]=='W' || accesstype[0]=='w') { access = 'w'; }
  578.     else HRETURN_ERROR(DFE_BADACC, NULL);
  579.  
  580.     if (vjv) {
  581.           sprintf(sjs,"#VSATTACH:vsid=%ld access=%s\n",vsid, accesstype); zj;
  582.         }
  583.  
  584.     if (vsid == -1) {  /* ---------- VSID IS -1 ----------------------- */
  585.           if (access == 'r') {
  586.             HERROR(DFE_BADACC);
  587.             HEreport("VSattach: may not read vsid of -1");
  588.             return(NULL);
  589.           }
  590.  
  591.           /* otherwise 'w' */
  592.           /* allocate space for vs,  & zero it out  */
  593.           if ( (vs= (VDATA*) HDgetspace (sizeof(VDATA))) == NULL)
  594.             HRETURN_ERROR(DFE_NOSPACE, NULL);
  595.  
  596.           vs->nvertices = 0;
  597.           vs->wlist.n = vs->rlist.n = 0;
  598.           vs->islinked = FALSE;
  599.           vs->nusym = 0;
  600.           
  601.           vs->oref        = vnewref(f);
  602.           if (vs->oref == 0) {HERROR(DFE_NOREF); HDfreespace(vs); return(NULL);}
  603.           
  604.           vs->otag        = VSDESCTAG;
  605.           vs->vsname[0]     = '\0';
  606.           vs->interlace        = FULL_INTERLACE; /* DEFAULT */
  607.           vs->access        = 'w';
  608.           vs->f            = f;
  609.           vs->marked        = 0;
  610.           
  611.           vs->vsclass[0]    = '\0';
  612.           vs->extag        = 0;
  613.           vs->exref        = 0;
  614.           vs->more            = 0;
  615.           vs->version        = VSET_VERSION;
  616.           
  617.           vs->vm        = (VMBLOCK*) NULL;
  618.           
  619.           vs->aid        = 0;
  620.           
  621.           /* attach new vs to file's vstab */
  622.           if ( NULL == (w = (vsinstance_t*) HDgetspace (sizeof(vsinstance_t))))
  623.             HRETURN_ERROR(DFE_NOSPACE, NULL);
  624.           
  625.           vf->vstabtail->next = w;
  626.           vf->vstabtail       = w;
  627.           vf->vstabn++;
  628.           
  629.           w->next      = NULL;
  630.           w->ref       = (intn) vs->oref;
  631.           w->vs        = vs;
  632.           w->nattach   = 1;
  633.           w->nvertices = 0;
  634.           
  635.           vs->instance = w;
  636.  
  637.           return (vs);
  638.     } /* end of case where vsid is -1 */
  639.  
  640.     /*  --------  VSID IS NON_NEGATIVE ------------- */
  641.  
  642.     if (access == 'r') { /* reading an existing vdata */
  643.  
  644.         if (NULL == (w =  vsinstance (f, (uint16) vsid)) )
  645.             HRETURN_ERROR(DFE_VTAB, NULL);
  646.           
  647.         if (w->nattach && w->vs->access == 'r') {
  648.             /* this vdata is already attached for 'r', ok to do so again */
  649.             w->nattach++;
  650.             return (w->vs);
  651.           }
  652.           
  653.         if (w->vs) {
  654.             /* use existing vs record */
  655.             vs = w->vs;
  656.  
  657.         } else {
  658.  
  659.             /* allocate space for vs,  & zero it out  */
  660.             if ( (vs=(VDATA*) HDgetspace (sizeof(VDATA))) == NULL)
  661.               HRETURN_ERROR(DFE_NOSPACE, NULL);
  662.  
  663.         }
  664.  
  665.           /* need to fetch from file */
  666.         if (Hgetelement(f,VSDESCTAG,(uint16)vsid,vspack) == FAIL)
  667.             HRETURN_ERROR(DFE_NOVS, NULL);
  668.           
  669.         vs->wlist.n = vs->rlist.n = 0;
  670.  
  671.         /* unpack the vs, then init all other fields in it */
  672.         vunpackvs (vs,vspack,&vspacksize);
  673.         vs->otag    = VSDESCTAG;
  674.         vs->oref    = (uint16)vsid;
  675.         vs->access  = 'r';
  676.         vs->f   = f;
  677.         vs->marked  = 0;
  678.         vs->nusym   = 0;
  679.  
  680.         vs->vm      = (VMBLOCK*) NULL; /* always NULL for "r" */
  681.  
  682.         vs->aid     = Hstartread(vs->f, VSDATATAG, vs->oref);
  683.         if(vs->aid == FAIL) {
  684.           HDfreespace(vs);
  685.           HRETURN_ERROR(DFE_BADAID, NULL);
  686.         }
  687.  
  688.         vs->instance = w;
  689.  
  690.         /* attach vs to vsdir  at the vdata instance w */
  691.         w->vs        = vs;
  692.         w->nattach   = 1;
  693.         w->nvertices = vs->nvertices;
  694.         return (vs);
  695.      } /* end of case where vsid is positive, and "r"  */
  696.  
  697.  
  698.     if (access == 'w') { /* writing to an existing vdata */
  699.  
  700.           if ((w = vsinstance(f, (uint16) vsid)) == NULL) 
  701.             HRETURN_ERROR(DFE_VTAB, NULL);
  702.           
  703.           if (w->nattach)  /* vdata previously attached before */
  704.             RTNULL("VSattach: May not write to a previously attached vdata!");
  705.  
  706.           /* free old record (should reuse....) */
  707.           if(w->vs) {
  708.             vs = w->vs;
  709.           } else {
  710.             /* allocate space */
  711.             if( (vs=(VDATA*) HDgetspace (sizeof(VDATA))) == NULL)
  712.               HRETURN_ERROR(DFE_NOSPACE, NULL);
  713.           }
  714.           
  715.           /* need to fetch from file */
  716.           if (Hgetelement(f, VSDESCTAG, (uint16)vsid, vspack) == FAIL)
  717.             HRETURN_ERROR(DFE_NOMATCH, NULL);
  718.           
  719.           
  720.           /*
  721.             zerofill((BYTE*) vs, (int16) sizeof(VDATA));
  722.             */
  723.  
  724.           vs->wlist.n = vs->rlist.n = 0;
  725.           vs->nusym = 0;
  726.           
  727.           /* unpack the vs, then init all other fields in it */
  728.           vunpackvs (vs,vspack,&vspacksize);
  729.           vs->otag    = VSDESCTAG;
  730.           vs->oref    = (uint16)vsid;
  731.           vs->access    = 'w';
  732.           vs->f        = f;
  733.           vs->marked    = 0;
  734.           vs->vm    = (VMBLOCK*) NULL; 
  735.           
  736.           vs->aid   = Hstartwrite(vs->f, VSDATATAG, vs->oref, 0);
  737.           if(vs->aid == FAIL) { 
  738.             HDfreespace(vs);
  739.             HRETURN_ERROR(DFE_BADAID, NULL);
  740.           }
  741.           
  742.           vs->instance = w;
  743.  
  744.           /* attach vs to vsdir  at the vdata instance w */
  745.           w->vs        = vs;
  746.           w->nattach   = 1;
  747.           w->nvertices = vs->nvertices;
  748.           
  749.           return (vs);
  750.           
  751.     } /* end of case where vsid is positive, and "w"  */
  752.     return (NULL);
  753.  
  754. } /* VSattach */
  755.  
  756. /* ------------------------ VSdetach ----------------------------- */
  757.  
  758. /* *************************************************************** 
  759.      Detach vs from vstab. 
  760.  
  761.     if vs has "w" access,   ( <=> only attached ONCE! )
  762.         decr nattach.
  763.         if (nattach is not  0)  => bad error in code.
  764.         if nvertices (in vs) is 0) just free vs from vstab.
  765.  
  766.         if marked flag is 1
  767.             write out vs to file and set marked flag to 0.
  768.            free vs from vsdir.
  769.  
  770.     if vs has "r" access,   ( <=> only attached ONCE! )
  771.         decr nattach.
  772.         if (nattach is 0)   just free vs from vstab.
  773.             
  774.    *************************************************************** */
  775.  
  776. #ifdef PROTOTYPE
  777. PUBLIC void VSdetach (VDATA *vs)
  778. #else
  779.  
  780. PUBLIC void VSdetach (vs)
  781.     VDATA  *vs;
  782.  
  783. #endif
  784.  
  785. {
  786.     int32            i, stat, vspacksize;
  787.     BYTE            vspack[sizeof(VWRITELIST)];
  788.     vsinstance_t    *w;
  789.     char * FUNC = "VSdetach";
  790.  
  791.     if ((vs == NULL) || (vs->otag != VSDESCTAG)) {
  792.           HERROR(DFE_ARGS);
  793.           HEprint(stderr,0);
  794.           return;
  795.         }
  796.  
  797.     /* locate vs's entry in vstab */
  798.     if (!(w = vs->instance)) {
  799.           sprintf(sjs,"@VSdetach: vs not found\n"); zj;
  800.           return;
  801.     }
  802.  
  803.     w->nattach--;
  804.  
  805.     /* --- case where access was 'r' --- */
  806.     if (vs->access =='r') {
  807.           if (w->nattach == 0) {
  808. #if 0
  809.             w->vs = NULL; /* detach vs from vsdir */
  810.             HDfreespace (vs);
  811. #endif
  812.           }
  813.           Hendaccess (vs->aid);
  814.           return;
  815.     }
  816.  
  817.     /* --- case where access was 'w' --- */
  818.     if (w->nattach != 0) {
  819.         sprintf(sjs,"BUG IN VSET CODE. VSdetach on a vdata with 'w' access\n"); zj;
  820.         sprintf(sjs,"nattach is %d (should be ZERO) \n",w->nattach); zj;
  821.         }
  822.  
  823.     if (vs->marked)  { /* if marked , write out vdata's VSDESC to file */
  824.         if(vs->nvertices==0) {sprintf(sjs,"VSdetach: Empty vdata detached\n"); zj; }
  825.         vpackvs(vs,vspack,&vspacksize);
  826.         stat = Hputelement (vs->f,VSDESCTAG,vs->oref,vspack,vspacksize);
  827.         if (stat == FAIL)  RT("VSdetach: cannot write out vs");
  828.         vs->marked = 0;
  829.     }
  830.  
  831.     if (vjv && vs->nvertices<=0){
  832.         sprintf(sjs,"#VSdetach:vs->nver=%ld!\n",vs->nvertices); zj;
  833.     }
  834.  
  835.     /* remove all defined symbols */
  836.     for (i=0;i<vs->nusym;i++) HDfreespace (vs->usym[i].name);
  837.     vs->nusym = 0;
  838.  
  839. #if 0
  840.         {{ /* THIS VERSION WITH VMBLOCKS */
  841.                   VMBLOCK * t, *p;
  842.                   int32 aid, stat, cursize, totalsize = 0;
  843.                   BYTE * vwhole;
  844.                   
  845.                   /* count total byte size */
  846.                   t = vs->vm;
  847.                   while (t != NULL) { totalsize += t->n; t = t->next; }
  848.                   if (vjv) {
  849.                     sprintf(sjs,"VMBLOCKS total size = %ld\n", totalsize);zj;
  850.                   }
  851.                   vwhole = (BYTE*) HDgetspace( totalsize );
  852.                   if (vwhole==NULL) {
  853.                     sprintf(sjs,"VSdetach: no mem for VWHOLE\n"); zj;
  854.                     return;
  855.                   }
  856.                   /* coalesce all VMBLOCKS into vwhole */
  857.                   cursize = 0;
  858.                   t = vs->vm;
  859.                   while (t != NULL) { 
  860.                     HDmemcpy(&vwhole[cursize], t->mem, t->n);
  861.                     HDfreespace(t->mem);
  862.                     cursize+= t->n;
  863.                     t = t->next; 
  864.                   }
  865.                   /* free all VMBLOCKS */
  866.                   t = vs->vm;
  867.                   while (t != NULL) { p = t; t = t->next; HDfreespace(p); }
  868.                   vs->vm = (VMBLOCK*) NULL;
  869.                   
  870.                   /* write out vwhole to file as 1 vdata */
  871.                   if (vjv) {
  872.                     sprintf(sjs,"---- QQstartwrite nbytes = %ld\n", totalsize);zj; }
  873.                   stat = aid =QQstartwrite(vs->f,VSDATATAG,vs->oref, totalsize);
  874.                   QQwrite(aid,  totalsize , vwhole);
  875.                   QQendaccess (aid);
  876.                   HDfreespace (vwhole);
  877.                   /* END OF VMBLOCK VERSION */     }}
  878. #endif
  879.  
  880.         Hendaccess (vs->aid);
  881. #if 0
  882.         w->vs = NULL; /* detach vs from vsdir */
  883.         HDfreespace (vs);
  884. #endif
  885.     return;
  886.  
  887. } /* VSdetach */
  888.  
  889. /* -------------------------- VSappendable -------------------------------- */
  890. /*
  891.  * make it possible to append unlimitedly to an existing VData
  892.  *
  893.  *  Returns: SUCCEED, or FAIL for error
  894.  *
  895.  * undocumented 
  896.  *
  897.  */
  898.  
  899. #ifdef PROTOTYPE
  900. PUBLIC int32 VSappendable (VDATA *vs)
  901. #else
  902.  
  903. PUBLIC int32 VSappendable (vs)
  904.     VDATA  *vs;
  905.  
  906. #endif
  907.  
  908. {
  909.   int32        status;
  910.   int32         blksize, curr_size;
  911.   char * FUNC = "VSappendable";
  912.   
  913.   if ((vs == NULL) || (vs->otag != VSDESCTAG)) {
  914.     HERROR(DFE_ARGS);
  915.     HEprint(stderr,0);
  916.     return (FAIL);
  917.   }
  918.  
  919.   curr_size = vs->nvertices * vs->wlist.ivsize;
  920.  
  921.   if(vs->nvertices && (curr_size > VDEFAULTBLKSIZE))
  922.       blksize = curr_size;
  923.   else
  924.       blksize = VDEFAULTBLKSIZE;
  925.  
  926.   status = HLcreate(vs->f, VSDATATAG, vs->oref, blksize, VDEFAULTNBLKS);
  927.   if(status == FAIL)
  928.     return FAIL;
  929.  
  930.   Hendaccess(status);
  931.  
  932.   return SUCCEED;
  933.  
  934. } /* VSappendable */
  935.  
  936. /* -------------------------- Visvs -------------------------------- */
  937.  
  938. /* Visvs
  939. *  checks if an id in a vgroup refers to a VDATA
  940. *  RETURNS 1 if so
  941. *  RETURNS 0 if not, or if error.
  942. */
  943.  
  944. #ifdef PROTOTYPE
  945. PUBLIC int32 Visvs (VGROUP *vg, int32 id)       
  946. #else
  947.  
  948. PUBLIC int32 Visvs (vg, id)       
  949.     VGROUP  *vg;
  950.     int32   id;
  951.  
  952. #endif
  953.  
  954. {
  955.   register intn i;
  956.   char * FUNC = "VSisvs";
  957.  
  958.   i = vg->nvelt;
  959.   while(i) 
  960.     if (vg->ref[--i] == (uint16)id && vg->tag[i]==VSDESCTAG) return(1);
  961.   
  962.   return(0);
  963.   
  964. } /* Visvs */
  965.  
  966. /* ======================================================= */
  967.  
  968. /* 
  969. returns the id of the next  VDATA from the file f .
  970. (vsid = -1 gets the 1st vDATA). 
  971. RETURNS -1 on error.
  972. RETURNS vdata id (0 or +ve integer) 
  973. */
  974.  
  975. #ifdef PROTOTYPE
  976. PUBLIC int32 VSgetid (HFILEID f, int32 vsid)
  977. #else
  978.  
  979. PUBLIC int32 VSgetid (f, vsid)
  980.     int32     vsid;
  981.     HFILEID    f;
  982.  
  983. #endif
  984.  
  985. {
  986.     vsinstance_t   * w;
  987.     vfile_t           * vf;
  988.     char * FUNC = "VSgetid";
  989.  
  990.     if (vsid < -1)            HRETURN_ERROR(DFE_ARGS, FAIL);
  991.     if (!(vf = Get_vfile(f))) HRETURN_ERROR(DFE_FNF, FAIL);
  992.  
  993.     if (vjv) {
  994.         sprintf(sjs,"#VSgetid:vstabn is %ld\n",vf->vstabn); zj;
  995.     }
  996.  
  997.     if (vsid == -1) {
  998.           if (NULL == vf->vstab.next)
  999.             return (FAIL);
  1000.           else
  1001.             return((int32) (vf->vstab.next)->ref); /* rets 1st vdata's ref */
  1002.     }
  1003.  
  1004.     /* look in vstab  for vsid */
  1005.  
  1006.         if ((w = vsinstance(f, (uint16) vsid)) == NULL) 
  1007.           HRETURN_ERROR(DFE_VTAB, FAIL);
  1008.  
  1009.     if (w->next == NULL)
  1010.           return(FAIL);            /* this is the last vdata, no more after it */
  1011.     else
  1012.           return( (int32) (w->next)->ref);  /* success, ret the next vdata's ref */
  1013.  
  1014. } /* VSgetid */
  1015.  
  1016. /* ------------------------------------------------------------------ */
  1017. /*
  1018. zero out n bytes in array x.
  1019. */
  1020. #if 0
  1021. #ifdef PROTOTYPE
  1022. void zerofill (BYTE x[], int16 n)    
  1023. #else
  1024.  
  1025. void zerofill (x, n)    
  1026.     BYTE     x[];
  1027.     int16 n;
  1028.  
  1029. #endif
  1030. {
  1031.     for( ; n; n--) *x++ = 0;
  1032.  
  1033. } /* zerofill */
  1034. #endif
  1035.  
  1036. /* -------------- Return the version number of a VData----------------- */
  1037.  
  1038. PUBLIC 
  1039. #ifdef PROTOTYPE
  1040. int32 VSgetversion(VDATA *vs)
  1041. #else
  1042. int32 VSgetversion(vs)
  1043.      VDATA *vs;
  1044. #endif
  1045. {
  1046.  
  1047.   if(!vs) return 0;
  1048.   
  1049.   return (vs->version);
  1050.  
  1051. }
  1052.