1 /* asntypes.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name: asntypes.c
27 *
28 * Author: James Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.9 $
33 *
34 * File Description:
35 * Routines to deal with internal operations on AsnType objects.
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * Date Name Description of modification
40 * ------- ---------- -----------------------------------------------------
41 * 3/4/91 Kans Stricter typecasting for GNU C and C++
42 * 04-20-93 Schuler LIBCALL calling convention
43 * 02-24-94 Schuler Make AsnTypeStringToHex LIBCALL too
44 *
45 * $Log: asntypes.c,v $
46 * Revision 6.9 2003/12/03 19:31:09 gouriano
47 * Corrected DTD generation (a different approach)
48 *
49 * Revision 6.8 2003/12/02 21:40:17 gouriano
50 * Revert back to rev 6.6
51 *
52 * Revision 6.7 2003/12/02 19:52:49 gouriano
53 * Corrected DTD generation
54 *
55 * Revision 6.6 2000/07/25 20:30:58 ostell
56 * added support for printing multiple ASN.1 modules as multiple XML DTD and .mod files
57 *
58 * Revision 6.5 2000/05/26 14:51:23 ostell
59 * fixed uninitialized variable
60 *
61 * Revision 6.4 2000/05/10 03:12:37 ostell
62 * added support for XML DTD and XML data output
63 *
64 * Revision 6.2 1998/06/12 19:27:56 kans
65 * fixed unix compiler warnings
66 *
67 * Revision 6.1 1997/10/29 02:42:10 vakatov
68 * Type castings to pass through the C++ compiler
69 *
70 * Revision 6.0 1997/08/25 18:10:25 madden
71 * Revision changed to 6.0
72 *
73 * Revision 5.3 1997/04/24 12:47:49 ostell
74 * in AsnTypeStringToHex, allowed argument "left" to be NULL
75 *
76 * Revision 5.2 1997/04/23 21:23:03 ostell
77 * changed BitHex reading routine to strip internal spaces and allow for linewraps at
78 * any spacing.
79 *
80 * Revision 5.1 1996/12/03 21:43:48 vakatov
81 * Adopted for 32-bit MS-Windows DLLs
82 *
83 * Revision 5.0 1996/05/28 14:00:29 ostell
84 * Set to revision 5.0
85 *
86 * Revision 4.0 1995/07/26 13:47:38 ostell
87 * force revision to 4.0
88 *
89 * Revision 2.19 1995/05/20 17:05:26 ostell
90 * added ASNTYPE_RUNTIME_LINK
91 * if defined enables oldstyle runtime link of AsnLinkType().
92 * default is disabled, which assumes all linking of asn.1 parse trees
93 * via calls to AsnLoad() functions is done before any AsnREAD or AsnWrite
94 *
95 * Revision 2.18 1995/05/15 18:38:28 ostell
96 * added Log line
97 *
98 *
99 * ==========================================================================
100 */
101
102 /*****************************************************************************
103 *
104 * asntypes.c
105 * basic routines for processing asn1 types
106 * does not support lexxing of type definitions - those are in
107 * asnlext.c
108 *
109 *****************************************************************************/
110
111 #include "asnbuild.h"
112
113 /*****************************************************************************
114 *
115 * This stores all loaded parse trees and links them together
116 *
117 *****************************************************************************/
118 static ValNodePtr
119 amps , /* the AsnModulePtr blocks */
120 names ; /* the load file names */
121
122 /*****************************************************************************
123 *
124 * CharPtr AsnFindPrimName(atp)
125 * returns the string name of an ASN.1 primitive type
126 *
127 *****************************************************************************/
AsnFindPrimName(AsnTypePtr atp)128 NLM_EXTERN CharPtr LIBCALL AsnFindPrimName (AsnTypePtr atp)
129 {
130 AsnTypePtr atp2;
131
132 atp2 = AsnFindBaseType(atp);
133 if (atp2 == NULL)
134 return NULL;
135
136 return atp2->type->name;
137 }
138
139 /*****************************************************************************
140 *
141 * CharPtr AsnFindBaseName(atp)
142 * returns the string name of an ASN.1 basic entity
143 * returns NULL if not resolved
144 * returns NULL if resolves to a primitive type (use AsnFindPrimName)
145 *
146 *****************************************************************************/
AsnFindBaseName(AsnTypePtr atp)147 NLM_EXTERN CharPtr LIBCALL AsnFindBaseName (AsnTypePtr atp)
148 {
149 AsnTypePtr atp2;
150
151 atp2 = AsnFindBaseType(atp);
152 if (atp2 == NULL)
153 return NULL;
154
155 if (atp2->name == NULL)
156 return NULL;
157 else if (IS_UPPER(*atp2->name))
158 return atp2->name;
159 else
160 return NULL;
161 }
162
163 /*****************************************************************************
164 *
165 * void AsnKillValue(atp, dvp)
166 * eliminates stored values such as strings
167 *
168 *****************************************************************************/
AsnKillValue(AsnTypePtr atp,DataValPtr dvp)169 NLM_EXTERN void LIBCALL AsnKillValue (AsnTypePtr atp, DataValPtr dvp)
170 {
171 Int2 isa;
172
173 isa = AsnFindBaseIsa(atp);
174 if (ISA_STRINGTYPE(isa))
175 MemFree(dvp->ptrvalue);
176 else if ((isa == OCTETS_TYPE) || (isa == STRSTORE_TYPE))
177 BSFree((ByteStorePtr) dvp->ptrvalue);
178 return;
179 }
180
181 /*****************************************************************************
182 *
183 * void AsnTypeSetIndent(increase, aip, atp)
184 * set the typestack type_indent
185 *
186 *****************************************************************************/
AsnTypeSetIndent(Boolean increase,AsnIoPtr aip,AsnTypePtr atp)187 NLM_EXTERN void AsnTypeSetIndent (Boolean increase, AsnIoPtr aip, AsnTypePtr atp)
188 {
189 Int1 curr_indent;
190 PstackPtr tmptype;
191
192
193 if (increase)
194 {
195 aip->typestack[aip->type_indent].type = atp; /* save type */
196 aip->type_indent++;
197 curr_indent = aip->type_indent;
198 if (curr_indent == aip->max_type) /* expand indent levels */
199 {
200 tmptype = aip->typestack;
201 aip->typestack = (PstackPtr) MemNew((sizeof(Pstack) * (aip->max_type + 10)));
202 MemCopy(aip->typestack, tmptype, (size_t)(sizeof(Pstack) * aip->max_type));
203 MemFree(tmptype);
204 aip->max_type += 10;
205 }
206 aip->typestack[curr_indent].type = NULL; /* set to first time */
207 }
208 else
209 {
210 do
211 {
212 aip->typestack[aip->type_indent].type = NULL;
213 if (aip->type_indent)
214 aip->type_indent--;
215 } while ((aip->type_indent) &&
216 (AsnFindBaseIsa(aip->typestack[aip->type_indent-1].type) == CHOICE_TYPE)
217 && (aip->token != ISMODULE_TOKEN) && (!(aip->type & ASNIO_XML)));
218 /* this is to pop out of choice nests */
219 /* XML popping is formatted at ends */
220 }
221 return;
222 }
223
224 /*****************************************************************************
225 *
226 * AsnTypePtr AsnFindBaseType(atp)
227 * find the primitive type for atp
228 *
229 *****************************************************************************/
AsnFindBaseType(AsnTypePtr atp)230 NLM_EXTERN AsnTypePtr LIBCALL AsnFindBaseType (AsnTypePtr atp)
231 {
232 if (atp == NULL) return NULL;
233
234 if (atp->type == NULL) return NULL;
235
236 while (! ISA_BASETYPE(atp->type->isa))
237 {
238 atp = atp->type;
239 if (atp->type == NULL) /* not found */
240 return NULL;
241 }
242 return atp;
243 }
244
AsnFindBaseTypeDTD(AsnTypePtr atp)245 NLM_EXTERN AsnTypePtr LIBCALL AsnFindBaseTypeDTD (AsnTypePtr atp)
246 {
247 if (atp == NULL) return NULL;
248
249 if (atp->type == NULL) return NULL;
250
251 if (! ISA_BASETYPE(atp->type->isa))
252 {
253 atp = atp->type;
254 if (atp->type == NULL) /* not found */
255 return atp;
256 }
257 return atp;
258 }
259
260 /*****************************************************************************
261 *
262 * Int2 AsnFindBaseIsa(atp)
263 * find the primitive type for atp
264 *
265 *****************************************************************************/
AsnFindBaseIsa(AsnTypePtr atp)266 NLM_EXTERN Int2 LIBCALL AsnFindBaseIsa (AsnTypePtr atp)
267 {
268 if (atp == NULL)
269 return -1;
270
271 if (ISA_BASETYPE(atp->isa))
272 return atp->isa;
273
274 if (atp->type == NULL)
275 return -1;
276
277 while (! ISA_BASETYPE(atp->type->isa))
278 {
279 atp = atp->type;
280 if (atp->type == NULL)
281 return -1;
282 }
283 return atp->type->isa;
284 }
285
286 /*****************************************************************************
287 *
288 * Boolean AsnTypeValidateOut(aip, atp, dvp)
289 * if not open or closing a SET, SEQ, SETOF, SEQOF, will
290 * put atp in aip->typestack if it validates.
291 *
292 * KNOWN DEFECT: SET should check for 1 of each non-optional element
293 * It does not right now, it only checks that an element is a valid
294 * member of the SET.
295 *
296 *****************************************************************************/
AsnTypeValidateOut(AsnIoPtr aip,AsnTypePtr atp,DataValPtr dvp)297 NLM_EXTERN Boolean AsnTypeValidateOut (AsnIoPtr aip, AsnTypePtr atp, DataValPtr dvp)
298 {
299 Int2 isa;
300 AsnTypePtr atp2, parent_type, base_type, curr_type;
301 Boolean foundit;
302 AsnValxNodePtr avnp;
303
304 if ((aip == NULL) || (atp == NULL))
305 return FALSE;
306
307 curr_type = aip->typestack[aip->type_indent].type;
308 base_type = AsnFindBaseType(atp);
309 if (base_type == NULL)
310 {
311 AsnIoErrorMsg(aip, 10, AsnErrGetTypeName(atp->name), "AsnTypeValidateOut");
312 return FALSE;
313 }
314
315 isa = base_type->type->isa;
316
317 if (((isa == SEQ_TYPE) || (isa == SET_TYPE) ||
318 (isa == SEQOF_TYPE) || (isa == SETOF_TYPE))
319 && (dvp->intvalue == END_STRUCT))
320 {
321 switch (isa)
322 {
323 case SEQOF_TYPE:
324 case SETOF_TYPE:
325 break;
326 case SEQ_TYPE: /* check that no more waiting */
327 if (curr_type != NULL) /* check next one */
328 atp2 = curr_type->next;
329 else /* empty sequence written */
330 atp2 = (AsnTypePtr) base_type->branch;
331 while (atp2 != NULL)
332 {
333 if (! (atp2->optional || atp2->hasdefault))
334 {
335 AsnIoErrorMsg(aip, 7, AsnErrGetTypeName(atp2->name), AsnErrGetTypeName(atp->name));
336 return FALSE;
337 }
338 atp2 = atp2->next;
339 }
340 break;
341 default:
342 break;
343 }
344 return TRUE;
345 }
346
347 if (aip->type_indent) /* part of a larger struct */
348 {
349 foundit = FALSE;
350 if (aip->type_indent < 1)
351 return FALSE;
352
353 parent_type = aip->typestack[aip->type_indent - 1].type;
354 base_type = AsnFindBaseType(parent_type);
355 if (base_type == NULL)
356 return FALSE;
357 isa = base_type->type->isa;
358 atp2 = (AsnTypePtr) base_type->branch;
359 while (atp2 != NULL)
360 {
361 if (atp2 == atp)
362 {
363 foundit = TRUE;
364 break;
365 }
366 atp2 = atp2->next;
367 }
368 if (! foundit)
369 {
370 atp2 = AsnFindBaseType(atp);
371 AsnIoErrorMsg(aip, 22, AsnErrGetTypeName(atp->name),
372 AsnErrGetTypeName(atp2->name), AsnErrGetTypeName(parent_type->name));
373 return FALSE;
374 }
375 switch (isa)
376 {
377 case SETOF_TYPE: /* just has to be right type */
378 case SEQOF_TYPE:
379 break;
380 case CHOICE_TYPE: /* can only have one value */
381 if (curr_type != NULL)
382 {
383 AsnIoErrorMsg(aip, 23, AsnErrGetTypeName(parent_type->name),
384 AsnErrGetTypeName(atp->name));
385 return FALSE;
386 }
387 break;
388 case SET_TYPE: /* SET should check for 1 of each */
389 /* non-optional element, but doesn't */
390 if (curr_type == atp)
391 {
392 AsnIoErrorMsg(aip, 24, AsnErrGetTypeName(atp->name),
393 AsnErrGetTypeName(parent_type->name));
394 return FALSE;
395 }
396 break;
397 case SEQ_TYPE:
398 if (curr_type == atp)
399 {
400 AsnIoErrorMsg(aip, 24, AsnErrGetTypeName(atp->name),
401 AsnErrGetTypeName(parent_type->name));
402 return FALSE;
403 }
404 /* check preceeding elements */
405 if (curr_type != NULL)
406 {
407 atp2 = (AsnTypePtr) base_type->branch;
408 while (atp2 != curr_type->next)
409 {
410 if (atp == atp2)
411 {
412 AsnIoErrorMsg(aip, 6, AsnErrGetTypeName(atp->name),
413 AsnErrGetTypeName(parent_type->name));
414 return FALSE;
415 }
416 atp2 = atp2->next;
417 }
418 }
419 else
420 atp2 = (AsnTypePtr) base_type->branch;
421 while ((atp2 != NULL) && (atp != atp2))
422 {
423 if (! (atp2->optional || atp2->hasdefault))
424 { /* skipped a non-optional element */
425 AsnIoErrorMsg(aip, 7, AsnErrGetTypeName(atp2->name),
426 AsnErrGetTypeName(parent_type->name));
427 return FALSE;
428 }
429 atp2 = atp2->next;
430 }
431 if (atp2 == NULL) /* element out of order */
432 {
433 AsnIoErrorMsg(aip, 6, AsnErrGetTypeName(atp->name),
434 AsnErrGetTypeName(parent_type->name));
435 return FALSE;
436 }
437 break;
438 default:
439 AsnIoErrorMsg(aip, 25, AsnErrGetTypeName(parent_type->name),
440 parent_type->isa);
441 return FALSE;
442 }
443 base_type = AsnFindBaseType(atp);
444 isa = base_type->type->isa;
445 }
446
447 if (ISA_STRINGTYPE(isa))
448 isa = GENERALSTRING_TYPE;
449
450 /******************* maintain typestack ****************/
451 switch (isa) /* set aip->typestack for non-struct types */
452 { /* this is done for them in AsnTypeSetIndent() */
453 case SEQ_TYPE:
454 case SET_TYPE:
455 case SEQOF_TYPE:
456 case SETOF_TYPE:
457 case CHOICE_TYPE:
458 default: /* terminal value */
459 aip->typestack[aip->type_indent].type = atp;
460 break;
461 }
462
463 switch (isa) /* check ranges and values */
464 {
465 case ENUM_TYPE:
466 avnp = (AsnValxNodePtr) base_type->branch;
467 while (avnp != NULL)
468 {
469 if (avnp->intvalue == dvp->intvalue)
470 return TRUE;
471 avnp = avnp->next;
472 }
473 AsnIoErrorMsg(aip, 12, dvp->intvalue, AsnErrGetTypeName(atp->name));
474 return FALSE;
475 default :
476 break;
477 }
478 return TRUE;
479 }
480
481 /*****************************************************************************
482 *
483 * AsnTypePathFind(amp, str, countptr)
484 * like AsnTypeFind() but allocates an array of AsnTypePtr and fills
485 * it in with the proper path. Sets countptr to sizeof array.
486 * Returns array or NULL on failure
487 *
488 *****************************************************************************/
AsnTypePathFind(AsnModulePtr amp,CharPtr str,Int2Ptr countptr)489 NLM_EXTERN AsnTypePtr PNTR LIBCALL AsnTypePathFind (AsnModulePtr amp, CharPtr str, Int2Ptr countptr)
490 {
491 AsnModulePtr amp2;
492 AsnTypePtr atp;
493 Int2 count;
494 AsnTypePtr PNTR typeptr;
495 CharPtr ptr;
496
497 *countptr = 0;
498 count = 1;
499 ptr = str;
500 while (*ptr != '\0')
501 {
502 if (*ptr == '.')
503 count++;
504 ptr++;
505 }
506 typeptr = (AsnTypePtr*) MemNew(sizeof(AsnTypePtr) * count);
507
508 if (amp == NULL)
509 {
510 if (amps == NULL)
511 {
512 AsnIoErrorMsg(NULL, (Int2)105);
513 return NULL;
514 }
515 amp = (AsnModulePtr) amps->data.ptrvalue;
516 }
517
518 amp2 = amp;
519 atp = NULL;
520
521 while (amp2 != NULL)
522 {
523 atp = AsnTypeFindType(amp2->types, str, typeptr, count, FALSE);
524 if (atp != NULL)
525 {
526 *countptr = count;
527 return typeptr;
528 }
529 else
530 amp2 = amp2->next;
531 }
532
533 MemFree(typeptr);
534 return NULL; /* not found */
535 }
536
537
538 /*****************************************************************************
539 *
540 * AsnTypePtr AsnTypeFind(amp, str)
541 * finds a type in a module or set of modules
542 * str is a path with dot separation.
543 * E is used to indicate an element of SEQOF or SETOF
544 * looks for partial paths as well
545 *
546 * if called with amp == NULL
547 * searches all loaded modules
548 * returns a single node at the end of the path
549 *
550 *****************************************************************************/
AsnTypeFind(AsnModulePtr amp,CharPtr str)551 NLM_EXTERN AsnTypePtr LIBCALL AsnTypeFind (AsnModulePtr amp, CharPtr str)
552 {
553 AsnModulePtr amp2;
554 AsnTypePtr atp;
555
556 if (amp == NULL)
557 {
558 if (amps == NULL)
559 {
560 AsnIoErrorMsg(NULL, (Int2)105);
561 return NULL;
562 }
563 amp = (AsnModulePtr) amps->data.ptrvalue;
564 }
565
566 amp2 = amp;
567 atp = NULL;
568
569 while (amp2 != NULL)
570 {
571 atp = AsnTypeFindType(amp2->types, str, NULL, 0, FALSE);
572 if (atp != NULL)
573 return atp;
574 else
575 amp2 = amp2->next;
576 }
577
578 return atp; /* not found */
579 }
580
581 /*****************************************************************************
582 *
583 * AsnTypePtr AsnTypeFindType(atp, str, typeptr, count, in_it)
584 *
585 *****************************************************************************/
AsnTypeFindType(AsnTypePtr atp,CharPtr str,AsnTypePtr PNTR typeptr,Int2 count,Boolean in_it)586 NLM_EXTERN AsnTypePtr AsnTypeFindType (AsnTypePtr atp, CharPtr str, AsnTypePtr PNTR typeptr, Int2 count, Boolean in_it)
587 {
588 AsnTypePtr curr, next;
589 CharPtr beg;
590 Int2 len, isa;
591 Boolean is_element, /* (unamed) element of setof seqof */
592 is_type, /* if a type, must find the original def */
593 got_it;
594 AsnTypePtr PNTR typenext;
595 Int2 newcount;
596
597 if (count < 0) /* off array ... error condition */
598 return NULL;
599
600 beg = str;
601 len = 0;
602 if (typeptr == NULL)
603 {
604 typenext = NULL;
605 newcount = 0;
606 }
607 else
608 {
609 newcount = count - 1;
610 if (newcount >= 0)
611 typenext = typeptr + 1;
612 else
613 typenext = NULL;
614 }
615 is_element = FALSE;
616 is_type = FALSE;
617 while ((*beg != '.') && (*beg != '\0'))
618 {
619 beg++; len++;
620 }
621
622 if ((*str == 'E') && (len == 1))
623 is_element = TRUE;
624 else if (IS_UPPER(*str))
625 is_type = TRUE;
626
627 curr = atp; /* look at this level */
628 while (curr != NULL)
629 {
630 got_it = FALSE;
631 if (is_element)
632 got_it = TRUE;
633 else if (StrMatch(curr->name, str, len)) /* found it */
634 {
635 if (! is_type)
636 got_it = TRUE;
637 else /* check that this is the real def */
638 {
639 if (! curr->imported)
640 got_it = TRUE;
641 }
642 }
643
644 if (got_it)
645 {
646 if (typeptr != NULL)
647 *typeptr = curr;
648
649 if (*beg == '\0') /* that's it */
650 return curr;
651 else /* go down the path */
652 {
653 next = AsnFindBaseType(curr);
654 isa = next->type->isa;
655 if ((next->branch != NULL) /* go further */
656 && (isa != INTEGER_TYPE)
657 && (isa != ENUM_TYPE))
658 {
659 next = AsnTypeFindType((AsnTypePtr) next->branch, (beg + 1), typenext, newcount, TRUE);
660 if (next != NULL)
661 return next;
662 }
663 }
664 }
665 curr = curr->next;
666 }
667
668 if (in_it) /* processing a path and can't find next node here */
669 return NULL;
670
671 curr = atp; /* start down a level */
672 while (curr != NULL)
673 {
674 if (curr->branch != NULL)
675 {
676 next = AsnFindBaseType(curr);
677
678 if ((next != NULL) && (next->type != NULL))
679 {
680 isa = next->type->isa;
681 if ((next->branch != NULL) /* go further */
682 && (isa != INTEGER_TYPE)
683 && (isa != ENUM_TYPE))
684 {
685 next = AsnTypeFindType((AsnTypePtr) next->branch, str, typenext, newcount, FALSE);
686 if (next != NULL)
687 {
688 if (typeptr != NULL)
689 *typeptr = curr;
690 return next;
691 }
692 }
693 }
694 /** else, an error has occurred, unresolved branch **/
695 }
696 curr = curr->next;
697 }
698 return NULL;
699 }
700
701 /*****************************************************************************
702 *
703 * CharPtr AsnTypeDumpStack(str, aip)
704 * dump a typestack into str
705 * returns a pointer to the '\0' at the end of the str
706 *
707 *****************************************************************************/
AsnTypeDumpStack(CharPtr str,AsnIoPtr aip)708 NLM_EXTERN CharPtr LIBCALL AsnTypeDumpStack (CharPtr str, AsnIoPtr aip)
709 {
710 Int2 level, isa, lastnochoice;
711
712 lastnochoice = -1;
713 *str = '\0';
714
715 for(level = 0; level <= aip->type_indent; level++)
716 {
717 if (level == aip->type_indent)
718 {
719 if ((aip->type & ASNIO_OUT) ||
720 ((aip->type & ASNIO_IN) && (aip->read_id == FALSE)))
721 str = StringMove(str, "<");
722 }
723 if (aip->typestack[level].type == NULL)
724 str = StringMove(str, " ");
725 else
726 {
727 isa = AsnFindBaseIsa(aip->typestack[level].type);
728 if (aip->typestack[level].type->name != NULL)
729 str = StringMove(str, aip->typestack[level].type->name);
730 else if ((lastnochoice == SEQOF_TYPE) ||
731 (lastnochoice == SETOF_TYPE))
732 str = StringMove(str, "E");
733 else
734 str = StringMove(str, "?");
735 if (isa != CHOICE_TYPE)
736 lastnochoice = isa;
737 }
738 if (level != aip->type_indent)
739 str = StringMove(str, ".");
740 else
741 {
742 if ((aip->type & ASNIO_OUT) ||
743 ((aip->type & ASNIO_IN) && (aip->read_id == FALSE)))
744 str = StringMove(str, ">");
745 }
746 }
747 return str;
748 }
749
750 /*****************************************************************************
751 *
752 * Int4 AsnTypeStringToHex(from, len, to, left)
753 * converts an octet string to binary
754 * returns number of hex digits created if all ok
755 * *left is chars left at the end of the buffer including first letter of
756 * a remaining digit (from does not have an even number of letters)
757 * since this could include white space, could be more than 1
758 * returns a negative number on an error
759 * skips over internal or trailing white space
760 * left can be NULL in which case it is ignored
761 *
762 *****************************************************************************/
AsnTypeStringToHex(Pointer from,Int4 len,Pointer to,Int4Ptr left)763 NLM_EXTERN Int4 LIBCALL AsnTypeStringToHex (Pointer from, Int4 len, Pointer to, Int4Ptr left)
764 {
765 BytePtr f, t;
766 Byte octet = 0, value;
767 int i;
768 Int4 added = 0;
769
770 f = (BytePtr) from;
771 t = (BytePtr) to;
772 if (left != NULL)
773 *left = 0;
774 i = 16;
775
776 while (len)
777 {
778 if (! IS_WHITESP(*f)) /* skip spaces */
779 {
780 if (i == 16) /* first letter of pair */
781 {
782 octet = 0;
783 if (left != NULL)
784 *left = len; /* point at it in case one letter left */
785 }
786
787 value = TO_UPPER(*f);
788 if ((value >= 'A') && (value <= 'F'))
789 octet += (((value - 'A') + 10) * i);
790 else if ((value >= '0') && (value <= '9'))
791 octet += ((value - '0') * i);
792 else
793 return (Int4)(-1);
794
795 if (i == 16) /* first letter of pair */
796 i = 1; /* goto second letter */
797 else /* letter pair was read */
798 {
799 i = 16; /* reset for first letter */
800 if (left != NULL)
801 *left = 0; /* nothing left so far */
802 *t = octet; /* record the hex digit */
803 t++; added++;
804 }
805
806 }
807 len--;
808 f++;
809 }
810 return added;
811 }
812
813 #ifdef ASNTYPE_RUNTIME_LINK
814 static Int2 tstack_max;
815 static AsnTypePtr PNTR tstack;
816 static Int2Ptr prev;
817 #endif
818
819 /*****************************************************************************
820 *
821 * AsnLinkType(type, localtype)
822 * provides for linkage of imported types
823 * if (type != NULL)
824 * it's an element of type localtype
825 * so, set type->type to localtype
826 * else
827 * it's localtype itself
828 * so, return localtype
829 * return pointer to correct type
830 *
831 * ifdef'd OUT NOW THAT LINKING IS DONE AT LOAD TIME
832 *
833 *****************************************************************************/
AsnLinkType(AsnTypePtr type,AsnTypePtr localtype)834 NLM_EXTERN AsnTypePtr LIBCALL AsnLinkType (AsnTypePtr type, AsnTypePtr localtype)
835 {
836
837 if (type == NULL)
838 return localtype;
839 else
840 #ifndef ASNTYPE_RUNTIME_LINK
841 return type; /* assume has been linked at tree load time */
842 #else
843 {
844 Int2 i, j;
845 Int2Ptr oldprev;
846 AsnTypePtr PNTR oldtstack;
847
848 for (i = 0; i < tstack_max; i++)
849 {
850 if (tstack[i] == NULL)
851 break;
852 }
853
854 if (i >= tstack_max) /* increase stack size */
855 {
856 oldtstack = tstack;
857 oldprev = prev;
858 tstack = MemNew(((tstack_max + 20) * sizeof(AsnTypePtr)));
859 prev = MemNew(((tstack_max + 20) * sizeof(Int2)));
860 MemCopy(tstack, oldtstack, (size_t)(tstack_max * sizeof(AsnTypePtr)));
861 MemCopy(prev, oldprev, (size_t)(tstack_max * sizeof(Int2)));
862 MemFree(oldtstack);
863 MemFree(oldprev);
864 tstack_max += 20;
865 }
866
867 j = type->tmp;
868 if (j) /* previous type linked */
869 prev[i] = j;
870 tstack[i] = type->type;
871 type->tmp = (i + 1);
872 if (type != localtype) /* don't link to itself */
873 type->type = localtype;
874 return type;
875 }
876 #endif
877 }
878
879 /*****************************************************************************
880 *
881 * AsnUnlinkType(type)
882 * disconnects local tree.
883 *
884 *****************************************************************************/
AsnUnlinkType(AsnTypePtr type)885 NLM_EXTERN void LIBCALL AsnUnlinkType (AsnTypePtr type)
886 {
887 #ifdef ASNTYPE_RUNTIME_LINK
888 Int2 j;
889
890 if (type != NULL)
891 {
892 j = type->tmp;
893 j--;
894 type->type = tstack[j];
895 if (prev[j])
896 type->tmp = prev[j];
897 else
898 type->tmp = 0;
899 tstack[j] = NULL;
900 prev[j] = 0;
901 }
902 #endif
903 return;
904 }
905
AddXMLname(AsnTypePtr atp,AsnTypePtr PNTR typestack,Int2 stackptr)906 static void AddXMLname(AsnTypePtr atp, AsnTypePtr PNTR typestack, Int2 stackptr)
907 {
908 Char buf[80];
909 AsnTypePtr atp2;
910 Boolean found=FALSE, getparent=TRUE, doitem = FALSE, done = FALSE;
911 CharPtr tmp;
912 Int2 i, isa;
913
914 if (atp->XMLname == NULL) /* only do it once */
915 {
916 tmp = buf; *tmp = '\0';
917 if (atp->name == NULL)
918 {
919 doitem = TRUE;
920 }
921 else if (IS_UPPER(*(atp->name)))
922 {
923 getparent = FALSE;
924 tmp = StringMove(tmp, atp->name);
925 }
926
927 if ((getparent) && (stackptr))
928 {
929 atp2 = typestack[stackptr - 1];
930 isa = AsnFindBaseIsa(atp2);
931 if ((doitem) && ((isa == SEQOF_TYPE) || (isa == SETOF_TYPE)))
932 {
933 atp2 = AsnFindBaseTypeDTD(atp);
934 if (atp2 != NULL)
935 {
936 if (atp2->name == NULL)
937 {
938 atp2 = typestack[stackptr - 1];
939 if (atp->type != NULL)
940 {
941 if (ISA_BASETYPE(atp->type->isa))
942 {
943 if (atp2->XMLname != NULL)
944 {
945 tmp = StringMove(tmp, atp2->XMLname);
946 getparent = FALSE;
947 found = TRUE;
948 }
949 }
950 }
951 }
952 else
953 {
954 if (atp2->XMLname != NULL)
955 tmp = StringMove(tmp, atp2->XMLname);
956 else if (atp2->name != NULL)
957 tmp = StringMove(tmp, atp2->name);
958 if (*buf != '\0')
959 {
960 doitem = FALSE;
961 getparent = FALSE;
962 done = TRUE;
963 found = TRUE;
964 }
965 }
966 }
967 }
968
969 atp2 = typestack[stackptr - 1];
970 if ((getparent) && (atp2->XMLname != NULL)) /* already nested */
971 {
972 tmp = StringMove(tmp, atp2->XMLname);
973 tmp = StringMove(tmp, "_");
974 getparent = FALSE;
975 found = TRUE;
976 }
977
978 if ((stackptr) && (getparent))
979 {
980 found = FALSE;
981
982 for (i = (stackptr - 1); (i >= 0) && (! found); i--)
983 {
984 atp2 = AsnFindBaseTypeDTD(typestack[i]);
985 if ((atp2 != NULL) && (atp2->name != NULL) && (IS_UPPER(*(atp2->name))))
986 {
987 while (i < stackptr)
988 {
989 atp2 = AsnFindBaseTypeDTD(typestack[i]);
990 if (atp2->name == NULL)
991 tmp = StringMove(tmp, "E");
992 else
993 tmp = StringMove(tmp, atp2->name);
994 tmp = StringMove(tmp, "_");
995 i++;
996 }
997 found = TRUE;
998 }
999 }
1000 }
1001
1002 if ((! done) && found)
1003 {
1004 if (doitem)
1005 tmp = StringMove(tmp, "_E");
1006 else
1007 tmp = StringMove(tmp, atp->name);
1008 }
1009 }
1010
1011
1012 if (*buf != '\0')
1013 {
1014 atp->XMLname = StringSave(buf);
1015 }
1016 }
1017
1018 atp2 = AsnFindBaseTypeDTD(atp);
1019 if ((! atp->imported) && (atp2 != NULL) && (atp2->type != NULL))
1020 {
1021 isa = atp2->type->isa;
1022 if ((isa == SEQ_TYPE) || (isa == SET_TYPE))
1023 {
1024 typestack[stackptr] = atp;
1025 for (atp2 = atp->branch; atp2 != NULL; atp2 = atp2->next)
1026 AddXMLname(atp2, typestack, (Int2)(stackptr + 1));
1027 }
1028 else if ((isa == SEQOF_TYPE) || (isa == SETOF_TYPE))
1029 {
1030 typestack[stackptr] = atp;
1031 for (atp2 = atp->branch; atp2 != NULL; atp2 = atp2->next)
1032 AddXMLname(atp2, typestack, (Int2)(stackptr + 1));
1033 }
1034 else if (isa == CHOICE_TYPE)
1035 {
1036 typestack[stackptr] = atp;
1037 for (atp2 = atp->branch; atp2 != NULL; atp2 = atp2->next)
1038 AddXMLname(atp2, typestack, (Int2)(stackptr + 1));
1039 }
1040 }
1041
1042 return;
1043
1044 }
1045 /*****************************************************************************
1046 *
1047 * void AsnModuleLink(amp)
1048 * links IMPORT types with EXPORTS from other modules
1049 * if cannot link an IMPORT, no errors are generated
1050 *
1051 *****************************************************************************/
AsnModuleLink(AsnModulePtr amp)1052 NLM_EXTERN void LIBCALL AsnModuleLink (AsnModulePtr amp)
1053 {
1054 AsnTypePtr atp, atp2, typestack[10];
1055 AsnModulePtr currmod, mod;
1056 Boolean found;
1057
1058 currmod = amp;
1059 while (currmod != NULL)
1060 {
1061 atp = currmod->types;
1062 while (atp != NULL)
1063 {
1064 if ((atp->imported) && (atp->type == NULL)) /* link imported types */
1065 {
1066 mod = amp;
1067 if (mod == currmod)
1068 mod = mod->next;
1069 found = FALSE;
1070 while ((mod != NULL) && (! found))
1071 {
1072 atp2 = mod->types;
1073 while ((atp2 != NULL) && (! found))
1074 {
1075 if ((! atp2->imported) &&
1076 (! StringCmp(atp2->name, atp->name)))
1077 {
1078 if (atp2->exported)
1079 {
1080 atp->type = atp2;
1081 found = TRUE;
1082 }
1083 else
1084 {
1085 AsnIoErrorMsg(NULL, 84, AsnErrGetTypeName(atp2->name),
1086 mod->modulename);
1087 atp2 = atp2->next;
1088 }
1089 }
1090 else
1091 atp2 = atp2->next;
1092 }
1093 mod = mod->next;
1094 if (mod == currmod)
1095 mod = mod->next;
1096 }
1097 }
1098 atp = atp->next;
1099 }
1100 currmod = currmod->next;
1101 }
1102
1103 /*** Fill in the XML names *********/
1104
1105 currmod = amp;
1106 while (currmod != NULL)
1107 {
1108 atp = currmod->types;
1109 while (atp != NULL)
1110 {
1111 AddXMLname(atp, typestack, (Int2)0);
1112 atp = atp->next;
1113 }
1114 currmod = currmod->next;
1115 }
1116
1117
1118 return;
1119 }
1120
1121 /*****************************************************************************
1122 *
1123 * AsnStoreTree(file, amp)
1124 *
1125 *****************************************************************************/
AsnStoreTree(CharPtr file,AsnModulePtr amp)1126 NLM_EXTERN void LIBCALL AsnStoreTree (CharPtr file, AsnModulePtr amp)
1127 {
1128 ValNodePtr anp, last;
1129 AsnModulePtr tamp, tamp2, newamp;
1130 Int2 numamp;
1131
1132 /* check to see if we already have it (could happen) */
1133
1134 anp = names;
1135 last = NULL;
1136 while (anp != NULL)
1137 {
1138 if (! StringCmp((CharPtr)anp->data.ptrvalue, file))
1139 return; /* have it */
1140 last = anp;
1141 anp = anp->next;
1142 }
1143
1144 /* add the name */
1145 anp = ValNodeNew(last);
1146 if (last == NULL)
1147 names = anp;
1148 anp->data.ptrvalue = (Pointer) StringSave(file);
1149
1150 last = NULL;
1151 anp = amps;
1152 while (anp != NULL)
1153 {
1154 last = anp;
1155 anp = anp->next;
1156 }
1157 anp = ValNodeNew(last);
1158 if (last == NULL)
1159 amps = anp;
1160
1161 tamp = amp;
1162 numamp = 0;
1163 while (tamp != NULL)
1164 {
1165 numamp++;
1166 tamp = tamp->next;
1167 }
1168 newamp = (AsnModulePtr) MemNew(numamp * sizeof(AsnModule));
1169 anp->data.ptrvalue = (Pointer) newamp;
1170 tamp = amp;
1171 tamp2 = newamp;
1172 while (numamp)
1173 {
1174 MemCopy(tamp2, tamp, sizeof(AsnModule));
1175 tamp2++; tamp++; numamp--;
1176 }
1177 if (last != NULL)
1178 {
1179 tamp = (AsnModulePtr)last->data.ptrvalue;
1180 while (tamp->next != NULL)
1181 tamp = tamp->next;
1182 tamp->next = newamp; /* link it in to list copy */
1183 }
1184
1185 tamp = (AsnModulePtr) amps->data.ptrvalue;
1186 AsnModuleLink(tamp); /* connect the tree */
1187 return;
1188 }
1189
1190
1191 /*****************************************************************************
1192 *
1193 * Pointer PointerDecode(index, avn, at)
1194 *
1195 *****************************************************************************/
PointerDecode(Int2 index,AsnValxNodePtr avn,AsnTypePtr at)1196 static Pointer PointerDecode (Int2 index, AsnValxNodePtr avn, AsnTypePtr at)
1197 {
1198 if (index == -32000)
1199 return NULL;
1200 if (index == -32001)
1201 return (Pointer) avn;
1202 if (index < 0)
1203 {
1204 index *= -1;
1205 return (Pointer) &avn[index];
1206 }
1207 return (Pointer) &at[index];
1208 }
1209
1210 /*****************************************************************************
1211 *
1212 * AsnTreeLoad(file, &avn, &at, &)
1213 *
1214 *****************************************************************************/
AsnTreeLoad(char * file,AsnValxNodePtr * avnptr,AsnTypePtr * atptr,AsnModulePtr * ampptr)1215 NLM_EXTERN Boolean LIBCALL AsnTreeLoad (char *file, AsnValxNodePtr *avnptr, AsnTypePtr *atptr, AsnModulePtr *ampptr)
1216 {
1217 AsnValxNodePtr avn = NULL, avncurr;
1218 AsnTypePtr at = NULL, atcurr;
1219 AsnModulePtr amp = NULL, ampcurr;
1220 ValNodePtr anp, ampanp;
1221 int numval, numtype, nummod, i;
1222 FILE * fp;
1223 int isa, next;
1224 long intvalue;
1225 double realvalue;
1226 char name[PATH_MAX], fname[60];
1227 CharPtr ptr;
1228 int bools[5], tagclass, tagnumber, defaultvalue, type, branch;
1229
1230 /* check to see if we already have it (could happen) */
1231
1232 anp = names;
1233 ampanp = amps;
1234 while (anp != NULL)
1235 {
1236 if (! StringCmp((CharPtr)anp->data.ptrvalue, file))
1237 { /* have it */
1238 if (* ampptr == NULL) /* fill dynamic load */
1239 {
1240 * ampptr = (AsnModulePtr) ampanp->data.ptrvalue;
1241 * atptr = (* ampptr)->types;
1242 /* don't really need avnptr filled in */
1243 }
1244 return TRUE;
1245 }
1246 ampanp = ampanp->next;
1247 anp = anp->next;
1248 }
1249
1250 if (! ProgMon("Load ASN.1 Trees"))
1251 return FALSE;
1252
1253 if (* ampptr != NULL) /* static load, add to list */
1254 {
1255 AsnStoreTree(file, (* ampptr));
1256 return TRUE; /* already loaded */
1257 }
1258
1259 if (! FindPath("ncbi", "ncbi", "asnload", name, sizeof (name)))
1260 {
1261 AsnIoErrorMsg(NULL, 85);
1262 return FALSE;
1263 }
1264
1265 FileBuildPath (name, NULL, file);/* add file to path */
1266
1267 fp = FileOpen(name, "r");
1268 if (fp == NULL)
1269 {
1270 AsnIoErrorMsg(NULL, 83, (CharPtr) name);
1271 return FALSE;
1272 }
1273
1274 fscanf(fp, "%d %d %d", &numval, &numtype, &nummod);
1275
1276 if (numval)
1277 avn = (AsnValxNodePtr) MemNew(numval * sizeof(AsnValxNode));
1278 at = (AsnTypePtr) MemNew(numtype * sizeof(AsnType));
1279 amp = (AsnModulePtr) MemNew(nummod * sizeof(AsnModule));
1280
1281 *avnptr = avn;
1282 *atptr = at;
1283 *ampptr = amp;
1284
1285 avncurr = avn;
1286 for (i = 0; i < numval; i++)
1287 {
1288 fscanf(fp, "%d %s %ld %lf %d", &isa, name, &intvalue, &realvalue, &next);
1289 avncurr->valueisa = isa;
1290 if (*name != '-')
1291 avncurr->name = StringSave(name);
1292 avncurr->intvalue = (Int4)intvalue;
1293 avncurr->realvalue = (FloatHi)realvalue;
1294 avncurr->next = (AsnValxNodePtr) PointerDecode((Int2)next, avn, at);
1295 avncurr++;
1296 }
1297
1298 atcurr = at;
1299 for (i = 0; i < numtype; i++)
1300 {
1301 fscanf(fp, "%d %s %d %d %d %d %d %d %d %d %d %d %d",
1302 &isa, name, &tagclass, &tagnumber, bools, bools+1, bools+2,
1303 bools+3, bools+4, &defaultvalue, &type, &branch, &next);
1304 atcurr->isa = isa;
1305 if (*name != '-')
1306 {
1307 atcurr->name = StringSave(name);
1308 ptr = atcurr->name;
1309 while (*ptr != '\0')
1310 {
1311 if (*ptr == '!')
1312 *ptr = ' ';
1313 ptr++;
1314 }
1315 }
1316 atcurr->tagclass = (Uint1)tagclass;
1317 atcurr->tagnumber = tagnumber;
1318 atcurr->implicit = (Boolean)bools[0];
1319 atcurr->optional = (Boolean)bools[1];
1320 atcurr->hasdefault = (Boolean)bools[2];
1321 atcurr->exported = (Boolean)bools[3];
1322 atcurr->imported = (Boolean)bools[4];
1323 atcurr->defaultvalue = (AsnValxNodePtr)PointerDecode((Int2)defaultvalue, avn, at);
1324 atcurr->type = (AsnTypePtr)PointerDecode((Int2)type, avn, at);
1325 atcurr->branch = PointerDecode((Int2)branch, avn, at);
1326 atcurr->next = (AsnTypePtr)PointerDecode((Int2)next, avn,at);
1327 atcurr++;
1328 }
1329
1330 ampcurr = amp;
1331 for (i = 0; i < nummod; i++)
1332 {
1333 fscanf(fp, "%s %s %d %d", name, fname, &type, &next);
1334 if (*name != '-')
1335 ampcurr->modulename = StringSave(name);
1336 if (*fname != '-')
1337 ampcurr->filename = StringSave(fname);
1338 ampcurr->types = (AsnTypePtr)PointerDecode((Int2)type, avn, at);
1339 if (next != -32000)
1340 ampcurr->next = &[next];
1341 ampcurr++;
1342 }
1343
1344 FileClose(fp);
1345 /* store it in list */
1346 AsnStoreTree(file, (* ampptr));
1347
1348 return TRUE;
1349 }
1350
1351 /*****************************************************************************
1352 *
1353 * AsnEnumStr(type, val)
1354 *
1355 *****************************************************************************/
AsnEnumStr(CharPtr type,Int2 val)1356 NLM_EXTERN CharPtr LIBCALL AsnEnumStr (CharPtr type, Int2 val)
1357 {
1358 AsnTypePtr atp;
1359
1360 if (amps == NULL)
1361 {
1362 AsnIoErrorMsg(NULL, (Int2)105);
1363 return NULL;
1364 }
1365 atp = AsnTypeFind((AsnModulePtr)amps->data.ptrvalue, type);
1366 return AsnEnumTypeStr(atp, val);
1367 }
1368
1369 /*****************************************************************************
1370 *
1371 * AsnEnumTypeStr(atp, val)
1372 * returns string for ennumerated type val or a named integer
1373 *
1374 *****************************************************************************/
AsnEnumTypeStr(AsnTypePtr atp,Int2 val)1375 NLM_EXTERN CharPtr LIBCALL AsnEnumTypeStr (AsnTypePtr atp, Int2 val)
1376 {
1377 AsnValxNodePtr avnp;
1378
1379 atp = AsnFindBaseType(atp);
1380 if (atp == NULL)
1381 return NULL;
1382
1383 if ((atp->type->isa != ENUM_TYPE) && (atp->type->isa != INTEGER_TYPE))
1384 return NULL;
1385
1386 avnp = (AsnValxNodePtr) atp->branch;
1387 while (avnp != NULL)
1388 {
1389 if (val == (Int2) avnp->intvalue)
1390 return avnp->name;
1391 else
1392 avnp = avnp->next;
1393 }
1394 return NULL;
1395 }
1396
1397 /*****************************************************************************
1398 *
1399 * AsnAllModPtr()
1400 * returns a pointer to the start of all modules in memory
1401 *
1402 *****************************************************************************/
AsnAllModPtr(void)1403 NLM_EXTERN AsnModulePtr LIBCALL AsnAllModPtr (void)
1404 {
1405 if (amps == NULL)
1406 return NULL;
1407 return (AsnModulePtr)amps->data.ptrvalue;
1408 }
1409
1410
1411
1412