blob: a8f169e4b5fbb5b359f3fc7b36bce9ca85e6e0c4 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include <stdio.h>
Lev Walkinf2b2f372016-03-14 02:23:48 -07002#include <stdarg.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00003#include <string.h>
4#include <errno.h>
5#include <assert.h>
6
7#include <asn1parser.h>
Lev Walkin3140e0e2004-08-18 04:50:37 +00008#include <asn1fix_export.h>
Lev Walkin9095ada2004-08-18 05:41:05 +00009#include <asn1fix_crange.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000010
11#include "asn1print.h"
12
Lev Walkin1ec76052016-03-13 17:13:20 -070013#define INDENT(fmt, args...) do { \
14 if(!(flags & APF_NOINDENT)) { \
15 int tmp_i = level; \
Lev Walkinf2b2f372016-03-14 02:23:48 -070016 while(tmp_i--) safe_printf(" "); \
Lev Walkin1ec76052016-03-13 17:13:20 -070017 } \
Lev Walkinf2b2f372016-03-14 02:23:48 -070018 safe_printf(fmt, ##args); \
Lev Walkin1ec76052016-03-13 17:13:20 -070019 } while(0)
Lev Walkinf15320b2004-06-03 03:38:44 +000020
Lev Walkin3140e0e2004-08-18 04:50:37 +000021static int asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags);
Lev Walkind6db8022005-03-18 03:53:05 +000022static int asn1print_oid(int prior_len, asn1p_oid_t *oid, enum asn1print_flags flags);
Lev Walkin3140e0e2004-08-18 04:50:37 +000023static int asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags);
24static int asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags);
25static int asn1print_params(asn1p_paramlist_t *pl,enum asn1print_flags flags);
26static int asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags);
27static int asn1print_constraint(asn1p_constraint_t *, enum asn1print_flags);
28static int asn1print_value(asn1p_value_t *val, enum asn1print_flags flags);
Lev Walkinf7484512004-10-13 09:13:56 +000029static int asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level);
30static int asn1print_expr_dtd(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level);
Lev Walkinf15320b2004-06-03 03:38:44 +000031
Lev Walkinf2b2f372016-03-14 02:23:48 -070032/* Check printf's error code, to be pedantic. */
33static int safe_printf(const char *fmt, ...) {
34 va_list ap;
35 va_start(ap, fmt);
36 int ret = vprintf(fmt, ap);
37 assert(ret >= 0);
38 va_end(ap);
39 return ret;
40}
41
42/* Pedantically check fwrite's return value. */
43static size_t safe_fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream) {
44 size_t ret = fwrite(ptr, 1, size * nitems, stream);
45 assert(ret == size * nitems);
46 return ret;
47}
48
Lev Walkinf15320b2004-06-03 03:38:44 +000049/*
50 * Print the contents of the parsed ASN tree.
51 */
52int
Lev Walkin3140e0e2004-08-18 04:50:37 +000053asn1print(asn1p_t *asn, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000054 asn1p_module_t *mod;
Lev Walkinc70c2ef2004-09-30 06:38:21 +000055 int modno = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000056
57 if(asn == NULL) {
58 errno = EINVAL;
59 return -1;
60 }
61
Lev Walkinf7484512004-10-13 09:13:56 +000062 if(flags & APF_PRINT_XML_DTD)
Lev Walkinf2b2f372016-03-14 02:23:48 -070063 safe_printf("<!-- XML DTD generated by asn1c-" VERSION " -->\n\n");
Lev Walkinf7484512004-10-13 09:13:56 +000064
Lev Walkinf15320b2004-06-03 03:38:44 +000065 TQ_FOR(mod, &(asn->modules), mod_next) {
Lev Walkin6b3ff542006-03-06 14:51:00 +000066 if(mod->_tags & MT_STANDARD_MODULE)
67 return 0; /* Ignore modules imported from skeletons */
Lev Walkinf2b2f372016-03-14 02:23:48 -070068 if(modno++) safe_printf("\n");
Lev Walkin3140e0e2004-08-18 04:50:37 +000069 asn1print_module(asn, mod, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +000070 }
71
Lev Walkin112d69e2005-03-09 20:52:15 +000072 if(flags & APF_PRINT_XML_DTD) {
73 /* Values for BOOLEAN */
Lev Walkinf2b2f372016-03-14 02:23:48 -070074 safe_printf("<!ELEMENT true EMPTY>\n");
75 safe_printf("<!ELEMENT false EMPTY>\n");
Lev Walkin112d69e2005-03-09 20:52:15 +000076 }
77
Lev Walkinf15320b2004-06-03 03:38:44 +000078 return 0;
79}
80
81static int
Lev Walkin3140e0e2004-08-18 04:50:37 +000082asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +000083 asn1p_expr_t *tc;
84
Lev Walkinf7484512004-10-13 09:13:56 +000085 if(flags & APF_PRINT_XML_DTD)
Lev Walkinf2b2f372016-03-14 02:23:48 -070086 safe_printf("<!-- ASN.1 module\n");
Lev Walkinf7484512004-10-13 09:13:56 +000087
Lev Walkinf2b2f372016-03-14 02:23:48 -070088 safe_printf("%s ", mod->ModuleName);
Lev Walkinf15320b2004-06-03 03:38:44 +000089 if(mod->module_oid) {
Lev Walkinb36317c2005-08-12 10:09:10 +000090 asn1print_oid(strlen(mod->ModuleName), mod->module_oid, flags);
Lev Walkinf2b2f372016-03-14 02:23:48 -070091 safe_printf("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +000092 }
93
Lev Walkinf7484512004-10-13 09:13:56 +000094 if(flags & APF_PRINT_XML_DTD) {
95 if(mod->source_file_name
96 && strcmp(mod->source_file_name, "-"))
Lev Walkinf2b2f372016-03-14 02:23:48 -070097 safe_printf("found in %s", mod->source_file_name);
98 safe_printf(" -->\n\n");
Lev Walkinf7484512004-10-13 09:13:56 +000099
100 TQ_FOR(tc, &(mod->members), next) {
101 asn1print_expr_dtd(asn, mod, tc, flags, 0);
102 }
103
104 return 0;
105 }
106
Lev Walkinf2b2f372016-03-14 02:23:48 -0700107 safe_printf("DEFINITIONS");
Lev Walkinf15320b2004-06-03 03:38:44 +0000108
Lev Walkin3140e0e2004-08-18 04:50:37 +0000109 if(mod->module_flags & MSF_TAG_INSTRUCTIONS)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700110 safe_printf(" TAG INSTRUCTIONS");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000111 if(mod->module_flags & MSF_XER_INSTRUCTIONS)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700112 safe_printf(" XER INSTRUCTIONS");
Lev Walkinf15320b2004-06-03 03:38:44 +0000113 if(mod->module_flags & MSF_EXPLICIT_TAGS)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700114 safe_printf(" EXPLICIT TAGS");
Lev Walkinf15320b2004-06-03 03:38:44 +0000115 if(mod->module_flags & MSF_IMPLICIT_TAGS)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700116 safe_printf(" IMPLICIT TAGS");
Lev Walkinf15320b2004-06-03 03:38:44 +0000117 if(mod->module_flags & MSF_AUTOMATIC_TAGS)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700118 safe_printf(" AUTOMATIC TAGS");
Lev Walkinf15320b2004-06-03 03:38:44 +0000119 if(mod->module_flags & MSF_EXTENSIBILITY_IMPLIED)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700120 safe_printf(" EXTENSIBILITY IMPLIED");
Lev Walkinf15320b2004-06-03 03:38:44 +0000121
Lev Walkinf2b2f372016-03-14 02:23:48 -0700122 safe_printf(" ::=\n");
123 safe_printf("BEGIN\n\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000124
125 TQ_FOR(tc, &(mod->members), next) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000126 asn1print_expr(asn, mod, tc, flags, 0);
Lev Walkind370e9f2006-03-16 10:03:35 +0000127 if(flags & APF_PRINT_CONSTRAINTS)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700128 safe_printf("\n");
Lev Walkinb1ef3962004-08-20 13:24:28 +0000129 else
Lev Walkinf2b2f372016-03-14 02:23:48 -0700130 safe_printf("\n\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000131 }
132
Lev Walkinf2b2f372016-03-14 02:23:48 -0700133 safe_printf("END\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000134
135 return 0;
136}
137
138static int
Lev Walkind6db8022005-03-18 03:53:05 +0000139asn1print_oid(int prior_len, asn1p_oid_t *oid, enum asn1print_flags flags) {
140 size_t accum = prior_len;
Lev Walkinf15320b2004-06-03 03:38:44 +0000141 int ac;
Lev Walkinf15320b2004-06-03 03:38:44 +0000142
Lev Walkind9bd7752004-06-05 08:17:50 +0000143 (void)flags; /* Unused argument */
144
Lev Walkinf2b2f372016-03-14 02:23:48 -0700145 safe_printf("{");
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 for(ac = 0; ac < oid->arcs_count; ac++) {
Lev Walkin4efbfb72005-02-25 14:20:30 +0000147 const char *arcname = oid->arcs[ac].name;
148
Lev Walkin5b7eeaf2005-03-28 17:52:43 +0000149 if(accum + strlen(arcname ? arcname : "") > 72) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700150 safe_printf("\n\t");
Lev Walkin5b7eeaf2005-03-28 17:52:43 +0000151 accum = 8;
Lev Walkind6db8022005-03-18 03:53:05 +0000152 } else {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700153 accum += safe_printf(" ");
Lev Walkin4efbfb72005-02-25 14:20:30 +0000154 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000155
Lev Walkin4efbfb72005-02-25 14:20:30 +0000156 if(arcname) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700157 accum += safe_printf("%s", arcname);
Lev Walkin0056aec2004-09-05 10:38:50 +0000158 if(oid->arcs[ac].number >= 0) {
Lev Walkinda997b12017-08-04 01:38:41 -0700159 accum += safe_printf("(%s)",
160 asn1p_itoa(oid->arcs[ac].number));
Lev Walkin0056aec2004-09-05 10:38:50 +0000161 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000162 } else {
Lev Walkinda997b12017-08-04 01:38:41 -0700163 accum += safe_printf("%s", asn1p_itoa(oid->arcs[ac].number));
Lev Walkinf15320b2004-06-03 03:38:44 +0000164 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000165 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700166 safe_printf(" }");
Lev Walkinf15320b2004-06-03 03:38:44 +0000167
168 return 0;
169}
170
171static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000172asn1print_ref(asn1p_ref_t *ref, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000173
Lev Walkind9bd7752004-06-05 08:17:50 +0000174 (void)flags; /* Unused argument */
175
Lev Walkin62d95d22017-08-06 23:41:11 -0700176 for(size_t cc = 0; cc < ref->comp_count; cc++) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700177 if(cc) safe_printf(".");
178 safe_printf("%s", ref->components[cc].name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000179 }
180
181 return 0;
182}
183
184static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000185asn1print_tag(asn1p_expr_t *tc, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000186 struct asn1p_type_tag_s *tag = &tc->tag;
187
Lev Walkind9bd7752004-06-05 08:17:50 +0000188 (void)flags; /* Unused argument */
189
Lev Walkinf2b2f372016-03-14 02:23:48 -0700190 safe_printf("%s", asn1p_tag2string(tag, 0));
Lev Walkinf15320b2004-06-03 03:38:44 +0000191
192 return 0;
193}
194
195static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000196asn1print_value(asn1p_value_t *val, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000197
198 if(val == NULL)
199 return 0;
200
201 switch(val->type) {
202 case ATV_NOVALUE:
203 break;
Lev Walkinb1e07082004-09-15 11:44:55 +0000204 case ATV_NULL:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700205 safe_printf("NULL");
Lev Walkinb1e07082004-09-15 11:44:55 +0000206 return 0;
207 case ATV_REAL:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700208 safe_printf("%f", val->value.v_double);
Lev Walkinb1e07082004-09-15 11:44:55 +0000209 return 0;
Lev Walkina9532f42006-09-17 04:52:50 +0000210 case ATV_TYPE:
211 asn1print_expr(val->value.v_type->module->asn1p,
212 val->value.v_type->module,
213 val->value.v_type, flags, 0);
214 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000215 case ATV_INTEGER:
Lev Walkinda997b12017-08-04 01:38:41 -0700216 safe_printf("%s", asn1p_itoa(val->value.v_integer));
Lev Walkinf15320b2004-06-03 03:38:44 +0000217 return 0;
Lev Walkinf2b2f372016-03-14 02:23:48 -0700218 case ATV_MIN: safe_printf("MIN"); return 0;
219 case ATV_MAX: safe_printf("MAX"); return 0;
220 case ATV_FALSE: safe_printf("FALSE"); return 0;
221 case ATV_TRUE: safe_printf("TRUE"); return 0;
Lev Walkin1e448d32005-03-24 14:26:38 +0000222 case ATV_TUPLE:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700223 safe_printf("{%d, %d}",
Lev Walkin1e448d32005-03-24 14:26:38 +0000224 (int)(val->value.v_integer >> 4),
225 (int)(val->value.v_integer & 0x0f));
226 return 0;
227 case ATV_QUADRUPLE:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700228 safe_printf("{%d, %d, %d, %d}",
Lev Walkin1e448d32005-03-24 14:26:38 +0000229 (int)((val->value.v_integer >> 24) & 0xff),
230 (int)((val->value.v_integer >> 16) & 0xff),
231 (int)((val->value.v_integer >> 8) & 0xff),
232 (int)((val->value.v_integer >> 0) & 0xff)
233 );
234 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000235 case ATV_STRING:
236 {
Lev Walkin84fbd722005-06-15 18:41:50 +0000237 char *p = (char *)val->value.string.buf;
Lev Walkinf15320b2004-06-03 03:38:44 +0000238 putchar('"');
239 if(strchr(p, '"')) {
240 /* Mask quotes */
241 for(; *p; p++) {
242 if(*p == '"')
243 putchar(*p);
244 putchar(*p);
245 }
246 } else {
247 fputs(p, stdout);
248 }
249 putchar('"');
250 }
251 return 0;
252 case ATV_UNPARSED:
Lev Walkin84fbd722005-06-15 18:41:50 +0000253 fputs((char *)val->value.string.buf, stdout);
Lev Walkinf15320b2004-06-03 03:38:44 +0000254 return 0;
255 case ATV_BITVECTOR:
256 {
257 uint8_t *bitvector;
258 int bits;
259 int i;
260
261 bitvector = val->value.binary_vector.bits;
262 bits = val->value.binary_vector.size_in_bits;
263
Lev Walkinf2b2f372016-03-14 02:23:48 -0700264 safe_printf("'");
Lev Walkinf15320b2004-06-03 03:38:44 +0000265 if(bits%8) {
266 for(i = 0; i < bits; i++) {
267 uint8_t uc;
268 uc = bitvector[i>>3];
269 putchar(((uc >> (7-(i%8)))&1)?'1':'0');
270 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700271 safe_printf("'B");
Lev Walkinf15320b2004-06-03 03:38:44 +0000272 } else {
273 char hextable[16] = "0123456789ABCDEF";
274 for(i = 0; i < (bits>>3); i++) {
275 putchar(hextable[bitvector[i] >> 4]);
276 putchar(hextable[bitvector[i] & 0x0f]);
277 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700278 safe_printf("'H");
Lev Walkinf15320b2004-06-03 03:38:44 +0000279 }
Lev Walkin043af0d2005-02-24 21:07:35 +0000280 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000281 }
Lev Walkinb1e07082004-09-15 11:44:55 +0000282 case ATV_REFERENCED:
283 return asn1print_ref(val->value.reference, flags);
Lev Walkin5045dfa2006-03-21 09:41:28 +0000284 case ATV_VALUESET:
285 return asn1print_constraint(val->value.constraint, flags);
Lev Walkinb1e07082004-09-15 11:44:55 +0000286 case ATV_CHOICE_IDENTIFIER:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700287 safe_printf("%s: ", val->value.choice_identifier.identifier);
Lev Walkinb1e07082004-09-15 11:44:55 +0000288 return asn1print_value(val->value.choice_identifier.value, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +0000289 }
290
291 assert(val->type || !"Unknown");
292
293 return 0;
294}
295
296static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000297asn1print_constraint(asn1p_constraint_t *ct, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000298 int symno = 0;
299
300 if(ct == 0) return 0;
301
302 if(ct->type == ACT_CA_SET)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700303 safe_printf("(");
Lev Walkinf15320b2004-06-03 03:38:44 +0000304
305 switch(ct->type) {
Lev Walkinff7dd142005-03-20 12:58:00 +0000306 case ACT_EL_TYPE:
Lev Walkin5045dfa2006-03-21 09:41:28 +0000307 asn1print_value(ct->containedSubtype, flags);
Lev Walkinff7dd142005-03-20 12:58:00 +0000308 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000309 case ACT_EL_VALUE:
310 asn1print_value(ct->value, flags);
311 break;
312 case ACT_EL_RANGE:
313 case ACT_EL_LLRANGE:
314 case ACT_EL_RLRANGE:
315 case ACT_EL_ULRANGE:
316 asn1print_value(ct->range_start, flags);
317 switch(ct->type) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700318 case ACT_EL_RANGE: safe_printf(".."); break;
319 case ACT_EL_LLRANGE: safe_printf("<.."); break;
320 case ACT_EL_RLRANGE: safe_printf("..<"); break;
321 case ACT_EL_ULRANGE: safe_printf("<..<"); break;
322 default: safe_printf("?..?"); break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000323 }
324 asn1print_value(ct->range_stop, flags);
325 break;
326 case ACT_EL_EXT:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700327 safe_printf("...");
Lev Walkinf15320b2004-06-03 03:38:44 +0000328 break;
329 case ACT_CT_SIZE:
330 case ACT_CT_FROM:
331 switch(ct->type) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700332 case ACT_CT_SIZE: safe_printf("SIZE("); break;
333 case ACT_CT_FROM: safe_printf("FROM("); break;
334 default: safe_printf("??? ("); break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000335 }
336 assert(ct->el_count != 0);
337 assert(ct->el_count == 1);
338 asn1print_constraint(ct->elements[0], flags);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700339 safe_printf(")");
Lev Walkinf15320b2004-06-03 03:38:44 +0000340 break;
341 case ACT_CT_WCOMP:
Lev Walkine596bf02005-03-28 15:01:27 +0000342 assert(ct->el_count != 0);
343 assert(ct->el_count == 1);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700344 safe_printf("WITH COMPONENT (");
Lev Walkine596bf02005-03-28 15:01:27 +0000345 asn1print_constraint(ct->elements[0], flags);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700346 safe_printf(")");
Lev Walkin8638f0d2005-03-28 07:50:06 +0000347 break;
Lev Walkine596bf02005-03-28 15:01:27 +0000348 case ACT_CT_WCOMPS: {
349 unsigned int i;
Lev Walkinf2b2f372016-03-14 02:23:48 -0700350 safe_printf("WITH COMPONENTS { ");
Lev Walkine596bf02005-03-28 15:01:27 +0000351 for(i = 0; i < ct->el_count; i++) {
352 asn1p_constraint_t *cel = ct->elements[i];
Lev Walkinf2b2f372016-03-14 02:23:48 -0700353 if(i) safe_printf(", ");
354 safe_fwrite(cel->value->value.string.buf,
Lev Walkine596bf02005-03-28 15:01:27 +0000355 1, cel->value->value.string.size,
356 stdout);
357 if(cel->el_count) {
358 assert(cel->el_count == 1);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700359 safe_printf(" ");
Lev Walkine596bf02005-03-28 15:01:27 +0000360 asn1print_constraint(cel->elements[0],
361 flags);
362 }
363 switch(cel->presence) {
364 case ACPRES_DEFAULT: break;
Lev Walkinf2b2f372016-03-14 02:23:48 -0700365 case ACPRES_PRESENT: safe_printf(" PRESENT"); break;
366 case ACPRES_ABSENT: safe_printf(" ABSENT"); break;
367 case ACPRES_OPTIONAL: safe_printf(" OPTIONAL");break;
Lev Walkine596bf02005-03-28 15:01:27 +0000368 }
369 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700370 safe_printf(" }");
Lev Walkine596bf02005-03-28 15:01:27 +0000371 }
Lev Walkin8638f0d2005-03-28 07:50:06 +0000372 break;
Lev Walkin1893ddf2005-03-20 14:28:32 +0000373 case ACT_CT_CTDBY:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700374 safe_printf("CONSTRAINED BY ");
Lev Walkin1893ddf2005-03-20 14:28:32 +0000375 assert(ct->value->type == ATV_UNPARSED);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700376 safe_fwrite(ct->value->value.string.buf,
Lev Walkin1893ddf2005-03-20 14:28:32 +0000377 1, ct->value->value.string.size, stdout);
Lev Walkina9532f42006-09-17 04:52:50 +0000378 break;
379 case ACT_CT_CTNG:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700380 safe_printf("CONTAINING ");
Lev Walkina9532f42006-09-17 04:52:50 +0000381 asn1print_expr(ct->value->value.v_type->module->asn1p,
382 ct->value->value.v_type->module,
383 ct->value->value.v_type,
384 flags, 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000385 break;
Lev Walkin5c541f12006-10-18 18:40:14 +0000386 case ACT_CT_PATTERN:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700387 safe_printf("PATTERN ");
Lev Walkin5c541f12006-10-18 18:40:14 +0000388 asn1print_value(ct->value, flags);
Lev Walkin5c541f12006-10-18 18:40:14 +0000389 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000390 case ACT_CA_SET: symno++;
391 case ACT_CA_CRC: symno++;
392 case ACT_CA_CSV: symno++;
393 case ACT_CA_UNI: symno++;
394 case ACT_CA_INT: symno++;
395 case ACT_CA_EXC:
396 {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000397 char *symtable[] = { " EXCEPT ", " ^ ", " | ", ",",
Lev Walkinf15320b2004-06-03 03:38:44 +0000398 "", "(" };
Lev Walkin0056aec2004-09-05 10:38:50 +0000399 unsigned int i;
Lev Walkinf15320b2004-06-03 03:38:44 +0000400 for(i = 0; i < ct->el_count; i++) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000401 if(i) fputs(symtable[symno], stdout);
402 if(ct->type == ACT_CA_CRC) fputs("{", stdout);
Lev Walkin1e448d32005-03-24 14:26:38 +0000403 asn1print_constraint(ct->elements[i], flags);
Lev Walkinf15320b2004-06-03 03:38:44 +0000404 if(ct->type == ACT_CA_CRC) fputs("}", stdout);
405 if(i+1 < ct->el_count
406 && ct->type == ACT_CA_SET)
407 fputs(")", stdout);
408 }
409 }
410 break;
Lev Walkin1e448d32005-03-24 14:26:38 +0000411 case ACT_CA_AEX:
412 assert(ct->el_count == 1);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700413 safe_printf("ALL EXCEPT ");
Lev Walkin1e448d32005-03-24 14:26:38 +0000414 asn1print_constraint(ct->elements[0], flags);
415 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000416 case ACT_INVALID:
417 assert(ct->type != ACT_INVALID);
418 break;
419 }
420
421 if(ct->type == ACT_CA_SET)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700422 safe_printf(")");
Lev Walkinf15320b2004-06-03 03:38:44 +0000423
424 return 0;
425}
426
427static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000428asn1print_params(asn1p_paramlist_t *pl, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000429 if(pl) {
430 int i;
Lev Walkinf2b2f372016-03-14 02:23:48 -0700431 safe_printf("{");
Lev Walkinf15320b2004-06-03 03:38:44 +0000432 for(i = 0; i < pl->params_count; i++) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700433 if(i) safe_printf(", ");
Lev Walkinf15320b2004-06-03 03:38:44 +0000434 if(pl->params[i].governor) {
435 asn1print_ref(pl->params[i].governor, flags);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700436 safe_printf(":");
Lev Walkinf15320b2004-06-03 03:38:44 +0000437 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700438 safe_printf("%s", pl->params[i].argument);
Lev Walkinf15320b2004-06-03 03:38:44 +0000439 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700440 safe_printf("}");
Lev Walkinf15320b2004-06-03 03:38:44 +0000441 }
442
443 return 0;
444}
445
446static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000447asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000448 if(wx) {
449 asn1p_wsyntx_chunk_t *wc;
Lev Walkinf15320b2004-06-03 03:38:44 +0000450 TQ_FOR(wc, &(wx->chunks), next) {
Lev Walkin9d542d22006-03-14 16:31:37 +0000451 switch(wc->type) {
452 case WC_LITERAL:
Lev Walkin57074f12006-03-16 05:11:14 +0000453 case WC_WHITESPACE:
Lev Walkind370e9f2006-03-16 10:03:35 +0000454 case WC_FIELD:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700455 safe_printf("%s", wc->content.token);
Lev Walkin9d542d22006-03-14 16:31:37 +0000456 break;
Lev Walkin9d542d22006-03-14 16:31:37 +0000457 case WC_OPTIONALGROUP:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700458 safe_printf("[");
Lev Walkin9d542d22006-03-14 16:31:37 +0000459 asn1print_with_syntax(wc->content.syntax,flags);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700460 safe_printf("]");
Lev Walkin9d542d22006-03-14 16:31:37 +0000461 break;
462 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000463 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000464 }
465
466 return 0;
467}
468
469static int
Lev Walkin3140e0e2004-08-18 04:50:37 +0000470asn1print_crange_value(asn1cnst_edge_t *edge, int as_char) {
471 switch(edge->type) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700472 case ARE_MIN: safe_printf("MIN"); break;
473 case ARE_MAX: safe_printf("MAX"); break;
Lev Walkin3140e0e2004-08-18 04:50:37 +0000474 case ARE_VALUE:
475 if(as_char) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700476 safe_printf("\"%c\"", (unsigned char)edge->value);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000477 } else {
Lev Walkinda997b12017-08-04 01:38:41 -0700478 safe_printf("%s", asn1p_itoa(edge->value));
Lev Walkin3140e0e2004-08-18 04:50:37 +0000479 }
480 }
481 return 0;
482}
483
484static int
Lev Walkina28cbb92017-07-31 20:20:17 -0700485asn1print_constraint_explain_type(const char *dbg_name, asn1p_expr_type_e expr_type, asn1p_constraint_t *ct, enum asn1p_constraint_type_e type, enum cpr_flags cpr) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000486 asn1cnst_range_t *range;
487 int as_char = (type==ACT_CT_FROM);
488 int i;
489
Lev Walkina28cbb92017-07-31 20:20:17 -0700490 range = asn1constraint_compute_constraint_range(dbg_name, expr_type, ct, type, 0, 0, cpr);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000491 if(!range) return -1;
492
Lev Walkina2abcaa2017-07-23 21:08:49 +0400493 if(range->incompatible) return 0;
494
495 if((cpr & CPR_strict_OER_visibility) && range->not_OER_visible) {
496 asn1constraint_range_free(range);
497 return 0;
498 }
499
500 if((cpr & CPR_strict_PER_visibility) && range->not_PER_visible) {
Lev Walkine8e87f12004-08-25 02:00:03 +0000501 asn1constraint_range_free(range);
502 return 0;
503 }
504
Lev Walkin3140e0e2004-08-18 04:50:37 +0000505 switch(type) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700506 case ACT_CT_FROM: safe_printf("(FROM("); break;
507 case ACT_CT_SIZE: safe_printf("(SIZE("); break;
508 default: safe_printf("("); break;
Lev Walkin3140e0e2004-08-18 04:50:37 +0000509 }
510 for(i = -1; i < range->el_count; i++) {
511 asn1cnst_range_t *r;
512 if(i == -1) {
513 if(range->el_count) continue;
514 r = range;
515 } else {
516 r = range->elements[i];
517 }
518 if(i > 0) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700519 safe_printf(" | ");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000520 }
521 asn1print_crange_value(&r->left, as_char);
522 if(r->left.type != r->right.type
523 || r->left.value != r->right.value) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700524 safe_printf("..");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000525 asn1print_crange_value(&r->right, as_char);
526 }
527 }
528 if(range->extensible)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700529 safe_printf(",...");
530 safe_printf(type==ACT_EL_RANGE?")":"))");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000531
532 if(range->empty_constraint)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700533 safe_printf(":Empty!");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000534
535 asn1constraint_range_free(range);
536 return 0;
537}
538
539static int
Lev Walkina28cbb92017-07-31 20:20:17 -0700540asn1print_constraint_explain(const char *dbg_name, asn1p_expr_type_e expr_type,
Lev Walkina2abcaa2017-07-23 21:08:49 +0400541 asn1p_constraint_t *ct, enum cpr_flags cpr) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000542
Lev Walkina28cbb92017-07-31 20:20:17 -0700543 asn1print_constraint_explain_type(dbg_name, expr_type, ct, ACT_EL_RANGE, cpr);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700544 safe_printf(" ");
Lev Walkina28cbb92017-07-31 20:20:17 -0700545 asn1print_constraint_explain_type(dbg_name, expr_type, ct, ACT_CT_SIZE, cpr);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700546 safe_printf(" ");
Lev Walkina28cbb92017-07-31 20:20:17 -0700547 asn1print_constraint_explain_type(dbg_name, expr_type, ct, ACT_CT_FROM, cpr);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000548
549 return 0;
550}
551
552static int
553asn1print_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 +0000554 int SEQ_OF = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000555
Lev Walkinf4069d22005-02-15 07:06:05 +0000556 if(flags & APF_LINE_COMMENTS && !(flags & APF_NOINDENT))
Lev Walkinf7484512004-10-13 09:13:56 +0000557 INDENT("-- #line %d\n", tc->_lineno);
Lev Walkinef625402005-09-05 05:17:57 +0000558
559 /* Reconstruct compiler directive information */
560 if((tc->marker.flags & EM_INDIRECT)
561 && (tc->marker.flags & EM_OMITABLE) != EM_OMITABLE) {
562 if((flags & APF_NOINDENT))
Lev Walkinf2b2f372016-03-14 02:23:48 -0700563 safe_printf(" --<ASN1C.RepresentAsPointer>-- ");
Lev Walkinef625402005-09-05 05:17:57 +0000564 else
565 INDENT("--<ASN1C.RepresentAsPointer>--\n");
566 }
567
Lev Walkina00d6b32006-03-21 03:40:38 +0000568 if(tc->Identifier
569 && (!(tc->meta_type == AMT_VALUE && tc->expr_type == A1TC_REFERENCE)
570 || level == 0))
Lev Walkinf15320b2004-06-03 03:38:44 +0000571 INDENT("%s", tc->Identifier);
572
Lev Walkina00d6b32006-03-21 03:40:38 +0000573 if(tc->lhs_params) {
574 asn1print_params(tc->lhs_params, flags);
Lev Walkinf15320b2004-06-03 03:38:44 +0000575 }
576
577 if(tc->meta_type != AMT_VALUE
Lev Walkinc74ea222004-08-25 02:27:47 +0000578 && tc->meta_type != AMT_VALUESET
Lev Walkinf15320b2004-06-03 03:38:44 +0000579 && tc->expr_type != A1TC_EXTENSIBLE) {
580 if(level) {
Lev Walkinf4069d22005-02-15 07:06:05 +0000581 if(tc->Identifier && !(flags & APF_NOINDENT))
Lev Walkinf2b2f372016-03-14 02:23:48 -0700582 safe_printf("\t");
Lev Walkinf15320b2004-06-03 03:38:44 +0000583 } else {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700584 safe_printf(" ::=");
Lev Walkinf15320b2004-06-03 03:38:44 +0000585 }
586 }
587
588 if(tc->tag.tag_class) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700589 safe_printf(" ");
Lev Walkinf15320b2004-06-03 03:38:44 +0000590 asn1print_tag(tc, flags);
591 }
592
593 switch(tc->expr_type) {
594 case A1TC_EXTENSIBLE:
595 if(tc->value) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700596 safe_printf("!");
Lev Walkinf15320b2004-06-03 03:38:44 +0000597 asn1print_value(tc->value, flags);
598 }
599 break;
Lev Walkinfd151ce2004-08-22 03:08:51 +0000600 case A1TC_COMPONENTS_OF:
601 SEQ_OF = 1; /* Equivalent to SET OF for printint purposes */
Lev Walkinf2b2f372016-03-14 02:23:48 -0700602 safe_printf(" COMPONENTS OF");
Lev Walkinfd151ce2004-08-22 03:08:51 +0000603 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000604 case A1TC_REFERENCE:
605 case A1TC_UNIVERVAL:
Lev Walkinf15320b2004-06-03 03:38:44 +0000606 break;
607 case A1TC_CLASSDEF:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700608 safe_printf(" CLASS");
Lev Walkinf15320b2004-06-03 03:38:44 +0000609 break;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000610 case A1TC_CLASSFIELD_TFS ... A1TC_CLASSFIELD_OSFS:
Lev Walkinf15320b2004-06-03 03:38:44 +0000611 /* Nothing to print here */
612 break;
Lev Walkinb1ef3962004-08-20 13:24:28 +0000613 case ASN_CONSTR_SET_OF:
614 case ASN_CONSTR_SEQUENCE_OF:
615 SEQ_OF = 1;
616 if(tc->expr_type == ASN_CONSTR_SET_OF)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700617 safe_printf(" SET");
Lev Walkinb1ef3962004-08-20 13:24:28 +0000618 else
Lev Walkinf2b2f372016-03-14 02:23:48 -0700619 safe_printf(" SEQUENCE");
Lev Walkinb1ef3962004-08-20 13:24:28 +0000620 if(tc->constraints) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700621 safe_printf(" ");
Lev Walkinb1ef3962004-08-20 13:24:28 +0000622 asn1print_constraint(tc->constraints, flags);
623 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700624 safe_printf(" OF");
Lev Walkinb1ef3962004-08-20 13:24:28 +0000625 break;
Lev Walkin5045dfa2006-03-21 09:41:28 +0000626 case A1TC_VALUESET:
627 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000628 default:
629 {
630 char *p = ASN_EXPR_TYPE2STR(tc->expr_type);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700631 safe_printf(" %s", p?p:"<unknown type!>");
Lev Walkinf15320b2004-06-03 03:38:44 +0000632 }
633 break;
634 }
635
Lev Walkinb9d0ae32005-06-02 04:06:24 +0000636 /*
637 * Put the name of the referred type.
638 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000639 if(tc->reference) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700640 safe_printf(" ");
Lev Walkinf15320b2004-06-03 03:38:44 +0000641 asn1print_ref(tc->reference, flags);
642 }
643
Lev Walkin5045dfa2006-03-21 09:41:28 +0000644 if(tc->meta_type == AMT_VALUESET && level == 0)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700645 safe_printf(" ::=");
Lev Walkinc74ea222004-08-25 02:27:47 +0000646
Lev Walkinf15320b2004-06-03 03:38:44 +0000647 /*
648 * Display the descendants (children) of the current type.
649 */
Lev Walkinc74ea222004-08-25 02:27:47 +0000650 if(TQ_FIRST(&(tc->members))
651 || (tc->expr_type & ASN_CONSTR_MASK)
Lev Walkinc74ea222004-08-25 02:27:47 +0000652 || tc->meta_type == AMT_OBJECT
Lev Walkin9c2285a2006-03-09 08:49:26 +0000653 || tc->meta_type == AMT_OBJECTCLASS
654 || tc->meta_type == AMT_OBJECTFIELD
Lev Walkinc74ea222004-08-25 02:27:47 +0000655 ) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000656 asn1p_expr_t *se; /* SubExpression */
Lev Walkin9c2285a2006-03-09 08:49:26 +0000657 int put_braces = (!SEQ_OF) /* Don't need 'em, if SET OF... */
658 && (tc->meta_type != AMT_OBJECTFIELD);
Lev Walkinf15320b2004-06-03 03:38:44 +0000659
Lev Walkinc74ea222004-08-25 02:27:47 +0000660 if(put_braces) {
Lev Walkinf4069d22005-02-15 07:06:05 +0000661 if(flags & APF_NOINDENT) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700662 safe_printf("{");
Lev Walkinf4069d22005-02-15 07:06:05 +0000663 if(!TQ_FIRST(&tc->members))
Lev Walkinf2b2f372016-03-14 02:23:48 -0700664 safe_printf("}");
Lev Walkinf4069d22005-02-15 07:06:05 +0000665 } else {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700666 safe_printf(" {");
Lev Walkinf4069d22005-02-15 07:06:05 +0000667 if(TQ_FIRST(&tc->members))
Lev Walkinf2b2f372016-03-14 02:23:48 -0700668 safe_printf("\n");
Lev Walkinf4069d22005-02-15 07:06:05 +0000669 else
Lev Walkinf2b2f372016-03-14 02:23:48 -0700670 safe_printf(" }");
Lev Walkinf4069d22005-02-15 07:06:05 +0000671 }
Lev Walkinc74ea222004-08-25 02:27:47 +0000672 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000673
674 TQ_FOR(se, &(tc->members), next) {
675 /*
Lev Walkinfd151ce2004-08-22 03:08:51 +0000676 * Print the expression as it were a stand-alone type.
Lev Walkinf15320b2004-06-03 03:38:44 +0000677 */
Lev Walkinf7484512004-10-13 09:13:56 +0000678 asn1print_expr(asn, mod, se, flags, level + 1);
Lev Walkinb1e07082004-09-15 11:44:55 +0000679 if((se->marker.flags & EM_DEFAULT) == EM_DEFAULT) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700680 safe_printf(" DEFAULT ");
Lev Walkinb1e07082004-09-15 11:44:55 +0000681 asn1print_value(se->marker.default_value, flags);
682 } else if((se->marker.flags & EM_OPTIONAL)
683 == EM_OPTIONAL) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700684 safe_printf(" OPTIONAL");
Lev Walkinb1e07082004-09-15 11:44:55 +0000685 }
Lev Walkinef625402005-09-05 05:17:57 +0000686 if(TQ_NEXT(se, next)) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700687 safe_printf(",");
Lev Walkinef625402005-09-05 05:17:57 +0000688 if(!(flags & APF_NOINDENT))
689 INDENT("\n");
690 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000691 }
692
Lev Walkinc74ea222004-08-25 02:27:47 +0000693 if(put_braces && TQ_FIRST(&tc->members)) {
Lev Walkinf4069d22005-02-15 07:06:05 +0000694 if(!(flags & APF_NOINDENT))
Lev Walkinf2b2f372016-03-14 02:23:48 -0700695 safe_printf("\n");
Lev Walkinf15320b2004-06-03 03:38:44 +0000696 INDENT("}");
697 }
698 }
699
Lev Walkin9d542d22006-03-14 16:31:37 +0000700 if(tc->with_syntax) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700701 safe_printf(" WITH SYNTAX {");
Lev Walkinf15320b2004-06-03 03:38:44 +0000702 asn1print_with_syntax(tc->with_syntax, flags);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700703 safe_printf("}\n");
Lev Walkin9d542d22006-03-14 16:31:37 +0000704 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000705
Lev Walkina00d6b32006-03-21 03:40:38 +0000706 /* Right hand specialization */
707 if(tc->rhs_pspecs) {
708 asn1p_expr_t *se;
Lev Walkinf2b2f372016-03-14 02:23:48 -0700709 safe_printf("{");
Lev Walkina00d6b32006-03-21 03:40:38 +0000710 TQ_FOR(se, &(tc->rhs_pspecs->members), next) {
711 asn1print_expr(asn, mod, se, flags, level + 1);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700712 if(TQ_NEXT(se, next)) safe_printf(", ");
Lev Walkina00d6b32006-03-21 03:40:38 +0000713 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700714 safe_printf("}");
Lev Walkina00d6b32006-03-21 03:40:38 +0000715 }
716
Lev Walkinb1ef3962004-08-20 13:24:28 +0000717 if(!SEQ_OF && tc->constraints) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700718 safe_printf(" ");
Lev Walkin557f27d2006-03-21 07:46:48 +0000719 if(tc->meta_type == AMT_VALUESET)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700720 safe_printf("{");
Lev Walkinf15320b2004-06-03 03:38:44 +0000721 asn1print_constraint(tc->constraints, flags);
Lev Walkin557f27d2006-03-21 07:46:48 +0000722 if(tc->meta_type == AMT_VALUESET)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700723 safe_printf("}");
Lev Walkinf15320b2004-06-03 03:38:44 +0000724 }
Lev Walkin3140e0e2004-08-18 04:50:37 +0000725
Lev Walkinf15320b2004-06-03 03:38:44 +0000726 if(tc->unique) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700727 safe_printf(" UNIQUE");
Lev Walkinf15320b2004-06-03 03:38:44 +0000728 }
729
730 if(tc->meta_type == AMT_VALUE
731 && tc->expr_type != A1TC_EXTENSIBLE) {
Lev Walkin0056aec2004-09-05 10:38:50 +0000732 if(tc->expr_type == A1TC_UNIVERVAL) {
Lev Walkinb1e07082004-09-15 11:44:55 +0000733 if(tc->value) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700734 safe_printf("(");
Lev Walkinb1e07082004-09-15 11:44:55 +0000735 asn1print_value(tc->value, flags);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700736 safe_printf(")");
Lev Walkinb1e07082004-09-15 11:44:55 +0000737 }
Lev Walkin0056aec2004-09-05 10:38:50 +0000738 } else {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700739 if(level == 0) safe_printf(" ::= ");
Lev Walkin0056aec2004-09-05 10:38:50 +0000740 asn1print_value(tc->value, flags);
741 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000742 }
743
Lev Walkinfd151ce2004-08-22 03:08:51 +0000744 /*
Lev Walkinf4069d22005-02-15 07:06:05 +0000745 * The following section exists entirely for debugging.
Lev Walkinfd151ce2004-08-22 03:08:51 +0000746 */
Lev Walkind370e9f2006-03-16 10:03:35 +0000747 if(flags & APF_PRINT_CONSTRAINTS
Lev Walkinb1ef3962004-08-20 13:24:28 +0000748 && tc->expr_type != A1TC_EXTENSIBLE) {
Lev Walkin3140e0e2004-08-18 04:50:37 +0000749 asn1p_expr_t *top_parent;
750
751 if(tc->combined_constraints) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700752 safe_printf("\n-- Combined constraints: ");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000753 asn1print_constraint(tc->combined_constraints, flags);
754 }
755
Lev Walkine4d6ab82004-09-22 16:05:13 +0000756 top_parent = asn1f_find_terminal_type_ex(asn, tc);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000757 if(top_parent) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700758 safe_printf("\n-- Practical constraints (%s): ",
Lev Walkine8e87f12004-08-25 02:00:03 +0000759 top_parent->Identifier);
Lev Walkina28cbb92017-07-31 20:20:17 -0700760 asn1print_constraint_explain(top_parent->Identifier,
761 top_parent->expr_type,
Lev Walkine8e87f12004-08-25 02:00:03 +0000762 tc->combined_constraints, 0);
Lev Walkina2abcaa2017-07-23 21:08:49 +0400763 safe_printf("\n-- OER-visible constraints (%s): ",
764 top_parent->Identifier);
Lev Walkina28cbb92017-07-31 20:20:17 -0700765 asn1print_constraint_explain(top_parent->Identifier,
766 top_parent->expr_type,
Lev Walkina2abcaa2017-07-23 21:08:49 +0400767 tc->combined_constraints, CPR_strict_OER_visibility);
Lev Walkinf2b2f372016-03-14 02:23:48 -0700768 safe_printf("\n-- PER-visible constraints (%s): ",
Lev Walkinb1ef3962004-08-20 13:24:28 +0000769 top_parent->Identifier);
Lev Walkina28cbb92017-07-31 20:20:17 -0700770 asn1print_constraint_explain(top_parent->Identifier,
771 top_parent->expr_type,
Lev Walkina2abcaa2017-07-23 21:08:49 +0400772 tc->combined_constraints, CPR_strict_PER_visibility);
Lev Walkin3140e0e2004-08-18 04:50:37 +0000773 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700774 safe_printf("\n");
Lev Walkin3140e0e2004-08-18 04:50:37 +0000775 }
776
Lev Walkind0f7b912017-08-07 18:13:04 -0700777 if(flags & APF_PRINT_CLASS_MATRIX) do {
Lev Walkin62d95d22017-08-06 23:41:11 -0700778 size_t col, maxidlen;
Lev Walkin4dcf8362017-08-07 20:10:05 -0700779 if(tc->ioc_table == NULL) {
Lev Walkind0f7b912017-08-07 18:13:04 -0700780 if(tc->expr_type == A1TC_CLASSDEF) {
781 safe_printf("\n-- Information Object Class table is empty");
782 }
Lev Walkind370e9f2006-03-16 10:03:35 +0000783 break;
784 }
Lev Walkind0f7b912017-08-07 18:13:04 -0700785 safe_printf("\n-- Information Object Set has %d entr%s:\n",
Lev Walkin4dcf8362017-08-07 20:10:05 -0700786 tc->ioc_table->rows,
787 tc->ioc_table->rows==1 ? "y" : "ies");
788 maxidlen = asn1p_ioc_table_max_identifier_length(tc->ioc_table);
789 for(ssize_t r = -1; r < (ssize_t)tc->ioc_table->rows; r++) {
790 asn1p_ioc_row_t *row;
791 row = tc->ioc_table->row[r<0?0:r];
Lev Walkinf2b2f372016-03-14 02:23:48 -0700792 if(r < 0) safe_printf("-- %s", r > 9 ? " " : "");
793 else safe_printf("-- [%*d]", r > 9 ? 2 : 1, r+1);
Lev Walkind370e9f2006-03-16 10:03:35 +0000794 for(col = 0; col < row->columns; col++) {
795 struct asn1p_ioc_cell_s *cell;
796 cell = &row->column[col];
797 if(r < 0) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700798 safe_printf("[%*s]", maxidlen,
Lev Walkind370e9f2006-03-16 10:03:35 +0000799 cell->field->Identifier);
800 continue;
801 }
802 if(!cell->value) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700803 safe_printf(" %*s ", maxidlen, "<no entry>");
Lev Walkind370e9f2006-03-16 10:03:35 +0000804 continue;
805 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700806 safe_printf(" %*s ", maxidlen,
Lev Walkind370e9f2006-03-16 10:03:35 +0000807 cell->value->Identifier);
808 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700809 safe_printf("\n");
Lev Walkind370e9f2006-03-16 10:03:35 +0000810 }
811 } while(0);
812
Lev Walkina00d6b32006-03-21 03:40:38 +0000813 if(flags & APF_PRINT_CLASS_MATRIX
814 && tc->lhs_params) do {
815 int i;
816 if(tc->specializations.pspecs_count == 0) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700817 safe_printf("\n-- No specializations found\n");
Lev Walkina00d6b32006-03-21 03:40:38 +0000818 break;
819 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700820 safe_printf("\n-- Specializations list has %d entr%s:\n",
Lev Walkina00d6b32006-03-21 03:40:38 +0000821 tc->specializations.pspecs_count,
822 tc->specializations.pspecs_count == 1 ? "y" : "ies");
823 for(i = 0; i < tc->specializations.pspecs_count; i++) {
824 asn1p_expr_t *se;
825 struct asn1p_pspec_s *pspec;
826 pspec = &tc->specializations.pspec[i];
Lev Walkinf2b2f372016-03-14 02:23:48 -0700827 safe_printf("-- ");
Lev Walkina00d6b32006-03-21 03:40:38 +0000828 TQ_FOR(se, &(pspec->rhs_pspecs->members), next) {
829 asn1print_expr(asn, mod, se, flags, level+1);
830 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700831 safe_printf("\n");
Lev Walkina00d6b32006-03-21 03:40:38 +0000832 }
833 } while(0);
834
Lev Walkinf15320b2004-06-03 03:38:44 +0000835 return 0;
836}
Lev Walkin3140e0e2004-08-18 04:50:37 +0000837
Lev Walkinf7484512004-10-13 09:13:56 +0000838
839static int
840asn1print_expr_dtd(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, enum asn1print_flags flags, int level) {
841 asn1p_expr_t *se;
842 int expr_unordered = 0;
Lev Walkinef39f7e2004-10-14 05:11:25 +0000843 int dont_involve_children = 0;
Lev Walkinf7484512004-10-13 09:13:56 +0000844
845 switch(expr->meta_type) {
846 case AMT_TYPE:
847 case AMT_TYPEREF:
848 break;
849 default:
850 if(expr->expr_type == A1TC_UNIVERVAL)
851 break;
852 return 0;
853 }
854
855 if(!expr->Identifier) return 0;
856
Lev Walkinf7484512004-10-13 09:13:56 +0000857 if(flags & APF_LINE_COMMENTS)
858 INDENT("<!-- #line %d -->\n", expr->_lineno);
859 INDENT("<!ELEMENT %s", expr->Identifier);
860
861 if(expr->expr_type == A1TC_REFERENCE) {
862 se = asn1f_find_terminal_type_ex(asn, expr);
863 if(!se) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700864 safe_printf(" (ANY)");
Lev Walkinf7484512004-10-13 09:13:56 +0000865 return 0;
866 }
867 expr = se;
Lev Walkinef39f7e2004-10-14 05:11:25 +0000868 dont_involve_children = 1;
Lev Walkinf7484512004-10-13 09:13:56 +0000869 }
870
Lev Walkind7963aa2005-03-10 15:16:56 +0000871 if(expr->expr_type == ASN_CONSTR_CHOICE
872 || expr->expr_type == ASN_CONSTR_SEQUENCE_OF
873 || expr->expr_type == ASN_CONSTR_SET_OF
874 || expr->expr_type == ASN_CONSTR_SET
Lev Walkin112d69e2005-03-09 20:52:15 +0000875 || expr->expr_type == ASN_BASIC_INTEGER
876 || expr->expr_type == ASN_BASIC_ENUMERATED) {
877 expr_unordered = 1;
878 }
879
Lev Walkinf7484512004-10-13 09:13:56 +0000880 if(TQ_FIRST(&expr->members)) {
881 int extensible = 0;
Lev Walkinfbaeb852006-11-21 10:39:52 +0000882 if(expr->expr_type == ASN_BASIC_BIT_STRING)
883 dont_involve_children = 1;
Lev Walkinf2b2f372016-03-14 02:23:48 -0700884 safe_printf(" (");
Lev Walkinf7484512004-10-13 09:13:56 +0000885 TQ_FOR(se, &(expr->members), next) {
886 if(se->expr_type == A1TC_EXTENSIBLE) {
887 extensible = 1;
888 continue;
889 } else if(!se->Identifier
890 && se->expr_type == A1TC_REFERENCE) {
891 asn1print_ref(se->reference, flags);
892 } else if(se->Identifier) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700893 safe_printf("%s", se->Identifier);
Lev Walkinf7484512004-10-13 09:13:56 +0000894 } else {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700895 safe_printf("ANY");
Lev Walkinf7484512004-10-13 09:13:56 +0000896 }
897 if(expr->expr_type != ASN_CONSTR_SET
898 && expr->expr_type != ASN_CONSTR_CHOICE
899 && expr->expr_type != ASN_BASIC_INTEGER
900 && expr->expr_type != ASN_BASIC_ENUMERATED) {
901 if(expr_unordered)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700902 safe_printf("*");
Lev Walkinf7484512004-10-13 09:13:56 +0000903 else if(se->marker.flags)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700904 safe_printf("?");
Lev Walkinfbaeb852006-11-21 10:39:52 +0000905 else if(expr->expr_type == ASN_BASIC_BIT_STRING)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700906 safe_printf("?");
Lev Walkinf7484512004-10-13 09:13:56 +0000907 }
908 if(TQ_NEXT(se, next)
909 && TQ_NEXT(se, next)->expr_type != A1TC_EXTENSIBLE) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700910 safe_printf(expr_unordered?"|":", ");
Lev Walkinf7484512004-10-13 09:13:56 +0000911 }
912 }
913 if(extensible) {
Lev Walkinf2b2f372016-03-14 02:23:48 -0700914 safe_printf(expr_unordered?"|":", ");
915 safe_printf("ANY");
Lev Walkinf7484512004-10-13 09:13:56 +0000916 if(expr->expr_type != ASN_CONSTR_SET
917 && expr->expr_type != ASN_CONSTR_CHOICE
918 && expr->expr_type != ASN_BASIC_INTEGER
919 && expr->expr_type != ASN_BASIC_ENUMERATED)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700920 safe_printf("*");
Lev Walkinf7484512004-10-13 09:13:56 +0000921 }
922
Lev Walkinf2b2f372016-03-14 02:23:48 -0700923 safe_printf(")");
Lev Walkinf7484512004-10-13 09:13:56 +0000924 if(expr->expr_type == ASN_CONSTR_SET)
Lev Walkinf2b2f372016-03-14 02:23:48 -0700925 safe_printf("*");
Lev Walkinf7484512004-10-13 09:13:56 +0000926
Lev Walkinef39f7e2004-10-14 05:11:25 +0000927 } else switch(expr->expr_type) {
928 case ASN_BASIC_BOOLEAN:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700929 safe_printf(" (true|false)");
Lev Walkinef39f7e2004-10-14 05:11:25 +0000930 break;
931 case ASN_CONSTR_CHOICE:
932 case ASN_CONSTR_SET:
933 case ASN_CONSTR_SET_OF:
934 case ASN_CONSTR_SEQUENCE:
935 case ASN_CONSTR_SEQUENCE_OF:
936 case ASN_BASIC_NULL:
937 case A1TC_UNIVERVAL:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700938 safe_printf(" EMPTY");
Lev Walkinef39f7e2004-10-14 05:11:25 +0000939 break;
940 case ASN_TYPE_ANY:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700941 safe_printf(" ANY");
Lev Walkinef39f7e2004-10-14 05:11:25 +0000942 break;
943 case ASN_BASIC_BIT_STRING:
944 case ASN_BASIC_OCTET_STRING:
945 case ASN_BASIC_OBJECT_IDENTIFIER:
946 case ASN_BASIC_RELATIVE_OID:
Lev Walkincc116532004-10-15 06:01:54 +0000947 case ASN_BASIC_INTEGER:
Lev Walkinef39f7e2004-10-14 05:11:25 +0000948 case ASN_BASIC_UTCTime:
949 case ASN_BASIC_GeneralizedTime:
Lev Walkinef39f7e2004-10-14 05:11:25 +0000950 case ASN_STRING_NumericString:
951 case ASN_STRING_PrintableString:
Lev Walkinf2b2f372016-03-14 02:23:48 -0700952 safe_printf(" (#PCDATA)");
Lev Walkinef39f7e2004-10-14 05:11:25 +0000953 break;
954 case ASN_STRING_VisibleString:
955 case ASN_STRING_ISO646String:
956 /* Entity references, but not XML elements may be present */
Lev Walkinf2b2f372016-03-14 02:23:48 -0700957 safe_printf(" (#PCDATA)");
Lev Walkinef39f7e2004-10-14 05:11:25 +0000958 break;
959 case ASN_BASIC_REAL: /* e.g. <MINUS-INFINITY/> */
960 case ASN_BASIC_ENUMERATED: /* e.g. <enumIdentifier1/> */
961 default:
962 /*
963 * XML elements are allowed.
964 * For example, a UTF8String may contain "<bel/>".
965 */
Lev Walkinf2b2f372016-03-14 02:23:48 -0700966 safe_printf(" ANY");
Lev Walkinf7484512004-10-13 09:13:56 +0000967 }
Lev Walkinf2b2f372016-03-14 02:23:48 -0700968 safe_printf(">\n");
Lev Walkinf7484512004-10-13 09:13:56 +0000969
970 /*
971 * Display the descendants (children) of the current type.
972 */
Lev Walkinef39f7e2004-10-14 05:11:25 +0000973 if(!dont_involve_children) {
974 TQ_FOR(se, &(expr->members), next) {
975 if(se->expr_type == A1TC_EXTENSIBLE) continue;
976 asn1print_expr_dtd(asn, mod, se, flags, level + 1);
977 }
Lev Walkinf7484512004-10-13 09:13:56 +0000978 }
979
980 return 0;
981}