home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / UIFlow 1.0.1 / UIFlow Source / VSet2.0 / Src / vgp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-20  |  26.9 KB  |  1,234 lines  |  [TEXT/????]

  1. /*****************************************************************************
  2. *              NCSA HDF Vset release 2.1
  3. *                    May 1991
  4. *
  5. * NCSA HDF Vset release 2.1 source code and documentation are in the public
  6. * domain.  Specifically, we give to the public domain all rights for future
  7. * licensing of the source code, all resale rights, and all publishing rights.
  8. * We ask, but do not require, that the following message be included in all
  9. * derived works:
  10. * Portions developed at the National Center for Supercomputing Applications at
  11. * the University of Illinois at Urbana-Champaign.
  12. * THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
  13. * SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
  14. * WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
  15. *****************************************************************************
  16. * Likkai Ng NCSA May 1991
  17. * vgp.c
  18. * Part of the vertex-set interface.
  19. * VGROUPs are handled by routines in here.
  20. *
  21. *************************************************************************/
  22.  
  23. #include "vg.h"
  24.  
  25. /* ------------------------------------------------------------ */
  26. /* 
  27. *
  28. * G L O B A L S 
  29. *
  30. * These are the *only* globals in the vset interface!!  
  31. * They are used only for debugging.  No globals in other files. 
  32. * The 2 functions below turn debugging on and off.
  33. *
  34. */
  35.  
  36. PUBLIC    char         sjs[200];
  37. PUBLIC    int      vjv    =    0;
  38.  
  39. /*
  40. turn debug on 
  41. */
  42. PUBLIC void    setjj()              /*@-@*/
  43.     vjv=1; 
  44. }
  45.  
  46. /*
  47. turn debug off 
  48. */
  49. PUBLIC void setnojj()         /*@-@*/
  50.     vjv=0; 
  51. }
  52.  
  53.  
  54. /*
  55. * -------------------------------------------------------------------- 
  56. * PRIVATE  data structure and routines.
  57. * Info about all vgroups in the file are loaded into vgtab  at start;
  58. * and the vg field set to NULL until that vgroup is attached,
  59. * and reset back to NULL when that vgroup is detached. 
  60. * Info about all vdatas in the file are loaded into vstab  at start;
  61. * and the vs field set to NULL until that vdata is attached,
  62. * and reset back to NULL when that vdata is detached. 
  63. * -------------------------------------------------------------------- 
  64. */
  65.  
  66.  
  67. PRIVATE vfile_t  vfile [VFILEMAX];
  68. PRIVATE int      nvfile = 0;
  69.  
  70. /*
  71.   ***Only called by Get_vfile()***   
  72. loads vgtab table with info of all vgroups in file f.
  73. Will allocate a new vfile_t, then proceed to load vg instances.
  74. RETURNS -1 if error
  75. RETURNS INDEX into vfile[] if ok.
  76. */
  77. PRIVATE int Load_vfile (f)              /*@@*/
  78.  
  79. DF *f;
  80. {
  81.     DFdesc   d;
  82.     vfile_t    * vf;
  83.     vginstance_t  * v;
  84.     vsinstance_t  * w;
  85.     int returnval;
  86.  
  87.     if (vjv) {
  88.         sprintf(sjs,"@Load_vfile \n");
  89.         zj;
  90.     }
  91.  
  92.     /* allocate a new vfile_t structure */
  93.     if (nvfile >= VFILEMAX-1) RTNEG ("Load_vfile: full\n");
  94.  
  95.     returnval = nvfile;
  96.     vf = &vfile[nvfile];
  97.     nvfile++;
  98.  
  99.     vf->f            = f;
  100.  
  101.     /* load all the vg's  tag/refs from file */
  102.     vf->vgtabn    = -1;
  103.     vf->vgtabtail = &(vf->vgtab);
  104.  
  105.     vf->vgtab.ref      = -1;
  106.     vf->vgtab.nattach  = -1;
  107.     vf->vgtab.nentries = -1;
  108.     vf->vgtab.vg       = NULL;
  109.     vf->vgtab.next     = NULL;
  110.  
  111.     vf->vgtabn = 0;
  112.     DFsetfind(f,VGDESCTAG,DFREF_WILDCARD);
  113.  
  114.     while (1) {
  115.         if ( DFfind(f,&d) != 0) break;          /* no more vgs */
  116.         if (vjv) {
  117.             sprintf(sjs,"#LOADVGDIR:FOUND (%d) <%d/%d>\n ",
  118.                 vf->vgtabn, d.tag,d.ref);
  119.             zj;
  120.         }
  121.  
  122.         if (NULL == (v = (vginstance_t*) DFIgetspace(sizeof(vginstance_t))))
  123.             RTNEG ("Load_vfile: no more space\n");
  124.  
  125.         vf->vgtabtail->next    = v;
  126.         vf->vgtabtail            = v;
  127.         v->next        = NULL;
  128.         v->ref      = d.ref;
  129.         v->vg       = (VGROUP*) NULL; /* ie not attached yet */
  130.         v->nattach  = 0;
  131.         v->nentries = 0;
  132.         vf->vgtabn++;
  133.  
  134.     }
  135.  
  136.     /* load all the vs's  tag/refs from file */
  137.     vf->vstabn    = -1;
  138.     vf->vstabtail = &(vf->vstab);
  139.  
  140.     vf->vstab.ref      = -1;
  141.     vf->vstab.nattach  = -1;
  142.     vf->vstab.nvertices= -1;
  143.     vf->vstab.vs       = NULL;
  144.     vf->vstab.next     = NULL;
  145.  
  146.     vf->vstabn = 0;
  147.     DFsetfind(f,VSDESCTAG,DFREF_WILDCARD);
  148.  
  149.     while (1) {
  150.         if ( DFfind(f,&d) != 0) break;      /* no more vgs */
  151.         if (vjv) {
  152.             sprintf(sjs,"#LOADVSDIR:FOUND (%d) <%d/%d>\n ",
  153.                 vf->vstabn, d.tag,d.ref);
  154.             zj;
  155.         }
  156.         if (NULL == (w = (vsinstance_t*) DFIgetspace(sizeof(vsinstance_t))))
  157.             RTNEG ("Load_vfile: no more space\n");
  158.  
  159.         vf->vstabtail->next  = w;
  160.         vf->vstabtail        = w;
  161.         w->next     = NULL;
  162.         w->ref      = d.ref;
  163.         w->vs       = (VDATA*) NULL; /* ie not attached yet */
  164.         w->nattach  = 0;
  165.         w->nvertices= 0;
  166.         vf->vstabn++;
  167.  
  168.     }
  169.  
  170.     /* file may be incompatible with vset version 2.x. Need to check it */
  171.     if ( (0 == vf->vgtabn) && (0 == vf->vstabn) )
  172.         if ( 0 == vicheckcompat (f) ) { /* not compatible */
  173.             sprintf(sjs,"********************************************\n\n");
  174.             zj;
  175.             sprintf(sjs,"%cFile incompatible with vset version 2.0\n",7); 
  176.             zj;
  177.             sprintf(sjs,"%cFirst use the utility vcompat on this file\n",7); 
  178.             zj;
  179.             sprintf(sjs,"********************************************\n\n");
  180.             zj;
  181.             nvfile--;     /* delete the structure for that file */
  182.             RTNEG ("Load_vfile: incompatible file\n");
  183.         }
  184.  
  185.     /* otherwise, success */
  186.     return (returnval); /* ok, return the index  */
  187.  
  188. } /* Load_vfile */
  189.  
  190. /* returns the vfile pointer for file f, else NULL */
  191. vfile_t * Get_vfile (f)
  192. DF * f;
  193. {
  194.     int i, vfileno;
  195.  
  196.     /* loop thru vfile[], if found, return ptr */
  197.     for (i=0;i<nvfile;i++) if (vfile[i].f == f)    return(&vfile[i]);
  198.  
  199.     /* not found, try to load it */
  200.     vfileno = Load_vfile (f);
  201.  
  202.     if (-1 == vfileno) {
  203.         RTNULL("Get_vfile: cannot load file\n");
  204.     }
  205.     else
  206.         return( &vfile[vfileno]); /* ok, return vfile pointer */
  207.  
  208. } /* Get_vfile */
  209.  
  210.  
  211.  
  212. PRIVATE void Remove_vfile (f)
  213. DF * f;
  214. {
  215.     int i;
  216.  
  217.     /* loop thru vfile[], if found, delete it */
  218.         for (i=0;i<nvfile;i++)
  219.             if (vfile[i].f == f) { vfile[i].f = NULL; break; }
  220.             }
  221.  
  222. /* should be replaced by HDFopen() or such */
  223. /* is called by DFvsetopen() only */
  224.  
  225. PUBLIC void Vinitialize(f)
  226. DF * f; {
  227.   if (f!=NULL) Remove_vfile (f);
  228.     if (vjv) {
  229.         sprintf(sjs,"@Vinitialize: f=%x\n", f);
  230.         zj;
  231.     }
  232.   }
  233.  
  234. /* ==================================================================== */
  235.  
  236. /*
  237. * Looks thru vgtab for vgid and return the addr of the vg instance
  238. * where vgid is found.
  239. * RETURNS NULL if error or not found.
  240. * RETURNS vginstance_t pointer if ok.
  241. *
  242. */
  243.  
  244. vginstance_t * vginstance (f,vgid)             /*@@*/
  245. DF  *f;
  246. int vgid;
  247.  
  248. {
  249.     vginstance_t * v;
  250.     vfile_t      * vf;
  251.  
  252.     if (NULL== (vf = (vfile_t*) Get_vfile(f)))
  253.         RTNULL ("vginstance: no such file\n");
  254.  
  255.     v = vf->vgtab.next;
  256.     while (NULL != v) {
  257.         if (v->ref == vgid) return(v);
  258.         v = v->next;
  259.     }
  260.     return(NULL);
  261.  
  262. } /* vginstance */
  263.  
  264. /* 
  265. * Tests if a vgroup with id vgid is in the file's vgtab.
  266. * returns -1 if not found,
  267. * returns 1 if found.
  268. */
  269. int vexistvg (f,vgid)             /*@@*/
  270. DF  *f;
  271. int vgid;
  272. {
  273.     if (NULL== (vginstance_t *) vginstance(f,vgid))
  274.         return(-1);
  275.     else
  276.         return (1);
  277.  
  278. } /* vexistvg */
  279. /* ==================================================================== */
  280. /*
  281. * vpackvg() and vunpackvg() : Packing and unpacking routines.
  282. * For use in retrieving and storing vgroups to/from the HDF file.
  283. *
  284. *    Fields of VGROUP  that gets stored in HDF as a VGDESCTAG data object:
  285. *        int16        nvelt (no of entries )
  286. *        char        vgname[MAXVGNAMELEN]
  287. *        int16        tag[1..nvelt]        
  288. *        int16        ref[1..nvelt]        
  289. */
  290. /* ==================================================================== */
  291.  
  292. #define INT16SIZE 2
  293.  
  294. /* ==================================================================== */
  295. /* 
  296. *    vpackvg
  297. *    extracts fields from  a VGROUP struct vg and pack the fields
  298. *  into array buf in preparation for storage in the HDF file.
  299. *
  300. *  NO RETURN VALUES.
  301. */
  302.  
  303. void vpackvg (vg,buf,size)       /*@@*/
  304.  
  305. VGROUP            *vg;        /* vgroup to be saved to file */
  306. unsigned char     buf[];     /* buffer to receive the packed fields */
  307. int               *size;    /* the size of buf is returned here */
  308.  
  309. {
  310.     int              i;
  311.     unsigned     char*b, *bb;
  312.     int16            int16var;
  313.  
  314.     bb = &buf[0];
  315.  
  316.     /* save nvelt */
  317.     b= bb;
  318.     INT16WRITE(b,vg->nvelt);
  319.     bb +=INT16SIZE;
  320.  
  321.  
  322.     /* save all tags */
  323.     for(i=0;i<vg->nvelt;i++) {
  324.         b= bb;
  325.         INT16WRITE(b,vg->tag[i]);
  326.         bb +=INT16SIZE;
  327.     }
  328.  
  329.     /* save all refs */
  330.     for(i=0;i<vg->nvelt;i++) {
  331.         b= bb;
  332.         INT16WRITE(b,vg->ref[i]);
  333.         bb +=INT16SIZE;
  334.     }
  335.  
  336.     /* save the vgnamelen and vgname - omit the null */
  337.     b= bb;
  338.     int16var = strlen(vg->vgname);
  339.     INT16WRITE(b,int16var);
  340.     bb +=INT16SIZE;
  341.  
  342.     strcpy((char*) bb,vg->vgname);
  343.     bb +=  strlen(vg->vgname) ;
  344.  
  345.     /* save the vgclasslen and vgclass- omit the null */
  346.     b= bb;
  347.     int16var = strlen(vg->vgclass);
  348.     INT16WRITE(b,int16var);
  349.     bb +=INT16SIZE;
  350.  
  351.     strcpy((char*) bb,vg->vgclass);
  352.     bb +=  strlen(vg->vgclass) ;
  353.  
  354.     /* save the expansion tag/ref pair */
  355.     b= bb;
  356.     INT16WRITE(b,vg->extag);   /* the vg's expansion tag */
  357.     bb +=INT16SIZE;
  358.  
  359.     b= bb;
  360.     INT16WRITE(b,vg->exref);   /* the vg's expansion ref */
  361.     bb +=INT16SIZE;
  362.  
  363.     /*  save the vg's version field */
  364.     b= bb;
  365.     INT16WRITE(b,vg->version);
  366.     bb +=INT16SIZE;
  367.  
  368.     /* save the vg's more field */
  369.     b= bb;
  370.     INT16WRITE(b,vg->more);
  371.     bb +=INT16SIZE;
  372.  
  373.     if (vjv) {
  374.         sprintf(sjs,"vpackvg: vgname is [%s]\n",vg->vgname);
  375.         zj;
  376.     }
  377.  
  378.     /* returns the size of total fields saved */
  379.     *size = bb - buf + 1;
  380.  
  381.     if (vjv) {
  382.         sprintf(sjs,"#vpackvg: vg->nvelt=%d\n",vg->nvelt);
  383.         zj;
  384.     }
  385.  
  386. } /* vpackvg */
  387.  
  388. /* ==================================================================== */
  389. /*
  390. *    vunpackvg:
  391. *    Unpacks the fields from a buf (ie a VGDESCTAG data object just 
  392. *    read in from the HDF file), into a VGROUP structure vg.
  393. *
  394. *     Will first zero out vg, unpack fields, then inits as much of 
  395. *  vg as it can.
  396. *
  397. *    NO RETURN VALUES
  398. *
  399. */
  400.  
  401. void vunpackvg (vg,buf,size)          /*@@*/
  402.  
  403. VGROUP*              vg;        /* vgroup to be loaded with file data */
  404. unsigned char     buf[];     /* must contain a VGDESCTAG data object from file */
  405.  
  406. int*              size;      /* ignored, but included to look like vpackvg() */
  407.  
  408. {
  409.  
  410.     unsigned char    *b, *bb;
  411.     int                 i;
  412.     int                 int16var;
  413.  
  414.     i = *size; /* dummy, so that compiler thinks it is used  */
  415.  
  416.     bb = &buf[0];
  417.  
  418.     /* retrieve nvelt */
  419.     b = bb;
  420.     INT16READ(b,vg->nvelt);
  421.     bb+=INT16SIZE;
  422.  
  423.     /* retrieve the tags */
  424.     for (i=0;i<vg->nvelt;i++) {
  425.         b= bb;
  426.         INT16READ(b,vg->tag[i]);
  427.         bb +=INT16SIZE;
  428.     }
  429.  
  430.     /* retrieve the refs */
  431.     for (i=0;i<vg->nvelt;i++) {
  432.         b= bb;
  433.         INT16READ(b,vg->ref[i]);
  434.         bb +=INT16SIZE;
  435.     }
  436.  
  437.     /* retrieve vgname (and its len)  */
  438.     b= bb;
  439.     INT16READ(b,int16var);
  440.     bb +=INT16SIZE;
  441.  
  442.     strncpy(vg->vgname, (char*) bb, int16var);
  443.     vg->vgname[int16var] = '\0';
  444.     bb += int16var;
  445.  
  446.     if (vjv) {
  447.         sprintf(sjs,"vunpackvg: vgname is [%s]\n",vg->vgname);
  448.         zj;
  449.     }
  450.  
  451.     /* retrieve vgclass (and its len)  */
  452.     b= bb;
  453.     INT16READ(b,int16var);
  454.     bb +=INT16SIZE;
  455.  
  456.     strncpy(vg->vgclass, (char*) bb, int16var);
  457.     vg->vgclass[int16var] = '\0';
  458.     bb += int16var;
  459.  
  460.     b = bb;
  461.     INT16READ(b,vg->extag); /* retrieve the vg's expansion tag */
  462.     bb += INT16SIZE;
  463.  
  464.     b = bb;
  465.     INT16READ(b,vg->exref); /* retrieve the vg's expansion ref */
  466.     bb += INT16SIZE;
  467.  
  468.     b = bb;
  469.     INT16READ(b,vg->version); /* retrieve the vg's version field */
  470.     bb += INT16SIZE;
  471.  
  472.     b = bb;
  473.     INT16READ(b,vg->more); /* retrieve the vg's more field */
  474.     bb += INT16SIZE;
  475.  
  476.  
  477. } /* vunpackvg */
  478.  
  479.  
  480. /* ------------------------------------------------- */
  481.  
  482.  
  483. /* ==================================================================== */
  484.  
  485. /*
  486. *     Vattach:
  487. *
  488. *   attaches to an existing vgroup or creates a new vgroup.
  489. *     returns NULL if  error, else ptr to vgroup.
  490. *
  491. *    IGNORE accesstype. (but save it)  
  492. *  if vgid == -1,
  493. *      create a NEW vg if vgdir is not full.
  494. *      Also set nattach =1, nentries=0.
  495. *  if vgid +ve, 
  496. *      look in vgdir to see if already attached,
  497. *      if yes, incr nattach 
  498. *      if not, fetch from file. attach, set nattach=1, netries= val from file 
  499. *
  500. *    In any case, set marked flag to 0.
  501. */
  502.  
  503. PUBLIC VGROUP *Vattach (f, vgid, accesstype)     /*@-@*/
  504.  
  505. int         vgid;                 /* actual vgroup's vgid or -1 for new vgroup */
  506. char       *accesstype;     /* ignored */
  507. DF            *f;                 /* HDF file handle */
  508.  
  509. {
  510.     VGROUP            *vg;
  511.     int                 access,  vgpacksize;
  512.     unsigned char     vgpack[sizeof(VGROUP)];
  513.     vginstance_t    * v;
  514.     vfile_t            * vf;
  515.  
  516.  
  517.     if (f==NULL)
  518.         RTNULL("vattach:bad f");
  519.  
  520.     if (NULL==(vf = (vfile_t*) Get_vfile(f)))
  521.         RTNULL ("Vattach: no such file\n");
  522.  
  523.     if      ( accesstype[0]=='R' || accesstype[0]=='r') { 
  524.         access = 'r'; 
  525.     }
  526.     else if ( accesstype[0]=='W' || accesstype[0]=='w') { 
  527.         access = 'w'; 
  528.     }
  529.     else RTNULL("Vattach: bad access type");
  530.  
  531.     if (vgid == -1) {             /******* create a NEW vg in vgdir ******/
  532.  
  533.         if (access=='r') RTNULL("Vattach: don't use r acces with new vg\n");
  534.  
  535.         /* allocate space for vg, & zero it out */
  536.         if ( (vg = (VGROUP*) DFIgetspace(sizeof(VGROUP)) ) == NULL)
  537.             RTNULL("Vattach: cannot getspace\n");
  538.         zerofill ((unsigned char*) vg,sizeof(VGROUP));
  539.  
  540.         /* initialize new vg */
  541.         vg->nvelt         = 0;
  542.         vg->vgname[0]    = '\0';
  543.         vg->f                = f;
  544.         vg->otag         = VGDESCTAG;
  545.         vg->oref            = vnewref(f);  /* create a new unique ref for it */
  546.         vg->access      = access;
  547.  
  548.         vg->marked        = 0;
  549.         vg->vgclass[0]    = '\0';
  550.         vg->extag        = 0;
  551.         vg->exref        = 0;
  552.         vg->more            = 0;
  553.         vg->version        = VSET_VERSION;
  554.  
  555.         if( vg->oref < 0)
  556.             RTNULL("Vattach: no more refs");
  557.  
  558.         /* attach new vg to file's vgtab  */
  559.         if ( NULL == (v = (vginstance_t*) DFIgetspace(sizeof(vginstance_t))))
  560.             RTNULL("Vattach: cannot getspace for vgtab \n");
  561.  
  562.         vf->vgtabtail->next = v;
  563.         vf->vgtabtail          = v;
  564.         vf->vgtabn++;
  565.         v->next                  = NULL;
  566.         v->ref       = vg->oref;
  567.         v->vg          = vg;
  568.         v->nattach    = 1;
  569.         v->nentries    = 0;
  570.  
  571.         return(vg);
  572.     }
  573.  
  574.     else {                             /******* access an EXISTING vg *********/
  575.  
  576.         if (NULL == (v= (vginstance_t*) vginstance (f,vgid)))
  577.             RTNULL("Vattach: vgid not in vgtab");
  578.  
  579.         if (v->vg != NULL) {  /* vg already attached */
  580.             v->nattach++;         /* so, just incr nattach */
  581.             return(v->vg);        /* & return that vg's ptr */
  582.  
  583.         }
  584.  
  585.         /* else vg not attached, must fetch vg from file */
  586.  
  587.         if (-1 ==  DFgetelement(f,VGDESCTAG,vgid,vgpack))
  588.             RTNULL("Vattach: vg  not in file");
  589.  
  590.         /* allocate space for vg, & zero it out */
  591.  
  592.         if (NULL== (vg =(VGROUP*) DFIgetspace(sizeof(VGROUP))) )
  593.             RTNULL("Vattach: cannot getspace\n");
  594.         zerofill((unsigned char*) vg,sizeof(VGROUP));
  595.  
  596.         /* unpack vgpack into structure vg, and init  */
  597.  
  598.         vunpackvg(vg,vgpack,&vgpacksize);
  599.         vg->f                = f;
  600.         vg->oref            = vgid;
  601.         vg->otag         = VGDESCTAG;
  602.         vg->access        = access;
  603.         vg->marked        = 0;
  604.  
  605.         /* attach vg to file's vgtab at the vg instance v */
  606.         v->vg                = vg;
  607.         v->nattach        = 1;
  608.         v->nentries = vg->nvelt;
  609.  
  610.         return(vg);
  611.     }
  612.  
  613.  
  614. } /* Vattach */
  615.  
  616. /* ==================================================================== */
  617. /* 
  618. *    Vdetach
  619. *    Detaches access to vg.    
  620. *    NO RETURN VALUES
  621. *
  622. *  if marked flag is 1, write out vg to file.
  623. *    if vg still has velts attached to it, cannot detach vg.
  624. *    decr  nattach. if (nattach is 0), free vg from vg instance.
  625. *    (check that no velts are still attached to vg before freeing)
  626. *
  627. *  if attached with read access, just return.
  628. *
  629. * after detach, set marked flag to 0.    
  630. *
  631. */
  632.  
  633. PUBLIC void Vdetach (vg)             /*@-@*/
  634.  
  635. VGROUP *vg;
  636. {
  637.  
  638.     int              i,vgpacksize;
  639.     unsigned char vgpack[sizeof(VGROUP)];
  640.     vginstance_t * v;
  641.  
  642.     if (vg==NULL) return;
  643.     if (vg->otag != VGDESCTAG) return;
  644.  
  645.     /* locate vg's index in vgtab */
  646.     if (NULL ==( v = (vginstance_t*) vginstance (vg->f,vg->oref))) {
  647.         sprintf(sjs,"@Vdetach: vg not found\n");
  648.         zj;
  649.         return;
  650.     }
  651.  
  652.     /* update vgroup to file if it has write-access */
  653.  
  654.     /* if its marked flag is 1 */
  655.     /* - OR - */
  656.     /* if that vgroup is empty */
  657.     if (vg->access == 'w') {
  658.         if ((vg->nvelt==0) || (vg->marked == 1)) {
  659.             if (vjv) {
  660.                 sprintf(sjs,"@VDETACH: added %d entries in vg..update vg to file\n",
  661.                     vg->nvelt - v->nentries);
  662.                 zj;
  663.             }
  664.             vpackvg(vg,vgpack,&vgpacksize);
  665.             if (DFputelement(vg->f,VGDESCTAG,vg->oref,vgpack,vgpacksize) == -1)
  666.                 sprintf(sjs,"@Vdetach: putelement error\n"); 
  667.             zj;
  668.             vg->marked = 0;
  669.             return;
  670.         }
  671.     }
  672.  
  673.     v->nattach--;
  674.     if (vjv) {
  675.         sprintf(sjs,"#Vdetach: nattach is now %d\n", v->nattach);
  676.         zj;
  677.     }
  678.  
  679.     if (v->nattach > 0)
  680.         return;    /* ok */
  681.  
  682.  
  683.     /* else, we can detach and remove vg from file's vgtab  */
  684.  
  685.     for (i=0;i<vg->nvelt;i++)       /* check if vg still has attached entries */
  686.         if (vg->velt[i] != NULL) {
  687.             sprintf(sjs,"@Vdetach: vg has vs %d undetached! continuing. \n",i);
  688.             zj;
  689.             break;
  690.         }
  691.  
  692.     v->vg = NULL;              /* detach vg from vgdir */
  693.  
  694.     DFIfreespace(vg);
  695.  
  696.     return; /* ok */
  697.  
  698. } /* Vdetach */
  699.  
  700.  
  701. /* ==================================================================== */
  702. /*
  703. *    Vinsert
  704. *  inserts a velt (vs or vg)  into a vg 
  705. *    RETURNS entry position within vg (0 or +ve) or -1 on error.
  706. *
  707. *    checks and prevents duplicate links.
  708. *
  709. * Since multiple files are now possible, check that both vg and velt
  710. * are from the same file. else error.
  711. */
  712.  
  713. PUBLIC int Vinsert (vg,velt)             /*@-@*/
  714.  
  715. VGROUP    *vg;
  716. VDATA     *velt;            /* (VGROUP*) or (VDATA*), doesn't matter */
  717.  
  718. {
  719.     int i;
  720.     char ss[80];
  721.  
  722.     if (vg == NULL || velt == NULL) return(FAIL);
  723.     if (vg->otag != VGDESCTAG || vg->nvelt >= MAXNVELT) return(FAIL);
  724.  
  725.     if ( (vfile_t*) Get_vfile(vg->f) != (vfile_t*) Get_vfile(velt->f) )
  726.         RTNEG("Vinsert: vg and velt not in same file\n");
  727.  
  728.     /* check in vstab  (kkk!!)  or vgtab that velt actually exist in file */
  729.  
  730.     switch (velt->otag) {
  731.     case VSDESCTAG:
  732.         if (-1 == vexistvs (vg->f,velt->oref))
  733.             RTNEG("@Vinsert vs doesn't exist\n");
  734.         break;
  735.  
  736.     case VGDESCTAG:
  737.         if (-1 == vexistvg (vg->f,velt->oref))
  738.             RTNEG("@Vinsert: vg doesn't exist\n");
  739.         break;
  740.  
  741.     default:
  742.         RTNEG("@Vinsert: unknown element\n");
  743.         break;
  744.     } /* switch */
  745.  
  746.     /* check and prevent duplicate links */
  747.     for(i=0;i<vg->nvelt;i++)
  748.         if ( (vg->tag[i] == velt->otag) && (vg->ref[i] == velt->oref) ) {
  749.             sprintf(ss,"@Vinsert: duplicate link <%d/%d>\n", 
  750.                 velt->otag,velt->oref);
  751.             RTNEG(ss);
  752.         }
  753.  
  754.     /* Finally, ok to insert */
  755.     vinsertpair ( vg, velt->otag, velt->oref);
  756.  
  757.     if (vjv) {
  758.         sprintf(sjs,"#Vinsert:inserted <%d/%d> at nvelt=%d\n",
  759.             velt->otag, velt->oref, vg->nvelt);
  760.         zj;
  761.     }
  762.  
  763.     vg->marked = 1;
  764.     return(vg->nvelt - 1);
  765.  
  766. } /* Vinsert */
  767.  
  768. /* ------------------------------------------------------------------ */
  769. /*
  770. Checks to see if the given field exists in a vdata belonging to this vgroup.
  771. If found, returns the ref of the vdata.
  772. If not found, or error, returns -1.
  773. 28-MAR-91 Jason Ng NCSA
  774. */
  775.  
  776. PUBLIC int Vflocate (vg, field)
  777. VGROUP * vg;
  778. char * field;
  779. {
  780.     int     i, s;
  781.     VDATA *vs;
  782.  
  783.     for (i=0;i<vg->nvelt;i++)  {
  784.         if (vg->tag[i] != VSDESCTAG) continue;
  785.         vs = (VDATA*) VSattach (vg->f,vg->ref[i],"r"); 
  786.         if (vs==NULL) return (-1);
  787.         s = VSfexist (vs, field);
  788.         VSdetach (vs);
  789.         if (s==1) return (vg->ref[i]); /* found. return vdata's ref */
  790.     }
  791.  
  792.     return (-1); /* field not found */
  793.  
  794. } /* Vflocate */
  795.  
  796. /* ------------------------------------------------------------------ */
  797. /*
  798. * Checks whether the given tag/ref pair already exists in the vgroup.
  799. * RETURNS 1 if exist
  800. * RETURNS 0 if not.
  801. * 28-MAR-91 Jason Ng NCSA
  802. */
  803. PUBLIC int Vinqtagref ( vg, tag, ref)
  804. VGROUP * vg;
  805. int tag, ref;
  806. {
  807.     int i;
  808.  
  809.     for (i=0; i<vg->nvelt; i++)
  810.         if ( (tag== vg->tag[i]) && (ref== vg->ref[i]) ) return (1); /* exist */
  811.  
  812.     return (0); /* does not exist */
  813.  
  814. } /* Vinqtagref */
  815.  
  816. /* ------------------------------------------------------------------ */
  817. /*
  818. * Returns the number (0 or +ve integer) of tag/ref pairs in a vgroup.
  819. * If error, returns -1.
  820. * 28-MAR-91 Jason Ng NCSA.
  821. */
  822.  
  823. PUBLIC int Vntagrefs (vg)
  824. VGROUP * vg;
  825. {
  826.     return ( (vg->otag==VGDESCTAG) ? vg->nvelt: -1);
  827. } /* Vntagrefs */
  828.  
  829. /* ------------------------------------------------------------------ */
  830. /*
  831. * Returns n tag/ref pairs from the vgroup into the caller-supplied arrays
  832. * tagrarray and refarray.
  833. * n can be any +ve number, but arrays must be this big.
  834. * RETURNS the total number of (0 or +ve #)  tag/ref pairs returned.
  835. * RETURNS -1 if error.
  836. * 28-MAR-91 Jason Ng NCSA.
  837. *
  838. * NOTE: Do not confuse with Vgettagref().
  839. *
  840. */
  841.  
  842. PUBLIC int Vgettagrefs (vg, tagarray, refarray, n)
  843. VGROUP * vg;
  844. int n;
  845. int tagarray[], refarray[];
  846.  
  847. {
  848.     int i, ntagrefs;
  849.  
  850.     if ( n <= vg->nvelt) ntagrefs = n;
  851.     else n = vg->nvelt;
  852.  
  853.     for (i=0; i<ntagrefs; i++) {
  854.         tagarray[i] = vg->tag[i];
  855.         refarray[i] = vg->ref[i];
  856.     }
  857.  
  858.     return (ntagrefs);
  859. } /* Vgettagrefs */
  860.  
  861. /* ------------------------------------------------------------------ */
  862. /*
  863. * Returns a specified tag/ref pair from the vgroup.
  864. * User specifies an index. 
  865. * RETURNS 1 if OK.
  866. * RETURNS -1 if error.
  867. * 12-MAY-91 Jason Ng NCSA.
  868. *
  869. * NOTE: Do not confuse with Vgettagrefs().
  870. *
  871. */
  872.  
  873. PUBLIC int Vgettagref (vg, which, tag, ref)
  874. VGROUP * vg;
  875. int which;
  876. int *tag, *ref; /* these are returned */
  877.  
  878. {
  879.  
  880.     if (vg==NULL) return (-1);
  881.     if (which < 0 || which > vg->nvelt-1) return (-1); /* range err */
  882.  
  883.         *tag  = vg->tag[which];
  884.         *ref  = vg->ref[which];
  885.     return (1); /* ok */
  886.  
  887. } /* Vgettagref */
  888. /* ------------------------------------------------------------------ */
  889. /*
  890. * Inserts a tag/ref pair into the attached vgroup vg.
  891. * First checks that the tag/ref is unique.
  892. * If error, returns -1 or tag/ref is not inserted.
  893. * If OK, returns the total number of tag/refs in the vgroup (a +ve integer).
  894. * 28-MAR-91 Jason Ng NCSA.
  895. */
  896.  
  897. PUBLIC int Vaddtagref ( vg, tag, ref)
  898. VGROUP * vg;
  899. int tag, ref;
  900. {
  901.     int  n;
  902.  
  903.     if (Vinqtagref (vg, tag, ref) == 1) return (-1); /* error, already exists */
  904.     n = vinsertpair (vg, tag, ref);
  905.     return (n);
  906. } /* Vaddtagref */
  907.  
  908. /* ------------------------------------------------------------------ */
  909. /*
  910. * Inserts a tag/ref pair into the attached vgroup vg.
  911. * Does not check for errors. 
  912. * Returns the total number of tag/refs in theat vgroup.
  913. */
  914.  
  915. int vinsertpair ( vg, tag, ref)
  916. VGROUP    * vg;
  917. int        tag, ref;
  918. {
  919.     vg->velt[vg->nvelt]  = NULL;
  920.     vg->tag[vg->nvelt]   = tag;
  921.     vg->ref[vg->nvelt]   = ref;
  922.     vg->nvelt ++;
  923.  
  924.     vg->marked = 1;
  925.     return (vg->nvelt);
  926. }
  927.  
  928. /* ==================================================================== */
  929. /* 
  930. *     Ventries
  931. *    returns the no of entries (+ve integer) in the vgroup vgid.
  932. *  vgid must be an actual id
  933. *  RETURNS -1 if error
  934. *
  935. *  undocumented
  936. *
  937. */
  938.  
  939. int Ventries (f,vgid)                 /*@@*/
  940.  
  941. DF* f;
  942. int vgid;
  943. {
  944.     unsigned char vgpack[sizeof(VGROUP)];
  945.     VGROUP vg;
  946.     int    vgpacksize;
  947.  
  948.     if (vgid < 1) return(FAIL);
  949.     if ( DFgetelement(f,VGDESCTAG ,vgid,vgpack) == -1) {
  950.         sprintf(sjs,"@Ventries: cannot get vg from file\n");
  951.         zj;
  952.         return(FAIL);
  953.     }
  954.  
  955.     vunpackvg(&vg,vgpack,&vgpacksize);
  956.     return(vg.nvelt);
  957.  
  958. } /* Ventries */
  959.  
  960.  
  961. /* ==================================================================== */
  962. /*
  963. *    Vsetname
  964. *     gives a name to the VGROUP vg.
  965. *
  966. * NO RETURN VALUES.
  967. *
  968. *    truncates to max length of VGNAMELENMAX 
  969. */
  970.  
  971. PUBLIC void Vsetname (vg, vgname)         /*@-@*/
  972.  
  973. VGROUP    *vg;
  974. char        *vgname;
  975.  
  976. {
  977.     if (vg == NULL) return;
  978.     if ( strlen(vgname) > VGNAMELENMAX) {
  979.         strncpy(vg->vgname, vgname,VGNAMELENMAX);
  980.         vg->vgname[VGNAMELENMAX]='\0';
  981.     }
  982.     else
  983.         strcpy(vg->vgname, vgname);
  984.     vg->marked = 1;
  985.     return;
  986.  
  987. } /* Vsetname */
  988.  
  989. /* ==================================================================== */
  990. /*
  991. *    Vsetclass
  992. *     assigns a class name to the VGROUP vg.
  993. *
  994. * NO RETURN VALUES.
  995. *
  996. *    truncates to max length of VGNAMELENMAX 
  997. */
  998.  
  999. PUBLIC void Vsetclass (vg, vgclass)         /*@-@*/
  1000.  
  1001. VGROUP    *vg;
  1002. char        *vgclass;
  1003.  
  1004. {
  1005.     if (vg == NULL) return;
  1006.     if ( strlen(vgclass) > VGNAMELENMAX) {
  1007.         strncpy(vg->vgclass, vgclass,VGNAMELENMAX);
  1008.         vg->vgclass[VGNAMELENMAX]='\0';
  1009.     }
  1010.     else
  1011.         strcpy(vg->vgclass, vgclass);
  1012.     vg->marked = 1;
  1013.     return;
  1014.  
  1015. } /* Vsetclass*/
  1016.  
  1017.  
  1018. /* ======================================================= */
  1019. /*
  1020. *     Visvg
  1021. *    tests if an entry in the vgroup vg is a VGROUP, given the entry's id. 
  1022. *
  1023. *    RETURNS 1 if so
  1024. *    RETURNS 0 if not, or if error
  1025. *
  1026. */
  1027.  
  1028. PUBLIC int Visvg (vg,id)           /*@-@*/
  1029.  
  1030. VGROUP    *vg;
  1031. int         id;        /* valid id of the entry in question */
  1032. {
  1033.     int     i;
  1034.  
  1035.     for(i=0;i<vg->nvelt;i++)
  1036.         if (vg->ref[i] == id   &&      /* if the ids match, */
  1037.         vg->tag[i]==VGDESCTAG)     /* and it is a vgroup */
  1038.             return (1);
  1039.  
  1040.     return (0);
  1041.  
  1042. } /* Visvg */
  1043.  
  1044. /* ======================================================= */
  1045. /* 
  1046. *    Vgetid
  1047. *    
  1048. *    Given a vgroup's id, returns the next vgroup's id in the file f .
  1049. *    The call Vgetid(f,-1) returns the id of the FIRST vgroup in the file. 
  1050. *
  1051. *    RETURNS -1 if error
  1052. *    RETURNS the next vgroup's id (0 or +ve integer).
  1053. *
  1054. *    This id is actually the "ref" of the vgroup "tag/ref".
  1055. */
  1056.  
  1057. PUBLIC int Vgetid (f,vgid)               /*@-@*/
  1058.  
  1059. int     vgid;                    /* current vgid */
  1060. DF*     f;                        /* HDF file handle */
  1061.  
  1062. {
  1063.     vginstance_t * v;
  1064.     vfile_t        * vf;
  1065.  
  1066.     if ( vgid < -1) return(FAIL);
  1067.  
  1068.     if (NULL==(vf = (vfile_t*) Get_vfile(f)))
  1069.         RTNEG ("Vgetid: no such file\n");
  1070.  
  1071.     if (vjv) {
  1072.         sprintf(sjs,"#Vgetid:vgtabn= %d vgid=%d\n",vf->vgtabn,vgid);
  1073.         zj;
  1074.     }
  1075.  
  1076.     if (vgid == -1) {
  1077.         if (NULL == vf->vgtab.next)
  1078.             return (-1);
  1079.         else
  1080.             return( (vf->vgtab.next)->ref); /* rets 1st vgroup's ref */
  1081.     }
  1082.  
  1083.     /* look in vgtab for vgid */
  1084.     v = (vf->vgtab).next;
  1085.     while(NULL != v) {
  1086.         if(v->ref == vgid) break;
  1087.         v = v->next;
  1088.     }
  1089.     if (v==NULL)
  1090.         return (FAIL); /* none found */
  1091.     else
  1092.         if( v->next ==NULL)
  1093.             return (FAIL); /* this is the last vg, no more after it */
  1094.         else
  1095.             return((v->next)->ref); /* success, return the next vg's ref */
  1096.  
  1097. } /* Vgetid */
  1098.  
  1099.  
  1100. /* ================================================================= */
  1101. /*
  1102. *    Vgetnext
  1103. *
  1104. *    Given the id of an entry from a vgroup vg, looks in vg for the next
  1105. *    entry after it, and returns its id.
  1106. *    The call Vgetnext (vg,-1) returns the id of the FIRST entry in the vgroup.
  1107. *
  1108. *  Vgetnext will look at only VSET elements in the vgroup.
  1109. *  To look at all links in a vgroup, use Vgettagrefs instead.
  1110. *
  1111. *    RETURNS -1 if error
  1112. *    RETURNS the id of the next entry( 0 or +ve integer)  in the vgroup.
  1113. *
  1114. *    This id is actually the "ref" of the entry's "tag/ref".
  1115. *
  1116. */
  1117.  
  1118. PUBLIC int Vgetnext (vg,id)           /*@-@*/
  1119.  
  1120. VGROUP    *vg;
  1121. int         id;                    /* actual id of an entry in the vgroup vg */
  1122. {
  1123.     int     i;
  1124.  
  1125.     if (id < -1) return(FAIL);
  1126.     if (vg == NULL) return(FAIL);
  1127.     if (vg->otag != VGDESCTAG) return(FAIL);
  1128.  
  1129.     if (vjv) {
  1130.         sprintf(sjs,"#Vgetnext:vg->nvelt is %d\n",vg->nvelt);
  1131.         zj;
  1132.     }
  1133.     if (vg->nvelt  == 0) return(FAIL);             /* nothing in vg */
  1134.  
  1135.     if (id == -1) {
  1136.         if ((vg->tag[0]==VGDESCTAG) || (vg->tag[0]==VSDESCTAG)) 
  1137.                 return(vg->ref[0]);         /* id of first entry */
  1138.         }
  1139.     
  1140.     /* look in vg for id */
  1141.     for(i=0;i<vg->nvelt;i++) 
  1142.         if ((vg->tag[i]==VGDESCTAG) || (vg->tag[i]==VSDESCTAG)) {
  1143.             if(vg->ref[i] == id) {
  1144.                 if (i == (vg->nvelt - 1) )
  1145.                     return(FAIL);
  1146.                 else  {
  1147.                     if ((vg->tag[i+1]==VGDESCTAG) ||
  1148.                          (vg->tag[i+1]==VSDESCTAG)) 
  1149.                         return(vg->ref[i+1]);        /* return the id of next entry */
  1150.                     else  return (-1); 
  1151.                     }
  1152.             }
  1153.         }
  1154.  
  1155.     return (FAIL);
  1156.  
  1157. } /* Vgetnext  */
  1158.  
  1159. /* ================================================================= */
  1160. /*
  1161. *    Vgetname
  1162. *    returns the vgroup's name
  1163. *
  1164. */
  1165.  
  1166. PUBLIC void Vgetname (vg, vgname)          /*@-@*/
  1167.  
  1168. VGROUP    *vg;
  1169. char        *vgname;                /* its name is returned in this var */
  1170. {
  1171.     if(vg != NULL) strcpy(vgname, vg->vgname);
  1172.     return;
  1173.  
  1174. } /* Vgetname */
  1175. /* ================================================================= */
  1176. /*
  1177. *    Vgetclass
  1178. *    returns the vgroup's class name 
  1179. *
  1180. */
  1181.  
  1182. PUBLIC void Vgetclass (vg, vgclass)          /*@-@*/
  1183.  
  1184. VGROUP    *vg;
  1185. char        *vgclass;                /* its class name is returned in this var */
  1186. {
  1187.     if(vg != NULL) strcpy(vgclass, vg->vgclass);
  1188.     return;
  1189.  
  1190. } /* Vgetclass*/
  1191.  
  1192. /* ================================================================= */
  1193. /*
  1194. *    Vinquire
  1195. *
  1196. *    General inquiry routine for VGROUP. 
  1197. *
  1198. *    output parameters:
  1199. *            nentries - no of entries in the vgroup
  1200. *            vgname    - the vgroup's name
  1201. *
  1202. *    RETURNS -1 if error
  1203. *    RETURNS 1 if ok
  1204. *
  1205. */
  1206.  
  1207. PUBLIC int Vinquire (vg, nentries, vgname)     /*@-@*/
  1208.  
  1209. VGROUP    *vg;
  1210. char        *vgname;
  1211. int         *nentries;
  1212. {
  1213.     if (vg == NULL) return(FAIL);
  1214.     if (vg->otag != VGDESCTAG) return(FAIL);
  1215.  
  1216.     strcpy(vgname, vg->vgname);
  1217.     *nentries = vg->nvelt;
  1218.  
  1219.     return(1); /* ok */
  1220.  
  1221. } /* Vinquire */
  1222.  
  1223. /* ================================================================= */
  1224.  
  1225.