blob: 6065a7acd07a3e12729b038dfcb06811b1e66e78 [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;
Bi-Ruei, Chiub9adfc52016-11-09 00:17:25 +080025 expr->ref_cnt = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000026 }
27
28 return expr;
29}
30
31asn1p_expr_t *
Lev Walkin070a52d2004-08-22 03:19:54 +000032asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
Lev Walkina00d6b32006-03-21 03:40:38 +000033 return asn1p_expr_clone_impl(expr, skip_extensions, 0, 0);
34}
35
36asn1p_expr_t *
37asn1p_expr_clone_with_resolver(asn1p_expr_t *expr, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
38 return asn1p_expr_clone_impl(expr, 0, r, rarg);
39}
40
41static asn1p_expr_t *
42asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
43 asn1p_value_t *(*vr)(asn1p_value_t *, void *) = 0;
44 asn1p_expr_t *clone = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000045 asn1p_expr_t *tcmemb; /* Child of tc */
Lev Walkin070a52d2004-08-22 03:19:54 +000046 int hit_ext = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000047
Lev Walkinf15320b2004-06-03 03:38:44 +000048#define CLCOPY(field) do { clone->field = expr->field; } while(0)
Lev Walkina00d6b32006-03-21 03:40:38 +000049#define CLCLONE(field, func) do { if(expr->field) { \
50 clone->field = func(expr->field); \
51 if(clone->field == NULL) { \
52 asn1p_expr_free(clone); \
53 return NULL; \
54 } \
Lev Walkinf15320b2004-06-03 03:38:44 +000055 } } while(0)
Lev Walkina00d6b32006-03-21 03:40:38 +000056#define CLVRCLONE(field, func) do { if(expr->field) { \
57 clone->field = func(expr->field, vr, rarg); \
58 if(clone->field == NULL) { \
59 asn1p_expr_free(clone); \
60 return NULL; \
61 } \
62 } } while(0)
63
64 if(r) {
65 vr = value_resolver;
66 clone = r(expr, rarg);
67 if(clone) {
68 /* Merge constraints */
69 if(expr->constraints) {
70 asn1p_constraint_t *tmpct = asn1p_constraint_clone_with_resolver(expr->constraints, vr, rarg);
71 if(clone->constraints) {
72 if(asn1p_constraint_insert(clone->constraints, tmpct)) {
73 asn1p_constraint_free(tmpct);
74 asn1p_expr_free(clone);
75 return NULL;
76 }
77 } else {
78 clone->constraints = tmpct;
79 }
Lev Walkin0c0bca62006-03-21 04:48:15 +000080 assert(expr->combined_constraints == 0);
Lev Walkina00d6b32006-03-21 03:40:38 +000081 }
Lev Walkin0c0bca62006-03-21 04:48:15 +000082 /* Merge defaults */
83 CLCOPY(marker.flags);
84 CLVRCLONE(marker.default_value,
85 asn1p_value_clone_with_resolver);
86 if(clone->tag.tag_class == TC_NOCLASS) {
87 CLCOPY(tag);
88 } else if(expr->tag.tag_class != TC_NOCLASS) {
89 fprintf(stderr, "asn1c does not support "
90 "nested tagging in parameterization, "
91 "necessary at line %d\n",
92 expr->_lineno);
93 asn1p_expr_free(clone);
94 return NULL;
95 }
Lev Walkina00d6b32006-03-21 03:40:38 +000096 return clone;
97 } else if(errno != ESRCH) {
98 return NULL; /* Hard error */
99 }
100 }
Lev Walkina9532f42006-09-17 04:52:50 +0000101 if(!clone) clone = asn1p_expr_new(expr->_lineno, expr->module);
Lev Walkina00d6b32006-03-21 03:40:38 +0000102 if(!clone) return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000103
104 /*
105 * Copy simple fields.
106 */
107 CLCOPY(meta_type);
108 CLCOPY(expr_type);
109 CLCOPY(tag);
Lev Walkin5498f2d2004-09-15 11:59:30 +0000110 CLCOPY(marker.flags); /* OPTIONAL/DEFAULT */
Lev Walkinf15320b2004-06-03 03:38:44 +0000111 CLCOPY(_mark);
112
113 clone->data = 0; /* Do not clone this */
114 clone->data_free = 0; /* Do not clone this */
115
116 /*
117 * Clone complex fields.
118 */
119 CLCLONE(Identifier, strdup);
120 CLCLONE(reference, asn1p_ref_clone);
Lev Walkina00d6b32006-03-21 03:40:38 +0000121 CLVRCLONE(constraints, asn1p_constraint_clone_with_resolver);
122 CLVRCLONE(combined_constraints, asn1p_constraint_clone_with_resolver);
123 CLCLONE(lhs_params, asn1p_paramlist_clone);
124 CLVRCLONE(value, asn1p_value_clone_with_resolver);
Lev Walkin0c0bca62006-03-21 04:48:15 +0000125 CLVRCLONE(marker.default_value, asn1p_value_clone_with_resolver);
Lev Walkinf15320b2004-06-03 03:38:44 +0000126 CLCLONE(with_syntax, asn1p_wsyntx_clone);
127
128 /*
129 * Copy all the children of this expr.
130 */
131 TQ_FOR(tcmemb, &(expr->members), next) {
Lev Walkin070a52d2004-08-22 03:19:54 +0000132 asn1p_expr_t *cmemb;
133
134 if(skip_extensions
135 && tcmemb->expr_type == A1TC_EXTENSIBLE) {
136 hit_ext++; /* Even if hit_ext wraps around, we're OK. */
137 continue;
138 }
139 if(hit_ext == 1) continue; /* Skip between ...'s */
140
Lev Walkina00d6b32006-03-21 03:40:38 +0000141 cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
Lev Walkinf15320b2004-06-03 03:38:44 +0000142 if(cmemb == NULL) {
143 asn1p_expr_free(clone);
144 return NULL;
145 }
Lev Walkin1004aa92004-09-08 00:28:11 +0000146 asn1p_expr_add(clone, cmemb);
Lev Walkinf15320b2004-06-03 03:38:44 +0000147 }
148
149 return clone;
150}
151
Lev Walkina00d6b32006-03-21 03:40:38 +0000152
153static asn1p_value_t *
154value_resolver(asn1p_value_t *value, void *rarg) {
155 asn1p_value_t *cval;
156 asn1p_expr_t *tmpexpr;
157 asn1p_expr_t *target;
158 asn1p_ref_t *ref;
159 struct {
160 asn1p_expr_t *(*expr_resolve)(asn1p_expr_t *, void *arg);
161 } *varg = rarg;
162
163 if(!value || value->type != ATV_REFERENCED) {
164 errno = ESRCH;
165 return NULL;
166 }
167
168 ref = value->value.reference;
Lev Walkina9532f42006-09-17 04:52:50 +0000169 tmpexpr = asn1p_expr_new(ref->_lineno, 0);
Lev Walkina00d6b32006-03-21 03:40:38 +0000170 tmpexpr->meta_type = AMT_TYPEREF;
171 tmpexpr->expr_type = A1TC_REFERENCE;
172 tmpexpr->reference = ref;
173 target = varg->expr_resolve(tmpexpr, rarg);
174 tmpexpr->reference = 0;
175 asn1p_expr_free(tmpexpr);
176
177 if(!target)
178 return NULL; /* errno's are compatible */
179
Lev Walkin5045dfa2006-03-21 09:41:28 +0000180 if(target->meta_type == AMT_VALUE) {
181 if(!target->value) {
182 fprintf(stderr,
183 "FATAL: Parameterization did not resolve "
184 "value reference at line %d\n", ref->_lineno);
185 asn1p_expr_free(target);
186 errno = EPERM;
187 return NULL;
188 }
189 cval = asn1p_value_clone(target->value);
190 } else if(target->meta_type == AMT_VALUESET) {
191 if(!target->constraints) {
192 fprintf(stderr,
193 "FATAL: Parameterization did not resolve "
194 "value set reference at line %d\n", ref->_lineno);
195 asn1p_expr_free(target);
196 errno = EPERM;
197 return NULL;
198 }
199 cval = asn1p_value_fromconstr(target->constraints, 1);
200 } else {
Lev Walkina00d6b32006-03-21 03:40:38 +0000201 errno = EPERM;
Lev Walkin5045dfa2006-03-21 09:41:28 +0000202 cval = NULL;
Lev Walkina00d6b32006-03-21 03:40:38 +0000203 }
204
Lev Walkina00d6b32006-03-21 03:40:38 +0000205 asn1p_expr_free(target);
206 return cval;
207}
208
Lev Walkinf15320b2004-06-03 03:38:44 +0000209/*
Lev Walkin1004aa92004-09-08 00:28:11 +0000210 * Add expression as a member of another.
211 */
212void
213asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
214 TQ_ADD(&(to->members), what, next);
215 what->parent_expr = to;
216}
217
Lev Walkin0e90aa02013-03-19 16:17:13 -0700218/*
219 * Add inner expressions as members of another.
220 */
221void
222asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what) {
223 asn1p_expr_t *expr;
224 TQ_FOR(expr, &(from_what->members), next) {
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800225 expr->parent_expr = to;
226 }
Lev Walkin0e90aa02013-03-19 16:17:13 -0700227 TQ_CONCAT(&(to->members), &(from_what->members), next);
228}
229
Lev Walkin1004aa92004-09-08 00:28:11 +0000230
231/*
Lev Walkinf15320b2004-06-03 03:38:44 +0000232 * Destruct the types collection structure.
233 */
234void
235asn1p_expr_free(asn1p_expr_t *expr) {
236 if(expr) {
237 asn1p_expr_t *tm;
238
Bi-Ruei, Chiub9adfc52016-11-09 00:17:25 +0800239 if (expr->ref_cnt) {
240 /* Decrease reference count only */
241 expr->ref_cnt--;
242 return;
243 }
244
Lev Walkin1004aa92004-09-08 00:28:11 +0000245 /* Remove all children */
246 while((tm = TQ_REMOVE(&(expr->members), next))) {
247 if(tm->parent_expr != expr)
248 printf("<%s:%p !-> %s:%p>\n",
249 tm->Identifier, tm->parent_expr,
250 expr->Identifier, expr);
251 assert(tm->parent_expr == expr);
252 asn1p_expr_free(tm);
253 }
254
Lev Walkind8b83642016-03-14 02:00:27 -0700255 free(expr->Identifier);
Markus Elfring671eb9a2016-03-14 17:07:26 +0100256 asn1p_ref_free(expr->reference);
257 asn1p_constraint_free(expr->constraints);
258 asn1p_constraint_free(expr->combined_constraints);
259 asn1p_paramlist_free(expr->lhs_params);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800260 asn1p_expr_free(expr->rhs_pspecs);
Markus Elfring671eb9a2016-03-14 17:07:26 +0100261 asn1p_value_free(expr->value);
262 asn1p_value_free(expr->marker.default_value);
263 asn1p_wsyntx_free(expr->with_syntax);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800264 if(expr->specializations.pspec) {
265 int pspec;
266 for(pspec = 0; pspec < expr->specializations.pspecs_count; pspec++) {
267 asn1p_expr_free(expr->specializations.pspec[pspec].rhs_pspecs);
268 asn1p_expr_free(expr->specializations.pspec[pspec].my_clone);
269 }
270 free(expr->specializations.pspec);
271 }
272 if(expr->object_class_matrix.row) {
273 int row;
274 for(row = 0; row < expr->object_class_matrix.rows; row++) {
275 asn1p_ioc_row_delete(expr->object_class_matrix.row[row]);
276 }
277 free(expr->object_class_matrix.row);
278 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000279
Lev Walkinf15320b2004-06-03 03:38:44 +0000280 if(expr->data && expr->data_free)
281 expr->data_free(expr->data);
282
283 memset(expr, 0, sizeof(*expr));
284 free(expr);
285 }
286}
287
Lev Walkin71160962005-06-02 05:21:53 +0000288
289char *asn1p_tag2string(struct asn1p_type_tag_s *tag, char *buf) {
Lev Walkin8f294e02005-06-06 08:28:58 +0000290 static char buf_stat[TAG2STRING_BUFFER_SIZE];
Lev Walkin71160962005-06-02 05:21:53 +0000291 char *start;
292 char *end;
293
294 if(!buf) buf = buf_stat;
295 start = buf;
296 end = buf + TAG2STRING_BUFFER_SIZE;
297
298 if(tag->tag_class == TC_NOCLASS) {
299 *buf = 0;
300 return buf;
301 }
302
303 strcpy(buf, "[");
304 switch(tag->tag_class) {
305 case TC_NOCLASS:
306 assert(tag->tag_class != TC_NOCLASS);
307 break;
308 case TC_UNIVERSAL: strcat(buf, "UNIVERSAL "); break;
309 case TC_PRIVATE: strcat(buf, "PRIVATE "); break;
310 case TC_APPLICATION: strcat(buf, "APPLICATION "); break;
311 case TC_CONTEXT_SPECIFIC:
312 break;
313 }
314 buf += snprintf(buf + strlen(buf), end - buf,
315 "%" PRIdASN "]", tag->tag_value);
Lev Walkin8f294e02005-06-06 08:28:58 +0000316 assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
Lev Walkin71160962005-06-02 05:21:53 +0000317
318 switch(tag->tag_mode) {
319 case TM_DEFAULT: break;
320 case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
321 case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
322 }
323
324 return start;
325}