]> git.saurik.com Git - apple/security.git/blob - SecuritySNACCRuntime/compiler/core/recursive.c
Security-54.1.tar.gz
[apple/security.git] / SecuritySNACCRuntime / compiler / core / recursive.c
1 /*
2 * compiler/core/recursive.c - finds and marks the recursive types in a module.
3 *
4 * ALSO:
5 * prints msgs for infinitely recursive types (ie recursive component
6 * is not OPTIONAL, nor a CHOICE elmt, nor a SET OF nor a SEQ OF elmt.
7 * (OPTIONALs can be left out, CHOICE elements have alternatives (hopefully),
8 * and SET OF and SEQUENCE OF values can have zero elements)
9 *
10 * prints msg for recursive types that hold no real information
11 * Foo ::= SET OF Foo (sets of sets of .... of empty sets)
12 *
13 * finds bogus recursive types (hold no info) (same as above)
14 * A ::= B
15 * B ::= C
16 * D ::= A
17 *
18 * MS 92
19 *
20 * Copyright (C) 1991, 1992 Michael Sample
21 * and the University of British Columbia
22 *
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2 of the License, or
26 * (at your option) any later version.
27 *
28 * $Header: /cvs/Darwin/Security/SecuritySNACCRuntime/compiler/core/recursive.c,v 1.1 2001/06/20 21:27:58 dmitch Exp $
29 * $Log: recursive.c,v $
30 * Revision 1.1 2001/06/20 21:27:58 dmitch
31 * Adding missing snacc compiler files.
32 *
33 * Revision 1.1.1.1 1999/03/16 18:06:52 aram
34 * Originals from SMIME Free Library.
35 *
36 * Revision 1.3 1995/07/25 19:41:43 rj
37 * changed `_' to `-' in file names.
38 *
39 * Revision 1.2 1994/09/01 00:43:10 rj
40 * snacc_config.h removed; recursive.h includet.
41 *
42 * Revision 1.1 1994/08/28 09:49:35 rj
43 * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog.
44 *
45 */
46
47 #include <stdio.h>
48
49 #include "asn-incl.h"
50 #include "asn1module.h"
51 #include "recursive.h"
52 #include "snacc-util.h"
53
54 void MkRecTypeDef PROTO ((Module *m, TypeDef *td));
55
56 void MkRecType PROTO ((Module *m, TypeDef *td,Type *t, int optional, int empty));
57
58
59 void
60 MarkRecursiveTypes PARAMS ((m),
61 Module *m)
62 {
63 TypeDef *td;
64
65 /* first set all typedef as un-visited */
66 FOR_EACH_LIST_ELMT (td, m->typeDefs)
67 {
68 td->visited = FALSE;
69 td->tmpRefCount = 0;
70 }
71
72 FOR_EACH_LIST_ELMT (td, m->typeDefs)
73 {
74 MkRecTypeDef (m, td);
75 }
76 } /* MarkRecursiveTypes */
77
78
79
80 void
81 MkRecTypeDef PARAMS ((m, td),
82 Module *m _AND_
83 TypeDef *td)
84 {
85 MkRecType (m, td, td->type, 0, 1);
86 } /* MkRecTypeDef */
87
88
89
90 /*
91 * cruise through aggregate types and type refs looking for
92 * a type ref to the original type def, td. If is a ref to
93 * the td, then mark the td as recusive.
94 *
95 * the optional flag is set if the current type branch is
96 * optional via an OPTIONAL SET/SEQ elmt, CHOICE elmt, SET OF elmt
97 * or SEQ OF elmt.
98 *
99 * the empty flag is initially TRUE and remains true until a
100 * non-type reference type is encountered
101 */
102 void
103 MkRecType PARAMS ((m, td, t, optional, empty),
104 Module *m _AND_
105 TypeDef *td _AND_
106 Type *t _AND_
107 int optional _AND_
108 int empty)
109 {
110 int newOptional;
111 NamedType *e;
112
113 switch (t->basicType->choiceId)
114 {
115 case BASICTYPE_CHOICE:
116 if (AsnListCount (t->basicType->a.choice) > 1)
117 {
118 empty = 0;
119 optional = 1;
120 }
121 FOR_EACH_LIST_ELMT (e, t->basicType->a.choice)
122 {
123 MkRecType (m, td, e->type, optional, empty);
124 }
125 break;
126
127 case BASICTYPE_SET:
128 case BASICTYPE_SEQUENCE:
129 empty = 0;
130
131 FOR_EACH_LIST_ELMT (e, t->basicType->a.set)
132 {
133 newOptional = optional || (e->type->optional) ||
134 (e->type->defaultVal != NULL);
135 MkRecType (m, td, e->type, newOptional, empty);
136 }
137 break;
138
139 case BASICTYPE_SETOF:
140 case BASICTYPE_SEQUENCEOF:
141 empty = 0; /* since an empty set is actual data */
142 optional = 1; /* since SET OF and SEQ OF's can be empty */
143 MkRecType (m, td, t->basicType->a.setOf, optional, empty);
144 break;
145
146 case BASICTYPE_LOCALTYPEREF:
147 case BASICTYPE_IMPORTTYPEREF:
148
149 /*
150 * check if ref to original type def & mark recursive if so.
151 */
152 /* if ((strcmp (t->basicType->a.localTypeRef->typeName, td->definedName) == 0) && (t->basicType->a.localTypeRef->module == m))
153 easier to just check ptrs!
154 */
155 if (t->basicType->a.localTypeRef->link == td)
156 {
157 td->recursive = 1;
158 if (empty)
159 {
160 PrintErrLoc (m->asn1SrcFileName, td->type->lineNo);
161 fprintf (stderr,"WARNING: Type \"%s\" appears to be infinitely recursive and can hold no values! (circular type references)\n", td->definedName);
162 }
163 else if (!optional)
164 {
165 PrintErrLoc (m->asn1SrcFileName, t->lineNo);
166 fprintf (stderr,"WARNING: Type \"%s\" appears to be infinitely recursive! (infinitely sized values)\n", td->definedName);
167 }
168 }
169
170 /*
171 * else follow this type reference if we aren't in it already
172 * (ie another recursive type in td)
173 */
174 else if (t->basicType->a.localTypeRef->link->tmpRefCount == 0)
175 {
176 /*
177 * mark this typedef as 'entered' to
178 * detect when looping in a recusive type that is contained
179 * in the original td (use tmpRefCount)
180 */
181 t->basicType->a.localTypeRef->link->tmpRefCount = 1;
182
183 newOptional = optional || (t->optional) || (t->defaultVal != NULL);
184 MkRecType (m, td, t->basicType->a.localTypeRef->link->type, newOptional, empty);
185
186 /*
187 * un-mark this type since finished with it
188 * for recursive ref's to td
189 */
190 t->basicType->a.localTypeRef->link->tmpRefCount = 0;
191 }
192 break;
193
194 /*
195 * default: other types are not aggregate and
196 * do not make recursive refs - they can be ignored
197 */
198 }
199 } /* MkRecType */