blob: 5728bd4cd5d65a1233a09e007a3ea21603898fba [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 }
163 case ATV_CHOICE_IDENTIFIER:
164 {
165 char *cid = v->value.choice_identifier.identifier;
166 char const *vptr = asn1f_printable_value(
167 v->value.choice_identifier.value);
168 char *val;
169
170 val = strdup(vptr);
171 if(!val) return "<memory allocation error>";
172
173 ENSURE(strlen(cid) + sizeof(": ") + strlen(val));
174
175 ret = snprintf(managedptr, managedptr_len + 1,
176 "%s: %s", cid, val);
Lev Walkin4efbfb72005-02-25 14:20:30 +0000177 assert(ret >= 0 && (size_t)ret <= managedptr_len);
Lev Walkincaaf7a52004-09-15 11:46:28 +0000178 free(val);
179 return managedptr;
180 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000181 }
182
183 return "<some complex value>";
184}
185
186
187/*
188 * Recursively invoke a given function over the given expr and all its
189 * children.
190 */
191int
192asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) {
193 asn1p_expr_t *expr = arg->expr;
194 int rvalue = 0;
195 int ret;
196
197 assert(expr);
198
Lev Walkina00d6b32006-03-21 03:40:38 +0000199 if(expr->lhs_params && expr->spec_index == -1) {
200 int i;
201 for(i = 0; i < expr->specializations.pspecs_count; i++) {
202 arg->expr = expr->specializations.pspec[i].my_clone;
203 ret = asn1f_recurse_expr(arg, callback);
204 RET2RVAL(ret, rvalue);
205 }
206 arg->expr = expr; /* revert */
207 return rvalue;
208 }
209
Lev Walkinf15320b2004-06-03 03:38:44 +0000210 /*
211 * Invoke the callback at this very level.
212 */
213 ret = callback(arg);
214 RET2RVAL(ret, rvalue);
215
216 /*
217 * Recursively invoke myself
218 * to iterate over each element in the tree.
219 */
220 TQ_FOR(arg->expr, &(expr->members), next) {
221 assert(arg->expr->expr_type != A1TC_INVALID);
Lev Walkin1004aa92004-09-08 00:28:11 +0000222 assert(arg->expr->parent_expr == expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000223 ret = asn1f_recurse_expr(arg, callback);
224 RET2RVAL(ret, rvalue);
225 }
226
227 arg->expr = expr; /* Restore original position */
228
229 return rvalue;
230}
231
232
233/*
234 * Check that every child of a given expr has unique name or does not have any.
235 */
236int
237asn1f_check_unique_expr(arg_t *arg,
238 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b)) {
239 asn1p_expr_t *expr;
240 int rvalue = 0;
241
242 TQ_FOR(expr, &(arg->expr->members), next) {
243 if(expr->Identifier) {
244 int ret = asn1f_check_unique_expr_child(arg, expr,
245 opt_compare);
246 if(ret) rvalue = -1;
247 } else {
248 /*
249 * No point of comparing this child with any other:
250 * this one does not have a name.
251 */
252 }
253 }
254
255 return rvalue;
256}
257
258/*
259 * Check that every preceeding child of the given expr is not
260 * having the name of the given one.
261 */
262int
263asn1f_check_unique_expr_child(arg_t *arg, asn1p_expr_t *child,
264 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b)) {
265 asn1p_expr_t *expr;
266 int rvalue = 0;
267
268 assert(child);
269 assert(opt_compare || child->Identifier);
270
271 TQ_FOR(expr, &(arg->expr->members), next) {
272 int ret;
273
274 if(expr == child)
275 break;
276
277 /*
278 * Compare according to the custom rule or default
279 * names comparisons.
280 */
281 if(opt_compare) {
282 ret = opt_compare(expr, child);
283 } else {
284 if(expr->Identifier == NULL
285 || expr->expr_type == A1TC_EXTENSIBLE)
286 continue;
287 ret = strcasecmp(expr->Identifier, child->Identifier);
288 }
289
290 if(ret == 0) {
291 char *msg;
292 msg = opt_compare
293 ?"Expressions clash"
294 :"Identifiers name clash";
295 arg->eh(1,
296 "%s: "
297 "\"%s\" at line %d has similar %s with "
298 "\"%s\" at line %d",
299 msg,
300 expr->Identifier,
301 expr->_lineno,
302 opt_compare?"property":"name",
303 child->Identifier,
304 child->_lineno
305 );
306
307 rvalue = -1;
308 }
309 }
310
311 return rvalue;
312}
313
314int
315asn1f_count_children(asn1p_expr_t *expr) {
316 asn1p_expr_t *child;
317 int count = 0;
318
319 TQ_FOR(child, &(expr->members), next) {
320 count++;
321 }
322
323 return count;
324}
325
Lev Walkin97bdee22004-06-28 21:21:24 +0000326
327static char **known_types;
328static int known_types_count;
329static int known_types_size;
330
331static int _known_types_cmp(const void *ap, const void *bp) {
332 const char *a = *(const char * const *)ap;
333 const char *b = *(const char * const *)bp;
334 return strcmp(a, b);
335}
336
337int
338asn1f_make_known_external_type(const char *type_name) {
339 char *tname;
340
341 /* Check for duplicates */
342 if(asn1f_check_known_external_type(type_name) == 0) {
343 errno = EEXIST;
344 return -1;
345 }
346
347 /* Ensure enough space */
348 if(known_types_count <= known_types_size) {
349 int n = known_types_size ? known_types_size << 1 : 4;
350 void *p;
351 p = realloc(known_types, n * sizeof(known_types[0]));
352 if(!p) return -1;
353 known_types = p;
354 known_types_size = n;
355 }
356
357 tname = strdup(type_name);
358 if(!tname) return -1;
359
360 known_types[known_types_count++] = tname;
361
362#ifdef HAVE_MERGESORT
363 mergesort
364#else
365 qsort
366#endif
367 (known_types, known_types_count, sizeof(known_types[0]),
368 _known_types_cmp);
369
370 return 0;
371}
372
373int
374asn1f_check_known_external_type(const char *type_name) {
Lev Walkina460ba32004-10-20 15:40:04 +0000375 if(known_types_count) {
376 void *p = bsearch(&type_name, known_types, known_types_count,
377 sizeof(known_types[0]), _known_types_cmp);
378 if(p) return 0;
379 }
Lev Walkin97bdee22004-06-28 21:21:24 +0000380 errno = ESRCH;
381 return -1;
382}
383