2 * compiler/core/err_chk.c - Check for semantic errors an ASN.1 module
4 * The following are checked:
6 * - Components of CHOICE and SET types must have distinct tags. x
8 * - CHOICE, ANY, and ANY DEFINED BY types cannot be implicitly tagged. x
10 * - Type and value names within the same scope must be unique. x
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
17 * - An APPLICATION tag can only be used once per module. x (done in asn1.yacc)
19 * - Each value in a named bit (BIT STRINGs) or named number x
20 * (INTEGERs and ENUMERATED) list must be different.
22 * - Each identifier in a named bit or named number list must be different. x
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
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.
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.
36 * ******* following are not done yet - need improved value proc. first*****
38 * - Each identifier in a BIT STRING value must from that BIT
39 * STRING's named bit list.
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.
48 * Copyright (C) 1991, 1992 Michael Sample
49 * and the University of British Columbia
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.
56 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/compiler/core/err-chk.c,v 1.1 2001/06/20 21:27:56 dmitch Exp $
58 * Revision 1.1 2001/06/20 21:27:56 dmitch
59 * Adding missing snacc compiler files.
61 * Revision 1.1.1.1 1999/03/16 18:06:47 aram
62 * Originals from SMIME Free Library.
64 * Revision 1.4 1997/09/01 14:19:43 wan
65 * Improved error output in certain cases.
67 * Revision 1.3 1995/07/25 19:41:25 rj
68 * changed `_' to `-' in file names.
70 * Revision 1.2 1994/09/01 00:33:02 rj
71 * snacc_config.h removed; err_chk.h includet.
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.
83 #include "asn1module.h"
84 #include "snacc-util.h"
89 typedef struct DefinedTag
92 struct DefinedTag
*next
;
96 typedef struct DefinedName
99 struct DefinedName
*next
;
103 static NamedType
*badNamedType
;
104 static DefinedName
*fieldNames
= NULL
;
107 void ErrChkTypeDef
PROTO ((Module
*m
, TypeDef
*td
));
109 void ErrChkType
PROTO ((Module
*m
, TypeDef
*td
, Type
*parent
, NamedType
*nt
, Type
*t
));
111 void ErrChkElmtTypes
PROTO ((Module
*m
, TypeDef
*td
, Type
*parent
, NamedTypeList
*e
));
113 void ErrChkBasicType
PROTO ((Module
*m
, TypeDef
*td
, Type
*parent
, NamedType
*nt
, Type
*type
));
115 void ErrChkValueDef
PROTO ((Module
*m
, ValueDef
*vd
));
117 void ErrChkValue
PROTO ((Module
*m
, ValueDef
*vd
, Value
*v
));
119 int HasDistinctTags
PROTO ((NamedTypeList
*elmts
));
121 int AddFirstTag
PROTO ((DefinedObj
**definedTags
, Type
*t
));
123 void ChkFieldNames
PROTO ((Module
*m
, TypeDef
*td
, Type
*parent
, NamedTypeList
*elmts
));
125 void ChkNamedNumbers
PROTO ((Module
*m
, Type
*t
, NamedNumberList
*n
));
127 void ChkNamedBits
PROTO ((Module
*m
, Type
*t
, NamedNumberList
*n
));
129 void ChkSeqTags
PROTO ((Module
*m
, TypeDef
*td
, Type
*t
));
132 /* return TRUE if the Tag *t1 and t2 are the same in class and code */
134 TagObjCmp
PARAMS ((t1
, t2
),
138 return (((Tag
*) t1
)->tclass
== ((Tag
*) t2
)->tclass
) &&
139 (((Tag
*) t1
)->code
== ((Tag
*) t2
)->code
);
144 * Checks for errors listed above.
145 * sets module status to MOD_ERROR if any errors occured
148 ErrChkModule
PARAMS ((m
),
153 DefinedObj
*typeNames
;
154 DefinedObj
*valueNames
;
155 ImportModule
*impList
;
159 * go through each type in typeList
161 typeNames
= NewObjList();
162 FOR_EACH_LIST_ELMT (td
, m
->typeDefs
)
164 /* first check for name conflicts */
165 if (ObjIsDefined (typeNames
, td
->definedName
, StrObjCmp
))
167 PrintErrLoc (m
->asn1SrcFileName
, td
->type
->lineNo
);
168 fprintf (stderr
,"ERROR - type \"%s\" is multiply defined.\n", td
->definedName
);
169 m
->status
= MOD_ERROR
;
172 DefineObj (&typeNames
, td
->definedName
);
174 /* now check type def internals */
175 ErrChkTypeDef (m
, td
);
178 /* now check for name conflicts with imported types */
179 FOR_EACH_LIST_ELMT (impList
, m
->imports
)
181 FOR_EACH_LIST_ELMT (impElmt
, impList
->importElmts
)
183 if ((!impElmt
->privateScope
) && (isupper (impElmt
->name
[0])))
185 if (ObjIsDefined (typeNames
, impElmt
->name
, StrObjCmp
))
187 PrintErrLoc (m
->asn1SrcFileName
, impElmt
->lineNo
);
188 fprintf (stderr
,"ERROR - type \"%s\" is multiply defined.\n", impElmt
->name
);
189 m
->status
= MOD_ERROR
;
192 DefineObj (&typeNames
, impElmt
->name
);
196 FreeDefinedObjs (&typeNames
);
200 * go through each value for types
202 valueNames
= NewObjList();
203 FOR_EACH_LIST_ELMT (vd
, m
->valueDefs
)
205 /* check for name conflict */
206 if (ObjIsDefined (valueNames
, vd
->definedName
, StrObjCmp
))
208 PrintErrLoc (m
->asn1SrcFileName
, vd
->value
->lineNo
);
209 fprintf (stderr
,"ERROR - value \"%s\" is multiply defined.\n", vd
->definedName
);
210 m
->status
= MOD_ERROR
;
213 DefineObj (&valueNames
, vd
->definedName
);
215 /* check value internal info */
216 ErrChkValueDef (m
, vd
);
218 /* now check for name conflicts with imported values */
219 FOR_EACH_LIST_ELMT (impList
, m
->imports
)
221 FOR_EACH_LIST_ELMT (impElmt
, impList
->importElmts
)
223 if ((!impElmt
->privateScope
) && (islower (impElmt
->name
[0])))
225 if (ObjIsDefined (valueNames
, impElmt
->name
, StrObjCmp
))
227 PrintErrLoc (m
->asn1SrcFileName
, impElmt
->lineNo
);
228 fprintf (stderr
,"ERROR - value \"%s\" is multiply defined.\n", vd
->definedName
);
229 m
->status
= MOD_ERROR
;
232 DefineObj (&valueNames
, impElmt
->name
);
238 FreeDefinedObjs (&valueNames
);
245 ErrChkTypeDef
PARAMS ((m
, td
),
252 ErrChkType (m
, td
, NULL
, NULL
, td
->type
);
254 } /* ErrChkTypeDef */
259 ErrChkType
PARAMS ((m
, td
, parent
, nt
, t
),
269 ErrChkBasicType (m
, td
, parent
, nt
, t
);
276 ErrChkElmtTypes
PARAMS ((m
, td
, parent
, e
),
285 * if starting new type aggregate type,
286 * check that the field names are distinct
287 * (goes 'through' un-named elements that are CHOICEs)
289 if (td
->type
== parent
)
291 ChkFieldNames (m
, td
, parent
, e
);
295 FOR_EACH_LIST_ELMT (nt
, e
)
297 ErrChkType (m
, td
, parent
, nt
, nt
->type
);
299 } /* ErrChkElmtTypes */
304 ErrChkBasicType
PARAMS ((m
, td
, parent
, tnt
, type
),
311 int i
, numElmtsAdded
;
313 NamedType
**newElmtHndl
;
315 NamedTypeList
*elmts
;
318 enum BasicTypeChoiceId refdTypeId
;
321 if ((type
== NULL
) || (type
->basicType
== NULL
))
324 switch (type
->basicType
->choiceId
)
326 case BASICTYPE_LOCALTYPEREF
:
327 case BASICTYPE_IMPORTTYPEREF
:
329 * make sure that untagged CHOICE and ANY types
330 * are not implicitly tagged
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))
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");
344 if ((parent
!= NULL
) &&
345 ((refdTypeId
== BASICTYPE_ANY
) ||
346 (refdTypeId
== BASICTYPE_ANYDEFINEDBY
)))
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
355 if ((refdTypeId
== BASICTYPE_ANYDEFINEDBY
) &&
356 (parent
->basicType
->choiceId
== BASICTYPE_SET
))
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");
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"
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
)))
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");
379 if (parent
->basicType
->choiceId
== BASICTYPE_SEQUENCE
)
380 nt
= LAST_LIST_ELMT (parent
->basicType
->a
.sequence
);
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)
390 if (!((parent
->basicType
->choiceId
== BASICTYPE_SEQUENCE
) &&
391 (type
== nt
->type
)) &&
392 (type
->optional
) && (CountTags (type
) == 0))
394 PrintErrLoc (m
->asn1SrcFileName
, type
->lineNo
);
395 fprintf (stderr
,"WARNING - untagged optional ANY encountered, the produced code will be wrong.\n");
399 * if parent is SET or CHOICE then ANY or ANY DEFINED BY
400 * should be tagged to help determine its presence
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)
406 if (((parent
->basicType
->choiceId
== BASICTYPE_SET
) ||
407 (parent
->basicType
->choiceId
== BASICTYPE_CHOICE
)) &&
410 PrintErrLoc (m
->asn1SrcFileName
, type
->lineNo
);
411 fprintf (stderr
,"WARNING - untagged ANY in a SET or CHOICE, the produced code will be wrong.\n");
418 case BASICTYPE_INTEGER
:
419 case BASICTYPE_ENUMERATED
:
420 ChkNamedNumbers (m
, type
, type
->basicType
->a
.integer
);
423 case BASICTYPE_BITSTRING
:
424 ChkNamedBits (m
, type
, type
->basicType
->a
.bitString
);
428 case BASICTYPE_SEQUENCEOF
:
429 case BASICTYPE_SETOF
:
430 ErrChkType (m
, td
, type
, NULL
, type
->basicType
->a
.setOf
);
433 case BASICTYPE_SEQUENCE
:
434 ErrChkElmtTypes (m
, td
, type
, type
->basicType
->a
.sequence
);
437 * check that tags on one or more consecutive optional elmts
438 * and following (if any) non-optional elmt are distinct
440 ChkSeqTags (m
, td
, type
);
444 case BASICTYPE_CHOICE
:
445 /* CHOICE elements must have distinct tags */
446 if (!HasDistinctTags (type
->basicType
->a
.choice
))
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
;
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)
460 if (((type
->tags
== NULL
) || LIST_EMPTY (type
->tags
)) &&
463 PrintErrLoc (m
->asn1SrcFileName
, type
->lineNo
);
464 fprintf (stderr
,"ERROR - IMPLICITLy tagged CHOICE type.\n");
465 m
->status
= MOD_ERROR
;
468 /* Check out each of the components */
469 ErrChkElmtTypes (m
, td
, type
, type
->basicType
->a
.choice
);
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
))
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
;
486 /* make sure id field is not optional */
487 if (type
->basicType
->a
.anyDefinedBy
->link
->type
->optional
)
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
;
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
500 if ((parent
!= NULL
) &&
501 (parent
->basicType
->choiceId
== BASICTYPE_SET
))
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");
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"
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
)))
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");
524 /* fall through - arrrrrg! */
528 /* ANY cannot be implicitily tagged */
529 if (((type
->tags
== NULL
) || LIST_EMPTY (type
->tags
)) &&
532 PrintErrLoc (m
->asn1SrcFileName
, type
->lineNo
);
533 fprintf (stderr
,"ERROR - IMPLICITLy tagged ANY type.\n");
534 m
->status
= MOD_ERROR
;
540 if (parent
->basicType
->choiceId
== BASICTYPE_SEQUENCE
)
541 nt
= LAST_LIST_ELMT (parent
->basicType
->a
.sequence
);
544 * untagged, optional ANYs are strange and will cause faulty
545 * decoding code to be generated unless they are the last
548 if (!((parent
->basicType
->choiceId
== BASICTYPE_SEQUENCE
) &&
549 (type
== nt
->type
)) &&
550 (type
->optional
) && (CountTags (type
) == 0))
552 PrintErrLoc (m
->asn1SrcFileName
, type
->lineNo
);
553 fprintf (stderr
,"WARNING - untagged optional ANY encountered, the produced code will be wrong.\n");
557 * if parent is SET or CHOICE then ANY or ANY DEFINED BY
558 * should be tagged to help determine its presence
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)
564 if (((parent
->basicType
->choiceId
== BASICTYPE_SET
) ||
565 (parent
->basicType
->choiceId
== BASICTYPE_CHOICE
)) &&
566 (CountTags (type
) == 0))
568 PrintErrLoc (m
->asn1SrcFileName
, type
->lineNo
);
569 fprintf (stderr
,"WARNING - untagged ANY in a SET or CHOICE, the produced code will be wrong.\n");
579 /* SET elements must have distinct tags */
580 if (!HasDistinctTags (type
->basicType
->a
.set
))
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
;
589 /* Check out each of the components */
590 ErrChkElmtTypes (m
, td
, type
, type
->basicType
->a
.set
);
595 /* the rest do not need checking */
598 } /* ErrChkBasicType */
602 ErrChkValueDef
PARAMS ((m
, vd
),
606 ErrChkValue (m
, vd
, vd
->value
);
610 ErrChkValue
PARAMS ((m
, vd
, v
),
619 * returns non-zero if the first tags on the elements
620 * are all different. Otherwise 0 is returned
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;
628 HasDistinctTags
PARAMS ((elmts
),
629 NamedTypeList
*elmts
)
635 FOR_EACH_LIST_ELMT (e
, elmts
)
637 if (!AddFirstTag (&tL
, e
->type
))
639 FreeDefinedObjs (&tL
);
644 FreeDefinedObjs (&tL
);
647 } /* HasDistinctTags */
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
656 AddFirstTag
PARAMS ((definedTags
, t
),
657 DefinedObj
**definedTags _AND_
675 * get first tag from tag list local to this type if any
678 if ((tl
!= NULL
) && (CURR_LIST_NODE (tl
) != NULL
) &&
679 (CURR_LIST_ELMT (tl
) != NULL
))
681 tag
= (Tag
*) CURR_LIST_ELMT (tl
);
683 if (ObjIsDefined (*definedTags
, tag
, TagObjCmp
))
687 DefineObj (definedTags
, tag
);
693 * follow tags of referenced types if no tags on this type
696 if ((t
->basicType
->choiceId
== BASICTYPE_LOCALTYPEREF
) ||
697 (t
->basicType
->choiceId
== BASICTYPE_IMPORTTYPEREF
))
700 implicitRef
= t
->implicit
;
703 if (t
->basicType
->a
.localTypeRef
->link
== NULL
)
705 /* this should be found in the type link stage */
706 fprintf (stderr
,"ERROR - unresolved type ref, cannot get tags for decoding\n");
709 t
= t
->basicType
->a
.localTypeRef
->link
->type
;
714 AsnListFirst (tl
); /* set curr ptr to first node */
715 if ((!LIST_EMPTY (tl
)) && implicitRef
)
725 * if untagged choice and no tags found yet
727 else if ((t
->basicType
->choiceId
== BASICTYPE_CHOICE
))
730 * add top level tags from each choice elmt
734 fprintf (stderr
,"ERROR - IMPLICITLY Tagged CHOICE\n");
738 FOR_EACH_LIST_ELMT (e
, t
->basicType
->a
.choice
)
740 if (!AddFirstTag (definedTags
, e
->type
))
747 else /* could be ANY type - assume correct tagging */
758 * Prints Errors if the field names of the elements are
760 * currently an endless recursion problem here
761 * for recursive types involving CHOICEs - Fixed MS
764 ChkFieldNamesRec
PARAMS ((m
, td
, parent
, elmts
, fieldNames
, followedTypeRefs
),
768 NamedTypeList
*elmts _AND_
769 DefinedObj
**fieldNames _AND_
770 DefinedObj
**followedTypeRefs
)
775 FOR_EACH_LIST_ELMT (e
, elmts
)
777 definingType
= ParanoidGetType (e
->type
);
778 if (e
->fieldName
!= NULL
)
780 if (ObjIsDefined (*fieldNames
, e
->fieldName
, StrObjCmp
))
782 if (parent
->basicType
->a
.choice
== elmts
)
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
);
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");
793 /* m->status = MOD_ERROR; */
796 DefineObj (fieldNames
, e
->fieldName
);
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)
804 else if (((e
->type
->basicType
->choiceId
== BASICTYPE_LOCALTYPEREF
) ||
805 (e
->type
->basicType
->choiceId
== BASICTYPE_IMPORTTYPEREF
)) &&
806 (definingType
->basicType
->choiceId
== BASICTYPE_CHOICE
))
808 /* stop if this is a recursive ref we have already checked */
809 if (!ObjIsDefined (*followedTypeRefs
, e
->type
->basicType
->a
.localTypeRef
->typeName
, StrObjCmp
))
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
);
816 /* pop this type name since we're done checking it */
817 UndefineObj (followedTypeRefs
, e
->type
->basicType
->a
.localTypeRef
->typeName
, StrObjCmp
);
821 /* this is an embedded CHOICE definition (fieldName is NULL) */
822 else if (e
->type
->basicType
->choiceId
== BASICTYPE_CHOICE
)
824 ChkFieldNamesRec (m
, td
, e
->type
, /* pass in field type for line */
825 definingType
->basicType
->a
.choice
, fieldNames
, followedTypeRefs
);
829 } /* ChkFieldNamesRec */
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.
839 ChkFieldNames
PARAMS ((m
, td
, parent
, elmts
),
843 NamedTypeList
*elmts
)
845 DefinedObj
*fieldNames
;
846 DefinedObj
*followedTypeRefs
;
848 fieldNames
= NewObjList();
849 followedTypeRefs
= NewObjList();
852 * first define the type itself as followed to prevent
853 * infinintely checking it
855 DefineObj (&followedTypeRefs
, td
->definedName
);
857 ChkFieldNamesRec (m
, td
, parent
, elmts
, &fieldNames
, &followedTypeRefs
);
859 FreeDefinedObjs (&fieldNames
);
860 FreeDefinedObjs (&followedTypeRefs
);
862 } /* ChkFieldNames */
867 * make sure that the identifiers of the named numbers are unique
870 * also check that the values of the named numbers are unique
874 ChkNamedNumbers
PARAMS ((m
, t
, n
),
890 FOR_EACH_LIST_ELMT (nn
, n
)
892 if (ObjIsDefined (ids
, nn
->definedName
, StrObjCmp
))
894 PrintErrLoc (m
->asn1SrcFileName
, t
->lineNo
);
895 fprintf (stderr
,"ERROR - named numbers (%s) must have unique identifiers.\n", nn
->definedName
);
898 DefineObj (&ids
, nn
->definedName
);
900 baseVal
= GetValue (nn
->value
);
901 if (baseVal
->basicValue
->choiceId
!= BASICVALUE_INTEGER
)
903 PrintErrLoc (m
->asn1SrcFileName
, t
->lineNo
);
904 fprintf (stderr
,"ERROR - value format problem (%s)- named numbers must be integers.\n", nn
->definedName
);
906 else if (ObjIsDefined (nums
, &baseVal
->basicValue
->a
.integer
, IntObjCmp
))
908 PrintErrLoc (m
->asn1SrcFileName
, t
->lineNo
);
909 fprintf (stderr
,"ERROR - named numbers (%s) must have unique values.\n", nn
->definedName
);
912 DefineObj (&nums
, &baseVal
->basicValue
->a
.integer
);
916 FreeDefinedObjs (&ids
);
917 FreeDefinedObjs (&nums
);
919 } /* ChkNamedNumbers */
924 * The same as ChkNamedNumbers except that the elmt values must be
925 * > 0 (needed for BIT STRINGs)
928 ChkNamedBits
PARAMS ((m
, t
, n
),
936 ChkNamedNumbers (m
, t
, n
);
938 FOR_EACH_LIST_ELMT (vd
, n
)
940 baseVal
= GetValue (vd
->value
);
941 if ((baseVal
->basicValue
->choiceId
== BASICVALUE_INTEGER
) &&
942 (baseVal
->basicValue
->a
.integer
< 0))
944 PrintErrLoc (m
->asn1SrcFileName
, t
->lineNo
);
945 fprintf (stderr
,"ERROR - named bits (%s) must have positive values.\n", vd
->definedName
);
954 * check that tags on one or more consecutive optional elmts
955 * and following (if any) non-optional elmt are distinct
958 ChkSeqTags
PARAMS ((m
, td
, t
),
966 if (t
->basicType
->choiceId
!= BASICTYPE_SEQUENCE
)
970 FOR_EACH_LIST_ELMT (e
, t
->basicType
->a
.sequence
)
972 /* if optional add tag */
973 if (e
->type
->optional
|| (e
->type
->defaultVal
!= NULL
))
975 if (!AddFirstTag (&dO
, e
->type
))
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
;
982 else if (dO
!= NULL
) /* first non-opt after opt elmts */
984 if (!AddFirstTag (&dO
, e
->type
))
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
;
990 FreeDefinedObjs (&dO
);
994 FreeDefinedObjs (&dO
);