blob: 8297f276b7a06931ba826d9604a45719e1059cb1 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3int asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype);
4static void asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value);
5static int asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype);
6
7int
8asn1f_fix_bit_string(arg_t *arg) {
9 asn1p_expr_t *expr = arg->expr;
10 int r_value = 0;
11 int ret;
12
13 if(expr->meta_type == AMT_VALUE) {
14 asn1p_expr_t *ttype;
15
vlmfd245932005-03-10 10:02:50 +000016 DEBUG("(%s) for line %d", expr->Identifier, expr->_lineno);
vlmfa67ddc2004-06-03 03:38:44 +000017
vlm2e0c1942004-08-22 03:10:23 +000018 ttype = asn1f_find_terminal_type(arg, expr);
vlmfa67ddc2004-06-03 03:38:44 +000019 if(ttype && ttype->expr_type == ASN_BASIC_BIT_STRING) {
20 ret = asn1f_fix_bit_string_value(arg, ttype);
21 RET2RVAL(ret, r_value);
22 }
23 }
24
25 return r_value;
26}
27
28int
29asn1f_fix_bit_string_value(arg_t *arg, asn1p_expr_t *ttype) {
30 asn1p_expr_t *expr = arg->expr;
31 int r_value = 0;
32
vlmfd245932005-03-10 10:02:50 +000033 DEBUG("(%s) for line %d",
vlmfa67ddc2004-06-03 03:38:44 +000034 expr->Identifier, expr->_lineno);
35
36 switch(expr->value->type) {
37 case ATV_UNPARSED:
38 /*
39 * Most definitely we have something like
40 * value BitStringType1 ::= { a, b, c }
41 * which could not be parsed by the LALR parser, mostly
42 * because it requires knowledge about BitStringType1
43 * during the parsing. So, here's a little hack: we create
44 * a buffer containing the full specification of a module,
45 * which contains some pre-defined INTEGER type with the
46 * opaque definition "{ a, b, c }" from the bit string.
47 */
48 if(asn1f_BS_unparsed_convert(arg, expr->value, ttype)) {
49 r_value = -1;
50 break;
51 }
52 /* Fall through: remove trailing zero bits */
53 case ATV_BITVECTOR:
54 asn1f_BS_remove_trailing_zero_bits(expr->value);
55 break;
56 default:
57 break;
58 }
59
60 return r_value;
61}
62
63static void
64asn1f_BS_remove_trailing_zero_bits(asn1p_value_t *value) {
65 int lmfb = -1; /* Last meaningful byte position */
66 int bits; /* Number of bits in the BIT STRING value */
67 int b;
68
69 assert(value->type == ATV_BITVECTOR);
70
71 bits = value->value.binary_vector.size_in_bits;
72 /*
73 * Figure out the rightmost meaningful byte.
74 */
75 for(b = 0; b < ((bits + 7) >> 3); b++) {
76 uint8_t uc = value->value.binary_vector.bits[b];
77 if(uc && b > lmfb)
78 lmfb = b;
79 }
80 if(lmfb == -1) {
81 bits = 0;
82 } else {
83 uint8_t uc;
84 uc = value->value.binary_vector.bits[lmfb];
85 bits = (lmfb+1) * 8;
86 /*
87 * Squeeze the bit string width until the rightmost
88 * bit is set.
89 */
90 for(; uc && (uc & 1) == 0; uc >>= 1)
91 bits--;
92 if(uc == 0) {
93 bits = lmfb * 8;
94 }
95 }
96 value->value.binary_vector.size_in_bits = bits;
97}
98
99static int
100asn1f_BS_unparsed_convert(arg_t *arg, asn1p_value_t *value, asn1p_expr_t *ttype) {
101 asn1p_t *asn;
102 asn1p_module_t *mod;
103 asn1p_expr_t *V;
104 asn1p_expr_t *bit;
vlmd5b3bf32004-09-29 13:17:17 +0000105 asn1c_integer_t aI;
vlmfa67ddc2004-06-03 03:38:44 +0000106 uint8_t *bitbuf;
107 int bits;
108 int psize;
109 char *p;
110 int ret;
111 int r_value = 0;
112
113 assert(value->type == ATV_UNPARSED);
114
115 psize = value->value.string.size + 64;
116 p = malloc(psize);
117 if(p == NULL)
118 return -1;
119
120 ret = snprintf(p, psize,
121 "M DEFINITIONS ::=\nBEGIN\n"
122 "V ::= INTEGER %s\n"
123 "END\n",
124 value->value.string.buf
125 );
126 assert(ret < psize);
127 psize = ret;
128
129 asn = asn1p_parse_buffer(p, psize, A1P_NOFLAGS);
130 free(p);
131 if(asn == NULL) {
132 FATAL("Cannot parse BIT STRING value %s "
133 "defined as %s at line %d",
134 arg->expr->Identifier,
135 value->value.string.buf,
136 arg->expr->_lineno
137 );
138 return -1;
139 }
140
141 mod = TQ_FIRST(&(asn->modules));
142 assert(mod);
143 V = TQ_FIRST(&(mod->members));
144 assert(V);
145 assert(strcmp(V->Identifier, "V") == 0);
146 assert(TQ_FIRST(&(V->members)));
147
148 /*
149 * Simple loop just to fetch the maximal bit position
150 * out of the BIT STRING value defined as NamedBitList.
151 */
152 aI = -1;
153 TQ_FOR(bit, &(V->members), next) {
154 asn1p_expr_t *bitdef;
155 bitdef = asn1f_lookup_child(ttype, bit->Identifier);
156 if(bitdef && bitdef->value
157 && bitdef->value->type == ATV_INTEGER) {
158 if(bitdef->value->value.v_integer > aI)
159 aI = bitdef->value->value.v_integer;
160 }
161 }
162
163 if(aI > 1024 * 1024 * 8) { /* One megabyte */
164 FATAL("Unsupportedly large BIT STRING value \"%s\" "
165 "defined at line %d "
166 "(larger than 1MByte)",
167 arg->expr->Identifier,
168 arg->expr->_lineno
169 );
170 asn1p_free(asn);
171 return -1;
172 }
173
174 bits = aI + 1; /* Number of bits is more than a last bit position */
175 bitbuf = calloc(1, 1 + ((bits + 7) / 8));
176 if(bitbuf == NULL) {
177 asn1p_free(asn);
178 return -1;
179 }
180
181 TQ_FOR(bit, &(V->members), next) {
182 asn1p_expr_t *bitdef;
183 int set_bit_pos;
184
185 if(bit->value) {
186 WARNING("Identifier \"%s\" at line %d "
187 "must not have a value",
188 bit->Identifier, bit->_lineno);
189 RET2RVAL(1, r_value);
190 }
191 bitdef = asn1f_lookup_child(ttype, bit->Identifier);
192 if(bitdef == NULL) {
193 FATAL("Identifier \"%s\" at line %d is not defined "
194 "in the \"%s\" type definition at line %d",
195 bit->Identifier,
196 bit->_lineno,
197 ttype->Identifier,
198 ttype->_lineno
199 );
200 RET2RVAL(-1, r_value);
201 continue;
202 }
203 if(bitdef->value == NULL
204 || bitdef->value->type != ATV_INTEGER) {
205 FATAL("Broken identifier "
206 "\"%s\" at line %d "
207 "referenced by \"%s\" at line %d",
208 bitdef->Identifier,
209 bitdef->_lineno,
210 arg->expr->Identifier,
211 arg->expr->_lineno
212 );
213 RET2RVAL(-1, r_value);
214 continue;
215 }
216
217 assert(bitdef->value->value.v_integer < bits);
218 set_bit_pos = bitdef->value->value.v_integer;
219 bitbuf[set_bit_pos>>3] |= 1 << (7-(set_bit_pos % 8));
220 }
221
222 asn1p_free(asn);
223 free(value->value.string.buf);
224 value->type = ATV_BITVECTOR;
225 value->value.binary_vector.bits = bitbuf;
226 value->value.binary_vector.size_in_bits = bits;
227
228 return r_value;
229}