1 #include "asn1fix_internal.h"
5 asn1f_printable_reference(const asn1p_ref_t *ref) {
7 return asn1p_ref_string(ref);
14 asn1f_printable_value(asn1p_value_t *v) {
16 static char *managedptr;
17 static size_t managedptr_len;
20 #define ENSURE(len) do { \
21 size_t tmp_len = (len); \
22 if(tmp_len >= managedptr_len) { \
24 managedptr = calloc(1, tmp_len + 1); \
26 managedptr_len = tmp_len; \
29 return "<memory allocation error>"; \
43 ret = snprintf(buf, sizeof(buf), "%f", v->value.v_double);
44 if(ret >= (ssize_t)sizeof(buf))
45 memcpy(buf + sizeof(buf) - 4, "...", 4);
48 ret = snprintf(buf, sizeof(buf), "%s", asn1p_itoa(v->value.v_integer));
49 if(ret >= (ssize_t)sizeof(buf))
50 memcpy(buf + sizeof(buf) - 4, "...", 4);
52 case ATV_MIN: return "MIN";
53 case ATV_MAX: return "MAX";
54 case ATV_FALSE: return "FALSE";
55 case ATV_TRUE: return "TRUE";
57 ret = snprintf(buf, sizeof(buf), "{%d, %d}",
58 (int)(v->value.v_integer >> 4),
59 (int)(v->value.v_integer & 0xff));
60 if(ret >= (ssize_t)sizeof(buf))
61 memcpy(buf + sizeof(buf) - 4, "...", 4);
64 ret = snprintf(buf, sizeof(buf), "{%d, %d, %d, %d}",
65 (int)((v->value.v_integer >> 24) & 0xff),
66 (int)((v->value.v_integer >> 16) & 0xff),
67 (int)((v->value.v_integer >> 8) & 0xff),
68 (int)(v->value.v_integer & 0xff));
69 if(ret >= (ssize_t)sizeof(buf))
70 memcpy(buf + sizeof(buf) - 4, "...", 4);
74 /* Buffer is guaranteed to be null-terminated */
75 assert(v->value.string.buf[v->value.string.size] == '\0');
76 return (char *)v->value.string.buf;
86 * Compute number of bytes necessary
87 * to represend the binary value.
89 int bits = v->value.binary_vector.size_in_bits;
90 len = ((bits%8)?bits:(bits >> 2)) + sizeof("''H");
92 * Reallocate managed buffer
100 bitvector = v->value.binary_vector.bits;
106 for(i = 0; i < bits; i++) {
108 uc = bitvector[i>>3];
109 *ptr++ = ((uc >> (7-(i%8)))&1)?'1':'0';
112 static const char *hextable="0123456789ABCDEF";
116 for(i = 0; i < (bits >> 3); i++) {
117 *ptr++ = hextable[bitvector[i] >> 4];
118 *ptr++ = hextable[bitvector[i] & 0x0f];
122 *ptr++ = (bits%8)?'B':'H';
124 assert(len == (size_t)(ptr - managedptr));
133 assert(v->value.reference);
134 ref = v->value.reference;
135 reflen = ref->comp_count; /* Number of dots */
136 for(size_t i = 0; i < ref->comp_count; i++)
137 reflen += strlen(ref->components[i].name);
139 * Make sure we have a buffer of this size.
144 * Fill-up the buffer.
147 for(size_t i = 0; i < ref->comp_count; i++) {
150 for(nc = ref->components[i].name; *nc; nc++)
154 assert(reflen == (size_t)(ptr - managedptr));
159 case ATV_CHOICE_IDENTIFIER:
161 char *cid = v->value.choice_identifier.identifier;
162 char const *vptr = asn1f_printable_value(
163 v->value.choice_identifier.value);
167 if(!val) return "<memory allocation error>";
169 ENSURE(strlen(cid) + sizeof(": ") + strlen(val));
171 ret = snprintf(managedptr, managedptr_len + 1,
173 assert(ret >= 0 && (size_t)ret <= managedptr_len);
179 return "<some complex value>";
184 * Recursively invoke a given function over the given expr and all its
188 asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) {
189 asn1p_expr_t *expr = arg->expr;
195 if(expr->lhs_params && expr->spec_index == -1) {
197 for(i = 0; i < expr->specializations.pspecs_count; i++) {
198 arg->expr = expr->specializations.pspec[i].my_clone;
199 ret = asn1f_recurse_expr(arg, callback);
200 RET2RVAL(ret, rvalue);
202 arg->expr = expr; /* revert */
207 * Invoke the callback at this very level.
210 RET2RVAL(ret, rvalue);
213 * Recursively invoke myself
214 * to iterate over each element in the tree.
216 TQ_FOR(arg->expr, &(expr->members), next) {
217 assert(arg->expr->expr_type != A1TC_INVALID);
218 assert(arg->expr->parent_expr == expr);
219 ret = asn1f_recurse_expr(arg, callback);
220 RET2RVAL(ret, rvalue);
223 arg->expr = expr; /* Restore original position */
230 * Check that every child of a given expr has unique name or does not have any.
233 asn1f_check_unique_expr(arg_t *arg) {
237 TQ_FOR(expr, &(arg->expr->members), next) {
238 if(expr->Identifier) {
239 int ret = asn1f_check_unique_expr_child(arg, expr,
244 * No point of comparing this child with any other:
245 * this one does not have a name.
254 * Check that every preceeding child of the given expr is not
255 * having the name of the given one.
258 asn1f_check_unique_expr_child(arg_t *arg, asn1p_expr_t *child,
259 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b),
260 const char *opt_property_name) {
263 if(!opt_property_name) opt_property_name = "property";
266 assert(opt_compare || child->Identifier);
268 TQ_FOR(expr, &(arg->expr->members), next) {
275 * Compare according to the custom rule or default
279 ret = opt_compare(expr, child);
281 if(expr->Identifier == NULL
282 || expr->expr_type == A1TC_EXTENSIBLE)
284 ret = strcmp(expr->Identifier, child->Identifier);
288 FATAL("Clash detected: "
289 "\"%s\" at line %d has similar %s with "
305 asn1f_count_children(asn1p_expr_t *expr) {
309 TQ_FOR(child, &(expr->members), next) {
317 static char **known_types;
318 static int known_types_count;
319 static int known_types_size;
321 static int _known_types_cmp(const void *ap, const void *bp) {
322 const char *a = *(const char * const *)ap;
323 const char *b = *(const char * const *)bp;
328 asn1f_make_known_external_type(const char *type_name) {
331 /* Check for duplicates */
332 if(asn1f_check_known_external_type(type_name) == 0) {
337 /* Ensure enough space */
338 if(known_types_count <= known_types_size) {
339 int n = known_types_size ? known_types_size << 1 : 4;
341 p = realloc(known_types, n * sizeof(known_types[0]));
344 known_types_size = n;
347 tname = strdup(type_name);
348 if(!tname) return -1;
350 known_types[known_types_count++] = tname;
352 #ifdef HAVE_MERGESORT
357 (known_types, known_types_count, sizeof(known_types[0]),
364 asn1f_check_known_external_type(const char *type_name) {
365 if(known_types_count) {
366 void *p = bsearch(&type_name, known_types, known_types_count,
367 sizeof(known_types[0]), _known_types_cmp);