-X for XML DTD


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@500 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/ChangeLog b/ChangeLog
index c4b1ab2..0a8030c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
 
-0.9.7.2:	2004-Oct-12
+0.9.8:	2004-Oct-13
 
+	* -X command line option added to asn1c to generate XML DTD.
 	* Empty SEQUENCE and SET clauses are now allowed.
 
 0.9.7.1:	2004-Oct-12
diff --git a/asn1c/asn1c.1 b/asn1c/asn1c.1
index b331d44..7a6f87f 100644
--- a/asn1c/asn1c.1
+++ b/asn1c/asn1c.1
@@ -3,18 +3,19 @@
 asn1c \- ASN.1 Compiler
 .SH SYNOPSIS
 asn1c [\fB\-E\fR [\fB-F\fR] | \fB\-P\fR | \fB\-R\fR]
-      [\fB\-S\fR\fIdir\fR]
+      [\fB\-S\fR\fIdir\fR] [\fB-X\fR]
       [\fB\-W\fR\fIdebug-\fR...] [\fB\-f\fR\fIoption\fR...] [\fB\-p\fR\fIrint-\fR...]
       \fIinfile\fR...
 .SH DESCRIPTION
 asn1c compiles the ASN.1 specifications into the set of
-target language (C/C++) encoders and decoders for BER, DER,
+target language (C/C++) encoders and decoders for BER, DER, XER,
 and other encoding standards.
 .SH OPTIONS
 .TP
 \fIOverall Options\fR
 \fB\-E \-F \-P \-R\fR
 .BI "\-S " directory
+\fB\-X
 .TP
 \fIWarning Options\fR
 .br
@@ -50,6 +51,9 @@
 .TP
 \fB\-S\fR \fIdirectory\fR
 Use the specified directory with ASN.1 skeleton files.
+.TP
+.B \-X
+Generate the XML DTD schema for the specified ASN.1 files.
 .SH WARNING OPTIONS
 .TP
 .B \-Werror
diff --git a/asn1c/asn1c.c b/asn1c/asn1c.c
index 98a607a..32e6e74 100644
--- a/asn1c/asn1c.c
+++ b/asn1c/asn1c.c
@@ -70,7 +70,7 @@
 	/*
 	 * Process command-line options.
 	 */
-	while((ch = getopt(ac, av, "EFf:hLPp:RS:vW:")) != -1)
+	while((ch = getopt(ac, av, "EFf:hLPp:RS:vW:X")) != -1)
 	switch(ch) {
 	case 'E':
 		print_arg__print_out = 1;
@@ -146,6 +146,11 @@
 			exit(EX_USAGE);
 		}
 		break;
+	case 'X':
+		print_arg__print_out = 1;	/* Implicit -E */
+		print_arg__fix_n_print = 1;	/* Implicit -F */
+		asn1_printer_flags |= APF_PRINT_XML_DTD;
+		break;
 	default:
 		usage(av[0]);
 	}
@@ -299,6 +304,7 @@
 "  -R                    Restrict output (tables only, no support code)\n"
 "  -S <dir>              Directory with support (skeleton?) files\n"
 "                        (Default is \"%s\")\n"
+"  -X                    Generate and print the XML DTD\n"
 "\n"
 
 "  -Werror               Treat warnings as errors; abort if any warning\n"
diff --git a/configure b/configure
index 78e1c9a..7501337 100755
--- a/configure
+++ b/configure
@@ -1881,7 +1881,7 @@
 
 # Define the identity of the package.
  PACKAGE=asn1c
- VERSION=0.9.7.2
+ VERSION=0.9.8
 
 
 cat >>confdefs.h <<_ACEOF
diff --git a/configure.in b/configure.in
index 5c6a1e7..ce67231 100644
--- a/configure.in
+++ b/configure.in
@@ -3,7 +3,7 @@
 AC_CANONICAL_BUILD
 AC_CANONICAL_TARGET
 AC_PREREQ(2.53)
-AM_INIT_AUTOMAKE(asn1c, 0.9.7.2)
+AM_INIT_AUTOMAKE(asn1c, 0.9.8)
 
 AM_MAINTAINER_MODE
 
diff --git a/doc/asn1c-usage.html b/doc/asn1c-usage.html
index fcc2980..e9096bf 100644
--- a/doc/asn1c-usage.html
+++ b/doc/asn1c-usage.html
@@ -692,6 +692,9 @@
 <TR><TD VALIGN=BASELINE ALIGN=LEFT NOWRAP>-S <I>&lt;directory&gt;</I></TD><TD VALIGN=BASELINE ALIGN=LEFT WIDTH="216">
 <FONT SIZE="-1">Use the specified directory with ASN.1 skeleton files.</FONT></TD></TR>
 </TBODY><TBODY>
+<TR><TD VALIGN=BASELINE ALIGN=LEFT NOWRAP>-X</TD><TD VALIGN=BASELINE ALIGN=LEFT WIDTH="216">
+<FONT SIZE="-1">Generate the XML DTD schema for the specified ASN.1 modules.</FONT></TD></TR>
+</TBODY><TBODY>
 <TR><TD VALIGN=BASELINE ALIGN=LEFT NOWRAP><B>Warning Options</B></TD><TD VALIGN=BASELINE ALIGN=LEFT WIDTH="216">
 <B>Description</B></TD></TR>
 </TBODY><TBODY>
diff --git a/doc/asn1c-usage.lyx b/doc/asn1c-usage.lyx
index 012503c..c6b377f 100644
--- a/doc/asn1c-usage.lyx
+++ b/doc/asn1c-usage.lyx
@@ -71,7 +71,7 @@
 \backslash 
 lhead{Document describes 
 \backslash 
-href{http://lionet.info/soft/asn1c-0.9.6.tar.gz}{asn1c-0.9.6}}
+href{http://lionet.info/asn1c}{asn1c-0.9.8}}
 \layout Standard
 
 \backslash 
@@ -1341,7 +1341,7 @@
 
 
 \begin_inset  Tabular
-<lyxtabular version="3" rows="21" columns="2">
+<lyxtabular version="3" rows="22" columns="2">
 <features islongtable="true">
 <column alignment="left" valignment="top" leftline="true" width="0">
 <column alignment="block" valignment="top" leftline="true" rightline="true" width="3in">
@@ -1452,7 +1452,7 @@
 \end_inset 
 </cell>
 </row>
-<row topline="true" bottomline="true">
+<row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
 
@@ -1474,6 +1474,24 @@
 \end_inset 
 </cell>
 </row>
+<row topline="true" bottomline="true">
+<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+-X
+\end_inset 
+</cell>
+<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
+\begin_inset Text
+
+\layout Standard
+
+Generate the XML DTD for the specified ASN.1 modules.
+\end_inset 
+</cell>
+</row>
 <row topline="true">
 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
 \begin_inset Text
diff --git a/doc/asn1c-usage.pdf b/doc/asn1c-usage.pdf
index df871b0..bab14c4 100644
--- a/doc/asn1c-usage.pdf
+++ b/doc/asn1c-usage.pdf
Binary files differ
diff --git a/libasn1print/asn1print.c b/libasn1print/asn1print.c
index 4132204..a6c3edb 100644
--- a/libasn1print/asn1print.c
+++ b/libasn1print/asn1print.c
@@ -10,7 +10,7 @@
 #include "asn1print.h"
 
 #define	INDENT(fmt, args...)	do {					\
-		int __i = level; while(__i--) putchar(' ');		\
+		int __i = level; while(__i--) printf("    ");		\
 		printf(fmt, ##args);					\
 	} while(0)
 
@@ -22,8 +22,8 @@
 static int asn1print_with_syntax(asn1p_wsyntx_t *wx, enum asn1print_flags flags);
 static int asn1print_constraint(asn1p_constraint_t *, enum asn1print_flags);
 static int asn1print_value(asn1p_value_t *val, enum asn1print_flags flags);
-static int asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags,
-		int level);
+static int asn1print_expr(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level);
+static int asn1print_expr_dtd(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *tc, enum asn1print_flags flags, int level);
 
 /*
  * Print the contents of the parsed ASN tree.
@@ -38,6 +38,9 @@
 		return -1;
 	}
 
+	if(flags & APF_PRINT_XML_DTD)
+		printf("<!-- XML DTD generated by asn1c-" VERSION " -->\n\n");
+
 	TQ_FOR(mod, &(asn->modules), mod_next) {
 		if(modno++) printf("\n");
 		asn1print_module(asn, mod, flags);
@@ -50,12 +53,28 @@
 asn1print_module(asn1p_t *asn, asn1p_module_t *mod, enum asn1print_flags flags) {
 	asn1p_expr_t *tc;
 
+	if(flags & APF_PRINT_XML_DTD)
+		printf("<!-- ASN.1 module\n");
+
 	printf("%s ", mod->Identifier);
 	if(mod->module_oid) {
 		asn1print_oid(mod->module_oid, flags);
 		printf("\n");
 	}
 
+	if(flags & APF_PRINT_XML_DTD) {
+		if(mod->source_file_name
+		&& strcmp(mod->source_file_name, "-"))
+			printf("found in %s", mod->source_file_name);
+		printf(" -->\n\n");
+
+		TQ_FOR(tc, &(mod->members), next) {
+			asn1print_expr_dtd(asn, mod, tc, flags, 0);
+		}
+
+		return 0;
+	}
+
 	printf("DEFINITIONS");
 
 	if(mod->module_flags & MSF_TAG_INSTRUCTIONS)
@@ -442,7 +461,7 @@
 	int SEQ_OF = 0;
 
 	if(flags & APF_LINE_COMMENTS)
-	INDENT("-- #line %d\n", tc->_lineno);
+		INDENT("-- #line %d\n", tc->_lineno);
 	if(tc->Identifier)
 		INDENT("%s", tc->Identifier);
 
@@ -539,7 +558,7 @@
 			/*
 			 * Print the expression as it were a stand-alone type.
 			 */
-			asn1print_expr(asn, mod, se, flags, level + 4);
+			asn1print_expr(asn, mod, se, flags, level + 1);
 			if((se->marker.flags & EM_DEFAULT) == EM_DEFAULT) {
 				printf(" DEFAULT ");
 				asn1print_value(se->marker.default_value, flags);
@@ -614,3 +633,115 @@
 	return 0;
 }
 
+
+static int
+asn1print_expr_dtd(asn1p_t *asn, asn1p_module_t *mod, asn1p_expr_t *expr, enum asn1print_flags flags, int level) {
+	asn1p_expr_t *se;
+	int expr_unordered = 0;
+
+	switch(expr->meta_type) {
+	case AMT_TYPE:
+	case AMT_TYPEREF:
+		break;
+	default:
+		if(expr->expr_type == A1TC_UNIVERVAL)
+			break;
+		return 0;
+	}
+
+	if(!expr->Identifier) return 0;
+
+	if(expr->expr_type == ASN_CONSTR_CHOICE
+	|| expr->expr_type == ASN_CONSTR_SEQUENCE_OF
+	|| expr->expr_type == ASN_CONSTR_SET_OF
+	|| expr->expr_type == ASN_CONSTR_SET
+	|| expr->expr_type == ASN_BASIC_INTEGER
+	|| expr->expr_type == ASN_BASIC_ENUMERATED) {
+		expr_unordered = 1;
+	}
+
+	if(flags & APF_LINE_COMMENTS)
+		INDENT("<!-- #line %d -->\n", expr->_lineno);
+	INDENT("<!ELEMENT %s", expr->Identifier);
+
+	if(expr->expr_type == A1TC_REFERENCE) {
+		se = asn1f_find_terminal_type_ex(asn, expr);
+		if(!se) {
+			printf("(ANY)");
+			return 0;
+		}
+		expr = se;
+	}
+
+	if(TQ_FIRST(&expr->members)) {
+		int extensible = 0;
+		printf(" (");
+		TQ_FOR(se, &(expr->members), next) {
+			if(se->expr_type == A1TC_EXTENSIBLE) {
+				extensible = 1;
+				continue;
+			} else if(!se->Identifier
+					&& se->expr_type == A1TC_REFERENCE) {
+				asn1print_ref(se->reference, flags);
+			} else if(se->Identifier) {
+				printf("%s", se->Identifier);
+			} else {
+				printf("ANY");
+			}
+			if(expr->expr_type != ASN_CONSTR_SET
+			&& expr->expr_type != ASN_CONSTR_CHOICE
+			&& expr->expr_type != ASN_BASIC_INTEGER
+			&& expr->expr_type != ASN_BASIC_ENUMERATED) {
+				if(expr_unordered)
+					printf("*");
+				else if(se->marker.flags)
+					printf("?");
+			}
+			if(TQ_NEXT(se, next)
+			&& TQ_NEXT(se, next)->expr_type != A1TC_EXTENSIBLE) {
+				printf(expr_unordered?"|":", ");
+			}
+		}
+		if(extensible) {
+			printf(expr_unordered?"|":", ");
+			printf("ANY");
+			if(expr->expr_type != ASN_CONSTR_SET
+			&& expr->expr_type != ASN_CONSTR_CHOICE
+			&& expr->expr_type != ASN_BASIC_INTEGER
+			&& expr->expr_type != ASN_BASIC_ENUMERATED)
+				printf("*");
+		}
+
+		printf(")");
+		if(expr->expr_type == ASN_CONSTR_SET)
+			printf("*");
+
+	} else if((expr->expr_type & ASN_CONSTR_MASK)
+		|| expr->expr_type == ASN_BASIC_NULL) {
+		printf(" EMPTY");
+	} else if(expr->expr_type == A1TC_UNIVERVAL) {
+		printf(" EMPTY");
+	} else if(expr->expr_type == ASN_TYPE_ANY) {
+		printf(" ANY"); 
+	} else if(expr->expr_type == ASN_BASIC_BIT_STRING
+		|| expr->expr_type == ASN_BASIC_OBJECT_IDENTIFIER
+		|| expr->expr_type == ASN_BASIC_RELATIVE_OID
+		|| expr->expr_type == ASN_BASIC_UTCTime
+		|| expr->expr_type == ASN_BASIC_GeneralizedTime
+	) {
+		printf(" (#CDATA)");
+	} else {
+		printf(" (#PCDATA)");
+	}
+	printf(">\n");
+
+	/*
+	 * Display the descendants (children) of the current type.
+	 */
+	TQ_FOR(se, &(expr->members), next) {
+		if(se->expr_type == A1TC_EXTENSIBLE) continue;
+		asn1print_expr_dtd(asn, mod, se, flags, level + 1);
+	}
+
+	return 0;
+}
diff --git a/libasn1print/asn1print.h b/libasn1print/asn1print.h
index c24e58e..51233e9 100644
--- a/libasn1print/asn1print.h
+++ b/libasn1print/asn1print.h
@@ -5,6 +5,7 @@
 	APF_NOFLAGS,
 	APF_LINE_COMMENTS	= 0x01, /* Include line comments */
 	APF_DEBUG_CONSTRAINTS	= 0x02,	/* Explain constraints */
+	APF_PRINT_XML_DTD	= 0x04,	/* Generate XML DTD */
 };
 
 /*