blob: 4132204f081172dd8a23b25781f5a5d818f443b2 [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;
Lev Walkinc70c2ef2004-09-30 06:38:21 +000034 int modno = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000035
36 if(asn == NULL) {
37 errno = EINVAL;
38 return -1;
39 }
40
41 TQ_FOR(mod, &(asn->modules), mod_next) {
Lev Walkinc70c2ef2004-09-30 06:38:21 +000042 if(modno++) printf("\n");
Lev Walkin3140e0e2004-08-18 04:50:37 +000043 asn1print_module(asn, mod, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000044 }
45
46 return 0;
47}
48
49static int
Lev Walkin3140e0e2004-08-18 04:50:37 +000050asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000051 asn1p_expr_t *tc;
52
Lev Walkinc70c2ef2004-09-30 06:38:21 +000053 printf("%s ", mod->Identifier);
Lev Walkinf15320b2004-06-03 03:38:44 +000054 if(mod->module_oid) {
55 asn1print_oid(mod->module_oid, flags);
56 printf("\n");
57 }
58
59 printf("DEFINITIONS");
60
Lev Walkin3140e0e2004-08-18 04:50:37 +000061 if(mod->module_flags & MSF_TAG_INSTRUCTIONS)
62 printf(" TAG INSTRUCTIONS");
63 if(mod->module_flags & MSF_XER_INSTRUCTIONS)
64 printf(" XER INSTRUCTIONS");
Lev Walkinf15320b2004-06-03 03:38:44 +000065 if(mod->module_flags & MSF_EXPLICIT_TAGS)
66 printf(" EXPLICIT TAGS");
67 if(mod->module_flags & MSF_IMPLICIT_TAGS)
68 printf(" IMPLICIT TAGS");
69 if(mod->module_flags & MSF_AUTOMATIC_TAGS)
70 printf(" AUTOMATIC TAGS");
71 if(mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
72 printf(" EXTENSIBILITY IMPLIED");
73
74 printf(" ::=\n");
75 printf("BEGIN\n\n");
76
77 TQ_FOR(tc, &(mod->members), next) {
Lev Walkin3140e0e2004-08-18 04:50:37 +000078 asn1print_expr(asn, mod, tc, flags, 0);
Lev Walkinb1ef3962004-08-20 13:24:28 +000079 if(flags & APF_DEBUG_CONSTRAINTS)
80 printf("\n");
81 else
82 printf("\n\n");
Lev Walkinf15320b2004-06-03 03:38:44 +000083 }
84
85 printf("END\n");
86
87 return 0;
88}
89
90static int
Lev Walkin3140e0e2004-08-18 04:50:37 +000091asn1print_oid(asn1p_oid_t *oid, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000092 int ac;
93 int accum = 0;
94
Lev Walkind9bd7752004-06-05 08:17:50 +000095 (void)flags; /* Unused argument */
96
Lev Walkinf15320b2004-06-03 03:38:44 +000097 printf("{");
98 for(ac = 0; ac < oid->arcs_count; ac++) {
99 if(accum + strlen(oid->arcs[ac].name?:"") > 50) {
100 printf("\n\t");
101 accum = 0;
102 } else if(ac) printf(" ");
103
104 if(oid->arcs[ac].name) {
Lev Walkin0056aec2004-09-05 10:38:50 +0000105 printf("%s", oid->arcs[ac].name);
106 if(oid->arcs[ac].number >= 0) {
Lev Walkin33c16ba2004-09-24 21:01:43 +0000107 printf("(%" PRIdASN ")", oid->arcs[ac].number);
Lev Walkin0056aec2004-09-05 10:38:50 +0000108 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000109 accum += strlen(oid->arcs[ac].name);
110 } else {
111 printf("%d",
112 (int)oid->arcs[ac].number);
113 }
114 accum += 4;
115 }
116 printf(" }");
117
118 return 0;
119}
120
121static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000122asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000123 int cc;
124
Lev Walkind9bd7752004-06-05 08:17:50 +0000125 (void)flags; /* Unused argument */
126
Lev Walkinf15320b2004-06-03 03:38:44 +0000127 for(cc = 0; cc < ref->comp_count; cc++) {
128 if(cc) printf(".");
129 printf("%s", ref->components[cc].name);
130 }
131
132 return 0;
133}
134
135static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000136asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000137 struct asn1p_type_tag_s *tag = &tc->tag;
138
Lev Walkind9bd7752004-06-05 08:17:50 +0000139 (void)flags; /* Unused argument */
140
Lev Walkinf15320b2004-06-03 03:38:44 +0000141 if(tag->tag_class == TC_NOCLASS)
142 return 0;
143
144 printf("[");
145 switch(tag->tag_class) {
146 case TC_NOCLASS:
147 assert(tag->tag_class != TC_NOCLASS);
148 break;
149 case TC_UNIVERSAL: printf("UNIVERSAL "); break;
150 case TC_PRIVATE: printf("PRIVATE "); break;
151 case TC_APPLICATION: printf("APPLICATION "); break;
152 case TC_CONTEXT_SPECIFIC:
153 break;
154 }
Lev Walkin33c16ba2004-09-24 21:01:43 +0000155 printf("%" PRIdASN "]", tag->tag_value);
Lev Walkinf15320b2004-06-03 03:38:44 +0000156
157 switch(tag->tag_mode) {
158 case TM_DEFAULT: break;
159 case TM_IMPLICIT: printf(" IMPLICIT"); break;
160 case TM_EXPLICIT: printf(" EXPLICIT"); break;
161 }
162
163 return 0;
164}
165
166static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000167asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000168
169 if(val == NULL)
170 return 0;
171
172 switch(val->type) {
173 case ATV_NOVALUE:
174 break;
Lev Walkinb1e07082004-09-15 11:44:55 +0000175 case ATV_NULL:
176 printf("NULL");
177 return 0;
178 case ATV_REAL:
179 printf("%f", val->value.v_double);
180 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000181 case ATV_INTEGER:
Lev Walkin33c16ba2004-09-24 21:01:43 +0000182 printf("%" PRIdASN, val->value.v_integer);
Lev Walkinf15320b2004-06-03 03:38:44 +0000183 return 0;
184 case ATV_MIN: printf("MIN"); return 0;
185 case ATV_MAX: printf("MAX"); return 0;
186 case ATV_FALSE: printf("FALSE"); return 0;
187 case ATV_TRUE: printf("TRUE"); return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000188 case ATV_STRING:
189 {
190 char *p = val->value.string.buf;
191 putchar('"');
192 if(strchr(p, '"')) {
193 /* Mask quotes */
194 for(; *p; p++) {
195 if(*p == '"')
196 putchar(*p);
197 putchar(*p);
198 }
199 } else {
200 fputs(p, stdout);
201 }
202 putchar('"');
203 }
204 return 0;
205 case ATV_UNPARSED:
206 fputs(val->value.string.buf, stdout);
207 return 0;
208 case ATV_BITVECTOR:
209 {
210 uint8_t *bitvector;
211 int bits;
212 int i;
213
214 bitvector = val->value.binary_vector.bits;
215 bits = val->value.binary_vector.size_in_bits;
216
217 printf("'");
218 if(bits%8) {
219 for(i = 0; i < bits; i++) {
220 uint8_t uc;
221 uc = bitvector[i>>3];
222 putchar(((uc >> (7-(i%8)))&1)?'1':'0');
223 }
224 printf("'B");
225 } else {
226 char hextable[16] = "0123456789ABCDEF";
227 for(i = 0; i < (bits>>3); i++) {
228 putchar(hextable[bitvector[i] >> 4]);
229 putchar(hextable[bitvector[i] & 0x0f]);
230 }
231 printf("'H");
232 }
233 }
Lev Walkinb1e07082004-09-15 11:44:55 +0000234 case ATV_REFERENCED:
235 return asn1print_ref(val->value.reference, flags);
236 case ATV_CHOICE_IDENTIFIER:
237 printf("%s: ", val->value.choice_identifier.identifier);
238 return asn1print_value(val->value.choice_identifier.value, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +0000239 }
240
241 assert(val->type || !"Unknown");
242
243 return 0;
244}
245
246static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000247asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000248 int symno = 0;
249
250 if(ct == 0) return 0;
251
252 if(ct->type == ACT_CA_SET)
253 printf("(");
254
255 switch(ct->type) {
256 case ACT_EL_VALUE:
257 asn1print_value(ct->value, flags);
258 break;
259 case ACT_EL_RANGE:
260 case ACT_EL_LLRANGE:
261 case ACT_EL_RLRANGE:
262 case ACT_EL_ULRANGE:
263 asn1print_value(ct->range_start, flags);
264 switch(ct->type) {
265 case ACT_EL_RANGE: printf(".."); break;
266 case ACT_EL_LLRANGE: printf("<.."); break;
267 case ACT_EL_RLRANGE: printf("..<"); break;
268 case ACT_EL_ULRANGE: printf("<..<"); break;
269 default: printf("?..?"); break;
270 }
271 asn1print_value(ct->range_stop, flags);
272 break;
273 case ACT_EL_EXT:
274 printf("...");
275 break;
276 case ACT_CT_SIZE:
277 case ACT_CT_FROM:
278 switch(ct->type) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000279 case ACT_CT_SIZE: printf("SIZE("); break;
280 case ACT_CT_FROM: printf("FROM("); break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000281 default: printf("??? ("); break;
282 }
283 assert(ct->el_count != 0);
284 assert(ct->el_count == 1);
285 asn1print_constraint(ct->elements[0], flags);
286 printf(")");
287 break;
288 case ACT_CT_WCOMP:
289 case ACT_CT_WCOMPS:
290 printf("???");
291 break;
292 case ACT_CA_SET: symno++;
293 case ACT_CA_CRC: symno++;
294 case ACT_CA_CSV: symno++;
295 case ACT_CA_UNI: symno++;
296 case ACT_CA_INT: symno++;
297 case ACT_CA_EXC:
298 {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000299 char *symtable[] = { " EXCEPT ", " ^ ", " | ", ",",
Lev Walkinf15320b2004-06-03 03:38:44 +0000300 "", "(" };
Lev Walkin0056aec2004-09-05 10:38:50 +0000301 unsigned int i;
Lev Walkinf15320b2004-06-03 03:38:44 +0000302 for(i = 0; i < ct->el_count; i++) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000303 enum asn1print_flags nflags = flags;
Lev Walkinf15320b2004-06-03 03:38:44 +0000304 if(i) fputs(symtable[symno], stdout);
305 if(ct->type == ACT_CA_CRC) fputs("{", stdout);
306 asn1print_constraint(ct->elements[i], nflags);
307 if(ct->type == ACT_CA_CRC) fputs("}", stdout);
308 if(i+1 < ct->el_count
309 && ct->type == ACT_CA_SET)
310 fputs(")", stdout);
311 }
312 }
313 break;
314 case ACT_INVALID:
315 assert(ct->type != ACT_INVALID);
316 break;
317 }
318
319 if(ct->type == ACT_CA_SET)
320 printf(")");
321
322 return 0;
323}
324
325static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000326asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000327 if(pl) {
328 int i;
329 printf("{");
330 for(i = 0; i < pl->params_count; i++) {
331 if(i) printf(", ");
332 if(pl->params[i].governor) {
333 asn1print_ref(pl->params[i].governor, flags);
334 printf(":");
335 }
336 printf("%s", pl->params[i].argument);
337 }
338 printf("}");
339 }
340
341 return 0;
342}
343
344static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000345asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000346 if(wx) {
347 asn1p_wsyntx_chunk_t *wc;
348 printf(" WITH SYNTAX {");
349 TQ_FOR(wc, &(wx->chunks), next) {
350 if(wc->ref) {
351 asn1print_ref(wc->ref, flags);
352 } else {
353 fwrite(wc->buf, 1, wc->len, stdout);
354 }
355 }
356 printf("}\n");
357 }
358
359 return 0;
360}
361
362static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000363asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
364 switch(edge->type) {
365 case ARE_MIN: printf("MIN"); break;
366 case ARE_MAX: printf("MAX"); break;
367 case ARE_VALUE:
368 if(as_char) {
369 printf("\"%c\"", (unsigned char)edge->value);
370 } else {
Lev Walkin33c16ba2004-09-24 21:01:43 +0000371 printf("%" PRIdASN, edge->value);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000372 }
373 }
374 return 0;
375}
376
377static int
Lev Walkine8e87f12004-08-25 02:00:03 +0000378asn1print_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 +0000379 asn1cnst_range_t *range;
380 int as_char = (type==ACT_CT_FROM);
381 int i;
382
Lev Walkine8e87f12004-08-25 02:00:03 +0000383 range = asn1constraint_compute_PER_range(expr_type, ct, type,
384 0, 0, strict_PER_visible);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000385 if(!range) return -1;
386
Lev Walkine8e87f12004-08-25 02:00:03 +0000387 if(range->incompatible
388 || (strict_PER_visible && range->not_PER_visible)) {
389 asn1constraint_range_free(range);
390 return 0;
391 }
392
Lev Walkin3140e0e2004-08-18 04:50:37 +0000393 switch(type) {
394 case ACT_CT_FROM: printf("(FROM("); break;
395 case ACT_CT_SIZE: printf("(SIZE("); break;
396 default: printf("("); break;
397 }
398 for(i = -1; i < range->el_count; i++) {
399 asn1cnst_range_t *r;
400 if(i == -1) {
401 if(range->el_count) continue;
402 r = range;
403 } else {
404 r = range->elements[i];
405 }
406 if(i > 0) {
407 printf(" | ");
408 }
409 asn1print_crange_value(&r->left, as_char);
410 if(r->left.type != r->right.type
411 || r->left.value != r->right.value) {
412 printf("..");
413 asn1print_crange_value(&r->right, as_char);
414 }
415 }
416 if(range->extensible)
417 printf(",...");
418 printf(type==ACT_EL_RANGE?")":"))");
419
420 if(range->empty_constraint)
421 printf(":Empty!");
422
423 asn1constraint_range_free(range);
424 return 0;
425}
426
427static int
428asn1print_constraint_explain(asn1p_expr_type_e expr_type,
Lev Walkine8e87f12004-08-25 02:00:03 +0000429 asn1p_constraint_t *ct, int s_PV) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000430
Lev Walkine8e87f12004-08-25 02:00:03 +0000431 asn1print_constraint_explain_type(expr_type, ct, ACT_EL_RANGE, 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_SIZE, s_PV);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000434 printf(" ");
Lev Walkine8e87f12004-08-25 02:00:03 +0000435 asn1print_constraint_explain_type(expr_type, ct, ACT_CT_FROM, s_PV);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000436
437 return 0;
438}
439
440static int
441asn1print_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 +0000442 int SEQ_OF = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000443
444 if(flags & APF_LINE_COMMENTS)
445 INDENT("-- #line %d\n", tc->_lineno);
446 if(tc->Identifier)
447 INDENT("%s", tc->Identifier);
448
449 if(tc->params) {
450 asn1print_params(tc->params, flags);
451 }
452
453 if(tc->meta_type != AMT_VALUE
Lev Walkinc74ea222004-08-25 02:27:47 +0000454 && tc->meta_type != AMT_VALUESET
Lev Walkinf15320b2004-06-03 03:38:44 +0000455 && tc->expr_type != A1TC_EXTENSIBLE) {
456 if(level) {
457 if(tc->Identifier)
458 printf("\t");
459 } else {
460 printf(" ::=");
461 }
462 }
463
464 if(tc->tag.tag_class) {
465 printf(" ");
466 asn1print_tag(tc, flags);
467 }
468
469 switch(tc->expr_type) {
470 case A1TC_EXTENSIBLE:
471 if(tc->value) {
472 printf("!");
473 asn1print_value(tc->value, flags);
474 }
475 break;
Lev Walkinfd151ce2004-08-22 03:08:51 +0000476 case A1TC_COMPONENTS_OF:
477 SEQ_OF = 1; /* Equivalent to SET OF for printint purposes */
478 printf(" COMPONENTS OF");
479 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000480 case A1TC_REFERENCE:
481 case A1TC_UNIVERVAL:
482 case A1TC_PARAMETRIZED:
483 break;
484 case A1TC_CLASSDEF:
485 printf(" CLASS");
486 break;
487 case A1TC_CLASSFIELD:
488 /* Nothing to print here */
489 break;
Lev Walkinb1ef3962004-08-20 13:24:28 +0000490 case ASN_CONSTR_SET_OF:
491 case ASN_CONSTR_SEQUENCE_OF:
492 SEQ_OF = 1;
493 if(tc->expr_type == ASN_CONSTR_SET_OF)
494 printf(" SET");
495 else
496 printf(" SEQUENCE");
497 if(tc->constraints) {
498 printf(" ");
499 asn1print_constraint(tc->constraints, flags);
500 }
501 printf(" OF");
502 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000503 default:
504 {
505 char *p = ASN_EXPR_TYPE2STR(tc->expr_type);
506 printf(" %s", p?p:"<unknown type!>");
507 }
508 break;
509 }
510
511 if(tc->reference) {
512 printf(" ");
513 asn1print_ref(tc->reference, flags);
514 }
515
Lev Walkinc74ea222004-08-25 02:27:47 +0000516 if(tc->meta_type == AMT_VALUESET)
517 printf(" ::=");
518
Lev Walkinf15320b2004-06-03 03:38:44 +0000519 /*
520 * Display the descendants (children) of the current type.
521 */
Lev Walkinc74ea222004-08-25 02:27:47 +0000522 if(TQ_FIRST(&(tc->members))
523 || (tc->expr_type & ASN_CONSTR_MASK)
524 || tc->meta_type == AMT_VALUESET
525 || tc->meta_type == AMT_OBJECT
526 || tc->meta_type == AMT_OBJECTSET
527 ) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000528 asn1p_expr_t *se; /* SubExpression */
Lev Walkinfd151ce2004-08-22 03:08:51 +0000529 int put_braces = !SEQ_OF; /* Don't need 'em, if SET OF... */
Lev Walkinf15320b2004-06-03 03:38:44 +0000530
Lev Walkinc74ea222004-08-25 02:27:47 +0000531 if(put_braces) {
532 printf(" {");
533 if(TQ_FIRST(&tc->members))
534 printf("\n");
535 else printf(" }");
536 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000537
538 TQ_FOR(se, &(tc->members), next) {
539 /*
Lev Walkinfd151ce2004-08-22 03:08:51 +0000540 * Print the expression as it were a stand-alone type.
Lev Walkinf15320b2004-06-03 03:38:44 +0000541 */
Lev Walkin3140e0e2004-08-18 04:50:37 +0000542 asn1print_expr(asn, mod, se, flags, level + 4);
Lev Walkinb1e07082004-09-15 11:44:55 +0000543 if((se->marker.flags & EM_DEFAULT) == EM_DEFAULT) {
544 printf(" DEFAULT ");
545 asn1print_value(se->marker.default_value, flags);
546 } else if((se->marker.flags & EM_OPTIONAL)
547 == EM_OPTIONAL) {
Lev Walkin6e8da2b2004-09-10 08:21:27 +0000548 printf(" OPTIONAL");
Lev Walkinb1e07082004-09-15 11:44:55 +0000549 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000550 if(TQ_NEXT(se, next)) {
551 printf(",");
552 INDENT("\n");
553 }
554 }
555
Lev Walkinc74ea222004-08-25 02:27:47 +0000556 if(put_braces && TQ_FIRST(&tc->members)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000557 printf("\n");
558 INDENT("}");
559 }
560 }
561
562 if(tc->with_syntax)
563 asn1print_with_syntax(tc->with_syntax, flags);
564
Lev Walkinb1ef3962004-08-20 13:24:28 +0000565 if(!SEQ_OF && tc->constraints) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000566 printf(" ");
567 asn1print_constraint(tc->constraints, flags);
568 }
Lev Walkin3140e0e2004-08-18 04:50:37 +0000569
Lev Walkinf15320b2004-06-03 03:38:44 +0000570 if(tc->unique) {
571 printf(" UNIQUE");
572 }
573
574 if(tc->meta_type == AMT_VALUE
575 && tc->expr_type != A1TC_EXTENSIBLE) {
Lev Walkin0056aec2004-09-05 10:38:50 +0000576 if(tc->expr_type == A1TC_UNIVERVAL) {
Lev Walkinb1e07082004-09-15 11:44:55 +0000577 if(tc->value) {
578 printf("(");
579 asn1print_value(tc->value, flags);
580 printf(")");
581 }
Lev Walkin0056aec2004-09-05 10:38:50 +0000582 } else {
583 printf(" ::= ");
584 asn1print_value(tc->value, flags);
585 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000586 }
587
Lev Walkinfd151ce2004-08-22 03:08:51 +0000588 /*
589 * The following section exists entirely for debugging only.
590 */
Lev Walkinb1ef3962004-08-20 13:24:28 +0000591 if(flags & APF_DEBUG_CONSTRAINTS
592 && tc->expr_type != A1TC_EXTENSIBLE) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000593 asn1p_expr_t *top_parent;
594
595 if(tc->combined_constraints) {
596 printf("\n-- Combined constraints: ");
597 asn1print_constraint(tc->combined_constraints, flags);
598 }
599
Lev Walkine4d6ab82004-09-22 16:05:13 +0000600 top_parent = asn1f_find_terminal_type_ex(asn, tc);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000601 if(top_parent) {
Lev Walkine8e87f12004-08-25 02:00:03 +0000602 printf("\n-- Practical constraints (%s): ",
603 top_parent->Identifier);
604 asn1print_constraint_explain(top_parent->expr_type,
605 tc->combined_constraints, 0);
Lev Walkinb1ef3962004-08-20 13:24:28 +0000606 printf("\n-- PER-visible constraints (%s): ",
607 top_parent->Identifier);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000608 asn1print_constraint_explain(top_parent->expr_type,
Lev Walkine8e87f12004-08-25 02:00:03 +0000609 tc->combined_constraints, 1);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000610 }
Lev Walkinb1ef3962004-08-20 13:24:28 +0000611 printf("\n");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000612 }
613
Lev Walkinf15320b2004-06-03 03:38:44 +0000614 return 0;
615}
Lev Walkin3140e0e2004-08-18 04:50:37 +0000616