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