diff --git a/decs.c b/decs.c
index 5f0d465f980982890aa2c699c433b26bab8249e4..a142c20dbd41eb035a309c6ec137e3b16a81d930 100644
--- a/decs.c
+++ b/decs.c
@@ -4,51 +4,53 @@
 
 
 #ifdef HASPROTOS
-static void p_type( FILE * , char * , char , int );
-static void make_init( FILE * , FILE * , char * );
-static void make_data_decls( FILE * , declnlist );
-static void make_1_proto( FILE * , char * , shapelist , BOOL );
-static void make_protos( FILE * , declnlist , BOOL );
-static void make_fn_hdr( FILE * , char * , shapelist );
-static void make_fn_body( FILE * , char * , shapelist );
-static void make_fns( FILE * , declnlist );
+static void init( FILE * , FILE * , char * );
+static void data_decls( FILE * , declnlist );
+static void one_proto( FILE * , char * , shapelist , BOOL );
+static void protos( FILE * , declnlist , BOOL );
+static void cons_fn_hdr( FILE * , char * , shapelist );
+static void cons_fn_body( FILE * , char * , shapelist );
+static void cons_fns( FILE * , declnlist );
+static void print_fns( FILE * , declnlist );
+static void print_fn_shape( FILE * , char * , shapelist );
+static void print_param( FILE *, char * , char * , char * );
 #else
-static void p_type();
-static void make_init();
-static void make_data_decls();
-static void make_1_proto();
-static void make_protos();
-static void make_fn_hdr();
-static void make_fn_body();
-static void make_fns();
+static void init();
+static void data_decls();
+static void one_proto();
+static void protos();
+static void cons_fn_hdr();
+static void cons_fn_body();
+static void cons_fns();
+static void print_fns();
+static void print_fn_shape();
+static void print_param();
 #endif
 
 
-static void p_type( f, type, sep, stars ) FILE *f; char sep, *type; int stars;
-{
-	fprintf( f, "%s%c", type, sep );
-	for( ; stars; stars-- ) {
-		fputc( '*', f );
-	}
-}
-
-
-static void make_init( h, c, basename ) FILE *c, *h; char *basename;
+static void init( h, c, basename ) FILE *c, *h; char *basename;
 {
 	fprintf( h, "/*\n" );
 	fprintf( h, "\tAutomatically Generated by DataDec\n" );
 	fprintf( h, " */\n\n");
+	fprintf( h, "typedef char *string;\n\n" );
+	fprintf( h, "typedef char BOOL;\n" );
+	fprintf( h, "#define TRUE 0\n" );
+	fprintf( h, "#define FALSE 1\n\n" );
 
 	fprintf( c, "/*\n" );
 	fprintf( c, "\tAutomatically Generated by DataDec\n" );
 	fprintf( c, " */\n\n");
 
-	fprintf( c, "#include <dcw.h>\n" );
-	fprintf( c, "#include <%s.h>\n\n\n", basename );
+	fprintf( c, "#include <stdio.h>\n" );
+	fprintf( c, "#include \"%s.h\"\n\n\n", basename );
+
+	fprintf( c, "#define NEW(t) ((t *)malloc(sizeof(t)))\n\n" );
+	fprintf( c, "#define ABORT(m) {printf m; exit(1);}\n\n\n" );
 }
 
 
-static void make_data_decls( f, dl ) FILE *f; declnlist dl;
+static void data_decls( f, dl ) FILE *f; declnlist dl;
 {
 	declnlist d;
 	char *name;
@@ -57,26 +59,31 @@ static void make_data_decls( f, dl ) FILE *f; declnlist dl;
 	char *tag;
 	paramlist p;
 
-	for( d=dl; d; d=d->next ) {
+	for( d=dl; d; d=d->next )
+	{
 		name = d->name;
 		fprintf( f, "typedef struct %s_str *%s;\n", name, name );
 	}
-	for( d=dl; d; d=d->next ) {
+	fprintf( f, "\n\n" );
+	for( d=dl; d; d=d->next )
+	{
 		name = d->name;
 		fprintf( f, "/* ---- Type %s ---- */\n\n", name );
 		n = 0;
-		for( s = d->shapes; s; s=s->next ) {
+		for( s = d->shapes; s; s=s->next )
+		{
 			fprintf( f, "#define %s_%s_tag %d\n",
 				name, s->tagname, n++ );
 		}
 		fprintf( f, "\nstruct %s_str {\n", name );
 		fprintf( f, "\tint\ttag;\n" );
-		for( s = d->shapes; s; s=s->next ) {
+		for( s = d->shapes; s; s=s->next )
+		{
 			tag = s->tagname;
-			for( p = s->params; p; p=p->next ) {
-				fputc( '\t', f );
-				p_type( f, p->type, '\t', p->stars );
-				fprintf( f, "%s_%s;\n", tag, p->name );
+			for( p = s->params; p; p=p->next )
+			{
+				fprintf( f, "\t%s\t%s_%s;\n",
+					p->type, tag, p->name );
 			}
 		}
 		fprintf( f, "};\n\n" );
@@ -84,7 +91,7 @@ static void make_data_decls( f, dl ) FILE *f; declnlist dl;
 }
 
 
-static void make_1_proto( f, name, s, protos ) FILE *f; char *name; shapelist s; BOOL protos;
+static void one_proto( f, name, s, protos ) FILE *f; char *name; shapelist s; BOOL protos;
 {
 	char *tag;
 	paramlist p;
@@ -92,36 +99,49 @@ static void make_1_proto( f, name, s, protos ) FILE *f; char *name; shapelist s;
 
 	tag = s->tagname;
 	fprintf( f, "extern %s %s_%s( ", name, name, tag );
-	if( protos ) {
-		if( s->params == NULL ) {
-			fprintf( f, "void" );
-		} else {
+	if( protos )
+	{
+		if( s->params == NULL )
+		{
+			fprintf( f, "void " );
+		} else
+		{
 			first = TRUE;
-			for( p = s->params; p ; p=p->next, first=FALSE ) {
+			for( p = s->params; p ; p=p->next, first=FALSE )
+			{
 				if( !first ) fprintf( f, ", " );
-				p_type( f, p->type, ' ', p->stars );
+				fprintf( f, "%s ", p->type );
 			}
 		}
 	}
-	fprintf( f, " );\n" );
+	fprintf( f, ");\n" );
 }
 
 
-static void make_protos( f, d, protos ) FILE *f; declnlist d; BOOL protos;
+static void protos( f, d, protos ) FILE *f; declnlist d; BOOL protos;
 {
 	char *name;
+	declnlist dl;
 	shapelist s;
 
-	for( ; d; d = d->next ) {
-		name = d->name;
-		for( s = d->shapes; s; s=s->next ) {
-			make_1_proto( f, name, s );
+	for( dl=d; dl; dl = dl->next )
+	{
+		name = dl->name;
+		for( s = dl->shapes; s; s=s->next )
+		{
+			one_proto( f, name, s, protos );
 		}
 	}
+	for( dl=d; dl; dl = dl->next )
+	{
+		fprintf( f, "extern void print_%s( ", dl->name );
+		if( protos ) fprintf( f, "%s ", dl->name );
+		fprintf( f, ");\n" );
+	}
 }
 
 
-static void make_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
+static void cons_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
 {
 	char *tag;
 	paramlist p;
@@ -130,20 +150,21 @@ static void make_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
 	tag = s->tagname;
 	fprintf( f, "%s %s_%s( ", name, name, tag );
 	first = TRUE;
-	for( p=s->params; p; p=p->next, first=FALSE ) {
+	for( p=s->params; p; p=p->next, first=FALSE )
+	{
 		if( !first ) fprintf( f, ", " );
 		fprintf( f, "%s", p->name );
 	}
 	fprintf( f, " ) " );
-	for( p=s->params; p; p=p->next ) {
-		p_type( f, p->type, ' ', p->stars );
-		fprintf( f, "%s; ", p->name );
+	for( p=s->params; p; p=p->next )
+	{
+		fprintf( f, "%s %s; ", p->type, p->name );
 	}
 	fputc( '\n', f );
 }
 
 
-static void make_fn_body( f, name, s ) FILE *f; char *name; shapelist s;
+static void cons_fn_body( f, name, s ) FILE *f; char *name; shapelist s;
 {
 	char *tag;
 	paramlist p;
@@ -152,42 +173,130 @@ static void make_fn_body( f, name, s ) FILE *f; char *name; shapelist s;
 	fprintf( f, "{\n\t%s new;\n\n", name );
 	fprintf( f, "\tnew = NEW( struct %s_str );\n", name );
 	fprintf( f, "\tnew->tag = %s_%s_tag;\n", name, tag );
-	for( p=s->params; p; p=p->next ) {
+	for( p=s->params; p; p=p->next )
+	{
 		fprintf( f, "\tnew->%s_%s = %s;\n", tag, p->name, p->name );
 	}
 	fprintf( f, "\treturn new;\n}\n" );
 }
 
 
-static void make_fns( f, d ) FILE *f; declnlist d;
+static void cons_fns( f, d ) FILE *f; declnlist d;
 {
 	char *name;
 	shapelist s;
 
-	for( ; d; d=d->next ) {
+	for( ; d; d=d->next )
+	{
 		name = d->name;
-		for( s = d->shapes; s; s=s->next ) {
-			make_fn_hdr( f, name, s );
-			make_fn_body( f, name, s );
+		for( s = d->shapes; s; s=s->next )
+		{
+			cons_fn_hdr( f, name, s );
+			cons_fn_body( f, name, s );
 			fprintf( f, "\n\n" );
 		}
 	}
 }
 
 
+static void print_param( f, shape, ftype, fname ) FILE *f; char *shape, *ftype, *fname;
+{
+	char pname[200];
+
+	sprintf( pname, "p->%s_%s", shape, fname );
+	if( streq( ftype, "int" ) )
+	{
+		fprintf( f, "\t\tfprintf( f, \"%%d\", %s );\n", pname );
+	} else if( streq( ftype, "char" ) )
+	{
+		fprintf( f, "\t\tfprintf( f, \"%%c\", %s );\n", pname );
+	} else if( streq( ftype, "BOOL" ) )
+	{
+		fprintf( f, "\t\tfprintf( f, \"%%s\", %s?\"true\":\"false\" );\n",
+			pname );
+	} else if( streq( ftype, "string" ) )
+	{
+		fprintf( f, "\t\tfprintf( f, \"%%s\", %s );\n", pname );
+	} else
+	{
+		fprintf( f, "\t\tprint_%s( f, %s );\n", ftype, pname );
+	}
+}
+
+
+static void print_fn_shape( f, typename, s ) FILE *f; char *typename; shapelist s;
+{
+	printlist pl;
+	paramlist p;
+	int n;
+
+	fprintf( f, "\tcase %s_%s_tag:\n", typename, s->tagname );
+
+	if( s->pl == NULL )
+	{
+		for( p = s->params; p; p = p->next )
+		{
+			print_param( f, s->tagname, p->type, p->name );
+		}
+	} else
+	{
+		for( pl = s->pl; pl; pl = pl->next )
+		{
+			if( pl->item->tag == printitem_is_str )
+			{
+				fprintf( f, "\t\tfprintf( f, \"%s\" );\n",
+					pl->item->str );
+			} else
+			{
+				n = pl->item->num;
+				for( p = s->params; --n; p = p->next )
+				{
+					ASSERT( p != NULL,
+("datadec: bad printitem in shape %s of type %s\n",s->tagname,typename));
+				}
+				print_param( f, s->tagname, p->type, p->name );
+			}
+		}
+	}
+	fprintf( f, "\t\tbreak;\n" );
+}
+
+
+static void print_fns( f, d ) FILE *f ; declnlist d;
+{
+	shapelist s;
+
+	for( ; d; d = d->next )
+	{
+		fprintf( f, "void print_%s( f, p ) FILE *f; %s p;\n",
+			d->name, d->name );
+		fprintf( f, "{\n\tswitch( p->tag )\n\t{\n" );
+		for( s = d->shapes; s; s = s->next )
+		{
+			print_fn_shape( f, d->name, s );
+		}
+		fprintf( f, "\tdefault:\n" );
+		fprintf( f,
+		"\tABORT((\"print_%s: impossible tag %%d\\n\",p->tag));\n",
+			d->name );
+		fprintf( f, "\t}\n}\n\n" );
+	}
+}
+
 void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
 {
 	printf( "Making data declarations\n" );
 
-	make_init( h, c, basename );
+	init( h, c, basename );
 
-	make_data_decls( h, d );
+	data_decls( h, d );
 
 	fprintf( h, "#ifdef HASPROTOS\n" );
-	make_protos( h, d, TRUE );
+	protos( h, d, TRUE );
 	fprintf( h, "#else\n" );
-	make_protos( h, d, FALSE );
+	protos( h, d, FALSE );
 	fprintf( h, "#endif\n" );
 
-	make_fns( c, d );
+	cons_fns( c, d );
+	print_fns( c, d );
 }