1 /* asnlex.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: asnlex.c
27 *
28 * Author: James Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.11 $
33 *
34 * File Description:
35 * Routines for parsing ASN.1 value nototation (text) messages
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * Date Name Description of modification
40 * ------- ---------- -----------------------------------------------------
41 *
42 * ==========================================================================
43 */
44
45 /*****************************************************************************
46 *
47 * asnlex.c
48 * special text lexxer for asn.1
49 *
50 *****************************************************************************/
51
52 #include "asnbuild.h"
53
54
55 /*****************************************************************************
56 *
57 * Int2 AsnLexScan(aip, name)
58 * scans until name ::= to start reading asn.1 past garbage
59 *
60 *****************************************************************************/
61 static Int2 AsnLexScan PROTO((AsnIoPtr aip, CharPtr name));
62
63 /*****************************************************************************
64 *
65 * AsnTypePtr AsnTxtReadId(aip, amp, atp)
66 * reads identifier for next value
67 *
68 *****************************************************************************/
AsnTxtReadId(AsnIoPtr aip,AsnModulePtr amp,AsnTypePtr atp)69 NLM_EXTERN AsnTypePtr LIBCALL AsnTxtReadId (AsnIoPtr aip, AsnModulePtr amp, AsnTypePtr atp)
70 {
71 Int2 token, isa;
72 AsnTypePtr atp2, atp3, atp4;
73 PstackPtr currpsp, prevpsp;
74 Boolean is_ref;
75
76 if (! aip->type_indent) /* just starting reading */
77 {
78 if (atp == NULL) /* starting an unknown item */
79 {
80 token = AsnLexWord(aip);
81 if (token == EOF_TOKEN)
82 return NULL;
83
84 if (token != REF)
85 {
86 AsnIoErrorMsg(aip, 26, aip->linenumber);
87 return NULL;
88 }
89
90 atp = AsnLexFindType(aip, amp);
91 if (atp == NULL)
92 {
93 AsnIoErrorMsg(aip, 27, aip->linenumber);
94 return NULL;
95 }
96
97 token = AsnLexWord(aip);
98 if (token != ISDEF)
99 {
100 AsnIoErrorMsg(aip, 28, aip->linenumber);
101 return NULL;
102 }
103 }
104 else /* reading a known, possibly internal value */
105 {
106 if ((atp->name != NULL) && /* do we need to read a type ref? */
107 (IS_UPPER(*atp->name)))
108 is_ref = TRUE;
109 else
110 is_ref = FALSE;
111
112 if ((is_ref) && (aip->scan_for_start))
113 {
114 token = AsnLexScan(aip, atp->name); /* scan to start */
115 if (token == EOF_TOKEN)
116 return NULL;
117 if (token != ISDEF)
118 {
119 AsnIoErrorMsg(aip, 28, aip->linenumber);
120 return NULL;
121 }
122 }
123 else if ((is_ref) || (aip->bytes)) /* reading an internal value */
124 {
125 token = AsnLexWord(aip);
126 if (token == EOF_TOKEN)
127 return NULL;
128
129 if (! StrMatch(atp->name, aip->word, aip->wordlen))
130 {
131 AsnIoErrorMsg(aip, 29,AsnErrGetTypeName(atp->name), aip->linenumber);
132 return NULL;
133 }
134 if (token == REF) /* read of a non-internal value */
135 {
136 token = AsnLexWord(aip);
137 if (token != ISDEF)
138 {
139 AsnIoErrorMsg(aip, 28, aip->linenumber);
140 return NULL;
141 }
142 }
143 }
144
145 }
146
147 aip->typestack[0].type = atp; /* load first type */
148 aip->typestack[0].resolved = FALSE;
149
150 return atp;
151 }
152
153 currpsp = & aip->typestack[aip->type_indent];
154 prevpsp = currpsp - 1;
155
156 if (currpsp->type != NULL) /* reading in a struct */
157 {
158 token = AsnLexWord(aip);
159 switch (token)
160 {
161 case COMMA:
162 break;
163 case END_STRUCT:
164 return prevpsp->type;
165
166 default:
167 AsnIoErrorMsg(aip, 30, aip->linenumber);
168 return NULL;
169 }
170 }
171
172 /* check for SEQOF and SETOF */
173
174 atp = prevpsp->type;
175 atp2 = AsnFindBaseType(atp);
176 isa = atp2->type->isa;
177 if ((isa == SEQOF_TYPE) || (isa == SETOF_TYPE))
178 {
179 token = AsnLexWord(aip);
180 if (token == END_STRUCT) /* empty set */
181 return prevpsp->type;
182 aip->tagsaved = TRUE; /* not empty, note not read */
183 atp = (AsnTypePtr) atp2->branch; /* set of what type? */
184 currpsp->type = atp;
185 currpsp->resolved = FALSE;
186 return atp; /* no type identifier */
187 }
188
189
190 token = AsnLexWord(aip);
191
192 if (token == EOF_TOKEN)
193 {
194 AsnIoErrorMsg(aip, 17 );
195 return NULL;
196 }
197
198 if ((token == END_STRUCT) && ((isa == SEQ_TYPE) || (isa == SET_TYPE)))
199 return prevpsp->type; /* empty SET/SEQ */
200
201 if (token != IDENT)
202 {
203 AsnIoErrorMsg(aip, 31, aip->linenumber);
204 return NULL;
205 }
206
207 atp = AsnLexFindElement(aip, (AsnTypePtr) atp2->branch);
208 if (atp == NULL)
209 {
210 AsnIoErrorMsg(aip, 32, AsnErrGetTypeName(prevpsp->type->name), aip->linenumber);
211 return NULL;
212 }
213
214 if (atp2->type->isa == SEQ_TYPE) /* check sequence order */
215 {
216 atp3 = currpsp->type;
217 if (atp3 != NULL)
218 {
219 atp4 = (AsnTypePtr) atp2->branch;
220 atp3 = atp3->next;
221 while (atp4 != atp3)
222 {
223 if (atp == atp4)
224 {
225 AsnIoErrorMsg(aip, 33,AsnErrGetTypeName(atp->name), AsnErrGetTypeName(atp2->name), aip->linenumber);
226 return NULL;
227 }
228 atp4 = atp4->next;
229 }
230 }
231 else
232 atp3 = (AsnTypePtr) atp2->branch;
233
234 while ((atp3 != NULL) && (atp3 != atp))
235 {
236 if (! (atp3->optional || atp3->hasdefault))
237 {
238 AsnIoErrorMsg(aip, 34,AsnErrGetTypeName(atp3->name), AsnErrGetTypeName(atp2->name), aip->linenumber);
239 return NULL;
240 }
241 atp3 = atp3->next;
242 }
243 }
244
245 currpsp->type = atp;
246 currpsp->resolved = FALSE; /* mark first use */
247 return atp;
248 }
249
250 /*****************************************************************************
251 *
252 * Int2 AsnTxtReadVal(aip, atp, valueptr)
253 * read the value pointed at by atp
254 * returns START_STRUCT
255 * END_STRUCT
256 * or 1 if ok
257 * 0 if an error
258 * if (valueptr == NULL)
259 * just checks that value is of proper type
260 *
261 *****************************************************************************/
262
263 static Pointer AsnLexReadStringUTF8 (AsnIoPtr aip, AsnTypePtr atp);
264 static Boolean AsnLexSkipStringUTF8 (AsnIoPtr aip, AsnTypePtr atp);
265
AsnTxtReadVal(AsnIoPtr aip,AsnTypePtr atp,DataValPtr valueptr)266 NLM_EXTERN Int2 LIBCALL AsnTxtReadVal (AsnIoPtr aip, AsnTypePtr atp, DataValPtr valueptr)
267 {
268 Int2 isa, token, retval;
269 Boolean terminalvalue; /* set if read a terminal value */
270 AsnTypePtr atp2;
271 Boolean read_value;
272 DataVal fake_value;
273 AsnTypePtr base_type, curr_type;
274 PstackPtr currpsp;
275
276 retval = 1; /* assume success */
277 currpsp = & aip->typestack[aip->type_indent];
278 curr_type = currpsp->type;
279
280 if (atp == NULL)
281 return 0;
282
283 base_type = AsnFindBaseType(atp);
284 if (base_type == NULL) /* not found */
285 {
286 base_type = atp;
287 while (base_type->type != NULL)
288 base_type = base_type->type;
289 if (base_type->imported)
290 {
291 AsnIoErrorMsg(aip,35, AsnErrGetTypeName(atp->name), base_type->name, aip->linenumber);
292 return 0;
293 }
294 else
295 {
296 AsnIoErrorMsg(aip,36, AsnErrGetTypeName(atp->name), base_type->name, aip->linenumber);
297 return 0;
298 }
299 }
300 isa = base_type->type->isa;
301
302 if (valueptr == NULL) /* just check the value */
303 {
304 read_value = FALSE;
305 valueptr = &fake_value;
306 }
307 else
308 read_value = TRUE;
309
310 terminalvalue = TRUE; /* most values are terminal values */
311
312 if (ISA_STRINGTYPE(isa) && isa != UTF8STRING_TYPE)
313 isa = GENERALSTRING_TYPE;
314
315 switch (isa)
316 {
317 case SEQ_TYPE:
318 case SET_TYPE:
319 case SETOF_TYPE:
320 case SEQOF_TYPE:
321 terminalvalue = FALSE; /* handled by AsnTypeSetIndent() */
322 if (aip->token != END_STRUCT) /* should be open brace */
323 {
324 token = AsnLexWord(aip); /* read open brace */
325 if (token != START_STRUCT)
326 {
327 AsnIoErrorMsg(aip, 37, aip->linenumber);
328 return 0;
329 }
330 AsnTypeSetIndent(TRUE, aip, atp);
331 retval = START_STRUCT;
332 valueptr->intvalue = START_STRUCT;
333 terminalvalue = FALSE;
334 }
335 else
336 { /* close brace already read in AsnTxtReadId */
337 switch (isa)
338 {
339 case SEQOF_TYPE:
340 case SETOF_TYPE:
341 break;
342 case SEQ_TYPE: /* check that no more waiting */
343 if (curr_type != NULL) /* check next one */
344 atp2 = curr_type->next;
345 else /* empty sequence written */
346 atp2 = (AsnTypePtr)base_type->branch;
347 while (atp2 != NULL)
348 {
349 if (! (atp2->optional || atp2->hasdefault))
350 {
351
352 AsnIoErrorMsg(aip, 34, AsnErrGetTypeName(atp2->name), base_type->name, aip->linenumber);
353 return 0;
354 }
355 atp2 = atp2->next;
356 }
357 break;
358 default:
359 break;
360 }
361 AsnTypeSetIndent(FALSE, aip, atp);
362 retval = END_STRUCT;
363 valueptr->intvalue = END_STRUCT;
364 }
365 break;
366 case CHOICE_TYPE:
367 AsnTypeSetIndent(TRUE, aip, atp); /* nest down to type */
368 terminalvalue = FALSE;
369 break;
370 case BOOLEAN_TYPE:
371 valueptr->boolvalue = AsnLexReadBoolean(aip, atp);
372 break;
373 case INTEGER_TYPE:
374 valueptr->intvalue = AsnLexReadBigInt(aip, atp);
375 break;
376 case ENUM_TYPE:
377 valueptr->intvalue = AsnLexReadInteger(aip, atp);
378 break;
379 case BIGINT_TYPE:
380 valueptr->bigintvalue = AsnLexReadBigInt(aip, atp);
381 break;
382 case REAL_TYPE:
383 valueptr->realvalue = AsnLexReadReal(aip, atp);
384 break;
385 case GENERALSTRING_TYPE:
386 if (read_value)
387 {
388 valueptr->ptrvalue = AsnLexReadString(aip, atp);
389 if (valueptr->ptrvalue == NULL)
390 return 0;
391 }
392 else
393 {
394 if (! AsnLexSkipString(aip, atp))
395 return 0;
396 }
397 break;
398 case UTF8STRING_TYPE:
399 if (read_value)
400 {
401 valueptr->ptrvalue = AsnLexReadStringUTF8(aip, atp);
402 if (valueptr->ptrvalue == NULL)
403 return 0;
404 }
405 else
406 {
407 if (! AsnLexSkipStringUTF8(aip, atp))
408 return 0;
409 }
410 break;
411 case NULL_TYPE:
412 AsnLexReadNull(aip, atp);
413 break;
414 case OCTETS_TYPE:
415 if (read_value)
416 {
417 valueptr->ptrvalue = AsnLexReadOctets(aip, atp);
418 if (valueptr->ptrvalue == NULL) return 0;
419 }
420 else
421 AsnLexSkipOctets(aip, atp);
422 break;
423 case STRSTORE_TYPE:
424 if (read_value)
425 {
426 valueptr->ptrvalue = (ByteStorePtr) AsnLexReadString(aip, atp);
427 if (valueptr->ptrvalue == NULL)
428 return 0;
429 }
430 else
431 {
432 if (! AsnLexSkipString(aip, atp))
433 return 0;
434 }
435 break;
436 default:
437 AsnIoErrorMsg(aip, 38, AsnErrGetTypeName(atp->name),aip->linenumber);
438 return 0;
439 }
440
441 if (terminalvalue) /* pop out of any CHOICE nests */
442 {
443 while ((aip->type_indent) &&
444 (AsnFindBaseIsa(aip->typestack[aip->type_indent - 1].type) == CHOICE_TYPE))
445 AsnTypeSetIndent(FALSE, aip, atp);
446 }
447
448 return retval;
449 }
450
451 /*****************************************************************************
452 *
453 * AsnTypePtr AsnLexFindType(aip, amp)
454 * returns pointer to type definition in amp
455 * or NULL if not found
456 *
457 *****************************************************************************/
AsnLexFindType(AsnIoPtr aip,AsnModulePtr amp)458 NLM_EXTERN AsnTypePtr AsnLexFindType (AsnIoPtr aip, AsnModulePtr amp)
459 {
460 AsnTypePtr atp;
461
462 while (amp != NULL)
463 {
464 atp = AsnLexFindElement(aip, amp->types);
465 if (atp != NULL)
466 return atp;
467
468 amp = amp->next;
469 }
470 return NULL;
471 }
472
473 /*****************************************************************************
474 *
475 * AsnTypePtr AsnLexFindElement(aip, atp)
476 * finds an element in a list of elements
477 * (elements of SEQ, SET, CHOICE)
478 *
479 *****************************************************************************/
AsnLexFindElement(AsnIoPtr aip,AsnTypePtr atp)480 NLM_EXTERN AsnTypePtr AsnLexFindElement (AsnIoPtr aip, AsnTypePtr atp)
481 {
482 while (atp != NULL)
483 {
484 if (StrMatch(atp->name, aip->word, aip->wordlen)) /* it matches */
485 return atp;
486 else
487 atp = atp->next;
488 }
489 return NULL;
490 }
491
492
493 /*****************************************************************************
494 *
495 * Int4 AsnLexReadInteger(aip, atp)
496 * expects an INTEGER or ENUMERATED next
497 * assumes none of it has already been read
498 * does not advance to next token
499 * atp points to the definition of this integer for named values
500 *
501 *****************************************************************************/
AsnLexReadInteger(AsnIoPtr aip,AsnTypePtr atp)502 NLM_EXTERN Int4 AsnLexReadInteger (AsnIoPtr aip, AsnTypePtr atp)
503 {
504 Int2 token;
505 AsnValxNodePtr avnp;
506 AsnTypePtr atp2;
507
508 token = AsnLexWord(aip); /* read the integer */
509
510 if (token == NUMBER) /* just a number */
511 {
512 return AsnLexInteger(aip);
513 }
514
515 if (token != IDENT) /* not number or named value */
516 {
517 AsnIoErrorMsg(aip, 39, AsnErrGetTypeName(atp->name), aip->linenumber);
518 return 0;
519 }
520
521 /******************** read a named integer value *********/
522 atp2 = AsnFindBaseType(atp);
523 if (atp2->branch != NULL) /* named values */
524 {
525 avnp = (AsnValxNodePtr) atp2->branch;
526 while (avnp != NULL)
527 {
528 if (StrMatch(avnp->name, aip->word, aip->wordlen))
529 return avnp->intvalue;
530 avnp = avnp->next;
531 }
532 }
533
534 if (atp2->type->isa == ENUM_TYPE) /* enumerated MUST match named value */
535 {
536 AsnIoErrorMsg(aip, 40, AsnErrGetTypeName(atp->name), aip->linenumber);
537 return 0;
538 }
539
540 /******************* could it be a previously defined value? ***/
541
542 AsnIoErrorMsg(aip, 41, AsnErrGetTypeName(atp->name), aip->linenumber);
543
544 return 0;
545 }
546
547 /*****************************************************************************
548 *
549 * Int8 AsnLexReadBigInt(aip, atp)
550 * expects an INTEGER next
551 * assumes none of it has already been read
552 * does not advance to next token
553 * atp points to the definition of this integer for named values
554 *
555 *****************************************************************************/
AsnLexReadBigInt(AsnIoPtr aip,AsnTypePtr atp)556 NLM_EXTERN Int8 AsnLexReadBigInt (AsnIoPtr aip, AsnTypePtr atp)
557 {
558 Int2 token;
559 AsnValxNodePtr avnp;
560 AsnTypePtr atp2;
561
562 token = AsnLexWord(aip); /* read the integer */
563
564 if (token == NUMBER) /* just a number */
565 {
566 return AsnLexBigInt(aip);
567 }
568
569 if (token != IDENT) /* not number or named value */
570 {
571 AsnIoErrorMsg(aip, 39, AsnErrGetTypeName(atp->name), aip->linenumber);
572 return 0;
573 }
574
575 /******************** read a named integer value *********/
576 atp2 = AsnFindBaseType(atp);
577 if (atp2->branch != NULL) /* named values */
578 {
579 avnp = (AsnValxNodePtr) atp2->branch;
580 while (avnp != NULL)
581 {
582 if (StrMatch(avnp->name, aip->word, aip->wordlen))
583 return avnp->intvalue;
584 avnp = avnp->next;
585 }
586 }
587
588 if (atp2->type->isa == ENUM_TYPE) /* enumerated MUST match named value */
589 {
590 AsnIoErrorMsg(aip, 40, AsnErrGetTypeName(atp->name), aip->linenumber);
591 return 0;
592 }
593
594 /******************* could it be a previously defined value? ***/
595
596 AsnIoErrorMsg(aip, 41, AsnErrGetTypeName(atp->name), aip->linenumber);
597
598 return (Int8)0;
599 }
600
601 /*****************************************************************************
602 *
603 * Boolean AsnLexReadBoolean(aip, atp)
604 * expects a BOOLEAN next
605 * assumes none of it has already been read
606 * does not advance to next token
607 * atp points to the definition of this BOOLEN
608 *
609 *****************************************************************************/
AsnLexReadBoolean(AsnIoPtr aip,AsnTypePtr atp)610 NLM_EXTERN Boolean AsnLexReadBoolean (AsnIoPtr aip, AsnTypePtr atp)
611 {
612 AsnLexWord(aip); /* read the boolean */
613
614 if (StrMatch("TRUE", aip->word, aip->wordlen))
615 return TRUE;
616 else if (StrMatch("FALSE", aip->word, aip->wordlen))
617 return FALSE;
618
619 AsnIoErrorMsg(aip, 42, AsnErrGetTypeName(atp->name), aip->linenumber);
620
621 return FALSE; /* just for lint */
622 }
623
624 /*****************************************************************************
625 *
626 * Int4 AsnLexReadString(aip, atp)
627 * expects any String type next
628 * assumes none of it has already been read
629 * does not advance to next token
630 * atp points to the definition of this String
631 * if atp->type->isa == a string type
632 * packs String to single value, if segmented on input
633 * otherwise returns the stringstoreptr itself
634 *
635 *****************************************************************************/
636 static Int2 AsnLexWordEx (AsnIoPtr aip, Uint1 fix_non_print);
637
AsnLexReadStringEx(AsnIoPtr aip,AsnTypePtr atp,Uint1 fix_non_print)638 static Pointer AsnLexReadStringEx (AsnIoPtr aip, AsnTypePtr atp, Uint1 fix_non_print)
639 {
640 Int2 token;
641 ByteStorePtr ssp;
642 CharPtr result=NULL;
643 Int4 bytes;
644
645 token = AsnLexWordEx (aip, fix_non_print); /* read the start */
646 if (token != START_STRING)
647 {
648 AsnIoErrorMsg(aip, 43, AsnErrGetTypeName(atp->name), aip->linenumber);
649 return NULL;
650 }
651
652 ssp = BSNew(0);
653 if (ssp == NULL) return result;
654 token = AsnLexWordEx (aip, fix_non_print); /* read the string(s) */
655 while (token == IN_STRING)
656 {
657 bytes = BSWrite(ssp, aip->word, (Int4)aip->wordlen);
658 if (bytes != (Int4)(aip->wordlen))
659 {
660 BSFree(ssp);
661 return result;
662 }
663 token = AsnLexWordEx (aip, fix_non_print);
664 }
665
666 if (token == ERROR_TOKEN) return NULL;
667
668 if (token != END_STRING)
669 {
670 AsnIoErrorMsg(aip, 44, AsnErrGetTypeName(atp->name), aip->linenumber);
671 return NULL;
672 }
673 if (AsnFindBaseIsa(atp) == STRSTORE_TYPE) /* string store */
674 return ssp;
675
676 result = (CharPtr) BSMerge(ssp, NULL);
677 BSFree(ssp);
678
679 return result;
680 }
681
AsnLexReadString(AsnIoPtr aip,AsnTypePtr atp)682 NLM_EXTERN Pointer AsnLexReadString (AsnIoPtr aip, AsnTypePtr atp)
683
684 {
685 return AsnLexReadStringEx (aip, atp, aip->fix_non_print);
686 }
687
AsnLexReadStringUTF8(AsnIoPtr aip,AsnTypePtr atp)688 static Pointer AsnLexReadStringUTF8 (AsnIoPtr aip, AsnTypePtr atp)
689
690 {
691 return AsnLexReadStringEx (aip, atp, 2);
692 }
693
694 /*****************************************************************************
695 *
696 * void AsnLexSkipString(aip, atp)
697 * expects any String type next
698 * assumes none of it has already been read
699 * does not advance to next token
700 * atp points to the definition of this String
701 * just reads past end of string
702 *
703 *****************************************************************************/
704
AsnLexSkipStringEx(AsnIoPtr aip,AsnTypePtr atp,Uint1 fix_non_print)705 static Boolean AsnLexSkipStringEx (AsnIoPtr aip, AsnTypePtr atp, Uint1 fix_non_print)
706 {
707 Int2 token;
708
709 token = AsnLexWordEx(aip, fix_non_print); /* read the start */
710 if (token != START_STRING)
711 {
712 AsnIoErrorMsg(aip, 43, AsnErrGetTypeName(atp->name), aip->linenumber);
713 return FALSE;
714 }
715
716 token = AsnLexWordEx(aip, fix_non_print); /* read the string(s) */
717 while (token == IN_STRING)
718 token = AsnLexWord(aip);
719
720 if (token == ERROR_TOKEN) return FALSE;
721
722 if (token != END_STRING)
723 AsnIoErrorMsg(aip, 44, AsnErrGetTypeName(atp->name), aip->linenumber);
724
725 return TRUE;
726 }
727
AsnLexSkipString(AsnIoPtr aip,AsnTypePtr atp)728 NLM_EXTERN Boolean AsnLexSkipString (AsnIoPtr aip, AsnTypePtr atp)
729
730 {
731 return AsnLexSkipStringEx (aip, atp, aip->fix_non_print);
732 }
733
AsnLexSkipStringUTF8(AsnIoPtr aip,AsnTypePtr atp)734 static Boolean AsnLexSkipStringUTF8 (AsnIoPtr aip, AsnTypePtr atp)
735
736 {
737 return AsnLexSkipStringEx (aip, atp, 2);
738 }
739
740 /*****************************************************************************
741 *
742 * ByteStorePtr AsnLexReadOctets(aip, atp)
743 * expects Octets type next
744 * assumes none of it has already been read
745 * does not advance to next token
746 * atp points to the definition of this OCTET STRING
747 *
748 *****************************************************************************/
AsnLexReadOctets(AsnIoPtr aip,AsnTypePtr atp)749 NLM_EXTERN ByteStorePtr AsnLexReadOctets (AsnIoPtr aip, AsnTypePtr atp)
750 {
751 Int2 token, len;
752 ByteStorePtr ssp = NULL;
753 Byte tbuf[500]; /* was 101 - changed to handle occasional hand-edited ASN.1? */
754 Int4 bytes, left, added;
755
756 token = AsnLexWord(aip); /* read the start */
757 if (token != START_BITHEX)
758 {
759 AsnIoErrorMsg(aip, 45, AsnErrGetTypeName(atp->name), aip->linenumber);
760 return NULL;
761 }
762 ssp = BSNew(0);
763 if (ssp == NULL) return ssp;
764 token = AsnLexWord(aip); /* read the octet(s) */
765 left = 0;
766 while (token == IN_BITHEX)
767 {
768 len = (Int2)(aip->wordlen + left);
769 MemCopy((tbuf + left), aip->word, (len - left));
770 tbuf[len] = '\0';
771 added = AsnTypeStringToHex(tbuf, len, tbuf, &left);
772 if (added < 0)
773 {
774 AsnIoErrorMsg(aip, 46, AsnErrGetTypeName(atp->name), aip->linenumber);
775 return NULL;
776 }
777 if (added)
778 {
779 bytes = BSWrite(ssp, tbuf, added);
780 if (bytes != added)
781 {
782 ssp = BSFree(ssp);
783 return ssp;
784 }
785 }
786 if (left) /* left a char */
787 {
788 MemCopy(tbuf, ((aip->word)+(aip->wordlen - left)),left);
789 }
790
791 token = AsnLexWord(aip);
792 }
793
794 if (token != OCTETS)
795 {
796 AsnIoErrorMsg(aip, 47, AsnErrGetTypeName(atp->name), aip->linenumber);
797 return NULL;
798 }
799
800 return ssp;
801 }
802
803 /*****************************************************************************
804 *
805 * void AsnLexSkipOctets(aip, atp)
806 * expects Octets type next
807 * assumes none of it has already been read
808 * does not advance to next token
809 * atp points to the definition of this OCTET STRING
810 *
811 *****************************************************************************/
AsnLexSkipOctets(AsnIoPtr aip,AsnTypePtr atp)812 NLM_EXTERN void AsnLexSkipOctets (AsnIoPtr aip, AsnTypePtr atp)
813 {
814 Int2 token, left, len;
815 Int4 line;
816
817 token = AsnLexWord(aip); /* read the start */
818 if (token != START_BITHEX)
819 {
820 AsnIoErrorMsg(aip, 45, AsnErrGetTypeName(atp->name), aip->linenumber);
821 return;
822 }
823
824 line = aip->linenumber;
825 token = AsnLexWord(aip); /* read the octet(s) */
826 left = 0;
827 while (token == IN_BITHEX)
828 {
829 len = aip->wordlen + left;
830 left = len % 2;
831 token = AsnLexWord(aip);
832 }
833
834 if (left)
835 {
836 AsnIoErrorMsg(aip, 48, AsnErrGetTypeName(atp->name), line);
837 return;
838 }
839
840 if (token != OCTETS)
841 AsnIoErrorMsg(aip, 47, AsnErrGetTypeName(atp->name), aip->linenumber);
842
843 return;
844 }
845
846 /*****************************************************************************
847 *
848 * FloatHi AsnLexReadReal(aip, atp)
849 * expects a REAL next
850 * assumes none of it has already been read
851 * does not advance to next token
852 * atp points to the definition of this REAL
853 *
854 *****************************************************************************/
AsnLexReadReal(AsnIoPtr aip,AsnTypePtr atp)855 NLM_EXTERN FloatHi AsnLexReadReal (AsnIoPtr aip, AsnTypePtr atp)
856 {
857 Int2 token;
858 double mantissa, result;
859 int base, exponent;
860 char buf[100];
861
862 result = 0.0;
863 token = AsnLexWord(aip); /* read the { */
864 if (token != START_STRUCT)
865 {
866 AsnIoErrorMsg(aip, 49, AsnErrGetTypeName(atp->name), aip->linenumber);
867 return (FloatHi)result;
868 }
869
870 token = AsnLexWord(aip); /* read mantissa */
871 if (token != NUMBER)
872 {
873 AsnIoErrorMsg(aip, 50, AsnErrGetTypeName(atp->name), aip->linenumber);
874 return (FloatHi)result;
875 }
876 MemCopy(buf, aip->word, (size_t)aip->wordlen);
877 buf[aip->wordlen] = '\0';
878 mantissa = atof(buf);
879
880 token = AsnLexWord(aip); /* read comma */
881 if (token != COMMA)
882 {
883 AsnIoErrorMsg(aip, 51, AsnErrGetTypeName(atp->name), aip->linenumber);
884 return (FloatHi)result;
885 }
886
887 token = AsnLexWord(aip); /* read base */
888 if (token != NUMBER)
889 {
890 AsnIoErrorMsg(aip, 52, AsnErrGetTypeName(atp->name), aip->linenumber);
891 return (FloatHi)result;
892 }
893 MemCopy(buf, aip->word, (size_t)aip->wordlen);
894 buf[aip->wordlen] = '\0';
895 base = atoi(buf);
896 if ((base != 2) && (base != 10))
897 {
898 AsnIoErrorMsg(aip, 53, AsnErrGetTypeName(atp->name), aip->linenumber);
899 return (FloatHi)result;
900 }
901
902 token = AsnLexWord(aip);
903 if (token != COMMA)
904 {
905 AsnIoErrorMsg(aip, 54, AsnErrGetTypeName(atp->name), aip->linenumber);
906 return (FloatHi)result;
907 }
908
909 token = AsnLexWord(aip);
910 if (token != NUMBER)
911 {
912 AsnIoErrorMsg(aip, 55, AsnErrGetTypeName(atp->name), aip->linenumber);
913 return (FloatHi)result;
914 }
915 MemCopy(buf, aip->word, (size_t)aip->wordlen);
916 buf[aip->wordlen] = '\0';
917 exponent = atoi(buf);
918
919 token = AsnLexWord(aip);
920 if (token != END_STRUCT)
921 {
922 AsnIoErrorMsg(aip, 56, AsnErrGetTypeName(atp->name), aip->linenumber);
923 return (FloatHi)result;
924 }
925
926 if (base == 10) /* range checking only on base 10, for doubles */
927 {
928 if (exponent > DBL_MAX_10_EXP) /* exponent too big */
929 return (FloatHi)DBL_MAX;
930 else if (exponent < DBL_MIN_10_EXP) /* exponent too small */
931 return (FloatHi)result;
932 }
933
934 result = mantissa * Nlm_Powi((double)base, exponent);
935
936 return (FloatHi)result;
937 }
938
939 /*****************************************************************************
940 *
941 * void AsnLexReadNull(aip, atp)
942 *
943 *****************************************************************************/
AsnLexReadNull(AsnIoPtr aip,AsnTypePtr atp)944 NLM_EXTERN void AsnLexReadNull (AsnIoPtr aip, AsnTypePtr atp)
945 {
946 AsnLexWord(aip);
947 if (! StrMatch("NULL", aip->word, aip->wordlen))
948 {
949 AsnIoErrorMsg(aip, 57, AsnErrGetTypeName(atp->name), aip->linenumber);
950 return;
951 }
952 return;
953 }
954
955 /*****************************************************************************
956 *
957 * CharPtr AsnLexSaveWord(aip)
958 * create a new null terminated string from
959 * a non null terminated string (word) of length (len)
960 *
961 *****************************************************************************/
AsnLexSaveWord(AsnIoPtr aip)962 NLM_EXTERN CharPtr AsnLexSaveWord (AsnIoPtr aip)
963 {
964 CharPtr ptr;
965
966 ptr = (CharPtr) MemNew((size_t)(aip->wordlen + 1));
967 MemCopy(ptr, aip->word, (size_t)aip->wordlen);
968 return ptr;
969 }
970
971 /*****************************************************************************
972 *
973 * void AsnLexSkipStruct(aip)
974 * skips current structure and all substructures
975 * Does NOT read following element
976 *
977 *****************************************************************************/
AsnLexSkipStruct(AsnIoPtr aip)978 NLM_EXTERN void AsnLexSkipStruct (AsnIoPtr aip)
979 {
980 int type_indent = 1;
981 Int2 token;
982
983 while (type_indent)
984 {
985 token = AsnLexWord(aip);
986 switch (token)
987 {
988 case START_STRUCT: /* another substructure */
989 type_indent++;
990 break;
991 case END_STRUCT: /* a close brace */
992 type_indent--;
993 break;
994 case EOF_TOKEN:
995 AsnIoErrorMsg(aip, 17);
996 return;
997 default:
998 break;
999 }
1000 }
1001
1002 return;
1003 }
1004
1005 /*****************************************************************************
1006 *
1007 * Int4 AsnLexInteger(aip)
1008 *
1009 *****************************************************************************/
AsnLexInteger(AsnIoPtr aip)1010 NLM_EXTERN Int4 AsnLexInteger (AsnIoPtr aip)
1011 {
1012 char tbuf[11];
1013 Int4 value;
1014
1015 MemCopy(tbuf, aip->word, (size_t)aip->wordlen);
1016 tbuf[aip->wordlen] = '\0';
1017 value = atol(tbuf);
1018 return value;
1019 }
1020
1021 /*****************************************************************************
1022 *
1023 * Int8 AsnLexBigInt(aip)
1024 *
1025 *****************************************************************************/
AsnLexBigInt(AsnIoPtr aip)1026 NLM_EXTERN Int8 AsnLexBigInt (AsnIoPtr aip)
1027 {
1028 char tbuf[40];
1029 Int8 value;
1030 const char * result;
1031
1032 MemCopy(tbuf, aip->word, (size_t)aip->wordlen);
1033 tbuf[aip->wordlen] = '\0';
1034 value = Nlm_StringToInt8 (tbuf, &result);
1035 return value;
1036 }
1037
1038 /*****************************************************************************
1039 *
1040 * Int2 AsnLexWord(aip)
1041 * reads words, punctuation
1042 * returns tokens defined in asntypes.h
1043 * does not return ASN reserved words - use AsnLexWord() for that
1044 *
1045 *****************************************************************************/
1046
AsnLexWordEx(AsnIoPtr aip,Uint1 fix_non_print)1047 static Int2 AsnLexWordEx (AsnIoPtr aip, Uint1 fix_non_print)
1048 {
1049 register CharPtr pos;
1050 Int1 state;
1051 Int2 token;
1052 register int linepos, len;
1053 int done;
1054
1055 if (aip->tagsaved) /* had to read ahead */
1056 {
1057 aip->tagsaved = FALSE;
1058 return aip->token;
1059 }
1060
1061 if (! aip->bytes) /* no data loaded */
1062 AsnIoGets(aip);
1063
1064 linepos = aip->linepos;
1065 pos = aip->linebuf + linepos;
1066 state = aip->state;
1067 len = 0;
1068
1069 while (*pos == '\n' || *pos == '\r') /* skip empty lines */
1070 {
1071 pos = AsnIoGets(aip); /* get a line */
1072
1073 if (pos == NULL)
1074 return EOF_TOKEN;
1075 }
1076
1077 if (state == IN_STRING_STATE)
1078 {
1079 aip->word = pos;
1080 if ((* pos == '\"') && (*(pos + 1) != '\"')) /* end of string */
1081 {
1082 token = END_STRING;
1083 pos++;
1084 state = 0; /* reset state */
1085 }
1086 else
1087 {
1088 token = IN_STRING;
1089 while ((* pos != '\"') && (* pos != '\n') && (* pos != '\r'))
1090 {
1091 if ((fix_non_print != 2) && ((*pos < ' ') || (*pos > '~')))
1092 {
1093 done = (int)(*pos);
1094 *pos = '\0';
1095 if ((fix_non_print == 0) || (fix_non_print == 3))
1096 {
1097 AsnIoErrorMsg(aip, 106, done, aip->word);
1098 }
1099 done = 0;
1100 *pos = '#'; /* replace with # */
1101 }
1102 pos++; len++;
1103 }
1104
1105 if ((*pos != '\n') && (*pos != '\r') && (* (pos + 1) == '\"')) /* internal quote */
1106 {
1107 len++; /* include in previous string */
1108 pos += 2; /* point to rest of string */
1109 }
1110 }
1111 }
1112 else if (state == IN_BITHEX_STATE)
1113 {
1114 aip->word = pos;
1115 if (*pos == '\'') /* end of binhex */
1116 {
1117 state = 0; /* set to normal */
1118 pos++; /* move past quote */
1119 while (IS_WHITESP(*pos))
1120 {
1121 if (*pos == '\n' || *pos == '\r') /* skip empty lines */
1122 {
1123 pos = AsnIoGets(aip); /* get a line */
1124
1125 if (pos == NULL)
1126 return EOF_TOKEN;
1127 }
1128 else
1129 pos++;
1130 }
1131 if (* pos == 'H')
1132 token = OCTETS;
1133 else if (* pos == 'B')
1134 token = ASNBITS;
1135 else
1136 {
1137 AsnIoErrorMsg(aip, 58, aip->linenumber);
1138 token = ERROR_TOKEN;
1139 }
1140 pos++; /* move past H or B */
1141 }
1142 else
1143 {
1144 token = IN_BITHEX;
1145 while ((* pos != '\'') && (* pos != '\n') && (* pos != '\r'))
1146 {
1147 pos++; len++;
1148 }
1149 }
1150 }
1151 else /* normal scanning */
1152 {
1153 while ((* pos <= ' ') || ((*pos == '-') && (*(pos+1) == '-'))) /* skip leading white space */
1154 {
1155 if (*pos == '\n' || *pos == '\r')
1156 {
1157 pos = AsnIoGets(aip);
1158
1159 if (pos == NULL)
1160 return EOF_TOKEN;
1161 }
1162 else if ((*pos == '-') && (*(pos+1) == '-')) /* skip comments */
1163 {
1164 pos += 2;
1165 done = 0;
1166 while (! done)
1167 {
1168 if ((*pos == '-') && (*(pos +1) == '-'))
1169 {
1170 pos += 2;
1171 done = 1;
1172 }
1173 else if (*pos == '\n' || *pos == '\r')
1174 done = 1;
1175 else
1176 pos++;
1177 }
1178 }
1179 else
1180 pos++;
1181
1182 }
1183
1184 aip->word = pos;
1185 if (* pos == '\"')
1186 {
1187 token = START_STRING;
1188 state = IN_STRING_STATE;
1189 }
1190 else if (* pos == '\'')
1191 {
1192 token = START_BITHEX;
1193 state = IN_BITHEX_STATE;
1194 }
1195 else if (* pos == ',')
1196 token = COMMA;
1197 else if (* pos == '{')
1198 token = START_STRUCT;
1199 else if (* pos == '}')
1200 token = END_STRUCT;
1201 else if (* pos == '[')
1202 token = START_TAG;
1203 else if (* pos == ']')
1204 token = END_TAG;
1205 else if (* pos == '(')
1206 token = OPEN_PAREN;
1207 else if (* pos == ')')
1208 token = CLOSE_PAREN;
1209 else if (* pos == ';')
1210 token = SEMI_COLON;
1211 else if (* pos == ':')
1212 {
1213 if ((*(pos + 1) == ':') && (*(pos + 2) == '='))
1214 {
1215 token = ISDEF;
1216 pos += 2;
1217 len = 3;
1218 }
1219 else
1220 {
1221 AsnIoErrorMsg(aip, 59, *pos, aip->linenumber);
1222 token = ERROR_TOKEN;
1223 }
1224 }
1225 else if (IS_UPPER(*pos)) /* a reference or keyword */
1226 {
1227 token = REF;
1228 while ((IS_ALPHANUM(*pos)) || (*pos == '-'))
1229 {
1230 pos++; len++;
1231 }
1232 pos--; /* move back for increment at end */
1233 len--;
1234 }
1235 else if (IS_LOWER(*pos)) /* an identifier or valuereference */
1236 {
1237 token = IDENT;
1238 while ((IS_ALPHANUM(*pos)) || (*pos == '-'))
1239 {
1240 pos++; len++;
1241 }
1242 pos--; /* move back for increment at end */
1243 len--;
1244 }
1245 else if ((IS_DIGIT(*pos)) || ((*pos == '-') && (IS_DIGIT(*(pos+1)))))
1246 {
1247 token = NUMBER;
1248 if (*pos == '-')
1249 {
1250 pos++; len++;
1251 }
1252
1253 while (IS_DIGIT(*pos))
1254 {
1255 pos++; len++;
1256 }
1257 pos--; /* move back for increment at end */
1258 len--;
1259 }
1260 else
1261 {
1262 AsnIoErrorMsg(aip, 59, *pos, aip->linenumber);
1263 token = ERROR_TOKEN;
1264 }
1265 len++; pos++; /* move over last symbol */
1266 }
1267
1268 aip->linepos = pos - aip->linebuf;
1269 /******************** check on MSWIN
1270 linepos = 0;
1271 while (pos != linebuf)
1272 {
1273 linepos++;
1274 pos++;
1275 }
1276 aip->linepos = linepos;
1277 **********************/
1278 aip->state = state;
1279 aip->wordlen = len;
1280 aip->token = token;
1281 return token;
1282 }
1283
AsnLexWord(AsnIoPtr aip)1284 NLM_EXTERN Int2 AsnLexWord (AsnIoPtr aip)
1285
1286 {
1287 return AsnLexWordEx (aip, aip->fix_non_print);
1288 }
1289
AsnLexWordUTF8(AsnIoPtr aip)1290 static Int2 AsnLexWordUTF8 (AsnIoPtr aip)
1291
1292 {
1293 return AsnLexWordEx (aip, 2);
1294 }
1295
1296 /*****************************************************************************
1297 *
1298 * Boolean StrMatch(a, b, len)
1299 * returns TRUE if a matches b for EXACTLY len
1300 * and a has a '\0' after that
1301 *
1302 *****************************************************************************/
StrMatch(CharPtr a,CharPtr b,Int2 len)1303 NLM_EXTERN Boolean StrMatch (CharPtr a, CharPtr b, Int2 len)
1304 {
1305 if ((a == NULL) || (b == NULL))
1306 return FALSE;
1307
1308 while (len)
1309 {
1310 if (*a != *b)
1311 return FALSE;
1312 a++; b++; len--;
1313 }
1314 if (*a != '\0')
1315 return FALSE;
1316 return TRUE;
1317 }
1318
1319
1320 /*****************************************************************************
1321 *
1322 * Int2 AsnLexScan(aip, name)
1323 * scans until name ::= to start reading asn.1 past garbage
1324 *
1325 *****************************************************************************/
AsnLexScan(AsnIoPtr aip,CharPtr name)1326 static Int2 AsnLexScan (AsnIoPtr aip, CharPtr name)
1327 {
1328 register CharPtr pos;
1329 Int2 token = 0;
1330 register int linepos, len;
1331 int done;
1332 Boolean started = FALSE, matched_ref = FALSE;
1333
1334 if (aip->type_indent) /* only for start */
1335 return ERROR_TOKEN;
1336
1337 if (! aip->bytes) /* no data loaded */
1338 AsnIoGets(aip);
1339
1340 linepos = aip->linepos;
1341 pos = aip->linebuf + linepos;
1342 len = 0;
1343
1344 while (*pos == '\n' || *pos == '\r') /* skip empty lines */
1345 {
1346 pos = AsnIoGets(aip); /* get a line */
1347
1348 if (pos == NULL)
1349 return EOF_TOKEN;
1350 }
1351
1352 while (! started)
1353 {
1354 while ((* pos <= ' ') || ((*pos == '-') && (*(pos+1) == '-'))) /* skip leading white space */
1355 {
1356 if (*pos == '\n' || *pos == '\r')
1357 {
1358 pos = AsnIoGets(aip);
1359
1360 if (pos == NULL)
1361 return EOF_TOKEN;
1362 }
1363 else if ((*pos == '-') && (*(pos+1) == '-')) /* skip comments */
1364 {
1365 pos += 2;
1366 done = 0;
1367 while (! done)
1368 {
1369 if ((*pos == '-') && (*(pos +1) == '-'))
1370 {
1371 pos += 2;
1372 done = 1;
1373 }
1374 else if (*pos == '\n' || *pos == '\r')
1375 done = 1;
1376 else
1377 pos++;
1378 }
1379 }
1380 else
1381 pos++;
1382
1383 }
1384
1385 aip->word = pos;
1386 len = 0;
1387 if (* pos == ':')
1388 {
1389 if ((*(pos + 1) == ':') && (*(pos + 2) == '='))
1390 {
1391 token = ISDEF;
1392 pos += 2;
1393 len = 3;
1394 if (matched_ref)
1395 started = TRUE;
1396 else
1397 {
1398 AsnIoErrorMsg(aip, 59, *pos, aip->linenumber);
1399 return ERROR_TOKEN;
1400 }
1401 }
1402 else
1403 matched_ref = FALSE;
1404 }
1405 else if (IS_UPPER(*pos)) /* a reference or keyword */
1406 {
1407 token = REF;
1408 while ((IS_ALPHANUM(*pos)) || (*pos == '-'))
1409 {
1410 pos++; len++;
1411 }
1412 pos--; /* move back for increment at end */
1413 aip->wordlen = len;
1414 if (StrMatch(name, aip->word, (Int2)len))
1415 matched_ref = TRUE;
1416 else
1417 matched_ref = FALSE;
1418 }
1419 else
1420 matched_ref = FALSE;
1421 pos++; /* move over last symbol */
1422 }
1423
1424 /* found it , do normal return after ::= */
1425
1426 aip->linepos = pos - aip->linebuf;
1427 aip->wordlen = len;
1428 aip->token = token;
1429 return token;
1430 }
1431
1432
1433