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