blob: 9e8cc07fbec78217a13d9215c508bf985a8d49c9 [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 Walkinf15320b2004-06-03 03:38:44 +000084 case ATV_BITVECTOR:
85 {
86 uint8_t *bitvector;
87 char *ptr;
Lev Walkin4efbfb72005-02-25 14:20:30 +000088 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000089 int i;
90 /*
91 * Compute number of bytes necessary
92 * to represend the binary value.
93 */
94 int bits = v->value.binary_vector.size_in_bits;
95 len = ((bits%8)?bits:(bits >> 2)) + sizeof("''H");
96 /*
97 * Reallocate managed buffer
98 */
99 ENSURE(len);
100
101 /*
102 * Fill the buffer.
103 */
104 ptr = managedptr;
105 bitvector = v->value.binary_vector.bits;
106 *ptr++ = '\'';
107 if(bits%8) {
108 /*
109 * Dump bit by bit.
110 */
111 for(i = 0; i < bits; i++) {
112 uint8_t uc;
113 uc = bitvector[i>>3];
114 *ptr++ = ((uc >> (7-(i%8)))&1)?'1':'0';
115 }
116 } else {
Lev Walkind9bd7752004-06-05 08:17:50 +0000117 static const char *hextable="0123456789ABCDEF";
Lev Walkinf15320b2004-06-03 03:38:44 +0000118 /*
119 * Dump byte by byte.
120 */
121 for(i = 0; i < (bits >> 3); i++) {
122 *ptr++ = hextable[bitvector[i] >> 4];
123 *ptr++ = hextable[bitvector[i] & 0x0f];
124 }
125 }
126 *ptr++ = '\'';
127 *ptr++ = (bits%8)?'B':'H';
128 *ptr++ = 'H';
Lev Walkin4efbfb72005-02-25 14:20:30 +0000129 assert(len == (size_t)(ptr - managedptr));
Lev Walkinf15320b2004-06-03 03:38:44 +0000130 return managedptr;
131 }
Lev Walkincaaf7a52004-09-15 11:46:28 +0000132 case ATV_REFERENCED:
133 {
134 asn1p_ref_t *ref;
Lev Walkin4efbfb72005-02-25 14:20:30 +0000135 size_t reflen;
Lev Walkincaaf7a52004-09-15 11:46:28 +0000136 char *ptr;
137 int i;
138
139 assert(v->value.reference);
140 ref = v->value.reference;
141 reflen = ref->comp_count; /* Number of dots */
142 for(i = 0; i < ref->comp_count; i++)
143 reflen += strlen(ref->components[i].name);
144 /*
145 * Make sure we have a buffer of this size.
146 */
147 ENSURE(reflen);
148
149 /*
150 * Fill-up the buffer.
151 */
152 ptr = managedptr;
153 for(i = 0; i < ref->comp_count; i++) {
154 char *nc;
155 if(i) *ptr++ = '.';
156 for(nc = ref->components[i].name; *nc; nc++)
157 *ptr++ = *nc;
158 }
159 *ptr++ = '\0';
Lev Walkin4efbfb72005-02-25 14:20:30 +0000160 assert(reflen == (size_t)(ptr - managedptr));
Lev Walkincaaf7a52004-09-15 11:46:28 +0000161 return managedptr;
162 }
Lev Walkin5045dfa2006-03-21 09:41:28 +0000163 case ATV_VALUESET:
164 return "<ValueSet>";
Lev Walkincaaf7a52004-09-15 11:46:28 +0000165 case ATV_CHOICE_IDENTIFIER:
166 {
167 char *cid = v->value.choice_identifier.identifier;
168 char const *vptr = asn1f_printable_value(
169 v->value.choice_identifier.value);
170 char *val;
171
172 val = strdup(vptr);
173 if(!val) return "<memory allocation error>";
174
175 ENSURE(strlen(cid) + sizeof(": ") + strlen(val));
176
177 ret = snprintf(managedptr, managedptr_len + 1,
178 "%s: %s", cid, val);
Lev Walkin4efbfb72005-02-25 14:20:30 +0000179 assert(ret >= 0 && (size_t)ret <= managedptr_len);
Lev Walkincaaf7a52004-09-15 11:46:28 +0000180 free(val);
181 return managedptr;
182 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000183 }
184
185 return "<some complex value>";
186}
187
188
189/*
190 * Recursively invoke a given function over the given expr and all its
191 * children.
192 */
193int
194asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) {
195 asn1p_expr_t *expr = arg->expr;
196 int rvalue = 0;
197 int ret;
198
199 assert(expr);
200
Lev Walkina00d6b32006-03-21 03:40:38 +0000201 if(expr->lhs_params && expr->spec_index == -1) {
202 int i;
203 for(i = 0; i < expr->specializations.pspecs_count; i++) {
204 arg->expr = expr->specializations.pspec[i].my_clone;
205 ret = asn1f_recurse_expr(arg, callback);
206 RET2RVAL(ret, rvalue);
207 }
208 arg->expr = expr; /* revert */
209 return rvalue;
210 }
211
Lev Walkinf15320b2004-06-03 03:38:44 +0000212 /*
213 * Invoke the callback at this very level.
214 */
215 ret = callback(arg);
216 RET2RVAL(ret, rvalue);
217
218 /*
219 * Recursively invoke myself
220 * to iterate over each element in the tree.
221 */
222 TQ_FOR(arg->expr, &(expr->members), next) {
223 assert(arg->expr->expr_type != A1TC_INVALID);
Lev Walkin1004aa92004-09-08 00:28:11 +0000224 assert(arg->expr->parent_expr == expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000225 ret = asn1f_recurse_expr(arg, callback);
226 RET2RVAL(ret, rvalue);
227 }
228
229 arg->expr = expr; /* Restore original position */
230
231 return rvalue;
232}
233
234
235/*
236 * Check that every child of a given expr has unique name or does not have any.
237 */
238int
239asn1f_check_unique_expr(arg_t *arg,
240 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b)) {
241 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,
247 opt_compare);
248 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,
266 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b)) {
267 asn1p_expr_t *expr;
268 int rvalue = 0;
269
270 assert(child);
271 assert(opt_compare || child->Identifier);
272
273 TQ_FOR(expr, &(arg->expr->members), next) {
274 int ret;
275
276 if(expr == child)
277 break;
278
279 /*
280 * Compare according to the custom rule or default
281 * names comparisons.
282 */
283 if(opt_compare) {
284 ret = opt_compare(expr, child);
285 } else {
286 if(expr->Identifier == NULL
287 || expr->expr_type == A1TC_EXTENSIBLE)
288 continue;
289 ret = strcasecmp(expr->Identifier, child->Identifier);
290 }
291
292 if(ret == 0) {
293 char *msg;
294 msg = opt_compare
295 ?"Expressions clash"
296 :"Identifiers name clash";
Lev Walkina0c92902006-08-28 02:24:24 +0000297 FATAL("%s: "
Lev Walkinf15320b2004-06-03 03:38:44 +0000298 "\"%s\" at line %d has similar %s with "
299 "\"%s\" at line %d",
300 msg,
301 expr->Identifier,
302 expr->_lineno,
303 opt_compare?"property":"name",
304 child->Identifier,
305 child->_lineno
306 );
307
308 rvalue = -1;
309 }
310 }
311
312 return rvalue;
313}
314
315int
316asn1f_count_children(asn1p_expr_t *expr) {
317 asn1p_expr_t *child;
318 int count = 0;
319
320 TQ_FOR(child, &(expr->members), next) {
321 count++;
322 }
323
324 return count;
325}
326
Lev Walkin97bdee22004-06-28 21:21:24 +0000327
328static char **known_types;
329static int known_types_count;
330static int known_types_size;
331
332static int _known_types_cmp(const void *ap, const void *bp) {
333 const char *a = *(const char * const *)ap;
334 const char *b = *(const char * const *)bp;
335 return strcmp(a, b);
336}
337
338int
339asn1f_make_known_external_type(const char *type_name) {
340 char *tname;
341
342 /* Check for duplicates */
343 if(asn1f_check_known_external_type(type_name) == 0) {
344 errno = EEXIST;
345 return -1;
346 }
347
348 /* Ensure enough space */
349 if(known_types_count <= known_types_size) {
350 int n = known_types_size ? known_types_size << 1 : 4;
351 void *p;
352 p = realloc(known_types, n * sizeof(known_types[0]));
353 if(!p) return -1;
354 known_types = p;
355 known_types_size = n;
356 }
357
358 tname = strdup(type_name);
359 if(!tname) return -1;
360
361 known_types[known_types_count++] = tname;
362
363#ifdef HAVE_MERGESORT
364 mergesort
365#else
366 qsort
367#endif
368 (known_types, known_types_count, sizeof(known_types[0]),
369 _known_types_cmp);
370
371 return 0;
372}
373
374int
375asn1f_check_known_external_type(const char *type_name) {
Lev Walkina460ba32004-10-20 15:40:04 +0000376 if(known_types_count) {
377 void *p = bsearch(&type_name, known_types, known_types_count,
378 sizeof(known_types[0]), _known_types_cmp);
379 if(p) return 0;
380 }
Lev Walkin97bdee22004-06-28 21:21:24 +0000381 errno = ESRCH;
382 return -1;
383}
384