blob: 886c949213d949a47cf9c8fd0aa3900fe6307c4c [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 Walkin9095ada2004-08-18 05:41:05 +00008#include <asn1fix_crange.h>
Lev Walkinf15320b2004-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
Lev Walkin3140e0e2004-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,
Lev Walkinf15320b2004-06-03 03:38:44 +000026 int level);
27
28/*
29 * Print the contents of the parsed ASN tree.
30 */
31int
Lev Walkin3140e0e2004-08-18 04:50:37 +000032asn1print(asn1p_t *asn, enum asn1print_flags flags) {
Lev Walkinf15320b2004-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) {
Lev Walkin3140e0e2004-08-18 04:50:37 +000041 asn1print_module(asn, mod, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000042 }
43
44 return 0;
45}
46
47static int
Lev Walkin3140e0e2004-08-18 04:50:37 +000048asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000049 asn1p_expr_t *tc;
50
Lev Walkinf15320b2004-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
Lev Walkin3140e0e2004-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");
Lev Walkinf15320b2004-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) {
Lev Walkin3140e0e2004-08-18 04:50:37 +000076 asn1print_expr(asn, mod, tc, flags, 0);
Lev Walkinb1ef3962004-08-20 13:24:28 +000077 if(flags & APF_DEBUG_CONSTRAINTS)
78 printf("\n");
79 else
80 printf("\n\n");
Lev Walkinf15320b2004-06-03 03:38:44 +000081 }
82
83 printf("END\n");
84
85 return 0;
86}
87
88static int
Lev Walkin3140e0e2004-08-18 04:50:37 +000089asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000090 int ac;
91 int accum = 0;
92
Lev Walkind9bd7752004-06-05 08:17:50 +000093 (void)flags; /* Unused argument */
94
Lev Walkinf15320b2004-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) {
Lev Walkin0056aec2004-09-05 10:38:50 +0000103 printf("%s", oid->arcs[ac].name);
104 if(oid->arcs[ac].number >= 0) {
Lev Walkin33c16ba2004-09-24 21:01:43 +0000105 printf("(%" PRIdASN ")", oid->arcs[ac].number);
Lev Walkin0056aec2004-09-05 10:38:50 +0000106 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000107 accum += strlen(oid->arcs[ac].name);
108 } else {
109 printf("%d",
110 (int)oid->arcs[ac].number);
111 }
112 accum += 4;
113 }
114 printf(" }");
115
116 return 0;
117}
118
119static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000120asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000121 int cc;
122
Lev Walkind9bd7752004-06-05 08:17:50 +0000123 (void)flags; /* Unused argument */
124
Lev Walkinf15320b2004-06-03 03:38:44 +0000125 for(cc = 0; cc < ref->comp_count; cc++) {
126 if(cc) printf(".");
127 printf("%s", ref->components[cc].name);
128 }
129
130 return 0;
131}
132
133static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000134asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000135 struct asn1p_type_tag_s *tag = &tc->tag;
136
Lev Walkind9bd7752004-06-05 08:17:50 +0000137 (void)flags; /* Unused argument */
138
Lev Walkinf15320b2004-06-03 03:38:44 +0000139 if(tag->tag_class == TC_NOCLASS)
140 return 0;
141
142 printf("[");
143 switch(tag->tag_class) {
144 case TC_NOCLASS:
145 assert(tag->tag_class != TC_NOCLASS);
146 break;
147 case TC_UNIVERSAL: printf("UNIVERSAL "); break;
148 case TC_PRIVATE: printf("PRIVATE "); break;
149 case TC_APPLICATION: printf("APPLICATION "); break;
150 case TC_CONTEXT_SPECIFIC:
151 break;
152 }
Lev Walkin33c16ba2004-09-24 21:01:43 +0000153 printf("%" PRIdASN "]", tag->tag_value);
Lev Walkinf15320b2004-06-03 03:38:44 +0000154
155 switch(tag->tag_mode) {
156 case TM_DEFAULT: break;
157 case TM_IMPLICIT: printf(" IMPLICIT"); break;
158 case TM_EXPLICIT: printf(" EXPLICIT"); break;
159 }
160
161 return 0;
162}
163
164static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000165asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000166
167 if(val == NULL)
168 return 0;
169
170 switch(val->type) {
171 case ATV_NOVALUE:
172 break;
Lev Walkinb1e07082004-09-15 11:44:55 +0000173 case ATV_NULL:
174 printf("NULL");
175 return 0;
176 case ATV_REAL:
177 printf("%f", val->value.v_double);
178 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000179 case ATV_INTEGER:
Lev Walkin33c16ba2004-09-24 21:01:43 +0000180 printf("%" PRIdASN, val->value.v_integer);
Lev Walkinf15320b2004-06-03 03:38:44 +0000181 return 0;
182 case ATV_MIN: printf("MIN"); return 0;
183 case ATV_MAX: printf("MAX"); return 0;
184 case ATV_FALSE: printf("FALSE"); return 0;
185 case ATV_TRUE: printf("TRUE"); return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000186 case ATV_STRING:
187 {
188 char *p = val->value.string.buf;
189 putchar('"');
190 if(strchr(p, '"')) {
191 /* Mask quotes */
192 for(; *p; p++) {
193 if(*p == '"')
194 putchar(*p);
195 putchar(*p);
196 }
197 } else {
198 fputs(p, stdout);
199 }
200 putchar('"');
201 }
202 return 0;
203 case ATV_UNPARSED:
204 fputs(val->value.string.buf, stdout);
205 return 0;
206 case ATV_BITVECTOR:
207 {
208 uint8_t *bitvector;
209 int bits;
210 int i;
211
212 bitvector = val->value.binary_vector.bits;
213 bits = val->value.binary_vector.size_in_bits;
214
215 printf("'");
216 if(bits%8) {
217 for(i = 0; i < bits; i++) {
218 uint8_t uc;
219 uc = bitvector[i>>3];
220 putchar(((uc >> (7-(i%8)))&1)?'1':'0');
221 }
222 printf("'B");
223 } else {
224 char hextable[16] = "0123456789ABCDEF";
225 for(i = 0; i < (bits>>3); i++) {
226 putchar(hextable[bitvector[i] >> 4]);
227 putchar(hextable[bitvector[i] & 0x0f]);
228 }
229 printf("'H");
230 }
231 }
Lev Walkinb1e07082004-09-15 11:44:55 +0000232 case ATV_REFERENCED:
233 return asn1print_ref(val->value.reference, flags);
234 case ATV_CHOICE_IDENTIFIER:
235 printf("%s: ", val->value.choice_identifier.identifier);
236 return asn1print_value(val->value.choice_identifier.value, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +0000237 }
238
239 assert(val->type || !"Unknown");
240
241 return 0;
242}
243
244static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000245asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000246 int symno = 0;
247
248 if(ct == 0) return 0;
249
250 if(ct->type == ACT_CA_SET)
251 printf("(");
252
253 switch(ct->type) {
254 case ACT_EL_VALUE:
255 asn1print_value(ct->value, flags);
256 break;
257 case ACT_EL_RANGE:
258 case ACT_EL_LLRANGE:
259 case ACT_EL_RLRANGE:
260 case ACT_EL_ULRANGE:
261 asn1print_value(ct->range_start, flags);
262 switch(ct->type) {
263 case ACT_EL_RANGE: printf(".."); break;
264 case ACT_EL_LLRANGE: printf("<.."); break;
265 case ACT_EL_RLRANGE: printf("..<"); break;
266 case ACT_EL_ULRANGE: printf("<..<"); break;
267 default: printf("?..?"); break;
268 }
269 asn1print_value(ct->range_stop, flags);
270 break;
271 case ACT_EL_EXT:
272 printf("...");
273 break;
274 case ACT_CT_SIZE:
275 case ACT_CT_FROM:
276 switch(ct->type) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000277 case ACT_CT_SIZE: printf("SIZE("); break;
278 case ACT_CT_FROM: printf("FROM("); break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000279 default: printf("??? ("); break;
280 }
281 assert(ct->el_count != 0);
282 assert(ct->el_count == 1);
283 asn1print_constraint(ct->elements[0], flags);
284 printf(")");
285 break;
286 case ACT_CT_WCOMP:
287 case ACT_CT_WCOMPS:
288 printf("???");
289 break;
290 case ACT_CA_SET: symno++;
291 case ACT_CA_CRC: symno++;
292 case ACT_CA_CSV: symno++;
293 case ACT_CA_UNI: symno++;
294 case ACT_CA_INT: symno++;
295 case ACT_CA_EXC:
296 {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000297 char *symtable[] = { " EXCEPT ", " ^ ", " | ", ",",
Lev Walkinf15320b2004-06-03 03:38:44 +0000298 "", "(" };
Lev Walkin0056aec2004-09-05 10:38:50 +0000299 unsigned int i;
Lev Walkinf15320b2004-06-03 03:38:44 +0000300 for(i = 0; i < ct->el_count; i++) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000301 enum asn1print_flags nflags = flags;
Lev Walkinf15320b2004-06-03 03:38:44 +0000302 if(i) fputs(symtable[symno], stdout);
303 if(ct->type == ACT_CA_CRC) fputs("{", stdout);
304 asn1print_constraint(ct->elements[i], nflags);
305 if(ct->type == ACT_CA_CRC) fputs("}", stdout);
306 if(i+1 < ct->el_count
307 && ct->type == ACT_CA_SET)
308 fputs(")", stdout);
309 }
310 }
311 break;
312 case ACT_INVALID:
313 assert(ct->type != ACT_INVALID);
314 break;
315 }
316
317 if(ct->type == ACT_CA_SET)
318 printf(")");
319
320 return 0;
321}
322
323static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000324asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000325 if(pl) {
326 int i;
327 printf("{");
328 for(i = 0; i < pl->params_count; i++) {
329 if(i) printf(", ");
330 if(pl->params[i].governor) {
331 asn1print_ref(pl->params[i].governor, flags);
332 printf(":");
333 }
334 printf("%s", pl->params[i].argument);
335 }
336 printf("}");
337 }
338
339 return 0;
340}
341
342static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000343asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000344 if(wx) {
345 asn1p_wsyntx_chunk_t *wc;
346 printf(" WITH SYNTAX {");
347 TQ_FOR(wc, &(wx->chunks), next) {
348 if(wc->ref) {
349 asn1print_ref(wc->ref, flags);
350 } else {
351 fwrite(wc->buf, 1, wc->len, stdout);
352 }
353 }
354 printf("}\n");
355 }
356
357 return 0;
358}
359
360static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000361asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
362 switch(edge->type) {
363 case ARE_MIN: printf("MIN"); break;
364 case ARE_MAX: printf("MAX"); break;
365 case ARE_VALUE:
366 if(as_char) {
367 printf("\"%c\"", (unsigned char)edge->value);
368 } else {
Lev Walkin33c16ba2004-09-24 21:01:43 +0000369 printf("%" PRIdASN, edge->value);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000370 }
371 }
372 return 0;
373}
374
375static int
Lev Walkine8e87f12004-08-25 02:00:03 +0000376asn1print_constraint_explain_type(asn1p_expr_type_e expr_type, asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, int strict_PER_visible) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000377 asn1cnst_range_t *range;
378 int as_char = (type==ACT_CT_FROM);
379 int i;
380
Lev Walkine8e87f12004-08-25 02:00:03 +0000381 range = asn1constraint_compute_PER_range(expr_type, ct, type,
382 0, 0, strict_PER_visible);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000383 if(!range) return -1;
384
Lev Walkine8e87f12004-08-25 02:00:03 +0000385 if(range->incompatible
386 || (strict_PER_visible && range->not_PER_visible)) {
387 asn1constraint_range_free(range);
388 return 0;
389 }
390
Lev Walkin3140e0e2004-08-18 04:50:37 +0000391 switch(type) {
392 case ACT_CT_FROM: printf("(FROM("); break;
393 case ACT_CT_SIZE: printf("(SIZE("); break;
394 default: printf("("); break;
395 }
396 for(i = -1; i < range->el_count; i++) {
397 asn1cnst_range_t *r;
398 if(i == -1) {
399 if(range->el_count) continue;
400 r = range;
401 } else {
402 r = range->elements[i];
403 }
404 if(i > 0) {
405 printf(" | ");
406 }
407 asn1print_crange_value(&r->left, as_char);
408 if(r->left.type != r->right.type
409 || r->left.value != r->right.value) {
410 printf("..");
411 asn1print_crange_value(&r->right, as_char);
412 }
413 }
414 if(range->extensible)
415 printf(",...");
416 printf(type==ACT_EL_RANGE?")":"))");
417
418 if(range->empty_constraint)
419 printf(":Empty!");
420
421 asn1constraint_range_free(range);
422 return 0;
423}
424
425static int
426asn1print_constraint_explain(asn1p_expr_type_e expr_type,
Lev Walkine8e87f12004-08-25 02:00:03 +0000427 asn1p_constraint_t *ct, int s_PV) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000428
Lev Walkine8e87f12004-08-25 02:00:03 +0000429 asn1print_constraint_explain_type(expr_type, ct, ACT_EL_RANGE, s_PV);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000430 printf(" ");
Lev Walkine8e87f12004-08-25 02:00:03 +0000431 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_SIZE, s_PV);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000432 printf(" ");
Lev Walkine8e87f12004-08-25 02:00:03 +0000433 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_FROM, s_PV);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000434
435 return 0;
436}
437
438static int
439asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level) {
Lev Walkinb1ef3962004-08-20 13:24:28 +0000440 int SEQ_OF = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000441
442 if(flags & APF_LINE_COMMENTS)
443 INDENT("-- #line %d\n", tc->_lineno);
444 if(tc->Identifier)
445 INDENT("%s", tc->Identifier);
446
447 if(tc->params) {
448 asn1print_params(tc->params, flags);
449 }
450
451 if(tc->meta_type != AMT_VALUE
Lev Walkinc74ea222004-08-25 02:27:47 +0000452 && tc->meta_type != AMT_VALUESET
Lev Walkinf15320b2004-06-03 03:38:44 +0000453 && tc->expr_type != A1TC_EXTENSIBLE) {
454 if(level) {
455 if(tc->Identifier)
456 printf("\t");
457 } else {
458 printf(" ::=");
459 }
460 }
461
462 if(tc->tag.tag_class) {
463 printf(" ");
464 asn1print_tag(tc, flags);
465 }
466
467 switch(tc->expr_type) {
468 case A1TC_EXTENSIBLE:
469 if(tc->value) {
470 printf("!");
471 asn1print_value(tc->value, flags);
472 }
473 break;
Lev Walkinfd151ce2004-08-22 03:08:51 +0000474 case A1TC_COMPONENTS_OF:
475 SEQ_OF = 1; /* Equivalent to SET OF for printint purposes */
476 printf(" COMPONENTS OF");
477 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000478 case A1TC_REFERENCE:
479 case A1TC_UNIVERVAL:
480 case A1TC_PARAMETRIZED:
481 break;
482 case A1TC_CLASSDEF:
483 printf(" CLASS");
484 break;
485 case A1TC_CLASSFIELD:
486 /* Nothing to print here */
487 break;
Lev Walkinb1ef3962004-08-20 13:24:28 +0000488 case ASN_CONSTR_SET_OF:
489 case ASN_CONSTR_SEQUENCE_OF:
490 SEQ_OF = 1;
491 if(tc->expr_type == ASN_CONSTR_SET_OF)
492 printf(" SET");
493 else
494 printf(" SEQUENCE");
495 if(tc->constraints) {
496 printf(" ");
497 asn1print_constraint(tc->constraints, flags);
498 }
499 printf(" OF");
500 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000501 default:
502 {
503 char *p = ASN_EXPR_TYPE2STR(tc->expr_type);
504 printf(" %s", p?p:"<unknown type!>");
505 }
506 break;
507 }
508
509 if(tc->reference) {
510 printf(" ");
511 asn1print_ref(tc->reference, flags);
512 }
513
Lev Walkinc74ea222004-08-25 02:27:47 +0000514 if(tc->meta_type == AMT_VALUESET)
515 printf(" ::=");
516
Lev Walkinf15320b2004-06-03 03:38:44 +0000517 /*
518 * Display the descendants (children) of the current type.
519 */
Lev Walkinc74ea222004-08-25 02:27:47 +0000520 if(TQ_FIRST(&(tc->members))
521 || (tc->expr_type & ASN_CONSTR_MASK)
522 || tc->meta_type == AMT_VALUESET
523 || tc->meta_type == AMT_OBJECT
524 || tc->meta_type == AMT_OBJECTSET
525 ) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000526 asn1p_expr_t *se; /* SubExpression */
Lev Walkinfd151ce2004-08-22 03:08:51 +0000527 int put_braces = !SEQ_OF; /* Don't need 'em, if SET OF... */
Lev Walkinf15320b2004-06-03 03:38:44 +0000528
Lev Walkinc74ea222004-08-25 02:27:47 +0000529 if(put_braces) {
530 printf(" {");
531 if(TQ_FIRST(&tc->members))
532 printf("\n");
533 else printf(" }");
534 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000535
536 TQ_FOR(se, &(tc->members), next) {
537 /*
Lev Walkinfd151ce2004-08-22 03:08:51 +0000538 * Print the expression as it were a stand-alone type.
Lev Walkinf15320b2004-06-03 03:38:44 +0000539 */
Lev Walkin3140e0e2004-08-18 04:50:37 +0000540 asn1print_expr(asn, mod, se, flags, level + 4);
Lev Walkinb1e07082004-09-15 11:44:55 +0000541 if((se->marker.flags & EM_DEFAULT) == EM_DEFAULT) {
542 printf(" DEFAULT ");
543 asn1print_value(se->marker.default_value, flags);
544 } else if((se->marker.flags & EM_OPTIONAL)
545 == EM_OPTIONAL) {
Lev Walkin6e8da2b2004-09-10 08:21:27 +0000546 printf(" OPTIONAL");
Lev Walkinb1e07082004-09-15 11:44:55 +0000547 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000548 if(TQ_NEXT(se, next)) {
549 printf(",");
550 INDENT("\n");
551 }
552 }
553
Lev Walkinc74ea222004-08-25 02:27:47 +0000554 if(put_braces && TQ_FIRST(&tc->members)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000555 printf("\n");
556 INDENT("}");
557 }
558 }
559
560 if(tc->with_syntax)
561 asn1print_with_syntax(tc->with_syntax, flags);
562
Lev Walkinb1ef3962004-08-20 13:24:28 +0000563 if(!SEQ_OF && tc->constraints) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000564 printf(" ");
565 asn1print_constraint(tc->constraints, flags);
566 }
Lev Walkin3140e0e2004-08-18 04:50:37 +0000567
Lev Walkinf15320b2004-06-03 03:38:44 +0000568 if(tc->unique) {
569 printf(" UNIQUE");
570 }
571
572 if(tc->meta_type == AMT_VALUE
573 && tc->expr_type != A1TC_EXTENSIBLE) {
Lev Walkin0056aec2004-09-05 10:38:50 +0000574 if(tc->expr_type == A1TC_UNIVERVAL) {
Lev Walkinb1e07082004-09-15 11:44:55 +0000575 if(tc->value) {
576 printf("(");
577 asn1print_value(tc->value, flags);
578 printf(")");
579 }
Lev Walkin0056aec2004-09-05 10:38:50 +0000580 } else {
581 printf(" ::= ");
582 asn1print_value(tc->value, flags);
583 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000584 }
585
Lev Walkinfd151ce2004-08-22 03:08:51 +0000586 /*
587 * The following section exists entirely for debugging only.
588 */
Lev Walkinb1ef3962004-08-20 13:24:28 +0000589 if(flags & APF_DEBUG_CONSTRAINTS
590 && tc->expr_type != A1TC_EXTENSIBLE) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000591 asn1p_expr_t *top_parent;
592
593 if(tc->combined_constraints) {
594 printf("\n-- Combined constraints: ");
595 asn1print_constraint(tc->combined_constraints, flags);
596 }
597
Lev Walkine4d6ab82004-09-22 16:05:13 +0000598 top_parent = asn1f_find_terminal_type_ex(asn, tc);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000599 if(top_parent) {
Lev Walkine8e87f12004-08-25 02:00:03 +0000600 printf("\n-- Practical constraints (%s): ",
601 top_parent->Identifier);
602 asn1print_constraint_explain(top_parent->expr_type,
603 tc->combined_constraints, 0);
Lev Walkinb1ef3962004-08-20 13:24:28 +0000604 printf("\n-- PER-visible constraints (%s): ",
605 top_parent->Identifier);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000606 asn1print_constraint_explain(top_parent->expr_type,
Lev Walkine8e87f12004-08-25 02:00:03 +0000607 tc->combined_constraints, 1);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000608 }
Lev Walkinb1ef3962004-08-20 13:24:28 +0000609 printf("\n");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000610 }
611
Lev Walkinf15320b2004-06-03 03:38:44 +0000612 return 0;
613}
Lev Walkin3140e0e2004-08-18 04:50:37 +0000614