decs.c 9.49 KB
Newer Older
dcw's avatar
dcw committed
1 2 3 4 5 6
#include <dcw.h>
#include "struct.h"
#include "decs.h"


#ifdef HASPROTOS
dcw's avatar
dcw committed
7
static void init( FILE * , FILE * , char * );
8
static void data_decls( declnlist );
dcw's avatar
dcw committed
9 10 11
static void one_proto( FILE * , char * , shapelist , BOOL );
static void protos( FILE * , declnlist , BOOL );
static void cons_fn_hdr( FILE * , char * , shapelist );
12
static void cons_fn_body( char * , shapelist );
dcw's avatar
dcw committed
13 14
static void cons_fns( FILE * , declnlist );
static void print_fns( FILE * , declnlist );
15 16
static void print_fn_shape( char * , shapelist );
static void print_param( char * , char * , char * );
17 18 19
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
20
#else
dcw's avatar
dcw committed
21 22 23 24 25 26 27 28 29 30
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();
31 32 33
static void count_empty_non();
static void optimize();
static void line();
dcw's avatar
dcw committed
34 35 36
#endif


37 38 39
BOOL print, verbose;		/* print == generate print functions */
				/* verbose == be verbose - diagnostics */

40 41 42 43 44 45 46
static int numtabs = 0;
static FILE *outfile;


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

47
#define usefile(f) outfile = f, numtabs = 0
48 49 50 51 52 53 54 55 56 57 58 59 60


/*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
61
static void init( h, c, basename ) FILE *c, *h; char *basename;
dcw's avatar
dcw committed
62
{
63 64 65 66 67 68 69 70 71 72 73 74 75
	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
76
	fprintf( c, "#include \"%s.h\"\n\n\n", basename );
dcw's avatar
dcw committed
77 78 79
}


80
static void data_decls( decs ) declnlist decs;
dcw's avatar
dcw committed
81
{
82 83 84 85
	declnlist	d;
	shapelist	s;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed
86

87
	for( d=decs; d; d=d->next )
dcw's avatar
dcw committed
88
	{
89
		line( "typedef struct %s_str *%s;", d->name, d->name );
dcw's avatar
dcw committed
90
	}
91 92
	line( "\n" );
	for( d=decs; d; d=d->next )
dcw's avatar
dcw committed
93
	{
94
		line( "/* ---- Type %s ---- */\n", d->name );
dcw's avatar
dcw committed
95
		n = 0;
dcw's avatar
dcw committed
96 97
		for( s = d->shapes; s; s=s->next )
		{
98 99
			line( "#define %s_%s_tag %d",
				d->name, s->name, n++ );
dcw's avatar
dcw committed
100
		}
101
		line( "" );
102

103
		line( "struct %s_str {", d->name );
104 105 106 107
		indent();
		line( "int\ttag;" );
		line( "union {" );
		indent();
dcw's avatar
dcw committed
108 109
		for( s = d->shapes; s; s=s->next )
		{
dcw's avatar
dcw committed
110
			if( s->params )
dcw's avatar
dcw committed
111
			{
112 113
				line( "struct {" );
				indent();
dcw's avatar
dcw committed
114 115
				for( p = s->params; p; p=p->next )
				{
116
					line( "%s\t%s;",
dcw's avatar
dcw committed
117 118
						p->type, p->name );
				}
119
				outdent();
120
				line( "} %s;", s->name );
dcw's avatar
dcw committed
121 122
			}
		}
123 124 125 126
		outdent();
		line( "} u;" );
		outdent();
		line( "};\n" );
dcw's avatar
dcw committed
127 128 129 130
	}
}


131
static void one_proto( f, name, s, prot ) FILE *f; char *name; shapelist s; BOOL prot;
dcw's avatar
dcw committed
132 133 134 135
{
	paramlist p;
	BOOL first;

136 137
	fprintf( f, "extern %s %s_%s( ", name, name, s->name );
	if( prot )
dcw's avatar
dcw committed
138 139 140
	{
		if( s->params == NULL )
		{
141
			fputs( "void ", f );
dcw's avatar
dcw committed
142 143
		} else
		{
dcw's avatar
dcw committed
144
			first = TRUE;
dcw's avatar
dcw committed
145 146
			for( p = s->params; p ; p=p->next, first=FALSE )
			{
147 148 149
				if( !first ) fputs( ", ", f );
				fputs( p->type, f );
				fputc( ' ', f );
dcw's avatar
dcw committed
150 151 152
			}
		}
	}
153
	fputs( ");\n", f );
dcw's avatar
dcw committed
154 155 156
}


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

161
	for( ; d; d = d->next )
dcw's avatar
dcw committed
162
	{
163
		for( s = d->shapes; s; s = s->next )
dcw's avatar
dcw committed
164
		{
165 166 167 168 169 170 171 172 173 174 175 176 177
			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
178
		}
dcw's avatar
dcw committed
179
	}
dcw's avatar
dcw committed
180 181 182
}


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

188
	fprintf( f, "%s %s_%s( ", name, name, s->name );
dcw's avatar
dcw committed
189
	first = TRUE;
dcw's avatar
dcw committed
190 191
	for( p=s->params; p; p=p->next, first=FALSE )
	{
192 193
		if( !first ) fputs( ", ", f );
		fputs( p->name, f );
dcw's avatar
dcw committed
194
	}
195
	fputs( " ) ", f );
dcw's avatar
dcw committed
196 197 198
	for( p=s->params; p; p=p->next )
	{
		fprintf( f, "%s %s; ", p->type, p->name );
dcw's avatar
dcw committed
199 200 201 202 203
	}
	fputc( '\n', f );
}


204
static void cons_fn_body( name, s ) char *name; shapelist s;
dcw's avatar
dcw committed
205 206 207
{
	paramlist p;

208 209 210 211
	line( "{" );
	indent();
	line( "%s new;\n", name );
	line( "new = NEW( struct %s_str );", name );
212
	line( "new->tag = %s_%s_tag;", name, s->name );
dcw's avatar
dcw committed
213 214
	for( p=s->params; p; p=p->next )
	{
215
		line( "new->u.%s.%s = %s;", s->name, p->name, p->name );
dcw's avatar
dcw committed
216
	}
217 218 219
	line( "return new;" );
	outdent();
	line( "}" );
dcw's avatar
dcw committed
220 221 222
}


dcw's avatar
dcw committed
223
static void cons_fns( f, d ) FILE *f; declnlist d;
dcw's avatar
dcw committed
224 225 226
{
	shapelist s;

227 228
	usefile( f );

dcw's avatar
dcw committed
229 230 231 232
	for( ; d; d=d->next )
	{
		for( s = d->shapes; s; s=s->next )
		{
233 234
			cons_fn_hdr( f, d->name, s );
			cons_fn_body( d->name, s );
dcw's avatar
dcw committed
235 236 237 238 239 240
			fprintf( f, "\n\n" );
		}
	}
}


241
static void print_param( shape, ftype, fname ) char *shape, *ftype, *fname;
dcw's avatar
dcw committed
242 243 244
{
	char pname[200];

dcw's avatar
dcw committed
245
	sprintf( pname, "p->u.%s.%s", shape, fname );
dcw's avatar
dcw committed
246 247
	if( streq( ftype, "int" ) )
	{
248
		line( "fprintf( f, \"%%d\", %s );", pname );
dcw's avatar
dcw committed
249 250
	} else if( streq( ftype, "char" ) )
	{
251
		line( "fputc( %s, f );", pname );
dcw's avatar
dcw committed
252 253
	} else if( streq( ftype, "BOOL" ) )
	{
254
		line( "fputs( %s?\"true\":\"false\", f );", pname );
dcw's avatar
dcw committed
255 256
	} else if( streq( ftype, "string" ) )
	{
257
		line( "fputs( %s, f );", pname );
dcw's avatar
dcw committed
258 259
	} else
	{
260
		line( "print_%s( f, %s );", ftype, pname );
dcw's avatar
dcw committed
261 262 263 264
	}
}


265
static void print_fn_shape( typename, s ) char *typename; shapelist s;
dcw's avatar
dcw committed
266
{
267 268 269
	printlist	pl;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed
270

271
	line( "case %s_%s_tag:", typename, s->name );
dcw's avatar
dcw committed
272

273
	indent();
dcw's avatar
dcw committed
274 275
	if( s->pl == NULL )
	{
276 277 278 279 280
		line( "fputs( \"%s\", f );", s->name );
		if( s->params )
		{
			line( "fputc( '(', f );" );
		}
dcw's avatar
dcw committed
281 282
		for( p = s->params; p; p = p->next )
		{
283 284 285 286 287
			print_param( s->name, p->type, p->name );
		}
		if( s->params )
		{
			line( "fputc( ')', f );" );
dcw's avatar
dcw committed
288 289 290 291 292 293 294
		}
	} else
	{
		for( pl = s->pl; pl; pl = pl->next )
		{
			if( pl->item->tag == printitem_is_str )
			{
295
				line( "fputs( \"%s\", f );",
dcw's avatar
dcw committed
296 297 298 299 300 301 302
					pl->item->str );
			} else
			{
				n = pl->item->num;
				for( p = s->params; --n; p = p->next )
				{
					ASSERT( p != NULL,
303
("datadec: bad printitem in shape %s of type %s\n",s->name,typename));
dcw's avatar
dcw committed
304
				}
305
				print_param( s->name, p->type, p->name );
dcw's avatar
dcw committed
306 307 308
			}
		}
	}
309 310
	line( "break;" );
	outdent();
dcw's avatar
dcw committed
311 312 313 314 315 316 317
}


static void print_fns( f, d ) FILE *f ; declnlist d;
{
	shapelist s;

318 319
	usefile( f );

dcw's avatar
dcw committed
320 321
	for( ; d; d = d->next )
	{
322 323 324 325 326
		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
327 328
		for( s = d->shapes; s; s = s->next )
		{
329
			print_fn_shape( d->name, s );
dcw's avatar
dcw committed
330
		}
331 332 333 334 335 336 337 338 339 340
		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
341 342 343
	}
}

dcw's avatar
dcw committed
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

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 )
	{
364 365 366 367 368 369 370 371
		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;
dcw's avatar
dcw committed
372

373 374
			d->Defines = d->TagField = d->Struct =
			d->Union = d->UseNull = FALSE;
dcw's avatar
dcw committed
375 376

/* ONE, EMPTY, eg. 'data x = y' => ERROR */
377 378
			ASSERT( t!=1 || e!=1,
				( "datadec: type %s is empty!\n",d->name) );
dcw's avatar
dcw committed
379

380
			if( t==1 && ne==1 )
dcw's avatar
dcw committed
381
/* ONE, NON EMPTY, eg. 'data x = fred(string z)' */
382 383 384 385
			{
				d->Struct = TRUE;
				/* !Defines, !TagField, !Union, !UseNull */
			} else if( t>1 && ne==0 )
dcw's avatar
dcw committed
386 387
/* >1, ALL EMPTY, eg. 'data x = a | b | c | d | e' */
			{
388 389 390
				d->Defines = TRUE;
				/* !TagField, !Struct, !Union, !UseNull */
			} else if( d->shapes->params == NULL ) /* 1st empty */
dcw's avatar
dcw committed
391
			{
392 393 394 395 396 397 398 399
				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
400
/* >TWO, 1ST EMPTY, ONLY ONE NE, eg. 'data x = a | b | c(char z) | d | e' */
401 402 403 404 405 406 407 408 409 410
					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
411
			} else
412
/* ELSE */
dcw's avatar
dcw committed
413
			{
414
				d->Defines = d->TagField = d->Struct =
dcw's avatar
dcw committed
415 416
				d->Union = TRUE;
			}
417

418 419
			if( verbose )
			{
420
#define XXX(x)	( (x)?' ':'!')
421 422 423 424 425 426
				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) );
427
#undef XXX
428
			}
429

430 431 432 433 434 435 436 437 438 439 440
			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
441 442 443 444
	}
}


dcw's avatar
dcw committed
445 446
void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
{
447
	printf( "datadec: Making data declarations\n" );
dcw's avatar
dcw committed
448

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

dcw's avatar
dcw committed
451 452
	optimize( d );

453 454 455
	usefile( h );

	data_decls( d );
dcw's avatar
dcw committed
456

457
	line( "#ifdef HASPROTOS" );
dcw's avatar
dcw committed
458
	protos( h, d, TRUE );
459
	line( "#else" );
dcw's avatar
dcw committed
460
	protos( h, d, FALSE );
461
	line( "#endif" );
dcw's avatar
dcw committed
462

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