1 /*  asnlext.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:  asnlext.c
27 *
28 * Author:  James Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.10 $
33 *
34 * File Description:
35 *   Routines for parsing ASN.1 module definitions.  Extends asnlex.c
36 *
37 * Modifications:
38 * --------------------------------------------------------------------------
39 * Date     Name        Description of modification
40 * -------  ----------  -----------------------------------------------------
41 * 2/11/91  Ostell      AsnModuleLink - corrected bug linking imported types
42 *                         to other imported types.
43 * 3/4/91   Kans        Stricter typecasting for GNU C and C++
44 * 04-20-93 Schuler     LIBCALL calling convention
45 *
46 * ==========================================================================
47 */
48 
49 /*****************************************************************************
50 *
51 *   asnlext.c
52 *   	routines of type AsnLexT..()
53 *   	Lexxer routines for Asn.1 specifications
54 *
55 *****************************************************************************/
56 
57 #include "asnbuild.h"
58 
59 #define NUMASNWORD 59         /* number of asnwords */
60 
61 static CharPtr asnwords[NUMASNWORD] = {     /* primitives from asn.1 */
62 	"BOOLEAN",				 /*  1 */
63 	"INTEGER",				 /*  2 */
64 	"BIT",					 /*  3 */
65 	"OCTET",				 /*  4 */
66 	"NULL",					 /*  5 */
67 	"OBJECT",				 /*  6 */
68 	"ObjectDescriptor",		 /*  7 */
69 	"EXTERNAL",				 /*  8 */
70 	"REAL",					 /*  9 */
71 	"ENUMERATED",			 /* 10 */
72 	"SEQUENCE",				 /* 11 */
73 	"STRING",				 /* 12 */
74 	"SET",					 /* 13 */
75 	"OF",					 /* 14 */
76 	"CHOICE",                /* 15 */
77 	"ANY",           		/* 16 */
78 	"NumericString",    	/* 17 */
79 	"PrintableString",      /* 18 */
80 	"TeletexString", 		/* 19 */
81 	"UTF8String",           /* 20 */
82 	"IA5String",			/* 21 */
83 	"GraphicString",		/* 22 */
84 	"VisibleString",		/* 23 */
85 	"GeneralString",		/* 24 */
86 	"CharacterString",		/* 25 */
87 	"GeneralizedTime",		/* 26 */
88 	"UTCTime",				/* 27 */
89 	"DEFINITIONS",           /* 28 */
90 	"BEGIN",                 /* 29 */
91 	"END",                   /* 30 */
92 	"APPLICATION",           /* 31 */
93 	"PRIVATE",               /* 32 */
94 	"UNIVERSAL",             /* 33 */
95 	"COMPONENTS",			 /* 34 */
96 	"DEFAULT" ,              /* 35 */
97 	"FALSE",                 /* 36 */
98 	"TRUE",                  /* 37 */
99 	"IMPLICIT",              /* 38 */
100 	"OPTIONAL",              /* 39 */
101 	"EXPORTS",				/* 40 */
102 	"IMPORTS",				/* 41 */
103 	"ABSENT", 				/* 42 */
104 	"BY",					/* 43 */
105 	"COMPONENT",            /* 44 */
106 	"DEFINED",              /* 45 */
107 	"FROM",                 /* 46 */
108 	"INCLUDES",             /* 47 */
109 	"MIN",                  /* 48 */
110 	"MINUS-INFINITY",       /* 49 */
111 	"MAX",                  /* 50 */
112 	"PRESENT",              /* 51 */
113 	"PLUS-INFINITY",        /* 52 */
114 	"SIZE",                 /* 53 */
115 	"TAGS",                 /* 54 */
116 	"WITH",                 /* 55 */
117 	"IDENTIFIER",			 /* 56 */
118 	"StringStore",           /* 57 */      /* NCBI application type */
119 	"$Revision:",            /* 58 */       /* NCBI asn versions */
120 	"BigInt"                 /* 59 */       /* NCBI application type */
121 	};
122 
123 static AsnPrimType asnprimtypes[] = {
124 	{BOOLEAN_TYPE, "BOOLEAN", 0, 1 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
125 	{INTEGER_TYPE, "INTEGER", 0, 2 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
126 	{BITS_TYPE, "BIT STRING", 0, 3 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
127 	{OCTETS_TYPE, "OCTET STRING", 0, 4 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
128 	{NULL_TYPE, "NULL", 0, 5 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
129 	{OBID_TYPE, "OBJECT IDENTIFIER", 0, 6 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
130 	{OBDES_TYPE, "ObjectDescriptor", 0, 7 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
131 	{EXTERNAL_TYPE, "EXTERNAL", 0, 8 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
132 	{REAL_TYPE, "REAL", 0, 9 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
133 	{ENUM_TYPE, "ENUMERATED", 0, 10 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
134 	{SEQ_TYPE, "SEQUENCE", 0, 16 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
135 	{SEQOF_TYPE, "SEQUENCE OF", 0, 16 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
136 	{SET_TYPE, "SET", 0, 17 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
137 	{SETOF_TYPE, "SET OF", 0, 17 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
138 	{CHOICE_TYPE, "CHOICE", 0, -1 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
139 	{ANY_TYPE, "ANY", 0, -1 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
140 	{NUMERICSTRING_TYPE, "NumericString", 0, 18 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
141 	{PRINTABLESTRING_TYPE, "PrintableString", 0, 19 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
142 	{TELETEXSTRING_TYPE, "TeletexString", 0, 20 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
143 	{UTF8STRING_TYPE, "UTF8String", 0, 12 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
144 	{IA5STRING_TYPE, "IA5String", 0, 22 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
145 	{GRAPHICSTRING_TYPE, "GraphicString", 0, 25 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
146 	{VISIBLESTRING_TYPE, "VisibleString", 0, 26 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
147 	{GENERALSTRING_TYPE, "GeneralString", 0, 27 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
148 	{CHARACTERSTRING_TYPE, "CharacterString", 0, 28 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
149 	{GENTIME_TYPE, "GeneralizedTime", 0, 24 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
150 	{UTCTIME_TYPE, "UTCTime", 0, 23 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL}};
151 
152 static AsnPrimType asnapptypes[] = {         /* application wide types */
153 	{STRSTORE_TYPE, "StringStore", 64, 1 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL},
154 	{BIGINT_TYPE, "BigInt", 64, 2 , 0, 0, 0, 0, 0, 0, NULL, NULL,NULL,0,NULL, NULL}
155 	};
156 
157 
158 /*****************************************************************************
159 *
160 *   AsnLoadModules(aip)
161 *   	reads and links several modules
162 *
163 *****************************************************************************/
AsnLoadModules(AsnIoPtr aip)164 NLM_EXTERN AsnModulePtr LIBCALL  AsnLoadModules (AsnIoPtr aip)
165 {
166 	AsnModulePtr amp, nextmod, currentmod = NULL;
167 
168 	amp = NULL;
169 	while ((nextmod = AsnLexTReadModule(aip)) != NULL )
170 	{
171 		if (amp == NULL)
172 			amp = nextmod;
173 		else
174 			currentmod->next = nextmod;
175 		currentmod = nextmod;
176 	}
177 
178 	AsnModuleLink(amp);      /* link up modules where possible */
179 	return amp;
180 }
181 
182 /*****************************************************************************
183 *
184 *   AsnLexTReadModule(aip)
185 *
186 *****************************************************************************/
AsnLexTReadModule(AsnIoPtr aip)187 NLM_EXTERN AsnModulePtr AsnLexTReadModule (AsnIoPtr aip)
188 {
189 	AsnModulePtr amp;
190 	AsnOptionPtr aop;
191 	DataVal dv;
192 
193 					/* get name and look for valid start */
194 
195 	amp = AsnLexTStartModule(aip);
196 	if (amp == NULL)
197 		return amp;
198 
199 	aop = AsnIoOptionGet(aip, OP_TYPEORDER, 0, NULL);
200 	if (aop == NULL)
201 	{
202 		MemSet(&dv, 0, sizeof(DataVal));
203 		aop = AsnIoOptionNew(aip, OP_TYPEORDER, 0, dv, NULL);
204 	}
205 	aop->data.intvalue = 1;  /* start the order counter */
206 
207 			   		/* scan declarations */
208 
209 	while (aip->token != END_TOKEN)     /* END */
210 	{
211 		if (aip->token == REF)        /* its a type assignment */
212 			aip->token = AsnLexTReadTypeAssign(aip, amp);
213 		/**************************** not implemented yet ********
214 		else if (token == IDENT)
215 			aip->token = AsnReadDefinedValue(aip, amp);
216 		**********************************************************/
217 		else
218 		{
219 			AsnIoErrorMsg(aip, 60, aip->linenumber, aip->word);
220 			return NULL;
221 		}
222 	}
223 
224 	amp = AsnCheckModule(amp, aip);
225 
226 	return amp;
227 }
228 
229 /*****************************************************************************
230 *
231 *   Int2 AsnLexTReadTypeAssign(aip, amp)
232 *   	reads a type assignment for one type
233 *       assumes has read name already
234 *   	returns token to following item
235 *       returns 0 on error
236 *
237 *****************************************************************************/
AsnLexTReadTypeAssign(AsnIoPtr aip,AsnModulePtr amp)238 NLM_EXTERN Int2 AsnLexTReadTypeAssign (AsnIoPtr aip, AsnModulePtr amp)
239 {
240 	AsnTypePtr atp;
241 	Int2 token;
242 	AsnOptionPtr aop;
243 
244 							/* store the typereference */
245 
246 	atp = AsnTypeNew(aip, amp);
247 	aop = AsnIoOptionGet(aip, OP_TYPEORDER, 0, NULL);
248 	if (aop != NULL)   /* add ordered display */
249 	{
250 		AsnOptionNew(&(atp->hints), OP_TYPEORDER, 0, aop->data, NULL);
251 		aop->data.intvalue++;
252 	}
253 
254 	if ((token = AsnLexTWord(aip)) != ISDEF)
255 	{
256 		AsnIoErrorMsg(aip, 28, aip->linenumber);
257 		return 0;
258 	}
259 
260 	token = AsnLexTWord(aip);   /* get next element */
261 
262 	token = AsnLexTReadType(aip, amp, atp);
263 
264 	return token;
265 }
266 
AsnLexTAddTypeComment(AsnIoPtr aip,AsnOptionPtr PNTR aopp)267 static void AsnLexTAddTypeComment(AsnIoPtr aip, AsnOptionPtr PNTR aopp)
268 {
269 	AsnOptionPtr aop, aop2;
270 	DataVal dv;
271 
272 	aop = NULL;                 /* check for comments before this type */
273 	aop2 = NULL;
274 	while ((aop = AsnIoOptionGet(aip, OP_COMMENT, 0, aop)) != NULL)
275 	{
276 		dv.ptrvalue = aop->data.ptrvalue;
277 		aop->data.ptrvalue = NULL;
278 		aop2 = AsnOptionNew(aopp, OP_COMMENT, 0, dv, DefAsnOptionFree);
279 	}
280 	if (aop2 != NULL)   /* got some */
281 		AsnIoOptionFree(aip, OP_COMMENT, 0);   /* clear them out */
282 }
283 /*****************************************************************************
284 *
285 *   Int2 AsnLexTReadType(aip, amp, atp)
286 *   	reads a type assignment for one type
287 *       assumes has read name already
288 *       assumes has read next input item after name
289 *   	returns token to following item
290 *       returns 0 on error
291 *
292 *****************************************************************************/
AsnLexTReadType(AsnIoPtr aip,AsnModulePtr amp,AsnTypePtr atp)293 NLM_EXTERN Int2 AsnLexTReadType (AsnIoPtr aip, AsnModulePtr amp, AsnTypePtr atp)
294 {
295 	Int2 isa;
296 	Boolean first;
297 	AsnValxNodePtr avnp, prevavnp;
298 	Int2 token;
299 
300 	token = aip->token;
301 
302 	if (token == COMMENT_TOKEN)
303 	{
304 		AsnLexTAddTypeComment(aip, &(atp->hints));
305 		token = AsnLexTWord(aip);
306 	}
307 
308 	if (token == IMPLICIT_TOKEN)
309 	{
310 		atp->implicit = TRUE;
311 		token = AsnLexTWord(aip);
312 	}
313 
314 	if (token == START_TAG)                      /* TAG */
315 	{
316 		token = AsnLexTWord(aip);
317 		if (ISA_TAGCLASS(token))
318 		{
319 			switch (token)
320 			{
321 				case UNIV_TAG_TOKEN:
322 					atp->tagclass = TAG_UNIVERSAL;
323 					break;
324 				case PRIV_TAG_TOKEN:
325 					atp->tagclass = TAG_PRIVATE;
326 					break;
327 				case AP_TAG_TOKEN:
328 					atp->tagclass = TAG_APPLICATION;
329 					break;
330 			}
331 			token = AsnLexTWord(aip);
332 		}
333 		else
334 			atp->tagclass = TAG_CONTEXT;
335 
336 		if (token == NUMBER)
337 		{
338 			atp->tagnumber = (Int2) AsnLexInteger(aip);
339 			token = AsnLexTWord(aip);
340 			if (token != END_TAG)
341 			{
342 				AsnIoErrorMsg(aip, 61, aip->linenumber);
343 				return 0;
344 			}
345 			else
346 				token = AsnLexTWord(aip);
347 		}
348 		else if (token == IDENT)
349 		{
350 			AsnIoErrorMsg(aip, 62, aip->linenumber);
351 			return 0;
352 		}
353 		else
354 		{
355 			AsnIoErrorMsg(aip, 63, aip->linenumber);
356 			return 0;
357 		}
358 	}
359 
360 	atp->type = AsnGetType(aip, amp);
361 	isa = atp->type->isa;
362 
363 	token = AsnLexTWord(aip);   /* read next token */
364 
365 	AsnLexTAddTypeComment(aip, &(atp->hints));  /* check for stored comments */
366 
367 	if (token == COMMENT_TOKEN)
368 		token = AsnLexTWord(aip);
369 
370  					/*********** SubType Processing *********************/
371 	if (token == OPEN_PAREN)
372 	{
373 		AsnIoErrorMsg(aip, 64, aip->linenumber);
374 		return 0;
375 	}
376 	                 /******************* process various types *********/
377 
378 	if (isa < 400)       /* operate on builtin types */
379 		switch (isa)
380 	{
381 		case INTEGER_TYPE:           /* check for named integers */
382 			if (token != START_STRUCT)
383 				break;
384 		case ENUM_TYPE:
385 			if (token != START_STRUCT)
386 			{
387 				AsnIoErrorMsg(aip, 65, aip->linenumber);
388 				return 0;
389 			}
390 
391 									 /* read named integers */
392 			first = TRUE;
393 			avnp = NULL;
394 			prevavnp = NULL;
395 			token = AsnLexTWord(aip);
396 			if (token == COMMENT_TOKEN)
397 			{
398 			    AsnLexTAddTypeComment(aip, &(atp->hints));  /* check for stored comments */
399 			    token = AsnLexTWord(aip);
400 		        }
401 
402 			while (token != END_STRUCT)
403 			{
404 				avnp = AsnValxNodeNew(avnp, VALUE_ISA_NAMED_INT);
405 
406 				if (! first)
407 				{
408 					if (token != COMMA)
409 					{
410 						AsnIoErrorMsg(aip, 66, aip->linenumber);
411 						return 0;
412 					}
413 					else
414 					{
415 						token = AsnLexTWord(aip);
416 						if (token == COMMENT_TOKEN)
417 						{
418 							AsnLexTAddTypeComment(aip, &(prevavnp->aop));
419 							token = AsnLexTWord(aip);
420 						}
421 					}
422 
423 				}
424 				else
425 				{
426 					first = FALSE;
427 					atp->branch = avnp;
428 				}
429 
430 				if (token != IDENT)
431 				{
432 					AsnIoErrorMsg(aip, 86, aip->linenumber);
433 					return 0;
434 				}
435 				avnp->name = AsnLexSaveWord(aip);
436 				token = AsnLexTWord(aip);
437 				if (token != OPEN_PAREN)
438 				{
439 					AsnIoErrorMsg(aip, 87, aip->linenumber);
440 					return 0;
441 				}
442 				avnp->intvalue = AsnLexReadInteger(aip, atp);
443 				token = AsnLexTWord(aip);
444 				if (token != CLOSE_PAREN)
445 				{
446 					AsnIoErrorMsg(aip, 88, aip->linenumber);
447 					return 0;
448 				}
449 				token = AsnLexTWord(aip);
450 				if (token == COMMENT_TOKEN)
451 					token = AsnLexTWord(aip);
452 
453 				AsnLexTAddTypeComment(aip, &(avnp->aop));  /* check for stored comments */
454 				prevavnp = avnp;
455 			}
456 			token = AsnLexTWord(aip);
457 			if (token == COMMENT_TOKEN)
458 			{
459 				AsnLexTAddTypeComment(aip, &(prevavnp->aop));
460 				token = AsnLexTWord(aip);
461 			}
462 			break;
463 		case SETOF_TYPE:			/* create branch for type */
464 		case SEQOF_TYPE:
465 			atp->branch = AsnElementTypeNew(NULL);   /* get unnamed element for type */
466 			token = AsnLexTReadType(aip, amp, (AsnTypePtr) atp->branch);
467 			break;
468 		case SEQ_TYPE:
469 		case SET_TYPE:
470 			atp->branch = AsnLexTReadElementTypeList(aip, amp, atp);
471 			token = aip->token;
472 			break;
473 		case CHOICE_TYPE:
474 			atp->branch = AsnLexTReadAlternativeTypeList(aip, amp, atp);
475 			token = aip->token;
476 			break;
477 	}
478 	atp->resolved = TRUE;
479 	return token;
480 }
481 
482 /*****************************************************************************
483 *
484 *	AsnTypePtr AsnLexTReadElementTypeList(aip, amp)
485 *   	assumes has read first { already
486 *   	returns token to following element
487 *
488 *****************************************************************************/
AsnLexTReadElementTypeList(AsnIoPtr aip,AsnModulePtr amp,AsnTypePtr parent)489 NLM_EXTERN AsnTypePtr AsnLexTReadElementTypeList (AsnIoPtr aip, AsnModulePtr amp, AsnTypePtr parent)
490 {
491 	Int2 token;
492 	AsnTypePtr atp, atp1, atplast, atp2;
493 	AsnValxNodePtr avnp;
494 
495 	token = aip->token;
496 	atp1 = NULL;
497 	atplast = NULL;
498 
499 	if (token != START_STRUCT)
500 	{
501 		AsnIoErrorMsg(aip, 37, aip->linenumber);
502 		return NULL;
503 	}
504 	token = AsnLexTWord(aip);
505 	if (token == COMMENT_TOKEN)
506 	{
507 		if (parent != NULL)
508 			AsnLexTAddTypeComment(aip, &(parent->hints));
509 		token = AsnLexTWord(aip);
510 	}
511 
512 	while (token != END_STRUCT)
513 	{
514 		if (atp1 != NULL)        /* not the first */
515 		{
516 			if (token != COMMA)
517 			{
518 				AsnIoErrorMsg(aip, 66, aip->linenumber);
519 				return NULL;
520 			}
521 			else
522 			{
523 				token = AsnLexTWord(aip);
524 				if (token == COMMENT_TOKEN)
525 				{
526 					if (atplast != NULL)
527 						AsnLexTAddTypeComment(aip, &(atplast->hints));
528 					token = AsnLexTWord(aip);
529 				}
530 			}
531 		}
532 
533 		if (token == COMPS_TOKEN)        /* COMPONENTS OF */
534 		{
535 			AsnIoErrorMsg(aip, 93, aip->linenumber);
536 			return NULL;
537 		}
538 		else if (token != IDENT)	     /* not named */
539 		{
540 			atp = AsnElementTypeNew(NULL);
541 		}
542 		else					         /* named Type */
543 		{
544 			atp = AsnElementTypeNew(aip);
545 			token = AsnLexTWord(aip);
546 			if (token == COMMENT_TOKEN)
547 			{
548 				AsnLexTAddTypeComment(aip, &(atp->hints));
549 				token = AsnLexTWord(aip);
550 			}
551 		}
552 								/* add to chain */
553 		if (atp1 == NULL)
554 			atp1 = atp;
555 		else
556 			atplast->next = atp;
557 
558 		token = AsnLexTReadType(aip, amp, atp);
559 
560 		if (token == OPTIONAL_TOKEN)         /* OPTIONAL */
561 		{
562 			atp->optional = TRUE;
563 			token = AsnLexTWord(aip);
564 		}
565 		else if (token == DEFAULT_TOKEN)    /* DEFAULT */
566 		{
567 			atp->hasdefault = TRUE;
568 			avnp = AsnValxNodeNew(NULL, VALUE_ISA_BOOL);
569 			atp->defaultvalue = avnp;
570 						/* read the default value */
571 			atp2 = AsnFindBaseType(atp);
572 
573 			if (atp2 == NULL)
574 			{
575 				AsnIoErrorMsg(aip, 95, AsnErrGetTypeName(atp->name), aip->linenumber);
576 				return NULL;
577 			}
578 
579 			switch (atp2->type->isa)
580 			{
581 				case BOOLEAN_TYPE:
582 					avnp->intvalue = (Int4) AsnLexReadBoolean(aip, atp2);
583 					break;
584 				case INTEGER_TYPE:
585 				case ENUM_TYPE:
586 					avnp->valueisa = VALUE_ISA_INT;
587 					avnp->intvalue = AsnLexReadInteger(aip, atp2);
588 					break;
589 				case VISIBLESTRING_TYPE:
590 					avnp->valueisa = VALUE_ISA_PTR;
591 					avnp->name = (CharPtr) AsnLexReadString(aip, atp2);
592 					break;
593 				case REAL_TYPE:
594 					avnp->valueisa = VALUE_ISA_REAL;
595 					avnp->realvalue = AsnLexReadReal(aip, atp2);
596 					break;
597 				default:
598 					AsnIoErrorMsg(aip, 94, AsnErrGetTypeName(atp->name));
599 					return NULL;
600 			}
601 			token = AsnLexTWord(aip);
602 		}
603 		atplast = atp;
604 
605 		AsnLexTAddTypeComment(aip, &(atplast->hints));
606 		if (token == COMMENT_TOKEN)
607 			token = AsnLexTWord(aip);
608 
609 	}
610 	token = AsnLexTWord(aip);   /* read following item */
611 	if (token == COMMENT_TOKEN)
612 	{
613 		if (atplast != NULL)
614 			AsnLexTAddTypeComment(aip, &(atplast->hints));
615 		token = AsnLexTWord(aip);
616 	}
617 	return atp1;
618 }
619 
620 /*****************************************************************************
621 *
622 *	AsnTypePtr AsnLexTReadAlternativeTypeList(aip, amp, parent)
623 *   	assumes has read first { already
624 *   	returns token to following element
625 *
626 *****************************************************************************/
AsnLexTReadAlternativeTypeList(AsnIoPtr aip,AsnModulePtr amp,AsnTypePtr parent)627 NLM_EXTERN AsnTypePtr AsnLexTReadAlternativeTypeList (AsnIoPtr aip, AsnModulePtr amp, AsnTypePtr
628 						      parent)
629 {
630 	Int2 token;
631 	AsnTypePtr atp, atp1, atplast;
632 
633 	token = aip->token;
634 	atp1 = NULL;
635 	atplast = NULL;
636 
637 	if (token != START_STRUCT)
638 	{
639 		AsnIoErrorMsg(aip, 37, aip->linenumber);
640 		return NULL;
641 	}
642 	token = AsnLexTWord(aip);
643 	if (token == COMMENT_TOKEN)
644 	{
645 		if (parent != NULL)
646 			AsnLexTAddTypeComment(aip, &(parent->hints));
647 		token = AsnLexTWord(aip);
648 	}
649 
650 	while (token != END_STRUCT)
651 	{
652 		if (atp1 != NULL)        /* not the first */
653 		{
654 			if (token != COMMA)
655 			{
656 				AsnIoErrorMsg(aip, 66, aip->linenumber);
657 				return NULL;
658 			}
659 			else
660 			{
661 				token = AsnLexTWord(aip);
662 				if (token == COMMENT_TOKEN)
663 				{
664 					if (atplast != NULL)
665 						AsnLexTAddTypeComment(aip, &(atplast->hints));
666 					token = AsnLexTWord(aip);
667 				}
668 			}
669 		}
670 
671 		if (token != IDENT)	     /* not named */
672 		{
673 			atp = AsnElementTypeNew(NULL);
674 		}
675 		else					         /* named Type */
676 		{
677 			atp = AsnElementTypeNew(aip);
678 			token = AsnLexTWord(aip);
679 			if (token == COMMENT_TOKEN)
680 			{
681 				AsnLexTAddTypeComment(aip, &(atp->hints));
682 				token = AsnLexTWord(aip);
683 			}
684 		}
685 								/* add to chain */
686 		if (atp1 == NULL)
687 			atp1 = atp;
688 		else
689 			atplast->next = atp;
690 
691 		token = AsnLexTReadType(aip, amp, atp);
692 		atplast = atp;
693 
694 		AsnLexTAddTypeComment(aip, &(atplast->hints));
695 		if (token == COMMENT_TOKEN)
696 			token = AsnLexTWord(aip);
697 	}
698 	token = AsnLexTWord(aip);   /* read following item */
699 	if (token == COMMENT_TOKEN)
700 	{
701 		if (atplast != NULL)
702 			AsnLexTAddTypeComment(aip, &(atplast->hints));
703 		token = AsnLexTWord(aip);
704 	}
705 	return atp1;
706 }
707 
708 /*****************************************************************************
709 *
710 *   AsnModulePtr AsnLexTStartModule(aip)
711 *   	if $Revision: in comment in first line of file, puts the string
712 *        containing the revision number in amp->filename
713 *       if --$Revision: X.YY
714 *     			stores "YY"
715 *       if --$Revision: X.Y  stores "XY"
716 *   	if --$Revision: X
717 *               stores "X"
718 *
719 *****************************************************************************/
AsnLexTStartModule(AsnIoPtr aip)720 NLM_EXTERN AsnModulePtr AsnLexTStartModule (AsnIoPtr aip)
721 {
722 	Int2 token;
723 	AsnModulePtr amp;
724 	Int2 asntype;
725 	AsnTypePtr atp;
726 	Boolean wasref;
727 	Char buf[10];
728 	CharPtr from, to;
729 	Int2 len;
730 
731 	amp = (AsnModulePtr) MemNew(sizeof(AsnModule));
732 
733 	token = AsnLexTWord(aip);    /* get the module name or $Revision: */
734 
735         while (token == COMMENT_TOKEN)
736         {
737                 token = AsnLexTWord(aip);
738 	}
739 
740 
741 	if (token == REVISION_TOKEN)            /* revision of file */
742 	{
743 		to = buf;
744 		*to = '\0';
745                 len = (Int2)(aip->wordlen);
746 		if (len == 4)     /* x.yy */
747 		{
748 			from = aip->word + 2;
749 			len -= 2;
750 		}
751 		else
752 			from = aip->word;
753 
754 		if (len)
755 		{
756 			if (IS_DIGIT(*from))
757 			{
758 				*to = *from; to++; from++;len--;
759 			}
760 			while ((len) && (! IS_DIGIT(*from)))
761 			{
762 				len--; from++;
763 			}
764 			if ((len) && (IS_DIGIT(*from)))
765 			{
766 				*to = *from; to++;
767 			}
768 			*to = '\0';
769 			amp->filename = StringSave(buf);
770 		}
771 
772 		token = AsnLexTWord(aip);     /* get the module name */
773 
774 		while (token == COMMENT_TOKEN)
775 		{
776 			token = AsnLexTWord(aip);
777 		}
778 	}
779 
780 	if (token != REF)
781 	{
782 		MemFree(amp->filename);
783 		amp = (AsnModulePtr) MemFree(amp);
784 		return amp;
785 	}
786 
787 	if ((asntype = AsnLexTMatchToken(aip)) != 0)     /* any predefined value is wrong */
788 	{
789 		AsnIoErrorMsg(aip, 67, asnwords[asntype -1], aip->linenumber);
790 		return NULL;
791 	}
792 
793 						     /* create a new module */
794 
795 
796 	amp->modulename = AsnLexSaveWord(aip);
797 	amp->lasttype = 400;
798 	amp->lastvalue = 10000;
799 
800 	token = AsnLexTWord(aip);
801 
802         while (token == COMMENT_TOKEN)
803         {
804                 token = AsnLexTWord(aip);
805 	}
806 
807 	if (token == START_STRUCT)       /* it has an object identifier */
808 	{
809 		AsnIoErrorMsg(aip, 68);
810 		    /* skip object identifier */
811 		AsnLexSkipStruct(aip);
812 		token = AsnLexTWord(aip);  /* next token */
813 	}
814 
815         while (token == COMMENT_TOKEN)
816         {
817                 token = AsnLexTWord(aip);
818 	}
819 
820 	if (token != DEF_TOKEN)        /* DEFINITIONS */
821 	{
822 		AsnIoErrorMsg(aip, 69, asnwords[DEF_TOKEN - 401], aip->linenumber);
823 		return NULL;
824 	}
825 	else
826 		token = AsnLexTWord(aip);
827 
828     while (token == COMMENT_TOKEN)
829     {
830         token = AsnLexTWord(aip);
831     }
832     while (token != ISDEF && token != BEGIN_TOKEN && token != ERROR_TOKEN)
833     {
834         token = AsnLexTWord(aip);
835     }
836 	if (token != ISDEF)           /* ::= */
837 	{
838 		AsnIoErrorMsg(aip, 69, "::=", aip->linenumber);
839 		return NULL;
840 	}
841 	else
842 		token = AsnLexTWord(aip);
843 
844         while (token == COMMENT_TOKEN)
845         {
846                 token = AsnLexTWord(aip);
847 	}
848 
849 	if (token != BEGIN_TOKEN)    /* BEGIN */
850 	{
851 		AsnIoErrorMsg(aip, 69, asnwords[BEGIN_TOKEN - 401], aip->linenumber);
852 		return NULL;
853 	}
854 	else
855 		token = AsnLexTWord(aip);
856 
857         while (token == COMMENT_TOKEN)
858         {
859                 token = AsnLexTWord(aip);
860 	}
861 
862 	if (token == EXPORTS_TOKEN)     /* read any EXPORTS */
863 	{
864 		wasref = FALSE;
865 		while ((token = AsnLexTWord(aip)) != SEMI_COLON)
866 		{
867 			if (token == REF)     /* should be REF */
868 			{
869 				if (wasref)
870 				{
871 					AsnIoErrorMsg(aip, 66, aip->linenumber);
872 					return NULL;
873 				}
874 				atp = AsnTypeNew(aip, amp);
875 				atp->exported = TRUE;
876 				wasref = TRUE;
877 			}
878 			else if (token == COMMA)
879 			{
880 				if (! wasref)
881 				{
882 					AsnIoErrorMsg(aip, 70, aip->linenumber);
883 					return NULL;
884 				}
885 			   	wasref = FALSE;
886 			}
887 			else if (token != COMMENT_TOKEN)
888 			{
889 				AsnIoErrorMsg(aip, 59, ' ', aip->linenumber);
890 				return NULL;
891 			}
892 		}
893 						   /* get next after semi-colon */
894 
895 		token = AsnLexTWord(aip);
896 	}
897 
898         while (token == COMMENT_TOKEN)
899         {
900                 token = AsnLexTWord(aip);
901 	}
902 
903 	if (token == IMPORTS_TOKEN)             /* IMPORTS */
904 	{
905 		wasref = FALSE;
906 		token = AsnLexTWord(aip);
907 
908 		while (token != SEMI_COLON)
909 		{
910 			if (token == REF)     /* should be REF */
911 			{
912 				atp = AsnTypeNew(aip, amp);
913 				atp->imported = TRUE;
914 				wasref = TRUE;
915 			}
916 			else if (token == COMMA)
917 			{
918 				if (! wasref)
919 				{
920 					AsnIoErrorMsg(aip, 70, aip->linenumber);
921 					return NULL;
922 				}
923 			   	wasref = FALSE;
924 			}
925 			else if (token == FROM_TOKEN)
926 			{
927 				if (! wasref)
928 				{
929 					AsnIoErrorMsg(aip, 71, aip->linenumber);
930 					return NULL;
931 				}
932 				else								/* read source module */
933 					token = AsnLexTWord(aip);
934 
935 				if (token != REF)
936 				{
937 					AsnIoErrorMsg(aip, 72, aip->linenumber);
938 					return NULL;
939 				}
940 				else
941 				{
942 					atp = amp->types;
943 					while (atp != NULL)
944 					{
945 						if ((atp->imported == TRUE) && (atp->branch == NULL))
946 							atp->branch = AsnLexSaveWord(aip);
947 						atp = atp->next;
948 					}
949 				}
950 				wasref = FALSE;
951 			}
952 			else if (token == START_STRUCT)
953 			{
954 				AsnIoErrorMsg(aip, 73, aip->linenumber);
955 				AsnLexSkipStruct(aip);
956 				token = AsnLexTWord(aip);
957 				wasref = FALSE;
958 			}
959 			else if (token != COMMENT_TOKEN)
960 				AsnIoErrorMsg(aip, 96, aip->linenumber);
961 
962 			token = AsnLexTWord(aip);
963 		}
964 						   /* get next after semi-colon */
965 		token = AsnLexTWord(aip);
966 	}
967 
968         while (token == COMMENT_TOKEN)
969         {
970                 token = AsnLexTWord(aip);
971 	}
972 
973 	if (token == EXPORTS_TOKEN)     /* EXPORTS out of place */
974 		AsnIoErrorMsg(aip, 97, aip->linenumber);
975 
976 	return amp;
977 }
978 
979 
980 /*****************************************************************************
981 *
982 *   Int2 AsnLexTMatchToken(aip)
983 *
984 *****************************************************************************/
AsnLexTMatchToken(AsnIoPtr aip)985 NLM_EXTERN Int2 AsnLexTMatchToken (AsnIoPtr aip)
986 {
987 	CharPtr word;
988 	register int i;
989 	Int2 len;
990 
991 	word = aip->word;
992 	len = aip->wordlen;
993 
994 	for (i = 0; i < NUMASNWORD; i++)
995 	{
996 		if (StrMatch(asnwords[i], word, len))
997 			return i+1;
998 	}
999 	return 0;     /* not found */
1000 }
AsnLexTAddComment(CharPtr cbeg,CharPtr cend,AsnIoPtr aip)1001 static void AsnLexTAddComment(CharPtr cbeg, CharPtr cend, AsnIoPtr aip)
1002 {
1003 	Char tchar;
1004 	CharPtr comment;
1005 	DataVal dv;
1006 
1007 	tchar = *cend;
1008 	*cend = '\0';
1009 	comment = StringSave(cbeg);
1010 	*cend = tchar;
1011 	dv.ptrvalue = comment;
1012 
1013 	AsnIoOptionNew(aip, OP_COMMENT, 0, dv, NULL);
1014 	return;
1015 }
1016 /*****************************************************************************
1017 *
1018 *   Int2 AsnLexTWord(aip)
1019 *   	reads words, punctuation, and asn keywords with 2 parts
1020 *   	returns tokens defined at top
1021 *
1022 *****************************************************************************/
AsnLexTWord(AsnIoPtr aip)1023 NLM_EXTERN Int2 AsnLexTWord (AsnIoPtr aip)
1024 {
1025 	register CharPtr pos;
1026 	register int len;
1027 	Int1 state;
1028 	Int2 token, asntype, linepos;
1029 	int done;
1030 	Boolean first = FALSE, hitnewline = FALSE;
1031 	CharPtr commentptr;
1032 
1033 	if (! aip->bytes)   /* no data loaded */
1034 	{
1035 		hitnewline = TRUE;
1036 		first = TRUE;
1037 		AsnIoGets(aip);
1038 	}
1039 
1040 	linepos = aip->linepos;
1041 	pos = aip->linebuf + linepos;
1042 	state = aip->state;
1043 	len = 0;
1044 	token = -1;
1045 
1046 	while (*pos == '\n' || *pos == '\r')    /* skip empty lines */
1047 	{
1048 		hitnewline = TRUE;
1049 		pos = AsnIoGets(aip);
1050 
1051 		if (pos == NULL)
1052 			return EOF_TOKEN;
1053 	}
1054 
1055 	if (state == IN_STRING_STATE)
1056 	{
1057 		aip->word = pos;
1058 		if (* pos == '\"')    /* end of string */
1059 		{
1060 			token = END_STRING;
1061 			pos++;
1062 			state = 0;        /* reset state */
1063 		}
1064 		else
1065 		{
1066 			token = IN_STRING;
1067 			while ((* pos != '\"') && (* pos != '\n') && (* pos != '\r'))
1068 			{
1069 				pos++; len++;
1070 			}
1071 
1072 			if ((*pos != '\n') && (*pos != '\r') && (* (pos + 1) == '\"')) /* internal quote */
1073 			{
1074 				len++;        /* include in previous string */
1075 				pos += 2;     /* point to rest of string */
1076 			}
1077 		}
1078 	}
1079 	else if (state == IN_BITHEX_STATE)
1080 	{
1081 		aip->word = pos;
1082 		if (*pos == '\'')  			  /* end of binhex */
1083 		{
1084 			state = 0;              /* set to normal */
1085 			pos++;                       /* move past quote */
1086 			while (IS_WHITESP(*pos))
1087 				pos++;
1088 			if (* pos == 'H')
1089 				token = OCTETS;
1090 			else if (* pos == 'B')
1091 				token = ASNBITS;
1092 			else
1093 			{
1094 				AsnIoErrorMsg(aip, 58, aip->linenumber);
1095 				token = ERROR_TOKEN;
1096 			}
1097 		}
1098 		else
1099 		{
1100 			token = IN_BITHEX;
1101 			while ((* pos != '\'') && (* pos != '\n') && (* pos != '\r'))
1102 			{
1103 				pos++; len++;
1104 			}
1105 		}
1106 	}
1107 	else              /* normal scanning */
1108 	{
1109 		done = 0;
1110 		while (! done)
1111 		{
1112 			while (* pos <= ' ')     /* skip leading white space */
1113 			{
1114 				if (*pos == '\n' || *pos == '\r')
1115 				{
1116 					hitnewline = TRUE;
1117 					pos = AsnIoGets(aip);
1118 
1119 					if (pos == NULL)
1120 						return EOF_TOKEN;
1121 				}
1122 				else
1123 					pos++;
1124 			}
1125 			done = 1;
1126 
1127 			while (done && (*pos == '-') && (*(pos+1) == '-'))   /* skip comments */
1128 			{
1129 				pos += 2;
1130 				if (first)   /* could be revision */
1131 				{
1132 				 	first = FALSE;
1133 					if (StrMatch(asnwords[57], pos, 10))  /* $Revision: */
1134 					{
1135 						token = REVISION_TOKEN;
1136 						pos += 10;
1137 						while (IS_WHITESP(*pos))
1138 							pos++;
1139 						aip->word = pos;
1140 						while (IS_DIGIT(*pos))       /* eg. 1.2 */
1141 						{
1142 							len++;
1143 							pos++;
1144 						}
1145 						if (*pos == '.')        /* take after . if present */
1146 						{
1147 							pos++;
1148                                                         len++;
1149 							while (IS_DIGIT(*pos))
1150 							{
1151 								len++;
1152 								pos++;
1153 							}
1154 						}
1155 					}
1156 				}
1157 				commentptr = pos;
1158 
1159 				done = 0;
1160 				while (! done)   /* skip to end of comment */
1161 				{
1162 					if ((*pos == '-') && (*(pos +1) == '-'))
1163 					{
1164 						if (token != REVISION_TOKEN)
1165 						{
1166 							AsnLexTAddComment(commentptr, pos, aip);
1167 							if ((! hitnewline) && (aip->token != COMMENT_TOKEN))
1168 								token = COMMENT_TOKEN;
1169 						}
1170 						pos += 2;
1171 						done = 1;
1172 					}
1173 					else if (*pos == '\n' || *pos == '\r')
1174 					{
1175 						if (token != REVISION_TOKEN)
1176 						{
1177 							AsnLexTAddComment(commentptr, pos, aip);
1178 							if ((! hitnewline) && (aip->token != COMMENT_TOKEN))
1179 								token = COMMENT_TOKEN;
1180 						}
1181 
1182 						done = 1;
1183 					}
1184 					else
1185 						pos++;
1186 				}
1187 
1188 				if ((token == REVISION_TOKEN) || (token == COMMENT_TOKEN))
1189 				{
1190 					aip->linepos = pos - aip->linebuf;
1191 					aip->state = state;
1192 					aip->wordlen = len;
1193 					aip->token = token;
1194 					return token;
1195 				}
1196 
1197 				if (*pos <= ' ')
1198 					done = 0;
1199 				else
1200 					done = 1;
1201 			}
1202 		}
1203 
1204 		aip->word = pos;
1205 		if (* pos == '\"')
1206 		{
1207 			token = START_STRING;
1208 			state = IN_STRING_STATE;
1209 		}
1210 		else if (* pos == '\'')
1211 		{
1212 			token = START_BITHEX;
1213 			state = IN_BITHEX_STATE;
1214 		}
1215 		else if (* pos == ',')
1216 			token = COMMA;
1217 		else if (* pos == '{')
1218 			token = START_STRUCT;
1219 		else if (* pos == '}')
1220 			token = END_STRUCT;
1221 		else if (* pos == '[')
1222 			token = START_TAG;
1223 		else if (* pos == ']')
1224 			token = END_TAG;
1225 		else if (* pos == '(')
1226 			token = OPEN_PAREN;
1227 		else if (* pos == ')')
1228 			token = CLOSE_PAREN;
1229 		else if (* pos == ';')
1230 			token = SEMI_COLON;
1231 		else if (* pos == ':')
1232 		{
1233 			if ((*(pos + 1) == ':') && (*(pos + 2) == '='))
1234 			{
1235 				token = ISDEF;
1236 				pos += 2;
1237 				len = 3;
1238 			}
1239 			else
1240 			{
1241 				AsnIoErrorMsg(aip, 59, *pos, aip->linenumber);
1242 				token = ERROR_TOKEN;
1243 			}
1244 		}
1245 		else if (IS_UPPER(*pos))  /* a reference or keyword */
1246 		{
1247 			token = REF;
1248 			while ((IS_ALPHANUM(*pos)) || (*pos == '-'))
1249 			{
1250 				pos++; len++;
1251 			}
1252 
1253 			aip->wordlen = len;
1254 			asntype = AsnLexTMatchToken(aip);    /* check types */
1255 			if (asntype)          /* did it match ? */
1256 			{
1257 				if ((asntype > 27) && (asntype < 57))   /* not a primitive type */
1258 				{
1259 					token = asntype + 400;   /* make a keyword type */
1260 					if (asntype == COMPS_TOKEN)  /* COMPONENTS OF */
1261 					{
1262 						if ((*(pos + 1) == 'O') &&
1263 							(*(pos + 2) == 'F') &&
1264 							(IS_WHITESP(*(pos+3))))
1265 						{
1266 							pos += 3;    /* move past OF */
1267 							len += 3;
1268 						}
1269 						else
1270 							AsnIoErrorMsg(aip, 89, aip->linenumber);
1271 					}
1272 				}
1273 				else if (asntype == 57)    /* StringStore */
1274 					token = STRSTORE_TYPE;
1275 				else if (asntype == 59)    /* BitInt */
1276 					token = BIGINT_TYPE;
1277 				else
1278 				{
1279 					switch (asntype)
1280 					{
1281 						case 3:				/* BIT */
1282 						case 4:				/* OCTET */
1283 							if (! StrMatch(asnwords[11], (pos+1), 6))
1284 								AsnIoErrorMsg(aip, 90, aip->linenumber);
1285 							pos += 7;       /* move past STRING */
1286 							len += 7;
1287 							break;
1288 						case 11:			/* SEQUENCE */
1289 						case 13:			/* SET */
1290 							if ((*(pos + 1) == 'O') &&
1291 								(*(pos + 2) == 'F'))
1292 							{
1293 								asntype++;   /* SET or SEQ OF */
1294 								pos += 3;
1295 								len += 3;
1296 								if (! IS_WHITESP(*pos))
1297 									AsnIoErrorMsg(aip, 91, aip->linenumber);
1298 							}
1299 							break;
1300 						case 6:				/* OBJECT */
1301 							if ((! StrMatch(asnwords[55], (pos+1), 10)))  /* IDENTIFIER */
1302 								AsnIoErrorMsg(aip, 92, aip->linenumber);
1303 							pos += 11;
1304 							len += 11;
1305 							break;
1306 						default:
1307 							break;
1308 					}
1309 					token = asntype + 300;   /* change to point at type */
1310 				}
1311 			}
1312 			pos--;    /* move back for increment at end */
1313 			len--;
1314 		}
1315 		else if (IS_LOWER(*pos))  /* an identifier or valuereference */
1316 		{
1317 			token = IDENT;
1318 			while ((IS_ALPHANUM(*pos)) || (*pos == '-'))
1319 			{
1320 				pos++; len++;
1321 			}
1322 			pos--;		  /* move back for increment at end */
1323 			len--;
1324 		}
1325 		else if ((IS_DIGIT(*pos)) || ((*pos == '-') && (IS_DIGIT(*(pos+1)))))
1326 		{
1327 			token = NUMBER;
1328 			if (*pos == '-')
1329 			{
1330 				pos++; len++;
1331 			}
1332 
1333 			while (IS_DIGIT(*pos))
1334 			{
1335 				pos++; len++;
1336 			}
1337 			pos--;    /* move back for increment at end */
1338 			len--;
1339 		}
1340 		else
1341 		{
1342 			AsnIoErrorMsg(aip, 59, *pos, aip->linenumber);
1343 			token = ERROR_TOKEN;
1344 		}
1345 		len++; pos++;     /* move over last symbol */
1346 	}
1347 	aip->linepos = pos - aip->linebuf;
1348 	aip->state = state;
1349 	aip->wordlen = len;
1350 	aip->token = token;
1351 	return token;
1352 }
1353 
1354 /*****************************************************************************
1355 *
1356 *   AsnTypePtr AsnGetType(aip, amp)
1357 *   	return pointer to type of last element read
1358 *
1359 *****************************************************************************/
AsnGetType(AsnIoPtr aip,AsnModulePtr amp)1360 NLM_EXTERN AsnTypePtr AsnGetType (AsnIoPtr aip, AsnModulePtr amp)
1361 {
1362 	AsnTypePtr atp;
1363 	AsnPrimTypePtr aptp;
1364 	Int2 wordlen;
1365 	Int2 token;
1366 
1367 	wordlen = aip->wordlen;
1368 	token = aip->token;
1369 
1370 	if (ISA_ASNTYPE(aip->token))     /* a primitive */
1371 	{
1372 		aptp = asnprimtypes;
1373 		while (aptp->isa != token)
1374 			aptp++;
1375 		return (AsnTypePtr)aptp;
1376 	}
1377 	else if (ISA_BASETYPE(aip->token))    /* an application type */
1378 	{
1379 		aptp = asnapptypes;
1380 		while (aptp->isa != token)
1381 			aptp++;
1382 		return (AsnTypePtr)aptp;
1383 	}
1384 
1385 	if (aip->token != REF)        /* not a type */
1386 	{
1387 		AsnIoErrorMsg(aip, 98, aip->word, aip->linenumber);
1388 		return NULL;
1389 	}
1390 
1391 		/**************** not a primitive - do we have it already? *******/
1392 
1393 	atp = amp->types;
1394 	while (atp != NULL)
1395 	{
1396 		if (StrMatch(atp->name, aip->word, wordlen))   /* it matches */
1397 		{
1398 			if (atp->imported == TRUE)   /* reference to imported type */
1399 				atp->resolved = TRUE;
1400 			return atp;
1401 		}
1402 		else
1403 			atp = atp->next;
1404 	}
1405 
1406 		/*************** not defined - add unresolved node *************/
1407 
1408 	atp = AsnTypeNew(aip, amp);
1409 
1410 	return atp;
1411 }
1412 
1413 /*****************************************************************************
1414 *
1415 *   AsnTypePtr AsnTypeNew(aip, amp)
1416 *
1417 *****************************************************************************/
AsnTypeNew(AsnIoPtr aip,AsnModulePtr amp)1418 NLM_EXTERN AsnTypePtr AsnTypeNew (AsnIoPtr aip, AsnModulePtr amp)
1419 {
1420 	AsnTypePtr atp, next;
1421 	Int2 token;
1422 
1423 	next = amp->types;
1424 	atp = amp->types;
1425 
1426 	if ((token = AsnLexTMatchToken(aip)) != 0)    /* it's a reserved word */
1427 		AsnIoErrorMsg(aip, 67, asnwords[token - 1], aip->linenumber);
1428 
1429 	while (next != NULL)
1430 	{
1431 		atp = next;
1432 		next = atp->next;
1433 		if (StrMatch(atp->name, aip->word, aip->wordlen))     /* already used name */
1434 		{
1435 			if (! atp->resolved)     /* needs to be resolved yet, so OK */
1436 				return atp;
1437 			else                     /* already defined */
1438 			{
1439 				AsnIoErrorMsg(aip, 99, AsnErrGetTypeName(atp->name), aip->linenumber);
1440 			}
1441 		}
1442 	}
1443 
1444 	next = (AsnTypePtr) MemNew(sizeof(AsnType));
1445 	next->tagclass = TAG_NONE;    /* default tag class */
1446 	next->name = AsnLexSaveWord(aip);
1447 	amp->lasttype++;       /* increment defined types isa */
1448 	next->isa = amp->lasttype;
1449 
1450 	if (atp == NULL)    /* first one */
1451 		amp->types = next;
1452 	else
1453 		atp->next = next;
1454 
1455 	return next;
1456 }
1457 
1458 /*****************************************************************************
1459 *
1460 *   AsnTypePtr AsnElementTypeNew(aip)
1461 *
1462 *****************************************************************************/
AsnElementTypeNew(AsnIoPtr aip)1463 NLM_EXTERN AsnTypePtr AsnElementTypeNew (AsnIoPtr aip)
1464 {
1465 	AsnTypePtr atp;
1466 
1467 	atp = (AsnTypePtr) MemNew(sizeof(AsnType));
1468 	atp->tagclass = TAG_NONE;    /* default tag class */
1469 	atp->tagnumber = -1;         /* not yet assigned */
1470 	if (aip != NULL)
1471 		atp->name = AsnLexSaveWord(aip);
1472 
1473 	return atp;
1474 }
1475 
1476 /*****************************************************************************
1477 *
1478 *   AsnModulePtr AsnCheckModule(amp, aip)
1479 *
1480 *****************************************************************************/
AsnCheckModule(AsnModulePtr amp,AsnIoPtr aip)1481 NLM_EXTERN AsnModulePtr AsnCheckModule (AsnModulePtr amp, AsnIoPtr aip)
1482 {
1483 	AsnTypePtr atp;
1484 	Boolean ok = TRUE;
1485 
1486 	atp = amp->types;              /* check that everything got resolved */
1487 	while (atp != NULL)
1488 	{
1489 		if (atp->resolved != TRUE)
1490 		{
1491 			if (atp->imported != TRUE)    /* only imported not resolved */
1492 			{
1493 				AsnIoErrorMsg(aip, 100,	AsnErrGetTypeName(atp->name), amp->modulename);
1494 				ok = FALSE;
1495 			}
1496 			else
1497 				AsnIoErrorMsg(aip, 101,	AsnErrGetTypeName(atp->name), amp->modulename);
1498 		}
1499 
1500 		if (atp->imported == TRUE)
1501 		{
1502 			if (atp->branch == NULL)
1503 			{
1504 				AsnIoErrorMsg(aip, 102,	AsnErrGetTypeName(atp->name), amp->modulename);
1505 				ok = FALSE;
1506 			}
1507 		}
1508 
1509 		atp = atp->next;
1510 	}
1511 
1512 	AsnSetTags(amp->types);      /* assign tags */
1513 
1514 	if (ok)
1515 		return amp;
1516 	else
1517 		return NULL;
1518 }
1519 
1520 /*****************************************************************************
1521 *
1522 *   void AsnSetTags(atp)
1523 *   	automatically assign CONTEXT tags to named elements
1524 *       if (tagnumer == -1) then not explicitly assigned in spec
1525 *       if (>= 0)  then tag is assumed already assigned and not reassigned
1526 *
1527 *****************************************************************************/
AsnSetTags(AsnTypePtr atp)1528 NLM_EXTERN void AsnSetTags (AsnTypePtr atp)
1529 {
1530 	int ctr = 0;
1531 	Int2 isa;
1532 	AsnTypePtr orig;
1533 
1534 	if (atp == NULL) return;
1535 	                                           /* find highest set tag */
1536 
1537 	for (orig = atp; atp != NULL; atp = atp->next)
1538 	{
1539 		if (atp->name != NULL)
1540 		{
1541 			if (IS_LOWER(*atp->name))      /* identifier, not Type */
1542 			{
1543 				if ((atp->tagclass == TAG_NONE) ||    /* context tag set? */
1544 					(atp->tagclass == TAG_CONTEXT))
1545 				{
1546 					atp->tagclass = TAG_CONTEXT;
1547 					if (atp->tagnumber > ctr)		  /* set default higher */
1548 						ctr = (int)(atp->tagnumber + 1);
1549 				}
1550 			}
1551 		}
1552 
1553 	}
1554 
1555     atp = orig;
1556 
1557 	while (atp != NULL)
1558 	{
1559 		if (atp->type != NULL)
1560 		{
1561 			isa = atp->type->isa;
1562 			switch (isa)
1563 			{
1564 				case SEQOF_TYPE:
1565 				case SETOF_TYPE:      /* check subtypes */
1566 				case SEQ_TYPE:
1567 				case SET_TYPE:
1568 				case CHOICE_TYPE:
1569 					AsnSetTags((AsnTypePtr) atp->branch);
1570 					break;
1571 				default:
1572 					break;
1573 			}
1574 		}
1575 		if (atp->name != NULL)
1576 		{
1577 			if (IS_LOWER(*atp->name))      /* identifier, not Type */
1578 			{
1579 				if (atp->tagclass == TAG_CONTEXT)    /* assign it */
1580 				{
1581 					if (atp->tagnumber < 0)  /* not assigned */
1582 					{
1583 						atp->tagnumber = ctr;
1584 						ctr++;
1585 					}
1586 				}
1587 			}
1588 		}
1589 		atp = atp->next;
1590 	}
1591 	return;
1592 }
1593 
1594 /*****************************************************************************
1595 *
1596 *   AsnValxNodePtr AsnValxNodeNew(anvp, type)
1597 *
1598 *****************************************************************************/
AsnValxNodeNew(AsnValxNodePtr avnp,Int2 type)1599 NLM_EXTERN AsnValxNodePtr AsnValxNodeNew (AsnValxNodePtr avnp, Int2 type)
1600 {
1601 	AsnValxNodePtr newnode;
1602 
1603 	newnode = (AsnValxNodePtr) MemNew((sizeof(AsnValxNode)));
1604 	newnode->valueisa = type;
1605 	if (avnp != NULL)   /* add to chain */
1606 	{
1607 		while (avnp->next != NULL)
1608 			avnp = avnp->next;
1609 		avnp->next = newnode;
1610 	}
1611 	return newnode;
1612 }
1613 
1614 
1615 
1616 
1617