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

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


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

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


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

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


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

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


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

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


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

285 286
	usefile( f );

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


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

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


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

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


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


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

399 400
	usefile( f );

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

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

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

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

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

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

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

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


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

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

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

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

567 568 569
	usefile( h );

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

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

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