blob: 23005b95182bf434e378b152d9356b7ccc21a7e4 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
Lev Walkin97bdee22004-06-28 21:21:24 +00002#include "asn1fix.h"
Lev Walkinf15320b2004-06-03 03:38:44 +00003
4char const *
5asn1f_printable_reference(asn1p_ref_t *ref) {
6 if(ref) {
7 asn1p_value_t v;
8
9 v.type = ATV_REFERENCED;
10 v.value.reference = ref;
11
12 return asn1f_printable_value(&v);
13 } else {
14 return "<no ref>";
15 }
16}
17
18char const *
19asn1f_printable_value(asn1p_value_t *v) {
20 static char buf[128];
21 static char *managedptr;
Lev Walkin4efbfb72005-02-25 14:20:30 +000022 static size_t managedptr_len;
Lev Walkinf15320b2004-06-03 03:38:44 +000023 int ret;
24
Lev Walkin1ec76052016-03-13 17:13:20 -070025#define ENSURE(len) do { \
26 size_t tmp_len = (len); \
27 if(tmp_len >= managedptr_len) { \
28 free(managedptr); \
29 managedptr = malloc(tmp_len + 1); \
30 if(managedptr) { \
31 managedptr_len = tmp_len; \
32 } else { \
33 managedptr_len = 0; \
34 return "<memory allocation error>"; \
35 } \
36 } \
37 } while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000038
39 if(v == NULL)
40 return "<no value>";
41
42 switch(v->type) {
43 case ATV_NOVALUE:
44 return "<NO VALUE>";
Lev Walkincaaf7a52004-09-15 11:46:28 +000045 case ATV_NULL:
46 return "NULL";
Lev Walkinf15320b2004-06-03 03:38:44 +000047 case ATV_REAL:
48 ret = snprintf(buf, sizeof(buf), "%f", v->value.v_double);
Lev Walkind9bd7752004-06-05 08:17:50 +000049 if(ret >= (ssize_t)sizeof(buf))
Lev Walkinf15320b2004-06-03 03:38:44 +000050 memcpy(buf + sizeof(buf) - 4, "...", 4);
51 return buf;
52 case ATV_INTEGER:
Lev Walkin33c16ba2004-09-24 21:01:43 +000053 ret = snprintf(buf, sizeof(buf), "%" PRIdASN,
54 v->value.v_integer);
Lev Walkind9bd7752004-06-05 08:17:50 +000055 if(ret >= (ssize_t)sizeof(buf))
Lev Walkinf15320b2004-06-03 03:38:44 +000056 memcpy(buf + sizeof(buf) - 4, "...", 4);
57 return buf;
58 case ATV_MIN: return "MIN";
59 case ATV_MAX: return "MAX";
60 case ATV_FALSE: return "FALSE";
61 case ATV_TRUE: return "TRUE";
Lev Walkin81d57412005-03-24 14:40:22 +000062 case ATV_TUPLE:
63 ret = snprintf(buf, sizeof(buf), "{%d, %d}",
64 (int)(v->value.v_integer >> 4),
65 (int)(v->value.v_integer & 0xff));
66 if(ret >= (ssize_t)sizeof(buf))
67 memcpy(buf + sizeof(buf) - 4, "...", 4);
68 return buf;
69 case ATV_QUADRUPLE:
70 ret = snprintf(buf, sizeof(buf), "{%d, %d, %d, %d}",
71 (int)((v->value.v_integer >> 24) & 0xff),
72 (int)((v->value.v_integer >> 16) & 0xff),
73 (int)((v->value.v_integer >> 8) & 0xff),
74 (int)(v->value.v_integer & 0xff));
75 if(ret >= (ssize_t)sizeof(buf))
76 memcpy(buf + sizeof(buf) - 4, "...", 4);
77 return buf;
Lev Walkinf15320b2004-06-03 03:38:44 +000078 case ATV_STRING:
79 case ATV_UNPARSED:
80 /* Buffer is guaranteed to be null-terminated */
81 assert(v->value.string.buf[v->value.string.size] == '\0');
Lev Walkin84fbd722005-06-15 18:41:50 +000082 return (char *)v->value.string.buf;
Lev Walkina9532f42006-09-17 04:52:50 +000083 case ATV_TYPE:
84 return "<Type>";
Lev Walkinf15320b2004-06-03 03:38:44 +000085 case ATV_BITVECTOR:
86 {
87 uint8_t *bitvector;
88 char *ptr;
Lev Walkin4efbfb72005-02-25 14:20:30 +000089 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000090 int i;
91 /*
92 * Compute number of bytes necessary
93 * to represend the binary value.
94 */
95 int bits = v->value.binary_vector.size_in_bits;
96 len = ((bits%8)?bits:(bits >> 2)) + sizeof("''H");
97 /*
98 * Reallocate managed buffer
99 */
100 ENSURE(len);
101
102 /*
103 * Fill the buffer.
104 */
105 ptr = managedptr;
106 bitvector = v->value.binary_vector.bits;
107 *ptr++ = '\'';
108 if(bits%8) {
109 /*
110 * Dump bit by bit.
111 */
112 for(i = 0; i < bits; i++) {
113 uint8_t uc;
114 uc = bitvector[i>>3];
115 *ptr++ = ((uc >> (7-(i%8)))&1)?'1':'0';
116 }
117 } else {
Lev Walkind9bd7752004-06-05 08:17:50 +0000118 static const char *hextable="0123456789ABCDEF";
Lev Walkinf15320b2004-06-03 03:38:44 +0000119 /*
120 * Dump byte by byte.
121 */
122 for(i = 0; i < (bits >> 3); i++) {
123 *ptr++ = hextable[bitvector[i] >> 4];
124 *ptr++ = hextable[bitvector[i] & 0x0f];
125 }
126 }
127 *ptr++ = '\'';
128 *ptr++ = (bits%8)?'B':'H';
129 *ptr++ = 'H';
Lev Walkin4efbfb72005-02-25 14:20:30 +0000130 assert(len == (size_t)(ptr - managedptr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000131 return managedptr;
132 }
Lev Walkincaaf7a52004-09-15 11:46:28 +0000133 case ATV_REFERENCED:
134 {
135 asn1p_ref_t *ref;
Lev Walkin4efbfb72005-02-25 14:20:30 +0000136 size_t reflen;
Lev Walkincaaf7a52004-09-15 11:46:28 +0000137 char *ptr;
138 int i;
139
140 assert(v->value.reference);
141 ref = v->value.reference;
142 reflen = ref->comp_count; /* Number of dots */
143 for(i = 0; i < ref->comp_count; i++)
144 reflen += strlen(ref->components[i].name);
145 /*
146 * Make sure we have a buffer of this size.
147 */
148 ENSURE(reflen);
149
150 /*
151 * Fill-up the buffer.
152 */
153 ptr = managedptr;
154 for(i = 0; i < ref->comp_count; i++) {
155 char *nc;
156 if(i) *ptr++ = '.';
157 for(nc = ref->components[i].name; *nc; nc++)
158 *ptr++ = *nc;
159 }
160 *ptr++ = '\0';
Lev Walkin4efbfb72005-02-25 14:20:30 +0000161 assert(reflen == (size_t)(ptr - managedptr));
Lev Walkincaaf7a52004-09-15 11:46:28 +0000162 return managedptr;
163 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000164 case ATV_VALUESET:
165 return "<ValueSet>";
Lev Walkincaaf7a52004-09-15 11:46:28 +0000166 case ATV_CHOICE_IDENTIFIER:
167 {
168 char *cid = v->value.choice_identifier.identifier;
169 char const *vptr = asn1f_printable_value(
170 v->value.choice_identifier.value);
171 char *val;
172
173 val = strdup(vptr);
174 if(!val) return "<memory allocation error>";
175
176 ENSURE(strlen(cid) + sizeof(": ") + strlen(val));
177
178 ret = snprintf(managedptr, managedptr_len + 1,
179 "%s: %s", cid, val);
Lev Walkin4efbfb72005-02-25 14:20:30 +0000180 assert(ret >= 0 && (size_t)ret <= managedptr_len);
Lev Walkincaaf7a52004-09-15 11:46:28 +0000181 free(val);
182 return managedptr;
183 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000184 }
185
186 return "<some complex value>";
187}
188
189
190/*
191 * Recursively invoke a given function over the given expr and all its
192 * children.
193 */
194int
195asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) {
196 asn1p_expr_t *expr = arg->expr;
197 int rvalue = 0;
198 int ret;
199
200 assert(expr);
201
Lev Walkina00d6b32006-03-21 03:40:38 +0000202 if(expr->lhs_params && expr->spec_index == -1) {
203 int i;
204 for(i = 0; i < expr->specializations.pspecs_count; i++) {
205 arg->expr = expr->specializations.pspec[i].my_clone;
206 ret = asn1f_recurse_expr(arg, callback);
207 RET2RVAL(ret, rvalue);
208 }
209 arg->expr = expr; /* revert */
210 return rvalue;
211 }
212
Lev Walkinf15320b2004-06-03 03:38:44 +0000213 /*
214 * Invoke the callback at this very level.
215 */
216 ret = callback(arg);
217 RET2RVAL(ret, rvalue);
218
219 /*
220 * Recursively invoke myself
221 * to iterate over each element in the tree.
222 */
223 TQ_FOR(arg->expr, &(expr->members), next) {
224 assert(arg->expr->expr_type != A1TC_INVALID);
Lev Walkin1004aa92004-09-08 00:28:11 +0000225 assert(arg->expr->parent_expr == expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000226 ret = asn1f_recurse_expr(arg, callback);
227 RET2RVAL(ret, rvalue);
228 }
229
230 arg->expr = expr; /* Restore original position */
231
232 return rvalue;
233}
234
235
236/*
237 * Check that every child of a given expr has unique name or does not have any.
238 */
239int
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000240asn1f_check_unique_expr(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000241 asn1p_expr_t *expr;
242 int rvalue = 0;
243
244 TQ_FOR(expr, &(arg->expr->members), next) {
245 if(expr->Identifier) {
246 int ret = asn1f_check_unique_expr_child(arg, expr,
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000247 0, "identifier");
Lev Walkinf15320b2004-06-03 03:38:44 +0000248 if(ret) rvalue = -1;
249 } else {
250 /*
251 * No point of comparing this child with any other:
252 * this one does not have a name.
253 */
254 }
255 }
256
257 return rvalue;
258}
259
260/*
261 * Check that every preceeding child of the given expr is not
262 * having the name of the given one.
263 */
264int
265asn1f_check_unique_expr_child(arg_t *arg, asn1p_expr_t *child,
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000266 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b),
267 const char *opt_property_name) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000268 asn1p_expr_t *expr;
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000269
270 if(!opt_property_name) opt_property_name = "property";
Lev Walkinf15320b2004-06-03 03:38:44 +0000271
272 assert(child);
273 assert(opt_compare || child->Identifier);
274
275 TQ_FOR(expr, &(arg->expr->members), next) {
276 int ret;
277
278 if(expr == child)
279 break;
280
281 /*
282 * Compare according to the custom rule or default
283 * names comparisons.
284 */
285 if(opt_compare) {
286 ret = opt_compare(expr, child);
287 } else {
288 if(expr->Identifier == NULL
289 || expr->expr_type == A1TC_EXTENSIBLE)
290 continue;
Lev Walkin1d6d5192013-03-28 05:00:31 -0700291 ret = strcmp(expr->Identifier, child->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000292 }
293
294 if(ret == 0) {
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000295 FATAL("Clash detected: "
Lev Walkinf15320b2004-06-03 03:38:44 +0000296 "\"%s\" at line %d has similar %s with "
297 "\"%s\" at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000298 expr->Identifier,
299 expr->_lineno,
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000300 opt_property_name,
Lev Walkinf15320b2004-06-03 03:38:44 +0000301 child->Identifier,
302 child->_lineno
303 );
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000304 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000305 }
306 }
307
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000308 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000309}
310
311int
312asn1f_count_children(asn1p_expr_t *expr) {
313 asn1p_expr_t *child;
314 int count = 0;
315
316 TQ_FOR(child, &(expr->members), next) {
317 count++;
318 }
319
320 return count;
321}
322
Lev Walkin97bdee22004-06-28 21:21:24 +0000323
324static char **known_types;
325static int known_types_count;
326static int known_types_size;
327
328static int _known_types_cmp(const void *ap, const void *bp) {
329 const char *a = *(const char * const *)ap;
330 const char *b = *(const char * const *)bp;
331 return strcmp(a, b);
332}
333
334int
335asn1f_make_known_external_type(const char *type_name) {
336 char *tname;
337
338 /* Check for duplicates */
339 if(asn1f_check_known_external_type(type_name) == 0) {
340 errno = EEXIST;
341 return -1;
342 }
343
344 /* Ensure enough space */
345 if(known_types_count <= known_types_size) {
346 int n = known_types_size ? known_types_size << 1 : 4;
347 void *p;
348 p = realloc(known_types, n * sizeof(known_types[0]));
349 if(!p) return -1;
350 known_types = p;
351 known_types_size = n;
352 }
353
354 tname = strdup(type_name);
355 if(!tname) return -1;
356
357 known_types[known_types_count++] = tname;
358
359#ifdef HAVE_MERGESORT
360 mergesort
361#else
362 qsort
363#endif
364 (known_types, known_types_count, sizeof(known_types[0]),
365 _known_types_cmp);
366
367 return 0;
368}
369
370int
371asn1f_check_known_external_type(const char *type_name) {
Lev Walkina460ba32004-10-20 15:40:04 +0000372 if(known_types_count) {
373 void *p = bsearch(&type_name, known_types, known_types_count,
374 sizeof(known_types[0]), _known_types_cmp);
375 if(p) return 0;
376 }
Lev Walkin97bdee22004-06-28 21:21:24 +0000377 errno = ESRCH;
378 return -1;
379}
380