NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1parser / asn1p_expr.c
1 #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
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);
11
12 void
13 asn1p_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
31 int
32 asn1p_expr_compare(const asn1p_expr_t *a, const asn1p_expr_t *b) {
33     if((a && !b) || (!a && b)) {
34         return -1;
35     }
36
37     if(a->meta_type != b->meta_type || a->expr_type != b->expr_type) {
38         return -1;
39     }
40
41     if((!a->Identifier && b->Identifier) || (a->Identifier && !b->Identifier)) {
42         return -1;
43     } else if(a->Identifier && strcmp(a->Identifier, b->Identifier)) {
44         return -1;
45     }
46
47     if((!a->reference && b->reference) || (a->reference && !b->reference)) {
48         return -1;
49     } else if(a->reference
50               && asn1p_ref_compare(a->reference, b->reference) != 0) {
51         return -1;
52     }
53
54     if((!a->value && b->value) || (a->value && !b->value)) {
55         return -1;
56     } else if(a->value && asn1p_value_compare(a->value, b->value)) {
57         return -1;
58     }
59
60     if((!a->constraints && b->constraints) || (a->constraints && !b->constraints)) {
61         return -1;
62     } else if(a->constraints && asn1p_constraint_compare(a->constraints, b->constraints)) {
63         return -1;
64     }
65
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)) {
69         return -1;
70     }
71
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))) {
78         return -1;
79     }
80
81     if(a->unique != b->unique) {
82         return -1;
83     }
84
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)) {
89             return -1;
90         } else if(asn1p_expr_compare(am, bm) != 0) {
91             return -1;
92         }
93     }
94
95     return 0;
96 }
97
98 /*
99  * Construct a new empty types collection.
100  */
101 asn1p_expr_t *
102 asn1p_expr_new(int _lineno, asn1p_module_t *mod) {
103         asn1p_expr_t *expr;
104
105         expr = calloc(1, sizeof *expr);
106         if(expr) {
107                 TQ_INIT(&(expr->members));
108                 expr->spec_index = -1;
109                 expr->module = mod;
110                 expr->_lineno = _lineno;
111                 expr->ref_cnt = 0;
112         }
113
114         return expr;
115 }
116
117 asn1p_expr_t *
118 asn1p_expr_clone(asn1p_expr_t *expr, int skip_extensions) {
119         return asn1p_expr_clone_impl(expr, skip_extensions, 0, 0);
120 }
121
122 asn1p_expr_t *
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);
125 }
126
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 */
132         int hit_ext = 0;
133
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);                 \
139                                 return NULL;                            \
140                         }                                               \
141                 } } while(0)
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);                 \
146                                 return NULL;                            \
147                         }                                               \
148                 } } while(0)
149
150         if(r) {
151                 vr = value_resolver;
152                 clone = r(expr, rarg);
153                 if(clone) {
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);
161                                                 return NULL;
162                                         }
163                                 } else {
164                                         clone->constraints = tmpct;
165                                 }
166                                 assert(expr->combined_constraints == 0);
167                         }
168                         /* Merge defaults */
169                         CLCOPY(marker.flags);
170                         CLVRCLONE(marker.default_value,
171                                 asn1p_value_clone_with_resolver);
172                         if(clone->tag.tag_class == TC_NOCLASS) {
173                                 CLCOPY(tag);
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",
178                                         expr->_lineno);
179                                 asn1p_expr_free(clone);
180                                 return NULL;
181                         }
182                         return clone;
183                 } else if(errno != ESRCH) {
184                         return NULL;    /* Hard error */
185                 }
186         }
187         if(!clone) clone = asn1p_expr_new(expr->_lineno, expr->module);
188         if(!clone) return NULL;
189
190         /*
191          * Copy simple fields.
192          */
193         CLCOPY(meta_type);
194         CLCOPY(expr_type);
195         CLCOPY(tag);
196         CLCOPY(marker.flags);           /* OPTIONAL/DEFAULT */
197         CLCOPY(_mark);
198         CLCOPY(parent_expr);
199         CLCOPY(_type_unique_index);
200
201         clone->data = 0;        /* Do not clone this */
202         clone->data_free = 0;   /* Do not clone this */
203
204         /*
205          * Clone complex fields.
206          */
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);
215
216         /*
217          * Copy all the children of this expr.
218          */
219         TQ_FOR(tcmemb, &(expr->members), next) {
220                 asn1p_expr_t *cmemb;
221
222                 if(skip_extensions
223                 && tcmemb->expr_type == A1TC_EXTENSIBLE) {
224                         hit_ext++; /* Even if hit_ext wraps around, we're OK. */
225                         continue;
226                 }
227                 if(hit_ext == 1) continue;      /* Skip between ...'s */
228
229                 cmemb = asn1p_expr_clone_impl(tcmemb, skip_extensions, r, rarg);
230                 if(cmemb == NULL) {
231                         asn1p_expr_free(clone);
232                         return NULL;
233                 }
234                 asn1p_expr_add(clone, cmemb);
235         }
236
237         return clone;
238 }
239
240
241 static asn1p_value_t *
242 value_resolver(asn1p_value_t *value, void *rarg) {
243         asn1p_value_t *cval;
244         asn1p_expr_t *tmpexpr;
245         asn1p_expr_t *target;
246         asn1p_ref_t *ref;
247         struct {
248                 asn1p_expr_t *(*expr_resolve)(asn1p_expr_t *, void *arg);
249         } *varg = rarg;
250
251         if(!value || value->type != ATV_REFERENCED) {
252                 errno = ESRCH;
253                 return NULL;
254         }
255
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);
264
265         if(!target)
266                 return NULL;    /* errno's are compatible */
267
268         if(target->meta_type == AMT_VALUE) {
269                 if(!target->value) {
270                         fprintf(stderr,
271                         "FATAL: Parameterization did not resolve "
272                         "value reference at line %d\n", ref->_lineno);
273                         asn1p_expr_free(target);
274                         errno = EPERM;
275                         return NULL;
276                 }
277                 cval = asn1p_value_clone(target->value);
278         } else if(target->meta_type == AMT_VALUESET) {
279                 if(!target->constraints) {
280                         fprintf(stderr,
281                         "FATAL: Parameterization did not resolve "
282                         "value set reference at line %d\n", ref->_lineno);
283                         asn1p_expr_free(target);
284                         errno = EPERM;
285                         return NULL;
286                 }
287                 cval = asn1p_value_fromconstr(target->constraints, 1);
288         } else {
289                 errno = EPERM;
290                 cval = NULL;
291         }
292
293         asn1p_expr_free(target);
294         return cval;
295 }
296
297 /*
298  * Add expression as a member of another.
299  */
300 void
301 asn1p_expr_add(asn1p_expr_t *to, asn1p_expr_t *what) {
302         TQ_ADD(&(to->members), what, next);
303         what->parent_expr = to;
304 }
305
306 /*
307  * Add inner expressions as members of another.
308  */
309 void
310 asn1p_expr_add_many(asn1p_expr_t *to, asn1p_expr_t *from_what) {
311         asn1p_expr_t *expr;
312         TQ_FOR(expr, &(from_what->members), next) {
313                 expr->parent_expr = to;
314         }
315         TQ_CONCAT(&(to->members), &(from_what->members), next);
316 }
317
318 /*
319  * Lookup a child by its name.
320  */
321 asn1p_expr_t *
322 asn1p_lookup_child(asn1p_expr_t *tc, const char *name) {
323         asn1p_expr_t *child_tc;
324
325         TQ_FOR(child_tc, &(tc->members), next) {
326                 if(child_tc->Identifier
327                 && strcmp(child_tc->Identifier, name) == 0) {
328                         return child_tc;
329                 }
330         }
331
332         errno = ESRCH;
333         return NULL;
334 }
335
336 /*
337  * Destruct the types collection structure.
338  */
339 void
340 asn1p_expr_free(asn1p_expr_t *expr) {
341         if(expr) {
342                 asn1p_expr_t *tm;
343
344                 if (expr->ref_cnt) {
345                         /* Decrease reference count only */
346                         expr->ref_cnt--;
347                         return;
348                 }
349
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);
357                         asn1p_expr_free(tm);
358                 }
359
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) {
370                         int 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);
374                         }
375                         free(expr->specializations.pspec);
376                 }
377                 asn1p_ioc_table_free(expr->ioc_table);
378
379                 if(expr->data && expr->data_free)
380                         expr->data_free(expr->data);
381
382                 memset(expr, 0, sizeof(*expr));
383                 free(expr);
384         }
385 }
386
387
388 const char *asn1p_tag2string(const struct asn1p_type_tag_s *tag, char *buf) {
389         static char buf_stat[TAG2STRING_BUFFER_SIZE];
390         char *start;
391         char *end;
392
393         if(!buf) buf = buf_stat;
394         start = buf;
395         end = buf + TAG2STRING_BUFFER_SIZE;
396
397         if(tag->tag_class == TC_NOCLASS) {
398                 *buf = 0;
399                 return buf;
400         }
401
402         strcpy(buf, "[");
403         switch(tag->tag_class) {
404         case TC_NOCLASS:
405                 assert(tag->tag_class != TC_NOCLASS);
406                 break;
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:
411                 break;
412         }
413         buf += snprintf(buf + strlen(buf), end - buf,
414                 "%s]", asn1p_itoa(tag->tag_value));
415         assert((unsigned int)(buf - end) > sizeof(" IMPLICIT "));
416
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;
421         }
422
423         return start;
424 }
425
426 asn1p_paramlist_t *
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);
431 }