Skip to content
Snippets Groups Projects
decs.c 9.32 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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 );
    
    static void cons_fn_body( char * , shapelist );
    
    dcw's avatar
    dcw committed
    static void cons_fns( FILE * , declnlist );
    static void print_fns( FILE * , declnlist );
    
    static void print_fn_shape( char * , shapelist );
    static void print_param( char * , char * , char * );
    
    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
    #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();
    
    static void count_empty_non();
    static void optimize();
    static void line();
    
    dcw's avatar
    dcw committed
    #endif
    
    
    
    BOOL print, verbose;		/* print == generate print functions */
    				/* verbose == be verbose - diagnostics */
    
    
    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
    }
    
    
    
    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
    	{
    
    		line( "typedef struct %s_str *%s;", d->name, 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
    		for( s = d->shapes; s; s=s->next )
    		{
    
    			line( "#define %s_%s_tag %d",
    				d->name, s->name, n++ );
    
    dcw's avatar
    dcw committed
    		}
    
    		line( "struct %s_str {", d->name );
    
    		indent();
    		line( "int\ttag;" );
    		line( "union {" );
    		indent();
    
    dcw's avatar
    dcw committed
    		for( s = d->shapes; s; s=s->next )
    		{
    
    dcw's avatar
    dcw committed
    			if( s->params )
    
    dcw's avatar
    dcw committed
    			{
    
    				line( "struct {" );
    				indent();
    
    dcw's avatar
    dcw committed
    				for( p = s->params; p; p=p->next )
    				{
    
    					line( "%s\t%s;",
    
    dcw's avatar
    dcw committed
    						p->type, p->name );
    				}
    
    				line( "} %s;", s->name );
    
    dcw's avatar
    dcw committed
    			}
    		}
    
    		outdent();
    		line( "} u;" );
    		outdent();
    		line( "};\n" );
    
    dcw's avatar
    dcw committed
    	}
    }
    
    
    
    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
    
    
    	for( ; d; d = d->next )
    
    dcw's avatar
    dcw committed
    	{
    
    		for( s = d->shapes; s; s = s->next )
    
    dcw's avatar
    dcw committed
    		{
    
    			one_proto( f, d->name, s, prot );
    		}
    		if( print )
    		{
    			if( prot )
    			{
    				fprintf( f, "extern void print_%s( %s );\n",
    					d->name, d->name );
    			} else
    			{
    				fprintf( f, "extern void print_%s( );\n",
    					d->name );
    			}
    
    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 );
    }
    
    
    
    static void cons_fn_body( name, s ) char *name; shapelist s;
    
    dcw's avatar
    dcw committed
    {
    	paramlist p;
    
    
    	line( "{" );
    	indent();
    	line( "%s new;\n", name );
    	line( "new = NEW( struct %s_str );", name );
    
    	line( "new->tag = %s_%s_tag;", name, s->name );
    
    dcw's avatar
    dcw committed
    	for( p=s->params; p; p=p->next )
    	{
    
    		line( "new->u.%s.%s = %s;", s->name, 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
    {
    	shapelist s;
    
    
    dcw's avatar
    dcw committed
    	for( ; d; d=d->next )
    	{
    		for( s = d->shapes; s; s=s->next )
    		{
    
    			cons_fn_hdr( f, d->name, s );
    			cons_fn_body( d->name, s );
    
    dcw's avatar
    dcw committed
    			fprintf( f, "\n\n" );
    		}
    	}
    }
    
    
    
    static void print_param( shape, ftype, fname ) char *shape, *ftype, *fname;
    
    dcw's avatar
    dcw committed
    {
    	char pname[200];
    
    
    dcw's avatar
    dcw committed
    	sprintf( pname, "p->u.%s.%s", shape, fname );
    
    dcw's avatar
    dcw committed
    	if( streq( ftype, "int" ) )
    	{
    
    		line( "fprintf( f, \"%%d\", %s );", pname );
    
    dcw's avatar
    dcw committed
    	} else if( streq( ftype, "char" ) )
    	{
    
    		line( "fputc( %s, f );", pname );
    
    dcw's avatar
    dcw committed
    	} else if( streq( ftype, "BOOL" ) )
    	{
    
    		line( "fputs( %s?\"true\":\"false\", f );", pname );
    
    dcw's avatar
    dcw committed
    	} else if( streq( ftype, "string" ) )
    	{
    
    		line( "fputs( %s, f );", pname );
    
    dcw's avatar
    dcw committed
    	} else
    	{
    
    		line( "print_%s( f, %s );", ftype, pname );
    
    static void print_fn_shape( typename, s ) char *typename; shapelist s;
    
    dcw's avatar
    dcw committed
    {
    
    	printlist	pl;
    	paramlist	p;
    	int		n;
    
    	line( "case %s_%s_tag:", typename, s->name );
    
    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 )
    		{
    
    			print_param( s->name, p->type, p->name );
    		}
    		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,
    
    ("datadec: bad printitem in shape %s of type %s\n",s->name,typename));
    
    dcw's avatar
    dcw committed
    				}
    
    				print_param( s->name, p->type, p->name );
    
    	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
    	for( ; d; d = d->next )
    	{
    
    		line( "void print_%s( f, p ) FILE *f; %s p;",d->name, d->name );
    		line( "{" );
    		indent();
    		line( "switch( p->tag )" );
    		line( "{" );
    
    dcw's avatar
    dcw committed
    		for( s = d->shapes; s; s = s->next )
    		{
    
    			print_fn_shape( d->name, s );
    
    dcw's avatar
    dcw committed
    		}
    
    		line( "default:" );
    		indent();
    		line( "fprintf( stderr," );
    		line( " \"print_%s: impossible tag %%d\\n\", p->tag );",
    			d->name );
    		line( "exit(1);" );
    		outdent();
    		line( "}" );
    		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 )
    	{
    		count_empty_non( d->shapes, &e, &ne );
    		t = e+ne;
    
    		d->Defines = d->TagField = d->Struct =
    		d->Union = d->UseNull = FALSE;
    
    /* 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 )
    /* ONE, NON EMPTY, eg. 'data x = fred(string z)' */
    		{
    			d->Struct = TRUE;
    			/* !Defines, !TagField, !Union, !UseNull */
    		} else if( t>1 && ne==0 )
    /* >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 is empty */
    		{
    			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 )
    			{
    /* >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;
    			}
    		} else
    /* ELSE */
    		{
    			d->Defines = d->TagField = d->Struct =
    			d->Union = TRUE;
    		}
    
    
    		if( verbose )
    		{
    #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) );
    #undef XXX
    		}
    
    
    dcw's avatar
    dcw committed
    		ASSERT( implies(d->Union,d->TagField),
    
    		("optimizer error: type %s has Union&!TagField\n",d->name) );
    
    dcw's avatar
    dcw committed
    		ASSERT( implies(d->Union,d->Struct),
    
    		("optimizer error: type %s has Union&!Struct\n",d->name) );
    
    dcw's avatar
    dcw committed
    		ASSERT( implies(d->TagField,d->Struct),
    
    		("optimizer error: type %s has TagField&!Struct\n",d->name) );
    
    dcw's avatar
    dcw committed
    		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;
    {
    
    	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
    
    
    	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
    }