blob: 9c2fed70e695d9b71fabde288c7c941729de8a8f [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include <stdio.h>
2#include <string.h>
3#include <errno.h>
4#include <assert.h>
5
6#include <asn1parser.h>
7
8#include "asn1print.h"
9
10#define INDENT(fmt, args...) do { \
11 int __i = level; while(__i--) putchar(' '); \
12 printf(fmt, ##args); \
13 } while(0)
14
15static int asn1print_module(asn1p_module_t *mod, enum asn1print_flags_e flags);
16static int asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags_e flags);
17static int asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags_e flags);
18static int asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags_e flags);
19static int asn1print_params(asn1p_paramlist_t *pl,enum asn1print_flags_e flags);
20static int asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags_e flags);
21static int asn1print_constraint(asn1p_constraint_t *, enum asn1print_flags_e);
22static int asn1print_value(asn1p_value_t *val, enum asn1print_flags_e flags);
23static int asn1print_expr(asn1p_expr_t *tc, enum asn1print_flags_e flags,
24 int level);
25
26/*
27 * Print the contents of the parsed ASN tree.
28 */
29int
30asn1print(asn1p_t *asn, enum asn1print_flags_e flags) {
31 asn1p_module_t *mod;
32
33 if(asn == NULL) {
34 errno = EINVAL;
35 return -1;
36 }
37
38 TQ_FOR(mod, &(asn->modules), mod_next) {
39 asn1print_module(mod, flags);
40 }
41
42 return 0;
43}
44
45static int
46asn1print_module(asn1p_module_t *mod, enum asn1print_flags_e flags) {
47 asn1p_expr_t *tc;
48
Lev Walkinf15320b2004-06-03 03:38:44 +000049 printf("\n%s ", mod->Identifier);
50 if(mod->module_oid) {
51 asn1print_oid(mod->module_oid, flags);
52 printf("\n");
53 }
54
55 printf("DEFINITIONS");
56
57 if(mod->module_flags & MSF_EXPLICIT_TAGS)
58 printf(" EXPLICIT TAGS");
59 if(mod->module_flags & MSF_IMPLICIT_TAGS)
60 printf(" IMPLICIT TAGS");
61 if(mod->module_flags & MSF_AUTOMATIC_TAGS)
62 printf(" AUTOMATIC TAGS");
63 if(mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
64 printf(" EXTENSIBILITY IMPLIED");
65
66 printf(" ::=\n");
67 printf("BEGIN\n\n");
68
69 TQ_FOR(tc, &(mod->members), next) {
70 asn1print_expr(tc, flags, 0);
71 printf("\n\n");
72 }
73
74 printf("END\n");
75
76 return 0;
77}
78
79static int
80asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags_e flags) {
81 int ac;
82 int accum = 0;
83
Lev Walkind9bd7752004-06-05 08:17:50 +000084 (void)flags; /* Unused argument */
85
Lev Walkinf15320b2004-06-03 03:38:44 +000086 printf("{");
87 for(ac = 0; ac < oid->arcs_count; ac++) {
88 if(accum + strlen(oid->arcs[ac].name?:"") > 50) {
89 printf("\n\t");
90 accum = 0;
91 } else if(ac) printf(" ");
92
93 if(oid->arcs[ac].name) {
94 printf("%s(%d)",
95 oid->arcs[ac].name,
96 (int)oid->arcs[ac].number);
97 accum += strlen(oid->arcs[ac].name);
98 } else {
99 printf("%d",
100 (int)oid->arcs[ac].number);
101 }
102 accum += 4;
103 }
104 printf(" }");
105
106 return 0;
107}
108
109static int
110asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags_e flags) {
111 int cc;
112
Lev Walkind9bd7752004-06-05 08:17:50 +0000113 (void)flags; /* Unused argument */
114
Lev Walkinf15320b2004-06-03 03:38:44 +0000115 for(cc = 0; cc < ref->comp_count; cc++) {
116 if(cc) printf(".");
117 printf("%s", ref->components[cc].name);
118 }
119
120 return 0;
121}
122
123static int
124asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags_e flags) {
125 struct asn1p_type_tag_s *tag = &tc->tag;
126
Lev Walkind9bd7752004-06-05 08:17:50 +0000127 (void)flags; /* Unused argument */
128
Lev Walkinf15320b2004-06-03 03:38:44 +0000129 if(tag->tag_class == TC_NOCLASS)
130 return 0;
131
132 printf("[");
133 switch(tag->tag_class) {
134 case TC_NOCLASS:
135 assert(tag->tag_class != TC_NOCLASS);
136 break;
137 case TC_UNIVERSAL: printf("UNIVERSAL "); break;
138 case TC_PRIVATE: printf("PRIVATE "); break;
139 case TC_APPLICATION: printf("APPLICATION "); break;
140 case TC_CONTEXT_SPECIFIC:
141 break;
142 }
143 printf("%lld]", (long long)tag->tag_value);
144
145 switch(tag->tag_mode) {
146 case TM_DEFAULT: break;
147 case TM_IMPLICIT: printf(" IMPLICIT"); break;
148 case TM_EXPLICIT: printf(" EXPLICIT"); break;
149 }
150
151 return 0;
152}
153
154static int
155asn1print_value(asn1p_value_t *val, enum asn1print_flags_e flags) {
156
157 if(val == NULL)
158 return 0;
159
160 switch(val->type) {
161 case ATV_NOVALUE:
162 break;
163 case ATV_REFERENCED:
164 return asn1print_ref(val->value.reference, flags);
165 case ATV_INTEGER:
166 printf("%lld", (long long)val->value.v_integer);
167 return 0;
168 case ATV_MIN: printf("MIN"); return 0;
169 case ATV_MAX: printf("MAX"); return 0;
170 case ATV_FALSE: printf("FALSE"); return 0;
171 case ATV_TRUE: printf("TRUE"); return 0;
172 case ATV_REAL:
173 printf("%f", val->value.v_double);
174 return 0;
175 case ATV_STRING:
176 {
177 char *p = val->value.string.buf;
178 putchar('"');
179 if(strchr(p, '"')) {
180 /* Mask quotes */
181 for(; *p; p++) {
182 if(*p == '"')
183 putchar(*p);
184 putchar(*p);
185 }
186 } else {
187 fputs(p, stdout);
188 }
189 putchar('"');
190 }
191 return 0;
192 case ATV_UNPARSED:
193 fputs(val->value.string.buf, stdout);
194 return 0;
195 case ATV_BITVECTOR:
196 {
197 uint8_t *bitvector;
198 int bits;
199 int i;
200
201 bitvector = val->value.binary_vector.bits;
202 bits = val->value.binary_vector.size_in_bits;
203
204 printf("'");
205 if(bits%8) {
206 for(i = 0; i < bits; i++) {
207 uint8_t uc;
208 uc = bitvector[i>>3];
209 putchar(((uc >> (7-(i%8)))&1)?'1':'0');
210 }
211 printf("'B");
212 } else {
213 char hextable[16] = "0123456789ABCDEF";
214 for(i = 0; i < (bits>>3); i++) {
215 putchar(hextable[bitvector[i] >> 4]);
216 putchar(hextable[bitvector[i] & 0x0f]);
217 }
218 printf("'H");
219 }
220 }
221 }
222
223 assert(val->type || !"Unknown");
224
225 return 0;
226}
227
228static int
229asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags_e flags) {
230 int symno = 0;
231
232 if(ct == 0) return 0;
233
234 if(ct->type == ACT_CA_SET)
235 printf("(");
236
237 switch(ct->type) {
238 case ACT_EL_VALUE:
239 asn1print_value(ct->value, flags);
240 break;
241 case ACT_EL_RANGE:
242 case ACT_EL_LLRANGE:
243 case ACT_EL_RLRANGE:
244 case ACT_EL_ULRANGE:
245 asn1print_value(ct->range_start, flags);
246 switch(ct->type) {
247 case ACT_EL_RANGE: printf(".."); break;
248 case ACT_EL_LLRANGE: printf("<.."); break;
249 case ACT_EL_RLRANGE: printf("..<"); break;
250 case ACT_EL_ULRANGE: printf("<..<"); break;
251 default: printf("?..?"); break;
252 }
253 asn1print_value(ct->range_stop, flags);
254 break;
255 case ACT_EL_EXT:
256 printf("...");
257 break;
258 case ACT_CT_SIZE:
259 case ACT_CT_FROM:
260 switch(ct->type) {
261 case ACT_CT_SIZE: printf("SIZE ("); break;
262 case ACT_CT_FROM: printf("FROM ("); break;
263 default: printf("??? ("); break;
264 }
265 assert(ct->el_count != 0);
266 assert(ct->el_count == 1);
267 asn1print_constraint(ct->elements[0], flags);
268 printf(")");
269 break;
270 case ACT_CT_WCOMP:
271 case ACT_CT_WCOMPS:
272 printf("???");
273 break;
274 case ACT_CA_SET: symno++;
275 case ACT_CA_CRC: symno++;
276 case ACT_CA_CSV: symno++;
277 case ACT_CA_UNI: symno++;
278 case ACT_CA_INT: symno++;
279 case ACT_CA_EXC:
280 {
281 char *symtable[] = { " EXCEPT ", "^", "|", ",",
282 "", "(" };
283 int i;
284 for(i = 0; i < ct->el_count; i++) {
285 enum asn1print_flags_e nflags = flags;
286 if(i) fputs(symtable[symno], stdout);
287 if(ct->type == ACT_CA_CRC) fputs("{", stdout);
288 asn1print_constraint(ct->elements[i], nflags);
289 if(ct->type == ACT_CA_CRC) fputs("}", stdout);
290 if(i+1 < ct->el_count
291 && ct->type == ACT_CA_SET)
292 fputs(")", stdout);
293 }
294 }
295 break;
296 case ACT_INVALID:
297 assert(ct->type != ACT_INVALID);
298 break;
299 }
300
301 if(ct->type == ACT_CA_SET)
302 printf(")");
303
304 return 0;
305}
306
307static int
308asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags_e flags) {
309 if(pl) {
310 int i;
311 printf("{");
312 for(i = 0; i < pl->params_count; i++) {
313 if(i) printf(", ");
314 if(pl->params[i].governor) {
315 asn1print_ref(pl->params[i].governor, flags);
316 printf(":");
317 }
318 printf("%s", pl->params[i].argument);
319 }
320 printf("}");
321 }
322
323 return 0;
324}
325
326static int
327asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags_e flags) {
328 if(wx) {
329 asn1p_wsyntx_chunk_t *wc;
330 printf(" WITH SYNTAX {");
331 TQ_FOR(wc, &(wx->chunks), next) {
332 if(wc->ref) {
333 asn1print_ref(wc->ref, flags);
334 } else {
335 fwrite(wc->buf, 1, wc->len, stdout);
336 }
337 }
338 printf("}\n");
339 }
340
341 return 0;
342}
343
344static int
345asn1print_expr(asn1p_expr_t *tc, enum asn1print_flags_e flags, int level) {
346
347 if(flags & APF_LINE_COMMENTS)
348 INDENT("-- #line %d\n", tc->_lineno);
349 if(tc->Identifier)
350 INDENT("%s", tc->Identifier);
351
352 if(tc->params) {
353 asn1print_params(tc->params, flags);
354 }
355
356 if(tc->meta_type != AMT_VALUE
357 && tc->expr_type != A1TC_EXTENSIBLE) {
358 if(level) {
359 if(tc->Identifier)
360 printf("\t");
361 } else {
362 printf(" ::=");
363 }
364 }
365
366 if(tc->tag.tag_class) {
367 printf(" ");
368 asn1print_tag(tc, flags);
369 }
370
371 switch(tc->expr_type) {
372 case A1TC_EXTENSIBLE:
373 if(tc->value) {
374 printf("!");
375 asn1print_value(tc->value, flags);
376 }
377 break;
378 case A1TC_REFERENCE:
379 case A1TC_UNIVERVAL:
380 case A1TC_PARAMETRIZED:
381 break;
382 case A1TC_CLASSDEF:
383 printf(" CLASS");
384 break;
385 case A1TC_CLASSFIELD:
386 /* Nothing to print here */
387 break;
388 default:
389 {
390 char *p = ASN_EXPR_TYPE2STR(tc->expr_type);
391 printf(" %s", p?p:"<unknown type!>");
392 }
393 break;
394 }
395
396 if(tc->reference) {
397 printf(" ");
398 asn1print_ref(tc->reference, flags);
399 }
400
401 /*
402 * Display the descendants (children) of the current type.
403 */
404 if(TQ_FIRST(&(tc->members))) {
405 asn1p_expr_t *se; /* SubExpression */
406
407 if((tc->expr_type != ASN_CONSTR_SEQUENCE_OF
408 && tc->expr_type != ASN_CONSTR_SET_OF)
409 || TQ_FIRST(&(tc->members))->expr_type & ASN_CONSTR_MASK)
410 printf(" {\n");
411
412 TQ_FOR(se, &(tc->members), next) {
413 /*
414 * Print the expression as it were stand-alone type.
415 */
416 asn1print_expr(se, flags, level + 4);
417 switch(se->marker) {
418 case EM_NOMARK: break;
419 case EM_OPTIONAL: printf(" OPTIONAL"); break;
420 case EM_DEFAULT: printf(" DEFAULT <?>"); break;
421 }
422 if(TQ_NEXT(se, next)) {
423 printf(",");
424 INDENT("\n");
425 }
426 }
427
428 if((tc->expr_type != ASN_CONSTR_SEQUENCE_OF
429 && tc->expr_type != ASN_CONSTR_SET_OF)
430 || TQ_FIRST(&(tc->members))->expr_type & ASN_CONSTR_MASK) {
431 printf("\n");
432 INDENT("}");
433 }
434 }
435
436 if(tc->with_syntax)
437 asn1print_with_syntax(tc->with_syntax, flags);
438
439 if(tc->constraints) {
440 printf(" ");
441 asn1print_constraint(tc->constraints, flags);
442 }
443 if(tc->unique) {
444 printf(" UNIQUE");
445 }
446
447 if(tc->meta_type == AMT_VALUE
448 && tc->expr_type != A1TC_EXTENSIBLE) {
449 if(tc->expr_type == A1TC_UNIVERVAL)
450 printf("(");
451 else
452 printf(" ::= ");
453 asn1print_value(tc->value, flags);
454 if(tc->expr_type == A1TC_UNIVERVAL)
455 printf(")");
456 }
457
458 return 0;
459}