blob: c90e966552fb4634dcccf055bba61c0fc50a7c88 [file] [log] [blame]
vlmfa67ddc2004-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>
vlm4808c702004-08-18 04:50:37 +00007#include <asn1fix_export.h>
vlm04a79e62004-08-18 05:41:05 +00008#include <asn1fix_crange.h>
vlmfa67ddc2004-06-03 03:38:44 +00009
10#include "asn1print.h"
11
12#define INDENT(fmt, args...) do { \
13 int __i = level; while(__i--) putchar(' '); \
14 printf(fmt, ##args); \
15 } while(0)
16
vlm4808c702004-08-18 04:50:37 +000017static int asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags);
18static int asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags);
19static int asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags);
20static int asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags);
21static int asn1print_params(asn1p_paramlist_t *pl,enum asn1print_flags flags);
22static int asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags);
23static int asn1print_constraint(asn1p_constraint_t *, enum asn1print_flags);
24static int asn1print_value(asn1p_value_t *val, enum asn1print_flags flags);
25static int asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags,
vlmfa67ddc2004-06-03 03:38:44 +000026 int level);
27
28/*
29 * Print the contents of the parsed ASN tree.
30 */
31int
vlm4808c702004-08-18 04:50:37 +000032asn1print(asn1p_t *asn, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +000033 asn1p_module_t *mod;
34
35 if(asn == NULL) {
36 errno = EINVAL;
37 return -1;
38 }
39
40 TQ_FOR(mod, &(asn->modules), mod_next) {
vlm4808c702004-08-18 04:50:37 +000041 asn1print_module(asn, mod, flags);
vlmfa67ddc2004-06-03 03:38:44 +000042 }
43
44 return 0;
45}
46
47static int
vlm4808c702004-08-18 04:50:37 +000048asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +000049 asn1p_expr_t *tc;
50
vlmfa67ddc2004-06-03 03:38:44 +000051 printf("\n%s ", mod->Identifier);
52 if(mod->module_oid) {
53 asn1print_oid(mod->module_oid, flags);
54 printf("\n");
55 }
56
57 printf("DEFINITIONS");
58
vlm4808c702004-08-18 04:50:37 +000059 if(mod->module_flags & MSF_TAG_INSTRUCTIONS)
60 printf(" TAG INSTRUCTIONS");
61 if(mod->module_flags & MSF_XER_INSTRUCTIONS)
62 printf(" XER INSTRUCTIONS");
vlmfa67ddc2004-06-03 03:38:44 +000063 if(mod->module_flags & MSF_EXPLICIT_TAGS)
64 printf(" EXPLICIT TAGS");
65 if(mod->module_flags & MSF_IMPLICIT_TAGS)
66 printf(" IMPLICIT TAGS");
67 if(mod->module_flags & MSF_AUTOMATIC_TAGS)
68 printf(" AUTOMATIC TAGS");
69 if(mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
70 printf(" EXTENSIBILITY IMPLIED");
71
72 printf(" ::=\n");
73 printf("BEGIN\n\n");
74
75 TQ_FOR(tc, &(mod->members), next) {
vlm4808c702004-08-18 04:50:37 +000076 asn1print_expr(asn, mod, tc, flags, 0);
vlm00ad2822004-08-20 13:24:28 +000077 if(flags & APF_DEBUG_CONSTRAINTS)
78 printf("\n");
79 else
80 printf("\n\n");
vlmfa67ddc2004-06-03 03:38:44 +000081 }
82
83 printf("END\n");
84
85 return 0;
86}
87
88static int
vlm4808c702004-08-18 04:50:37 +000089asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +000090 int ac;
91 int accum = 0;
92
vlmb42843a2004-06-05 08:17:50 +000093 (void)flags; /* Unused argument */
94
vlmfa67ddc2004-06-03 03:38:44 +000095 printf("{");
96 for(ac = 0; ac < oid->arcs_count; ac++) {
97 if(accum + strlen(oid->arcs[ac].name?:"") > 50) {
98 printf("\n\t");
99 accum = 0;
100 } else if(ac) printf(" ");
101
102 if(oid->arcs[ac].name) {
103 printf("%s(%d)",
104 oid->arcs[ac].name,
105 (int)oid->arcs[ac].number);
106 accum += strlen(oid->arcs[ac].name);
107 } else {
108 printf("%d",
109 (int)oid->arcs[ac].number);
110 }
111 accum += 4;
112 }
113 printf(" }");
114
115 return 0;
116}
117
118static int
vlm4808c702004-08-18 04:50:37 +0000119asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000120 int cc;
121
vlmb42843a2004-06-05 08:17:50 +0000122 (void)flags; /* Unused argument */
123
vlmfa67ddc2004-06-03 03:38:44 +0000124 for(cc = 0; cc < ref->comp_count; cc++) {
125 if(cc) printf(".");
126 printf("%s", ref->components[cc].name);
127 }
128
129 return 0;
130}
131
132static int
vlm4808c702004-08-18 04:50:37 +0000133asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000134 struct asn1p_type_tag_s *tag = &tc->tag;
135
vlmb42843a2004-06-05 08:17:50 +0000136 (void)flags; /* Unused argument */
137
vlmfa67ddc2004-06-03 03:38:44 +0000138 if(tag->tag_class == TC_NOCLASS)
139 return 0;
140
141 printf("[");
142 switch(tag->tag_class) {
143 case TC_NOCLASS:
144 assert(tag->tag_class != TC_NOCLASS);
145 break;
146 case TC_UNIVERSAL: printf("UNIVERSAL "); break;
147 case TC_PRIVATE: printf("PRIVATE "); break;
148 case TC_APPLICATION: printf("APPLICATION "); break;
149 case TC_CONTEXT_SPECIFIC:
150 break;
151 }
152 printf("%lld]", (long long)tag->tag_value);
153
154 switch(tag->tag_mode) {
155 case TM_DEFAULT: break;
156 case TM_IMPLICIT: printf(" IMPLICIT"); break;
157 case TM_EXPLICIT: printf(" EXPLICIT"); break;
158 }
159
160 return 0;
161}
162
163static int
vlm4808c702004-08-18 04:50:37 +0000164asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000165
166 if(val == NULL)
167 return 0;
168
169 switch(val->type) {
170 case ATV_NOVALUE:
171 break;
172 case ATV_REFERENCED:
173 return asn1print_ref(val->value.reference, flags);
174 case ATV_INTEGER:
175 printf("%lld", (long long)val->value.v_integer);
176 return 0;
177 case ATV_MIN: printf("MIN"); return 0;
178 case ATV_MAX: printf("MAX"); return 0;
179 case ATV_FALSE: printf("FALSE"); return 0;
180 case ATV_TRUE: printf("TRUE"); return 0;
181 case ATV_REAL:
182 printf("%f", val->value.v_double);
183 return 0;
184 case ATV_STRING:
185 {
186 char *p = val->value.string.buf;
187 putchar('"');
188 if(strchr(p, '"')) {
189 /* Mask quotes */
190 for(; *p; p++) {
191 if(*p == '"')
192 putchar(*p);
193 putchar(*p);
194 }
195 } else {
196 fputs(p, stdout);
197 }
198 putchar('"');
199 }
200 return 0;
201 case ATV_UNPARSED:
202 fputs(val->value.string.buf, stdout);
203 return 0;
204 case ATV_BITVECTOR:
205 {
206 uint8_t *bitvector;
207 int bits;
208 int i;
209
210 bitvector = val->value.binary_vector.bits;
211 bits = val->value.binary_vector.size_in_bits;
212
213 printf("'");
214 if(bits%8) {
215 for(i = 0; i < bits; i++) {
216 uint8_t uc;
217 uc = bitvector[i>>3];
218 putchar(((uc >> (7-(i%8)))&1)?'1':'0');
219 }
220 printf("'B");
221 } else {
222 char hextable[16] = "0123456789ABCDEF";
223 for(i = 0; i < (bits>>3); i++) {
224 putchar(hextable[bitvector[i] >> 4]);
225 putchar(hextable[bitvector[i] & 0x0f]);
226 }
227 printf("'H");
228 }
229 }
230 }
231
232 assert(val->type || !"Unknown");
233
234 return 0;
235}
236
237static int
vlm4808c702004-08-18 04:50:37 +0000238asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000239 int symno = 0;
240
241 if(ct == 0) return 0;
242
243 if(ct->type == ACT_CA_SET)
244 printf("(");
245
246 switch(ct->type) {
247 case ACT_EL_VALUE:
248 asn1print_value(ct->value, flags);
249 break;
250 case ACT_EL_RANGE:
251 case ACT_EL_LLRANGE:
252 case ACT_EL_RLRANGE:
253 case ACT_EL_ULRANGE:
254 asn1print_value(ct->range_start, flags);
255 switch(ct->type) {
256 case ACT_EL_RANGE: printf(".."); break;
257 case ACT_EL_LLRANGE: printf("<.."); break;
258 case ACT_EL_RLRANGE: printf("..<"); break;
259 case ACT_EL_ULRANGE: printf("<..<"); break;
260 default: printf("?..?"); break;
261 }
262 asn1print_value(ct->range_stop, flags);
263 break;
264 case ACT_EL_EXT:
265 printf("...");
266 break;
267 case ACT_CT_SIZE:
268 case ACT_CT_FROM:
269 switch(ct->type) {
vlm4808c702004-08-18 04:50:37 +0000270 case ACT_CT_SIZE: printf("SIZE("); break;
271 case ACT_CT_FROM: printf("FROM("); break;
vlmfa67ddc2004-06-03 03:38:44 +0000272 default: printf("??? ("); break;
273 }
274 assert(ct->el_count != 0);
275 assert(ct->el_count == 1);
276 asn1print_constraint(ct->elements[0], flags);
277 printf(")");
278 break;
279 case ACT_CT_WCOMP:
280 case ACT_CT_WCOMPS:
281 printf("???");
282 break;
283 case ACT_CA_SET: symno++;
284 case ACT_CA_CRC: symno++;
285 case ACT_CA_CSV: symno++;
286 case ACT_CA_UNI: symno++;
287 case ACT_CA_INT: symno++;
288 case ACT_CA_EXC:
289 {
vlm4808c702004-08-18 04:50:37 +0000290 char *symtable[] = { " EXCEPT ", " ^ ", " | ", ",",
vlmfa67ddc2004-06-03 03:38:44 +0000291 "", "(" };
292 int i;
293 for(i = 0; i < ct->el_count; i++) {
vlm4808c702004-08-18 04:50:37 +0000294 enum asn1print_flags nflags = flags;
vlmfa67ddc2004-06-03 03:38:44 +0000295 if(i) fputs(symtable[symno], stdout);
296 if(ct->type == ACT_CA_CRC) fputs("{", stdout);
297 asn1print_constraint(ct->elements[i], nflags);
298 if(ct->type == ACT_CA_CRC) fputs("}", stdout);
299 if(i+1 < ct->el_count
300 && ct->type == ACT_CA_SET)
301 fputs(")", stdout);
302 }
303 }
304 break;
305 case ACT_INVALID:
306 assert(ct->type != ACT_INVALID);
307 break;
308 }
309
310 if(ct->type == ACT_CA_SET)
311 printf(")");
312
313 return 0;
314}
315
316static int
vlm4808c702004-08-18 04:50:37 +0000317asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000318 if(pl) {
319 int i;
320 printf("{");
321 for(i = 0; i < pl->params_count; i++) {
322 if(i) printf(", ");
323 if(pl->params[i].governor) {
324 asn1print_ref(pl->params[i].governor, flags);
325 printf(":");
326 }
327 printf("%s", pl->params[i].argument);
328 }
329 printf("}");
330 }
331
332 return 0;
333}
334
335static int
vlm4808c702004-08-18 04:50:37 +0000336asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000337 if(wx) {
338 asn1p_wsyntx_chunk_t *wc;
339 printf(" WITH SYNTAX {");
340 TQ_FOR(wc, &(wx->chunks), next) {
341 if(wc->ref) {
342 asn1print_ref(wc->ref, flags);
343 } else {
344 fwrite(wc->buf, 1, wc->len, stdout);
345 }
346 }
347 printf("}\n");
348 }
349
350 return 0;
351}
352
353static int
vlm4808c702004-08-18 04:50:37 +0000354asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
355 switch(edge->type) {
356 case ARE_MIN: printf("MIN"); break;
357 case ARE_MAX: printf("MAX"); break;
358 case ARE_VALUE:
359 if(as_char) {
360 printf("\"%c\"", (unsigned char)edge->value);
361 } else {
362 printf("%lld", (long long)edge->value);
363 }
364 }
365 return 0;
366}
367
368static int
vlmeeca98f2004-08-25 02:00:03 +0000369asn1print_constraint_explain_type(asn1p_expr_type_e expr_type, asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, int strict_PER_visible) {
vlm4808c702004-08-18 04:50:37 +0000370 asn1cnst_range_t *range;
371 int as_char = (type==ACT_CT_FROM);
372 int i;
373
vlmeeca98f2004-08-25 02:00:03 +0000374 range = asn1constraint_compute_PER_range(expr_type, ct, type,
375 0, 0, strict_PER_visible);
vlm4808c702004-08-18 04:50:37 +0000376 if(!range) return -1;
377
vlmeeca98f2004-08-25 02:00:03 +0000378 if(range->incompatible
379 || (strict_PER_visible && range->not_PER_visible)) {
380 asn1constraint_range_free(range);
381 return 0;
382 }
383
vlm4808c702004-08-18 04:50:37 +0000384 switch(type) {
385 case ACT_CT_FROM: printf("(FROM("); break;
386 case ACT_CT_SIZE: printf("(SIZE("); break;
387 default: printf("("); break;
388 }
389 for(i = -1; i < range->el_count; i++) {
390 asn1cnst_range_t *r;
391 if(i == -1) {
392 if(range->el_count) continue;
393 r = range;
394 } else {
395 r = range->elements[i];
396 }
397 if(i > 0) {
398 printf(" | ");
399 }
400 asn1print_crange_value(&r->left, as_char);
401 if(r->left.type != r->right.type
402 || r->left.value != r->right.value) {
403 printf("..");
404 asn1print_crange_value(&r->right, as_char);
405 }
406 }
407 if(range->extensible)
408 printf(",...");
409 printf(type==ACT_EL_RANGE?")":"))");
410
411 if(range->empty_constraint)
412 printf(":Empty!");
413
414 asn1constraint_range_free(range);
415 return 0;
416}
417
418static int
419asn1print_constraint_explain(asn1p_expr_type_e expr_type,
vlmeeca98f2004-08-25 02:00:03 +0000420 asn1p_constraint_t *ct, int s_PV) {
vlm4808c702004-08-18 04:50:37 +0000421
vlmeeca98f2004-08-25 02:00:03 +0000422 asn1print_constraint_explain_type(expr_type, ct, ACT_EL_RANGE, s_PV);
vlm4808c702004-08-18 04:50:37 +0000423 printf(" ");
vlmeeca98f2004-08-25 02:00:03 +0000424 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_SIZE, s_PV);
vlm4808c702004-08-18 04:50:37 +0000425 printf(" ");
vlmeeca98f2004-08-25 02:00:03 +0000426 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_FROM, s_PV);
vlm4808c702004-08-18 04:50:37 +0000427
428 return 0;
429}
430
431static int
432asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level) {
vlm00ad2822004-08-20 13:24:28 +0000433 int SEQ_OF = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000434
435 if(flags & APF_LINE_COMMENTS)
436 INDENT("-- #line %d\n", tc->_lineno);
437 if(tc->Identifier)
438 INDENT("%s", tc->Identifier);
439
440 if(tc->params) {
441 asn1print_params(tc->params, flags);
442 }
443
444 if(tc->meta_type != AMT_VALUE
445 && tc->expr_type != A1TC_EXTENSIBLE) {
446 if(level) {
447 if(tc->Identifier)
448 printf("\t");
449 } else {
450 printf(" ::=");
451 }
452 }
453
454 if(tc->tag.tag_class) {
455 printf(" ");
456 asn1print_tag(tc, flags);
457 }
458
459 switch(tc->expr_type) {
460 case A1TC_EXTENSIBLE:
461 if(tc->value) {
462 printf("!");
463 asn1print_value(tc->value, flags);
464 }
465 break;
vlmddd6fd12004-08-22 03:08:51 +0000466 case A1TC_COMPONENTS_OF:
467 SEQ_OF = 1; /* Equivalent to SET OF for printint purposes */
468 printf(" COMPONENTS OF");
469 break;
vlmfa67ddc2004-06-03 03:38:44 +0000470 case A1TC_REFERENCE:
471 case A1TC_UNIVERVAL:
472 case A1TC_PARAMETRIZED:
473 break;
474 case A1TC_CLASSDEF:
475 printf(" CLASS");
476 break;
477 case A1TC_CLASSFIELD:
478 /* Nothing to print here */
479 break;
vlm00ad2822004-08-20 13:24:28 +0000480 case ASN_CONSTR_SET_OF:
481 case ASN_CONSTR_SEQUENCE_OF:
482 SEQ_OF = 1;
483 if(tc->expr_type == ASN_CONSTR_SET_OF)
484 printf(" SET");
485 else
486 printf(" SEQUENCE");
487 if(tc->constraints) {
488 printf(" ");
489 asn1print_constraint(tc->constraints, flags);
490 }
491 printf(" OF");
492 break;
vlmfa67ddc2004-06-03 03:38:44 +0000493 default:
494 {
495 char *p = ASN_EXPR_TYPE2STR(tc->expr_type);
496 printf(" %s", p?p:"<unknown type!>");
497 }
498 break;
499 }
500
501 if(tc->reference) {
502 printf(" ");
503 asn1print_ref(tc->reference, flags);
504 }
505
506 /*
507 * Display the descendants (children) of the current type.
508 */
509 if(TQ_FIRST(&(tc->members))) {
510 asn1p_expr_t *se; /* SubExpression */
vlmddd6fd12004-08-22 03:08:51 +0000511 int put_braces = !SEQ_OF; /* Don't need 'em, if SET OF... */
vlmfa67ddc2004-06-03 03:38:44 +0000512
vlmddd6fd12004-08-22 03:08:51 +0000513 if(put_braces) printf(" {\n");
vlmfa67ddc2004-06-03 03:38:44 +0000514
515 TQ_FOR(se, &(tc->members), next) {
516 /*
vlmddd6fd12004-08-22 03:08:51 +0000517 * Print the expression as it were a stand-alone type.
vlmfa67ddc2004-06-03 03:38:44 +0000518 */
vlm4808c702004-08-18 04:50:37 +0000519 asn1print_expr(asn, mod, se, flags, level + 4);
vlmfa67ddc2004-06-03 03:38:44 +0000520 switch(se->marker) {
521 case EM_NOMARK: break;
522 case EM_OPTIONAL: printf(" OPTIONAL"); break;
523 case EM_DEFAULT: printf(" DEFAULT <?>"); break;
524 }
525 if(TQ_NEXT(se, next)) {
526 printf(",");
527 INDENT("\n");
528 }
529 }
530
vlmddd6fd12004-08-22 03:08:51 +0000531 if(put_braces) {
vlmfa67ddc2004-06-03 03:38:44 +0000532 printf("\n");
533 INDENT("}");
534 }
535 }
536
537 if(tc->with_syntax)
538 asn1print_with_syntax(tc->with_syntax, flags);
539
vlm00ad2822004-08-20 13:24:28 +0000540 if(!SEQ_OF && tc->constraints) {
vlmfa67ddc2004-06-03 03:38:44 +0000541 printf(" ");
542 asn1print_constraint(tc->constraints, flags);
543 }
vlm4808c702004-08-18 04:50:37 +0000544
vlmfa67ddc2004-06-03 03:38:44 +0000545 if(tc->unique) {
546 printf(" UNIQUE");
547 }
548
549 if(tc->meta_type == AMT_VALUE
550 && tc->expr_type != A1TC_EXTENSIBLE) {
551 if(tc->expr_type == A1TC_UNIVERVAL)
552 printf("(");
553 else
554 printf(" ::= ");
555 asn1print_value(tc->value, flags);
556 if(tc->expr_type == A1TC_UNIVERVAL)
557 printf(")");
558 }
559
vlmddd6fd12004-08-22 03:08:51 +0000560 /*
561 * The following section exists entirely for debugging only.
562 */
vlm00ad2822004-08-20 13:24:28 +0000563 if(flags & APF_DEBUG_CONSTRAINTS
564 && tc->expr_type != A1TC_EXTENSIBLE) {
vlm4808c702004-08-18 04:50:37 +0000565 asn1p_expr_t *top_parent;
566
567 if(tc->combined_constraints) {
568 printf("\n-- Combined constraints: ");
569 asn1print_constraint(tc->combined_constraints, flags);
570 }
571
vlmddd6fd12004-08-22 03:08:51 +0000572 top_parent = asn1f_find_terminal_type_ex(asn, mod, tc);
vlm4808c702004-08-18 04:50:37 +0000573 if(top_parent) {
vlmeeca98f2004-08-25 02:00:03 +0000574 printf("\n-- Practical constraints (%s): ",
575 top_parent->Identifier);
576 asn1print_constraint_explain(top_parent->expr_type,
577 tc->combined_constraints, 0);
vlm00ad2822004-08-20 13:24:28 +0000578 printf("\n-- PER-visible constraints (%s): ",
579 top_parent->Identifier);
vlm4808c702004-08-18 04:50:37 +0000580 asn1print_constraint_explain(top_parent->expr_type,
vlmeeca98f2004-08-25 02:00:03 +0000581 tc->combined_constraints, 1);
vlm4808c702004-08-18 04:50:37 +0000582 }
vlm00ad2822004-08-20 13:24:28 +0000583 printf("\n");
vlm4808c702004-08-18 04:50:37 +0000584 }
585
vlmfa67ddc2004-06-03 03:38:44 +0000586 return 0;
587}
vlm4808c702004-08-18 04:50:37 +0000588