blob: b1cce6953fea085d17ab96c6c8aeb2531a5b25ee [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 *
16asn1p_expr_new(int _lineno) {
17 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;
vlmfa67ddc2004-06-03 03:38:44 +000023 expr->_lineno = _lineno;
24 }
25
26 return expr;
27}
28
29asn1p_expr_t *
vlmec8f6812004-08-22 03:19:54 +000030asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
vlm0c6d3812006-03-21 03:40:38 +000031 return asn1p_expr_clone_impl(expr, skip_extensions, 0, 0);
32}
33
34asn1p_expr_t *
35asn1p_expr_clone_with_resolver(asn1p_expr_t *expr, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
36 return asn1p_expr_clone_impl(expr, 0, r, rarg);
37}
38
39static asn1p_expr_t *
40asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
41 asn1p_value_t *(*vr)(asn1p_value_t *, void *) = 0;
42 asn1p_expr_t *clone = 0;
vlmfa67ddc2004-06-03 03:38:44 +000043 asn1p_expr_t *tcmemb; /* Child of tc */
vlmec8f6812004-08-22 03:19:54 +000044 int hit_ext = 0;
vlmfa67ddc2004-06-03 03:38:44 +000045
vlmfa67ddc2004-06-03 03:38:44 +000046#define CLCOPY(field) do { clone->field = expr->field; } while(0)
vlm0c6d3812006-03-21 03:40:38 +000047#define CLCLONE(field, func) do { if(expr->field) { \
48 clone->field = func(expr->field); \
49 if(clone->field == NULL) { \
50 asn1p_expr_free(clone); \
51 return NULL; \
52 } \
vlmfa67ddc2004-06-03 03:38:44 +000053 } } while(0)
vlm0c6d3812006-03-21 03:40:38 +000054#define CLVRCLONE(field, func) do { if(expr->field) { \
55 clone->field = func(expr->field, vr, rarg); \
56 if(clone->field == NULL) { \
57 asn1p_expr_free(clone); \
58 return NULL; \
59 } \
60 } } while(0)
61
62 if(r) {
63 vr = value_resolver;
64 clone = r(expr, rarg);
65 if(clone) {
66 /* Merge constraints */
67 if(expr->constraints) {
68 asn1p_constraint_t *tmpct = asn1p_constraint_clone_with_resolver(expr->constraints, vr, rarg);
69 if(clone->constraints) {
70 if(asn1p_constraint_insert(clone->constraints, tmpct)) {
71 asn1p_constraint_free(tmpct);
72 asn1p_expr_free(clone);
73 return NULL;
74 }
75 } else {
76 clone->constraints = tmpct;
77 }
vlm17e65d02006-03-21 04:48:15 +000078 assert(expr->combined_constraints == 0);
vlm0c6d3812006-03-21 03:40:38 +000079 }
vlm17e65d02006-03-21 04:48:15 +000080 /* Merge defaults */
81 CLCOPY(marker.flags);
82 CLVRCLONE(marker.default_value,
83 asn1p_value_clone_with_resolver);
84 if(clone->tag.tag_class == TC_NOCLASS) {
85 CLCOPY(tag);
86 } else if(expr->tag.tag_class != TC_NOCLASS) {
87 fprintf(stderr, "asn1c does not support "
88 "nested tagging in parameterization, "
89 "necessary at line %d\n",
90 expr->_lineno);
91 asn1p_expr_free(clone);
92 return NULL;
93 }
vlm0c6d3812006-03-21 03:40:38 +000094 return clone;
95 } else if(errno != ESRCH) {
96 return NULL; /* Hard error */
97 }
98 }
99 if(!clone) clone = asn1p_expr_new(expr->_lineno);
100 if(!clone) return NULL;
vlmfa67ddc2004-06-03 03:38:44 +0000101
102 /*
103 * Copy simple fields.
104 */
105 CLCOPY(meta_type);
106 CLCOPY(expr_type);
107 CLCOPY(tag);
vlm6ac9b0d2004-09-15 11:59:30 +0000108 CLCOPY(marker.flags); /* OPTIONAL/DEFAULT */
vlmec8f6812004-08-22 03:19:54 +0000109 CLCOPY(module);
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;
168 tmpexpr = asn1p_expr_new(ref->_lineno);
169 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
179 if(!target->value) {
180 fprintf(stderr,
181 "FATAL: Parameterization did not resolve value reference "
182 "at line %d", ref->_lineno);
183 asn1p_expr_free(target);
184 errno = EPERM;
185 return NULL;
186 }
187
188 cval = asn1p_value_clone(target->value);
189 asn1p_expr_free(target);
190 return cval;
191}
192
vlmfa67ddc2004-06-03 03:38:44 +0000193/*
vlm6a02a8a2004-09-08 00:28:11 +0000194 * Add expression as a member of another.
195 */
196void
197asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
198 TQ_ADD(&(to->members), what, next);
199 what->parent_expr = to;
200}
201
202
203/*
vlmfa67ddc2004-06-03 03:38:44 +0000204 * Destruct the types collection structure.
205 */
206void
207asn1p_expr_free(asn1p_expr_t *expr) {
208 if(expr) {
209 asn1p_expr_t *tm;
210
vlm6a02a8a2004-09-08 00:28:11 +0000211 /* Remove all children */
212 while((tm = TQ_REMOVE(&(expr->members), next))) {
213 if(tm->parent_expr != expr)
214 printf("<%s:%p !-> %s:%p>\n",
215 tm->Identifier, tm->parent_expr,
216 expr->Identifier, expr);
217 assert(tm->parent_expr == expr);
218 asn1p_expr_free(tm);
219 }
220
vlmfa67ddc2004-06-03 03:38:44 +0000221 if(expr->Identifier)
222 free(expr->Identifier);
223 if(expr->reference)
224 asn1p_ref_free(expr->reference);
225 if(expr->constraints)
226 asn1p_constraint_free(expr->constraints);
vlm9283dbe2004-08-18 04:59:12 +0000227 if(expr->combined_constraints)
228 asn1p_constraint_free(expr->combined_constraints);
vlm0c6d3812006-03-21 03:40:38 +0000229 if(expr->lhs_params)
230 asn1p_paramlist_free(expr->lhs_params);
vlmfa67ddc2004-06-03 03:38:44 +0000231 if(expr->value)
232 asn1p_value_free(expr->value);
vlm6ac9b0d2004-09-15 11:59:30 +0000233 if(expr->marker.default_value)
234 asn1p_value_free(expr->marker.default_value);
vlmfa67ddc2004-06-03 03:38:44 +0000235 if(expr->with_syntax)
236 asn1p_wsyntx_free(expr->with_syntax);
237
vlmfa67ddc2004-06-03 03:38:44 +0000238 if(expr->data && expr->data_free)
239 expr->data_free(expr->data);
240
241 memset(expr, 0, sizeof(*expr));
242 free(expr);
243 }
244}
245
vlm5b103032005-06-02 05:21:53 +0000246
247char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *buf) {
vlma5b977d2005-06-06 08:28:58 +0000248 static char buf_stat[TAG2STRING_BUFFER_SIZE];
vlm5b103032005-06-02 05:21:53 +0000249 char *start;
250 char *end;
251
252 if(!buf) buf = buf_stat;
253 start = buf;
254 end = buf + TAG2STRING_BUFFER_SIZE;
255
256 if(tag->tag_class == TC_NOCLASS) {
257 *buf = 0;
258 return buf;
259 }
260
261 strcpy(buf, "[");
262 switch(tag->tag_class) {
263 case TC_NOCLASS:
264 assert(tag->tag_class != TC_NOCLASS);
265 break;
266 case TC_UNIVERSAL: strcat(buf, "UNIVERSAL "); break;
267 case TC_PRIVATE: strcat(buf, "PRIVATE "); break;
268 case TC_APPLICATION: strcat(buf, "APPLICATION "); break;
269 case TC_CONTEXT_SPECIFIC:
270 break;
271 }
272 buf += snprintf(buf + strlen(buf), end - buf,
273 "%" PRIdASN "]", tag->tag_value);
vlma5b977d2005-06-06 08:28:58 +0000274 assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
vlm5b103032005-06-02 05:21:53 +0000275
276 switch(tag->tag_mode) {
277 case TM_DEFAULT: break;
278 case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
279 case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
280 }
281
282 return start;
283}