7 #include "asn1parser.h"
9 static asn1p_expr_t *asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*)(asn1p_expr_t *, void *), void *);
10 static asn1p_value_t *value_resolver(asn1p_value_t *, void *arg);
13 asn1p_expr_set_source(asn1p_expr_t *expr, asn1p_module_t *module, int lineno) {
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);
25 TQ_FOR(memb, &(expr->members), next) {
26 asn1p_expr_set_source(memb, module, lineno);
32 asn1p_expr_compare(const asn1p_expr_t *a, const asn1p_expr_t *b) {
33 if((a && !b) || (!a && b)) {
37 if(a->meta_type != b->meta_type || a->expr_type != b->expr_type) {
41 if((!a->Identifier && b->Identifier) || (a->Identifier && !b->Identifier)) {
43 } else if(a->Identifier && strcmp(a->Identifier, b->Identifier)) {
47 if((!a->reference && b->reference) || (a->reference && !b->reference)) {
49 } else if(a->reference
50 && asn1p_ref_compare(a->reference, b->reference) != 0) {
54 if((!a->value && b->value) || (a->value && !b->value)) {
56 } else if(a->value && asn1p_value_compare(a->value, b->value)) {
60 if((!a->constraints && b->constraints) || (a->constraints && !b->constraints)) {
62 } else if(a->constraints && asn1p_constraint_compare(a->constraints, b->constraints)) {
66 if((a->tag.tag_class != b->tag.tag_class)
67 || (a->tag.tag_mode != b->tag.tag_mode)
68 || (a->tag.tag_value != b->tag.tag_value)) {
72 if((a->marker.flags != b->marker.flags)
73 || (a->marker.default_value && !b->marker.default_value)
74 || (!a->marker.default_value && b->marker.default_value)
75 || (a->marker.default_value
76 && asn1p_value_compare(a->marker.default_value,
77 b->marker.default_value))) {
81 if(a->unique != b->unique) {
85 const asn1p_expr_t *am = TQ_FIRST(&a->members);
86 const asn1p_expr_t *bm = TQ_FIRST(&b->members);
87 for(; am || bm; am = TQ_NEXT(am, next), bm = TQ_NEXT(bm, next)) {
88 if((am && !bm) || (!am && bm)) {
90 } else if(asn1p_expr_compare(am, bm) != 0) {
99 * Construct a new empty types collection.
102 asn1p_expr_new(int _lineno, asn1p_module_t *mod) {
105 expr = calloc(1, sizeof *expr);
107 TQ_INIT(&(expr->members));
108 expr->spec_index = -1;
110 expr->_lineno = _lineno;
118 asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
119 return asn1p_expr_clone_impl(expr, skip_extensions, 0, 0);
123 asn1p_expr_clone_with_resolver(asn1p_expr_t *expr, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
124 return asn1p_expr_clone_impl(expr, 0, r, rarg);
127 static asn1p_expr_t *
128 asn1p_expr_clone_impl(asn1p_expr_t *expr, int skip_extensions, asn1p_expr_t *(*r)(asn1p_expr_t *, void *), void *rarg) {
129 asn1p_value_t *(*vr)(asn1p_value_t *, void *) = 0;
130 asn1p_expr_t *clone = 0;
131 asn1p_expr_t *tcmemb; /* Child of tc */
134 #define CLCOPY(field) do { clone->field = expr->field; } while(0)
135 #define CLCLONE(field, func) do { if(expr->field) { \
136 clone->field = func(expr->field); \
137 if(clone->field == NULL) { \
138 asn1p_expr_free(clone); \
142 #define CLVRCLONE(field, func) do { if(expr->field) { \
143 clone->field = func(expr->field, vr, rarg); \
144 if(clone->field == NULL) { \
145 asn1p_expr_free(clone); \
152 clone = r(expr, rarg);
154 /* Merge constraints */
155 if(expr->constraints) {
156 asn1p_constraint_t *tmpct = asn1p_constraint_clone_with_resolver(expr->constraints, vr, rarg);
157 if(clone->constraints) {
158 if(asn1p_constraint_insert(clone->constraints, tmpct)) {
159 asn1p_constraint_free(tmpct);
160 asn1p_expr_free(clone);
164 clone->constraints = tmpct;
166 assert(expr->combined_constraints == 0);
169 CLCOPY(marker.flags);
170 CLVRCLONE(marker.default_value,
171 asn1p_value_clone_with_resolver);
172 if(clone->tag.tag_class == TC_NOCLASS) {
174 } else if(expr->tag.tag_class != TC_NOCLASS) {
175 fprintf(stderr, "asn1c does not support "
176 "nested tagging in parameterization, "
177 "necessary at line %d\n",
179 asn1p_expr_free(clone);
183 } else if(errno != ESRCH) {
184 return NULL; /* Hard error */
187 if(!clone) clone = asn1p_expr_new(expr->_lineno, expr->module);
188 if(!clone) return NULL;
191 * Copy simple fields.
196 CLCOPY(marker.flags); /* OPTIONAL/DEFAULT */
199 CLCOPY(_type_unique_index);
201 clone->data = 0; /* Do not clone this */
202 clone->data_free = 0; /* Do not clone this */
205 * Clone complex fields.
207 CLCLONE(Identifier, strdup);
208 CLCLONE(reference, asn1p_ref_clone);
209 CLVRCLONE(constraints, asn1p_constraint_clone_with_resolver);
210 CLVRCLONE(combined_constraints, asn1p_constraint_clone_with_resolver);
211 CLCLONE(lhs_params, asn1p_paramlist_clone);
212 CLVRCLONE(value, asn1p_value_clone_with_resolver);
213 CLVRCLONE(marker.default_value, asn1p_value_clone_with_resolver);
214 CLCLONE(with_syntax, asn1p_wsyntx_clone);
217 * Copy all the children of this expr.
219 TQ_FOR(tcmemb, &(expr->members), next) {
223 && tcmemb->expr_type == A1TC_EXTENSIBLE) {
224 hit_ext++; /* Even if hit_ext wraps around, we're OK. */
227 if(hit_ext == 1) continue; /* Skip between ...'s */
229 cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
231 asn1p_expr_free(clone);
234 asn1p_expr_add(clone, cmemb);
241 static asn1p_value_t *
242 value_resolver(asn1p_value_t *value, void *rarg) {
244 asn1p_expr_t *tmpexpr;
245 asn1p_expr_t *target;
248 asn1p_expr_t *(*expr_resolve)(asn1p_expr_t *, void *arg);
251 if(!value || value->type != ATV_REFERENCED) {
256 ref = value->value.reference;
257 tmpexpr = asn1p_expr_new(ref->_lineno, 0);
258 tmpexpr->meta_type = AMT_TYPEREF;
259 tmpexpr->expr_type = A1TC_REFERENCE;
260 tmpexpr->reference = ref;
261 target = varg->expr_resolve(tmpexpr, rarg);
262 tmpexpr->reference = 0;
263 asn1p_expr_free(tmpexpr);
266 return NULL; /* errno's are compatible */
268 if(target->meta_type == AMT_VALUE) {
271 "FATAL: Parameterization did not resolve "
272 "value reference at line %d\n", ref->_lineno);
273 asn1p_expr_free(target);
277 cval = asn1p_value_clone(target->value);
278 } else if(target->meta_type == AMT_VALUESET) {
279 if(!target->constraints) {
281 "FATAL: Parameterization did not resolve "
282 "value set reference at line %d\n", ref->_lineno);
283 asn1p_expr_free(target);
287 cval = asn1p_value_fromconstr(target->constraints, 1);
293 asn1p_expr_free(target);
298 * Add expression as a member of another.
301 asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
302 TQ_ADD(&(to->members), what, next);
303 what->parent_expr = to;
307 * Add inner expressions as members of another.
310 asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what) {
312 TQ_FOR(expr, &(from_what->members), next) {
313 expr->parent_expr = to;
315 TQ_CONCAT(&(to->members), &(from_what->members), next);
319 * Lookup a child by its name.
322 asn1p_lookup_child(asn1p_expr_t *tc, const char *name) {
323 asn1p_expr_t *child_tc;
325 TQ_FOR(child_tc, &(tc->members), next) {
326 if(child_tc->Identifier
327 && strcmp(child_tc->Identifier, name) == 0) {
337 * Destruct the types collection structure.
340 asn1p_expr_free(asn1p_expr_t *expr) {
345 /* Decrease reference count only */
350 /* Remove all children */
351 while((tm = TQ_REMOVE(&(expr->members), next))) {
352 if(tm->parent_expr != expr)
353 printf("<%s:%p !-> %s:%p>\n",
354 tm->Identifier, tm->parent_expr,
355 expr->Identifier, expr);
356 assert(tm->parent_expr == expr);
360 free(expr->Identifier);
361 asn1p_ref_free(expr->reference);
362 asn1p_constraint_free(expr->constraints);
363 asn1p_constraint_free(expr->combined_constraints);
364 asn1p_paramlist_free(expr->lhs_params);
365 asn1p_expr_free(expr->rhs_pspecs);
366 asn1p_value_free(expr->value);
367 asn1p_value_free(expr->marker.default_value);
368 asn1p_wsyntx_free(expr->with_syntax);
369 if(expr->specializations.pspec) {
371 for(pspec = 0; pspec < expr->specializations.pspecs_count; pspec++) {
372 asn1p_expr_free(expr->specializations.pspec[pspec].rhs_pspecs);
373 asn1p_expr_free(expr->specializations.pspec[pspec].my_clone);
375 free(expr->specializations.pspec);
377 asn1p_ioc_table_free(expr->ioc_table);
379 if(expr->data && expr->data_free)
380 expr->data_free(expr->data);
382 memset(expr, 0, sizeof(*expr));
388 const char *asn1p_tag2string(const struct asn1p_type_tag_s *tag, char *buf) {
389 static char buf_stat[TAG2STRING_BUFFER_SIZE];
393 if(!buf) buf = buf_stat;
395 end = buf + TAG2STRING_BUFFER_SIZE;
397 if(tag->tag_class == TC_NOCLASS) {
403 switch(tag->tag_class) {
405 assert(tag->tag_class != TC_NOCLASS);
407 case TC_UNIVERSAL: strcat(buf, "UNIVERSAL "); break;
408 case TC_PRIVATE: strcat(buf, "PRIVATE "); break;
409 case TC_APPLICATION: strcat(buf, "APPLICATION "); break;
410 case TC_CONTEXT_SPECIFIC:
413 buf += snprintf(buf + strlen(buf), end - buf,
414 "%s]", asn1p_itoa(tag->tag_value));
415 assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
417 switch(tag->tag_mode) {
418 case TM_DEFAULT: break;
419 case TM_IMPLICIT: strcat(buf, " IMPLICIT"); break;
420 case TM_EXPLICIT: strcat(buf, " EXPLICIT"); break;
427 asn1p_get_namespace(asn1p_expr_t *expr) {
428 if(!expr) return NULL;
429 if(expr->lhs_params) return expr->lhs_params;
430 return asn1p_get_namespace(expr->parent_expr);