blob: 5fe69034f8b9449f515b7ded99288e9730988db8 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1fix_internal.h"
2
3
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;
22 static int managedptr_len;
23 int ret;
24
25#define ENSURE(len) do { \
26 if(len >= managedptr_len) { \
27 if(managedptr) \
28 free(managedptr); \
29 managedptr = malloc(len + 1); \
30 if(managedptr) { \
31 managedptr_len = len; \
32 } else { \
33 managedptr_len = 0; \
34 return "<memory allocation error>"; \
35 } \
36 } \
37 } while(0)
38
39 if(v == NULL)
40 return "<no value>";
41
42 switch(v->type) {
43 case ATV_NOVALUE:
44 return "<NO VALUE>";
45 case ATV_REFERENCED:
46 {
47 asn1p_ref_t *ref;
48 char reflen;
49 char *ptr;
50 int i;
51
52 assert(v->value.reference);
53 ref = v->value.reference;
54 reflen = ref->comp_count; /* Number of dots */
55 for(i = 0; i < ref->comp_count; i++)
56 reflen += strlen(ref->components[i].name);
57 /*
58 * Make sure we have a buffer of this size.
59 */
60 ENSURE(reflen);
61
62 /*
63 * Fill-up the buffer.
64 */
65 ptr = managedptr;
66 for(i = 0; i < ref->comp_count; i++) {
67 char *nc;
68 if(i) *ptr++ = '.';
69 for(nc = ref->components[i].name; *nc; nc++)
70 *ptr++ = *nc;
71 }
72 *ptr++ = '\0';
73 assert(reflen == (ptr - managedptr));
74 return managedptr;
75 }
76 case ATV_REAL:
77 ret = snprintf(buf, sizeof(buf), "%f", v->value.v_double);
78 if(ret >= sizeof(buf))
79 memcpy(buf + sizeof(buf) - 4, "...", 4);
80 return buf;
81 case ATV_INTEGER:
82 ret = snprintf(buf, sizeof(buf), "%lld",
83 (long long)v->value.v_integer);
84 if(ret >= sizeof(buf))
85 memcpy(buf + sizeof(buf) - 4, "...", 4);
86 return buf;
87 case ATV_MIN: return "MIN";
88 case ATV_MAX: return "MAX";
89 case ATV_FALSE: return "FALSE";
90 case ATV_TRUE: return "TRUE";
91 case ATV_STRING:
92 case ATV_UNPARSED:
93 /* Buffer is guaranteed to be null-terminated */
94 assert(v->value.string.buf[v->value.string.size] == '\0');
95 return v->value.string.buf;
96 case ATV_BITVECTOR:
97 {
98 uint8_t *bitvector;
99 char *ptr;
100 int len;
101 int i;
102 /*
103 * Compute number of bytes necessary
104 * to represend the binary value.
105 */
106 int bits = v->value.binary_vector.size_in_bits;
107 len = ((bits%8)?bits:(bits >> 2)) + sizeof("''H");
108 /*
109 * Reallocate managed buffer
110 */
111 ENSURE(len);
112
113 /*
114 * Fill the buffer.
115 */
116 ptr = managedptr;
117 bitvector = v->value.binary_vector.bits;
118 *ptr++ = '\'';
119 if(bits%8) {
120 /*
121 * Dump bit by bit.
122 */
123 for(i = 0; i < bits; i++) {
124 uint8_t uc;
125 uc = bitvector[i>>3];
126 *ptr++ = ((uc >> (7-(i%8)))&1)?'1':'0';
127 }
128 } else {
129 char hextable[16] = "0123456789ABCDEF";
130 /*
131 * Dump byte by byte.
132 */
133 for(i = 0; i < (bits >> 3); i++) {
134 *ptr++ = hextable[bitvector[i] >> 4];
135 *ptr++ = hextable[bitvector[i] & 0x0f];
136 }
137 }
138 *ptr++ = '\'';
139 *ptr++ = (bits%8)?'B':'H';
140 *ptr++ = 'H';
141 assert((ptr - managedptr) == len);
142 return managedptr;
143 }
144 }
145
146 return "<some complex value>";
147}
148
149
150/*
151 * Recursively invoke a given function over the given expr and all its
152 * children.
153 */
154int
155asn1f_recurse_expr(arg_t *arg, int (*callback)(arg_t *arg)) {
156 asn1p_expr_t *expr = arg->expr;
157 int rvalue = 0;
158 int ret;
159
160 assert(expr);
161
162 /*
163 * Invoke the callback at this very level.
164 */
165 ret = callback(arg);
166 RET2RVAL(ret, rvalue);
167
168 /*
169 * Recursively invoke myself
170 * to iterate over each element in the tree.
171 */
172 TQ_FOR(arg->expr, &(expr->members), next) {
173 assert(arg->expr->expr_type != A1TC_INVALID);
174 ret = asn1f_recurse_expr(arg, callback);
175 RET2RVAL(ret, rvalue);
176 }
177
178 arg->expr = expr; /* Restore original position */
179
180 return rvalue;
181}
182
183
184/*
185 * Check that every child of a given expr has unique name or does not have any.
186 */
187int
188asn1f_check_unique_expr(arg_t *arg,
189 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b)) {
190 asn1p_expr_t *expr;
191 int rvalue = 0;
192
193 TQ_FOR(expr, &(arg->expr->members), next) {
194 if(expr->Identifier) {
195 int ret = asn1f_check_unique_expr_child(arg, expr,
196 opt_compare);
197 if(ret) rvalue = -1;
198 } else {
199 /*
200 * No point of comparing this child with any other:
201 * this one does not have a name.
202 */
203 }
204 }
205
206 return rvalue;
207}
208
209/*
210 * Check that every preceeding child of the given expr is not
211 * having the name of the given one.
212 */
213int
214asn1f_check_unique_expr_child(arg_t *arg, asn1p_expr_t *child,
215 int (*opt_compare)(asn1p_expr_t *a, asn1p_expr_t *b)) {
216 asn1p_expr_t *expr;
217 int rvalue = 0;
218
219 assert(child);
220 assert(opt_compare || child->Identifier);
221
222 TQ_FOR(expr, &(arg->expr->members), next) {
223 int ret;
224
225 if(expr == child)
226 break;
227
228 /*
229 * Compare according to the custom rule or default
230 * names comparisons.
231 */
232 if(opt_compare) {
233 ret = opt_compare(expr, child);
234 } else {
235 if(expr->Identifier == NULL
236 || expr->expr_type == A1TC_EXTENSIBLE)
237 continue;
238 ret = strcasecmp(expr->Identifier, child->Identifier);
239 }
240
241 if(ret == 0) {
242 char *msg;
243 msg = opt_compare
244 ?"Expressions clash"
245 :"Identifiers name clash";
246 arg->eh(1,
247 "%s: "
248 "\"%s\" at line %d has similar %s with "
249 "\"%s\" at line %d",
250 msg,
251 expr->Identifier,
252 expr->_lineno,
253 opt_compare?"property":"name",
254 child->Identifier,
255 child->_lineno
256 );
257
258 rvalue = -1;
259 }
260 }
261
262 return rvalue;
263}
264
265int
266asn1f_count_children(asn1p_expr_t *expr) {
267 asn1p_expr_t *child;
268 int count = 0;
269
270 TQ_FOR(child, &(expr->members), next) {
271 count++;
272 }
273
274 return count;
275}
276