blob: 8760066d6db8e60ed7909bd235ab0273b6230112 [file] [log] [blame]
vlmfa67ddc2004-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
vlm0c6d3812006-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
vlmfa67ddc2004-06-03 03:38:44 +000012/*
13 * Construct a new empty types collection.
14 */
15asn1p_expr_t *
vlm43c8ac52006-09-17 04:52:50 +000016asn1p_expr_new(int _lineno, asn1p_module_t *mod) {
vlmfa67ddc2004-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));
vlm0c6d3812006-03-21 03:40:38 +000022 expr->spec_index = -1;
vlm43c8ac52006-09-17 04:52:50 +000023 expr->module = mod;
vlmfa67ddc2004-06-03 03:38:44 +000024 expr->_lineno = _lineno;
25 }
26
27 return expr;
28}
29
30asn1p_expr_t *
vlmec8f6812004-08-22 03:19:54 +000031asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
vlm0c6d3812006-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;
vlmfa67ddc2004-06-03 03:38:44 +000044 asn1p_expr_t *tcmemb; /* Child of tc */
vlmec8f6812004-08-22 03:19:54 +000045 int hit_ext = 0;
vlmfa67ddc2004-06-03 03:38:44 +000046
vlmfa67ddc2004-06-03 03:38:44 +000047#define CLCOPY(field) do { clone->field = expr->field; } while(0)
vlm0c6d3812006-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 } \
vlmfa67ddc2004-06-03 03:38:44 +000054 } } while(0)
vlm0c6d3812006-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 }
vlm17e65d02006-03-21 04:48:15 +000079 assert(expr->combined_constraints == 0);
vlm0c6d3812006-03-21 03:40:38 +000080 }
vlm17e65d02006-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 }
vlm0c6d3812006-03-21 03:40:38 +000095 return clone;
96 } else if(errno != ESRCH) {
97 return NULL; /* Hard error */
98 }
99 }
vlm43c8ac52006-09-17 04:52:50 +0000100 if(!clone) clone = asn1p_expr_new(expr->_lineno, expr->module);
vlm0c6d3812006-03-21 03:40:38 +0000101 if(!clone) return NULL;
vlmfa67ddc2004-06-03 03:38:44 +0000102
103 /*
104 * Copy simple fields.
105 */
106 CLCOPY(meta_type);
107 CLCOPY(expr_type);
108 CLCOPY(tag);
vlm6ac9b0d2004-09-15 11:59:30 +0000109 CLCOPY(marker.flags); /* OPTIONAL/DEFAULT */
vlmfa67ddc2004-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);
vlm0c6d3812006-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);
vlm17e65d02006-03-21 04:48:15 +0000124 CLVRCLONE(marker.default_value, asn1p_value_clone_with_resolver);
vlmfa67ddc2004-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) {
vlmec8f6812004-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
vlm0c6d3812006-03-21 03:40:38 +0000140 cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
vlmfa67ddc2004-06-03 03:38:44 +0000141 if(cmemb == NULL) {
142 asn1p_expr_free(clone);
143 return NULL;
144 }
vlm6a02a8a2004-09-08 00:28:11 +0000145 asn1p_expr_add(clone, cmemb);
vlmfa67ddc2004-06-03 03:38:44 +0000146 }
147
148 return clone;
149}
150
vlm0c6d3812006-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;
vlm43c8ac52006-09-17 04:52:50 +0000168 tmpexpr = asn1p_expr_new(ref->_lineno, 0);
vlm0c6d3812006-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
vlmdfbff8c2006-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 {
vlm0c6d3812006-03-21 03:40:38 +0000200 errno = EPERM;
vlmdfbff8c2006-03-21 09:41:28 +0000201 cval = NULL;
vlm0c6d3812006-03-21 03:40:38 +0000202 }
203
vlm0c6d3812006-03-21 03:40:38 +0000204 asn1p_expr_free(target);
205 return cval;
206}
207
vlmfa67ddc2004-06-03 03:38:44 +0000208/*
vlm6a02a8a2004-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
217
218/*
vlmfa67ddc2004-06-03 03:38:44 +0000219 * Destruct the types collection structure.
220 */
221void
222asn1p_expr_free(asn1p_expr_t *expr) {
223 if(expr) {
224 asn1p_expr_t *tm;
225
vlm6a02a8a2004-09-08 00:28:11 +0000226 /* Remove all children */
227 while((tm = TQ_REMOVE(&(expr->members), next))) {
228 if(tm->parent_expr != expr)
229 printf("<%s:%p !-> %s:%p>\n",
230 tm->Identifier, tm->parent_expr,
231 expr->Identifier, expr);
232 assert(tm->parent_expr == expr);
233 asn1p_expr_free(tm);
234 }
235
vlmfa67ddc2004-06-03 03:38:44 +0000236 if(expr->Identifier)
237 free(expr->Identifier);
238 if(expr->reference)
239 asn1p_ref_free(expr->reference);
240 if(expr->constraints)
241 asn1p_constraint_free(expr->constraints);
vlm9283dbe2004-08-18 04:59:12 +0000242 if(expr->combined_constraints)
243 asn1p_constraint_free(expr->combined_constraints);
vlm0c6d3812006-03-21 03:40:38 +0000244 if(expr->lhs_params)
245 asn1p_paramlist_free(expr->lhs_params);
vlmfa67ddc2004-06-03 03:38:44 +0000246 if(expr->value)
247 asn1p_value_free(expr->value);
vlm6ac9b0d2004-09-15 11:59:30 +0000248 if(expr->marker.default_value)
249 asn1p_value_free(expr->marker.default_value);
vlmfa67ddc2004-06-03 03:38:44 +0000250 if(expr->with_syntax)
251 asn1p_wsyntx_free(expr->with_syntax);
252
vlmfa67ddc2004-06-03 03:38:44 +0000253 if(expr->data && expr->data_free)
254 expr->data_free(expr->data);
255
256 memset(expr, 0, sizeof(*expr));
257 free(expr);
258 }
259}
260
vlm5b103032005-06-02 05:21:53 +0000261
262char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *buf) {
vlma5b977d2005-06-06 08:28:58 +0000263 static char buf_stat[TAG2STRING_BUFFER_SIZE];
vlm5b103032005-06-02 05:21:53 +0000264 char *start;
265 char *end;
266
267 if(!buf) buf = buf_stat;
268 start = buf;
269 end = buf + TAG2STRING_BUFFER_SIZE;
270
271 if(tag->tag_class == TC_NOCLASS) {
272 *buf = 0;
273 return buf;
274 }
275
276 strcpy(buf, "[");
277 switch(tag->tag_class) {
278 case TC_NOCLASS:
279 assert(tag->tag_class != TC_NOCLASS);
280 break;
281 case TC_UNIVERSAL: strcat(buf, "UNIVERSAL "); break;
282 case TC_PRIVATE: strcat(buf, "PRIVATE "); break;
283 case TC_APPLICATION: strcat(buf, "APPLICATION "); break;
284 case TC_CONTEXT_SPECIFIC:
285 break;
286 }
287 buf += snprintf(buf + strlen(buf), end - buf,
288 "%" PRIdASN "]", tag->tag_value);
vlma5b977d2005-06-06 08:28:58 +0000289 assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
vlm5b103032005-06-02 05:21:53 +0000290
291 switch(tag->tag_mode) {
292 case TM_DEFAULT: break;
293 case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
294 case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
295 }
296
297 return start;
298}