blob: b7a03ecb007714d6c4b4bf37a6b06921f4035c20 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <errno.h>
5#include <assert.h>
6
7#include "asn1parser.h"
8
Lev Walkina00d6b32006-03-21 03:40:38 +00009static asn1p_expr_t *asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*)(asn1p_expr_t *, void *), void *);
10static asn1p_value_t *value_resolver(asn1p_value_t *, void *arg);
11
Lev Walkinf15320b2004-06-03 03:38:44 +000012/*
13 * Construct a new empty types collection.
14 */
15asn1p_expr_t *
Lev Walkina9532f42006-09-17 04:52:50 +000016asn1p_expr_new(int _lineno, asn1p_module_t *mod) {
Lev Walkinf15320b2004-06-03 03:38:44 +000017 asn1p_expr_t *expr;
18
19 expr = calloc(1, sizeof *expr);
20 if(expr) {
21 TQ_INIT(&(expr->members));
Lev Walkina00d6b32006-03-21 03:40:38 +000022 expr->spec_index = -1;
Lev Walkina9532f42006-09-17 04:52:50 +000023 expr->module = mod;
Lev Walkinf15320b2004-06-03 03:38:44 +000024 expr->_lineno = _lineno;
25 }
26
27 return expr;
28}
29
30asn1p_expr_t *
Lev Walkin070a52d2004-08-22 03:19:54 +000031asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
Lev Walkina00d6b32006-03-21 03:40:38 +000032 return asn1p_expr_clone_impl(expr, skip_extensions, 0, 0);
33}
34
35asn1p_expr_t *
36asn1p_expr_clone_with_resolver(asn1p_expr_t *expr, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
37 return asn1p_expr_clone_impl(expr, 0, r, rarg);
38}
39
40static asn1p_expr_t *
41asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
42 asn1p_value_t *(*vr)(asn1p_value_t *, void *) = 0;
43 asn1p_expr_t *clone = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000044 asn1p_expr_t *tcmemb; /* Child of tc */
Lev Walkin070a52d2004-08-22 03:19:54 +000045 int hit_ext = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000046
Lev Walkinf15320b2004-06-03 03:38:44 +000047#define CLCOPY(field) do { clone->field = expr->field; } while(0)
Lev Walkina00d6b32006-03-21 03:40:38 +000048#define CLCLONE(field, func) do { if(expr->field) { \
49 clone->field = func(expr->field); \
50 if(clone->field == NULL) { \
51 asn1p_expr_free(clone); \
52 return NULL; \
53 } \
Lev Walkinf15320b2004-06-03 03:38:44 +000054 } } while(0)
Lev Walkina00d6b32006-03-21 03:40:38 +000055#define CLVRCLONE(field, func) do { if(expr->field) { \
56 clone->field = func(expr->field, vr, rarg); \
57 if(clone->field == NULL) { \
58 asn1p_expr_free(clone); \
59 return NULL; \
60 } \
61 } } while(0)
62
63 if(r) {
64 vr = value_resolver;
65 clone = r(expr, rarg);
66 if(clone) {
67 /* Merge constraints */
68 if(expr->constraints) {
69 asn1p_constraint_t *tmpct = asn1p_constraint_clone_with_resolver(expr->constraints, vr, rarg);
70 if(clone->constraints) {
71 if(asn1p_constraint_insert(clone->constraints, tmpct)) {
72 asn1p_constraint_free(tmpct);
73 asn1p_expr_free(clone);
74 return NULL;
75 }
76 } else {
77 clone->constraints = tmpct;
78 }
Lev Walkin0c0bca62006-03-21 04:48:15 +000079 assert(expr->combined_constraints == 0);
Lev Walkina00d6b32006-03-21 03:40:38 +000080 }
Lev Walkin0c0bca62006-03-21 04:48:15 +000081 /* Merge defaults */
82 CLCOPY(marker.flags);
83 CLVRCLONE(marker.default_value,
84 asn1p_value_clone_with_resolver);
85 if(clone->tag.tag_class == TC_NOCLASS) {
86 CLCOPY(tag);
87 } else if(expr->tag.tag_class != TC_NOCLASS) {
88 fprintf(stderr, "asn1c does not support "
89 "nested tagging in parameterization, "
90 "necessary at line %d\n",
91 expr->_lineno);
92 asn1p_expr_free(clone);
93 return NULL;
94 }
Lev Walkina00d6b32006-03-21 03:40:38 +000095 return clone;
96 } else if(errno != ESRCH) {
97 return NULL; /* Hard error */
98 }
99 }
Lev Walkina9532f42006-09-17 04:52:50 +0000100 if(!clone) clone = asn1p_expr_new(expr->_lineno, expr->module);
Lev Walkina00d6b32006-03-21 03:40:38 +0000101 if(!clone) return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000102
103 /*
104 * Copy simple fields.
105 */
106 CLCOPY(meta_type);
107 CLCOPY(expr_type);
108 CLCOPY(tag);
Lev Walkin5498f2d2004-09-15 11:59:30 +0000109 CLCOPY(marker.flags); /* OPTIONAL/DEFAULT */
Lev Walkinf15320b2004-06-03 03:38:44 +0000110 CLCOPY(_mark);
111
112 clone->data = 0; /* Do not clone this */
113 clone->data_free = 0; /* Do not clone this */
114
115 /*
116 * Clone complex fields.
117 */
118 CLCLONE(Identifier, strdup);
119 CLCLONE(reference, asn1p_ref_clone);
Lev Walkina00d6b32006-03-21 03:40:38 +0000120 CLVRCLONE(constraints, asn1p_constraint_clone_with_resolver);
121 CLVRCLONE(combined_constraints, asn1p_constraint_clone_with_resolver);
122 CLCLONE(lhs_params, asn1p_paramlist_clone);
123 CLVRCLONE(value, asn1p_value_clone_with_resolver);
Lev Walkin0c0bca62006-03-21 04:48:15 +0000124 CLVRCLONE(marker.default_value, asn1p_value_clone_with_resolver);
Lev Walkinf15320b2004-06-03 03:38:44 +0000125 CLCLONE(with_syntax, asn1p_wsyntx_clone);
126
127 /*
128 * Copy all the children of this expr.
129 */
130 TQ_FOR(tcmemb, &(expr->members), next) {
Lev Walkin070a52d2004-08-22 03:19:54 +0000131 asn1p_expr_t *cmemb;
132
133 if(skip_extensions
134 && tcmemb->expr_type == A1TC_EXTENSIBLE) {
135 hit_ext++; /* Even if hit_ext wraps around, we're OK. */
136 continue;
137 }
138 if(hit_ext == 1) continue; /* Skip between ...'s */
139
Lev Walkina00d6b32006-03-21 03:40:38 +0000140 cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
Lev Walkinf15320b2004-06-03 03:38:44 +0000141 if(cmemb == NULL) {
142 asn1p_expr_free(clone);
143 return NULL;
144 }
Lev Walkin1004aa92004-09-08 00:28:11 +0000145 asn1p_expr_add(clone, cmemb);
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 }
147
148 return clone;
149}
150
Lev Walkina00d6b32006-03-21 03:40:38 +0000151
152static asn1p_value_t *
153value_resolver(asn1p_value_t *value, void *rarg) {
154 asn1p_value_t *cval;
155 asn1p_expr_t *tmpexpr;
156 asn1p_expr_t *target;
157 asn1p_ref_t *ref;
158 struct {
159 asn1p_expr_t *(*expr_resolve)(asn1p_expr_t *, void *arg);
160 } *varg = rarg;
161
162 if(!value || value->type != ATV_REFERENCED) {
163 errno = ESRCH;
164 return NULL;
165 }
166
167 ref = value->value.reference;
Lev Walkina9532f42006-09-17 04:52:50 +0000168 tmpexpr = asn1p_expr_new(ref->_lineno, 0);
Lev Walkina00d6b32006-03-21 03:40:38 +0000169 tmpexpr->meta_type = AMT_TYPEREF;
170 tmpexpr->expr_type = A1TC_REFERENCE;
171 tmpexpr->reference = ref;
172 target = varg->expr_resolve(tmpexpr, rarg);
173 tmpexpr->reference = 0;
174 asn1p_expr_free(tmpexpr);
175
176 if(!target)
177 return NULL; /* errno's are compatible */
178
Lev Walkin5045dfa2006-03-21 09:41:28 +0000179 if(target->meta_type == AMT_VALUE) {
180 if(!target->value) {
181 fprintf(stderr,
182 "FATAL: Parameterization did not resolve "
183 "value reference at line %d\n", ref->_lineno);
184 asn1p_expr_free(target);
185 errno = EPERM;
186 return NULL;
187 }
188 cval = asn1p_value_clone(target->value);
189 } else if(target->meta_type == AMT_VALUESET) {
190 if(!target->constraints) {
191 fprintf(stderr,
192 "FATAL: Parameterization did not resolve "
193 "value set reference at line %d\n", ref->_lineno);
194 asn1p_expr_free(target);
195 errno = EPERM;
196 return NULL;
197 }
198 cval = asn1p_value_fromconstr(target->constraints, 1);
199 } else {
Lev Walkina00d6b32006-03-21 03:40:38 +0000200 errno = EPERM;
Lev Walkin5045dfa2006-03-21 09:41:28 +0000201 cval = NULL;
Lev Walkina00d6b32006-03-21 03:40:38 +0000202 }
203
Lev Walkina00d6b32006-03-21 03:40:38 +0000204 asn1p_expr_free(target);
205 return cval;
206}
207
Lev Walkinf15320b2004-06-03 03:38:44 +0000208/*
Lev Walkin1004aa92004-09-08 00:28:11 +0000209 * Add expression as a member of another.
210 */
211void
212asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
213 TQ_ADD(&(to->members), what, next);
214 what->parent_expr = to;
215}
216
Lev Walkin0e90aa02013-03-19 16:17:13 -0700217/*
218 * Add inner expressions as members of another.
219 */
220void
221asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what) {
222 asn1p_expr_t *expr;
223 TQ_FOR(expr, &(from_what->members), next) {
224 expr->parent_expr = to;
225 }
226 TQ_CONCAT(&(to->members), &(from_what->members), next);
227}
228
Lev Walkin1004aa92004-09-08 00:28:11 +0000229
230/*
Lev Walkinf15320b2004-06-03 03:38:44 +0000231 * Destruct the types collection structure.
232 */
233void
234asn1p_expr_free(asn1p_expr_t *expr) {
235 if(expr) {
236 asn1p_expr_t *tm;
237
Lev Walkin1004aa92004-09-08 00:28:11 +0000238 /* Remove all children */
239 while((tm = TQ_REMOVE(&(expr->members), next))) {
240 if(tm->parent_expr != expr)
241 printf("<%s:%p !-> %s:%p>\n",
242 tm->Identifier, tm->parent_expr,
243 expr->Identifier, expr);
244 assert(tm->parent_expr == expr);
245 asn1p_expr_free(tm);
246 }
247
Lev Walkind8b83642016-03-14 02:00:27 -0700248 free(expr->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000249 if(expr->reference)
250 asn1p_ref_free(expr->reference);
251 if(expr->constraints)
252 asn1p_constraint_free(expr->constraints);
Lev Walkinf59d0752004-08-18 04:59:12 +0000253 if(expr->combined_constraints)
254 asn1p_constraint_free(expr->combined_constraints);
Lev Walkina00d6b32006-03-21 03:40:38 +0000255 if(expr->lhs_params)
256 asn1p_paramlist_free(expr->lhs_params);
Lev Walkinf15320b2004-06-03 03:38:44 +0000257 if(expr->value)
258 asn1p_value_free(expr->value);
Lev Walkin5498f2d2004-09-15 11:59:30 +0000259 if(expr->marker.default_value)
260 asn1p_value_free(expr->marker.default_value);
Lev Walkinf15320b2004-06-03 03:38:44 +0000261 if(expr->with_syntax)
262 asn1p_wsyntx_free(expr->with_syntax);
263
Lev Walkinf15320b2004-06-03 03:38:44 +0000264 if(expr->data && expr->data_free)
265 expr->data_free(expr->data);
266
267 memset(expr, 0, sizeof(*expr));
268 free(expr);
269 }
270}
271
Lev Walkin71160962005-06-02 05:21:53 +0000272
273char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *buf) {
Lev Walkin8f294e02005-06-06 08:28:58 +0000274 static char buf_stat[TAG2STRING_BUFFER_SIZE];
Lev Walkin71160962005-06-02 05:21:53 +0000275 char *start;
276 char *end;
277
278 if(!buf) buf = buf_stat;
279 start = buf;
280 end = buf + TAG2STRING_BUFFER_SIZE;
281
282 if(tag->tag_class == TC_NOCLASS) {
283 *buf = 0;
284 return buf;
285 }
286
287 strcpy(buf, "[");
288 switch(tag->tag_class) {
289 case TC_NOCLASS:
290 assert(tag->tag_class != TC_NOCLASS);
291 break;
292 case TC_UNIVERSAL: strcat(buf, "UNIVERSAL "); break;
293 case TC_PRIVATE: strcat(buf, "PRIVATE "); break;
294 case TC_APPLICATION: strcat(buf, "APPLICATION "); break;
295 case TC_CONTEXT_SPECIFIC:
296 break;
297 }
298 buf += snprintf(buf + strlen(buf), end - buf,
299 "%" PRIdASN "]", tag->tag_value);
Lev Walkin8f294e02005-06-06 08:28:58 +0000300 assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
Lev Walkin71160962005-06-02 05:21:53 +0000301
302 switch(tag->tag_mode) {
303 case TM_DEFAULT: break;
304 case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
305 case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
306 }
307
308 return start;
309}