Skip to content
Snippets Groups Projects
decs.c 11.6 KiB
Newer Older
dcw's avatar
dcw committed
#include <dcw.h>
#include "struct.h"
#include "decs.h"


#ifdef HASPROTOS
dcw's avatar
dcw committed
static void init( FILE * , FILE * , char * );
static void data_decls( declnlist );
dcw's avatar
dcw committed
static void one_proto( FILE * , char * , shapelist , BOOL );
static void protos( FILE * , declnlist , BOOL );
static void cons_fn_hdr( FILE * , char * , shapelist );
dcw's avatar
dcw committed
static void cons_fn_body( declnlist, char * , shapelist );
dcw's avatar
dcw committed
static void cons_fns( FILE * , declnlist );
static void print_fns( FILE * , declnlist );
dcw's avatar
dcw committed
static void print_fn_shape( declnlist , shapelist );
static void print_param( char * , paramlist , BOOL );
static void print_all_params( declnlist , shapelist );
static void count_empty_non( shapelist , int *, int * );
static void optimize( declnlist );
static void line( char *, long, long, long, long );
dcw's avatar
dcw committed
static void declfields( paramlist );
dcw's avatar
dcw committed
#else
dcw's avatar
dcw committed
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();
dcw's avatar
dcw committed
static void print_all_params();
static void count_empty_non();
static void optimize();
static void line();
dcw's avatar
dcw committed
static void declfields();
dcw's avatar
dcw committed
#endif


dcw's avatar
dcw committed
BOOL print, verbose, opt;	/* print   == generate print functions */
				/* verbose == be verbose - diagnostics */
dcw's avatar
dcw committed
				/* opt     == perform optimizations    */
static int numtabs = 0;
static FILE *outfile;


#define indent() numtabs++
#define outdent() numtabs--

#define usefile(f) outfile = f, numtabs = 0


/*VARARGS*/
static void line( fmt, a, b, c, d ) char *fmt; long a, b, c, d;
{
	int i;

	for( i=numtabs; i; i-- ) fputc( '\t', outfile );
	fprintf( outfile, fmt, a, b, c, d );
	fputc( '\n', outfile );
}


dcw's avatar
dcw committed
static void init( h, c, basename ) FILE *c, *h; char *basename;
dcw's avatar
dcw committed
{
	fputs( "/*\n", h );
	fputs( " * Automatically Generated by DataDec\n", h );
	fputs( " */\n\n", h );
	fputs( "typedef char *string;\n\n", h );
	fputs( "typedef char BOOL;\n", h );
	fputs( "#define TRUE 1\n", h );
	fputs( "#define FALSE 0\n\n", h );
	fputs( "#define NEW(t) ((t *)malloc(sizeof(t)))\n\n\n", h );

	fputs( "/*\n", c );
	fputs( " * Automatically Generated by DataDec\n", c );
	fputs( " */\n\n", c);
	fputs( "#include <stdio.h>\n", c );
dcw's avatar
dcw committed
	fprintf( c, "#include \"%s.h\"\n\n\n", basename );
dcw's avatar
dcw committed
}


dcw's avatar
dcw committed
static void declfields( p ) paramlist p;
{
	for( ; p; p=p->next )
	{
		line( "%s\t%s;", p->type, p->name );
	}
}


static void data_decls( decs ) declnlist decs;
dcw's avatar
dcw committed
{
	declnlist	d;
	shapelist	s;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed

	for( d=decs; d; d=d->next )
dcw's avatar
dcw committed
	{
dcw's avatar
dcw committed
		if( d->Struct )
		{
			line( "typedef struct %s_str *%s;", d->name, d->name );
		} else
		{
			line( "typedef int %s;", d->name );
		}
dcw's avatar
dcw committed
	}
	line( "\n" );
	for( d=decs; d; d=d->next )
dcw's avatar
dcw committed
	{
		line( "/* ---- Type %s ---- */\n", d->name );
dcw's avatar
dcw committed
		n = 0;
dcw's avatar
dcw committed
		if( d->Defines )
dcw's avatar
dcw committed
		{
dcw's avatar
dcw committed
			for( s = d->shapes; s; s=s->next )
			{
				if( d->Struct )
				{
					line( "#define %s_%s_tag %d",
						d->name, s->name, n++ );
				} else
				{
					line( "#define %s_%s() %d",
						d->name, s->name, n++ );
				}
			}
			line( "" );
dcw's avatar
dcw committed
		}
dcw's avatar
dcw committed
		if( d->Struct )
dcw's avatar
dcw committed
		{
dcw's avatar
dcw committed
			line( "struct %s_str {", d->name );
			indent();
			if( d->TagField )
dcw's avatar
dcw committed
			{
dcw's avatar
dcw committed
				line( "int\ttag;" );
			}
			if( d->Union )
			{
				line( "union {" );
dcw's avatar
dcw committed
			}
			for( s = d->shapes; s; s=s->next )
			{
				if( d->Union && s->params )
				/* need internal structures */
				{
					line( "struct {" );
					indent();
					declfields( s->params );
					outdent();
					line( "} %s;", s->name );
				} else
dcw's avatar
dcw committed
					declfields( s->params );
dcw's avatar
dcw committed
			}
			if( d->Union )
			{
dcw's avatar
dcw committed
				line( "} u;" );
dcw's avatar
dcw committed
			}
dcw's avatar
dcw committed
			outdent();
			line( "};\n" );
static void one_proto( f, name, s, prot ) FILE *f; char *name; shapelist s; BOOL prot;
dcw's avatar
dcw committed
{
	paramlist p;
	BOOL first;

	fprintf( f, "extern %s %s_%s( ", name, name, s->name );
	if( prot )
dcw's avatar
dcw committed
	{
		if( s->params == NULL )
		{
			fputs( "void ", f );
dcw's avatar
dcw committed
		} else
		{
dcw's avatar
dcw committed
			first = TRUE;
dcw's avatar
dcw committed
			for( p = s->params; p ; p=p->next, first=FALSE )
			{
				if( !first ) fputs( ", ", f );
				fputs( p->type, f );
				fputc( ' ', f );
dcw's avatar
dcw committed
			}
		}
	}
	fputs( ");\n", f );
dcw's avatar
dcw committed
}


static void protos( f, d, prot ) FILE *f; declnlist d; BOOL prot;
dcw's avatar
dcw committed
{
dcw's avatar
dcw committed
	shapelist	shapes;
dcw's avatar
dcw committed

	for( ; d; d = d->next )
dcw's avatar
dcw committed
	{
dcw's avatar
dcw committed
		shapes = d->shapes;
		if( d->UseNull )
		{
			shapes = shapes->next;
		}
		for( s = shapes; s; s = s->next )
dcw's avatar
dcw committed
		{
			one_proto( f, d->name, s, prot );
		}
		if( print )
		{
dcw's avatar
dcw committed
			fprintf( f, "extern void print_%s(", d->name );
dcw's avatar
dcw committed
				fprintf( f, " %s ", d->name );
dcw's avatar
dcw committed
			fputs( ");\n", f );
dcw's avatar
dcw committed
		}
dcw's avatar
dcw committed
	}
dcw's avatar
dcw committed
}


dcw's avatar
dcw committed
static void cons_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
dcw's avatar
dcw committed
{
	paramlist p;
	BOOL first;

	fprintf( f, "%s %s_%s( ", name, name, s->name );
dcw's avatar
dcw committed
	first = TRUE;
dcw's avatar
dcw committed
	for( p=s->params; p; p=p->next, first=FALSE )
	{
		if( !first ) fputs( ", ", f );
		fputs( p->name, f );
dcw's avatar
dcw committed
	}
	fputs( " ) ", f );
dcw's avatar
dcw committed
	for( p=s->params; p; p=p->next )
	{
		fprintf( f, "%s %s; ", p->type, p->name );
dcw's avatar
dcw committed
	}
	fputc( '\n', f );
}


dcw's avatar
dcw committed
static void cons_fn_body( d, name, s ) declnlist d; char *name; shapelist s;
dcw's avatar
dcw committed
{
	paramlist p;

dcw's avatar
dcw committed
	ASSERT( d->Struct,
		("error: cons_func_body called but d->Struct is FALSE!\n") );
	line( "{" );
	indent();
dcw's avatar
dcw committed
	line( "%s\tnew;\n", name );
	line( "new = NEW( struct %s_str );", name );
dcw's avatar
dcw committed
	if( d->TagField )
	{
		line( "new->tag = %s_%s_tag;", name, s->name );
	}
dcw's avatar
dcw committed
	for( p=s->params; p; p=p->next )
	{
dcw's avatar
dcw committed
		if( d->Union )
		{
			line( "new->u.%s.%s = %s;",
				s->name, p->name, p->name );
		} else
		{
			line( "new->%s = %s;", p->name, p->name );
		}
dcw's avatar
dcw committed
	}
	line( "return new;" );
	outdent();
	line( "}" );
dcw's avatar
dcw committed
}


dcw's avatar
dcw committed
static void cons_fns( f, d ) FILE *f; declnlist d;
dcw's avatar
dcw committed
{
dcw's avatar
dcw committed
	shapelist	s;
	shapelist	shapes;
dcw's avatar
dcw committed

dcw's avatar
dcw committed
	for( ; d; d=d->next )
	{
dcw's avatar
dcw committed
		if( d->Struct )
dcw's avatar
dcw committed
		{
dcw's avatar
dcw committed
			/* We need constructor functions */
			shapes = d->shapes;
			if( d->UseNull )
			{
				/* Null cons func already made */
				shapes = shapes->next;
			}
			for( s = shapes; s; s=s->next )
			{
				cons_fn_hdr( f, d->name, s );
				cons_fn_body( d, d->name, s );
				fprintf( f, "\n\n" );
			}
dcw's avatar
dcw committed
static void print_param( shape, p, Union ) char *shape; paramlist p; BOOL Union;
dcw's avatar
dcw committed
{
	char pname[200];

dcw's avatar
dcw committed
	if( Union )
	{
		sprintf( pname, "p->u.%s.%s", shape, p->name );
	} else
	{
		sprintf( pname, "p->%s", p->name );
	}

	if( streq( p->type, "int" ) )
dcw's avatar
dcw committed
	{
		line( "fprintf( f, \"%%d\", %s );", pname );
dcw's avatar
dcw committed
	} else if( streq( p->type, "char" ) )
dcw's avatar
dcw committed
	{
		line( "fputc( %s, f );", pname );
dcw's avatar
dcw committed
	} else if( streq( p->type, "BOOL" ) )
dcw's avatar
dcw committed
	{
		line( "fputs( %s?\"true\":\"false\", f );", pname );
dcw's avatar
dcw committed
	} else if( streq( p->type, "string" ) )
dcw's avatar
dcw committed
	{
		line( "fputs( %s, f );", pname );
dcw's avatar
dcw committed
	} else
	{
dcw's avatar
dcw committed
		line( "print_%s( f, %s );", p->type, pname );
dcw's avatar
dcw committed
static void print_all_params( d, s ) declnlist d; shapelist s;
dcw's avatar
dcw committed
{
	printlist	pl;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed

	if( s->pl == NULL )
	{
		line( "fputs( \"%s\", f );", s->name );
		if( s->params )
		{
			line( "fputc( '(', f );" );
		}
dcw's avatar
dcw committed
		for( p = s->params; p; p = p->next )
		{
dcw's avatar
dcw committed
			print_param( s->name, p, d->Union );
		}
		if( s->params )
		{
			line( "fputc( ')', f );" );
dcw's avatar
dcw committed
		}
	} else
	{
		for( pl = s->pl; pl; pl = pl->next )
		{
			if( pl->item->tag == printitem_is_str )
			{
				line( "fputs( \"%s\", f );",
dcw's avatar
dcw committed
					pl->item->str );
			} else
			{
				n = pl->item->num;
				for( p = s->params; --n; p = p->next )
				{
					ASSERT( p != NULL,
dcw's avatar
dcw committed
("datadec: bad printitem in shape %s of type %s\n",s->name,d->name));
dcw's avatar
dcw committed
				}
dcw's avatar
dcw committed
				print_param( s->name, p, d->Union );
dcw's avatar
dcw committed
}


static void print_fn_shape( d, s ) declnlist d; shapelist s;
{
	line( "case %s_%s_tag:", d->name, s->name );
	indent();
	print_all_params( d, s );
	line( "break;" );
	outdent();
dcw's avatar
dcw committed
}


static void print_fns( f, d ) FILE *f ; declnlist d;
{
	shapelist s;
dcw's avatar
dcw committed
	shapelist shapes;
dcw's avatar
dcw committed
	for( ; d; d = d->next )
	{
dcw's avatar
dcw committed
		shapes = d->shapes;
		line( "void print_%s( f, p ) FILE *f; %s p;",d->name, d->name );
		line( "{" );
		indent();
dcw's avatar
dcw committed
		if( d->UseNull )
dcw's avatar
dcw committed
		{
dcw's avatar
dcw committed
			line( "if( p == NULL )" );
			line( "{" );
			indent();
			print_all_params( d, shapes );
			line( "return;" );
			outdent();
			line( "}" );
			shapes = shapes->next;
		}
		if( d->TagField )
		{
			line( "switch( p->tag )" );
			line( "{" );
			for( s = shapes; s; s = s->next )
			{
				print_fn_shape( d, s );
			}
			line( "default:" );
			indent();
			line( "fprintf( stderr," );
			line( " \"print_%s: impossible tag %%d\\n\", p->tag );",
				d->name );
			line( "exit(1);" );
			outdent();
			line( "}" );
		} else if( d->Struct )	/* only one shape left */
		{
			print_all_params( d, shapes );
		} else			/* enumerated type */
		{
			line( "switch( p )" );
			line( "{" );
			for( s = shapes; s; s = s->next )
			{
				line( "case %s_%s:", d->name, s->name );
				indent();
				print_all_params( d, s );
				line( "break;" );
				outdent();
			}
			line( "}" );
dcw's avatar
dcw committed
		}
		outdent();
		line( "}\n" );
dcw's avatar
dcw committed

static void count_empty_non( s, e, ne ) shapelist s; int *e, *ne;
{
	*e = *ne = 0;
	for( ; s!=NULL; s = s->next )
	{
		if( s->params == NULL ) (*e)++; else (*ne)++;
	}
}


#define implies( a, b ) (!(a) || (b))


static void optimize( d ) declnlist d;
{
	int t, e, ne;

	for( ; d != NULL; d = d->next )
	{
		if( ! opt )
		{
			d->Defines = d->TagField = d->Struct = d->Union = TRUE;
			d->UseNull = FALSE;
		} else
		{
			count_empty_non( d->shapes, &e, &ne );
			t = e+ne;
			d->Defines = d->TagField = d->Struct =
			d->Union = d->UseNull = FALSE;
dcw's avatar
dcw committed

/* ONE, EMPTY, eg. 'data x = y' => ERROR */
			ASSERT( t!=1 || e!=1,
				( "datadec: type %s is empty!\n",d->name) );
			if( t==1 && ne==1 )
dcw's avatar
dcw committed
/* ONE, NON EMPTY, eg. 'data x = fred(string z)' */
			{
				d->Struct = TRUE;
				/* !Defines, !TagField, !Union, !UseNull */
			} else if( t>1 && ne==0 )
dcw's avatar
dcw committed
/* >1, ALL EMPTY, eg. 'data x = a | b | c | d | e' */
			{
				d->Defines = TRUE;
				/* !TagField, !Struct, !Union, !UseNull */
			} else if( d->shapes->params == NULL ) /* 1st empty */
dcw's avatar
dcw committed
			{
				d->UseNull = d->Struct = TRUE;
				if( t==2 && ne==1 )
				{
/* TWO, 1ST EMPTY, 2ND NE, eg. 'data x = a | b(char z)' */
					d->UseNull = d->Struct = TRUE;
					/* !Union, !TagField, !Defines */
				} else if( t>2 && ne==1 )
				{
dcw's avatar
dcw committed
/* >TWO, 1ST EMPTY, ONLY ONE NE, eg. 'data x = a | b | c(char z) | d | e' */
					d->UseNull = d->Struct =
					d->Defines = d->TagField = TRUE;
					/* !Union */
				} else
				{
/* >TWO, 1ST EMPTY, >ONE NE, eg. 'data x = a | b(int y) | c(char z) | d | e' */
					d->UseNull = d->Struct =
					d->Defines = d->TagField =
					d->Union = TRUE;
				}
dcw's avatar
dcw committed
			} else
dcw's avatar
dcw committed
			{
				d->Defines = d->TagField = d->Struct =
dcw's avatar
dcw committed
				d->Union = TRUE;
			}
#define XXX(x)	( (x)?' ':'!')
				printf( "type %s: %cDefines, %cTagField, ",
					d->name, XXX(d->Defines),
					XXX(d->TagField) );
				printf( "%cStruct, %cUnion, %cUseNull\n",
					XXX(d->Struct), XXX(d->Union),
					XXX(d->UseNull) );
			ASSERT( implies(d->Union,d->TagField),
			("optimizer error: type %s has Union&!TagField\n",d->name) );
			ASSERT( implies(d->Union,d->Struct),
			("optimizer error: type %s has Union&!Struct\n",d->name) );
			ASSERT( implies(d->TagField,d->Struct),
			("optimizer error: type %s has TagField&!Struct\n",d->name) );
			ASSERT( implies(d->UseNull,d->Struct),
			("optimizer error: type %s has UseNull&!Struct\n",d->name) );
			ASSERT( implies(d->TagField,d->Defines),
			("optimizer error: type %s has TagField&!Defines\n",d->name) );
		}
dcw's avatar
dcw committed
void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
{
dcw's avatar
dcw committed
	declnlist dl;

	printf( "datadec: Making data declarations\n" );
dcw's avatar
dcw committed

dcw's avatar
dcw committed
	init( h, c, basename );
dcw's avatar
dcw committed

dcw's avatar
dcw committed
	optimize( d );

	usefile( h );

	data_decls( d );
dcw's avatar
dcw committed

dcw's avatar
dcw committed
	for( dl = d; dl; dl=dl->next )
	{
		if( dl->UseNull )
		{
			line( "#define %s_%s() ((%s)NULL)",
				dl->name, dl->shapes->name, dl->name );
		}
	}
	line( "#ifdef HASPROTOS" );
dcw's avatar
dcw committed
	protos( h, d, TRUE );
dcw's avatar
dcw committed
	protos( h, d, FALSE );
dcw's avatar
dcw committed

dcw's avatar
dcw committed
	cons_fns( c, d );
	if( print ) print_fns( c, d );
dcw's avatar
dcw committed
}