blob: 505f2606300631c24d88d459bcefa26d37d3b87f [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
Lev Walkinc0e03b92017-08-22 01:48:23 -07002#include <asn1_namespace.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00003
Lev Walkin8945e0e2004-09-10 06:07:04 +00004#define ADD_TAG(skip, newtag) do { \
5 void *__p; \
Lev Walkin188ed2c2004-09-13 08:31:01 +00006 if(skip && !(flags & AFT_FULL_COLLECT)) { \
Lev Walkin906654e2004-09-10 15:49:15 +00007 if(newtag.tag_mode != TM_IMPLICIT) \
8 skip--; \
9 break; \
10 } else { \
11 if(newtag.tag_mode == TM_IMPLICIT) \
12 skip++; \
13 } \
Lev Walkin8945e0e2004-09-10 06:07:04 +000014 __p = realloc((*tags), \
15 sizeof(struct asn1p_type_tag_s) * (count + 1)); \
16 if(!__p) return -1; \
17 *tags = __p; \
18 (*tags)[count++] = newtag; \
19 if((flags & AFT_FETCH_OUTMOST)) return count; \
Lev Walkin8945e0e2004-09-10 06:07:04 +000020} while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000021
Lev Walkin59b176e2005-11-26 11:25:14 +000022/* X.691, #22.2 */
23static int asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags);
24
Lev Walkin8945e0e2004-09-10 06:07:04 +000025static int
26asn1f_fetch_tags_impl(arg_t *arg, struct asn1p_type_tag_s **tags, int count, int skip, enum asn1f_aft_flags_e flags) {
27 asn1p_expr_t *expr = arg->expr;
Lev Walkinf15320b2004-06-03 03:38:44 +000028
Lev Walkin9c2285a2006-03-09 08:49:26 +000029 DEBUG("Fetching tag from %s: meta %d, type %s", expr->Identifier,
30 expr->meta_type, expr->expr_type);
31
Lev Walkin8945e0e2004-09-10 06:07:04 +000032 /* If this type is tagged, add this tag first */
33 if(expr->tag.tag_class != TC_NOCLASS)
34 ADD_TAG(skip, expr->tag);
35
36 /* REMOVE ME */
Lev Walkinf15320b2004-06-03 03:38:44 +000037 if(expr->expr_type == A1TC_EXTENSIBLE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000038 struct asn1p_type_tag_s tt;
39 memset(&tt, 0, sizeof(tt));
40 tt.tag_class = -1;
41 ADD_TAG(skip, tt);
42 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000043 }
44
45 if(expr->meta_type == AMT_TYPE) {
Lev Walkin8945e0e2004-09-10 06:07:04 +000046 struct asn1p_type_tag_s tt;
47 memset(&tt, 0, sizeof(tt));
48 tt.tag_class = TC_UNIVERSAL;
49 tt.tag_value = expr_type2uclass_value[expr->expr_type];
50 if(tt.tag_value == 0) {
51 if(expr->expr_type == ASN_TYPE_ANY
52 && (flags & AFT_IMAGINARY_ANY))
53 tt.tag_value = -1;
Lev Walkin59b176e2005-11-26 11:25:14 +000054 else if(expr->expr_type != ASN_CONSTR_CHOICE)
55 return -1;
56 else if(count) return count;
57 else if((flags & AFT_CANON_CHOICE) == 0)
58 return -1;
59 else if(asn1f_fetch_minimal_choice_root_tag(arg,
60 &tt, flags))
Lev Walkin8945e0e2004-09-10 06:07:04 +000061 return -1;
Lev Walkind541c252004-09-05 10:36:22 +000062 }
Lev Walkin8945e0e2004-09-10 06:07:04 +000063 ADD_TAG(skip, tt);
64 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +000065 }
66
67 if(expr->meta_type == AMT_TYPEREF) {
Lev Walkin906654e2004-09-10 15:49:15 +000068 asn1p_expr_t *nexpr;
Lev Walkin59b176e2005-11-26 11:25:14 +000069 DEBUG("Following the reference %s", expr->Identifier);
Lev Walkinc0e03b92017-08-22 01:48:23 -070070 nexpr = asn1f_lookup_symbol(arg, expr->rhs_pspecs, expr->reference);
Lev Walkin906654e2004-09-10 15:49:15 +000071 if(nexpr == NULL) {
72 if(errno != EEXIST) /* -fknown-extern-type */
73 return -1;
74 if(!count)
75 return 0; /* OK */
76 if((*tags)[count-1].tag_mode == TM_IMPLICIT) {
77 WARNING("Tagging mode for %s "
78 "is IMPLICIT, assuming %s "
79 "has exactly one tag",
80 expr->Identifier,
81 asn1f_printable_reference(expr->reference)
82 );
83 return count;
84 }
85 FATAL("Tagging mode %s -> %s "
86 "dangerously incompatible",
87 expr->Identifier,
88 asn1f_printable_reference(expr->reference)
89 );
90 return -1;
91 } else {
92 arg->expr = nexpr;
93 }
Lev Walkinf15320b2004-06-03 03:38:44 +000094 if(expr->_mark & TM_RECURSION)
95 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +000096 expr->_mark |= TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000097 count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000098 expr->_mark &= ~TM_RECURSION;
Lev Walkin8945e0e2004-09-10 06:07:04 +000099 return count;
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 }
101
Lev Walkin59b176e2005-11-26 11:25:14 +0000102 DEBUG("No tags discovered for type %d", expr->expr_type);
103
Lev Walkinf15320b2004-06-03 03:38:44 +0000104 return -1;
105}
106
Lev Walkin59b176e2005-11-26 11:25:14 +0000107static int
108asn1f_fetch_minimal_choice_root_tag(arg_t *arg, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
109 struct asn1p_type_tag_s min_tag;
110 asn1p_expr_t *v;
111
112 memset(&min_tag, 0, sizeof(min_tag));
113 min_tag.tag_class = TC_PRIVATE + 1;
114
115 TQ_FOR(v, &(arg->expr->members), next) {
116 arg_t tmparg = *arg;
117 struct asn1p_type_tag_s *tags = 0;
118 int count;
119
120 if(v->expr_type == A1TC_EXTENSIBLE)
121 break; /* Search only within extension root */
122
123 tmparg.expr = v;
124 count = asn1f_fetch_tags_impl(&tmparg, &tags, 0, 0, flags);
125 if(count <= 0) continue;
126
127 if(tags[0].tag_class < min_tag.tag_class)
128 min_tag = tags[0];
129 else if(tags[0].tag_class == min_tag.tag_class
130 && tags[0].tag_value < min_tag.tag_value)
131 min_tag = tags[0];
132 free(tags);
133 }
134
135 if(min_tag.tag_class == TC_PRIVATE + 1)
136 return -1;
137 else
138 *tag = min_tag;
139 return 0;
140}
Lev Walkin8945e0e2004-09-10 06:07:04 +0000141
142int
Lev Walkinc0e03b92017-08-22 01:48:23 -0700143asn1f_fetch_outmost_tag(asn1p_t *asn, asn1_namespace_t *ns, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s *tag, enum asn1f_aft_flags_e flags) {
Lev Walkin8945e0e2004-09-10 06:07:04 +0000144 struct asn1p_type_tag_s *tags;
Lev Walkin8945e0e2004-09-10 06:07:04 +0000145 int count;
146
Lev Walkin59b176e2005-11-26 11:25:14 +0000147 flags |= AFT_FETCH_OUTMOST;
Lev Walkin8945e0e2004-09-10 06:07:04 +0000148
Lev Walkinc0e03b92017-08-22 01:48:23 -0700149 count = asn1f_fetch_tags(asn, ns, mod, expr, &tags, flags);
Lev Walkin8945e0e2004-09-10 06:07:04 +0000150 if(count <= 0) return count;
151
152 *tag = tags[0];
153 free(tags);
154
155 return 0;
156}
157
158int
Lev Walkinc0e03b92017-08-22 01:48:23 -0700159asn1f_fetch_tags(asn1p_t *asn, asn1_namespace_t *ns, asn1p_module_t *mod, asn1p_expr_t *expr, struct asn1p_type_tag_s **tags_r, enum asn1f_aft_flags_e flags) {
Lev Walkin8945e0e2004-09-10 06:07:04 +0000160 arg_t arg;
161 struct asn1p_type_tag_s *tags = 0;
162 int count;
163
164 memset(&arg, 0, sizeof(arg));
165 arg.asn = asn;
Lev Walkinc0e03b92017-08-22 01:48:23 -0700166 arg.ns = ns;
Lev Walkin8945e0e2004-09-10 06:07:04 +0000167 arg.mod = mod;
168 arg.expr = expr;
169
170 count = asn1f_fetch_tags_impl(&arg, &tags, 0, 0, flags);
Markus Elfringf3d18612016-03-15 08:35:24 +0100171 if (count <= 0) {
Lev Walkin8945e0e2004-09-10 06:07:04 +0000172 free(tags);
173 tags = 0;
174 }
175 *tags_r = tags;
176 return count;
177}