blob: d2c9e5c7de9614c43344d13152052b086962332a [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
25#define ENSURE(len) do { \
Lev Walkin4efbfb72005-02-25 14:20:30 +000026 size_t __len = (len); \
Lev Walkincaaf7a52004-09-15 11:46:28 +000027 if(__len >= managedptr_len) { \
Lev Walkinf15320b2004-06-03 03:38:44 +000028 if(managedptr) \
29 free(managedptr); \
Lev Walkincaaf7a52004-09-15 11:46:28 +000030 managedptr = malloc(__len + 1); \
Lev Walkinf15320b2004-06-03 03:38:44 +000031 if(managedptr) { \
Lev Walkincaaf7a52004-09-15 11:46:28 +000032 managedptr_len = __len; \
Lev Walkinf15320b2004-06-03 03:38:44 +000033 } else { \
34 managedptr_len = 0; \
35 return "<memory allocation error>"; \
36 } \
37 } \
38 } while(0)
39
40 if(v == NULL)
41 return "<no value>";
42
43 switch(v->type) {
44 case ATV_NOVALUE:
45 return "<NO VALUE>";
Lev Walkincaaf7a52004-09-15 11:46:28 +000046 case ATV_NULL:
47 return "NULL";
Lev Walkinf15320b2004-06-03 03:38:44 +000048 case ATV_REAL:
49 ret = snprintf(buf, sizeof(buf), "%f", v->value.v_double);
Lev Walkind9bd7752004-06-05 08:17:50 +000050 if(ret >= (ssize_t)sizeof(buf))
Lev Walkinf15320b2004-06-03 03:38:44 +000051 memcpy(buf + sizeof(buf) - 4, "...", 4);
52 return buf;
53 case ATV_INTEGER:
Lev Walkin33c16ba2004-09-24 21:01:43 +000054 ret = snprintf(buf, sizeof(buf), "%" PRIdASN,
55 v->value.v_integer);
Lev Walkind9bd7752004-06-05 08:17:50 +000056 if(ret >= (ssize_t)sizeof(buf))
Lev Walkinf15320b2004-06-03 03:38:44 +000057 memcpy(buf + sizeof(buf) - 4, "...", 4);
58 return buf;
59 case ATV_MIN: return "MIN";
60 case ATV_MAX: return "MAX";
61 case ATV_FALSE: return "FALSE";
62 case ATV_TRUE: return "TRUE";
Lev Walkin81d57412005-03-24 14:40:22 +000063 case ATV_TUPLE:
64 ret = snprintf(buf, sizeof(buf), "{%d, %d}",
65 (int)(v->value.v_integer >> 4),
66 (int)(v->value.v_integer & 0xff));
67 if(ret >= (ssize_t)sizeof(buf))
68 memcpy(buf + sizeof(buf) - 4, "...", 4);
69 return buf;
70 case ATV_QUADRUPLE:
71 ret = snprintf(buf, sizeof(buf), "{%d, %d, %d, %d}",
72 (int)((v->value.v_integer >> 24) & 0xff),
73 (int)((v->value.v_integer >> 16) & 0xff),
74 (int)((v->value.v_integer >> 8) & 0xff),
75 (int)(v->value.v_integer & 0xff));
76 if(ret >= (ssize_t)sizeof(buf))
77 memcpy(buf + sizeof(buf) - 4, "...", 4);
78 return buf;
Lev Walkinf15320b2004-06-03 03:38:44 +000079 case ATV_STRING:
80 case ATV_UNPARSED:
81 /* Buffer is guaranteed to be null-terminated */
82 assert(v->value.string.buf[v->value.string.size] == '\0');
Lev Walkin84fbd722005-06-15 18:41:50 +000083 return (char *)v->value.string.buf;
Lev Walkina9532f42006-09-17 04:52:50 +000084 case ATV_TYPE:
85 return "<Type>";
Lev Walkinf15320b2004-06-03 03:38:44 +000086 case ATV_BITVECTOR:
87 {
88 uint8_t *bitvector;
89 char *ptr;
Lev Walkin4efbfb72005-02-25 14:20:30 +000090 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000091 int i;
92 /*
93 * Compute number of bytes necessary
94 * to represend the binary value.
95 */
96 int bits = v->value.binary_vector.size_in_bits;
97 len = ((bits%8)?bits:(bits >> 2)) + sizeof("''H");
98 /*
99 * Reallocate managed buffer
100 */
101 ENSURE(len);
102
103 /*
104 * Fill the buffer.
105 */
106 ptr = managedptr;
107 bitvector = v->value.binary_vector.bits;
108 *ptr++ = '\'';
109 if(bits%8) {
110 /*
111 * Dump bit by bit.
112 */
113 for(i = 0; i < bits; i++) {
114 uint8_t uc;
115 uc = bitvector[i>>3];
116 *ptr++ = ((uc >> (7-(i%8)))&1)?'1':'0';
117 }
118 } else {
Lev Walkind9bd7752004-06-05 08:17:50 +0000119 static const char *hextable="0123456789ABCDEF";
Lev Walkinf15320b2004-06-03 03:38:44 +0000120 /*
121 * Dump byte by byte.
122 */
123 for(i = 0; i < (bits >> 3); i++) {
124 *ptr++ = hextable[bitvector[i] >> 4];
125 *ptr++ = hextable[bitvector[i] & 0x0f];
126 }
127 }
128 *ptr++ = '\'';
129 *ptr++ = (bits%8)?'B':'H';
130 *ptr++ = 'H';
Lev Walkin4efbfb72005-02-25 14:20:30 +0000131 assert(len == (size_t)(ptr - managedptr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000132 return managedptr;
133 }
Lev Walkincaaf7a52004-09-15 11:46:28 +0000134 case ATV_REFERENCED:
135 {
136 asn1p_ref_t *ref;
Lev Walkin4efbfb72005-02-25 14:20:30 +0000137 size_t reflen;
Lev Walkincaaf7a52004-09-15 11:46:28 +0000138 char *ptr;
139 int i;
140
141 assert(v->value.reference);
142 ref = v->value.reference;
143 reflen = ref->comp_count; /* Number of dots */
144 for(i = 0; i < ref->comp_count; i++)
145 reflen += strlen(ref->components[i].name);
146 /*
147 * Make sure we have a buffer of this size.
148 */
149 ENSURE(reflen);
150
151 /*
152 * Fill-up the buffer.
153 */
154 ptr = managedptr;
155 for(i = 0; i < ref->comp_count; i++) {
156 char *nc;
157 if(i) *ptr++ = '.';
158 for(nc = ref->components[i].name; *nc; nc++)
159 *ptr++ = *nc;
160 }
161 *ptr++ = '\0';
Lev Walkin4efbfb72005-02-25 14:20:30 +0000162 assert(reflen == (size_t)(ptr - managedptr));
Lev Walkincaaf7a52004-09-15 11:46:28 +0000163 return managedptr;
164 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000165 case ATV_VALUESET:
166 return "<ValueSet>";
Lev Walkincaaf7a52004-09-15 11:46:28 +0000167 case ATV_CHOICE_IDENTIFIER:
168 {
169 char *cid = v->value.choice_identifier.identifier;
170 char const *vptr = asn1f_printable_value(
171 v->value.choice_identifier.value);
172 char *val;
173
174 val = strdup(vptr);
175 if(!val) return "<memory allocation error>";
176
177 ENSURE(strlen(cid) + sizeof(": ") + strlen(val));
178
179 ret = snprintf(managedptr, managedptr_len + 1,
180 "%s: %s", cid, val);
Lev Walkin4efbfb72005-02-25 14:20:30 +0000181 assert(ret >= 0 && (size_t)ret <= managedptr_len);
Lev Walkincaaf7a52004-09-15 11:46:28 +0000182 free(val);
183 return managedptr;
184 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000185 }
186
187 return "<some complex value>";
188}
189
190
191/*
192 * Recursively invoke a given function over the given expr and all its
193 * children.
194 */
195int
196asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) {
197 asn1p_expr_t *expr = arg->expr;
198 int rvalue = 0;
199 int ret;
200
201 assert(expr);
202
Lev Walkina00d6b32006-03-21 03:40:38 +0000203 if(expr->lhs_params && expr->spec_index == -1) {
204 int i;
205 for(i = 0; i < expr->specializations.pspecs_count; i++) {
206 arg->expr = expr->specializations.pspec[i].my_clone;
207 ret = asn1f_recurse_expr(arg, callback);
208 RET2RVAL(ret, rvalue);
209 }
210 arg->expr = expr; /* revert */
211 return rvalue;
212 }
213
Lev Walkinf15320b2004-06-03 03:38:44 +0000214 /*
215 * Invoke the callback at this very level.
216 */
217 ret = callback(arg);
218 RET2RVAL(ret, rvalue);
219
220 /*
221 * Recursively invoke myself
222 * to iterate over each element in the tree.
223 */
224 TQ_FOR(arg->expr, &(expr->members), next) {
225 assert(arg->expr->expr_type != A1TC_INVALID);
Lev Walkin1004aa92004-09-08 00:28:11 +0000226 assert(arg->expr->parent_expr == expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000227 ret = asn1f_recurse_expr(arg, callback);
228 RET2RVAL(ret, rvalue);
229 }
230
231 arg->expr = expr; /* Restore original position */
232
233 return rvalue;
234}
235
236
237/*
238 * Check that every child of a given expr has unique name or does not have any.
239 */
240int
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000241asn1f_check_unique_expr(arg_t *arg) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000242 asn1p_expr_t *expr;
243 int rvalue = 0;
244
245 TQ_FOR(expr, &(arg->expr->members), next) {
246 if(expr->Identifier) {
247 int ret = asn1f_check_unique_expr_child(arg, expr,
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000248 0, "identifier");
Lev Walkinf15320b2004-06-03 03:38:44 +0000249 if(ret) rvalue = -1;
250 } else {
251 /*
252 * No point of comparing this child with any other:
253 * this one does not have a name.
254 */
255 }
256 }
257
258 return rvalue;
259}
260
261/*
262 * Check that every preceeding child of the given expr is not
263 * having the name of the given one.
264 */
265int
266asn1f_check_unique_expr_child(arg_t *arg, asn1p_expr_t *child,
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000267 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b),
268 const char *opt_property_name) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000269 asn1p_expr_t *expr;
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000270
271 if(!opt_property_name) opt_property_name = "property";
Lev Walkinf15320b2004-06-03 03:38:44 +0000272
273 assert(child);
274 assert(opt_compare || child->Identifier);
275
276 TQ_FOR(expr, &(arg->expr->members), next) {
277 int ret;
278
279 if(expr == child)
280 break;
281
282 /*
283 * Compare according to the custom rule or default
284 * names comparisons.
285 */
286 if(opt_compare) {
287 ret = opt_compare(expr, child);
288 } else {
289 if(expr->Identifier == NULL
290 || expr->expr_type == A1TC_EXTENSIBLE)
291 continue;
Lev Walkin1d6d5192013-03-28 05:00:31 -0700292 ret = strcmp(expr->Identifier, child->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +0000293 }
294
295 if(ret == 0) {
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000296 FATAL("Clash detected: "
Lev Walkinf15320b2004-06-03 03:38:44 +0000297 "\"%s\" at line %d has similar %s with "
298 "\"%s\" at line %d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000299 expr->Identifier,
300 expr->_lineno,
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000301 opt_property_name,
Lev Walkinf15320b2004-06-03 03:38:44 +0000302 child->Identifier,
303 child->_lineno
304 );
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000305 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000306 }
307 }
308
Lev Walkinfbfc7bc2006-08-28 02:45:44 +0000309 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000310}
311
312int
313asn1f_count_children(asn1p_expr_t *expr) {
314 asn1p_expr_t *child;
315 int count = 0;
316
317 TQ_FOR(child, &(expr->members), next) {
318 count++;
319 }
320
321 return count;
322}
323
Lev Walkin97bdee22004-06-28 21:21:24 +0000324
325static char **known_types;
326static int known_types_count;
327static int known_types_size;
328
329static int _known_types_cmp(const void *ap, const void *bp) {
330 const char *a = *(const char * const *)ap;
331 const char *b = *(const char * const *)bp;
332 return strcmp(a, b);
333}
334
335int
336asn1f_make_known_external_type(const char *type_name) {
337 char *tname;
338
339 /* Check for duplicates */
340 if(asn1f_check_known_external_type(type_name) == 0) {
341 errno = EEXIST;
342 return -1;
343 }
344
345 /* Ensure enough space */
346 if(known_types_count <= known_types_size) {
347 int n = known_types_size ? known_types_size << 1 : 4;
348 void *p;
349 p = realloc(known_types, n * sizeof(known_types[0]));
350 if(!p) return -1;
351 known_types = p;
352 known_types_size = n;
353 }
354
355 tname = strdup(type_name);
356 if(!tname) return -1;
357
358 known_types[known_types_count++] = tname;
359
360#ifdef HAVE_MERGESORT
361 mergesort
362#else
363 qsort
364#endif
365 (known_types, known_types_count, sizeof(known_types[0]),
366 _known_types_cmp);
367
368 return 0;
369}
370
371int
372asn1f_check_known_external_type(const char *type_name) {
Lev Walkina460ba32004-10-20 15:40:04 +0000373 if(known_types_count) {
374 void *p = bsearch(&type_name, known_types, known_types_count,
375 sizeof(known_types[0]), _known_types_cmp);
376 if(p) return 0;
377 }
Lev Walkin97bdee22004-06-28 21:21:24 +0000378 errno = ESRCH;
379 return -1;
380}
381