blob: 902e04f5cd5b4c79f2ad08c72fbf45a2da64bbe1 [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 Walkinea6635b2017-08-06 23:23:04 -070012void
13asn1p_expr_set_source(asn1p_expr_t *expr, asn1p_module_t *module, int lineno) {
14 if(expr) {
15 expr->module = module;
16 expr->_lineno = lineno;
17 asn1p_ref_set_source(expr->reference, module, lineno);
18 asn1p_value_set_source(expr->value, module, lineno);
19 asn1p_constraint_set_source(expr->constraints, module, lineno);
20 asn1p_constraint_set_source(expr->combined_constraints, module, lineno);
21 asn1p_expr_set_source(expr->rhs_pspecs, module, lineno);
22
23 asn1p_expr_t *memb;
24
25 TQ_FOR(memb, &(expr->members), next) {
26 asn1p_expr_set_source(memb, module, lineno);
27 }
28 }
29}
30
31int
32asn1p_expr_compare(const asn1p_expr_t *a, const asn1p_expr_t *b) {
33 if(a->meta_type != b->meta_type || a->expr_type != b->expr_type) {
34 return -1;
35 }
36
37 if((!a->Identifier && b->Identifier) || (a->Identifier && !b->Identifier)) {
38 return -1;
39 } else if(a->Identifier && strcmp(a->Identifier, b->Identifier)) {
40 return -1;
41 }
42
43 if((!a->reference && b->reference) || (a->reference && !b->reference)) {
44 return -1;
45 } else if(a->reference
46 && asn1p_ref_compare(a->reference, b->reference) != 0) {
47 return -1;
48 }
49
50 if((!a->value && b->value) || (a->value && !b->value)) {
51 return -1;
52 } else if(a->value && asn1p_value_compare(a->value, b->value)) {
53 return -1;
54 }
55
56 if((a->tag.tag_class != b->tag.tag_class)
57 || (a->tag.tag_mode != b->tag.tag_mode)
58 || (a->tag.tag_value != b->tag.tag_value)) {
59 return -1;
60 }
61
62 if((a->marker.flags != b->marker.flags)
63 || (a->marker.default_value && !b->marker.default_value)
64 || (!a->marker.default_value && b->marker.default_value)
65 || (a->marker.default_value
66 && asn1p_value_compare(a->marker.default_value,
67 b->marker.default_value))) {
68 return -1;
69 }
70
71 if(a->unique != b->unique) {
72 return -1;
73 }
74
75 const asn1p_expr_t *am = TQ_FIRST(&a->members);
76 const asn1p_expr_t *bm = TQ_FIRST(&b->members);
77 for(; am || bm; am = TQ_NEXT(am, next), bm = TQ_NEXT(bm, next)) {
78 if((am && !bm) || (!am && bm)) {
79 return -1;
80 } else if(asn1p_expr_compare(am, bm) != 0) {
81 return -1;
82 }
83 }
84
85 return 0;
86}
87
Lev Walkinf15320b2004-06-03 03:38:44 +000088/*
89 * Construct a new empty types collection.
90 */
91asn1p_expr_t *
Lev Walkina9532f42006-09-17 04:52:50 +000092asn1p_expr_new(int _lineno, asn1p_module_t *mod) {
Lev Walkinf15320b2004-06-03 03:38:44 +000093 asn1p_expr_t *expr;
94
95 expr = calloc(1, sizeof *expr);
96 if(expr) {
97 TQ_INIT(&(expr->members));
Lev Walkina00d6b32006-03-21 03:40:38 +000098 expr->spec_index = -1;
Lev Walkina9532f42006-09-17 04:52:50 +000099 expr->module = mod;
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 expr->_lineno = _lineno;
Bi-Ruei, Chiub9adfc52016-11-09 00:17:25 +0800101 expr->ref_cnt = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000102 }
103
104 return expr;
105}
106
107asn1p_expr_t *
Lev Walkin070a52d2004-08-22 03:19:54 +0000108asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
Lev Walkina00d6b32006-03-21 03:40:38 +0000109 return asn1p_expr_clone_impl(expr, skip_extensions, 0, 0);
110}
111
112asn1p_expr_t *
113asn1p_expr_clone_with_resolver(asn1p_expr_t *expr, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
114 return asn1p_expr_clone_impl(expr, 0, r, rarg);
115}
116
117static asn1p_expr_t *
118asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
119 asn1p_value_t *(*vr)(asn1p_value_t *, void *) = 0;
120 asn1p_expr_t *clone = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000121 asn1p_expr_t *tcmemb; /* Child of tc */
Lev Walkin070a52d2004-08-22 03:19:54 +0000122 int hit_ext = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000123
Lev Walkinf15320b2004-06-03 03:38:44 +0000124#define CLCOPY(field) do { clone->field = expr->field; } while(0)
Lev Walkina00d6b32006-03-21 03:40:38 +0000125#define CLCLONE(field, func) do { if(expr->field) { \
126 clone->field = func(expr->field); \
127 if(clone->field == NULL) { \
128 asn1p_expr_free(clone); \
129 return NULL; \
130 } \
Lev Walkinf15320b2004-06-03 03:38:44 +0000131 } } while(0)
Lev Walkina00d6b32006-03-21 03:40:38 +0000132#define CLVRCLONE(field, func) do { if(expr->field) { \
133 clone->field = func(expr->field, vr, rarg); \
134 if(clone->field == NULL) { \
135 asn1p_expr_free(clone); \
136 return NULL; \
137 } \
138 } } while(0)
139
140 if(r) {
141 vr = value_resolver;
142 clone = r(expr, rarg);
143 if(clone) {
144 /* Merge constraints */
145 if(expr->constraints) {
146 asn1p_constraint_t *tmpct = asn1p_constraint_clone_with_resolver(expr->constraints, vr, rarg);
147 if(clone->constraints) {
148 if(asn1p_constraint_insert(clone->constraints, tmpct)) {
149 asn1p_constraint_free(tmpct);
150 asn1p_expr_free(clone);
151 return NULL;
152 }
153 } else {
154 clone->constraints = tmpct;
155 }
Lev Walkin0c0bca62006-03-21 04:48:15 +0000156 assert(expr->combined_constraints == 0);
Lev Walkina00d6b32006-03-21 03:40:38 +0000157 }
Lev Walkin0c0bca62006-03-21 04:48:15 +0000158 /* Merge defaults */
159 CLCOPY(marker.flags);
160 CLVRCLONE(marker.default_value,
161 asn1p_value_clone_with_resolver);
162 if(clone->tag.tag_class == TC_NOCLASS) {
163 CLCOPY(tag);
164 } else if(expr->tag.tag_class != TC_NOCLASS) {
165 fprintf(stderr, "asn1c does not support "
166 "nested tagging in parameterization, "
167 "necessary at line %d\n",
168 expr->_lineno);
169 asn1p_expr_free(clone);
170 return NULL;
171 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000172 return clone;
173 } else if(errno != ESRCH) {
174 return NULL; /* Hard error */
175 }
176 }
Lev Walkina9532f42006-09-17 04:52:50 +0000177 if(!clone) clone = asn1p_expr_new(expr->_lineno, expr->module);
Lev Walkina00d6b32006-03-21 03:40:38 +0000178 if(!clone) return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000179
180 /*
181 * Copy simple fields.
182 */
183 CLCOPY(meta_type);
184 CLCOPY(expr_type);
185 CLCOPY(tag);
Lev Walkin5498f2d2004-09-15 11:59:30 +0000186 CLCOPY(marker.flags); /* OPTIONAL/DEFAULT */
Lev Walkinf15320b2004-06-03 03:38:44 +0000187 CLCOPY(_mark);
188
189 clone->data = 0; /* Do not clone this */
190 clone->data_free = 0; /* Do not clone this */
191
192 /*
193 * Clone complex fields.
194 */
195 CLCLONE(Identifier, strdup);
196 CLCLONE(reference, asn1p_ref_clone);
Lev Walkina00d6b32006-03-21 03:40:38 +0000197 CLVRCLONE(constraints, asn1p_constraint_clone_with_resolver);
198 CLVRCLONE(combined_constraints, asn1p_constraint_clone_with_resolver);
199 CLCLONE(lhs_params, asn1p_paramlist_clone);
200 CLVRCLONE(value, asn1p_value_clone_with_resolver);
Lev Walkin0c0bca62006-03-21 04:48:15 +0000201 CLVRCLONE(marker.default_value, asn1p_value_clone_with_resolver);
Lev Walkinf15320b2004-06-03 03:38:44 +0000202 CLCLONE(with_syntax, asn1p_wsyntx_clone);
203
204 /*
205 * Copy all the children of this expr.
206 */
207 TQ_FOR(tcmemb, &(expr->members), next) {
Lev Walkin070a52d2004-08-22 03:19:54 +0000208 asn1p_expr_t *cmemb;
209
210 if(skip_extensions
211 && tcmemb->expr_type == A1TC_EXTENSIBLE) {
212 hit_ext++; /* Even if hit_ext wraps around, we're OK. */
213 continue;
214 }
215 if(hit_ext == 1) continue; /* Skip between ...'s */
216
Lev Walkina00d6b32006-03-21 03:40:38 +0000217 cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
Lev Walkinf15320b2004-06-03 03:38:44 +0000218 if(cmemb == NULL) {
219 asn1p_expr_free(clone);
220 return NULL;
221 }
Lev Walkin1004aa92004-09-08 00:28:11 +0000222 asn1p_expr_add(clone, cmemb);
Lev Walkinf15320b2004-06-03 03:38:44 +0000223 }
224
225 return clone;
226}
227
Lev Walkina00d6b32006-03-21 03:40:38 +0000228
229static asn1p_value_t *
230value_resolver(asn1p_value_t *value, void *rarg) {
231 asn1p_value_t *cval;
232 asn1p_expr_t *tmpexpr;
233 asn1p_expr_t *target;
234 asn1p_ref_t *ref;
235 struct {
236 asn1p_expr_t *(*expr_resolve)(asn1p_expr_t *, void *arg);
237 } *varg = rarg;
238
239 if(!value || value->type != ATV_REFERENCED) {
240 errno = ESRCH;
241 return NULL;
242 }
243
244 ref = value->value.reference;
Lev Walkina9532f42006-09-17 04:52:50 +0000245 tmpexpr = asn1p_expr_new(ref->_lineno, 0);
Lev Walkina00d6b32006-03-21 03:40:38 +0000246 tmpexpr->meta_type = AMT_TYPEREF;
247 tmpexpr->expr_type = A1TC_REFERENCE;
248 tmpexpr->reference = ref;
249 target = varg->expr_resolve(tmpexpr, rarg);
250 tmpexpr->reference = 0;
251 asn1p_expr_free(tmpexpr);
252
253 if(!target)
254 return NULL; /* errno's are compatible */
255
Lev Walkin5045dfa2006-03-21 09:41:28 +0000256 if(target->meta_type == AMT_VALUE) {
257 if(!target->value) {
258 fprintf(stderr,
259 "FATAL: Parameterization did not resolve "
260 "value reference at line %d\n", ref->_lineno);
261 asn1p_expr_free(target);
262 errno = EPERM;
263 return NULL;
264 }
265 cval = asn1p_value_clone(target->value);
266 } else if(target->meta_type == AMT_VALUESET) {
267 if(!target->constraints) {
268 fprintf(stderr,
269 "FATAL: Parameterization did not resolve "
270 "value set reference at line %d\n", ref->_lineno);
271 asn1p_expr_free(target);
272 errno = EPERM;
273 return NULL;
274 }
275 cval = asn1p_value_fromconstr(target->constraints, 1);
276 } else {
Lev Walkina00d6b32006-03-21 03:40:38 +0000277 errno = EPERM;
Lev Walkin5045dfa2006-03-21 09:41:28 +0000278 cval = NULL;
Lev Walkina00d6b32006-03-21 03:40:38 +0000279 }
280
Lev Walkina00d6b32006-03-21 03:40:38 +0000281 asn1p_expr_free(target);
282 return cval;
283}
284
Lev Walkinf15320b2004-06-03 03:38:44 +0000285/*
Lev Walkin1004aa92004-09-08 00:28:11 +0000286 * Add expression as a member of another.
287 */
288void
289asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
290 TQ_ADD(&(to->members), what, next);
291 what->parent_expr = to;
292}
293
Lev Walkin0e90aa02013-03-19 16:17:13 -0700294/*
295 * Add inner expressions as members of another.
296 */
297void
298asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what) {
299 asn1p_expr_t *expr;
300 TQ_FOR(expr, &(from_what->members), next) {
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800301 expr->parent_expr = to;
302 }
Lev Walkin0e90aa02013-03-19 16:17:13 -0700303 TQ_CONCAT(&(to->members), &(from_what->members), next);
304}
305
Lev Walkin1004aa92004-09-08 00:28:11 +0000306
307/*
Lev Walkinf15320b2004-06-03 03:38:44 +0000308 * Destruct the types collection structure.
309 */
310void
311asn1p_expr_free(asn1p_expr_t *expr) {
312 if(expr) {
313 asn1p_expr_t *tm;
314
Bi-Ruei, Chiub9adfc52016-11-09 00:17:25 +0800315 if (expr->ref_cnt) {
316 /* Decrease reference count only */
317 expr->ref_cnt--;
318 return;
319 }
320
Lev Walkin1004aa92004-09-08 00:28:11 +0000321 /* Remove all children */
322 while((tm = TQ_REMOVE(&(expr->members), next))) {
323 if(tm->parent_expr != expr)
324 printf("<%s:%p !-> %s:%p>\n",
325 tm->Identifier, tm->parent_expr,
326 expr->Identifier, expr);
327 assert(tm->parent_expr == expr);
328 asn1p_expr_free(tm);
329 }
330
Lev Walkind8b83642016-03-14 02:00:27 -0700331 free(expr->Identifier);
Markus Elfring671eb9a2016-03-14 17:07:26 +0100332 asn1p_ref_free(expr->reference);
333 asn1p_constraint_free(expr->constraints);
334 asn1p_constraint_free(expr->combined_constraints);
335 asn1p_paramlist_free(expr->lhs_params);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800336 asn1p_expr_free(expr->rhs_pspecs);
Markus Elfring671eb9a2016-03-14 17:07:26 +0100337 asn1p_value_free(expr->value);
338 asn1p_value_free(expr->marker.default_value);
339 asn1p_wsyntx_free(expr->with_syntax);
Bi-Ruei, Chiu3dcf05b2017-05-04 21:45:05 +0800340 if(expr->specializations.pspec) {
341 int pspec;
342 for(pspec = 0; pspec < expr->specializations.pspecs_count; pspec++) {
343 asn1p_expr_free(expr->specializations.pspec[pspec].rhs_pspecs);
344 asn1p_expr_free(expr->specializations.pspec[pspec].my_clone);
345 }
346 free(expr->specializations.pspec);
347 }
Lev Walkin4dcf8362017-08-07 20:10:05 -0700348 asn1p_ioc_table_free(expr->ioc_table);
Lev Walkinf15320b2004-06-03 03:38:44 +0000349
Lev Walkinf15320b2004-06-03 03:38:44 +0000350 if(expr->data && expr->data_free)
351 expr->data_free(expr->data);
352
353 memset(expr, 0, sizeof(*expr));
354 free(expr);
355 }
356}
357
Lev Walkin71160962005-06-02 05:21:53 +0000358
Lev Walkina45518f2017-08-23 07:22:52 -0700359const char *asn1p_tag2string(const struct asn1p_type_tag_s *tag, char *buf) {
Lev Walkin8f294e02005-06-06 08:28:58 +0000360 static char buf_stat[TAG2STRING_BUFFER_SIZE];
Lev Walkin71160962005-06-02 05:21:53 +0000361 char *start;
362 char *end;
363
364 if(!buf) buf = buf_stat;
365 start = buf;
366 end = buf + TAG2STRING_BUFFER_SIZE;
367
368 if(tag->tag_class == TC_NOCLASS) {
369 *buf = 0;
370 return buf;
371 }
372
373 strcpy(buf, "[");
374 switch(tag->tag_class) {
375 case TC_NOCLASS:
376 assert(tag->tag_class != TC_NOCLASS);
377 break;
378 case TC_UNIVERSAL: strcat(buf, "UNIVERSAL "); break;
379 case TC_PRIVATE: strcat(buf, "PRIVATE "); break;
380 case TC_APPLICATION: strcat(buf, "APPLICATION "); break;
381 case TC_CONTEXT_SPECIFIC:
382 break;
383 }
384 buf += snprintf(buf + strlen(buf), end - buf,
Lev Walkinda997b12017-08-04 01:38:41 -0700385 "%s]", asn1p_itoa(tag->tag_value));
Lev Walkin8f294e02005-06-06 08:28:58 +0000386 assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
Lev Walkin71160962005-06-02 05:21:53 +0000387
388 switch(tag->tag_mode) {
389 case TM_DEFAULT: break;
390 case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
391 case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
392 }
393
394 return start;
395}
Lev Walkinc0e03b92017-08-22 01:48:23 -0700396
397asn1p_paramlist_t *
398asn1p_get_namespace(asn1p_expr_t *expr) {
399 if(!expr) return NULL;
400 if(expr->lhs_params) return expr->lhs_params;
401 return asn1p_get_namespace(expr->parent_expr);
402}