1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF.  The full HDF copyright notice, including       *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /* $Id$ */
15 
16 /*-----------------------------------------------------------------------------
17  * File:     dfan.c
18  * Purpose:  read and write annotations: labels and descriptions of data items
19  * Invokes:  df.c
20  * Contents:
21  *
22  *  DFANclear:      - reset DFAN interface
23  *  DFANgetlablen:  - get length of label of tag/ref
24  *  DFANgetlabel:   - get label of tag/ref
25  *  DFANgetdesclen: - get length of description of tag/ref
26  *  DFANgetdesc:    - get description of tag/ref
27  *
28  *  DFANgetfidlen:  - get length of file ID
29  *  DFANgetfid:     - get file ID
30  *  DFANgetfdslen:  - get length of file description
31  *  DFANgetfds:     - get file description
32  *
33  *  DFANputlabel:   - put label of tag/ref
34  *  DFANputdesc:    - put description of tag/ref
35  *
36  *  DFANaddfid:     - add file ID
37  *  DFANaddfds:     - add file description
38  *
39  *  DFANlastref:    - return ref of last annotation read or written
40  *  DFANlablist:    - get list of labels for a particular tag
41  *
42  *  DFANIclear:     - clear Lastref, label/desc entries and directories
43  *  DFANIopen:      - open/reopen file
44  *  DFANIlocate:    - return ref of label/desc of tag/ref
45  *  DFANIaddentry:  - add entry in annotation directory
46  *  DFANIgetannlen: - get length of annotation of tag/ref
47  *  DFANIgetann:    - get annotation of tag/ref
48  *  DFANIputann:    - put annotation of tag/ref
49  *  DFANIlablist:   - get list of labels for a particular tag
50  *
51  *  DFANIaddfann:   - add file annotation (ID or description)
52  *  DFANIgetfannlen: - get length of file annotation
53  *  DFANIgetfann:    - get file annotation
54  *---------------------------------------------------------------------------*/
55 
56 #include "hdf.h"
57 #include "dfan.h"
58 PRIVATE uint16 Lastref = 0;     /* Last ref read/written */
59 PRIVATE uint16 Next_label_ref = 0;  /* Next file label ref to read/write */
60 PRIVATE uint16 Next_desc_ref = 0;   /* Next file desc ref to read/write */
61 
62 #if 0
63 static char Lastfile[DF_MAXFNLEN] = "";     /* last file opened */
64 #endif
65 PRIVATE char *Lastfile = NULL;
66 
67 /* pointers to directories of object annotations */
68 PRIVATE DFANdirhead *DFANdir[2] =
69 {NULL,                          /* object labels       */
70  NULL                           /* object descriptions */
71 };
72 
73 /* Whether we've installed the library termination function yet for this interface */
74 PRIVATE intn library_terminate = FALSE;
75 
76 /*
77    ** Prototypes for local functions
78  */
79 
80 PRIVATE int32 DFANIopen(const char *filename, intn acc_mode);
81 PRIVATE intn DFANIstart(void);
82 
83 /*-----------------------------------------------------------------------------
84  * HDF object (i.e. tag/ref) label and description input routines
85  *---------------------------------------------------------------------------*/
86 
87 /*-----------------------------------------------------------------------------
88  NAME
89        DFANgetlablen -- get length of label of tag/ref
90  USAGE
91        int32 DFANgetlablen(filename, tag, ref)
92        char *filename;     IN: filename: name of HDF file
93        uint16 tag;         IN: tag of data object assigned the label
94        uint16 ref;         IN: reference number of the data object assigned
95                                the label
96  RETURNS
97        length of label on success, FAIL (-1) otherwise
98  DESCRIPTION
99        Calls DFANIgetannlen to get label length.
100  GLOBAL VARIABLES
101  COMMENTS, BUGS, ASSUMPTIONS
102        This routine should be used to insure that there is enough space
103        allocated for a label before actually reading it.
104  EXAMPLES
105  REVISION LOG
106  *---------------------------------------------------------------------------*/
107 int32
DFANgetlablen(const char * filename,uint16 tag,uint16 ref)108 DFANgetlablen(const char *filename, uint16 tag, uint16 ref)
109 {
110   int32 ret_value;
111 
112   ret_value = (DFANIgetannlen(filename, tag, ref, DFAN_LABEL));
113 
114   return ret_value;
115 }
116 
117 /*--------------------------------------------------------------------------
118  NAME
119        DFANgetlabel -- get label of object identified by tag/ref
120  USAGE
121        int DFANgetlabel(filename, tag, ref, label, maxlen)
122        char *filename;   IN: name of HDF file
123        uint16 tag;       IN: tag of object of assigned the label
124        uint16 ref;       IN: ref number of object of assigned the label
125        char *label;      OUT: buffer allocated to hold the label
126        int32 maxlen;     IN: size of buffer allocated to hold the label
127  RETURNS
128        SUCCEED (0) if successful and FAIL (-1) otherwise
129  DESCRIPTION
130        Invokes DFANIgetann to get label
131  GLOBAL VARIABLES
132  COMMENTS, BUGS, ASSUMPTIONS
133        The value of maxlen must be at least one greater than the
134        anticipated length of the label, because a NULL byte is appended
135        to the annotation
136  EXAMPLES
137  REVISION LOG
138  *---------------------------------------------------------------------------*/
139 intn
DFANgetlabel(const char * filename,uint16 tag,uint16 ref,char * label,int32 maxlen)140 DFANgetlabel(const char *filename, uint16 tag, uint16 ref, char *label,
141              int32 maxlen)
142 {
143   intn ret_value;
144 
145   ret_value = (DFANIgetann(filename, tag, ref, (uint8 *) label, maxlen, DFAN_LABEL, 0));
146 
147   return ret_value;
148 }
149 
150 /*--------------------------------------------------------------------------
151  NAME
152        DFANgetdesclen -- get length of description of tag/ref
153  USAGE
154        int32 DFANgetdesclen(filename, tag, ref)
155        char *filename;  IN: name of HDF file
156        uint16 tag;      IN: tag of item of which we want description
157        uint16 ref;      IN: ref number of item of which we want description
158  RETURNS
159        Length of description if successful, and FAIL (-1) otherwise
160  DESCRIPTION
161        Calls DFANIgetannlen to get description length
162  GLOBAL VARIABLES
163  COMMENTS, BUGS, ASSUMPTIONS
164        This routine should be used to insure that there is enough space
165        allocated for a description before actually reading it.
166  EXAMPLES
167  REVISION LOG
168  *------------------------------------------------------------------------*/
169 int32
DFANgetdesclen(const char * filename,uint16 tag,uint16 ref)170 DFANgetdesclen(const char *filename, uint16 tag, uint16 ref)
171 {
172   int32 ret_value;
173 
174   ret_value = (DFANIgetannlen(filename, tag, ref, DFAN_DESC));
175 
176   return ret_value;
177 }
178 
179 /*--------------------------------------------------------------------------
180  NAME
181        DFANgetdesc -- Reads the description assigned to the data object
182                       with the given tag and reference number.
183  USAGE
184        int DFANgetdesc(filename, tag, ref, desc, maxlen)
185        char * filename; IN: name of HDF file
186        uint16 tag;      IN: tag of object of assigned the label
187        uint16 ref;      IN: ref number of object of assigned the label
188        char *desc;      OUT: buffer allocated to hold the description
189        int32 maxlen;    IN: size of buffer allocated to hold the description
190  RETURNS
191        SUCCEED (0) if successful and FAIL (-1) otherwise
192  DESCRIPTION
193        Invokes DFANIgetann to get description
194  GLOBAL VARIABLES
195  COMMENTS, BUGS, ASSUMPTIONS
196        The value of maxlen must be at least one greater than the
197        anticipated length of the description, because a NULL byte is
198        appended to the annotation
199  EXAMPLES
200  REVISION LOG
201  *------------------------------------------------------------------------*/
202 
203 intn
DFANgetdesc(const char * filename,uint16 tag,uint16 ref,char * desc,int32 maxlen)204 DFANgetdesc(const char *filename, uint16 tag, uint16 ref, char *desc,
205             int32 maxlen)
206 {
207   intn ret_value;
208 
209   ret_value = (DFANIgetann(filename, tag, ref, (uint8 *) desc, maxlen, DFAN_DESC, 0));
210 
211   return ret_value;
212 }
213 
214 /*-----------------------------------------------------------------------------
215  * File ID and description input routines
216  *---------------------------------------------------------------------------*/
217 
218 /*--------------------------------------------------------------------------
219  NAME
220        DFANgetfidlen -- get length of file label
221  USAGE
222        int32 DFANgetfidlen(file_id, isfirst)
223        int32 file_id;    IN: HDF file label returned by Hopen
224        int isfirst;      IN: 1 to read the first label in the file
225                              0 to read the next label in the file
226  RETURNS
227        Length of file label if successful, and FAIL (-1) otherwise
228  DESCRIPTION
229        Calls DFANIgetfannlen to get label length
230  GLOBAL VARIABLES
231  COMMENTS, BUGS, ASSUMPTIONS
232        When first called for a given file, DFANgetfidlen returns the
233        length of the first file label.  In order to get the lengths
234        of successive labels, you must call DFANgetfid between calls
235        to DFANgetfidlen.  Otherwise, successive calls to DFANgetfidlen
236        will return the length of the same file label.
237  EXAMPLES
238  REVISION LOG
239  *------------------------------------------------------------------------*/
240 int32
DFANgetfidlen(int32 file_id,int isfirst)241 DFANgetfidlen(int32 file_id, int isfirst)
242 {
243   int32 ret_value;
244 
245   ret_value = (DFANIgetfannlen(file_id, DFAN_LABEL, isfirst));
246 
247   return ret_value;
248 }
249 
250 /*--------------------------------------------------------------------------
251  NAME
252        DFANgetfid -- get next file label
253  USAGE
254        int32 DFANgetfid(file_id, label, maxlen, isfirst)
255        int32 file_id;   IN: HDF file label returned by Hopen
256        char *label;     OUT: buffer allocated to hold the label
257        int32 maxlen;    IN: size of buffer allocated to hold the label
258        int isfirst;     IN: 0 to read the next label in the file;
259                             1 to read the first label in the file
260  RETURNS
261        On success, length of label; FAIL (-1) otherwise
262  DESCRIPTION
263        Invokes DFANIgetfann to get label
264  GLOBAL VARIABLES
265  COMMENTS, BUGS, ASSUMPTIONS
266        If maxlen is not great enough, the label is truncated to
267        maxlen-1 characters.
268  EXAMPLES
269  REVISION LOG
270  *---------------------------------------------------------------------------*/
271 int32
DFANgetfid(int32 file_id,char * label,int32 maxlen,intn isfirst)272 DFANgetfid(int32 file_id, char *label, int32 maxlen, intn isfirst)
273 {
274   int32 ret_value;
275 
276   ret_value = (DFANIgetfann(file_id, label, maxlen, DFAN_LABEL, isfirst));
277 
278   return ret_value;
279 }
280 
281 /*--------------------------------------------------------------------------
282  NAME
283        DFANgetfdslen -- get length of file description
284  USAGE
285        int32 DFANgetfdslen(file_id, isfirst)
286        int32 file_id;    IN: HDF file description returned by Hopen
287        int isfirst;      IN: 1 to read the first description in the file
288                              0 to read the next description in the file
289  RETURNS
290        Length of file description if successful, and FAIL (-1) otherwise
291  DESCRIPTION
292        Calls DFANIgetfannlen to get description length
293  GLOBAL VARIABLES
294  COMMENTS, BUGS, ASSUMPTIONS
295        When first called for a given file, DFANgetfdslen returns the
296        length of the first file description.  In order to get the lengths
297        of successive descriptions, you must call DFANgetfds between calls
298        to DFANgetfdslen.  Otherwise, successive calls to DFANgetfdslen
299        will return the length of the same file description.
300  EXAMPLES
301  REVISION LOG
302  *------------------------------------------------------------------------*/
303 int32
DFANgetfdslen(int32 file_id,intn isfirst)304 DFANgetfdslen(int32 file_id, intn isfirst)
305 {
306   int32 ret_value;
307 
308   ret_value = (DFANIgetfannlen(file_id, DFAN_DESC, isfirst));
309 
310   return ret_value;
311 }
312 
313 /*--------------------------------------------------------------------------
314  NAME
315        DFANgetfds -- get next file description
316  USAGE
317        int32 DFANgetfds(file_id, desc, maxlen, isfirst)
318        int32 file_id;  IN: HDF file description returned by Hopen
319        char *desc;     OUT: buffer allocated to hold the description
320        int32 maxlen;   IN: size of buffer allocated to hold the description
321        int isfirst;    IN: 0 to read the next description in the file;
322                            1 to read the first description in the file
323  RETURNS
324        On success, length of description; FAIL (-1) otherwise
325  DESCRIPTION
326        Invokes DFANIgetfann to get description
327  GLOBAL VARIABLES
328  COMMENTS, BUGS, ASSUMPTIONS
329        If maxlen is not great enough, the description is truncated to
330        maxlen-1 characters.
331  EXAMPLES
332  REVISION LOG
333  *---------------------------------------------------------------------------*/
334 int32
DFANgetfds(int32 file_id,char * desc,int32 maxlen,intn isfirst)335 DFANgetfds(int32 file_id, char *desc, int32 maxlen, intn isfirst)
336 {
337   int32 ret_value;
338 
339   ret_value = (DFANIgetfann(file_id, desc, maxlen, DFAN_DESC, isfirst));
340 
341   return ret_value;
342 }
343 
344 /*-----------------------------------------------------------------------------
345  * HDF object (i.e. tag/ref) label and description output routines
346  *---------------------------------------------------------------------------*/
347 
348 /*--------------------------------------------------------------------------
349  NAME
350        DFANputlabel -- Assign a label to the data object with the given
351                        tag and reference number
352  USAGE
353        int DFANputlabel(filename, tag, ref, label)
354        char *filename;  IN: name of HDF file
355        uint16 tag;      IN: tag of item to be assigned the label
356        uint16 ref;      IN: reference number of item to be assigned the label
357        char *label;     IN: label to write to file; a single string of
358                             NULL-terminated text
359  RETURNS
360        SUCCEED (0) if successful and FAIL (-1) otherwise
361  DESCRIPTION
362        Invokes DFANIgetfann to write out label
363  GLOBAL VARIABLES
364  COMMENTS, BUGS, ASSUMPTIONS
365  EXAMPLES
366  REVISION LOG
367  *------------------------------------------------------------------------*/
368 intn
DFANputlabel(const char * filename,uint16 tag,uint16 ref,char * label)369 DFANputlabel(const char *filename, uint16 tag, uint16 ref, char *label)
370 {
371   intn ret_value;
372 
373   ret_value = (DFANIputann(filename, tag, ref, (uint8 *) label,
374                            (int32) HDstrlen(label), DFAN_LABEL));
375 
376   return ret_value;
377 }
378 
379 /*--------------------------------------------------------------------------
380  NAME
381        DFANputdesc -- Assign a description to the data object with the given
382                       tag and reference number
383  USAGE
384        int DFANputdesc(filename, tag, ref, desc, desclen)
385        char *filename;   IN: name of HDF file
386        uint16 tag;       IN: tag of item to be assigned the description
387        uint16 ref;       IN: ref number of item to be assigned description
388        char *desc;       IN: description to write to file; a single string
389                              of NULL-terminated text
390        int32 desclen;  IN: length of description
391  RETURNS
392        SUCCEED (0) if successful and FAIL (-1) otherwise
393  DESCRIPTION
394        Invokes DFANIgetfann to write out description
395  GLOBAL VARIABLES
396  COMMENTS, BUGS, ASSUMPTIONS
397        The parameter desc can contain any sequence of ASCII characters.
398        It does not have to be a string.
399  EXAMPLES
400  REVISION LOG
401  *------------------------------------------------------------------------*/
402 intn
DFANputdesc(const char * filename,uint16 tag,uint16 ref,char * desc,int32 desclen)403 DFANputdesc(const char *filename, uint16 tag, uint16 ref, char *desc,
404             int32 desclen)
405 {
406   intn ret_value;
407 
408   ret_value = (DFANIputann(filename, tag, ref, (uint8 *) desc, desclen, DFAN_DESC));
409 
410   return ret_value;
411 }
412 
413 /*-----------------------------------------------------------------------------
414  * File ID and description output routines
415  *---------------------------------------------------------------------------*/
416 
417 /*--------------------------------------------------------------------------
418  NAME
419        DFANaddfid -- Write a file label to a file
420  USAGE
421        int DFANaddfid(file_id, id)
422        int32 file_id;   IN: file identifier
423        char *id;        IN: label to write to file
424  RETURNS
425        SUCCEED (0) if successful and FAIL (-1) otherwise
426  DESCRIPTION
427        Invokes DFANIaddfann to write out label
428  GLOBAL VARIABLES
429  COMMENTS, BUGS, ASSUMPTIONS
430  EXAMPLES
431  REVISION LOG
432  *------------------------------------------------------------------------*/
433 intn
DFANaddfid(int32 file_id,char * id)434 DFANaddfid(int32 file_id, char *id)
435 {
436   intn ret_value;
437 
438   ret_value = (DFANIaddfann(file_id, id, (int32) HDstrlen(id), DFAN_LABEL));
439 
440   return ret_value;
441 }
442 
443 /*--------------------------------------------------------------------------
444  NAME
445        DFANaddfds -- Write a file description to a file
446  USAGE
447        int DFANaddfds(file_id, desc, desclen)
448        int32 file_id;   IN: file identifier
449        char *desc;      IN: description to write to file
450        int32 desclen;   IN: length of description
451  RETURNS
452        SUCCEED (0) if successful and FAIL (-1) otherwise
453  DESCRIPTION
454        Invokes DFANIaddfann to write out description
455  GLOBAL VARIABLES
456  COMMENTS, BUGS, ASSUMPTIONS
457        The parameter desc can contain any sequence of ASCII characters.
458        It does not have to be a string.
459  EXAMPLES
460  REVISION LOG
461  *------------------------------------------------------------------------*/
462 intn
DFANaddfds(int32 file_id,char * desc,int32 desclen)463 DFANaddfds(int32 file_id, char *desc, int32 desclen)
464 {
465   intn ret_value;
466 
467   ret_value = (DFANIaddfann(file_id, desc, desclen, DFAN_DESC));
468 
469   return ret_value;
470 }
471 
472 /*-----------------------------------------------------------------------------
473  * Miscellaneous other routines
474  *---------------------------------------------------------------------------*/
475 
476 /*--------------------------------------------------------------------------
477  NAME
478        DFANlastref -- Return the reference number of the annotation last
479                       written or read
480  USAGE
481        uint16 DFANlastref()
482  RETURNS
483        Reference number if successful and 0 otherwise
484  DESCRIPTION
485  GLOBAL VARIABLES
486        Lastref
487  COMMENTS, BUGS, ASSUMPTIONS
488  EXAMPLES
489  REVISION LOG
490  *------------------------------------------------------------------------*/
491 uint16
DFANlastref(void)492 DFANlastref(void)
493 {
494   uint16 ret_value;
495 
496   ret_value = (Lastref);
497 
498   return ret_value;
499 }
500 
501 /*--------------------------------------------------------------------------
502  NAME
503        DFANlablist -- Return list of refs and labels for a given tag
504  USAGE
505        int DFANlablist(filename, tag, reflist, labellist,
506                                                 listsize, maxlen, startpos)
507        char *filename;   IN: name of HDF file
508        uint16 tag;       IN: tag to use when searching for ref numbers
509                              and labels
510        uint16 reflist[]; OUT: array allocated to place ref numbers in
511        char *labellist;  OUT: array of strings allocated to place labels in
512        int listsize;     IN: size of ref number list and label list
513        int maxlen;       IN: maximum length allocated for label
514        int startpos;     IN: Starting position.  Beginning from the
515                              startpos'th entry, up to listsize entries
516                              will be returned.
517  RETURNS
518        Number of ref numbers found if successful and FAIL (-1) otherwise
519  DESCRIPTION
520        Invokes DFANIlablist to get label list.
521        Where there is no corresponding label, the position in
522        labellist is zero filled (C) or blank filled (Fortran).
523        Revised 04/17/90 so that it returns all ref numbers for
524        the given tag, rather than just those that have labels.
525  GLOBAL VARIABLES
526  COMMENTS, BUGS, ASSUMPTIONS
527  EXAMPLES
528  REVISION LOG
529        Revised 04/17/90.  (See DESCRIPTION.)
530  *------------------------------------------------------------------------*/
531 intn
DFANlablist(const char * filename,uint16 tag,uint16 reflist[],char * labellist,intn listsize,intn maxlen,intn startpos)532 DFANlablist(const char *filename, uint16 tag, uint16 reflist[], char *labellist,
533             intn listsize, intn maxlen, intn startpos)
534 {
535   intn ret_value;
536 
537   ret_value = (DFANIlablist(filename, tag, reflist, (uint8 *) labellist,
538                             listsize, maxlen, startpos, 0));
539   return ret_value;
540 }
541 
542 /*-------------------------------------------------------------------
543  Name
544         DFANclear --  Clear DFAN interface
545  Usage
546         intn DFANclear()
547  Returns
548         SUCCEED if ok; FAIL otherwise.
549  DESCRIPTION
550         Invokes DFANIclear.
551  GLOBAL VARIABLES
552  COMMENTS, BUGS, ASSUMPTIONS
553         When a file is re-created in a single run by other
554           interface, such as DFSDputdata(), user should
555           call DFANclear to reset DFAN interface structures.
556  EXAMPLES
557  REVISION LOG
558  *------------------------------------------------------------------*/
DFANclear(void)559 intn DFANclear(void)
560 {
561   intn ret_value;
562 
563   ret_value = DFANIclear();
564 
565   return ret_value;
566 }
567 
568 /******************************************************************************/
569 /*----------------------- Internal routines ---------------------------------*/
570 /******************************************************************************/
571 
572 /*---------------------------------------------------------------------------
573  Name
574        DFANIclear -- Clear label/desc entries and directories
575           Reset DFANdir[i] and Lastref
576  USAGE
577        intn DFANIclear()
578  Returns
579        SUCCEED if ok; FAIL otherwise.
580  DESCRIPTION
581        Reset DFANdir[i] and Lastref
582  GLOBAL VARIABLES
583         Lastref, DFANdir
584  COMMENTS, BUGS, ASSUMPTIONS
585 
586  EXAMPLES
587  REVISION LOG
588 
589  *-------------------------------------------------------------------------*/
590 intn
DFANIclear(void)591 DFANIclear(void)
592 {
593     CONSTR(FUNC, "DFANIclear");
594   DFANdirhead *p, *q;
595   intn ret_value = SUCCEED;
596 
597     HEclear();
598 
599     /* Perform global, one-time initialization */
600     if (library_terminate == FALSE)
601         if(DFANIstart()==FAIL)
602             HGOTO_ERROR(DFE_CANTINIT, FAIL);
603 
604   for (p=DFANdir[0]; p!=NULL; p=q) {  /* free linked list space */
605     q = p->next;
606     if (p->entries != NULL)
607 	    HDfree((VOIDP) p->entries);
608     p->nentries=0;
609     p->entries = NULL;
610     p->next=NULL;
611     HDfree((VOIDP) p);
612   }
613   for (p=DFANdir[1]; p!=NULL; p=q) {
614     q = p->next;
615     if (p->entries != NULL)
616 	    HDfree((VOIDP) p->entries);
617     p->nentries=0;
618     p->entries = NULL;
619     p->next=NULL;
620     HDfree((VOIDP) p);
621   }
622   DFANdir[0] = DFANdir[1] = NULL;
623 
624   Lastref = 0; /* 0 is invalid ref */
625 
626 done:
627   if(ret_value == FAIL)
628     { /* Error condition cleanup */
629 
630     } /* end if */
631 
632   /* Normal function cleanup */
633 
634   return ret_value;
635 }
636 
637 /*--------------------------------------------------------------------------
638  NAME
639        DFANIopen -- open or reopen a file
640  USAGE
641        PRIVATE int32 DFANIopen(filename, acc_mode)
642        char *filename;  IN: name of file to open
643        intn acc_mode;     IN: access mode
644  RETURNS
645        File identifier if successful and NULL on failure.
646  DESCRIPTION
647  GLOBAL VARIABLES
648  COMMENTS, BUGS, ASSUMPTIONS
649         This is a hook for someday providing more efficient ways to
650         reopen a file, to avoid re-reading all the headers
651 
652  EXAMPLES
653  REVISION LOG
654 
655  *------------------------------------------------------------------------*/
656 PRIVATE int32
DFANIopen(const char * filename,intn acc_mode)657 DFANIopen(const char *filename, intn acc_mode)
658 {
659   CONSTR(FUNC, "DFANIopen");
660   int32       file_id;
661   DFANdirhead *p, *q;
662   int32      ret_value = SUCCEED;
663 
664     HEclear();
665 
666     /* Perform global, one-time initialization */
667     if (library_terminate == FALSE)
668         if(DFANIstart()==FAIL)
669             HGOTO_ERROR(DFE_CANTINIT, FAIL);
670 
671   /* Check if filename buffer has been allocated */
672   if (Lastfile == NULL)
673     {
674       Lastfile = (char *) HDmalloc((DF_MAXFNLEN + 1) * sizeof(char));
675       if (Lastfile == NULL)
676         HGOTO_ERROR(DFE_NOSPACE, FAIL);
677       *Lastfile = '\0';     /* initialize with 0-length string */
678     }
679 
680   /* use reopen if same file as last time - more efficient */
681   if (HDstrncmp(Lastfile, filename, DF_MAXFNLEN) || (acc_mode == DFACC_CREATE))
682     {
683       /* treat create as different file */
684       if (( file_id = Hopen(filename, acc_mode, 0))== FAIL)
685           HGOTO_ERROR(DFE_BADOPEN,FAIL);
686 
687       for (p = DFANdir[0]; p != NULL; p = q)
688         {   /* free linked list space */
689           q = p->next;
690 	    if (p->entries != NULL)
691 		    HDfree((VOIDP) p->entries);
692 	    p->nentries=0;
693 	    p->entries = NULL;
694 	    p->next=NULL;
695           HDfree((VOIDP) p);
696         }
697       for (p = DFANdir[1]; p != NULL; p = q)
698         {
699           q = p->next;
700 	    if (p->entries != NULL)
701 		    HDfree((VOIDP) p->entries);
702 	    p->nentries=0;
703 	    p->entries = NULL;
704 	    p->next=NULL;
705           HDfree((VOIDP) p);
706         }
707       DFANdir[0] = DFANdir[1] = NULL;
708     }
709   else
710     {
711       if (( file_id = Hopen(filename, acc_mode, 0))== FAIL)
712           HGOTO_ERROR(DFE_BADOPEN,FAIL);
713     }
714 
715   HIstrncpy(Lastfile, filename, DF_MAXFNLEN);
716   /* remember filename, so reopen may be used next time if same file */
717 
718   ret_value = file_id;
719 
720 done:
721   if(ret_value == FAIL)
722     { /* Error condition cleanup */
723 
724     } /* end if */
725 
726   /* Normal function cleanup */
727 
728   return ret_value;
729 }
730 
731 /*--------------------------------------------------------------------------
732  NAME
733        DFANIlocate -- get ref of annotation of given data tag/ref
734  USAGE
735        uint16 DFANIlocate(file_id, type, tag, ref)
736        int32 file_id:   IN: pointer to HDF file
737        int type:        IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
738        uint16 tag, ref: IN: tag/ref of item for which we want ref of
739                             annotation
740 
741  RETURNS
742         ref of annotation on if successful; 0 otherwise
743  DESCRIPTION
744        Searches through directory for annotations with given tag/ref.  (If
745        there is no directory, it creates one.)
746 
747  GLOBAL VARIABLES
748 
749  COMMENTS, BUGS, ASSUMPTIONS
750        BUG: When FORTRAN calls this routine with type "label", the string
751        returned is incorrect in length by one character
752  EXAMPLES
753 
754  REVISION LOG
755 
756  *------------------------------------------------------------------------*/
757 uint16
DFANIlocate(int32 file_id,int type,uint16 tag,uint16 ref)758 DFANIlocate(int32 file_id, int type, uint16 tag, uint16 ref)
759 {
760   CONSTR(FUNC, "DFANIlocate");
761   uint8       datadi[4];
762   int32       more_anns;
763   int32       aid;
764   int32       nanns, i;
765   uint16      anntag, annref = 0;
766   DFANdirhead *p;
767   uint8      *ptr;
768   uint16     ret_value = 0; /* FAIL ? */
769 
770   HEclear();
771 
772     /* Perform global, one-time initialization */
773     if (library_terminate == FALSE)
774         if(DFANIstart()==FAIL)
775             HGOTO_ERROR(DFE_CANTINIT, (uint16)FAIL);
776 
777   anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA);
778 
779   /* if no directory for this type of annotation, make one */
780   if (DFANdir[type] == NULL)
781     {
782       nanns = Hnumber(file_id, anntag);
783       if (nanns == 0)
784         HGOTO_ERROR(DFE_INTERNAL, 0);
785 
786       /* allocate directory space, and space for entries. */
787       DFANdir[type] = (DFANdirhead *) HDmalloc((uint32) sizeof(DFANdirhead));
788       if (DFANdir[type] == NULL)
789         HGOTO_ERROR(DFE_NOSPACE, 0);
790       DFANdir[type]->entries = (DFANdirentry *)
791         HDmalloc( (size_t)nanns * sizeof(DFANdirentry));
792       if (DFANdir[type]->entries == NULL)
793         HGOTO_ERROR(DFE_NOSPACE, 0);
794 
795       DFANdir[type]->next = NULL;
796       DFANdir[type]->nentries = nanns;
797 
798       /* fill directory table */
799       if (( aid = Hstartread(file_id, anntag, DFREF_WILDCARD))== FAIL)
800         {
801           HGOTO_ERROR(DFE_BADAID, 0);
802         } /* end if */
803       else
804         more_anns = SUCCEED;
805 
806       for (i = 0; (i < nanns) && (more_anns != FAIL); i++)
807         {
808           if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref,
809                                (int32 *) NULL, (int32 *) NULL, (int32 *) NULL,
810                                (int16 *) NULL, (int16 *) NULL))
811                 HGOTO_ERROR(DFE_INTERNAL, 0);
812 
813           if ((int32) FAIL == Hread(aid, (int32) 4, datadi))
814                 HGOTO_ERROR(DFE_READERROR, 0);
815 
816           /* get data tag/ref */
817           DFANdir[type]->entries[i].annref = annref;
818           ptr = (uint8 *) &(datadi[0]);
819           UINT16DECODE(ptr, DFANdir[type]->entries[i].datatag);
820           UINT16DECODE(ptr, DFANdir[type]->entries[i].dataref);
821 
822           more_anns = Hnextread(aid, anntag, DFREF_WILDCARD, DF_CURRENT);
823         }
824       Hendaccess(aid);
825     }
826 
827   if (!tag)
828     HGOTO_DONE(1);
829 
830   /* find annotation that goes with this tag/ref */
831   for (p = (DFANdirhead *) DFANdir[type]; p != NULL; p = p->next)
832     for (i = 0; i < p->nentries; i++)
833       if (p->entries[i].annref != 0)
834         if ((p->entries[i].dataref == ref) && (p->entries[i].datatag == tag))
835             HGOTO_DONE(p->entries[i].annref);
836 
837   HERROR(DFE_NOMATCH);
838 
839 done:
840   if(ret_value == 0)
841     { /* Error condition cleanup */
842 
843     } /* end if */
844   /* Normal function cleanup */
845 
846   return ret_value;
847 }
848 
849 /*--------------------------------------------------------------------------
850  NAME
851        DFANIaddentry -- add entry to annotation directory
852  USAGE
853        int type:        IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
854        uint16 annref:   IN: ref of annotation
855        uint16 datatag,: IN: tag of item of which this is annotation
856        uint16 dataref;  IN: ref of item of which this is annotation
857 
858  RETURNS
859        SUCCEED (0) if successful and FAIL (-1) otherwise
860  DESCRIPTION
861        Moves to end of directory and appends entry.
862  GLOBAL VARIABLES
863  COMMENTS, BUGS, ASSUMPTIONS
864  EXAMPLES
865  REVISION LOG
866  *------------------------------------------------------------------------*/
867 int
DFANIaddentry(int type,uint16 annref,uint16 datatag,uint16 dataref)868 DFANIaddentry(int type, uint16 annref, uint16 datatag, uint16 dataref)
869 {
870   CONSTR(FUNC, "DFANIaddentry");
871   int32       i;
872   DFANdirhead *p, *q;
873   int         ret_value = SUCCEED;
874 
875     HEclear();
876 
877     /* Perform global, one-time initialization */
878     if (library_terminate == FALSE)
879         if(DFANIstart()==FAIL)
880             HGOTO_ERROR(DFE_CANTINIT, FAIL);
881 
882   /* move to last entry in list */
883   for (p = DFANdir[type]; (p != NULL) && (p->next != NULL); p = p->next)
884     ;
885 
886   if (p)
887     {     /* not new list */
888       for (i = 0; i < p->nentries; i++)     /* check all entries */
889         if (p->entries[i].annref == 0)
890           {   /* empty slot */
891             p->entries[i].annref = annref;  /* store entry */
892             p->entries[i].datatag = datatag;
893             p->entries[i].dataref = dataref;
894             HGOTO_DONE(SUCCEED);
895           }
896     }
897 
898   /* need new list or new node in list */
899   /* allocate directory space and space for entries. */
900   if ((q = (DFANdirhead *) HDmalloc((uint32) sizeof(DFANdirhead))) == NULL)
901       HGOTO_ERROR(DFE_NOSPACE,FAIL);
902   q->entries = (DFANdirentry *) HDmalloc( DFAN_DEFENTRIES * sizeof(DFANdirentry));
903   if (q->entries == NULL)
904       HGOTO_ERROR(DFE_NOSPACE,FAIL);
905 
906   q->next = NULL;
907   q->nentries = DFAN_DEFENTRIES;
908   if (!p)
909     DFANdir[type] = q;  /* set pointer to this new node */
910   else
911     p->next = q;
912 
913   /* store entry */
914   q->entries[0].annref = annref;
915   q->entries[0].datatag = datatag;
916   q->entries[0].dataref = dataref;
917 
918   for (i = 1; i < DFAN_DEFENTRIES; i++)   /* mark rest unused */
919     q->entries[i].annref = 0;
920 
921 done:
922   if(ret_value == FAIL)
923     { /* Error condition cleanup */
924 
925     } /* end if */
926   /* Normal function cleanup */
927 
928   return ret_value;
929 }
930 
931 /*--------------------------------------------------------------------------
932  NAME
933        DFANIgetannlen -- get length of annotation of tag/ref
934  USAGE
935        int32 DFANIgetannlen(filename, tag, ref, type)
936        char *filename;   IN: name of HDF file
937        int32 tag, ref;   IN: tag/ref of item of which we want annotation
938        int type;         IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
939  RETURNS
940        length of annotation if successful and FAIL (-1) otherwise
941  DESCRIPTION
942        Calls DFANIlocate to get ref of annotation.
943        Calls Hlength to get its length.
944  GLOBAL VARIABLES
945        Lastref
946  COMMENTS, BUGS, ASSUMPTIONS
947  EXAMPLES
948  REVISION LOG
949  *------------------------------------------------------------------------*/
950 int32
DFANIgetannlen(const char * filename,uint16 tag,uint16 ref,int type)951 DFANIgetannlen(const char *filename, uint16 tag, uint16 ref, int type)
952 {
953   CONSTR(FUNC, "DFANIgetannlen");
954   int32       file_id, annlength;
955   uint16      anntag, annref;
956   int32       ret_value = SUCCEED;
957 
958   HEclear();
959 
960     /* Perform global, one-time initialization */
961     if (library_terminate == FALSE)
962         if(DFANIstart()==FAIL)
963             HGOTO_ERROR(DFE_CANTINIT, FAIL);
964 
965   if (!tag)
966     HGOTO_ERROR(DFE_BADTAG,FAIL);
967 
968   if (!ref)
969     HGOTO_ERROR(DFE_BADREF,FAIL);
970 
971   if (( file_id = DFANIopen(filename, DFACC_READ))== FAIL)
972     HGOTO_ERROR(DFE_BADOPEN,FAIL);
973 
974     /* get ref of annotation of tag/ref */
975   annref = DFANIlocate(file_id, type, tag, ref);
976   if (annref == 0)
977     HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
978   anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA);   /* set type tag */
979 
980   annlength = Hlength(file_id, anntag, annref) - 4;   /* 4=len of data tag/ref */
981   if (annlength == FAIL)
982     HCLOSE_GOTO_ERROR(file_id,DFE_BADLEN,FAIL);
983   Lastref = annref;   /* remember ref last accessed */
984   if (Hclose(file_id) == FAIL)    /* close file */
985     ret_value = FAIL;
986 
987   ret_value = annlength;
988 
989 done:
990   if(ret_value == FAIL)
991     { /* Error condition cleanup */
992 
993     } /* end if */
994 
995   /* Normal function cleanup */
996 
997   return ret_value;
998 }
999 
1000 /*--------------------------------------------------------------------------
1001  NAME
1002        DFANIgetann -- get annotation of tag/ref
1003  USAGE
1004        intn DFANIgetann(filename, tag, ref, ann, maxlen, type)
1005        char *filename;   IN: name of HDF file
1006        uint16 tag, ref;  IN: tag/ref of item of which we want annotation
1007        uint8 *ann;       OUT: space to return annotation in
1008        int32 maxlen;     IN: size of space to return annotation in
1009        int type;         IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1010        int isfortran;    IN: 0 if C, 1 if Fortran
1011  RETURNS
1012        SUCCEED (0) if successful and FAIL (-1) otherwise
1013  DESCRIPTION
1014        Gets tag and ref of annotation.  Finds DD for that annotation.
1015        Reads the annotation, taking care of NULL terminator, if necessary.
1016  GLOBAL VARIABLES
1017        Lastref.
1018  COMMENTS, BUGS, ASSUMPTIONS
1019        BUG 1640: Added isfortran flag to avoid termination of the string with
1020        the null character when the routine is call from FORTRAN.
1021  EXAMPLES
1022  REVISION LOG
1023  *------------------------------------------------------------------------*/
1024 intn
DFANIgetann(const char * filename,uint16 tag,uint16 ref,uint8 * ann,int32 maxlen,int type,int isfortran)1025 DFANIgetann(const char *filename, uint16 tag, uint16 ref, uint8 *ann,
1026             int32 maxlen, int type, int isfortran)
1027 {
1028   CONSTR(FUNC, "DFANIgetann");
1029   int32       file_id, aid;
1030   int32       annlen;
1031   uint16      anntag, annref;
1032   uint8       datadi[4];      /* to read in and discard data/ref! */
1033   intn        ret_value = SUCCEED;
1034 
1035   HEclear();
1036 
1037     /* Perform global, one-time initialization */
1038     if (library_terminate == FALSE)
1039         if(DFANIstart()==FAIL)
1040             HGOTO_ERROR(DFE_CANTINIT, FAIL);
1041 
1042   if (!ann)
1043     HGOTO_ERROR(DFE_BADPTR,FAIL);
1044 
1045   if (!tag)
1046     HGOTO_ERROR(DFE_BADTAG,FAIL);
1047 
1048   if (!ref)
1049     HGOTO_ERROR(DFE_BADREF,FAIL);
1050 
1051   if (( file_id = DFANIopen(filename, DFACC_READ))== FAIL)
1052     HGOTO_ERROR(DFE_BADOPEN,FAIL);
1053 
1054   /* get annref and anntag of annotation of tag/ref */
1055   annref = DFANIlocate(file_id, type, tag, ref);
1056   if (annref == 0)
1057     HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1058   anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA);
1059 
1060     /* find DD for that annotation */
1061   aid = Hstartread(file_id, anntag, annref);
1062   if (aid == FAIL)
1063       HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1064 
1065   if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, (uint16 *) NULL,
1066                        &annlen, (int32 *) NULL, (int32 *) NULL, (int16 *) NULL,
1067                        (int16 *) NULL))
1068     {
1069       Hendaccess(aid);
1070       HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1071     }
1072   annlen -= 4;    /* first four bytes were tag/ref, so they don't count */
1073 
1074   /* check length, if not enough space, truncate annotation */
1075   /* In C labels need space for null terminator, descriptions don't */
1076   if (isfortran)
1077     {
1078       if (annlen > maxlen )
1079 	annlen = maxlen;
1080     }
1081   else
1082     if (type == DFAN_LABEL)
1083       {
1084 	if (annlen > maxlen - 1)
1085 	  annlen = maxlen - 1;
1086       }
1087     else
1088       {
1089 	if (annlen > maxlen)
1090 	  annlen = maxlen;
1091       }
1092 
1093   /* read annotation */
1094   if ((int32) FAIL == Hread(aid, (int32) 4, datadi))
1095     {     /* go past tag/ref */
1096       Hendaccess(aid);
1097       HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1098     }
1099   if ((int32) FAIL == Hread(aid, annlen, ann))
1100     {     /* read the annotation */
1101       Hendaccess(aid);
1102       HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1103     }
1104   /* add null for C */
1105   if (type == DFAN_LABEL)
1106     if (!isfortran)
1107       ann[annlen] = '\0'; /* terminate string properly for C */
1108 
1109   Lastref = annref;   /* remember ref last accessed */
1110   Hendaccess(aid);
1111   ret_value = (Hclose(file_id));
1112 
1113 done:
1114   if(ret_value == FAIL)
1115     { /* Error condition cleanup */
1116 
1117     } /* end if */
1118   /* Normal function cleanup */
1119 
1120   return ret_value;
1121 }
1122 
1123 /*--------------------------------------------------------------------------
1124  NAME
1125        DFANIputann -- put annotation of tag/ref into file
1126  USAGE
1127        intn DFANIputann(filename, tag, ref, ann, annlen, type)
1128        char *filename;   IN: name of HDF file
1129        uint16 tag, ref;  IN: tag/ref of item of which this is the annotation
1130        uint8 *ann;       IN: space to return annotation in
1131        int32 annlen;     IN: length of annotation
1132        int type;         IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1133 
1134  RETURNS
1135        SUCCEED (0) if successful and FAIL (-1) otherwise
1136  DESCRIPTION
1137        Checks for pre-existence of annotation, replacing old one if it
1138        exists. Writes out annotation, and updates directory..
1139  GLOBAL VARIABLES
1140        Lastref.
1141  COMMENTS, BUGS, ASSUMPTIONS
1142        If the given object already has this type of annotation, it replaces
1143        the old annotation with this one.
1144  EXAMPLES
1145  REVISION LOG
1146  *------------------------------------------------------------------------*/
1147 intn
DFANIputann(const char * filename,uint16 tag,uint16 ref,uint8 * ann,int32 annlen,int type)1148 DFANIputann(const char *filename, uint16 tag, uint16 ref, uint8 *ann,
1149             int32 annlen, int type)
1150 {
1151   CONSTR(FUNC, "DFANIputann");
1152   int32       file_id, aid;
1153   int         newflag = 0;
1154   uint16      anntag, annref;
1155   uint8       datadi[4];      /* to hold data tag/ref for writing */
1156   uint8      *ptr;
1157   intn        ret_value = SUCCEED;
1158 
1159   HEclear();
1160 
1161     /* Perform global, one-time initialization */
1162     if (library_terminate == FALSE)
1163         if(DFANIstart()==FAIL)
1164             HGOTO_ERROR(DFE_CANTINIT, FAIL);
1165 
1166   if (!ann)
1167     HGOTO_ERROR(DFE_BADPTR,FAIL);
1168 
1169   if (!tag)
1170     HGOTO_ERROR(DFE_BADTAG,FAIL);
1171 
1172   if (!ref)
1173     HGOTO_ERROR(DFE_BADREF,FAIL);
1174 
1175   if (( file_id = DFANIopen(filename, DFACC_RDWR))== 0)
1176     HGOTO_ERROR(DFE_BADOPEN,FAIL);
1177 
1178   anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_DIL : DFTAG_DIA);
1179 
1180   /* check if this tag/ref already has this type of annotation */
1181   annref = DFANIlocate(file_id, type, tag, ref);
1182   if (annref == 0)
1183     {
1184       annref = Htagnewref(file_id,anntag);
1185       if (annref == 0)
1186         HCLOSE_GOTO_ERROR(file_id,DFE_NOREF,FAIL);
1187       newflag = 1;  /* remember to add ann tag/ref to directory */
1188     }
1189 
1190   /*
1191    * if annotation exists, reuse tag/ref and rewrite new annotation
1192    */
1193   if (newflag == 0)
1194     {     /* does prev annotation exist? */
1195       if (HDreuse_tagref(file_id, anntag, annref) == FAIL)
1196         {
1197           Hclose(file_id);
1198           HEreport("Unable to replace old annotation");
1199           HGOTO_DONE(FAIL);
1200         }
1201     }
1202 
1203   /* put annotation */
1204   /* Note: cannot use DFputelement because need to write data tag/ref */
1205   aid = Hstartwrite(file_id, anntag, annref, annlen + 4);
1206   if (aid == FAIL)
1207     {
1208       Hendaccess(aid);
1209       HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1210     }
1211 
1212   /* write annotation */
1213   ptr = (uint8 *) &(datadi[0]);   /* first, write the object's tag/ref */
1214   UINT16ENCODE(ptr, tag);
1215   UINT16ENCODE(ptr, ref);
1216   if ((int32) FAIL == Hwrite(aid, (int32) 4, datadi))
1217       HCLOSE_GOTO_ERROR(file_id,DFE_WRITEERROR,FAIL);
1218   if ((int32) FAIL == Hwrite(aid, annlen, ann))
1219     {     /* then write the annotation */
1220       Hendaccess(aid);
1221       HCLOSE_GOTO_ERROR(file_id,DFE_WRITEERROR,FAIL);
1222     }
1223 
1224   /* put annotation tag/ref into directory if new */
1225   if (newflag)
1226     {
1227       if (FAIL == DFANIaddentry(type, annref, tag, ref))
1228         {
1229           Hendaccess(aid);
1230           HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1231         }
1232     }
1233 
1234   Lastref = annref;   /* remember ref last accessed */
1235   Hendaccess(aid);
1236   ret_value = (Hclose(file_id));
1237 
1238 done:
1239   if(ret_value == FAIL)
1240     { /* Error condition cleanup */
1241 
1242     } /* end if */
1243   /* Normal function cleanup */
1244 
1245   return ret_value;
1246 }
1247 
1248 /*--------------------------------------------------------------------------
1249  NAME
1250        DFANIlablist -- Return list of refs and labels for a given tag
1251  USAGE
1252        int DFANlablist(filename, tag, reflist, labellist,
1253                                                 listsize, maxlen, startpos)
1254        char *filename;   IN: name of HDF file
1255        uint16 tag;       IN: tag to use when searching for ref numbers
1256                              and labels
1257        uint16 reflist[]; OUT: array allocated to place ref numbers in
1258        char *labellist;  OUT: array of strings allocated to place labels in
1259        int listsize;     IN: size of ref number list and label list
1260        int maxlen;       IN: maximum length allocated for label
1261        int startpos;     IN: Starting position.  Beginning from the
1262                              startpos'th entry, up to listsize entries
1263                              will be returned.
1264        int isfortran: 0 if C, 1 if Fortran
1265  RETURNS
1266        Number of ref numbers found if successful and FAIL (-1) otherwise
1267  DESCRIPTION
1268        Where there is no corresponding label, the position in
1269        labellist is zero filled (C) or blank filled (Fortran).
1270        Revised 04/17/90 so that it returns all ref numbers for
1271        the given tag, rather than just those that have labels.
1272  GLOBAL VARIABLES
1273  COMMENTS, BUGS, ASSUMPTIONS
1274  EXAMPLES
1275  REVISION LOG
1276        Revised 04/17/90.  (See DESCRIPTION.)
1277  *------------------------------------------------------------------------*/
1278 intn
DFANIlablist(const char * filename,uint16 tag,uint16 reflist[],uint8 * labellist,int listsize,int maxlen,int startpos,int isfortran)1279 DFANIlablist(const char *filename, uint16 tag, uint16 reflist[],
1280              uint8 *labellist, int listsize, int maxlen, int startpos,
1281              int isfortran)
1282 {
1283   CONSTR(FUNC, "DFANIlablist");
1284   int32       i;
1285   int         j, k;
1286   int32       file_id, aid, len;
1287   uint16      ref=0;
1288   DFANdirhead *p;
1289   uint8      *lp;             /* pointer to label */
1290   intn        nrefs, nlabs;
1291   uint8       labeldi[4];     /* to read in and discard data/ref */
1292   intn        ret_value = SUCCEED;
1293 
1294   HEclear();
1295 
1296     /* Perform global, one-time initialization */
1297     if (library_terminate == FALSE)
1298         if(DFANIstart()==FAIL)
1299             HGOTO_ERROR(DFE_CANTINIT, FAIL);
1300 
1301   if (!reflist || !labellist)
1302     HGOTO_ERROR(DFE_BADPTR,FAIL);
1303 
1304   if (!tag)
1305     HGOTO_ERROR(DFE_BADTAG,FAIL);
1306 
1307   if (( file_id = DFANIopen(filename, DFACC_READ))== 0)
1308     HGOTO_ERROR(DFE_BADOPEN,FAIL);
1309 
1310     /* clear labellist.  pad with blanks for Fortran; add null for C  */
1311   if (isfortran)
1312     HDmemset(labellist, ' ', (uint32) maxlen * (uint32) listsize);
1313   else
1314     HDmemset(labellist, '\0', (uint32) maxlen * (uint32) listsize);
1315 
1316     /* find all refs for this tag; store them in reflist */
1317   nrefs = (intn) Hnumber(file_id, tag);   /* how many times is tag in file? */
1318   if (nrefs == FAIL)
1319     HCLOSE_GOTO_ERROR(file_id,DFE_NOMATCH,FAIL);
1320 
1321   aid = Hstartread(file_id, tag, DFREF_WILDCARD);     /* set search for refs */
1322   if (aid == FAIL)
1323     HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1324 
1325   for (i = 0, j = 0; i < nrefs && j < listsize; i++)
1326     {
1327       if (HQuerytagref(aid, (uint16 *) NULL, &ref) == FAIL)
1328         {
1329           Hendaccess(aid);
1330           HCLOSE_GOTO_ERROR(file_id,DFE_NOMATCH,FAIL);
1331         }
1332       if (i >= startpos - 1)
1333         reflist[j++] = ref;   /* store next ref in reflist */
1334       Hnextread(aid, tag, DFREF_WILDCARD, DF_CURRENT);
1335     }
1336   nrefs = j;
1337   Hendaccess(aid);
1338 
1339   /* get directory of all labels */
1340 
1341   nlabs = (intn) Hnumber(file_id, DFTAG_DIL);
1342   if (nlabs != 0)
1343     {
1344       if (DFANdir[DFAN_LABEL] == NULL)
1345         {   /* if no dir info create dir */
1346           if (0 == DFANIlocate(file_id, DFAN_LABEL, 0, 0))
1347             {
1348               Hendaccess(aid);
1349               HCLOSE_GOTO_ERROR(file_id,DFE_INTERNAL,FAIL);
1350             }
1351         }
1352 
1353       lp = labellist;
1354 
1355       /* Look through all labels. Get those that correspond to the tag,
1356          and match them with corresponding tag/refs in the reflist.      */
1357       for (p = DFANdir[DFAN_LABEL]; p != NULL; p = p->next)
1358         {   /* for each ann dir */
1359           for (i = 0; i < p->nentries; i++)
1360             {     /* for each tag in dir */
1361               if (p->entries[i].datatag == tag)
1362                 {   /* if this tag==our tag */
1363 
1364                   aid = Hstartread(file_id, DFTAG_DIL, p->entries[i].annref);
1365                   if (aid == FAIL)
1366                       HCLOSE_GOTO_ERROR(file_id,DFE_BADAID,FAIL);
1367                   if ((int32) FAIL == Hread(aid, (int32) 4, labeldi))
1368                     {     /* data tag/ref */
1369                       Hendaccess(aid);
1370                       HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1371                     }
1372                   /* look for corresponding ref in reflist */
1373                   for (k = 0; k < nrefs && p->entries[i].dataref != reflist[k]; k++)
1374                     ;
1375                   if (k < nrefs)
1376                     {     /* if ref found */
1377 
1378                       lp = labellist + k * maxlen;  /* get pos to copy to */
1379 
1380                       /* note len on read may be too big, but OK for DFread */
1381                       len = Hread(aid, (int32) (maxlen - 1), lp);
1382                       if (len == FAIL)
1383                         {
1384                           Hendaccess(aid);
1385                           HCLOSE_GOTO_ERROR(file_id,DFE_READERROR,FAIL);
1386                         }
1387                       /* ret now contains actual length read */
1388                       /* pad with blanks for Fortran; add null for C */
1389                       if (isfortran)
1390                         while (len++ < maxlen)
1391                           lp[len] = ' ';
1392                       else
1393                         lp[len] = '\0';
1394                     }
1395                   Hendaccess(aid);
1396                 }   /* tag == our tag  */
1397             }     /* for each tag in dir  */
1398         }   /* for each ann dir  */
1399     }     /* nlabs != 0  */
1400   if (FAIL == Hclose(file_id))    /* close file */
1401     ret_value = FAIL;
1402   else
1403     ret_value = nrefs;
1404 
1405 done:
1406   if(ret_value == FAIL)
1407     { /* Error condition cleanup */
1408 
1409     } /* end if */
1410 
1411   /* Normal function cleanup */
1412 
1413   return ret_value;
1414 }
1415 
1416 /*--------------------------------------------------------------------------
1417  NAME
1418        DFANaddfann -- Write a file label or description to a file
1419  USAGE
1420        int DFANaddfid(file_id, id)
1421        int32 file_id;  IN: pointer to HDF file
1422        char *ann;      IN: annotation to write to file
1423        int32 annlen:   IN: length of annotation
1424        int type:       IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1425  RETURNS
1426        SUCCEED (0) if successful and FAIL (-1) otherwise
1427  DESCRIPTION
1428        Calls Hputelement to putput the annotation.
1429  GLOBAL VARIABLES
1430        Lastref
1431  COMMENTS, BUGS, ASSUMPTIONS
1432  EXAMPLES
1433  REVISION LOG
1434  *------------------------------------------------------------------------*/
1435 int
DFANIaddfann(int32 file_id,char * ann,int32 annlen,int type)1436 DFANIaddfann(int32 file_id, char *ann, int32 annlen, int type)
1437 {
1438   CONSTR(FUNC, "DFANIaddfann");
1439   uint16      anntag, annref;
1440   int         ret_value = SUCCEED;
1441 
1442   HEclear();
1443 
1444     /* Perform global, one-time initialization */
1445     if (library_terminate == FALSE)
1446         if(DFANIstart()==FAIL)
1447             HGOTO_ERROR(DFE_CANTINIT, FAIL);
1448 
1449   if (!ann)
1450     HGOTO_ERROR(DFE_BADPTR,FAIL);
1451 
1452   anntag = (uint16) ((type == DFAN_LABEL) ? DFTAG_FID : DFTAG_FD);
1453 
1454   annref = Htagnewref(file_id,anntag);
1455   if (annref == 0)
1456     HGOTO_ERROR(DFE_NOREF,FAIL);
1457 
1458     /* write out annotation */
1459   if (FAIL == Hputelement(file_id, anntag, annref, (uint8 *) ann, annlen))
1460     HGOTO_ERROR(DFE_PUTELEM,FAIL);
1461 
1462   Lastref = annref;   /* remember ref last accessed */
1463 
1464 done:
1465   if(ret_value == FAIL)
1466     { /* Error condition cleanup */
1467 
1468     } /* end if */
1469   /* Normal function cleanup */
1470 
1471   return ret_value;
1472 }
1473 
1474 /*--------------------------------------------------------------------------
1475  NAME
1476        DFANIgetfannlen -- get length of next file annotation
1477  USAGE
1478        int32 DFANIgetannlen(filename, tag, ref, type)
1479        int32 file_id;   IN: id of HDF file
1480        int type;        IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1481        int isfirst;     IN: 1: start with first one; 0: get next one
1482  RETURNS
1483        length of annotation if successful and FAIL (-1) otherwise
1484  DESCRIPTION
1485        Uses isfirst and Next_label_ref (or Next_desc_ref) to determine
1486        which annotation to pick up next.
1487  GLOBAL VARIABLES
1488        Lastref
1489        Next_label_ref
1490        Next_desc_ref
1491  COMMENTS, BUGS, ASSUMPTIONS
1492  EXAMPLES
1493  REVISION LOG
1494  *------------------------------------------------------------------------*/
1495 int32
DFANIgetfannlen(int32 file_id,int type,int isfirst)1496 DFANIgetfannlen(int32 file_id, int type, int isfirst)
1497 {
1498   CONSTR(FUNC, "DFANIgetfannlen");
1499   uint16      anntag, annref;
1500   int32       aid;
1501   int32       length;
1502   int32       ret_value = SUCCEED;
1503 
1504   HEclear();
1505 
1506     /* Perform global, one-time initialization */
1507     if (library_terminate == FALSE)
1508         if(DFANIstart()==FAIL)
1509             HGOTO_ERROR(DFE_CANTINIT, FAIL);
1510 
1511     /* Identify tag for this "type" of access; determine which ref to key on. */
1512   if (type == DFAN_LABEL)
1513     {
1514       anntag = DFTAG_FID;
1515       annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_label_ref);
1516     }
1517   else
1518     {
1519       anntag = DFTAG_FD;
1520       annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_desc_ref);
1521     }
1522   aid = Hstartread(file_id, anntag, annref);
1523   if (aid == FAIL)
1524     HGOTO_ERROR(DFE_BADAID, FAIL);
1525   if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref, &length,
1526                        (int32 *) NULL, (int32 *) NULL, (int16 *) NULL, (int16 *) NULL))
1527     {
1528       Hendaccess(aid);
1529       HGOTO_ERROR(DFE_NOMATCH, FAIL);
1530     }
1531   if (type == DFAN_LABEL)     /* prepare for next call */
1532     Next_label_ref = annref;
1533   else
1534     Next_desc_ref = annref;
1535 
1536   Hendaccess(aid);
1537   Lastref = annref;   /* remember ref last accessed */
1538 
1539   if (length >= 0)    /* (length == 0) => no length found */
1540     ret_value = length;
1541   else
1542     HGOTO_ERROR(DFE_NOMATCH,FAIL);
1543 
1544 done:
1545   if(ret_value == FAIL)
1546     { /* Error condition cleanup */
1547 
1548     } /* end if */
1549   /* Normal function cleanup */
1550 
1551   return ret_value;
1552 }
1553 
1554 /*--------------------------------------------------------------------------
1555  NAME
1556        DFANIgetfann -- get next file annotation (file ID or file description)
1557  USAGE
1558        intn DFANIgetfann(filename, tag, ref, ann, maxlen, type)
1559        int32 file_id;    IN: id of HDF file
1560        uint8 *ann;       OUT: space to return annotation in
1561        int32 annlen;     IN: size of space to return annotation in
1562        int type;         IN: DFAN_LABEL for labels, DFAN_DESC for descriptions
1563        int isfirst;      IN: 1: start with first one; 0: get next one
1564 
1565  RETURNS
1566        Length of annotation if successful and FAIL (-1) otherwise
1567  DESCRIPTION
1568        Gets tag and ref of annotation.  Finds DD for that annotation.
1569        Reads the annotation, taking care of NULL terminator, if necessary.
1570  GLOBAL VARIABLES
1571        Lastref, Next_desc_ref, Next_label_ref
1572  COMMENTS, BUGS, ASSUMPTIONS
1573        If maxlen not great enough, ann is truncated to maxlen-1 chars
1574        BUG: If ref is high possible ref value, setting of Next_label_ref
1575             or Next_desc_ref behave unpredictably.
1576  EXAMPLES
1577  REVISION LOG
1578  *---------------------------------------------------------------------------*/
1579 int32
DFANIgetfann(int32 file_id,char * ann,int32 maxlen,int type,int isfirst)1580 DFANIgetfann(int32 file_id, char *ann, int32 maxlen, int type,
1581              int isfirst)
1582 {
1583   CONSTR(FUNC, "DFANIgetfann");
1584   uint16      anntag, annref;
1585   int32       length, aid;
1586   int32       ret_value = SUCCEED;
1587 
1588   HEclear();
1589 
1590     /* Perform global, one-time initialization */
1591     if (library_terminate == FALSE)
1592         if(DFANIstart()==FAIL)
1593             HGOTO_ERROR(DFE_CANTINIT, FAIL);
1594 
1595   if (!ann)
1596     HGOTO_ERROR(DFE_BADPTR,FAIL);
1597 
1598     /* Identify tag for this "type" of access; determine which ref to key on. */
1599   if (type == DFAN_LABEL)
1600     {
1601       anntag = DFTAG_FID;
1602       annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_label_ref);
1603     }
1604   else
1605     {
1606       anntag = DFTAG_FD;
1607       annref = (uint16) ((isfirst == 1) ? DFREF_WILDCARD : Next_desc_ref);
1608     }
1609 
1610   if (( aid = Hstartread(file_id, anntag, annref))== FAIL)
1611     HGOTO_ERROR(DFE_BADAID, FAIL);
1612   if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref, &length,
1613                    (int32 *) NULL, (int32 *) NULL, (int16 *) NULL, (int16 *) NULL))
1614     {
1615       Hendaccess(aid);
1616       HGOTO_ERROR(DFE_NOMATCH, FAIL);
1617     }
1618   length = (length > maxlen) ? maxlen : length;   /* truncate if too long */
1619 
1620   if ((int32) FAIL == Hread(aid, length, (uint8 *) ann))  /* get the annotation */
1621     {
1622       Hendaccess(aid);
1623       HGOTO_ERROR(DFE_READERROR, FAIL);
1624     }
1625 
1626   if (length > maxlen - 1)
1627     length = maxlen - 1;
1628 
1629   ann[length] = '\0';
1630 
1631   Lastref = annref;   /* remember ref last accessed */
1632 
1633   /* prepare for next call */
1634   if (FAIL == Hnextread(aid, anntag, DFREF_WILDCARD, DF_CURRENT))
1635     {     /* If no more of them, set Next_ ???_ref */
1636       if (type == DFAN_LABEL)   /*    to one higher than current value   */
1637         Next_label_ref++;     /*    so that next call will fail.       */
1638       else
1639         Next_desc_ref++;
1640     }
1641   else
1642     {     /* Otherwise save the next ref */
1643       if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &annref,
1644                            (int32 *) NULL, (int32 *) NULL, (int32 *) NULL,
1645                            (int16 *) NULL, (int16 *) NULL))
1646         {
1647           Hendaccess(aid);
1648           HGOTO_ERROR(DFE_NOMATCH, FAIL);
1649         }
1650       if (type == DFAN_LABEL)
1651         Next_label_ref = annref;
1652       else
1653         Next_desc_ref = annref;
1654     }
1655 
1656   Hendaccess(aid);
1657 
1658 done:
1659   if(ret_value == FAIL)
1660     { /* Error condition cleanup */
1661 
1662     } /* end if */
1663   else
1664     ret_value = length;
1665 
1666   /* Normal function cleanup */
1667 
1668   return ret_value;
1669 }
1670 
1671 /*--------------------------------------------------------------------------
1672  NAME
1673     DFANIstart
1674  PURPOSE
1675     DFAN-level initialization routine
1676  USAGE
1677     intn DFANIstart()
1678  RETURNS
1679     Returns SUCCEED/FAIL
1680  DESCRIPTION
1681     Register the shut-down routine (DFANPshutdown) for call with atexit
1682  GLOBAL VARIABLES
1683  COMMENTS, BUGS, ASSUMPTIONS
1684  EXAMPLES
1685  REVISION LOG
1686 --------------------------------------------------------------------------*/
DFANIstart(void)1687 PRIVATE intn DFANIstart(void)
1688 {
1689     CONSTR(FUNC, "DFANIstart");    /* for HERROR */
1690     intn        ret_value = SUCCEED;
1691 
1692     /* Don't call this routine again... */
1693     library_terminate = TRUE;
1694 
1695     /* Install atexit() library cleanup routine */
1696     if (HPregister_term_func(&DFANPshutdown) != 0)
1697       HGOTO_ERROR(DFE_CANTINIT, FAIL);
1698 
1699 done:
1700   if(ret_value == FAIL)
1701     { /* Error condition cleanup */
1702 
1703     } /* end if */
1704 
1705   /* Normal function cleanup */
1706 
1707     return(ret_value);
1708 } /* end DFANIstart() */
1709 
1710 /*--------------------------------------------------------------------------
1711  NAME
1712     DFANPshutdown
1713  PURPOSE
1714     Terminate various static buffers.
1715  USAGE
1716     intn DFANPshutdown()
1717  RETURNS
1718     Returns SUCCEED/FAIL
1719  DESCRIPTION
1720     Free various buffers allocated in the DFAN routines.
1721  GLOBAL VARIABLES
1722  COMMENTS, BUGS, ASSUMPTIONS
1723     Should only ever be called by the "atexit" function HDFend
1724  EXAMPLES
1725  REVISION LOG
1726 --------------------------------------------------------------------------*/
DFANPshutdown(void)1727 intn DFANPshutdown(void)
1728 {
1729     DFANIclear();   /* frees the directory lists */
1730 
1731     if(Lastfile!=NULL)
1732       {
1733           HDfree(Lastfile);
1734           Lastfile=NULL;
1735       } /* end if */
1736     return(SUCCEED);
1737 } /* end DFANPshutdown() */
1738 
1739