Newer
Older
char const *
asn1f_printable_reference(asn1p_ref_t *ref) {
if(ref) {
asn1p_value_t v;
v.type = ATV_REFERENCED;
v.value.reference = ref;
return asn1f_printable_value(&v);
} else {
return "<no ref>";
}
}
char const *
asn1f_printable_value(asn1p_value_t *v) {
static char buf[128];
static char *managedptr;
} else { \
managedptr_len = 0; \
return "<memory allocation error>"; \
} \
} \
} while(0)
if(v == NULL)
return "<no value>";
switch(v->type) {
case ATV_NOVALUE:
return "<NO VALUE>";
case ATV_REAL:
ret = snprintf(buf, sizeof(buf), "%f", v->value.v_double);
memcpy(buf + sizeof(buf) - 4, "...", 4);
return buf;
case ATV_INTEGER:
ret = snprintf(buf, sizeof(buf), "%" PRIdASN,
v->value.v_integer);
memcpy(buf + sizeof(buf) - 4, "...", 4);
return buf;
case ATV_MIN: return "MIN";
case ATV_MAX: return "MAX";
case ATV_FALSE: return "FALSE";
case ATV_TRUE: return "TRUE";
case ATV_TUPLE:
ret = snprintf(buf, sizeof(buf), "{%d, %d}",
(int)(v->value.v_integer >> 4),
(int)(v->value.v_integer & 0xff));
if(ret >= (ssize_t)sizeof(buf))
memcpy(buf + sizeof(buf) - 4, "...", 4);
return buf;
case ATV_QUADRUPLE:
ret = snprintf(buf, sizeof(buf), "{%d, %d, %d, %d}",
(int)((v->value.v_integer >> 24) & 0xff),
(int)((v->value.v_integer >> 16) & 0xff),
(int)((v->value.v_integer >> 8) & 0xff),
(int)(v->value.v_integer & 0xff));
if(ret >= (ssize_t)sizeof(buf))
memcpy(buf + sizeof(buf) - 4, "...", 4);
return buf;
case ATV_STRING:
case ATV_UNPARSED:
/* Buffer is guaranteed to be null-terminated */
assert(v->value.string.buf[v->value.string.size] == '\0');
case ATV_BITVECTOR:
{
uint8_t *bitvector;
char *ptr;
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
int i;
/*
* Compute number of bytes necessary
* to represend the binary value.
*/
int bits = v->value.binary_vector.size_in_bits;
len = ((bits%8)?bits:(bits >> 2)) + sizeof("''H");
/*
* Reallocate managed buffer
*/
ENSURE(len);
/*
* Fill the buffer.
*/
ptr = managedptr;
bitvector = v->value.binary_vector.bits;
*ptr++ = '\'';
if(bits%8) {
/*
* Dump bit by bit.
*/
for(i = 0; i < bits; i++) {
uint8_t uc;
uc = bitvector[i>>3];
*ptr++ = ((uc >> (7-(i%8)))&1)?'1':'0';
}
} else {
static const char *hextable="0123456789ABCDEF";
/*
* Dump byte by byte.
*/
for(i = 0; i < (bits >> 3); i++) {
*ptr++ = hextable[bitvector[i] >> 4];
*ptr++ = hextable[bitvector[i] & 0x0f];
}
}
*ptr++ = '\'';
*ptr++ = (bits%8)?'B':'H';
*ptr++ = 'H';
char *ptr;
int i;
assert(v->value.reference);
ref = v->value.reference;
reflen = ref->comp_count; /* Number of dots */
for(i = 0; i < ref->comp_count; i++)
reflen += strlen(ref->components[i].name);
/*
* Make sure we have a buffer of this size.
*/
ENSURE(reflen);
/*
* Fill-up the buffer.
*/
ptr = managedptr;
for(i = 0; i < ref->comp_count; i++) {
char *nc;
if(i) *ptr++ = '.';
for(nc = ref->components[i].name; *nc; nc++)
*ptr++ = *nc;
}
*ptr++ = '\0';
case ATV_CHOICE_IDENTIFIER:
{
char *cid = v->value.choice_identifier.identifier;
char const *vptr = asn1f_printable_value(
v->value.choice_identifier.value);
char *val;
val = strdup(vptr);
if(!val) return "<memory allocation error>";
ENSURE(strlen(cid) + sizeof(": ") + strlen(val));
ret = snprintf(managedptr, managedptr_len + 1,
"%s: %s", cid, val);
}
return "<some complex value>";
}
/*
* Recursively invoke a given function over the given expr and all its
* children.
*/
int
asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) {
asn1p_expr_t *expr = arg->expr;
int rvalue = 0;
int ret;
assert(expr);
if(expr->lhs_params && expr->spec_index == -1) {
int i;
for(i = 0; i < expr->specializations.pspecs_count; i++) {
arg->expr = expr->specializations.pspec[i].my_clone;
ret = asn1f_recurse_expr(arg, callback);
RET2RVAL(ret, rvalue);
}
arg->expr = expr; /* revert */
return rvalue;
}
/*
* Invoke the callback at this very level.
*/
ret = callback(arg);
RET2RVAL(ret, rvalue);
/*
* Recursively invoke myself
* to iterate over each element in the tree.
*/
TQ_FOR(arg->expr, &(expr->members), next) {
assert(arg->expr->expr_type != A1TC_INVALID);
ret = asn1f_recurse_expr(arg, callback);
RET2RVAL(ret, rvalue);
}
arg->expr = expr; /* Restore original position */
return rvalue;
}
/*
* Check that every child of a given expr has unique name or does not have any.
*/
int
asn1p_expr_t *expr;
int rvalue = 0;
TQ_FOR(expr, &(arg->expr->members), next) {
if(expr->Identifier) {
int ret = asn1f_check_unique_expr_child(arg, expr,
if(ret) rvalue = -1;
} else {
/*
* No point of comparing this child with any other:
* this one does not have a name.
*/
}
}
return rvalue;
}
/*
* Check that every preceeding child of the given expr is not
* having the name of the given one.
*/
int
asn1f_check_unique_expr_child(arg_t *arg, asn1p_expr_t *child,
int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b),
const char *opt_property_name) {
assert(child);
assert(opt_compare || child->Identifier);
TQ_FOR(expr, &(arg->expr->members), next) {
int ret;
if(expr == child)
break;
/*
* Compare according to the custom rule or default
* names comparisons.
*/
if(opt_compare) {
ret = opt_compare(expr, child);
} else {
if(expr->Identifier == NULL
|| expr->expr_type == A1TC_EXTENSIBLE)
continue;
ret = strcmp(expr->Identifier, child->Identifier);
"\"%s\" at line %d has similar %s with "
"\"%s\" at line %d",
expr->Identifier,
expr->_lineno,
}
int
asn1f_count_children(asn1p_expr_t *expr) {
asn1p_expr_t *child;
int count = 0;
TQ_FOR(child, &(expr->members), next) {
count++;
}
return count;
}
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
static char **known_types;
static int known_types_count;
static int known_types_size;
static int _known_types_cmp(const void *ap, const void *bp) {
const char *a = *(const char * const *)ap;
const char *b = *(const char * const *)bp;
return strcmp(a, b);
}
int
asn1f_make_known_external_type(const char *type_name) {
char *tname;
/* Check for duplicates */
if(asn1f_check_known_external_type(type_name) == 0) {
errno = EEXIST;
return -1;
}
/* Ensure enough space */
if(known_types_count <= known_types_size) {
int n = known_types_size ? known_types_size << 1 : 4;
void *p;
p = realloc(known_types, n * sizeof(known_types[0]));
if(!p) return -1;
known_types = p;
known_types_size = n;
}
tname = strdup(type_name);
if(!tname) return -1;
known_types[known_types_count++] = tname;
#ifdef HAVE_MERGESORT
mergesort
#else
qsort
#endif
(known_types, known_types_count, sizeof(known_types[0]),
_known_types_cmp);
return 0;
}
int
asn1f_check_known_external_type(const char *type_name) {
if(known_types_count) {
void *p = bsearch(&type_name, known_types, known_types_count,
sizeof(known_types[0]), _known_types_cmp);
if(p) return 0;
}