decs.c 11.6 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 );
dcw's avatar
dcw committed
12
static void cons_fn_body( declnlist, char * , shapelist );
dcw's avatar
dcw committed
13 14
static void cons_fns( FILE * , declnlist );
static void print_fns( FILE * , declnlist );
dcw's avatar
dcw committed
15 16 17
static void print_fn_shape( declnlist , shapelist );
static void print_param( char * , paramlist , BOOL );
static void print_all_params( declnlist , shapelist );
18 19 20
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
21
static void declfields( paramlist );
dcw's avatar
dcw committed
22
#else
dcw's avatar
dcw committed
23 24 25 26 27 28 29 30 31 32
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
33
static void print_all_params();
34 35 36
static void count_empty_non();
static void optimize();
static void line();
dcw's avatar
dcw committed
37
static void declfields();
dcw's avatar
dcw committed
38 39 40
#endif


dcw's avatar
dcw committed
41
BOOL print, verbose, opt;	/* print   == generate print functions */
42
				/* verbose == be verbose - diagnostics */
dcw's avatar
dcw committed
43
				/* opt     == perform optimizations    */
44

45 46 47 48 49 50 51
static int numtabs = 0;
static FILE *outfile;


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

52
#define usefile(f) outfile = f, numtabs = 0
53 54 55 56 57 58 59 60 61 62 63 64 65


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


dcw's avatar
dcw committed
85 86 87 88 89 90 91 92 93
static void declfields( p ) paramlist p;
{
	for( ; p; p=p->next )
	{
		line( "%s\t%s;", p->type, p->name );
	}
}


94
static void data_decls( decs ) declnlist decs;
dcw's avatar
dcw committed
95
{
96 97 98 99
	declnlist	d;
	shapelist	s;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed
100

101
	for( d=decs; d; d=d->next )
dcw's avatar
dcw committed
102
	{
dcw's avatar
dcw committed
103 104
		if( d->Struct )
		{
105 106
			line("struct %s;", d->name);
			line("typedef struct %s *%s;", d->name, d->name );
dcw's avatar
dcw committed
107 108 109 110
		} else
		{
			line( "typedef int %s;", d->name );
		}
dcw's avatar
dcw committed
111
	}
112 113
	line( "\n" );
	for( d=decs; d; d=d->next )
dcw's avatar
dcw committed
114
	{
115
		line( "/* ---- Type %s ---- */\n", d->name );
dcw's avatar
dcw committed
116
		n = 0;
dcw's avatar
dcw committed
117
		if( d->Defines )
dcw's avatar
dcw committed
118
		{
dcw's avatar
dcw committed
119 120 121 122 123 124 125 126 127 128 129 130 131
			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
132
		}
133

dcw's avatar
dcw committed
134
		if( d->Struct )
dcw's avatar
dcw committed
135
		{
dcw's avatar
dcw committed
136 137 138
			line( "struct %s_str {", d->name );
			indent();
			if( d->TagField )
dcw's avatar
dcw committed
139
			{
dcw's avatar
dcw committed
140 141 142 143 144
				line( "int\ttag;" );
			}
			if( d->Union )
			{
				line( "union {" );
145
				indent();
dcw's avatar
dcw committed
146 147 148 149 150 151 152 153 154 155 156 157
			}
			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
158
				{
dcw's avatar
dcw committed
159
					declfields( s->params );
dcw's avatar
dcw committed
160
				}
dcw's avatar
dcw committed
161 162 163
			}
			if( d->Union )
			{
164
				outdent();
dcw's avatar
dcw committed
165
				line( "} u;" );
dcw's avatar
dcw committed
166
			}
dcw's avatar
dcw committed
167 168
			outdent();
			line( "};\n" );
dcw's avatar
dcw committed
169 170 171 172 173
		}
	}
}


174
static void one_proto( f, name, s, prot ) FILE *f; char *name; shapelist s; BOOL prot;
dcw's avatar
dcw committed
175 176 177 178
{
	paramlist p;
	BOOL first;

179 180
	fprintf( f, "extern %s %s_%s( ", name, name, s->name );
	if( prot )
dcw's avatar
dcw committed
181 182 183
	{
		if( s->params == NULL )
		{
184
			fputs( "void ", f );
dcw's avatar
dcw committed
185 186
		} else
		{
dcw's avatar
dcw committed
187
			first = TRUE;
dcw's avatar
dcw committed
188 189
			for( p = s->params; p ; p=p->next, first=FALSE )
			{
190 191 192
				if( !first ) fputs( ", ", f );
				fputs( p->type, f );
				fputc( ' ', f );
dcw's avatar
dcw committed
193 194 195
			}
		}
	}
196
	fputs( ");\n", f );
dcw's avatar
dcw committed
197 198 199
}


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

205
	for( ; d; d = d->next )
dcw's avatar
dcw committed
206
	{
dcw's avatar
dcw committed
207 208 209 210 211 212
		shapes = d->shapes;
		if( d->UseNull )
		{
			shapes = shapes->next;
		}
		for( s = shapes; s; s = s->next )
dcw's avatar
dcw committed
213
		{
214 215 216 217
			one_proto( f, d->name, s, prot );
		}
		if( print )
		{
dcw's avatar
dcw committed
218
			fprintf( f, "extern void print_%s(", d->name );
219 220
			if( prot )
			{
dcw's avatar
dcw committed
221
				fprintf( f, " %s ", d->name );
222
			}
dcw's avatar
dcw committed
223
			fputs( ");\n", f );
dcw's avatar
dcw committed
224
		}
dcw's avatar
dcw committed
225
	}
dcw's avatar
dcw committed
226 227 228
}


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

234
	fprintf( f, "%s %s_%s( ", name, name, s->name );
dcw's avatar
dcw committed
235
	first = TRUE;
dcw's avatar
dcw committed
236 237
	for( p=s->params; p; p=p->next, first=FALSE )
	{
238 239
		if( !first ) fputs( ", ", f );
		fputs( p->name, f );
dcw's avatar
dcw committed
240
	}
241
	fputs( " ) ", f );
dcw's avatar
dcw committed
242 243 244
	for( p=s->params; p; p=p->next )
	{
		fprintf( f, "%s %s; ", p->type, p->name );
dcw's avatar
dcw committed
245 246 247 248 249
	}
	fputc( '\n', f );
}


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

dcw's avatar
dcw committed
254
	ASSERT( d->Struct,
255
		("error: cons_fn_body called but d->Struct is FALSE!\n") );
256 257
	line( "{" );
	indent();
dcw's avatar
dcw committed
258
	line( "%s\tnew;\n", name );
259
	line( "new = NEW_(%s);", name );
dcw's avatar
dcw committed
260 261 262 263
	if( d->TagField )
	{
		line( "new->tag = %s_%s_tag;", name, s->name );
	}
dcw's avatar
dcw committed
264 265
	for( p=s->params; p; p=p->next )
	{
dcw's avatar
dcw committed
266 267 268 269 270 271 272 273
		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
274
	}
275 276 277
	line( "return new;" );
	outdent();
	line( "}" );
dcw's avatar
dcw committed
278 279 280
}


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

286 287
	usefile( f );

dcw's avatar
dcw committed
288 289
	for( ; d; d=d->next )
	{
dcw's avatar
dcw committed
290
		if( d->Struct )
dcw's avatar
dcw committed
291
		{
dcw's avatar
dcw committed
292 293 294 295 296 297 298 299 300 301 302 303 304
			/* 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
305 306 307 308 309
		}
	}
}


dcw's avatar
dcw committed
310
static void print_param( shape, p, Union ) char *shape; paramlist p; BOOL Union;
dcw's avatar
dcw committed
311 312 313
{
	char pname[200];

dcw's avatar
dcw committed
314 315 316 317 318 319 320 321 322
	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
323
	{
324
		line( "fprintf( f, \"%%d\", %s );", pname );
dcw's avatar
dcw committed
325
	} else if( streq( p->type, "char" ) )
dcw's avatar
dcw committed
326
	{
327
		line( "fputc( %s, f );", pname );
dcw's avatar
dcw committed
328
	} else if( streq( p->type, "BOOL" ) )
dcw's avatar
dcw committed
329
	{
330
		line( "fputs( %s?\"true\":\"false\", f );", pname );
dcw's avatar
dcw committed
331
	} else if( streq( p->type, "string" ) )
dcw's avatar
dcw committed
332
	{
333
		line( "fputs( %s, f );", pname );
dcw's avatar
dcw committed
334 335
	} else
	{
dcw's avatar
dcw committed
336
		line( "print_%s( f, %s );", p->type, pname );
dcw's avatar
dcw committed
337 338 339 340
	}
}


dcw's avatar
dcw committed
341
static void print_all_params( d, s ) declnlist d; shapelist s;
dcw's avatar
dcw committed
342
{
343 344 345
	printlist	pl;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed
346 347 348

	if( s->pl == NULL )
	{
349 350 351 352 353
		line( "fputs( \"%s\", f );", s->name );
		if( s->params )
		{
			line( "fputc( '(', f );" );
		}
dcw's avatar
dcw committed
354 355
		for( p = s->params; p; p = p->next )
		{
dcw's avatar
dcw committed
356
			print_param( s->name, p, d->Union );
357 358 359 360
		}
		if( s->params )
		{
			line( "fputc( ')', f );" );
dcw's avatar
dcw committed
361 362 363 364 365 366 367
		}
	} else
	{
		for( pl = s->pl; pl; pl = pl->next )
		{
			if( pl->item->tag == printitem_is_str )
			{
368
				line( "fputs( \"%s\", f );",
dcw's avatar
dcw committed
369 370 371 372 373 374 375
					pl->item->str );
			} else
			{
				n = pl->item->num;
				for( p = s->params; --n; p = p->next )
				{
					ASSERT( p != NULL,
dcw's avatar
dcw committed
376
("datadec: bad printitem in shape %s of type %s\n",s->name,d->name));
dcw's avatar
dcw committed
377
				}
dcw's avatar
dcw committed
378
				print_param( s->name, p, d->Union );
dcw's avatar
dcw committed
379 380 381
			}
		}
	}
dcw's avatar
dcw committed
382 383 384 385 386 387 388 389
}


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 );
390 391
	line( "break;" );
	outdent();
dcw's avatar
dcw committed
392 393 394 395 396 397
}


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

400 401
	usefile( f );

dcw's avatar
dcw committed
402 403
	for( ; d; d = d->next )
	{
dcw's avatar
dcw committed
404
		shapes = d->shapes;
405 406 407
		line( "void print_%s( f, p ) FILE *f; %s p;",d->name, d->name );
		line( "{" );
		indent();
dcw's avatar
dcw committed
408
		if( d->UseNull )
dcw's avatar
dcw committed
409
		{
dcw's avatar
dcw committed
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 450
			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
451
		}
452 453
		outdent();
		line( "}\n" );
dcw's avatar
dcw committed
454 455 456
	}
}

dcw's avatar
dcw committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476

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 )
	{
477 478 479 480 481 482 483 484
		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
485

486 487
			d->Defines = d->TagField = d->Struct =
			d->Union = d->UseNull = FALSE;
dcw's avatar
dcw committed
488 489

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

493
			if( t==1 && ne==1 )
dcw's avatar
dcw committed
494
/* ONE, NON EMPTY, eg. 'data x = fred(string z)' */
495 496 497 498
			{
				d->Struct = TRUE;
				/* !Defines, !TagField, !Union, !UseNull */
			} else if( t>1 && ne==0 )
dcw's avatar
dcw committed
499 500
/* >1, ALL EMPTY, eg. 'data x = a | b | c | d | e' */
			{
501 502 503
				d->Defines = TRUE;
				/* !TagField, !Struct, !Union, !UseNull */
			} else if( d->shapes->params == NULL ) /* 1st empty */
dcw's avatar
dcw committed
504
			{
505 506 507 508 509 510 511 512
				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
513
/* >TWO, 1ST EMPTY, ONLY ONE NE, eg. 'data x = a | b | c(char z) | d | e' */
514 515 516 517 518 519 520 521 522 523
					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
524
			} else
525
/* ELSE */
dcw's avatar
dcw committed
526
			{
527
				d->Defines = d->TagField = d->Struct =
dcw's avatar
dcw committed
528 529
				d->Union = TRUE;
			}
530

531 532
			if( verbose )
			{
533
#define XXX(x)	( (x)?' ':'!')
534 535 536 537 538 539
				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) );
540
#undef XXX
541
			}
542

543 544 545 546 547 548 549 550 551 552 553
			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
554 555 556 557
	}
}


dcw's avatar
dcw committed
558 559
void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
{
dcw's avatar
dcw committed
560 561
	declnlist dl;

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

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

dcw's avatar
dcw committed
566 567
	optimize( d );

568 569 570
	usefile( h );

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

dcw's avatar
dcw committed
572 573 574 575 576 577 578 579
	for( dl = d; dl; dl=dl->next )
	{
		if( dl->UseNull )
		{
			line( "#define %s_%s() ((%s)NULL)",
				dl->name, dl->shapes->name, dl->name );
		}
	}
580
	line( "#ifdef HASPROTOS" );
dcw's avatar
dcw committed
581
	protos( h, d, TRUE );
582
	line( "#else" );
dcw's avatar
dcw committed
583
	protos( h, d, FALSE );
584
	line( "#endif" );
dcw's avatar
dcw committed
585

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