blob: a6c3edb5feaca1221ee8882e61d4e87ff9924a8d [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 { \
vlm60e7ef02004-10-13 09:13:56 +000013 int __i = level; while(__i--) printf(" "); \
vlmfa67ddc2004-06-03 03:38:44 +000014 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);
vlm60e7ef02004-10-13 09:13:56 +000025static int asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level);
26static int asn1print_expr_dtd(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level);
vlmfa67ddc2004-06-03 03:38:44 +000027
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;
vlm281d82a2004-09-30 06:38:21 +000034 int modno = 0;
vlmfa67ddc2004-06-03 03:38:44 +000035
36 if(asn == NULL) {
37 errno = EINVAL;
38 return -1;
39 }
40
vlm60e7ef02004-10-13 09:13:56 +000041 if(flags & APF_PRINT_XML_DTD)
42 printf("<!-- XML DTD generated by asn1c-" VERSION " -->\n\n");
43
vlmfa67ddc2004-06-03 03:38:44 +000044 TQ_FOR(mod, &(asn->modules), mod_next) {
vlm281d82a2004-09-30 06:38:21 +000045 if(modno++) printf("\n");
vlm4808c702004-08-18 04:50:37 +000046 asn1print_module(asn, mod, flags);
vlmfa67ddc2004-06-03 03:38:44 +000047 }
48
49 return 0;
50}
51
52static int
vlm4808c702004-08-18 04:50:37 +000053asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +000054 asn1p_expr_t *tc;
55
vlm60e7ef02004-10-13 09:13:56 +000056 if(flags & APF_PRINT_XML_DTD)
57 printf("<!-- ASN.1 module\n");
58
vlm281d82a2004-09-30 06:38:21 +000059 printf("%s ", mod->Identifier);
vlmfa67ddc2004-06-03 03:38:44 +000060 if(mod->module_oid) {
61 asn1print_oid(mod->module_oid, flags);
62 printf("\n");
63 }
64
vlm60e7ef02004-10-13 09:13:56 +000065 if(flags & APF_PRINT_XML_DTD) {
66 if(mod->source_file_name
67 && strcmp(mod->source_file_name, "-"))
68 printf("found in %s", mod->source_file_name);
69 printf(" -->\n\n");
70
71 TQ_FOR(tc, &(mod->members), next) {
72 asn1print_expr_dtd(asn, mod, tc, flags, 0);
73 }
74
75 return 0;
76 }
77
vlmfa67ddc2004-06-03 03:38:44 +000078 printf("DEFINITIONS");
79
vlm4808c702004-08-18 04:50:37 +000080 if(mod->module_flags & MSF_TAG_INSTRUCTIONS)
81 printf(" TAG INSTRUCTIONS");
82 if(mod->module_flags & MSF_XER_INSTRUCTIONS)
83 printf(" XER INSTRUCTIONS");
vlmfa67ddc2004-06-03 03:38:44 +000084 if(mod->module_flags & MSF_EXPLICIT_TAGS)
85 printf(" EXPLICIT TAGS");
86 if(mod->module_flags & MSF_IMPLICIT_TAGS)
87 printf(" IMPLICIT TAGS");
88 if(mod->module_flags & MSF_AUTOMATIC_TAGS)
89 printf(" AUTOMATIC TAGS");
90 if(mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
91 printf(" EXTENSIBILITY IMPLIED");
92
93 printf(" ::=\n");
94 printf("BEGIN\n\n");
95
96 TQ_FOR(tc, &(mod->members), next) {
vlm4808c702004-08-18 04:50:37 +000097 asn1print_expr(asn, mod, tc, flags, 0);
vlm00ad2822004-08-20 13:24:28 +000098 if(flags & APF_DEBUG_CONSTRAINTS)
99 printf("\n");
100 else
101 printf("\n\n");
vlmfa67ddc2004-06-03 03:38:44 +0000102 }
103
104 printf("END\n");
105
106 return 0;
107}
108
109static int
vlm4808c702004-08-18 04:50:37 +0000110asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000111 int ac;
112 int accum = 0;
113
vlmb42843a2004-06-05 08:17:50 +0000114 (void)flags; /* Unused argument */
115
vlmfa67ddc2004-06-03 03:38:44 +0000116 printf("{");
117 for(ac = 0; ac < oid->arcs_count; ac++) {
118 if(accum + strlen(oid->arcs[ac].name?:"") > 50) {
119 printf("\n\t");
120 accum = 0;
121 } else if(ac) printf(" ");
122
123 if(oid->arcs[ac].name) {
vlmdc4d95a2004-09-05 10:38:50 +0000124 printf("%s", oid->arcs[ac].name);
125 if(oid->arcs[ac].number >= 0) {
vlm47ae1582004-09-24 21:01:43 +0000126 printf("(%" PRIdASN ")", oid->arcs[ac].number);
vlmdc4d95a2004-09-05 10:38:50 +0000127 }
vlmfa67ddc2004-06-03 03:38:44 +0000128 accum += strlen(oid->arcs[ac].name);
129 } else {
130 printf("%d",
131 (int)oid->arcs[ac].number);
132 }
133 accum += 4;
134 }
135 printf(" }");
136
137 return 0;
138}
139
140static int
vlm4808c702004-08-18 04:50:37 +0000141asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000142 int cc;
143
vlmb42843a2004-06-05 08:17:50 +0000144 (void)flags; /* Unused argument */
145
vlmfa67ddc2004-06-03 03:38:44 +0000146 for(cc = 0; cc < ref->comp_count; cc++) {
147 if(cc) printf(".");
148 printf("%s", ref->components[cc].name);
149 }
150
151 return 0;
152}
153
154static int
vlm4808c702004-08-18 04:50:37 +0000155asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000156 struct asn1p_type_tag_s *tag = &tc->tag;
157
vlmb42843a2004-06-05 08:17:50 +0000158 (void)flags; /* Unused argument */
159
vlmfa67ddc2004-06-03 03:38:44 +0000160 if(tag->tag_class == TC_NOCLASS)
161 return 0;
162
163 printf("[");
164 switch(tag->tag_class) {
165 case TC_NOCLASS:
166 assert(tag->tag_class != TC_NOCLASS);
167 break;
168 case TC_UNIVERSAL: printf("UNIVERSAL "); break;
169 case TC_PRIVATE: printf("PRIVATE "); break;
170 case TC_APPLICATION: printf("APPLICATION "); break;
171 case TC_CONTEXT_SPECIFIC:
172 break;
173 }
vlm47ae1582004-09-24 21:01:43 +0000174 printf("%" PRIdASN "]", tag->tag_value);
vlmfa67ddc2004-06-03 03:38:44 +0000175
176 switch(tag->tag_mode) {
177 case TM_DEFAULT: break;
178 case TM_IMPLICIT: printf(" IMPLICIT"); break;
179 case TM_EXPLICIT: printf(" EXPLICIT"); break;
180 }
181
182 return 0;
183}
184
185static int
vlm4808c702004-08-18 04:50:37 +0000186asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000187
188 if(val == NULL)
189 return 0;
190
191 switch(val->type) {
192 case ATV_NOVALUE:
193 break;
vlm093f6752004-09-15 11:44:55 +0000194 case ATV_NULL:
195 printf("NULL");
196 return 0;
197 case ATV_REAL:
198 printf("%f", val->value.v_double);
199 return 0;
vlmfa67ddc2004-06-03 03:38:44 +0000200 case ATV_INTEGER:
vlm47ae1582004-09-24 21:01:43 +0000201 printf("%" PRIdASN, val->value.v_integer);
vlmfa67ddc2004-06-03 03:38:44 +0000202 return 0;
203 case ATV_MIN: printf("MIN"); return 0;
204 case ATV_MAX: printf("MAX"); return 0;
205 case ATV_FALSE: printf("FALSE"); return 0;
206 case ATV_TRUE: printf("TRUE"); return 0;
vlmfa67ddc2004-06-03 03:38:44 +0000207 case ATV_STRING:
208 {
209 char *p = val->value.string.buf;
210 putchar('"');
211 if(strchr(p, '"')) {
212 /* Mask quotes */
213 for(; *p; p++) {
214 if(*p == '"')
215 putchar(*p);
216 putchar(*p);
217 }
218 } else {
219 fputs(p, stdout);
220 }
221 putchar('"');
222 }
223 return 0;
224 case ATV_UNPARSED:
225 fputs(val->value.string.buf, stdout);
226 return 0;
227 case ATV_BITVECTOR:
228 {
229 uint8_t *bitvector;
230 int bits;
231 int i;
232
233 bitvector = val->value.binary_vector.bits;
234 bits = val->value.binary_vector.size_in_bits;
235
236 printf("'");
237 if(bits%8) {
238 for(i = 0; i < bits; i++) {
239 uint8_t uc;
240 uc = bitvector[i>>3];
241 putchar(((uc >> (7-(i%8)))&1)?'1':'0');
242 }
243 printf("'B");
244 } else {
245 char hextable[16] = "0123456789ABCDEF";
246 for(i = 0; i < (bits>>3); i++) {
247 putchar(hextable[bitvector[i] >> 4]);
248 putchar(hextable[bitvector[i] & 0x0f]);
249 }
250 printf("'H");
251 }
252 }
vlm093f6752004-09-15 11:44:55 +0000253 case ATV_REFERENCED:
254 return asn1print_ref(val->value.reference, flags);
255 case ATV_CHOICE_IDENTIFIER:
256 printf("%s: ", val->value.choice_identifier.identifier);
257 return asn1print_value(val->value.choice_identifier.value, flags);
vlmfa67ddc2004-06-03 03:38:44 +0000258 }
259
260 assert(val->type || !"Unknown");
261
262 return 0;
263}
264
265static int
vlm4808c702004-08-18 04:50:37 +0000266asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000267 int symno = 0;
268
269 if(ct == 0) return 0;
270
271 if(ct->type == ACT_CA_SET)
272 printf("(");
273
274 switch(ct->type) {
275 case ACT_EL_VALUE:
276 asn1print_value(ct->value, flags);
277 break;
278 case ACT_EL_RANGE:
279 case ACT_EL_LLRANGE:
280 case ACT_EL_RLRANGE:
281 case ACT_EL_ULRANGE:
282 asn1print_value(ct->range_start, flags);
283 switch(ct->type) {
284 case ACT_EL_RANGE: printf(".."); break;
285 case ACT_EL_LLRANGE: printf("<.."); break;
286 case ACT_EL_RLRANGE: printf("..<"); break;
287 case ACT_EL_ULRANGE: printf("<..<"); break;
288 default: printf("?..?"); break;
289 }
290 asn1print_value(ct->range_stop, flags);
291 break;
292 case ACT_EL_EXT:
293 printf("...");
294 break;
295 case ACT_CT_SIZE:
296 case ACT_CT_FROM:
297 switch(ct->type) {
vlm4808c702004-08-18 04:50:37 +0000298 case ACT_CT_SIZE: printf("SIZE("); break;
299 case ACT_CT_FROM: printf("FROM("); break;
vlmfa67ddc2004-06-03 03:38:44 +0000300 default: printf("??? ("); break;
301 }
302 assert(ct->el_count != 0);
303 assert(ct->el_count == 1);
304 asn1print_constraint(ct->elements[0], flags);
305 printf(")");
306 break;
307 case ACT_CT_WCOMP:
308 case ACT_CT_WCOMPS:
309 printf("???");
310 break;
311 case ACT_CA_SET: symno++;
312 case ACT_CA_CRC: symno++;
313 case ACT_CA_CSV: symno++;
314 case ACT_CA_UNI: symno++;
315 case ACT_CA_INT: symno++;
316 case ACT_CA_EXC:
317 {
vlm4808c702004-08-18 04:50:37 +0000318 char *symtable[] = { " EXCEPT ", " ^ ", " | ", ",",
vlmfa67ddc2004-06-03 03:38:44 +0000319 "", "(" };
vlmdc4d95a2004-09-05 10:38:50 +0000320 unsigned int i;
vlmfa67ddc2004-06-03 03:38:44 +0000321 for(i = 0; i < ct->el_count; i++) {
vlm4808c702004-08-18 04:50:37 +0000322 enum asn1print_flags nflags = flags;
vlmfa67ddc2004-06-03 03:38:44 +0000323 if(i) fputs(symtable[symno], stdout);
324 if(ct->type == ACT_CA_CRC) fputs("{", stdout);
325 asn1print_constraint(ct->elements[i], nflags);
326 if(ct->type == ACT_CA_CRC) fputs("}", stdout);
327 if(i+1 < ct->el_count
328 && ct->type == ACT_CA_SET)
329 fputs(")", stdout);
330 }
331 }
332 break;
333 case ACT_INVALID:
334 assert(ct->type != ACT_INVALID);
335 break;
336 }
337
338 if(ct->type == ACT_CA_SET)
339 printf(")");
340
341 return 0;
342}
343
344static int
vlm4808c702004-08-18 04:50:37 +0000345asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000346 if(pl) {
347 int i;
348 printf("{");
349 for(i = 0; i < pl->params_count; i++) {
350 if(i) printf(", ");
351 if(pl->params[i].governor) {
352 asn1print_ref(pl->params[i].governor, flags);
353 printf(":");
354 }
355 printf("%s", pl->params[i].argument);
356 }
357 printf("}");
358 }
359
360 return 0;
361}
362
363static int
vlm4808c702004-08-18 04:50:37 +0000364asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags) {
vlmfa67ddc2004-06-03 03:38:44 +0000365 if(wx) {
366 asn1p_wsyntx_chunk_t *wc;
367 printf(" WITH SYNTAX {");
368 TQ_FOR(wc, &(wx->chunks), next) {
369 if(wc->ref) {
370 asn1print_ref(wc->ref, flags);
371 } else {
372 fwrite(wc->buf, 1, wc->len, stdout);
373 }
374 }
375 printf("}\n");
376 }
377
378 return 0;
379}
380
381static int
vlm4808c702004-08-18 04:50:37 +0000382asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
383 switch(edge->type) {
384 case ARE_MIN: printf("MIN"); break;
385 case ARE_MAX: printf("MAX"); break;
386 case ARE_VALUE:
387 if(as_char) {
388 printf("\"%c\"", (unsigned char)edge->value);
389 } else {
vlm47ae1582004-09-24 21:01:43 +0000390 printf("%" PRIdASN, edge->value);
vlm4808c702004-08-18 04:50:37 +0000391 }
392 }
393 return 0;
394}
395
396static int
vlmeeca98f2004-08-25 02:00:03 +0000397asn1print_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 +0000398 asn1cnst_range_t *range;
399 int as_char = (type==ACT_CT_FROM);
400 int i;
401
vlmeeca98f2004-08-25 02:00:03 +0000402 range = asn1constraint_compute_PER_range(expr_type, ct, type,
403 0, 0, strict_PER_visible);
vlm4808c702004-08-18 04:50:37 +0000404 if(!range) return -1;
405
vlmeeca98f2004-08-25 02:00:03 +0000406 if(range->incompatible
407 || (strict_PER_visible && range->not_PER_visible)) {
408 asn1constraint_range_free(range);
409 return 0;
410 }
411
vlm4808c702004-08-18 04:50:37 +0000412 switch(type) {
413 case ACT_CT_FROM: printf("(FROM("); break;
414 case ACT_CT_SIZE: printf("(SIZE("); break;
415 default: printf("("); break;
416 }
417 for(i = -1; i < range->el_count; i++) {
418 asn1cnst_range_t *r;
419 if(i == -1) {
420 if(range->el_count) continue;
421 r = range;
422 } else {
423 r = range->elements[i];
424 }
425 if(i > 0) {
426 printf(" | ");
427 }
428 asn1print_crange_value(&r->left, as_char);
429 if(r->left.type != r->right.type
430 || r->left.value != r->right.value) {
431 printf("..");
432 asn1print_crange_value(&r->right, as_char);
433 }
434 }
435 if(range->extensible)
436 printf(",...");
437 printf(type==ACT_EL_RANGE?")":"))");
438
439 if(range->empty_constraint)
440 printf(":Empty!");
441
442 asn1constraint_range_free(range);
443 return 0;
444}
445
446static int
447asn1print_constraint_explain(asn1p_expr_type_e expr_type,
vlmeeca98f2004-08-25 02:00:03 +0000448 asn1p_constraint_t *ct, int s_PV) {
vlm4808c702004-08-18 04:50:37 +0000449
vlmeeca98f2004-08-25 02:00:03 +0000450 asn1print_constraint_explain_type(expr_type, ct, ACT_EL_RANGE, s_PV);
vlm4808c702004-08-18 04:50:37 +0000451 printf(" ");
vlmeeca98f2004-08-25 02:00:03 +0000452 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_SIZE, s_PV);
vlm4808c702004-08-18 04:50:37 +0000453 printf(" ");
vlmeeca98f2004-08-25 02:00:03 +0000454 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_FROM, s_PV);
vlm4808c702004-08-18 04:50:37 +0000455
456 return 0;
457}
458
459static int
460asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level) {
vlm00ad2822004-08-20 13:24:28 +0000461 int SEQ_OF = 0;
vlmfa67ddc2004-06-03 03:38:44 +0000462
463 if(flags & APF_LINE_COMMENTS)
vlm60e7ef02004-10-13 09:13:56 +0000464 INDENT("-- #line %d\n", tc->_lineno);
vlmfa67ddc2004-06-03 03:38:44 +0000465 if(tc->Identifier)
466 INDENT("%s", tc->Identifier);
467
468 if(tc->params) {
469 asn1print_params(tc->params, flags);
470 }
471
472 if(tc->meta_type != AMT_VALUE
vlmda4df3f2004-08-25 02:27:47 +0000473 && tc->meta_type != AMT_VALUESET
vlmfa67ddc2004-06-03 03:38:44 +0000474 && tc->expr_type != A1TC_EXTENSIBLE) {
475 if(level) {
476 if(tc->Identifier)
477 printf("\t");
478 } else {
479 printf(" ::=");
480 }
481 }
482
483 if(tc->tag.tag_class) {
484 printf(" ");
485 asn1print_tag(tc, flags);
486 }
487
488 switch(tc->expr_type) {
489 case A1TC_EXTENSIBLE:
490 if(tc->value) {
491 printf("!");
492 asn1print_value(tc->value, flags);
493 }
494 break;
vlmddd6fd12004-08-22 03:08:51 +0000495 case A1TC_COMPONENTS_OF:
496 SEQ_OF = 1; /* Equivalent to SET OF for printint purposes */
497 printf(" COMPONENTS OF");
498 break;
vlmfa67ddc2004-06-03 03:38:44 +0000499 case A1TC_REFERENCE:
500 case A1TC_UNIVERVAL:
501 case A1TC_PARAMETRIZED:
502 break;
503 case A1TC_CLASSDEF:
504 printf(" CLASS");
505 break;
506 case A1TC_CLASSFIELD:
507 /* Nothing to print here */
508 break;
vlm00ad2822004-08-20 13:24:28 +0000509 case ASN_CONSTR_SET_OF:
510 case ASN_CONSTR_SEQUENCE_OF:
511 SEQ_OF = 1;
512 if(tc->expr_type == ASN_CONSTR_SET_OF)
513 printf(" SET");
514 else
515 printf(" SEQUENCE");
516 if(tc->constraints) {
517 printf(" ");
518 asn1print_constraint(tc->constraints, flags);
519 }
520 printf(" OF");
521 break;
vlmfa67ddc2004-06-03 03:38:44 +0000522 default:
523 {
524 char *p = ASN_EXPR_TYPE2STR(tc->expr_type);
525 printf(" %s", p?p:"<unknown type!>");
526 }
527 break;
528 }
529
530 if(tc->reference) {
531 printf(" ");
532 asn1print_ref(tc->reference, flags);
533 }
534
vlmda4df3f2004-08-25 02:27:47 +0000535 if(tc->meta_type == AMT_VALUESET)
536 printf(" ::=");
537
vlmfa67ddc2004-06-03 03:38:44 +0000538 /*
539 * Display the descendants (children) of the current type.
540 */
vlmda4df3f2004-08-25 02:27:47 +0000541 if(TQ_FIRST(&(tc->members))
542 || (tc->expr_type & ASN_CONSTR_MASK)
543 || tc->meta_type == AMT_VALUESET
544 || tc->meta_type == AMT_OBJECT
545 || tc->meta_type == AMT_OBJECTSET
546 ) {
vlmfa67ddc2004-06-03 03:38:44 +0000547 asn1p_expr_t *se; /* SubExpression */
vlmddd6fd12004-08-22 03:08:51 +0000548 int put_braces = !SEQ_OF; /* Don't need 'em, if SET OF... */
vlmfa67ddc2004-06-03 03:38:44 +0000549
vlmda4df3f2004-08-25 02:27:47 +0000550 if(put_braces) {
551 printf(" {");
552 if(TQ_FIRST(&tc->members))
553 printf("\n");
554 else printf(" }");
555 }
vlmfa67ddc2004-06-03 03:38:44 +0000556
557 TQ_FOR(se, &(tc->members), next) {
558 /*
vlmddd6fd12004-08-22 03:08:51 +0000559 * Print the expression as it were a stand-alone type.
vlmfa67ddc2004-06-03 03:38:44 +0000560 */
vlm60e7ef02004-10-13 09:13:56 +0000561 asn1print_expr(asn, mod, se, flags, level + 1);
vlm093f6752004-09-15 11:44:55 +0000562 if((se->marker.flags & EM_DEFAULT) == EM_DEFAULT) {
563 printf(" DEFAULT ");
564 asn1print_value(se->marker.default_value, flags);
565 } else if((se->marker.flags & EM_OPTIONAL)
566 == EM_OPTIONAL) {
vlmd82eb012004-09-10 08:21:27 +0000567 printf(" OPTIONAL");
vlm093f6752004-09-15 11:44:55 +0000568 }
vlmfa67ddc2004-06-03 03:38:44 +0000569 if(TQ_NEXT(se, next)) {
570 printf(",");
571 INDENT("\n");
572 }
573 }
574
vlmda4df3f2004-08-25 02:27:47 +0000575 if(put_braces && TQ_FIRST(&tc->members)) {
vlmfa67ddc2004-06-03 03:38:44 +0000576 printf("\n");
577 INDENT("}");
578 }
579 }
580
581 if(tc->with_syntax)
582 asn1print_with_syntax(tc->with_syntax, flags);
583
vlm00ad2822004-08-20 13:24:28 +0000584 if(!SEQ_OF && tc->constraints) {
vlmfa67ddc2004-06-03 03:38:44 +0000585 printf(" ");
586 asn1print_constraint(tc->constraints, flags);
587 }
vlm4808c702004-08-18 04:50:37 +0000588
vlmfa67ddc2004-06-03 03:38:44 +0000589 if(tc->unique) {
590 printf(" UNIQUE");
591 }
592
593 if(tc->meta_type == AMT_VALUE
594 && tc->expr_type != A1TC_EXTENSIBLE) {
vlmdc4d95a2004-09-05 10:38:50 +0000595 if(tc->expr_type == A1TC_UNIVERVAL) {
vlm093f6752004-09-15 11:44:55 +0000596 if(tc->value) {
597 printf("(");
598 asn1print_value(tc->value, flags);
599 printf(")");
600 }
vlmdc4d95a2004-09-05 10:38:50 +0000601 } else {
602 printf(" ::= ");
603 asn1print_value(tc->value, flags);
604 }
vlmfa67ddc2004-06-03 03:38:44 +0000605 }
606
vlmddd6fd12004-08-22 03:08:51 +0000607 /*
608 * The following section exists entirely for debugging only.
609 */
vlm00ad2822004-08-20 13:24:28 +0000610 if(flags & APF_DEBUG_CONSTRAINTS
611 && tc->expr_type != A1TC_EXTENSIBLE) {
vlm4808c702004-08-18 04:50:37 +0000612 asn1p_expr_t *top_parent;
613
614 if(tc->combined_constraints) {
615 printf("\n-- Combined constraints: ");
616 asn1print_constraint(tc->combined_constraints, flags);
617 }
618
vlmcbebb812004-09-22 16:05:13 +0000619 top_parent = asn1f_find_terminal_type_ex(asn, tc);
vlm4808c702004-08-18 04:50:37 +0000620 if(top_parent) {
vlmeeca98f2004-08-25 02:00:03 +0000621 printf("\n-- Practical constraints (%s): ",
622 top_parent->Identifier);
623 asn1print_constraint_explain(top_parent->expr_type,
624 tc->combined_constraints, 0);
vlm00ad2822004-08-20 13:24:28 +0000625 printf("\n-- PER-visible constraints (%s): ",
626 top_parent->Identifier);
vlm4808c702004-08-18 04:50:37 +0000627 asn1print_constraint_explain(top_parent->expr_type,
vlmeeca98f2004-08-25 02:00:03 +0000628 tc->combined_constraints, 1);
vlm4808c702004-08-18 04:50:37 +0000629 }
vlm00ad2822004-08-20 13:24:28 +0000630 printf("\n");
vlm4808c702004-08-18 04:50:37 +0000631 }
632
vlmfa67ddc2004-06-03 03:38:44 +0000633 return 0;
634}
vlm4808c702004-08-18 04:50:37 +0000635
vlm60e7ef02004-10-13 09:13:56 +0000636
637static int
638asn1print_expr_dtd(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, enum asn1print_flags flags, int level) {
639 asn1p_expr_t *se;
640 int expr_unordered = 0;
641
642 switch(expr->meta_type) {
643 case AMT_TYPE:
644 case AMT_TYPEREF:
645 break;
646 default:
647 if(expr->expr_type == A1TC_UNIVERVAL)
648 break;
649 return 0;
650 }
651
652 if(!expr->Identifier) return 0;
653
654 if(expr->expr_type == ASN_CONSTR_CHOICE
655 || expr->expr_type == ASN_CONSTR_SEQUENCE_OF
656 || expr->expr_type == ASN_CONSTR_SET_OF
657 || expr->expr_type == ASN_CONSTR_SET
658 || expr->expr_type == ASN_BASIC_INTEGER
659 || expr->expr_type == ASN_BASIC_ENUMERATED) {
660 expr_unordered = 1;
661 }
662
663 if(flags & APF_LINE_COMMENTS)
664 INDENT("<!-- #line %d -->\n", expr->_lineno);
665 INDENT("<!ELEMENT %s", expr->Identifier);
666
667 if(expr->expr_type == A1TC_REFERENCE) {
668 se = asn1f_find_terminal_type_ex(asn, expr);
669 if(!se) {
670 printf("(ANY)");
671 return 0;
672 }
673 expr = se;
674 }
675
676 if(TQ_FIRST(&expr->members)) {
677 int extensible = 0;
678 printf(" (");
679 TQ_FOR(se, &(expr->members), next) {
680 if(se->expr_type == A1TC_EXTENSIBLE) {
681 extensible = 1;
682 continue;
683 } else if(!se->Identifier
684 && se->expr_type == A1TC_REFERENCE) {
685 asn1print_ref(se->reference, flags);
686 } else if(se->Identifier) {
687 printf("%s", se->Identifier);
688 } else {
689 printf("ANY");
690 }
691 if(expr->expr_type != ASN_CONSTR_SET
692 && expr->expr_type != ASN_CONSTR_CHOICE
693 && expr->expr_type != ASN_BASIC_INTEGER
694 && expr->expr_type != ASN_BASIC_ENUMERATED) {
695 if(expr_unordered)
696 printf("*");
697 else if(se->marker.flags)
698 printf("?");
699 }
700 if(TQ_NEXT(se, next)
701 && TQ_NEXT(se, next)->expr_type != A1TC_EXTENSIBLE) {
702 printf(expr_unordered?"|":", ");
703 }
704 }
705 if(extensible) {
706 printf(expr_unordered?"|":", ");
707 printf("ANY");
708 if(expr->expr_type != ASN_CONSTR_SET
709 && expr->expr_type != ASN_CONSTR_CHOICE
710 && expr->expr_type != ASN_BASIC_INTEGER
711 && expr->expr_type != ASN_BASIC_ENUMERATED)
712 printf("*");
713 }
714
715 printf(")");
716 if(expr->expr_type == ASN_CONSTR_SET)
717 printf("*");
718
719 } else if((expr->expr_type & ASN_CONSTR_MASK)
720 || expr->expr_type == ASN_BASIC_NULL) {
721 printf(" EMPTY");
722 } else if(expr->expr_type == A1TC_UNIVERVAL) {
723 printf(" EMPTY");
724 } else if(expr->expr_type == ASN_TYPE_ANY) {
725 printf(" ANY");
726 } else if(expr->expr_type == ASN_BASIC_BIT_STRING
727 || expr->expr_type == ASN_BASIC_OBJECT_IDENTIFIER
728 || expr->expr_type == ASN_BASIC_RELATIVE_OID
729 || expr->expr_type == ASN_BASIC_UTCTime
730 || expr->expr_type == ASN_BASIC_GeneralizedTime
731 ) {
732 printf(" (#CDATA)");
733 } else {
734 printf(" (#PCDATA)");
735 }
736 printf(">\n");
737
738 /*
739 * Display the descendants (children) of the current type.
740 */
741 TQ_FOR(se, &(expr->members), next) {
742 if(se->expr_type == A1TC_EXTENSIBLE) continue;
743 asn1print_expr_dtd(asn, mod, se, flags, level + 1);
744 }
745
746 return 0;
747}