blob: 58ce284e7ced01b8da9e5cce05334efc046bce77 [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>
Lev Walkin3140e0e2004-08-18 04:50:37 +00007#include <asn1fix_export.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00008
9#include "asn1print.h"
10
11#define INDENT(fmt, args...) do { \
12 int __i = level; while(__i--) putchar(' '); \
13 printf(fmt, ##args); \
14 } while(0)
15
Lev Walkin3140e0e2004-08-18 04:50:37 +000016static int asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags);
17static int asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags);
18static int asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags);
19static int asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags);
20static int asn1print_params(asn1p_paramlist_t *pl,enum asn1print_flags flags);
21static int asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags);
22static int asn1print_constraint(asn1p_constraint_t *, enum asn1print_flags);
23static int asn1print_value(asn1p_value_t *val, enum asn1print_flags flags);
24static int asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags,
Lev Walkinf15320b2004-06-03 03:38:44 +000025 int level);
26
27/*
28 * Print the contents of the parsed ASN tree.
29 */
30int
Lev Walkin3140e0e2004-08-18 04:50:37 +000031asn1print(asn1p_t *asn, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000032 asn1p_module_t *mod;
33
34 if(asn == NULL) {
35 errno = EINVAL;
36 return -1;
37 }
38
39 TQ_FOR(mod, &(asn->modules), mod_next) {
Lev Walkin3140e0e2004-08-18 04:50:37 +000040 asn1print_module(asn, mod, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000041 }
42
43 return 0;
44}
45
46static int
Lev Walkin3140e0e2004-08-18 04:50:37 +000047asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000048 asn1p_expr_t *tc;
49
Lev Walkinf15320b2004-06-03 03:38:44 +000050 printf("\n%s ", mod->Identifier);
51 if(mod->module_oid) {
52 asn1print_oid(mod->module_oid, flags);
53 printf("\n");
54 }
55
56 printf("DEFINITIONS");
57
Lev Walkin3140e0e2004-08-18 04:50:37 +000058 if(mod->module_flags & MSF_TAG_INSTRUCTIONS)
59 printf(" TAG INSTRUCTIONS");
60 if(mod->module_flags & MSF_XER_INSTRUCTIONS)
61 printf(" XER INSTRUCTIONS");
Lev Walkinf15320b2004-06-03 03:38:44 +000062 if(mod->module_flags & MSF_EXPLICIT_TAGS)
63 printf(" EXPLICIT TAGS");
64 if(mod->module_flags & MSF_IMPLICIT_TAGS)
65 printf(" IMPLICIT TAGS");
66 if(mod->module_flags & MSF_AUTOMATIC_TAGS)
67 printf(" AUTOMATIC TAGS");
68 if(mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
69 printf(" EXTENSIBILITY IMPLIED");
70
71 printf(" ::=\n");
72 printf("BEGIN\n\n");
73
74 TQ_FOR(tc, &(mod->members), next) {
Lev Walkin3140e0e2004-08-18 04:50:37 +000075 asn1print_expr(asn, mod, tc, flags, 0);
Lev Walkinf15320b2004-06-03 03:38:44 +000076 printf("\n\n");
77 }
78
79 printf("END\n");
80
81 return 0;
82}
83
84static int
Lev Walkin3140e0e2004-08-18 04:50:37 +000085asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000086 int ac;
87 int accum = 0;
88
Lev Walkind9bd7752004-06-05 08:17:50 +000089 (void)flags; /* Unused argument */
90
Lev Walkinf15320b2004-06-03 03:38:44 +000091 printf("{");
92 for(ac = 0; ac < oid->arcs_count; ac++) {
93 if(accum + strlen(oid->arcs[ac].name?:"") > 50) {
94 printf("\n\t");
95 accum = 0;
96 } else if(ac) printf(" ");
97
98 if(oid->arcs[ac].name) {
99 printf("%s(%d)",
100 oid->arcs[ac].name,
101 (int)oid->arcs[ac].number);
102 accum += strlen(oid->arcs[ac].name);
103 } else {
104 printf("%d",
105 (int)oid->arcs[ac].number);
106 }
107 accum += 4;
108 }
109 printf(" }");
110
111 return 0;
112}
113
114static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000115asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000116 int cc;
117
Lev Walkind9bd7752004-06-05 08:17:50 +0000118 (void)flags; /* Unused argument */
119
Lev Walkinf15320b2004-06-03 03:38:44 +0000120 for(cc = 0; cc < ref->comp_count; cc++) {
121 if(cc) printf(".");
122 printf("%s", ref->components[cc].name);
123 }
124
125 return 0;
126}
127
128static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000129asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000130 struct asn1p_type_tag_s *tag = &tc->tag;
131
Lev Walkind9bd7752004-06-05 08:17:50 +0000132 (void)flags; /* Unused argument */
133
Lev Walkinf15320b2004-06-03 03:38:44 +0000134 if(tag->tag_class == TC_NOCLASS)
135 return 0;
136
137 printf("[");
138 switch(tag->tag_class) {
139 case TC_NOCLASS:
140 assert(tag->tag_class != TC_NOCLASS);
141 break;
142 case TC_UNIVERSAL: printf("UNIVERSAL "); break;
143 case TC_PRIVATE: printf("PRIVATE "); break;
144 case TC_APPLICATION: printf("APPLICATION "); break;
145 case TC_CONTEXT_SPECIFIC:
146 break;
147 }
148 printf("%lld]", (long long)tag->tag_value);
149
150 switch(tag->tag_mode) {
151 case TM_DEFAULT: break;
152 case TM_IMPLICIT: printf(" IMPLICIT"); break;
153 case TM_EXPLICIT: printf(" EXPLICIT"); break;
154 }
155
156 return 0;
157}
158
159static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000160asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000161
162 if(val == NULL)
163 return 0;
164
165 switch(val->type) {
166 case ATV_NOVALUE:
167 break;
168 case ATV_REFERENCED:
169 return asn1print_ref(val->value.reference, flags);
170 case ATV_INTEGER:
171 printf("%lld", (long long)val->value.v_integer);
172 return 0;
173 case ATV_MIN: printf("MIN"); return 0;
174 case ATV_MAX: printf("MAX"); return 0;
175 case ATV_FALSE: printf("FALSE"); return 0;
176 case ATV_TRUE: printf("TRUE"); return 0;
177 case ATV_REAL:
178 printf("%f", val->value.v_double);
179 return 0;
180 case ATV_STRING:
181 {
182 char *p = val->value.string.buf;
183 putchar('"');
184 if(strchr(p, '"')) {
185 /* Mask quotes */
186 for(; *p; p++) {
187 if(*p == '"')
188 putchar(*p);
189 putchar(*p);
190 }
191 } else {
192 fputs(p, stdout);
193 }
194 putchar('"');
195 }
196 return 0;
197 case ATV_UNPARSED:
198 fputs(val->value.string.buf, stdout);
199 return 0;
200 case ATV_BITVECTOR:
201 {
202 uint8_t *bitvector;
203 int bits;
204 int i;
205
206 bitvector = val->value.binary_vector.bits;
207 bits = val->value.binary_vector.size_in_bits;
208
209 printf("'");
210 if(bits%8) {
211 for(i = 0; i < bits; i++) {
212 uint8_t uc;
213 uc = bitvector[i>>3];
214 putchar(((uc >> (7-(i%8)))&1)?'1':'0');
215 }
216 printf("'B");
217 } else {
218 char hextable[16] = "0123456789ABCDEF";
219 for(i = 0; i < (bits>>3); i++) {
220 putchar(hextable[bitvector[i] >> 4]);
221 putchar(hextable[bitvector[i] & 0x0f]);
222 }
223 printf("'H");
224 }
225 }
226 }
227
228 assert(val->type || !"Unknown");
229
230 return 0;
231}
232
233static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000234asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000235 int symno = 0;
236
237 if(ct == 0) return 0;
238
239 if(ct->type == ACT_CA_SET)
240 printf("(");
241
242 switch(ct->type) {
243 case ACT_EL_VALUE:
244 asn1print_value(ct->value, flags);
245 break;
246 case ACT_EL_RANGE:
247 case ACT_EL_LLRANGE:
248 case ACT_EL_RLRANGE:
249 case ACT_EL_ULRANGE:
250 asn1print_value(ct->range_start, flags);
251 switch(ct->type) {
252 case ACT_EL_RANGE: printf(".."); break;
253 case ACT_EL_LLRANGE: printf("<.."); break;
254 case ACT_EL_RLRANGE: printf("..<"); break;
255 case ACT_EL_ULRANGE: printf("<..<"); break;
256 default: printf("?..?"); break;
257 }
258 asn1print_value(ct->range_stop, flags);
259 break;
260 case ACT_EL_EXT:
261 printf("...");
262 break;
263 case ACT_CT_SIZE:
264 case ACT_CT_FROM:
265 switch(ct->type) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000266 case ACT_CT_SIZE: printf("SIZE("); break;
267 case ACT_CT_FROM: printf("FROM("); break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000268 default: printf("??? ("); break;
269 }
270 assert(ct->el_count != 0);
271 assert(ct->el_count == 1);
272 asn1print_constraint(ct->elements[0], flags);
273 printf(")");
274 break;
275 case ACT_CT_WCOMP:
276 case ACT_CT_WCOMPS:
277 printf("???");
278 break;
279 case ACT_CA_SET: symno++;
280 case ACT_CA_CRC: symno++;
281 case ACT_CA_CSV: symno++;
282 case ACT_CA_UNI: symno++;
283 case ACT_CA_INT: symno++;
284 case ACT_CA_EXC:
285 {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000286 char *symtable[] = { " EXCEPT ", " ^ ", " | ", ",",
Lev Walkinf15320b2004-06-03 03:38:44 +0000287 "", "(" };
288 int i;
289 for(i = 0; i < ct->el_count; i++) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000290 enum asn1print_flags nflags = flags;
Lev Walkinf15320b2004-06-03 03:38:44 +0000291 if(i) fputs(symtable[symno], stdout);
292 if(ct->type == ACT_CA_CRC) fputs("{", stdout);
293 asn1print_constraint(ct->elements[i], nflags);
294 if(ct->type == ACT_CA_CRC) fputs("}", stdout);
295 if(i+1 < ct->el_count
296 && ct->type == ACT_CA_SET)
297 fputs(")", stdout);
298 }
299 }
300 break;
301 case ACT_INVALID:
302 assert(ct->type != ACT_INVALID);
303 break;
304 }
305
306 if(ct->type == ACT_CA_SET)
307 printf(")");
308
309 return 0;
310}
311
312static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000313asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000314 if(pl) {
315 int i;
316 printf("{");
317 for(i = 0; i < pl->params_count; i++) {
318 if(i) printf(", ");
319 if(pl->params[i].governor) {
320 asn1print_ref(pl->params[i].governor, flags);
321 printf(":");
322 }
323 printf("%s", pl->params[i].argument);
324 }
325 printf("}");
326 }
327
328 return 0;
329}
330
331static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000332asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000333 if(wx) {
334 asn1p_wsyntx_chunk_t *wc;
335 printf(" WITH SYNTAX {");
336 TQ_FOR(wc, &(wx->chunks), next) {
337 if(wc->ref) {
338 asn1print_ref(wc->ref, flags);
339 } else {
340 fwrite(wc->buf, 1, wc->len, stdout);
341 }
342 }
343 printf("}\n");
344 }
345
346 return 0;
347}
348
349static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000350asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
351 switch(edge->type) {
352 case ARE_MIN: printf("MIN"); break;
353 case ARE_MAX: printf("MAX"); break;
354 case ARE_VALUE:
355 if(as_char) {
356 printf("\"%c\"", (unsigned char)edge->value);
357 } else {
358 printf("%lld", (long long)edge->value);
359 }
360 }
361 return 0;
362}
363
364static int
365asn1print_constraint_explain_type(asn1p_expr_type_e expr_type, asn1p_constraint_t *ct, enum asn1p_constraint_type_e type) {
366 asn1cnst_range_t *range;
367 int as_char = (type==ACT_CT_FROM);
368 int i;
369
370 range = asn1constraint_compute_PER_range(expr_type, ct, type, 0, 0);
371 if(!range) return -1;
372
373 switch(type) {
374 case ACT_CT_FROM: printf("(FROM("); break;
375 case ACT_CT_SIZE: printf("(SIZE("); break;
376 default: printf("("); break;
377 }
378 for(i = -1; i < range->el_count; i++) {
379 asn1cnst_range_t *r;
380 if(i == -1) {
381 if(range->el_count) continue;
382 r = range;
383 } else {
384 r = range->elements[i];
385 }
386 if(i > 0) {
387 printf(" | ");
388 }
389 asn1print_crange_value(&r->left, as_char);
390 if(r->left.type != r->right.type
391 || r->left.value != r->right.value) {
392 printf("..");
393 asn1print_crange_value(&r->right, as_char);
394 }
395 }
396 if(range->extensible)
397 printf(",...");
398 printf(type==ACT_EL_RANGE?")":"))");
399
400 if(range->empty_constraint)
401 printf(":Empty!");
402
403 asn1constraint_range_free(range);
404 return 0;
405}
406
407static int
408asn1print_constraint_explain(asn1p_expr_type_e expr_type,
409 asn1p_constraint_t *ct) {
410
411 asn1print_constraint_explain_type(expr_type, ct, ACT_EL_RANGE);
412 printf(" ");
413 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_SIZE);
414 printf(" ");
415 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_FROM);
416
417 return 0;
418}
419
420static int
421asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000422
423 if(flags & APF_LINE_COMMENTS)
424 INDENT("-- #line %d\n", tc->_lineno);
425 if(tc->Identifier)
426 INDENT("%s", tc->Identifier);
427
428 if(tc->params) {
429 asn1print_params(tc->params, flags);
430 }
431
432 if(tc->meta_type != AMT_VALUE
433 && tc->expr_type != A1TC_EXTENSIBLE) {
434 if(level) {
435 if(tc->Identifier)
436 printf("\t");
437 } else {
438 printf(" ::=");
439 }
440 }
441
442 if(tc->tag.tag_class) {
443 printf(" ");
444 asn1print_tag(tc, flags);
445 }
446
447 switch(tc->expr_type) {
448 case A1TC_EXTENSIBLE:
449 if(tc->value) {
450 printf("!");
451 asn1print_value(tc->value, flags);
452 }
453 break;
454 case A1TC_REFERENCE:
455 case A1TC_UNIVERVAL:
456 case A1TC_PARAMETRIZED:
457 break;
458 case A1TC_CLASSDEF:
459 printf(" CLASS");
460 break;
461 case A1TC_CLASSFIELD:
462 /* Nothing to print here */
463 break;
464 default:
465 {
466 char *p = ASN_EXPR_TYPE2STR(tc->expr_type);
467 printf(" %s", p?p:"<unknown type!>");
468 }
469 break;
470 }
471
472 if(tc->reference) {
473 printf(" ");
474 asn1print_ref(tc->reference, flags);
475 }
476
477 /*
478 * Display the descendants (children) of the current type.
479 */
480 if(TQ_FIRST(&(tc->members))) {
481 asn1p_expr_t *se; /* SubExpression */
482
483 if((tc->expr_type != ASN_CONSTR_SEQUENCE_OF
484 && tc->expr_type != ASN_CONSTR_SET_OF)
485 || TQ_FIRST(&(tc->members))->expr_type & ASN_CONSTR_MASK)
486 printf(" {\n");
487
488 TQ_FOR(se, &(tc->members), next) {
489 /*
490 * Print the expression as it were stand-alone type.
491 */
Lev Walkin3140e0e2004-08-18 04:50:37 +0000492 asn1print_expr(asn, mod, se, flags, level + 4);
Lev Walkinf15320b2004-06-03 03:38:44 +0000493 switch(se->marker) {
494 case EM_NOMARK: break;
495 case EM_OPTIONAL: printf(" OPTIONAL"); break;
496 case EM_DEFAULT: printf(" DEFAULT <?>"); break;
497 }
498 if(TQ_NEXT(se, next)) {
499 printf(",");
500 INDENT("\n");
501 }
502 }
503
504 if((tc->expr_type != ASN_CONSTR_SEQUENCE_OF
505 && tc->expr_type != ASN_CONSTR_SET_OF)
506 || TQ_FIRST(&(tc->members))->expr_type & ASN_CONSTR_MASK) {
507 printf("\n");
508 INDENT("}");
509 }
510 }
511
512 if(tc->with_syntax)
513 asn1print_with_syntax(tc->with_syntax, flags);
514
515 if(tc->constraints) {
516 printf(" ");
517 asn1print_constraint(tc->constraints, flags);
518 }
Lev Walkin3140e0e2004-08-18 04:50:37 +0000519
Lev Walkinf15320b2004-06-03 03:38:44 +0000520 if(tc->unique) {
521 printf(" UNIQUE");
522 }
523
524 if(tc->meta_type == AMT_VALUE
525 && tc->expr_type != A1TC_EXTENSIBLE) {
526 if(tc->expr_type == A1TC_UNIVERVAL)
527 printf("(");
528 else
529 printf(" ::= ");
530 asn1print_value(tc->value, flags);
531 if(tc->expr_type == A1TC_UNIVERVAL)
532 printf(")");
533 }
534
Lev Walkin3140e0e2004-08-18 04:50:37 +0000535 if(flags & APF_DEBUG_CONSTRAINTS) {
536 asn1p_expr_t *top_parent;
537
538 if(tc->combined_constraints) {
539 printf("\n-- Combined constraints: ");
540 asn1print_constraint(tc->combined_constraints, flags);
541 }
542
543 top_parent = asn1f_find_terminal_type_ex(asn, mod, tc, NULL);
544 if(top_parent) {
545 printf("\n-- PER-visible constraints: ");
546 asn1print_constraint_explain(top_parent->expr_type,
547 tc->combined_constraints);
548 }
549 }
550
Lev Walkinf15320b2004-06-03 03:38:44 +0000551 return 0;
552}
Lev Walkin3140e0e2004-08-18 04:50:37 +0000553