]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/compiler/core/err-chk.c
Security-54.tar.gz
[apple/security.git] / SecuritySNACCRuntime / compiler / core / err-chk.c
1 /*
2 * compiler/core/err_chk.c - Check for semantic errors an ASN.1 module
3 *
4 * The following are checked:
5 *
6 * - Components of CHOICE and SET types must have distinct tags. x
7 *
8 * - CHOICE, ANY, and ANY DEFINED BY types cannot be implicitly tagged. x
9 *
10 * - Type and value names within the same scope must be unique. x
11 *
12 * - Field names in a SET, SEQUENCE or CHOICE must be distinct. If
13 * a CHOICE with no field name is embedded in a SET, SEQUENCE or CHOICE,
14 * then the embedded CHOICE's field names must be distinct from its
15 * parents to avoid ambiguity in value notation. x
16 *
17 * - An APPLICATION tag can only be used once per module. x (done in asn1.yacc)
18 *
19 * - Each value in a named bit (BIT STRINGs) or named number x
20 * (INTEGERs and ENUMERATED) list must be different.
21 *
22 * - Each identifier in a named bit or named number list must be different. x
23 *
24 * - The tags on a series of one or more consecutive OPTIONAL or DEFAULT
25 * SEQUENCE elements and the following element must be distinct. x
26 *
27 * link_types.c does the following three checks
28 * A COMPONENTS OF type in a SET must reference a SET
29 * A COMPONENTS OF type in a SEQUENCE must reference a SEQUENCE
30 * SELECTION types must reference a field of a CHOICE type.
31 *
32 * - gives a warning if an ANY DEFINED BY type appears in a SET or
33 * if and ANY DEFINED BY appears in a SEQUENCE before its identifier.
34 * these cases make decoding difficult.
35 *
36 * ******* following are not done yet - need improved value proc. first*****
37 *
38 * - Each identifier in a BIT STRING value must from that BIT
39 * STRING's named bit list.
40 *
41 * - SET or SEQUENCE values can be empty {} only if the SET or
42 * SEQUENCE type was defined as empty or all of its elements are marked
43 * as OPTIONAL or DEFAULT.
44 *
45 * Mike Sample
46 * 92/07/13
47 *
48 * Copyright (C) 1991, 1992 Michael Sample
49 * and the University of British Columbia
50 *
51 * This program is free software; you can redistribute it and/or modify
52 * it under the terms of the GNU General Public License as published by
53 * the Free Software Foundation; either version 2 of the License, or
54 * (at your option) any later version.
55 *
56 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/compiler/core/err-chk.c,v 1.1 2001/06/20 21:27:56 dmitch Exp $
57 * $Log: err-chk.c,v $
58 * Revision 1.1 2001/06/20 21:27:56 dmitch
59 * Adding missing snacc compiler files.
60 *
61 * Revision 1.1.1.1 1999/03/16 18:06:47 aram
62 * Originals from SMIME Free Library.
63 *
64 * Revision 1.4 1997/09/01 14:19:43 wan
65 * Improved error output in certain cases.
66 *
67 * Revision 1.3 1995/07/25 19:41:25 rj
68 * changed `_' to `-' in file names.
69 *
70 * Revision 1.2 1994/09/01 00:33:02 rj
71 * snacc_config.h removed; err_chk.h includet.
72 *
73 * Revision 1.1 1994/08/28 09:49:05 rj
74 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
75 *
76 */
77
78 #include <ctype.h>
79 #include <stdio.h>
80
81 #include "asn-incl.h"
82 #include "mem.h"
83 #include "asn1module.h"
84 #include "snacc-util.h"
85 #include "tag-util.h"
86 #include "define.h"
87 #include "err-chk.h"
88
89 typedef struct DefinedTag
90 {
91 Tag *tag;
92 struct DefinedTag *next;
93 } DefinedTag;
94
95
96 typedef struct DefinedName
97 {
98 char *name;
99 struct DefinedName *next;
100 } DefinedName;
101
102
103 static NamedType *badNamedType;
104 static DefinedName *fieldNames = NULL;
105
106
107 void ErrChkTypeDef PROTO ((Module *m, TypeDef *td));
108
109 void ErrChkType PROTO ((Module *m, TypeDef *td, Type *parent, NamedType *nt, Type *t));
110
111 void ErrChkElmtTypes PROTO ((Module *m, TypeDef *td, Type *parent, NamedTypeList *e));
112
113 void ErrChkBasicType PROTO ((Module *m, TypeDef *td, Type *parent, NamedType *nt, Type *type));
114
115 void ErrChkValueDef PROTO ((Module *m, ValueDef *vd));
116
117 void ErrChkValue PROTO ((Module *m, ValueDef *vd, Value *v));
118
119 int HasDistinctTags PROTO ((NamedTypeList *elmts));
120
121 int AddFirstTag PROTO ((DefinedObj **definedTags, Type *t));
122
123 void ChkFieldNames PROTO ((Module *m, TypeDef *td, Type *parent, NamedTypeList *elmts));
124
125 void ChkNamedNumbers PROTO ((Module *m, Type *t, NamedNumberList *n));
126
127 void ChkNamedBits PROTO ((Module *m, Type *t, NamedNumberList *n));
128
129 void ChkSeqTags PROTO ((Module *m, TypeDef *td, Type *t));
130
131
132 /* return TRUE if the Tag *t1 and t2 are the same in class and code */
133 int
134 TagObjCmp PARAMS ((t1, t2),
135 void *t1 _AND_
136 void *t2)
137 {
138 return (((Tag*) t1)->tclass == ((Tag*) t2)->tclass) &&
139 (((Tag*) t1)->code == ((Tag*) t2)->code);
140 }
141
142
143 /*
144 * Checks for errors listed above.
145 * sets module status to MOD_ERROR if any errors occured
146 */
147 void
148 ErrChkModule PARAMS ((m),
149 Module *m)
150 {
151 TypeDef *td;
152 ValueDef *vd;
153 DefinedObj *typeNames;
154 DefinedObj *valueNames;
155 ImportModule *impList;
156 ImportElmt *impElmt;
157
158 /*
159 * go through each type in typeList
160 */
161 typeNames = NewObjList();
162 FOR_EACH_LIST_ELMT (td, m->typeDefs)
163 {
164 /* first check for name conflicts */
165 if (ObjIsDefined (typeNames, td->definedName, StrObjCmp))
166 {
167 PrintErrLoc (m->asn1SrcFileName, td->type->lineNo);
168 fprintf (stderr,"ERROR - type \"%s\" is multiply defined.\n", td->definedName);
169 m->status = MOD_ERROR;
170 }
171 else
172 DefineObj (&typeNames, td->definedName);
173
174 /* now check type def internals */
175 ErrChkTypeDef (m, td);
176 }
177
178 /* now check for name conflicts with imported types */
179 FOR_EACH_LIST_ELMT (impList, m->imports)
180 {
181 FOR_EACH_LIST_ELMT (impElmt, impList->importElmts)
182 {
183 if ((!impElmt->privateScope) && (isupper (impElmt->name[0])))
184 {
185 if (ObjIsDefined (typeNames, impElmt->name, StrObjCmp))
186 {
187 PrintErrLoc (m->asn1SrcFileName, impElmt->lineNo);
188 fprintf (stderr,"ERROR - type \"%s\" is multiply defined.\n", impElmt->name);
189 m->status = MOD_ERROR;
190 }
191 else
192 DefineObj (&typeNames, impElmt->name);
193 }
194 }
195 }
196 FreeDefinedObjs (&typeNames);
197
198
199 /*
200 * go through each value for types
201 */
202 valueNames = NewObjList();
203 FOR_EACH_LIST_ELMT (vd, m->valueDefs)
204 {
205 /* check for name conflict */
206 if (ObjIsDefined (valueNames, vd->definedName, StrObjCmp))
207 {
208 PrintErrLoc (m->asn1SrcFileName, vd->value->lineNo);
209 fprintf (stderr,"ERROR - value \"%s\" is multiply defined.\n", vd->definedName);
210 m->status = MOD_ERROR;
211 }
212 else
213 DefineObj (&valueNames, vd->definedName);
214
215 /* check value internal info */
216 ErrChkValueDef (m, vd);
217 }
218 /* now check for name conflicts with imported values */
219 FOR_EACH_LIST_ELMT (impList, m->imports)
220 {
221 FOR_EACH_LIST_ELMT (impElmt, impList->importElmts)
222 {
223 if ((!impElmt->privateScope) && (islower (impElmt->name[0])))
224 {
225 if (ObjIsDefined (valueNames, impElmt->name, StrObjCmp))
226 {
227 PrintErrLoc (m->asn1SrcFileName, impElmt->lineNo);
228 fprintf (stderr,"ERROR - value \"%s\" is multiply defined.\n", vd->definedName);
229 m->status = MOD_ERROR;
230 }
231 else
232 DefineObj (&valueNames, impElmt->name);
233 }
234 }
235 }
236
237
238 FreeDefinedObjs (&valueNames);
239
240 } /* ErrChkModule */
241
242
243
244 void
245 ErrChkTypeDef PARAMS ((m, td),
246 Module *m _AND_
247 TypeDef *td)
248 {
249 if (td == NULL)
250 return;
251
252 ErrChkType (m, td, NULL, NULL, td->type);
253
254 } /* ErrChkTypeDef */
255
256
257
258 void
259 ErrChkType PARAMS ((m, td, parent, nt, t),
260 Module *m _AND_
261 TypeDef *td _AND_
262 Type *parent _AND_
263 NamedType *nt _AND_
264 Type *t)
265 {
266 if (t == NULL)
267 return;
268
269 ErrChkBasicType (m, td, parent, nt, t);
270
271 } /* ErrChkType */
272
273
274
275 void
276 ErrChkElmtTypes PARAMS ((m, td, parent, e),
277 Module *m _AND_
278 TypeDef *td _AND_
279 Type *parent _AND_
280 NamedTypeList *e)
281 {
282 NamedType *nt;
283
284 /*
285 * if starting new type aggregate type,
286 * check that the field names are distinct
287 * (goes 'through' un-named elements that are CHOICEs)
288 */
289 if (td->type == parent)
290 {
291 ChkFieldNames (m, td, parent, e);
292 }
293
294
295 FOR_EACH_LIST_ELMT (nt, e)
296 {
297 ErrChkType (m, td, parent, nt, nt->type);
298 }
299 } /* ErrChkElmtTypes */
300
301
302
303 void
304 ErrChkBasicType PARAMS ((m, td, parent, tnt, type),
305 Module *m _AND_
306 TypeDef *td _AND_
307 Type *parent _AND_
308 NamedType *tnt _AND_
309 Type *type)
310 {
311 int i, numElmtsAdded;
312 NamedType *newElmt;
313 NamedType **newElmtHndl;
314 NamedType *nt;
315 NamedTypeList *elmts;
316 NamedType *origNext;
317 Type *refdType;
318 enum BasicTypeChoiceId refdTypeId;
319 TypeDef *newDef;
320
321 if ((type == NULL) || (type->basicType == NULL))
322 return;
323
324 switch (type->basicType->choiceId)
325 {
326 case BASICTYPE_LOCALTYPEREF:
327 case BASICTYPE_IMPORTTYPEREF:
328 /*
329 * make sure that untagged CHOICE and ANY types
330 * are not implicitly tagged
331 */
332 refdTypeId = ParanoidGetBuiltinType (type);
333 if ((type->implicit) &&
334 ((refdTypeId == BASICTYPE_CHOICE) ||
335 (refdTypeId == BASICTYPE_ANY) ||
336 (refdTypeId == BASICTYPE_ANYDEFINEDBY)) &&
337 (CountTags (type->basicType->a.localTypeRef->link->type) == 0))
338 {
339 m->status = MOD_ERROR;
340 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
341 fprintf (stderr,"ERROR - IMPLICITLY tagged CHOICE, ANY or ANY DEFINED BY type.\n");
342 }
343
344 if ((parent != NULL) &&
345 ((refdTypeId == BASICTYPE_ANY) ||
346 (refdTypeId == BASICTYPE_ANYDEFINEDBY)))
347 {
348
349 /*
350 * give a warning. It is stupid to have an ANY DEFINED
351 * BY type in a SET since they are not ordered and hence
352 * the ANY DEFINED BY type may need to be decoded before
353 * its identifer which is very difficult
354 */
355 if ((refdTypeId == BASICTYPE_ANYDEFINEDBY) &&
356 (parent->basicType->choiceId == BASICTYPE_SET))
357 {
358 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
359 fprintf (stderr,"WARNING - ANY DEFINED BY in a SET needs to be decoded before its identifier. This is not guaranteed since SETs are not ordered. Use a SEQUENCE instead, if possible.\n");
360 }
361
362 /*
363 * give a warning. It is stupid to have an ANY DEFINED
364 * BY type in a SEQUENCE before its identifier.
365 * The ANY DEFINED BY type will need to be decoded before
366 * its identifer which is very difficult.
367 * tnt is the NamedType holding "type"
368 */
369 if ((refdTypeId == BASICTYPE_ANYDEFINEDBY) && (tnt != NULL) &&
370 (parent->basicType->choiceId == BASICTYPE_SEQUENCE) &&
371 (GetAsnListElmtIndex (tnt, parent->basicType->a.sequence) <
372 GetAsnListElmtIndex (type->basicType->a.anyDefinedBy->link, parent->basicType->a.sequence)))
373 {
374 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
375 fprintf (stderr,"WARNING - ANY DEFINED BY in SEQUENCE should appear before its identifier since the identifier must be decoded before the ANY DEFINED BY type.\n");
376 }
377
378
379 if (parent->basicType->choiceId == BASICTYPE_SEQUENCE)
380 nt = LAST_LIST_ELMT (parent->basicType->a.sequence);
381
382 /*
383 * untagged, optional ANYs are strange and will cause faulty
384 * decoding code to be generated unless they are the last
385 * elmt in a SEQUENCE.
386 * (if they are the last elmt it is easy to check
387 * for the presence of the ANY if definite lengths are used)
388 * (must peek ahead for EOC otherwise)
389 */
390 if (!((parent->basicType->choiceId == BASICTYPE_SEQUENCE) &&
391 (type == nt->type)) &&
392 (type->optional) && (CountTags (type) == 0))
393 {
394 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
395 fprintf (stderr,"WARNING - untagged optional ANY encountered, the produced code will be wrong.\n");
396 }
397
398 /*
399 * if parent is SET or CHOICE then ANY or ANY DEFINED BY
400 * should be tagged to help determine its presence
401 *
402 * NOTE: there are also probs with untagged ANYs in SEQs
403 * where the ANY is preceeded by optional elmts
404 * (err msg written in produced code)
405 */
406 if (((parent->basicType->choiceId == BASICTYPE_SET) ||
407 (parent->basicType->choiceId == BASICTYPE_CHOICE)) &&
408 (CountTags == 0))
409 {
410 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
411 fprintf (stderr,"WARNING - untagged ANY in a SET or CHOICE, the produced code will be wrong.\n");
412 }
413 }
414
415 break;
416
417
418 case BASICTYPE_INTEGER:
419 case BASICTYPE_ENUMERATED:
420 ChkNamedNumbers (m, type, type->basicType->a.integer);
421 break;
422
423 case BASICTYPE_BITSTRING:
424 ChkNamedBits (m, type, type->basicType->a.bitString);
425 break;
426
427
428 case BASICTYPE_SEQUENCEOF:
429 case BASICTYPE_SETOF:
430 ErrChkType (m, td, type, NULL, type->basicType->a.setOf);
431 break;
432
433 case BASICTYPE_SEQUENCE:
434 ErrChkElmtTypes (m, td, type, type->basicType->a.sequence);
435
436 /*
437 * check that tags on one or more consecutive optional elmts
438 * and following (if any) non-optional elmt are distinct
439 */
440 ChkSeqTags (m, td, type);
441 break;
442
443
444 case BASICTYPE_CHOICE:
445 /* CHOICE elements must have distinct tags */
446 if (!HasDistinctTags (type->basicType->a.choice))
447 {
448 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
449 fprintf (stderr,"ERROR - tag conflict among ");
450 PrintType (stderr, NULL, badNamedType->type);
451 fprintf (stderr," and the other CHOICE elements.\n");
452 m->status = MOD_ERROR;
453 }
454
455 /*
456 * untagged choices cannot be implicitily tagged
457 * (this would make it impossible/difficult to figure out which
458 * elmt of the choice was present when decoding)
459 */
460 if (((type->tags == NULL) || LIST_EMPTY (type->tags)) &&
461 (type->implicit))
462 {
463 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
464 fprintf (stderr,"ERROR - IMPLICITLy tagged CHOICE type.\n");
465 m->status = MOD_ERROR;
466 }
467
468 /* Check out each of the components */
469 ErrChkElmtTypes (m, td, type, type->basicType->a.choice);
470
471
472 break;
473
474 case BASICTYPE_ANYDEFINEDBY:
475 /* for ANY DEFINED BY make sure id field is int or oid */
476 refdType = GetType (type->basicType->a.anyDefinedBy->link->type);
477 if ((refdType->basicType->choiceId != BASICTYPE_INTEGER) &&
478 (refdType->basicType->choiceId != BASICTYPE_ENUMERATED) &&
479 (refdType->basicType->choiceId != BASICTYPE_OID))
480 {
481 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
482 fprintf (stderr,"ERROR - Field referenced by ANY DEFINED BY type must be of INTEGER or OBJECT IDENTIFIER type.\n");
483 m->status = MOD_ERROR;
484 }
485
486 /* make sure id field is not optional */
487 if (type->basicType->a.anyDefinedBy->link->type->optional)
488 {
489 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
490 fprintf (stderr,"ERROR - Field referenced by ANY DEFINED BY cannot be optional.\n");
491 m->status = MOD_ERROR;
492 }
493
494 /*
495 * give a warning. It is stupid to have an ANY DEFINED
496 * BY type in a SET since they are not ordered and hence
497 * the ANY DEFINED BY type may need to be decoded before
498 * its identifer which is very difficult
499 */
500 if ((parent != NULL) &&
501 (parent->basicType->choiceId == BASICTYPE_SET))
502 {
503 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
504 fprintf (stderr,"WARNING - ANY DEFINED BY in a SET needs to be decoded before its identifier. This is not guaranteed since SETs are not ordered. Use a SEQUENCE instead, if possible.\n");
505 }
506
507 /*
508 * give a warning. It is stupid to have an ANY DEFINED
509 * BY type in a SEQUENCE before its identifier.
510 * The ANY DEFINED BY type will need to be decoded before
511 * its identifer which is very difficult.
512 * tnt is the NamedType holding "type"
513 */
514 if ((parent != NULL) && (tnt != NULL) &&
515 (parent->basicType->choiceId == BASICTYPE_SEQUENCE) &&
516 (GetAsnListElmtIndex (tnt, parent->basicType->a.sequence) <
517 GetAsnListElmtIndex (type->basicType->a.anyDefinedBy->link, parent->basicType->a.sequence)))
518 {
519 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
520 fprintf (stderr,"WARNING - ANY DEFINED BY in SEQUENCE should appear before its identifier since the identifier must be decoded before the ANY DEFINED BY type.\n");
521 }
522
523
524 /* fall through - arrrrrg! */
525
526
527 case BASICTYPE_ANY:
528 /* ANY cannot be implicitily tagged */
529 if (((type->tags == NULL) || LIST_EMPTY (type->tags)) &&
530 (type->implicit))
531 {
532 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
533 fprintf (stderr,"ERROR - IMPLICITLy tagged ANY type.\n");
534 m->status = MOD_ERROR;
535 }
536
537
538 if (parent != NULL)
539 {
540 if (parent->basicType->choiceId == BASICTYPE_SEQUENCE)
541 nt = LAST_LIST_ELMT (parent->basicType->a.sequence);
542
543 /*
544 * untagged, optional ANYs are strange and will cause faulty
545 * decoding code to be generated unless they are the last
546 * elmt in a SEQUENCE
547 */
548 if (!((parent->basicType->choiceId == BASICTYPE_SEQUENCE) &&
549 (type == nt->type)) &&
550 (type->optional) && (CountTags (type) == 0))
551 {
552 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
553 fprintf (stderr,"WARNING - untagged optional ANY encountered, the produced code will be wrong.\n");
554 }
555
556 /*
557 * if parent is SET or CHOICE then ANY or ANY DEFINED BY
558 * should be tagged to help determine its presence
559 *
560 * NOTE: there are also probs with untagged ANYs in SEQs
561 * where the ANY is preceeded by optional elmts
562 * (err msg written in produced code)
563 */
564 if (((parent->basicType->choiceId == BASICTYPE_SET) ||
565 (parent->basicType->choiceId == BASICTYPE_CHOICE)) &&
566 (CountTags (type) == 0))
567 {
568 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
569 fprintf (stderr,"WARNING - untagged ANY in a SET or CHOICE, the produced code will be wrong.\n");
570 }
571 }
572
573
574 break;
575
576
577
578 case BASICTYPE_SET:
579 /* SET elements must have distinct tags */
580 if (!HasDistinctTags (type->basicType->a.set))
581 {
582 PrintErrLoc (m->asn1SrcFileName, type->lineNo);
583 fprintf (stderr,"ERROR - tag conflict among ");
584 PrintType (stderr, NULL, badNamedType->type);
585 fprintf (stderr," and the other SET elements.\n");
586 m->status = MOD_ERROR;
587 }
588
589 /* Check out each of the components */
590 ErrChkElmtTypes (m, td, type, type->basicType->a.set);
591 break;
592
593
594 default:
595 /* the rest do not need checking */
596 break;
597 }
598 } /* ErrChkBasicType */
599
600
601 void
602 ErrChkValueDef PARAMS ((m, vd),
603 Module *m _AND_
604 ValueDef *vd)
605 {
606 ErrChkValue (m, vd, vd->value);
607 }
608
609 void
610 ErrChkValue PARAMS ((m, vd, v),
611 Module *m _AND_
612 ValueDef *vd _AND_
613 Value *v)
614 {
615 }
616
617
618 /*
619 * returns non-zero if the first tags on the elements
620 * are all different. Otherwise 0 is returned
621 *
622 * algorithm: add each tag to a list, adding only if
623 * not already in list. if there, free list
624 * and return FALSE. if finished adding tags
625 * and no duplicates occurred then return TRUE;
626 */
627 int
628 HasDistinctTags PARAMS ((elmts),
629 NamedTypeList *elmts)
630 {
631 DefinedObj *tL;
632 NamedType *e;
633
634 tL = NewObjList();
635 FOR_EACH_LIST_ELMT (e, elmts)
636 {
637 if (!AddFirstTag (&tL, e->type))
638 {
639 FreeDefinedObjs (&tL);
640 badNamedType = e;
641 return FALSE;
642 }
643 }
644 FreeDefinedObjs (&tL);
645 badNamedType = NULL;
646 return TRUE;
647 } /* HasDistinctTags */
648
649
650 /*
651 * puts first tag of the given type into the defined tags list
652 * returns FALSE if the tag was already in the defined tags list.
653 * return TRUE otherwise
654 */
655 int
656 AddFirstTag PARAMS ((definedTags, t),
657 DefinedObj **definedTags _AND_
658 Type *t)
659 {
660 Tag *tag;
661 TagList *tl;
662 Tag *last;
663 int implicitRef;
664 NamedType *e;
665
666 tl = t->tags;
667 if (tl != NULL)
668 AsnListFirst (tl);
669
670 implicitRef = FALSE;
671
672 for (;;)
673 {
674 /*
675 * get first tag from tag list local to this type if any
676 */
677
678 if ((tl != NULL) && (CURR_LIST_NODE (tl) != NULL) &&
679 (CURR_LIST_ELMT (tl) != NULL))
680 {
681 tag = (Tag*) CURR_LIST_ELMT (tl);
682
683 if (ObjIsDefined (*definedTags, tag, TagObjCmp))
684 return FALSE;
685 else
686 {
687 DefineObj (definedTags, tag);
688 return TRUE;
689 }
690 }
691
692 /*
693 * follow tags of referenced types if no tags on this type
694 */
695
696 if ((t->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
697 (t->basicType->choiceId == BASICTYPE_IMPORTTYPEREF))
698 {
699 if (!implicitRef)
700 implicitRef = t->implicit;
701
702
703 if (t->basicType->a.localTypeRef->link == NULL)
704 {
705 /* this should be found in the type link stage */
706 fprintf (stderr,"ERROR - unresolved type ref, cannot get tags for decoding\n");
707 break;
708 }
709 t = t->basicType->a.localTypeRef->link->type;
710 tl = t->tags;
711
712 if (tl != NULL)
713 {
714 AsnListFirst (tl); /* set curr ptr to first node */
715 if ((!LIST_EMPTY (tl)) && implicitRef)
716 {
717 AsnListNext (tl);
718 implicitRef = FALSE;
719 }
720 }
721
722 }
723
724 /*
725 * if untagged choice and no tags found yet
726 */
727 else if ((t->basicType->choiceId == BASICTYPE_CHOICE))
728 {
729 /*
730 * add top level tags from each choice elmt
731 */
732 if (implicitRef)
733 {
734 fprintf (stderr,"ERROR - IMPLICITLY Tagged CHOICE\n");
735 }
736
737
738 FOR_EACH_LIST_ELMT (e, t->basicType->a.choice)
739 {
740 if (!AddFirstTag (definedTags, e->type))
741 return FALSE;
742 }
743
744 return TRUE;
745 }
746
747 else /* could be ANY type - assume correct tagging */
748 return TRUE;
749
750 }
751
752 } /* AddFirstTag */
753
754
755
756
757 /*
758 * Prints Errors if the field names of the elements are
759 * not distinct.
760 * currently an endless recursion problem here
761 * for recursive types involving CHOICEs - Fixed MS
762 */
763 void
764 ChkFieldNamesRec PARAMS ((m, td, parent, elmts, fieldNames, followedTypeRefs),
765 Module *m _AND_
766 TypeDef *td _AND_
767 Type *parent _AND_
768 NamedTypeList *elmts _AND_
769 DefinedObj **fieldNames _AND_
770 DefinedObj **followedTypeRefs)
771 {
772 NamedType *e;
773 Type *definingType;
774
775 FOR_EACH_LIST_ELMT (e, elmts)
776 {
777 definingType = ParanoidGetType (e->type);
778 if (e->fieldName != NULL)
779 {
780 if (ObjIsDefined (*fieldNames, e->fieldName, StrObjCmp))
781 {
782 if (parent->basicType->a.choice == elmts)
783 {
784 PrintErrLoc (m->asn1SrcFileName, e->type->lineNo);
785 fprintf (stderr,"WARNING - field name \"%s\" is used more than once in same value notation scope.\n", e->fieldName);
786 }
787 else
788 {
789 PrintErrLoc (m->asn1SrcFileName, parent->lineNo);
790 fprintf (stderr,"WARNING - field name \"%s\" in embedded CHOICE conflicts with field name in type \"%s\".", e->fieldName, td->definedName);
791 fprintf (stderr," This may lead to ambiguous value notation.\n");
792 }
793 /* m->status = MOD_ERROR; */
794 }
795 else
796 DefineObj (fieldNames, e->fieldName);
797 }
798
799 /*
800 * must include embedded CHOICE's field names
801 * if it has no field name (this case is a reference to
802 * a CHOICE) (fieldName is NULL)
803 */
804 else if (((e->type->basicType->choiceId == BASICTYPE_LOCALTYPEREF) ||
805 (e->type->basicType->choiceId == BASICTYPE_IMPORTTYPEREF)) &&
806 (definingType->basicType->choiceId == BASICTYPE_CHOICE))
807 {
808 /* stop if this is a recursive ref we have already checked */
809 if (!ObjIsDefined (*followedTypeRefs, e->type->basicType->a.localTypeRef->typeName, StrObjCmp))
810 {
811 /* push this type name so we don't go through it again */
812 DefineObj (followedTypeRefs, e->type->basicType->a.localTypeRef->typeName);
813 /* pass in field type not defining type as parent for line no*/
814 ChkFieldNamesRec (m, td, e->type, definingType->basicType->a.choice, fieldNames, followedTypeRefs);
815
816 /* pop this type name since we're done checking it */
817 UndefineObj (followedTypeRefs, e->type->basicType->a.localTypeRef->typeName, StrObjCmp);
818 }
819 }
820
821 /* this is an embedded CHOICE definition (fieldName is NULL) */
822 else if (e->type->basicType->choiceId == BASICTYPE_CHOICE)
823 {
824 ChkFieldNamesRec (m, td, e->type, /* pass in field type for line */
825 definingType->basicType->a.choice, fieldNames, followedTypeRefs);
826 }
827
828 }
829 } /* ChkFieldNamesRec */
830
831
832
833 /*
834 * wrapper for ChkFieldNamesRec
835 * Checks that the field names of an aggregate type (CHOICE/SET/SEQ)
836 * are distinct. Violations are printed to stderr.
837 */
838 void
839 ChkFieldNames PARAMS ((m, td, parent, elmts),
840 Module *m _AND_
841 TypeDef *td _AND_
842 Type *parent _AND_
843 NamedTypeList *elmts)
844 {
845 DefinedObj *fieldNames;
846 DefinedObj *followedTypeRefs;
847
848 fieldNames = NewObjList();
849 followedTypeRefs = NewObjList();
850
851 /*
852 * first define the type itself as followed to prevent
853 * infinintely checking it
854 */
855 DefineObj (&followedTypeRefs, td->definedName);
856
857 ChkFieldNamesRec (m, td, parent, elmts, &fieldNames, &followedTypeRefs);
858
859 FreeDefinedObjs (&fieldNames);
860 FreeDefinedObjs (&followedTypeRefs);
861
862 } /* ChkFieldNames */
863
864
865
866 /*
867 * make sure that the identifiers of the named numbers are unique
868 * among themselves.
869 *
870 * also check that the values of the named numbers are unique
871 * among themselves.
872 */
873 void
874 ChkNamedNumbers PARAMS ((m, t, n),
875 Module *m _AND_
876 Type *t _AND_
877 NamedNumberList *n)
878 {
879 DefinedObj *ids;
880 DefinedObj *nums;
881 ValueDef *nn;
882 Value *baseVal;
883
884
885 if (n == NULL)
886 return;
887
888 ids = NewObjList();
889 nums = NewObjList();
890 FOR_EACH_LIST_ELMT (nn, n)
891 {
892 if (ObjIsDefined (ids, nn->definedName, StrObjCmp))
893 {
894 PrintErrLoc (m->asn1SrcFileName, t->lineNo);
895 fprintf (stderr,"ERROR - named numbers (%s) must have unique identifiers.\n", nn->definedName);
896 }
897 else
898 DefineObj (&ids, nn->definedName);
899
900 baseVal = GetValue (nn->value);
901 if (baseVal->basicValue->choiceId != BASICVALUE_INTEGER)
902 {
903 PrintErrLoc (m->asn1SrcFileName, t->lineNo);
904 fprintf (stderr,"ERROR - value format problem (%s)- named numbers must be integers.\n", nn->definedName);
905 }
906 else if (ObjIsDefined (nums, &baseVal->basicValue->a.integer, IntObjCmp))
907 {
908 PrintErrLoc (m->asn1SrcFileName, t->lineNo);
909 fprintf (stderr,"ERROR - named numbers (%s) must have unique values.\n", nn->definedName);
910 }
911 else
912 DefineObj (&nums, &baseVal->basicValue->a.integer);
913
914 }
915
916 FreeDefinedObjs (&ids);
917 FreeDefinedObjs (&nums);
918
919 } /* ChkNamedNumbers */
920
921
922
923 /*
924 * The same as ChkNamedNumbers except that the elmt values must be
925 * > 0 (needed for BIT STRINGs)
926 */
927 void
928 ChkNamedBits PARAMS ((m, t, n),
929 Module *m _AND_
930 Type *t _AND_
931 NamedNumberList *n)
932 {
933 ValueDef *vd;
934 Value *baseVal;
935
936 ChkNamedNumbers (m, t, n);
937
938 FOR_EACH_LIST_ELMT (vd, n)
939 {
940 baseVal = GetValue (vd->value);
941 if ((baseVal->basicValue->choiceId == BASICVALUE_INTEGER) &&
942 (baseVal->basicValue->a.integer < 0))
943 {
944 PrintErrLoc (m->asn1SrcFileName, t->lineNo);
945 fprintf (stderr,"ERROR - named bits (%s) must have positive values.\n", vd->definedName);
946 }
947 }
948
949 } /* ChkNamedBits */
950
951
952
953 /*
954 * check that tags on one or more consecutive optional elmts
955 * and following (if any) non-optional elmt are distinct
956 */
957 void
958 ChkSeqTags PARAMS ((m, td, t),
959 Module *m _AND_
960 TypeDef *td _AND_
961 Type *t)
962 {
963 DefinedObj *dO;
964 NamedType *e;
965
966 if (t->basicType->choiceId != BASICTYPE_SEQUENCE)
967 return;
968
969 dO = NewObjList();
970 FOR_EACH_LIST_ELMT (e, t->basicType->a.sequence)
971 {
972 /* if optional add tag */
973 if (e->type->optional || (e->type->defaultVal != NULL))
974 {
975 if (!AddFirstTag (&dO, e->type))
976 {
977 PrintErrLoc (m->asn1SrcFileName, e->type->lineNo);
978 fprintf (stderr,"ERROR - one or more consecutive optional SEQUENCE elmements and the the following non-optional elmt (if any) must have distinct tags.\n");
979 m->status = MOD_ERROR;
980 }
981 }
982 else if (dO != NULL) /* first non-opt after opt elmts */
983 {
984 if (!AddFirstTag (&dO, e->type))
985 {
986 PrintErrLoc (m->asn1SrcFileName, e->type->lineNo);
987 fprintf (stderr,"ERROR - one or more consecutive optional SEQUENCE elmements and the the following non-optional elmt (if any) must have distinct tags.\n");
988 m->status = MOD_ERROR;
989 }
990 FreeDefinedObjs (&dO);
991 dO = NewObjList();
992 }
993 }
994 FreeDefinedObjs (&dO);
995
996 } /* ChkSeqTags */