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:     mfan.c
18  * Author:   GeorgeV
19  * Purpose:  Multi-file read and write annotations: labels and descriptions
20  *           of data items and file
21  * Invokes:
22  * Comments:
23  *           Currently the id returned by ANstart() is the same as the
24  *           one returned by Hopen().
25  *
26  *           Currently as least 4 TBBT trees are created to handle
27  *           annotations(1 for file_ann, 1 for file_desc, 1 for data_ann
28  *           and 1 for data_desc) for each file which is not pretty but it
29  *           does make search/find of annotations much easier.
30  *
31  *           NOTE2: Note that any mention of file ID's except in ANStart()
32  *                  should now refer to annotation interface ID.
33  *
34  * Contents:
35  *
36  *  Private Routines:
37  *  -----------------
38  *  NOTES: TYPE here refers to file/data label/description types
39  *         They are AN_FILE_LABEL, AN_FILE_DESC, AN_DATA_LABEL, AN_DATA_DESC
40  *         The tag/ref refers to data tag/ref
41  *
42  *  ANIinit      - Intialize the annotation interface
43  *  ANIdestroy   - Un-intialize the annotation interface
44  *
45  *  ANIanncmp    - compare two annotation handles(ann_id's)
46  *                  (used in annotation TBBTtree)
47  *  ANIaddentry:  - add entry to corresponding annotation TBBTtree
48  *  ANIcreate_ann_tree - create annotation TBBTtree
49  *  ANIfind:      - return annotation handle(ann_id) if found of given TYPE/ref
50  *  ANInumann:    - return number of annotations that match TYPE/tag/ref
51  *  ANIannlist:   - return list of handles(ann_id's) that match TYPE/tag/ref
52  *  ANIannlen:    - get length of annotation given handle(ann_id)
53  *  ANIreadann:   - read annotation given handle(ann_id)
54  *  ANIwriteann:  - write annotation given handle(ann_id)
55  *  ANIcreate     - create a new file/label annotation
56  *                  and return a handle(ann_id)
57  *
58  *  Public API routines:
59  *  --------------------
60  *  ANstart     - open file for annotation handling, returns an_id
61  *  ANfileinfo  - get number of file/data annotations in file. Indices returned
62  *                are used in ANselect() calls.
63  *  ANend       - end access to annotation handling on file
64  *  ANcreate    - create a new data annotation and return a handle(ann_id)
65  *  ANcreatef   - create a new file annotation and return a handle(ann_id)
66  *  ANselect    - returns an annotation handle(ann_id) from index for
67  *                a particular annotation TYPE. This handle is then used for
68  *                calls like ANwriteann(), ANreadann(), ANannlen(),..etc
69  *  ANnumann:   - return number of annotations that match TYPE/tag/ref
70  *  ANannlist:  - return list of handles(ann_id's) that match TYPE/tag/ref
71  *  ANannlen:   - get length of annotation given handle(ann_id)
72  *  ANreadann:  - read annotation given handle(ann_id)
73  *  ANwriteann: - write annotation given handle(ann_id)
74  *  ANendaccess - end access to annotation using handle(ann_id)
75  *
76  *  Public Miscellaneous API Routines
77  *  ---------------------------------
78  *  ANget_tagref - get tag/ref pair to annotation type and index
79  *  ANid2tagref  - get tag/ref pair to annotation ID
80  *  ANtagref2id  - get annotation id given tag/ref
81  *  ANatype2tag - annotation type to corresponding annotation TAG
82  *  ANtag2atype - annotation TAG to corresponding annotation type
83  *
84  *---------------------------------------------------------------------------*/
85 
86 #ifndef MFAN_MASTER  /* define main annotation source file */
87 #define MFAN_MASTER
88 
89 #include "mfan.h"
90 #include "atom.h"
91 #include "hfile.h" /* needed for filerec_t */
92 
93 /* Whether we've installed the library termination function yet for this
94    interface */
95 PRIVATE intn library_terminate = FALSE;
96 
97 /* Function Prototypes for fcns used by TBBT. Can not be PRIVATE. */
98 extern void ANfreedata(void * data);
99 extern void ANfreekey(void * key);
100 extern void dumpentryKey(void *key, void *data);
101 extern intn ANIanncmp(void * i, void * j, intn value);
102 
103 /* private initialization routine */
104 PRIVATE intn ANIstart(void);
105 
106 /*-----------------------------------------------------------------------------
107  *                          Internal Routines
108  *---------------------------------------------------------------------------*/
109 
110 /* ------------------------ Routines for TBBT ------------------------------*/
111 /* free data - used by tbbt routines */
112 void
ANfreedata(void * data)113 ANfreedata(void * data)
114 {
115     HDfree(data);
116 } /* ANfreekey() */
117 
118 /* free key - used by tbbt routines */
119 void
ANfreekey(void * key)120 ANfreekey(void * key)
121 {
122     HDfree(key);
123 } /* ANfreekey() */
124 
125 #ifdef AN_DEBUG
126 /* The following routine is used for debugging purposes to dump
127  * key/data pairs from the TBBT trees
128  * eg. tbbt_dump(tree, dumpentryKey, 0)*/
129 void
dumpentryKey(void * key,void * data)130 dumpentryKey(void *key, void *data)
131 {
132     ANentry *node = NULL;
133 
134     printf("key = %4.4d, data = ",*(int*)key);
135     if (data != NULL)
136       {
137           node = (ANentry *) data;
138           printf("ann_id=%ld, annref=%d, elmtag=%d, elmref=%d\n",
139                  (long)node->ann_id, node->annref, node->elmtag, node->elmref);
140       }
141     else
142         printf("(NULL)\n");
143     return;
144 } /* dumpentryKey() */
145 #endif /* AN_DEBUG */
146 
147 /* ------------------------ Private Internal Routines ---------------------*/
148 
149 /* ------------------------------- ANIanncmp --------------------------------
150  NAME
151 	ANIanncmp -- compare two annotation keys or id's
152 
153  DESCRIPTION
154     Compares two annotation keys. Used by tree for annotations
155     Also used to compare annotation id's since also 32 bit value.
156 
157  RETURNS
158     Returns 0 if i=j, -1 if i > j and 1 if i < j
159 
160  AUTHOR
161     GeorgeV.
162 --------------------------------------------------------------------------- */
163 intn
ANIanncmp(void * i,void * j,intn value)164 ANIanncmp(void * i,   /* IN: annotation key(tag,ref) */
165           void * j,   /* IN: annotation key(tag,ref) */
166           intn value /* not used */)
167 {
168     /* shut compiler up */
169     value = value;
170 
171     if (*(int32 *)i == *(int32 *)j)
172         return 0;
173     if (*(int32 *)i > *(int32 *)j)
174         return -1;
175     else
176         return 1;
177 } /* ANIanncmp */
178 
179 /* ------------------------------- ANIdestroy --------------------------------
180  NAME
181 	ANIdestroy -- Un-Initialize Annotation Interface
182 
183  DESCRIPTION
184     Destroys annotation Atom group ANIDGROUP. This routine is usually
185     registered with the atexit() rouinte.
186 
187  RETURNS
188     SUCCEED or FAIL
189 
190  AUTHOR
191     GeorgeV.
192 
193 --------------------------------------------------------------------------- */
194 intn
ANIdestroy(void)195 ANIdestroy(void)
196 {
197 #ifdef LATER
198     CONSTR(FUNC, "ANIdestroy");
199 #endif /* LATER */
200     int32    ret_value = SUCCEED;
201 
202     /* Clear error stack */
203     HEclear();
204 
205     /* Destroy the atom groups for annotations */
206     HAdestroy_group(ANIDGROUP);
207 
208     return ret_value;
209 } /* ANIdestroy () */
210 
211 /*--------------------------------------------------------------------------
212  NAME
213     ANIstart - AN-level initialization routine.
214 
215  DESCRIPTION
216     Register the shut-down routine (ANPdestroy) for call with atexit()
217 
218  RETURNS
219     Returns SUCCEED/FAIL
220 
221  AUTHOR
222     GeorgeV.
223 
224 --------------------------------------------------------------------------*/
225 PRIVATE intn
ANIstart(void)226 ANIstart(void)
227 {
228     CONSTR(FUNC, "ANIstart");    /* for HERROR */
229     intn        ret_value = SUCCEED;
230 
231     /* Don't call this routine again... */
232     library_terminate = TRUE;
233 
234     /* Install atexit() library cleanup routine ANIdestroy() */
235     if (HPregister_term_func(&ANIdestroy) != 0)
236         HGOTO_ERROR(DFE_CANTINIT, FAIL);
237 
238   done:
239     if(ret_value == FAIL)
240       { /* Error condition cleanup */
241 
242       } /* end if */
243 
244     /* Normal function cleanup */
245 
246     return(ret_value);
247 } /* end ANIstart() */
248 
249 /* ------------------------------- ANIinit --------------------------------
250  NAME
251 	ANIinit -- Initialize Annotation Interface
252 
253  DESCRIPTION
254     Initializes the annotation interface i.e. installs library
255     cleanup routine and creates the Atom group ANIDGROUP for annotations
256     if necessary.
257 
258  RETURNS
259     SUCCEED or FAIL
260 
261  AUTHOR
262     GeorgeV.
263 
264 --------------------------------------------------------------------------- */
265 PRIVATE int32
ANIinit(void)266 ANIinit(void)
267 {
268     CONSTR(FUNC, "ANIinit");
269     int32 ret_value = SUCCEED;
270 
271     /* Clear error stack */
272     HEclear();
273 
274     /* Perform global, one-time initialization */
275     if (library_terminate == FALSE)
276       {
277         if(ANIstart()==FAIL)
278             HGOTO_ERROR(DFE_CANTINIT, FAIL);
279 
280         /* Initialize the atom groups for annotations */
281         HAinit_group(ANIDGROUP,ANATOM_HASH_SIZE);
282       }
283 
284   done:
285     if(ret_value == FAIL)
286       { /* Error condition cleanup */
287 
288       } /* end if */
289 
290     /* Normal function cleanup */
291 
292     return ret_value;
293 } /* ANIinit() */
294 
295 /*--------------------------------------------------------------------------
296  NAME
297    ANIaddentry -- add entry to corresponding annotation TBBT tree and
298                   atom group.
299 
300  DESCRIPTION
301    Adds annotation to correct tree and register with atom group
302 
303  RETURNS
304    annotation ID if successful and FAIL (-1) otherwise
305 
306  AUTHOR
307     GeorgeV.
308 
309  -------------------------------------------------------------------------*/
310 PRIVATE int32
ANIaddentry(int32 an_id,ann_type type,uint16 ann_ref,uint16 elmtag,uint16 elmref,intn new_ann)311 ANIaddentry(int32 an_id,    /* IN: annotation interface id */
312             ann_type type,  /* IN: annotation type
313                                    AN_DATA_LABEL for data labels,
314                                    AN_DATA_DESC for data descriptions,
315                                    AN_FILE_LABEL for file labels,
316                                    AN_FILE_DESC for file descritpions.*/
317             uint16 ann_ref, /* IN: ref of annotation */
318             uint16 elmtag,  /* IN: tag of item of which this is annotation */
319             uint16 elmref,  /* IN: ref of item of which this is annotation */
320             intn new_ann    /* IN: new annotation flag */)
321 {
322     CONSTR(FUNC, "ANIaddentry");
323     filerec_t   *file_rec = NULL;		/* file record pointer */
324     uint16       ann_tag  = DFTAG_NULL;
325     int32       *ann_key  = NULL;
326     ANentry     *ann_entry  = NULL;
327     ANnode      *ann_node   = NULL;
328     int32        ret_value  = SUCCEED;
329 
330     /* Clear error stack */
331     HEclear();
332 
333     /* convert an_id i.e. file_id to file rec and check for validity */
334     file_rec = HAatom_object(an_id);
335     if (BADFREC(file_rec))
336         HGOTO_ERROR(DFE_ARGS, FAIL);
337 
338     /* Check for empty annotation tree of 'type'? */
339     if (file_rec->an_num[type] == -1)
340       {
341           if ((file_rec->an_tree[type] =
342                (TBBT_TREE *) tbbtdmake(ANIanncmp,sizeof(int32),0)) == NULL)
343             {
344               HE_REPORT_GOTO("failed to create annotation tree", FAIL);
345             }
346 
347           file_rec->an_num[type] = 0;
348       }
349 
350     /* Which type of annotation file/data label or desc? */
351     switch((ann_type)type)
352       {
353       case AN_DATA_LABEL:
354           ann_tag = DFTAG_DIL;
355           break;
356       case AN_DATA_DESC:
357           ann_tag = DFTAG_DIA;
358           break;
359       case AN_FILE_LABEL:
360           ann_tag = DFTAG_FID;
361           break;
362       case AN_FILE_DESC:
363           ann_tag = DFTAG_FD;
364           break;
365       default:
366           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
367       }
368 
369     /* allocate space for key */
370     if ((ann_key = (int32 *)HDmalloc(sizeof(int32))) == NULL)
371         HGOTO_ERROR(DFE_NOSPACE, FAIL);
372 
373     /* Create 32bit key from type/ref
374      *  ----------------------------
375      *  | type(16bits)| ref(16bits) |
376      *  -----------------------------*/
377     *ann_key = AN_CREATE_KEY(type, ann_ref);
378 
379     /* Initialize annotation node for insertion in annotation atom group*/
380     if ((ann_node = HDmalloc(sizeof(ANnode))) == NULL)
381         HGOTO_ERROR(DFE_NOSPACE, FAIL);
382 
383     ann_node->file_id = an_id;
384     ann_node->ann_key = *ann_key;
385     ann_node->new_ann = new_ann;
386 
387     /* Initialize annotation entry for insertion into corresponding TBBT */
388     if ((ann_entry = HDmalloc(sizeof(ANentry))) == NULL)
389         HGOTO_ERROR(DFE_NOSPACE, FAIL);
390 
391     /* register annotation with atom group ANIDGROUP */
392     ann_entry->annref  = ann_ref;
393     ann_entry->ann_id = HAregister_atom(ANIDGROUP,ann_node);
394     if (FAIL == ann_entry->ann_id)
395         HE_REPORT_GOTO("failed to insert annotation into ANIDGROUP atom group",
396                        FAIL);
397 
398     if (type == AN_DATA_LABEL || type == AN_DATA_DESC)
399       {
400           ann_entry->elmtag = (uint16) elmtag;
401           ann_entry->elmref = (uint16) elmref;
402       }
403     else
404       {
405           ann_entry->elmtag = ann_tag;
406           ann_entry->elmref = ann_ref;
407       }
408 
409     /* Add annotation entry to 'type' tree */
410     if (tbbtdins(file_rec->an_tree[type], ann_entry, ann_key) == NULL)
411         HE_REPORT_GOTO("failed to insert annotation into 'type' tree", FAIL);
412 
413     /* increment number of annotatiosn of 'type' */
414     file_rec->an_num[type] += 1;
415 
416     /* return annotation id */
417     ret_value = ann_entry->ann_id;
418 
419   done:
420     if(ret_value == FAIL)
421       { /* Error condition cleanup */
422           if (ann_key != NULL)
423               HDfree(ann_key);
424           if (ann_entry != NULL)
425               HDfree(ann_entry);
426           if (ann_node != NULL)
427               HDfree(ann_node);
428       } /* end if */
429 
430     /* Normal function cleanup */
431 
432     return ret_value;
433 } /* ANIaddentry */
434 
435 /*--------------------------------------------------------------------------
436  NAME
437    ANIcreate_ann_tree --  create an annotation tree of 'type' for given file
438 
439  DESCRIPTION
440    Creates either a label or descritption annotation TBBT tree.
441 
442  RETURNS
443    Number of annotations of 'type' in file if successful and
444    FAIL (-1) otherwise
445 
446  AUTHOR
447     GeorgeV.
448 
449  -------------------------------------------------------------------------*/
450 PRIVATE intn
ANIcreate_ann_tree(int32 an_id,ann_type type)451 ANIcreate_ann_tree(int32    an_id,/* IN: annotation interface id */
452                    ann_type type  /* IN: AN_DATA_LABEL for data labels,
453                                          AN_DATA_DESC for data descriptions,
454                                          AN_FILE_LABEL for file labels,
455                                          AN_FILE_DESC for file descritpions.*/)
456 {
457     CONSTR(FUNC, "ANIcreate_ann_tree");
458     filerec_t  *file_rec = NULL;		/* file record pointer */
459     uint8       datadi[4];
460     int32       more_anns;
461     int32       aid = FAIL;
462     int32       nanns;
463     int32       i;
464     int32      *ann_key = NULL;
465     uint16      ann_tag;
466     uint16      ann_ref;
467     uint8      *dptr = NULL;
468     ANentry    *ann_entry  = NULL;
469     ANnode     *ann_node   = NULL;
470     intn        ret_value  = SUCCEED;
471 
472     /* Clear error stack */
473     HEclear();
474 
475     /* convert an_id i.e. file_id to file rec and check for validity */
476     file_rec = HAatom_object(an_id);
477     if (BADFREC(file_rec))
478         HGOTO_ERROR(DFE_ARGS, FAIL);
479 
480     /* Check for empty annotation tree of 'type'? */
481     if (file_rec->an_num[type] == -1)
482       {
483           if ((file_rec->an_tree[type] =
484                (TBBT_TREE *) tbbtdmake(ANIanncmp,sizeof(int32),0)) == NULL)
485             {
486               HE_REPORT_GOTO("failed to create annotation tree", FAIL);
487             }
488           file_rec->an_num[type] = 0; /* initialize to zero entries */
489       }
490     else
491       {
492           ret_value = file_rec->an_num[type];  /* tree already created */
493           goto done; /* we are done */
494       }
495 
496     /* Which type of annotation data/file label or desc? */
497     switch((ann_type)type)
498       {
499       case AN_DATA_LABEL:
500           ann_tag = DFTAG_DIL;
501           break;
502       case AN_DATA_DESC:
503           ann_tag = DFTAG_DIA;
504           break;
505       case AN_FILE_LABEL:
506           ann_tag = DFTAG_FID;
507           break;
508       case AN_FILE_DESC:
509           ann_tag = DFTAG_FD;
510           break;
511       default:
512           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
513       }
514 
515     /* Get number of annotations of 'type' in file */
516     if ((nanns = Hnumber(an_id, ann_tag)) == 0)
517       { /* ZERO annotations of 'type' in file */
518           file_rec->an_num[type] = 0;
519           ret_value =  file_rec->an_num[type];
520           goto done; /* we are done */
521       }
522 
523     /* start read on 'type' annotations  in file
524      * note that so far an_id == file_id */
525     if ((aid = Hstartread(an_id, ann_tag, DFREF_WILDCARD)) == FAIL)
526       {
527         HE_REPORT_GOTO("Hstartread failed to read annotation", FAIL);
528       }
529     else
530         more_anns = SUCCEED;
531 
532     /* Process annotations of 'type' in file */
533     for (i = 0; (i < nanns) && (more_anns != FAIL); i++)
534       { /* see if annotation is there */
535           if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, &ann_ref,
536                                (int32 *) NULL, (int32 *) NULL, (int32 *) NULL,
537                                (int16 *) NULL, (int16 *) NULL))
538             {   /* record what we found so far and return */
539                 file_rec->an_num[type] = nanns;
540                 ret_value =  FAIL;
541                 goto done; /* we are done */
542             }
543 
544           /* if data annotation, read data annotation tag/ref */
545           if(type != AN_FILE_LABEL && type != AN_FILE_DESC)
546             {
547                 if ((int32) FAIL == Hread(aid, (int32) 4, datadi))
548                   {   /* record what we found so far and return */
549                       file_rec->an_num[type] = nanns;
550                       ret_value =  FAIL;
551                       goto done; /* we are done */
552                   }
553             }
554 
555           /* allocate space for key */
556           if ((ann_key = (int32 *)HDmalloc(sizeof(int32))) == NULL)
557               HGOTO_ERROR(DFE_NOSPACE, FAIL);
558 
559           /* Create key from tag/ref pair
560            *  ----------------------------
561            *  | tag(16bits) | ref(16bits) |
562            *  -----------------------------*/
563           *ann_key = AN_CREATE_KEY(type, ann_ref);
564 
565           /* Initialize annotation node for insertion in annotation atom group*/
566           if ((ann_node = HDmalloc(sizeof(ANnode))) == NULL)
567               HGOTO_ERROR(DFE_NOSPACE, FAIL);
568 
569           ann_node->file_id = an_id;
570           ann_node->ann_key = *ann_key;
571           ann_node->new_ann = 0;       /* not a newly created annotation */
572 
573           /* Initialize annotation entry for insertion into corresponding TBBT */
574           /* and  decode data tag/ref */
575           if ((ann_entry = HDmalloc(sizeof(ANentry))) == NULL)
576               HGOTO_ERROR(DFE_NOSPACE, FAIL);
577 
578           ann_entry->annref  = ann_ref;
579           /* ann_entry->ann_id  = *ann_id = num_anns++; */
580           ann_entry->ann_id = HAregister_atom(ANIDGROUP,ann_node);
581           if (FAIL == ann_entry->ann_id)
582               HE_REPORT_GOTO("failed to insert annotation into ann_id Group", FAIL);
583 
584           /* Check if data annotation to decode data tag/ref */
585           if(type != AN_FILE_LABEL && type != AN_FILE_DESC)
586             {
587                 dptr = (uint8 *) &(datadi[0]);
588                 UINT16DECODE(dptr, ann_entry->elmtag);
589                 UINT16DECODE(dptr, ann_entry->elmref);
590             }
591           else
592             {
593                 ann_entry->elmtag = ann_tag;
594                 ann_entry->elmref = ann_ref;
595             }
596 
597           /* Add annotation entry to 'type' tree */
598           if (tbbtdins(file_rec->an_tree[type], ann_entry, ann_key) == NULL)
599               HE_REPORT_GOTO("failed to insert annotation into 'type' tree", FAIL);
600 
601           /* set read on next annotation */
602           more_anns = Hnextread(aid, ann_tag, DFREF_WILDCARD, DF_CURRENT);
603       } /* end for "more_anns" */
604 
605     /* Finish access*/
606     if (FAIL != aid)
607       {
608         if (FAIL == Hendaccess(aid))
609             HGOTO_ERROR(DFE_INTERNAL, FAIL);
610       }
611 
612     /* set return value */
613     ret_value = file_rec->an_num[type] = nanns;
614 
615   done:
616     if(ret_value == FAIL)
617       { /* Error condition cleanup */
618           if (ann_key != NULL)
619               HDfree(ann_key);
620           if (ann_entry != NULL)
621               HDfree(ann_entry);
622           if (ann_node != NULL)
623               HDfree(ann_node);
624           if (FAIL != aid)
625               Hendaccess(aid);
626       } /* end if */
627 
628     /* Normal function cleanup */
629 
630     return ret_value;
631 } /* ANIcreate_ann_tree */
632 
633 #if NOT_USED_YET
634 /*--------------------------------------------------------------------------
635  NAME
636      ANIfind -- find annotation id for given annotation type and ref number
637 
638  DESCRIPTION
639      Find annotation id for the given annotation type and ref number
640 
641  RETURNS
642     Annotation id if successful and FAIL (-1) otherwise
643 
644  AUTHOR
645     GeorgeV.
646 
647  -------------------------------------------------------------------------*/
648 PRIVATE int32
ANIfind(int32 an_id,ann_type type,uint16 ann_ref)649 ANIfind(int32    an_id, /* IN: annotation interface id */
650         ann_type type,  /* IN: AN_DATA_LABEL for data labels,
651                                AN_DATA_DESC for data descriptions,
652                                AN_FILE_LABEL for file labels,
653                                AN_FILE_DESC for file descritpions.*/
654         uint16   ann_ref /* IN: ref of annotation */)
655 {
656     CONSTR(FUNC, "ANIfind");
657     filerec_t  *file_rec = NULL;		/* file record pointer */
658     TBBT_NODE  *entry    = NULL;
659     ANentry    *ann_entry  = NULL;
660     int32       ann_key;
661     int32       ret_value = SUCCEED;
662 
663     /* Clear error stack */
664     HEclear();
665 
666     /* convert an_id i.e. file_id to file rec and check for validity */
667     file_rec = HAatom_object(an_id);
668     if (BADFREC(file_rec))
669         HGOTO_ERROR(DFE_ARGS, FAIL);
670 
671     /* Check for empty annotation tree of 'type'? */
672     if (file_rec->an_num[type] == -1)
673       {
674           if ((file_rec->an_tree[type] =
675                (TBBT_TREE *) tbbtdmake(ANIanncmp,sizeof(int32),0)) == NULL)
676             {
677               HE_REPORT_GOTO("failed to create annotation tree", FAIL);
678             }
679 
680           file_rec->an_num[type] = 0; /* intialize after allocation */
681       }
682 
683     /* Create key from type/ref pair
684      *  ----------------------------
685      *  | type(16bits) | ref(16bits) |
686      *  -----------------------------*/
687     ann_key = AN_CREATE_KEY(type, ann_ref);
688 
689     /* See if annotation of 'type' with ref exits */
690     if ((entry = tbbtdfind(file_rec->an_tree[type], &ann_key, NULL)) == NULL)
691         HE_REPORT_GOTO("failed to find annotation of 'type'", FAIL);
692 
693     /* get annotation entry from node */
694     ann_entry = (ANentry *) entry->data;
695 
696     /* return annotation id */
697     ret_value = ann_entry->ann_id;
698 
699   done:
700     if(ret_value == FAIL)
701       { /* Error condition cleanup */
702 
703       } /* end if */
704 
705     /* Normal function cleanup */
706 
707     return ret_value;
708 } /* ANIfind */
709 #endif /* NOT_USED_YET */
710 
711 /*--------------------------------------------------------------------------
712  NAME
713    ANInumann -- find number of annotation of 'type' that
714                  match the given element tag/ref
715 
716  DESCRIPTION
717    Find number of annotation of 'type' for the given element
718    tag/ref pair. Not used for file lables/descs since there
719    can only be one set of them for a file.
720 
721  RETURNS
722    Number of annotation found if successful and FAIL (-1) otherwise
723 
724  AUTHOR
725     GeorgeV.
726 
727  -------------------------------------------------------------------------*/
728 PRIVATE intn
ANInumann(int32 an_id,ann_type type,uint16 elem_tag,uint16 elem_ref)729 ANInumann(int32    an_id,   /* IN: annotation interface id */
730           ann_type type,    /* IN: AN_DATA_LABEL for data labels,
731                                    AN_DATA_DESC for data descriptions,
732                                    AN_FILE_LABEL for file labels,
733                                    AN_FILE_DESC for file descritpions.*/
734           uint16   elem_tag, /* IN: tag of item of which this is annotation */
735           uint16   elem_ref  /* IN: ref of item of which this is annotation */)
736 {
737     CONSTR(FUNC, "ANInumann");
738     filerec_t  *file_rec = NULL;		/* file record pointer */
739     TBBT_NODE  *entry    = NULL;
740     ANentry    *ann_entry = NULL;
741     intn        nanns     = 0;
742     intn        ret_value = SUCCEED;
743 
744     /* Clear error stack */
745     HEclear();
746 
747     /* convert an_id i.e. file_id to file rec and check for validity */
748     file_rec = HAatom_object(an_id);
749     if (BADFREC(file_rec))
750         HGOTO_ERROR(DFE_ARGS, FAIL);
751 
752     /* Empty annotation tree */
753     if (file_rec->an_num[type] == -1)
754       {
755           if (ANIcreate_ann_tree(an_id, type) == FAIL)
756               HGOTO_ERROR(DFE_BADCALL, FAIL);
757       }
758 
759     /* Traverse the list looking for a match */
760     for(entry = tbbtfirst((TBBT_NODE *)*(file_rec->an_tree[type]));
761         entry != NULL; entry = tbbtnext(entry))
762       {
763           ann_entry = (ANentry *) entry->data; /* get annotation entry from node */
764           if ((ann_entry->elmref == elem_ref) && (ann_entry->elmtag == elem_tag))
765             {
766                 nanns++; /* increment ref counter if match */
767             }
768       }
769 
770     /* return number of annotation references found for tag/ref */
771     ret_value = nanns;
772 
773   done:
774     if(ret_value == FAIL)
775       { /* Error condition cleanup */
776 
777       } /* end if */
778 
779     /* Normal function cleanup */
780 
781     return ret_value;
782 } /* ANInumann */
783 
784 /*--------------------------------------------------------------------------
785  NAME
786    ANIannlist -- generate list of annotation ids of 'type' that
787                  match the given element tag/ref
788 
789  DESCRIPTION
790        Find and generate list of annotation ids of 'type' for the given
791        element tag/ref pair
792 
793  RETURNS
794        number of annotations ids found if successful and FAIL (-1) otherwise
795 
796  AUTHOR
797     GeorgeV.
798 
799  ------------------------------------------------------------------------*/
800 PRIVATE intn
ANIannlist(int32 an_id,ann_type type,uint16 elem_tag,uint16 elem_ref,int32 ann_list[])801 ANIannlist(int32    an_id,    /* IN: annotation interface id */
802            ann_type type,     /* IN: AN_DATA_LABEL for data labels,
803                                      AN_DATA_DESC for data descriptions,
804                                      AN_FILE_LABEL for file labels,
805                                      AN_FILE_DESC for file descritpions.*/
806            uint16   elem_tag, /* IN: tag of item of which this is annotation*/
807            uint16   elem_ref, /* IN: ref of item of which this is annotation */
808            int32    ann_list[]/* OUT: array of ann_id's that match criteria. */)
809 {
810     CONSTR(FUNC, "ANIannlist");
811     filerec_t  *file_rec = NULL;		/* file record pointer */
812     TBBT_NODE  *entry    = NULL;
813     ANentry    *ann_entry = NULL;
814     intn        nanns     = 0;
815     intn        ret_value = SUCCEED;
816 
817     /* Clear error stack */
818     HEclear();
819 
820     /* convert an_id i.e. file_id to file rec and check for validity */
821     file_rec = HAatom_object(an_id);
822     if (BADFREC(file_rec))
823         HGOTO_ERROR(DFE_ARGS, FAIL);
824 
825     /* Empty annotation tree */
826     if (file_rec->an_num[type] == -1)
827       {
828           if (ANIcreate_ann_tree(an_id, type) == FAIL)
829               HGOTO_ERROR(DFE_BADCALL, FAIL);
830       }
831 
832     /* Traverse the list looking for a match */
833     for(entry = tbbtfirst((TBBT_NODE *)*(file_rec->an_tree[type]));
834         entry != NULL; entry = tbbtnext(entry))
835       {
836           ann_entry = (ANentry *) entry->data; /* get annotation entry from node */
837           if ((ann_entry->elmref == elem_ref) && (ann_entry->elmtag == elem_tag))
838             { /* save ref of ann match in list */
839                 ann_list[nanns++] = ann_entry->ann_id;
840             }
841       }
842 
843     /* return number of annotation id's found for tag/ref */
844     ret_value = nanns;
845 
846   done:
847     if(ret_value == FAIL)
848       { /* Error condition cleanup */
849 
850       } /* end if */
851 
852     /* Normal function cleanup */
853 
854     return ret_value;
855 } /* ANIannlist */
856 
857 /*--------------------------------------------------------------------------
858  NAME
859    ANIannlen -- get length of annotation givne annotation id
860 
861  DESCRIPTION
862    Uses the annotation id to find ann_key & file_id
863 
864  RETURNS
865    length of annotation if successful and FAIL (-1) otherwise
866 
867  AUTHOR
868     GeorgeV.
869 
870  ------------------------------------------------------------------------*/
871 PRIVATE int32
ANIannlen(int32 ann_id)872 ANIannlen(int32 ann_id /*  IN: annotation id */)
873 {
874     CONSTR(FUNC, "ANIannlen");
875     ANnode    *ann_node   = NULL;
876     int32      file_id = FAIL;
877     int32      type;
878     int32      ann_key;
879     uint16     ann_tag;
880     uint16     ann_ref;
881     int32      ann_length =(-1);
882     int32      ret_value  = SUCCEED;
883 
884     /* Clear error stack */
885     HEclear();
886 
887     /* get annotation record */
888     ann_node = HAatom_object(ann_id);
889     if (NULL == ann_node)
890         HGOTO_ERROR(DFE_ARGS, FAIL);
891 
892     /* get file id and annotation key */
893     file_id = ann_node->file_id;
894     ann_key = ann_node->ann_key;
895     type    = AN_KEY2TYPE(ann_key);
896     ann_ref = AN_KEY2REF(ann_key);
897 
898     /* Valid file id */
899     if (file_id == FAIL)
900         HE_REPORT_GOTO("bad file_id", FAIL);
901 
902     /* set type annotation tag */
903     switch((int32)type)
904       {
905       case AN_DATA_LABEL:
906           ann_tag = DFTAG_DIL;
907           break;
908       case AN_DATA_DESC:
909           ann_tag = DFTAG_DIA;
910           break;
911       case AN_FILE_LABEL:
912           ann_tag = DFTAG_FID;
913           break;
914       case AN_FILE_DESC:
915           ann_tag = DFTAG_FD;
916           break;
917       default:
918           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
919       }
920 
921     if (ann_tag == DFTAG_DIL || ann_tag == DFTAG_DIA)
922       {  /* 4=length of data tag/ref for data label or description */
923           if ((ann_length = Hlength(file_id, ann_tag, ann_ref)) == FAIL)
924               HE_REPORT_GOTO("Failed to find annotation length", FAIL);
925           ann_length -= 4;
926       }
927     else if (ann_tag == DFTAG_FID || ann_tag == DFTAG_FD)
928       {  /* not data tag/ref for file label or description */
929           if ((ann_length = Hlength(file_id, ann_tag, ann_ref)) == FAIL)
930               HE_REPORT_GOTO("Failed to find annotation length", FAIL);
931       }
932 
933     /* return the length */
934     ret_value = (ann_length);
935 
936   done:
937     if(ret_value == FAIL)
938       { /* Error condition cleanup */
939 
940       } /* end if */
941 
942     /* Normal function cleanup */
943 
944     return ret_value;
945 } /* ANIannlen */
946 
947 /*--------------------------------------------------------------------------
948  NAME
949    ANIreadann -- read annotation given ann_id
950 
951  DESCRIPTION
952    Gets tag and ref of annotation.  Finds DD for that annotation.
953    Reads the annotation, taking care of NULL terminator, if necessary.
954 
955  RETURNS
956    SUCCEED (0) if successful and FAIL (-1) otherwise
957 
958  AUTHOR
959     GeorgeV.
960 
961  ------------------------------------------------------------------------*/
962 PRIVATE intn
ANIreadann(int32 ann_id,char * ann,int32 maxlen)963 ANIreadann(int32 ann_id, /* IN: annotation id (handle) */
964            char *ann,    /* OUT: space to return annotation in */
965            int32 maxlen  /* IN: size of space to return annotation in */)
966 {
967     CONSTR(FUNC, "ANIreadann");
968     ANnode  *ann_node   = NULL;
969     int32   file_id = FAIL;
970     int32   type;
971     int32   ann_key;
972     int32   aid = FAIL;
973     int32   ann_len;
974     uint16  ann_tag;
975     uint16  ann_ref;
976     uint8   datadi[4] = {0,0,0,0};   /* to read in and discard data/ref! */
977     intn    ret_value = SUCCEED;
978 
979     /* Clear error stack */
980     HEclear();
981 
982     /* get annotation record */
983     ann_node = HAatom_object(ann_id);
984     if (NULL == ann_node)
985         HGOTO_ERROR(DFE_ARGS, FAIL);
986 
987     /* get file id and annotation key */
988     file_id = ann_node->file_id;
989     ann_key = ann_node->ann_key;
990     type    = AN_KEY2TYPE(ann_key);
991     ann_ref = AN_KEY2REF(ann_key);
992 
993     /* Valid file id */
994     if (file_id == FAIL)
995         HE_REPORT_GOTO("bad file_id", FAIL);
996 
997     /* set type tag */
998     switch((int32)type)
999       {
1000       case AN_DATA_LABEL:
1001           ann_tag = DFTAG_DIL;
1002           break;
1003       case AN_DATA_DESC:
1004           ann_tag = DFTAG_DIA;
1005           break;
1006       case AN_FILE_LABEL:
1007           ann_tag = DFTAG_FID;
1008           break;
1009       case AN_FILE_DESC:
1010           ann_tag = DFTAG_FD;
1011           break;
1012       default:
1013           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
1014       }
1015 
1016     /* find DD for that annotation using tag/ref */
1017     aid = Hstartread(file_id, ann_tag, ann_ref);
1018     if (aid == FAIL)
1019         HE_REPORT_GOTO("Failed to get access to annotation",FAIL);
1020 
1021     if (FAIL == Hinquire(aid, (int32 *) NULL, (uint16 *) NULL, (uint16 *) NULL,
1022                          &ann_len, (int32 *) NULL, (int32 *) NULL,
1023                          (int16 *) NULL, (int16 *) NULL))
1024       {
1025           HE_REPORT_GOTO("Failed to get annotation",FAIL);
1026       }
1027 
1028     /* first four bytes were tag/ref if data annotation, so they don't count */
1029     if (ann_tag == DFTAG_DIL || ann_tag == DFTAG_DIA)
1030         ann_len -= 4;
1031 #ifdef AN_DEBUG
1032     printf("ANIreadann: from Hinquire, ann_len=%d, maxlen=%d\n",
1033            ann_len, maxlen);
1034 #endif
1035     /* Check length of space provided
1036      * if not enough space, truncate annotation
1037      * Labels need space for null terminator, Descriptions don't */
1038     if (ann_tag == DFTAG_FID || ann_tag == DFTAG_DIL)
1039       { /* Labels */
1040           if (ann_len > maxlen - 1)
1041               ann_len = maxlen - 1;
1042       }
1043     else
1044       { /* Descriptions */
1045           if (ann_len > maxlen)
1046               ann_len = maxlen;
1047       }
1048 
1049     /* If data label or description need to read past tag/ref */
1050     if (ann_tag == DFTAG_DIL || ann_tag == DFTAG_DIA)
1051       { /* Data label/description */
1052           if ((int32) FAIL == Hread(aid, (int32) 4, datadi))
1053               HE_REPORT_GOTO("Failed to go past tag/ref",FAIL);
1054       }
1055 
1056     /* read itslef annotation now..*/
1057     if ((int32) FAIL == Hread(aid, ann_len, ann))
1058         HE_REPORT_GOTO("Failed to read annotation",FAIL);
1059 
1060     /* If Label need to NULL terminate string */
1061     if (ann_tag == DFTAG_FID || ann_tag == DFTAG_DIL)
1062         ann[ann_len] = '\0';
1063 #ifdef AN_DEBUG
1064     printf("ANIreadann: ann_len=%d, ann=%s\n", ann_len,ann);
1065 #endif
1066     /* Close access to annotation object */
1067     if (FAIL != aid)
1068       {
1069         if (FAIL == Hendaccess(aid))
1070             HGOTO_ERROR(DFE_INTERNAL, FAIL);
1071       }
1072 
1073   done:
1074     if(ret_value == FAIL)
1075       { /* Error condition cleanup */
1076           if (FAIL != aid)
1077               Hendaccess(aid);
1078       } /* end if */
1079 
1080     /* Normal function cleanup */
1081 
1082     return ret_value;
1083 } /* ANIreadann */
1084 
1085 /*--------------------------------------------------------------------------
1086  NAME
1087    ANIwriteann -- write annotation given ann_id
1088 
1089  DESCRIPTION
1090    Checks for pre-existence of given annotation, replacing old one if it
1091    exists. Writes out annotation.
1092 
1093  RETURNS
1094    SUCCEED (0) if successful and FAIL (-1) otherwise
1095 
1096  AUTHOR
1097     GeorgeV.
1098 
1099  ------------------------------------------------------------------------*/
1100 PRIVATE intn
ANIwriteann(int32 ann_id,const char * ann,int32 ann_len)1101 ANIwriteann(int32 ann_id,    /* IN: annotation id */
1102             const char *ann, /* IN: annotation to write */
1103             int32 ann_len    /* IN: length of annotation */)
1104 {
1105     CONSTR(FUNC, "ANIwriteann");
1106     filerec_t  *file_rec = NULL;		/* file record pointer */
1107     TBBT_NODE  *entry  = NULL;
1108     ANentry    *ann_entry  = NULL;
1109     ANnode     *ann_node   = NULL;
1110     int32       file_id = FAIL;
1111     int32       type;
1112     int32       ann_key;
1113     int32       aid = FAIL;
1114     int         newflag = 0;
1115     uint16      ann_tag;
1116     uint16      ann_ref;
1117     uint16      elem_tag;
1118     uint16      elem_ref;
1119     uint8       datadi[4] = {0,0,0,0};      /* to hold data tag/ref for writing */
1120     uint8      *ptr = NULL;
1121     intn        ret_value = SUCCEED;
1122 
1123     /* Clear error stack */
1124     HEclear();
1125 
1126     /* get annotation record */
1127     ann_node = HAatom_object(ann_id);
1128     if (NULL == ann_node)
1129         HGOTO_ERROR(DFE_ARGS, FAIL);
1130 
1131     /* get file id and annotation key */
1132     file_id = ann_node->file_id;
1133     ann_key = ann_node->ann_key;
1134     type    = AN_KEY2TYPE(ann_key);
1135     ann_ref = AN_KEY2REF(ann_key);
1136 
1137     /* convert file_id to file rec and check for validity */
1138     file_rec = HAatom_object(file_id);
1139     if (BADFREC(file_rec))
1140         HGOTO_ERROR(DFE_INTERNAL, FAIL);
1141 
1142     /* set type tag */
1143     switch((int32)type)
1144       {
1145       case AN_DATA_LABEL:
1146           ann_tag = DFTAG_DIL;
1147           break;
1148       case AN_DATA_DESC:
1149           ann_tag = DFTAG_DIA;
1150           break;
1151       case AN_FILE_LABEL:
1152           ann_tag = DFTAG_FID;
1153           break;
1154       case AN_FILE_DESC:
1155           ann_tag = DFTAG_FD;
1156           break;
1157       default:
1158           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
1159       }
1160 
1161     /* Get annotation entry so that we can extract tag/ref of element
1162      * Note that for file labels and descriptions the tag/ref contain
1163      * DFTAG_XXX and annotation reference number */
1164     if ((entry = tbbtdfind(file_rec->an_tree[type], &ann_key, NULL)) == NULL)
1165         HE_REPORT_GOTO("failed to retrieve annotation of 'type' tree", FAIL);
1166 
1167     ann_entry = (ANentry *) entry->data;
1168 
1169     elem_tag = ann_entry->elmtag;
1170     elem_ref = ann_entry->elmref;
1171     newflag  = ann_node->new_ann;
1172 
1173     /* is this a new annotation */
1174     if (newflag == 1)
1175       {
1176           ann_node->new_ann = 0; /* set new annotation entry to false */
1177       }
1178 
1179     /* If annotation exists, re-used the DD and rewrite new annotation
1180        while preserving tag/ref. We assume annotations are not stored
1181        as linked-blocks for now. */
1182     if (newflag == 0)
1183       {  /* annotation exists in file, re-writing */
1184           /* Not new, re-used the tag/ref(i.e. DD) for new annotation.
1185              pointer to old annotation is lost. */
1186           if (HDreuse_tagref(file_id, ann_tag, ann_ref) == FAIL)
1187               HE_REPORT_GOTO("Unable to replace old annotation",FAIL);
1188       }
1189 
1190     if (ann_tag == DFTAG_DIL || ann_tag == DFTAG_DIA)
1191       { /* Data label/description
1192          * Note: cannot use Hputelement because need to write data tag/ref */
1193           aid = Hstartwrite(file_id, ann_tag, ann_ref, ann_len + 4);
1194           if (aid == FAIL)
1195               HE_REPORT_GOTO("Failed to start write access on annotation",FAIL);
1196 
1197           /* Setup up to write annotation tag/ref */
1198           ptr = (uint8 *) &(datadi[0]);   /* first, write the object's tag/ref */
1199           UINT16ENCODE(ptr, elem_tag);
1200           UINT16ENCODE(ptr, elem_ref);
1201 
1202           /* write annotation tag/ref of element */
1203           if ((int32) FAIL == Hwrite(aid, (int32) 4, datadi))
1204               HE_REPORT_GOTO("Failed to write tag/ref of annotation",FAIL);
1205 
1206 #ifdef AN_DEBUG
1207           printf("ANIwriteann: ann_len=%d, ann=%s\n", ann_len,ann);
1208 #endif
1209           /* then write the annotation itself */
1210           if ((int32) FAIL == Hwrite(aid, ann_len, ann))
1211               HE_REPORT_GOTO("Failed to write annotation",FAIL);
1212 
1213           /* end access to annotation */
1214           if (FAIL == Hendaccess(aid))
1215               HE_REPORT_GOTO("Failed to end access to annotation",FAIL);
1216       }
1217     else /* file label/description */
1218       {
1219          /* write out file label/description */
1220           if (FAIL == Hputelement(file_id, ann_tag, ann_ref, (const uint8 *)ann, ann_len))
1221               HE_REPORT_GOTO("Failed to write file annotation",FAIL);
1222 #ifdef AN_DEBUG
1223           printf("ANIwriteann: fann_len=%d, fann=%s\n", ann_len,ann);
1224 #endif
1225       }
1226 
1227   done:
1228     if(ret_value == FAIL)
1229       { /* Error condition cleanup */
1230           if (FAIL != aid)
1231               Hendaccess(aid);
1232       } /* end if */
1233 
1234     /* Normal function cleanup */
1235 
1236     return ret_value;
1237 } /* ANIwriteann */
1238 
1239 /* ------------------------------- ANIcreate -------------------------------
1240  NAME
1241 	ANIcreate - create a new annotation and return a handle(id)
1242 
1243  DESCRIPTION
1244     Creates an annotation, returns an 'an_id' to work with the new
1245     annotation which can either be a label or description.
1246 
1247  RETURNS
1248     An ID to an annotation which can either be a label or description
1249 
1250  AUTHOR
1251     GeorgeV.
1252 
1253 --------------------------------------------------------------------------- */
1254 PRIVATE intn
ANIcreate(int32 file_id,uint16 elem_tag,uint16 elem_ref,ann_type type)1255 ANIcreate(int32    file_id,  /* IN: file ID */
1256           uint16   elem_tag, /* IN: tag of item to be assigned annotation */
1257           uint16   elem_ref, /* IN: reference number of itme to be assigned ann */
1258           ann_type type      /* IN: AN_DATA_LABEL for data labels,
1259                                     AN_DATA_DESC for data descriptions,
1260                                     AN_FILE_LABEL for file labels,
1261                                     AN_FILE_DESC for file descritpions.*/)
1262 {
1263     CONSTR(FUNC, "ANIcreate");    /* for HERROR */
1264     int32   ann_id = FAIL;
1265     uint16  ann_tag;
1266     uint16  ann_ref;
1267     intn    ret_value = SUCCEED;
1268 
1269     /* Clear error stack */
1270     HEclear();
1271 
1272     /* Valid file id */
1273     if (HAatom_group(file_id) != FIDGROUP)
1274         HGOTO_ERROR(DFE_ARGS, FAIL);
1275 
1276     /* deal with type */
1277     switch((ann_type)type)
1278       {
1279       case AN_DATA_LABEL:
1280           ann_tag = DFTAG_DIL;
1281           ann_ref = Htagnewref(file_id,ann_tag);
1282           break;
1283       case AN_DATA_DESC:
1284           ann_tag = DFTAG_DIA;
1285           ann_ref = Htagnewref(file_id,ann_tag);
1286           break;
1287       case AN_FILE_LABEL:
1288           /* for file label set elmement tag/ref to ann_tag & ref */
1289           ann_tag = DFTAG_FID;
1290           ann_ref = Htagnewref(file_id,ann_tag);
1291           elem_tag = ann_tag;
1292           elem_ref = ann_ref;
1293           break;
1294       case AN_FILE_DESC:
1295           /* for file desc set elmement tag/ref to ann_tag & ref */
1296           ann_tag = DFTAG_FD;
1297           ann_ref = Htagnewref(file_id,ann_tag);
1298           elem_tag = ann_tag;
1299           elem_ref = ann_ref;
1300           break;
1301       default:
1302           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
1303       }
1304 
1305     /* Check tag and ref */
1306     if (!elem_tag)
1307         HGOTO_ERROR(DFE_BADTAG, FAIL);
1308     if (!elem_ref)
1309         HGOTO_ERROR(DFE_BADREF, FAIL);
1310 
1311     /* put new annotation tag/ref into 'type' TBBTtree */
1312     if ((ann_id = ANIaddentry(file_id, type, ann_ref, elem_tag, elem_ref, 1)) == FAIL)
1313         HE_REPORT_GOTO("Failed to add annotation to TBBT tree",FAIL);
1314 
1315     ret_value = ann_id;
1316 
1317   done:
1318     if(ret_value == FAIL)
1319       { /* Error condition cleanup */
1320 
1321       } /* end if */
1322 
1323     /* Normal function cleanup */
1324 
1325     return ret_value;
1326 } /* ANIcreate() */
1327 
1328 /* --------------------- Exported Multi-file Interface ----------------------*/
1329 
1330 /* ------------------------------- ANstart --------------------------------
1331  NAME
1332 	ANstart -- open file for annotation handling
1333 
1334  DESCRIPTION
1335     Start annotation handling on the file return a annotation ID to the file.
1336 
1337  RETURNS
1338     A file ID or FAIL. Note that we use 'an_id' which is the same
1339     as the file id.
1340 
1341  AUTHOR
1342     GeorgeV.
1343 
1344 --------------------------------------------------------------------------- */
1345 EXPORT int32
ANstart(int32 file_id)1346 ANstart(int32 file_id /* IN: file to start annotation access on*/)
1347 {
1348     CONSTR(FUNC, "ANstart");
1349     filerec_t  *file_rec = NULL;		/* file record pointer */
1350     int32       ret_value = SUCCEED;
1351 
1352     /* Clear error stack */
1353     HEclear();
1354 
1355     /* convert file id to file rec and check for validity */
1356     file_rec = HAatom_object(file_id);
1357     if (BADFREC(file_rec))
1358         HGOTO_ERROR(DFE_ARGS, FAIL);
1359 
1360     /* call ANIinit, should just register termination function once
1361        no matter how many times it is called. */
1362     ANIinit();
1363 
1364     ret_value = file_id;
1365 
1366   done:
1367     if(ret_value == FAIL)
1368       { /* Error condition cleanup */
1369       } /* end if */
1370 
1371     /* Normal function cleanup */
1372     return ret_value;
1373 } /* ANstart() */
1374 
1375 /*--------------------------------------------------------------------------
1376  NAME
1377     ANfileinfo - Report high-level information about the ANxxx interface
1378                  for a given file.
1379 
1380  DESCRIPTION
1381     Reports general information about the number of file and object(i.e. data)
1382     annotations in the file. This routine is generally used to find
1383     the range of acceptable indices for ANselect calls.
1384 
1385  RETURNS
1386     SUCCEED/FAIL
1387 
1388  AUTHOR
1389     GeorgeV.
1390 
1391 --------------------------------------------------------------------------*/
1392 EXPORT intn
ANfileinfo(int32 an_id,int32 * n_file_label,int32 * n_file_desc,int32 * n_obj_label,int32 * n_obj_desc)1393 ANfileinfo(int32  an_id,        /* IN:  annotation interface id */
1394            int32 *n_file_label, /* OUT: the # of file labels */
1395            int32 *n_file_desc,  /* OUT: the # of file descriptions */
1396            int32 *n_obj_label,  /* OUT: the # of object labels */
1397            int32 *n_obj_desc    /* OUT: the # of object descriptions */)
1398 {
1399     CONSTR(FUNC, "ANfileinfo");    /* for HERROR */
1400     filerec_t  *file_rec  = NULL;  /* file record pointer */
1401     intn        ret_value = SUCCEED;
1402 
1403     /* Clear error stack */
1404     HEclear();
1405 
1406     /* convert an_id i.e. file_id to file rec and check for validity */
1407     file_rec = HAatom_object(an_id);
1408     if (BADFREC(file_rec))
1409         HGOTO_ERROR(DFE_ARGS, FAIL);
1410 
1411     /* Empty file label annotation tree? */
1412     if (file_rec->an_num[AN_FILE_LABEL] == -1)
1413       {
1414           if ((*n_file_label = ANIcreate_ann_tree(an_id, AN_FILE_LABEL)) == FAIL)
1415               HE_REPORT_GOTO("failed to create file label annotation TBBTtree", FAIL);
1416       }
1417     else
1418         *n_file_label = file_rec->an_num[AN_FILE_LABEL];
1419 
1420     /* Empty file descritpiton annotation tree? */
1421     if (file_rec->an_num[AN_FILE_DESC] == -1)
1422       {
1423           if ((*n_file_desc = ANIcreate_ann_tree(an_id, AN_FILE_DESC)) == FAIL)
1424               HE_REPORT_GOTO("failed to create file desc annotation TBBTtree", FAIL);
1425       }
1426     else
1427         *n_file_desc = file_rec->an_num[AN_FILE_DESC];
1428 
1429     /* Empty label annotation tree? */
1430     if (file_rec->an_num[AN_DATA_LABEL] == -1)
1431       {
1432           if ((*n_obj_label = ANIcreate_ann_tree(an_id, AN_DATA_LABEL)) == FAIL)
1433               HE_REPORT_GOTO("failed to create data label annotation TBBTtree", FAIL);
1434       }
1435     else
1436         *n_obj_label = file_rec->an_num[AN_DATA_LABEL];
1437 
1438     /* Empty descritpiton annotation tree? */
1439     if (file_rec->an_num[AN_DATA_DESC] == -1)
1440       {
1441           if ((*n_obj_desc = ANIcreate_ann_tree(an_id, AN_DATA_DESC)) == FAIL)
1442               HE_REPORT_GOTO("failed to create data desc annotation TBBTtree", FAIL);
1443       }
1444     else
1445         *n_obj_desc = file_rec->an_num[AN_DATA_DESC];
1446 
1447   done:
1448     if(ret_value == FAIL)
1449       { /* Error condition cleanup */
1450 
1451       } /* end if */
1452 
1453     /* Normal function cleanup */
1454     return ret_value;
1455 } /* ANfileinfo() */
1456 
1457 /* -------------------------------- ANend ---------------------------------
1458  NAME
1459 	ANend -- End annotation access to file file
1460 
1461  DESCRIPTION
1462     End annotation access to file.
1463 
1464  RETURNS
1465     SUCCEED / FAIL
1466 --------------------------------------------------------------------------- */
1467 EXPORT int32
ANend(int32 an_id)1468 ANend(int32 an_id /* IN: Annotation ID of file to close */)
1469 {
1470     CONSTR(FUNC,"ANend");
1471     filerec_t *file_rec = NULL;  /* file record pointer */
1472     TBBT_NODE *aentry   = NULL;
1473     ANentry   *ann_entry = NULL;
1474     ANnode    *ann_node  = NULL;
1475     int32      ret_value = SUCCEED;
1476 
1477     /* Clear error stack */
1478     HEclear();
1479 
1480     /* convert an_id i.e. file_id to file rec and check for validity */
1481     file_rec = HAatom_object(an_id);
1482     if (BADFREC(file_rec))
1483         HGOTO_ERROR(DFE_ARGS, FAIL);
1484 
1485     /* NEED to delete trees of annotations attached to node
1486      * NOTE: This could be written shorter using a for loop....
1487      * or something....  */
1488 
1489     /* free file label annotation rb tree */
1490     if (file_rec->an_tree[AN_FILE_LABEL] != NULL)
1491       { /* Traverse tree puling ann_id's to delete from annotation atom group */
1492           for(aentry = tbbtfirst((TBBT_NODE *)*(file_rec->an_tree[AN_FILE_LABEL]));
1493               aentry != NULL;
1494               aentry = tbbtnext(aentry))
1495             { /* get annotation entry from node */
1496                 ann_entry = (ANentry *) aentry->data;
1497 
1498                 /* delete annotation node from annotation group  */
1499                 if(NULL == (ann_node = HAremove_atom(ann_entry->ann_id)))
1500                     HE_REPORT_GOTO("Failed to remove annotation with ann_id", FAIL);
1501 
1502                 if(ann_node != NULL)
1503                     HDfree(ann_node); /* free node */
1504             } /* end for 'entry */
1505           /* finally free tree */
1506           tbbtdfree(file_rec->an_tree[AN_FILE_LABEL], ANfreedata, ANfreekey);
1507       }
1508 
1509     /* free file desc annotation rb tree */
1510     if (file_rec->an_tree[AN_FILE_DESC] != NULL)
1511       { /* Traverse tree puling ann_id's to delete from annotation atom group */
1512           for(aentry = tbbtfirst((TBBT_NODE *)*(file_rec->an_tree[AN_FILE_DESC]));
1513               aentry != NULL;
1514               aentry = tbbtnext(aentry))
1515             { /* get annotation entry from node */
1516                 ann_entry = (ANentry *) aentry->data;
1517 
1518                 /* delete annotation node from annotation group  */
1519                 if(NULL == (ann_node = HAremove_atom(ann_entry->ann_id)))
1520                     HE_REPORT_GOTO("Failed to remove annotation with ann_id", FAIL);
1521 
1522                 if(ann_node != NULL)
1523                     HDfree(ann_node); /* free node */
1524 
1525             } /* end for 'entry */
1526           /* finally free tree */
1527           tbbtdfree(file_rec->an_tree[AN_FILE_DESC], ANfreedata, ANfreekey);
1528       }
1529 
1530     /* free label annotation rb tree */
1531     if (file_rec->an_tree[AN_DATA_LABEL] != NULL)
1532       { /* Traverse tree puling ann_id's to delete from annotation atom group */
1533           for(aentry = tbbtfirst((TBBT_NODE *)*(file_rec->an_tree[AN_DATA_LABEL]));
1534               aentry != NULL;
1535               aentry = tbbtnext(aentry))
1536             { /* get annotation entry from node */
1537                 ann_entry = (ANentry *) aentry->data;
1538 
1539                 /* delete annotation node from annotation group  */
1540                 if(NULL == (ann_node = HAremove_atom(ann_entry->ann_id)))
1541                     HE_REPORT_GOTO("Failed to remove annotation with ann_id", FAIL);
1542 
1543                 if(ann_node != NULL)
1544                     HDfree(ann_node); /* free node */
1545             } /* end for 'entry */
1546           /* finally free tree */
1547           tbbtdfree(file_rec->an_tree[AN_DATA_LABEL], ANfreedata, ANfreekey);
1548       }
1549 
1550     /* free desc annotation rb tree */
1551     if (file_rec->an_tree[AN_DATA_DESC] != NULL)
1552       { /* Traverse tree puling ann_id's to delete from annotation atom group */
1553           for(aentry = tbbtfirst((TBBT_NODE *)*(file_rec->an_tree[AN_DATA_DESC]));
1554               aentry != NULL;
1555               aentry = tbbtnext(aentry))
1556             { /* get annotation entry from node */
1557                 ann_entry = (ANentry *) aentry->data;
1558 
1559                 /* delete annotation node from annotation group  */
1560                 if(NULL == (ann_node = HAremove_atom(ann_entry->ann_id)))
1561                     HE_REPORT_GOTO("Failed to remove annotation with ann_id", FAIL);
1562 
1563                 if(ann_node != NULL)
1564                     HDfree(ann_node); /* free node */
1565 
1566             } /* end for 'entry */
1567           /* finally free tree */
1568           tbbtdfree(file_rec->an_tree[AN_DATA_DESC], ANfreedata, ANfreekey);
1569       }
1570 
1571     /* re-initalize everything in file record for annotations so
1572        the a ANstart() works. */
1573     file_rec->an_tree[AN_DATA_LABEL] = NULL;
1574     file_rec->an_tree[AN_DATA_DESC]  = NULL;
1575     file_rec->an_tree[AN_FILE_LABEL] = NULL;
1576     file_rec->an_tree[AN_FILE_DESC]  = NULL;
1577     file_rec->an_num[AN_DATA_LABEL] = -1;
1578     file_rec->an_num[AN_DATA_DESC]  = -1;
1579     file_rec->an_num[AN_FILE_LABEL] = -1;
1580     file_rec->an_num[AN_FILE_DESC]  = -1;
1581 
1582   done:
1583     if(ret_value == FAIL)
1584       { /* Error condition cleanup */
1585 
1586       } /* end if */
1587 
1588     /* Normal function cleanup */
1589     return ret_value;
1590 } /* ANend() */
1591 
1592 /* ------------------------------------------------------------------------
1593  NAME
1594 	ANcreate - create a new element annotation and return a handle(id)
1595 
1596  DESCRIPTION
1597     Creates a data annotation, returns an 'an_id' to work with the new
1598     annotation which can either be a label or description.
1599 
1600  RETURNS
1601     An ID to an annotation which can either be a label or description
1602 
1603  AUTHOR
1604     GeorgeV.
1605 
1606 --------------------------------------------------------------------------- */
1607 EXPORT int32
ANcreate(int32 an_id,uint16 elem_tag,uint16 elem_ref,ann_type type)1608 ANcreate(int32    an_id,    /* IN: annotation interface ID */
1609          uint16   elem_tag, /* IN: tag of item to be assigned annotation */
1610          uint16   elem_ref, /* IN: reference number of itme to be assigned ann */
1611          ann_type type      /* IN: AN_DATA_LABEL for data labels,
1612                                   AN_DATA_DESC for data descriptions*/)
1613 {
1614 #ifdef LATER
1615     CONSTR(FUNC, "ANcreate");    /* for HERROR */
1616 #endif /* LATER */
1617     int32    ret_value;
1618 
1619     ret_value = (ANIcreate(an_id, elem_tag, elem_ref, type));
1620 
1621     return ret_value;
1622 } /* ANcreate() */
1623 
1624 /* ------------------------------------------------------------------------
1625  NAME
1626 	ANcreatef - create a new file annotation and return a handle(id)
1627 
1628  DESCRIPTION
1629     Creates a file annotation, returns an 'an_id' to work with the new
1630     file annotation which can either be a label or description.
1631 
1632  RETURNS
1633     An ID to an annotation which can either be a file label or description
1634 
1635  AUTHOR
1636     GeorgeV.
1637 
1638 --------------------------------------------------------------------------- */
1639 EXPORT int32
ANcreatef(int32 an_id,ann_type type)1640 ANcreatef(int32    an_id,/* IN: annotation interface ID */
1641           ann_type type  /* IN:  AN_FILE_LABEL for file labels,
1642                                  AN_FILE_DESC for file descritpions.*/)
1643 {
1644 #ifdef LATER
1645     CONSTR(FUNC, "ANcreatef");    /* for HERROR */
1646 #endif /* LATER */
1647     uint16 ann_tag;
1648     uint16 ann_ref;
1649     int32  ret_value = SUCCEED;
1650 
1651     /* deal with type */
1652     switch((ann_type)type)
1653       {
1654       case AN_FILE_LABEL:
1655           ann_tag = DFTAG_FID;
1656           ann_ref = 0; /* initalize with invalid ref,
1657                           will be replaced in ANIcreate() */
1658           break;
1659       case AN_FILE_DESC:
1660           ann_tag = DFTAG_FD;
1661           ann_ref = 0; /* initialize with invalid ref,
1662                           will be replaced in ANIcreate() */
1663           break;
1664       default:
1665           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
1666       }
1667 
1668     ret_value = ANIcreate(an_id, ann_tag, ann_ref, type);
1669 
1670   done:
1671     if(ret_value == FAIL)
1672       { /* Error condition cleanup */
1673 
1674       } /* end if */
1675 
1676     /* Normal function cleanup */
1677     return ret_value;
1678 } /* ANcreateann() */
1679 
1680 /* ------------------------------- ANselect -------------------------------
1681  NAME
1682 	ANselect -- get an annotation ID from index of 'type'
1683 
1684  DESCRIPTION
1685     The position index is ZERO based
1686 
1687  RETURNS
1688     An ID to an annotation type which can either be a label or description
1689 
1690  AUTHOR
1691     GeorgeV.
1692 
1693 --------------------------------------------------------------------------- */
1694 EXPORT int32
ANselect(int32 an_id,int32 index,ann_type type)1695 ANselect(int32    an_id, /* IN: annotation interface ID */
1696          int32    index, /* IN: index of annottion to get ID for */
1697          ann_type type   /* IN: AN_DATA_LABEL for data labels,
1698                                 AN_DATA_DESC for data descriptions,
1699                                 AN_FILE_LABEL for file labels,
1700                                 AN_FILE_DESC for file descritpions.*/)
1701 {
1702     CONSTR(FUNC, "ANselect");    /* for HERROR */
1703     filerec_t *file_rec = NULL;  /* file record pointer */
1704     TBBT_NODE *entry    = NULL;
1705     ANentry   *ann_entry = NULL;
1706     int32      ret_value = SUCCEED;
1707 
1708     /* Clear error stack */
1709     HEclear();
1710 
1711     /* convert an_id i.e. file_id to file rec and check for validity */
1712     file_rec = HAatom_object(an_id);
1713     if (BADFREC(file_rec))
1714         HGOTO_ERROR(DFE_ARGS, FAIL);
1715 
1716     /* Empty annotation tree */
1717     if (file_rec->an_num[type] == -1)
1718       {
1719           if (ANIcreate_ann_tree(an_id, type) == FAIL)
1720               HGOTO_ERROR(DFE_BADCALL, FAIL);
1721       }
1722 
1723     /* check index and adjust to 1 based for tbbtindx()*/
1724     if(index >= 0 && index < file_rec->an_num[type])
1725         index++;
1726     else
1727         HE_REPORT_GOTO("bad index", FAIL);
1728 
1729     /* find 'index' entry */
1730     if ((entry = tbbtindx((TBBT_NODE *)*(file_rec->an_tree[type]), index)) == NULL)
1731         HE_REPORT_GOTO("failed to find 'index' entry", FAIL);
1732 
1733     ann_entry = (ANentry *) entry->data;
1734 
1735     /* return ann_id */
1736     ret_value = ann_entry->ann_id;
1737 
1738   done:
1739     if(ret_value == FAIL)
1740       { /* Error condition cleanup */
1741 
1742       } /* end if */
1743 
1744     /* Normal function cleanup */
1745     return ret_value;
1746 } /* ANselect() */
1747 
1748 /*--------------------------------------------------------------------------
1749  NAME
1750    ANnumann -- find number of annotation of 'type' that
1751                match the given element tag/ref
1752 
1753  DESCRIPTION
1754    Find number of annotation of 'type' for the given element
1755    tag/ref pair. Should not be used for File labels and
1756    descriptions.
1757 
1758  RETURNS
1759    Number of annotations found if successful and FAIL (-1) otherwise.
1760 
1761  AUTHOR
1762     GeorgeV.
1763 
1764  ------------------------------------------------------------------------*/
1765 EXPORT intn
ANnumann(int32 an_id,ann_type type,uint16 elem_tag,uint16 elem_ref)1766 ANnumann(int32    an_id,    /* IN: annotation interface id */
1767          ann_type type,     /* IN: AN_DATA_LABEL for data labels,
1768                                    AN_DATA_DESC for data descriptions,
1769                                    AN_FILE_LABEL for file labels,
1770                                    AN_FILE_DESC for file descritpions.*/
1771          uint16   elem_tag, /* IN: tag of item of which this is annotation */
1772          uint16   elem_ref  /* IN: ref of item of which this is annotation */ )
1773 {
1774     CONSTR(FUNC, "ANnumann");
1775     intn   ret_value = SUCCEED;
1776 
1777     /* deal with invalid types */
1778     if(type == AN_FILE_LABEL || type == AN_FILE_DESC)
1779         HGOTO_ERROR(DFE_ARGS, FAIL);
1780 
1781     ret_value = ANInumann(an_id, type, elem_tag, elem_ref);
1782 
1783   done:
1784     if(ret_value == FAIL)
1785       { /* Error condition cleanup */
1786 
1787       } /* end if */
1788 
1789     /* Normal function cleanup */
1790 
1791     return ret_value;
1792 } /* ANnumann() */
1793 
1794 /*--------------------------------------------------------------------------
1795  NAME
1796    ANannlist -- generate list of annotation ids of 'type' that
1797                 match the given element tag/ref
1798 
1799  DESCRIPTION
1800    Find and generate list of annotation ids of 'type' for the given
1801    element tag/ref pair. Should not be used for File labels and
1802    descriptions.
1803 
1804  RETURNS
1805    Number of annotations ids found if successful and FAIL (-1) otherwise
1806 
1807  AUTHOR
1808     GeorgeV.
1809 
1810  ------------------------------------------------------------------------*/
1811 EXPORT intn
ANannlist(int32 an_id,ann_type type,uint16 elem_tag,uint16 elem_ref,int32 ann_list[])1812 ANannlist(int32    an_id,      /* IN: annotation interface id */
1813           ann_type type,       /* IN: AN_DATA_LABEL for data labels,
1814                                       AN_DATA_DESC for data descriptions,
1815                                       AN_FILE_LABEL for file labels,
1816                                       AN_FILE_DESC for file descritpions.*/
1817           uint16   elem_tag,   /* IN: tag of item of which this is annotation */
1818           uint16   elem_ref,   /* IN: ref of item of which this is annotation */
1819           int32    ann_list[]  /* OUT: array of ann_id's that match criteria. */)
1820 {
1821     CONSTR(FUNC, "ANannlist");
1822     intn  ret_value = SUCCEED;
1823 
1824     /* deal with invalid types */
1825     if(type == AN_FILE_LABEL || type == AN_FILE_DESC)
1826         HGOTO_ERROR(DFE_ARGS, FAIL);
1827 
1828     ret_value = ANIannlist(an_id, type, elem_tag, elem_ref, ann_list);
1829 
1830   done:
1831     if(ret_value == FAIL)
1832       { /* Error condition cleanup */
1833 
1834       } /* end if */
1835 
1836     /* Normal function cleanup */
1837 
1838     return ret_value;
1839 } /* ANannlist() */
1840 
1841 /*--------------------------------------------------------------------------
1842  NAME
1843    ANannlen -- get length of annotation givne annotation id
1844 
1845  DESCRIPTION
1846    Uses the annotation id to find ann_key & file_id
1847 
1848  RETURNS
1849    length of annotation if successful and FAIL (-1) otherwise
1850 
1851  AUTHOR
1852     GeorgeV.
1853 
1854  ------------------------------------------------------------------------*/
1855 EXPORT int32
ANannlen(int32 ann_id)1856 ANannlen(int32 ann_id /* IN: annotation id */)
1857 {
1858 #ifdef LATER
1859     CONSTR(FUNC, "ANannlen");
1860 #endif /* LATER */
1861     int32  ret_value;
1862 
1863     ret_value =  ANIannlen(ann_id);
1864     return ret_value;
1865 } /* ANannlen() */
1866 
1867 /*--------------------------------------------------------------------------
1868  NAME
1869    ANwriteann -- write annotation given ann_id
1870 
1871  DESCRIPTION
1872    Checks for pre-existence of given annotation, replacing old one if it
1873    exists. Writes out annotation.
1874 
1875  RETURNS
1876    SUCCEED (0) if successful and FAIL (-1) otherwise
1877 
1878  AUTHOR
1879     GeorgeV.
1880 
1881  ------------------------------------------------------------------------*/
1882 EXPORT int32
ANwriteann(int32 ann_id,const char * ann,int32 annlen)1883 ANwriteann(int32 ann_id,     /* IN: annotation id */
1884            const char *ann,  /* IN: annotation to write */
1885            int32 annlen      /* IN: length of annotation */)
1886 {
1887 #ifdef LATER
1888     CONSTR(FUNC, "ANwriteann");    /* for HERROR */
1889 #endif /* LATER */
1890     int32  ret_value;
1891 
1892     ret_value = ANIwriteann(ann_id, ann, annlen);
1893     return ret_value;
1894 } /* ANwriteann() */
1895 
1896 /*--------------------------------------------------------------------------
1897  NAME
1898    ANreadann -- read annotation given ann_id
1899 
1900  DESCRIPTION
1901    Gets tag and ref of annotation.  Finds DD for that annotation.
1902    Reads the annotation, taking care of NULL terminator, if necessary.
1903 
1904  RETURNS
1905    SUCCEED (0) if successful and FAIL (-1) otherwise
1906 
1907  AUTHOR
1908     GeorgeV.
1909 
1910  ------------------------------------------------------------------------*/
1911 EXPORT int32
ANreadann(int32 ann_id,char * ann,int32 maxlen)1912 ANreadann(int32 ann_id,  /* IN: annotation id (handle) */
1913           char *ann,     /* OUT: space to return annotation in */
1914           int32 maxlen   /* IN: size of space to return annotation in */)
1915 {
1916 #ifdef LATER
1917     CONSTR(FUNC, "ANreadann");    /* for HERROR */
1918 #endif /* LATER */
1919     int32   ret_value;
1920 
1921     ret_value = ANIreadann(ann_id, ann, maxlen);
1922     return ret_value;
1923 } /* ANreadann() */
1924 
1925 /* -----------------------------------------------------------------------
1926  NAME
1927 	ANendaccess -- end access to an annotation given it's id
1928 
1929  DESCRIPTION
1930     Terminates access to an annotation. For now does nothing
1931 
1932  RETURNS
1933     SUCCEED(0) or FAIL(-1)
1934 
1935  AUTHOR
1936     GeorgeV.
1937 
1938 --------------------------------------------------------------------------- */
1939 EXPORT intn
ANendaccess(int32 ann_id)1940 ANendaccess(int32 ann_id /* IN: annotation id */)
1941 {
1942 #ifdef LATER
1943     CONSTR(FUNC, "ANendaccess");    /* for HERROR */
1944 #endif /* LATER */
1945     intn  ret_value = SUCCEED;
1946     /* shut compiler up */
1947     ann_id=ann_id;
1948 
1949     return ret_value;
1950 } /* ANendaccess() */
1951 
1952 /* -----------------------------------------------------------------------
1953  NAME
1954 	ANget_tagref - get tag/ref pair for annotation based on type and index
1955 
1956  DESCRIPTION
1957     Get the tag/ref of the annotation based on  the type and index of the
1958     annotation. The position index is zero based
1959 
1960  RETURNS
1961     A tag/ref pair for an annotation type which can either be a
1962     label or description.
1963 
1964  AUTHOR
1965     GeorgeV.
1966 
1967 --------------------------------------------------------------------------- */
1968 EXPORT int32
ANget_tagref(int32 an_id,int32 index,ann_type type,uint16 * tag,uint16 * ref)1969 ANget_tagref(int32    an_id, /* IN: annotation interface ID */
1970              int32    index, /* IN: index of annotation to get tag/ref for */
1971              ann_type type,  /* IN: AN_DATA_LABEL for data labels,
1972                                     AN_DATA_DESC for data descriptions,
1973                                     AN_FILE_LABEL for file labels,
1974                                     AN_FILE_DESC for file descritpions.*/
1975              uint16  *tag,   /* OUT: Tag for annotation */
1976              uint16  *ref    /* OUT: ref for annotation */)
1977 {
1978     CONSTR(FUNC, "ANget_tagref");    /* for HERROR */
1979     filerec_t *file_rec = NULL;  /* file record pointer */
1980     TBBT_NODE *entry    = NULL;
1981     ANentry   *ann_entry = NULL;
1982     int32      ret_value = SUCCEED;
1983 
1984     /* Clear error stack */
1985     HEclear();
1986 
1987     /* convert an_id i.e. file_id to file rec and check for validity */
1988     file_rec = HAatom_object(an_id);
1989     if (BADFREC(file_rec))
1990         HGOTO_ERROR(DFE_ARGS, FAIL);
1991 
1992     /* Empty annotation tree */
1993     if (file_rec->an_num[type] == -1)
1994       {
1995           if (ANIcreate_ann_tree(an_id, type) == FAIL)
1996               HGOTO_ERROR(DFE_BADCALL, FAIL);
1997       }
1998 
1999     /* check index and adjust to 1 based for tbbtindx()*/
2000     if(index >= 0 && index <= file_rec->an_num[type])
2001         index++;
2002     else
2003         HE_REPORT_GOTO("bad index", FAIL);
2004 
2005     /* find 'index' entry */
2006     if ((entry = tbbtindx((TBBT_NODE *)*(file_rec->an_tree[type]), index)) == NULL)
2007         HE_REPORT_GOTO("failed to find 'index' entry", FAIL);
2008 
2009     ann_entry = (ANentry *) entry->data;
2010 
2011     /* set ref */
2012     *ref = ann_entry->annref;
2013 
2014     /* set tag based on type */
2015     switch((int32)type)
2016       {
2017       case AN_DATA_LABEL:
2018           *tag = DFTAG_DIL;
2019           break;
2020       case AN_DATA_DESC:
2021           *tag = DFTAG_DIA;
2022           break;
2023       case AN_FILE_LABEL:
2024           *tag = DFTAG_FID;
2025           break;
2026       case AN_FILE_DESC:
2027           *tag = DFTAG_FD;
2028           break;
2029       default:
2030           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
2031       }
2032 
2033   done:
2034     if(ret_value == FAIL)
2035       { /* Error condition cleanup */
2036 
2037       } /* end if */
2038 
2039     /* Normal function cleanup */
2040 
2041     return ret_value;
2042 } /* ANget_tagref() */
2043 
2044 /*--------------------------------------------------------------------------
2045  NAME
2046     ANid2tagref -- get tag/ref given annotation id
2047 
2048  DESCRIPTION
2049     Uses the annotation id to find ann_node entry which contains ann_ref
2050 
2051  RETURNS
2052     SUCCEED(0) if successful and FAIL (-1) otherwise.
2053 
2054  AUTHOR
2055     GeorgeV.
2056 
2057  ------------------------------------------------------------------------*/
2058 int32
ANid2tagref(int32 ann_id,uint16 * tag,uint16 * ref)2059 ANid2tagref(int32   ann_id,/* IN: annotation id */
2060             uint16 *tag,   /* OUT: Tag for annotation */
2061             uint16 *ref    /* OUT: ref for annotation */)
2062 {
2063     CONSTR(FUNC, "ANid2tagref");
2064     ANnode    *ann_node = NULL;
2065     int32      file_id  = FAIL;
2066     int32      type;
2067     int32      ann_key;
2068     uint16     ann_ref;
2069     int32      ret_value = SUCCEED;
2070 
2071     /* Clear error stack */
2072     HEclear();
2073 
2074     /* Valid annotation id */
2075     /* get annotation record */
2076     ann_node = HAatom_object(ann_id);
2077     if (NULL == ann_node)
2078         HGOTO_ERROR(DFE_ARGS, FAIL);
2079 
2080     /* get file id and annotation key */
2081     file_id = ann_node->file_id;
2082     ann_key = ann_node->ann_key;
2083     type    = AN_KEY2TYPE(ann_key);
2084     ann_ref = AN_KEY2REF(ann_key);
2085 
2086     /* Valid file id */
2087     if (file_id == FAIL)
2088         HE_REPORT_GOTO("bad file_id", FAIL);
2089 
2090     *ref = ann_ref;
2091     /* set type annotation tag */
2092     switch((int32)type)
2093       {
2094       case AN_DATA_LABEL:
2095           *tag = DFTAG_DIL;
2096           break;
2097       case AN_DATA_DESC:
2098           *tag = DFTAG_DIA;
2099           break;
2100       case AN_FILE_LABEL:
2101           *tag = DFTAG_FID;
2102           break;
2103       case AN_FILE_DESC:
2104           *tag = DFTAG_FD;
2105           break;
2106       default:
2107           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
2108       }
2109 
2110   done:
2111     if(ret_value == FAIL)
2112       { /* Error condition cleanup */
2113 
2114       } /* end if */
2115 
2116     /* Normal function cleanup */
2117 
2118     return ret_value;
2119 } /* ANid2tagref */
2120 
2121 /*--------------------------------------------------------------------------
2122  NAME
2123        ANtagref2id -- get annotation id given tag/ref
2124 
2125  DESCRIPTION
2126        Gets the annotation id of the annotation given the tag/ref of
2127        the annotation itself and the annotation interface id.
2128 
2129  RETURNS
2130        Annotation id of annotation if successful and FAIL(-1) otherwise.
2131 
2132  AUTHOR
2133     GeorgeV.
2134 
2135  ------------------------------------------------------------------------*/
2136 int32
ANtagref2id(int32 an_id,uint16 ann_tag,uint16 ann_ref)2137 ANtagref2id(int32  an_id,   /* IN  Annotation interface id */
2138             uint16 ann_tag, /* IN: Tag for annotation */
2139             uint16 ann_ref  /* IN: ref for annotation */)
2140 {
2141     CONSTR(FUNC, "ANtagref2id");
2142     filerec_t *file_rec = NULL;		/* file record pointer */
2143     TBBT_NODE *entry    = NULL;
2144     ANentry   *ann_entry = NULL;
2145     int32      ann_key;
2146     ann_type   type;
2147     int32      ret_value = SUCCEED;
2148 
2149     /* Clear error stack */
2150     HEclear();
2151 
2152     /* convert an_id i.e. file_id to file rec and check for validity */
2153     file_rec = HAatom_object(an_id);
2154     if (BADFREC(file_rec))
2155         HGOTO_ERROR(DFE_ARGS, FAIL);
2156 
2157     /* set type given annotation tag */
2158     switch((uint16)ann_tag)
2159       {
2160       case DFTAG_DIL:
2161           type = AN_DATA_LABEL;
2162           break;
2163       case DFTAG_DIA:
2164           type = AN_DATA_DESC;
2165           break;
2166       case  DFTAG_FID:
2167           type = AN_FILE_LABEL;
2168           break;
2169       case  DFTAG_FD:
2170           type = AN_FILE_DESC;
2171           break;
2172       default:
2173           HE_REPORT_GOTO("Bad annotation type for this call",FAIL);
2174       }
2175 
2176     /* Check for empty annotation tree of 'type'? */
2177     if (file_rec->an_num[type] == -1)
2178       {
2179           if (ANIcreate_ann_tree(an_id, type) == FAIL)
2180               HGOTO_ERROR(DFE_BADCALL, FAIL);
2181       }
2182 
2183     /* Create key from type/ref pair
2184      *  ----------------------------
2185      *  | type(16bits) | ref(16bits) |
2186      *  -----------------------------*/
2187     ann_key = AN_CREATE_KEY(type, ann_ref);
2188 
2189     /* See if annotation of 'type' with ref exits */
2190     if ((entry = tbbtdfind(file_rec->an_tree[type], &ann_key, NULL)) == NULL)
2191         HE_REPORT_GOTO("failed to find annotation of 'type'", FAIL);
2192 
2193     /* get annotation entry from node */
2194     ann_entry = (ANentry *) entry->data;
2195 
2196     /* return annotation id */
2197     ret_value = ann_entry->ann_id;
2198 
2199   done:
2200     if(ret_value == FAIL)
2201       { /* Error condition cleanup */
2202 
2203       } /* end if */
2204 
2205     /* Normal function cleanup */
2206 
2207     return ret_value;
2208 } /* ANtagref2id */
2209 
2210 /*--------------------------------------------------------------------
2211  NAME
2212      ANatype2tag - annotation type to corresponding annotation TAG
2213 
2214  DESCRIPTION
2215      Translate annotation type to corresponding TAG
2216 
2217  RETURNS
2218      Returns TAG corresponding to annotatin type
2219 
2220  AUTHOR
2221     GeorgeV.
2222 
2223 --------------------------------------------------------------------*/
2224 EXPORT uint16
ANatype2tag(ann_type atype)2225 ANatype2tag(ann_type atype /* IN: Annotation type */)
2226 {   /* Switch on annotation type "atype" */
2227 #ifdef LATER
2228     CONSTR(FUNC, "ANatype2tag");    /* for HERROR */
2229 #endif /* LATER */
2230     uint16 ann_tag;
2231 
2232     switch((ann_type)atype)
2233       {
2234       case AN_FILE_LABEL: ann_tag = DFTAG_FID; break;
2235       case AN_FILE_DESC:  ann_tag = DFTAG_FD;  break;
2236       case AN_DATA_LABEL: ann_tag = DFTAG_DIL; break;
2237       case AN_DATA_DESC:  ann_tag = DFTAG_DIA; break;
2238       default: ann_tag = DFTAG_NULL;  /*changed from 5 to DFTAG_NULL -BMR*/
2239       } /* switch */
2240     return ann_tag;
2241 } /* ANatype2tag */
2242 
2243 /*--------------------------------------------------------------------
2244  NAME
2245      ANtag2atype - annotation TAG to corresponding annotation type
2246 
2247  DESCRIPTION
2248      Translate annotation TAG to corresponding atype
2249 
2250  RETURNS
2251      Returns type corresponding to annotatin TAG
2252 
2253  AUTHOR
2254     GeorgeV.
2255 
2256 --------------------------------------------------------------------*/
2257 EXPORT ann_type
ANtag2atype(uint16 atag)2258 ANtag2atype(uint16 atag /* IN: annotation tag */)
2259 {   /* Switch on annotation tag */
2260 #ifdef LATER
2261     CONSTR(FUNC, "ANtag2atype");    /* for HERROR */
2262 #endif /* LATER */
2263     ann_type atype;
2264 
2265     switch((uint16)atag)
2266       {
2267       case DFTAG_FID: atype = AN_FILE_LABEL; break;
2268       case DFTAG_FD:  atype = AN_FILE_DESC;  break;
2269       case DFTAG_DIL: atype = AN_DATA_LABEL; break;
2270       case DFTAG_DIA: atype = AN_DATA_DESC;  break;
2271           /* This will cause warnings on some compiliers */
2272       default: atype = AN_UNDEF;
2273       } /* switch */
2274     return atype;
2275 } /* ANtag2atype */
2276 
2277 #endif /* MFAN_MASTER */
2278