blob: 266f2d76d120eff26c54c6ef5bfbae299fb48a57 [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 }
78 }
79 assert(expr->combined_constraints == 0);
80 return clone;
81 } else if(errno != ESRCH) {
82 return NULL; /* Hard error */
83 }
84 }
85 if(!clone) clone = asn1p_expr_new(expr->_lineno);
86 if(!clone) return NULL;
vlmfa67ddc2004-06-03 03:38:44 +000087
88 /*
89 * Copy simple fields.
90 */
91 CLCOPY(meta_type);
92 CLCOPY(expr_type);
93 CLCOPY(tag);
vlm6ac9b0d2004-09-15 11:59:30 +000094 CLCOPY(marker.flags); /* OPTIONAL/DEFAULT */
vlmec8f6812004-08-22 03:19:54 +000095 CLCOPY(module);
vlmfa67ddc2004-06-03 03:38:44 +000096 CLCOPY(_mark);
97
98 clone->data = 0; /* Do not clone this */
99 clone->data_free = 0; /* Do not clone this */
100
101 /*
102 * Clone complex fields.
103 */
104 CLCLONE(Identifier, strdup);
105 CLCLONE(reference, asn1p_ref_clone);
vlm0c6d3812006-03-21 03:40:38 +0000106 CLVRCLONE(constraints, asn1p_constraint_clone_with_resolver);
107 CLVRCLONE(combined_constraints, asn1p_constraint_clone_with_resolver);
108 CLCLONE(lhs_params, asn1p_paramlist_clone);
109 CLVRCLONE(value, asn1p_value_clone_with_resolver);
vlm6ac9b0d2004-09-15 11:59:30 +0000110 CLCLONE(marker.default_value, asn1p_value_clone);
vlmfa67ddc2004-06-03 03:38:44 +0000111 CLCLONE(with_syntax, asn1p_wsyntx_clone);
112
113 /*
114 * Copy all the children of this expr.
115 */
116 TQ_FOR(tcmemb, &(expr->members), next) {
vlmec8f6812004-08-22 03:19:54 +0000117 asn1p_expr_t *cmemb;
118
119 if(skip_extensions
120 && tcmemb->expr_type == A1TC_EXTENSIBLE) {
121 hit_ext++; /* Even if hit_ext wraps around, we're OK. */
122 continue;
123 }
124 if(hit_ext == 1) continue; /* Skip between ...'s */
125
vlm0c6d3812006-03-21 03:40:38 +0000126 cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
vlmfa67ddc2004-06-03 03:38:44 +0000127 if(cmemb == NULL) {
128 asn1p_expr_free(clone);
129 return NULL;
130 }
vlm6a02a8a2004-09-08 00:28:11 +0000131 asn1p_expr_add(clone, cmemb);
vlmfa67ddc2004-06-03 03:38:44 +0000132 }
133
134 return clone;
135}
136
vlm0c6d3812006-03-21 03:40:38 +0000137
138static asn1p_value_t *
139value_resolver(asn1p_value_t *value, void *rarg) {
140 asn1p_value_t *cval;
141 asn1p_expr_t *tmpexpr;
142 asn1p_expr_t *target;
143 asn1p_ref_t *ref;
144 struct {
145 asn1p_expr_t *(*expr_resolve)(asn1p_expr_t *, void *arg);
146 } *varg = rarg;
147
148 if(!value || value->type != ATV_REFERENCED) {
149 errno = ESRCH;
150 return NULL;
151 }
152
153 ref = value->value.reference;
154 tmpexpr = asn1p_expr_new(ref->_lineno);
155 tmpexpr->meta_type = AMT_TYPEREF;
156 tmpexpr->expr_type = A1TC_REFERENCE;
157 tmpexpr->reference = ref;
158 target = varg->expr_resolve(tmpexpr, rarg);
159 tmpexpr->reference = 0;
160 asn1p_expr_free(tmpexpr);
161
162 if(!target)
163 return NULL; /* errno's are compatible */
164
165 if(!target->value) {
166 fprintf(stderr,
167 "FATAL: Parameterization did not resolve value reference "
168 "at line %d", ref->_lineno);
169 asn1p_expr_free(target);
170 errno = EPERM;
171 return NULL;
172 }
173
174 cval = asn1p_value_clone(target->value);
175 asn1p_expr_free(target);
176 return cval;
177}
178
vlmfa67ddc2004-06-03 03:38:44 +0000179/*
vlm6a02a8a2004-09-08 00:28:11 +0000180 * Add expression as a member of another.
181 */
182void
183asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
184 TQ_ADD(&(to->members), what, next);
185 what->parent_expr = to;
186}
187
188
189/*
vlmfa67ddc2004-06-03 03:38:44 +0000190 * Destruct the types collection structure.
191 */
192void
193asn1p_expr_free(asn1p_expr_t *expr) {
194 if(expr) {
195 asn1p_expr_t *tm;
196
vlm6a02a8a2004-09-08 00:28:11 +0000197 /* Remove all children */
198 while((tm = TQ_REMOVE(&(expr->members), next))) {
199 if(tm->parent_expr != expr)
200 printf("<%s:%p !-> %s:%p>\n",
201 tm->Identifier, tm->parent_expr,
202 expr->Identifier, expr);
203 assert(tm->parent_expr == expr);
204 asn1p_expr_free(tm);
205 }
206
vlmfa67ddc2004-06-03 03:38:44 +0000207 if(expr->Identifier)
208 free(expr->Identifier);
209 if(expr->reference)
210 asn1p_ref_free(expr->reference);
211 if(expr->constraints)
212 asn1p_constraint_free(expr->constraints);
vlm9283dbe2004-08-18 04:59:12 +0000213 if(expr->combined_constraints)
214 asn1p_constraint_free(expr->combined_constraints);
vlm0c6d3812006-03-21 03:40:38 +0000215 if(expr->lhs_params)
216 asn1p_paramlist_free(expr->lhs_params);
vlmfa67ddc2004-06-03 03:38:44 +0000217 if(expr->value)
218 asn1p_value_free(expr->value);
vlm6ac9b0d2004-09-15 11:59:30 +0000219 if(expr->marker.default_value)
220 asn1p_value_free(expr->marker.default_value);
vlmfa67ddc2004-06-03 03:38:44 +0000221 if(expr->with_syntax)
222 asn1p_wsyntx_free(expr->with_syntax);
223
vlmfa67ddc2004-06-03 03:38:44 +0000224 if(expr->data && expr->data_free)
225 expr->data_free(expr->data);
226
227 memset(expr, 0, sizeof(*expr));
228 free(expr);
229 }
230}
231
vlm5b103032005-06-02 05:21:53 +0000232
233char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *buf) {
vlma5b977d2005-06-06 08:28:58 +0000234 static char buf_stat[TAG2STRING_BUFFER_SIZE];
vlm5b103032005-06-02 05:21:53 +0000235 char *start;
236 char *end;
237
238 if(!buf) buf = buf_stat;
239 start = buf;
240 end = buf + TAG2STRING_BUFFER_SIZE;
241
242 if(tag->tag_class == TC_NOCLASS) {
243 *buf = 0;
244 return buf;
245 }
246
247 strcpy(buf, "[");
248 switch(tag->tag_class) {
249 case TC_NOCLASS:
250 assert(tag->tag_class != TC_NOCLASS);
251 break;
252 case TC_UNIVERSAL: strcat(buf, "UNIVERSAL "); break;
253 case TC_PRIVATE: strcat(buf, "PRIVATE "); break;
254 case TC_APPLICATION: strcat(buf, "APPLICATION "); break;
255 case TC_CONTEXT_SPECIFIC:
256 break;
257 }
258 buf += snprintf(buf + strlen(buf), end - buf,
259 "%" PRIdASN "]", tag->tag_value);
vlma5b977d2005-06-06 08:28:58 +0000260 assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
vlm5b103032005-06-02 05:21:53 +0000261
262 switch(tag->tag_mode) {
263 case TM_DEFAULT: break;
264 case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
265 case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
266 }
267
268 return start;
269}