Newer
Older
#include <dcw.h>
#include "struct.h"
#include "decs.h"
#ifdef HASPROTOS
static void data_decls( 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( declnlist, char * , shapelist );
static void cons_fns( FILE * , declnlist );
static void print_fns( FILE * , declnlist );
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 );
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();
BOOL print, verbose, opt; /* 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 );
}
static void init( h, c, basename ) FILE *c, *h; char *basename;
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 );
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;
declnlist d;
shapelist s;
paramlist p;
int n;
for( d=decs; d; d=d->next )
if( d->Struct )
{
line( "typedef struct %s_str *%s;", d->name, d->name );
} else
{
line( "typedef int %s;", d->name );
}
line( "\n" );
for( d=decs; d; d=d->next )
line( "/* ---- Type %s ---- */\n", d->name );
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( "" );
line( "struct %s_str {", d->name );
indent();
if( d->TagField )
line( "int\ttag;" );
}
if( d->Union )
{
line( "union {" );
}
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
static void one_proto( f, name, s, prot ) FILE *f; char *name; shapelist s; BOOL prot;
fprintf( f, "extern %s %s_%s( ", name, name, s->name );
if( prot )
for( p = s->params; p ; p=p->next, first=FALSE )
{
if( !first ) fputs( ", ", f );
fputs( p->type, f );
fputc( ' ', f );
static void protos( f, d, prot ) FILE *f; declnlist d; BOOL prot;
shapes = d->shapes;
if( d->UseNull )
{
shapes = shapes->next;
}
for( s = shapes; s; s = s->next )
one_proto( f, d->name, s, prot );
}
if( print )
{
static void cons_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
fprintf( f, "%s %s_%s( ", name, name, s->name );
for( p=s->params; p; p=p->next, first=FALSE )
{
if( !first ) fputs( ", ", f );
fputs( p->name, f );
for( p=s->params; p; p=p->next )
{
fprintf( f, "%s %s; ", p->type, p->name );
static void cons_fn_body( d, name, s ) declnlist d; char *name; shapelist s;
ASSERT( d->Struct,
("error: cons_func_body called but d->Struct is FALSE!\n") );
line( "new = NEW( struct %s_str );", name );
if( d->TagField )
{
line( "new->tag = %s_%s_tag;", name, s->name );
}
if( d->Union )
{
line( "new->u.%s.%s = %s;",
s->name, p->name, p->name );
} else
{
line( "new->%s = %s;", p->name, p->name );
}
line( "return new;" );
outdent();
line( "}" );
static void cons_fns( f, d ) FILE *f; declnlist d;
/* 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" );
}
static void print_param( shape, p, Union ) char *shape; paramlist p; BOOL Union;
if( Union )
{
sprintf( pname, "p->u.%s.%s", shape, p->name );
} else
{
sprintf( pname, "p->%s", p->name );
}
if( streq( p->type, "int" ) )
line( "fprintf( f, \"%%d\", %s );", pname );
line( "fputc( %s, f );", pname );
line( "fputs( %s?\"true\":\"false\", f );", pname );
line( "fputs( %s, f );", pname );
static void print_all_params( d, s ) declnlist d; shapelist s;
printlist pl;
paramlist p;
int n;
line( "fputs( \"%s\", f );", s->name );
if( s->params )
{
line( "fputc( '(', f );" );
}
}
if( s->params )
{
line( "fputc( ')', f );" );
}
} else
{
for( pl = s->pl; pl; pl = pl->next )
{
if( pl->item->tag == printitem_is_str )
{
line( "fputs( \"%s\", f );",
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,d->name));
}
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 );
}
static void print_fns( f, d ) FILE *f ; declnlist d;
{
shapelist s;
line( "void print_%s( f, p ) FILE *f; %s p;",d->name, d->name );
line( "{" );
indent();
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
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( "}" );
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;
ASSERT( t!=1 || e!=1,
( "datadec: type %s is empty!\n",d->name) );
/* 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 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;
}
d->Defines = d->TagField = d->Struct =
#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) );
}
void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
{
printf( "datadec: Making data declarations\n" );
usefile( h );
data_decls( d );
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" );
if( print ) print_fns( c, d );