blob: f3d5ad7314cf842f384fdd5580cfa327b6d6266b [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
vlmb9cdbb12006-08-28 02:12:49 +00003static int asn1f_fix_bit_string_type(arg_t *arg);
4static int asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype);
vlmfa67ddc2004-06-03 03:38:44 +00005static void asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value);
6static int asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype);
7
8int
9asn1f_fix_bit_string(arg_t *arg) {
10 asn1p_expr_t *expr = arg->expr;
11 int r_value = 0;
12 int ret;
13
14 if(expr->meta_type == AMT_VALUE) {
15 asn1p_expr_t *ttype;
16
vlmfd245932005-03-10 10:02:50 +000017 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
vlmfa67ddc2004-06-03 03:38:44 +000018
vlm2e0c1942004-08-22 03:10:23 +000019 ttype = asn1f_find_terminal_type(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +000020 if(ttype && ttype->expr_type == ASN_BASIC_BIT_STRING) {
21 ret = asn1f_fix_bit_string_value(arg, ttype);
22 RET2RVAL(ret, r_value);
23 }
24 }
25
vlmb9cdbb12006-08-28 02:12:49 +000026 if(expr->meta_type == AMT_TYPE
27 && expr->expr_type == ASN_BASIC_BIT_STRING) {
28 ret = asn1f_fix_bit_string_type(arg);
29 RET2RVAL(ret, r_value);
30 }
31
vlmfa67ddc2004-06-03 03:38:44 +000032 return r_value;
33}
34
vlmb9cdbb12006-08-28 02:12:49 +000035static int
36asn1f_fix_bit_string_type(arg_t *arg) {
37 asn1p_expr_t *expr = arg->expr;
38 asn1p_expr_t *v;
vlmadf419b2006-08-28 02:24:24 +000039 int r_value = 0;
40 int ret;
vlmb9cdbb12006-08-28 02:12:49 +000041
42 TQ_FOR(v, &(expr->members), next) {
vlmadf419b2006-08-28 02:24:24 +000043 /* Check identifier uniqueness as per 21.4 */
44 ret = asn1f_check_unique_expr_child(arg, v, 0);
45 RET2RVAL(ret, r_value);
46
47 if(v->expr_type == A1TC_EXTENSIBLE) {
48 FATAL("Extension marker (...) is not allowed "
49 "as a BIT STRING NamedBit at line %d ",
50 v->_lineno);
51 return -1;
52 }
vlmb9cdbb12006-08-28 02:12:49 +000053 if(v->expr_type != A1TC_UNIVERVAL) {
54 FATAL("BIT STRING value at line %d "
vlmadf419b2006-08-28 02:24:24 +000055 "is not an identifier", v->_lineno);
vlmb9cdbb12006-08-28 02:12:49 +000056 return -1;
57 }
vlmf04c7952006-08-28 02:30:41 +000058
59 /* 21.1 */
60 if(v->value == NULL) {
61 FATAL("BIT STRING NamedBit value at line %d "
62 "must be explicitly specified in braces",
63 v->_lineno);
64 return -1;
65 } else if(v->value->type == ATV_REFERENCED) {
66 /* Resolve the value */
67 if(asn1f_value_resolve(arg, v, 0))
68 return -1;
69 }
70 if(v->value->type != ATV_INTEGER
71 || v->value->value.v_integer < 0) {
72 FATAL("BIT STRING NamedBit value at line %d: "
73 "non-negative integer value expected",
74 v->_lineno);
75 return -1;
76 }
vlmb9cdbb12006-08-28 02:12:49 +000077 }
78
vlmadf419b2006-08-28 02:24:24 +000079 return r_value;
vlmb9cdbb12006-08-28 02:12:49 +000080}
81
82static int
vlmfa67ddc2004-06-03 03:38:44 +000083asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype) {
84 asn1p_expr_t *expr = arg->expr;
85 int r_value = 0;
86
vlmfd245932005-03-10 10:02:50 +000087 DEBUG("(%s) for line %d",
vlmfa67ddc2004-06-03 03:38:44 +000088 expr->Identifier, expr->_lineno);
89
90 switch(expr->value->type) {
91 case ATV_UNPARSED:
92 /*
93 * Most definitely we have something like
94 * value BitStringType1 ::= { a, b, c }
95 * which could not be parsed by the LALR parser, mostly
96 * because it requires knowledge about BitStringType1
97 * during the parsing. So, here's a little hack: we create
98 * a buffer containing the full specification of a module,
99 * which contains some pre-defined INTEGER type with the
100 * opaque definition "{ a, b, c }" from the bit string.
101 */
102 if(asn1f_BS_unparsed_convert(arg, expr->value, ttype)) {
103 r_value = -1;
104 break;
105 }
106 /* Fall through: remove trailing zero bits */
107 case ATV_BITVECTOR:
108 asn1f_BS_remove_trailing_zero_bits(expr->value);
109 break;
110 default:
111 break;
112 }
113
114 return r_value;
115}
116
117static void
118asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value) {
119 int lmfb = -1; /* Last meaningful byte position */
120 int bits; /* Number of bits in the BIT STRING value */
121 int b;
122
123 assert(value->type == ATV_BITVECTOR);
124
125 bits = value->value.binary_vector.size_in_bits;
126 /*
127 * Figure out the rightmost meaningful byte.
128 */
129 for(b = 0; b < ((bits + 7) >> 3); b++) {
130 uint8_t uc = value->value.binary_vector.bits[b];
131 if(uc && b > lmfb)
132 lmfb = b;
133 }
134 if(lmfb == -1) {
135 bits = 0;
136 } else {
137 uint8_t uc;
138 uc = value->value.binary_vector.bits[lmfb];
139 bits = (lmfb+1) * 8;
140 /*
141 * Squeeze the bit string width until the rightmost
142 * bit is set.
143 */
144 for(; uc && (uc & 1) == 0; uc >>= 1)
145 bits--;
146 if(uc == 0) {
147 bits = lmfb * 8;
148 }
149 }
150 value->value.binary_vector.size_in_bits = bits;
151}
152
153static int
154asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype) {
155 asn1p_t *asn;
156 asn1p_module_t *mod;
157 asn1p_expr_t *V;
158 asn1p_expr_t *bit;
vlmd5b3bf32004-09-29 13:17:17 +0000159 asn1c_integer_t aI;
vlmfa67ddc2004-06-03 03:38:44 +0000160 uint8_t *bitbuf;
161 int bits;
162 int psize;
163 char *p;
164 int ret;
165 int r_value = 0;
166
167 assert(value->type == ATV_UNPARSED);
168
169 psize = value->value.string.size + 64;
170 p = malloc(psize);
171 if(p == NULL)
172 return -1;
173
174 ret = snprintf(p, psize,
175 "M DEFINITIONS ::=\nBEGIN\n"
176 "V ::= INTEGER %s\n"
177 "END\n",
178 value->value.string.buf
179 );
180 assert(ret < psize);
181 psize = ret;
182
183 asn = asn1p_parse_buffer(p, psize, A1P_NOFLAGS);
184 free(p);
185 if(asn == NULL) {
186 FATAL("Cannot parse BIT STRING value %s "
187 "defined as %s at line %d",
188 arg->expr->Identifier,
189 value->value.string.buf,
190 arg->expr->_lineno
191 );
192 return -1;
193 }
194
195 mod = TQ_FIRST(&(asn->modules));
196 assert(mod);
197 V = TQ_FIRST(&(mod->members));
198 assert(V);
199 assert(strcmp(V->Identifier, "V") == 0);
200 assert(TQ_FIRST(&(V->members)));
201
202 /*
203 * Simple loop just to fetch the maximal bit position
204 * out of the BIT STRING value defined as NamedBitList.
205 */
206 aI = -1;
207 TQ_FOR(bit, &(V->members), next) {
208 asn1p_expr_t *bitdef;
209 bitdef = asn1f_lookup_child(ttype, bit->Identifier);
210 if(bitdef && bitdef->value
211 && bitdef->value->type == ATV_INTEGER) {
212 if(bitdef->value->value.v_integer > aI)
213 aI = bitdef->value->value.v_integer;
214 }
215 }
216
217 if(aI > 1024 * 1024 * 8) { /* One megabyte */
218 FATAL("Unsupportedly large BIT STRING value \"%s\" "
219 "defined at line %d "
220 "(larger than 1MByte)",
221 arg->expr->Identifier,
222 arg->expr->_lineno
223 );
224 asn1p_free(asn);
225 return -1;
226 }
227
228 bits = aI + 1; /* Number of bits is more than a last bit position */
229 bitbuf = calloc(1, 1 + ((bits + 7) / 8));
230 if(bitbuf == NULL) {
231 asn1p_free(asn);
232 return -1;
233 }
234
235 TQ_FOR(bit, &(V->members), next) {
236 asn1p_expr_t *bitdef;
237 int set_bit_pos;
238
239 if(bit->value) {
240 WARNING("Identifier \"%s\" at line %d "
241 "must not have a value",
242 bit->Identifier, bit->_lineno);
243 RET2RVAL(1, r_value);
244 }
245 bitdef = asn1f_lookup_child(ttype, bit->Identifier);
246 if(bitdef == NULL) {
247 FATAL("Identifier \"%s\" at line %d is not defined "
248 "in the \"%s\" type definition at line %d",
249 bit->Identifier,
250 bit->_lineno,
251 ttype->Identifier,
252 ttype->_lineno
253 );
254 RET2RVAL(-1, r_value);
255 continue;
256 }
257 if(bitdef->value == NULL
258 || bitdef->value->type != ATV_INTEGER) {
259 FATAL("Broken identifier "
260 "\"%s\" at line %d "
261 "referenced by \"%s\" at line %d",
262 bitdef->Identifier,
263 bitdef->_lineno,
264 arg->expr->Identifier,
265 arg->expr->_lineno
266 );
267 RET2RVAL(-1, r_value);
268 continue;
269 }
270
271 assert(bitdef->value->value.v_integer < bits);
272 set_bit_pos = bitdef->value->value.v_integer;
273 bitbuf[set_bit_pos>>3] |= 1 << (7-(set_bit_pos % 8));
274 }
275
276 asn1p_free(asn);
277 free(value->value.string.buf);
278 value->type = ATV_BITVECTOR;
279 value->value.binary_vector.bits = bitbuf;
280 value->value.binary_vector.size_in_bits = bits;
281
282 return r_value;
283}