decs.c 20.1 KB
Newer Older
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <stdbool.h>
4
#include <string.h>
5

dcw's avatar
dcw committed
6
#include "struct.h"
7
#include "set.h"
dcw's avatar
dcw committed
8 9
#include "decs.h"

10
bool makefree = false;
dcw's avatar
dcw committed
11

12
//static void line( char * fmt, long a, long b, long c, long d );
Duncan White's avatar
Duncan White committed
13
static void literalline( char * mesg );
14
static void h_declns( char * base, char * exports, bool init, declnlist d );
15
static void c_declns( char * base, char * globals, char * begin, set suppress, declnlist d );
16 17
static void ddtypes( declnlist d );
static void ddoneshape( decln d, shapelist s );
Duncan White's avatar
Duncan White committed
18 19 20
static void data_decls( declnlist decs );
static void declare_type( decln d );
static void declfields( paramlist p );
21 22
static void protos( bool init, char * base, declnlist d, bool prot );
static void proto_type( decln d, bool prot );
Duncan White's avatar
Duncan White committed
23
static void cons_fns( declnlist d );
24
static void cons_fn_proto( decln d, shapelist s, bool prot );
Duncan White's avatar
Duncan White committed
25 26 27
static void cons_fn( decln d, shapelist s );
static void decons_fns( declnlist d );
static void decons_fns_type( decln d );
28
static void deconskind_proto( decln d, bool prot );
Duncan White's avatar
Duncan White committed
29
static void deconskind_fn( decln d );
30
static void decons_fn_proto( decln d, shapelist s, bool prot );
Duncan White's avatar
Duncan White committed
31
static void decons_fn( decln d, shapelist s );
32
static void print_fn_proto( char * name, bool prot );
33
static void print_fns( declnlist d, set suppress );
Duncan White's avatar
Duncan White committed
34 35
static void print_fn_shape( declnlist d, shapelist s );
static void print_all_params( declnlist d, shapelist s );
36 37
static void print_param( shapelist s, paramlist p, bool Union );
static void free_fn_proto( char * name, bool prot );
38 39 40
static void free_fns( declnlist d );
static void free_fn_shape( declnlist d, shapelist s );
static void free_all_params( declnlist d, shapelist s );
41
static void free_param( shapelist s, paramlist p, bool Union );
dcw's avatar
dcw committed
42 43


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


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

dcw's avatar
dcw committed
51 52 53 54
#define nl()		fputc( '\n', outfile )
#define outchar(c)	fputc( c, outfile )
#define usefile(f)	outfile = f, numtabs = 0

55 56 57 58


/*VARARGS*/
static void line( fmt, a, b, c, d ) char *fmt; long a, b, c, d;
Duncan White's avatar
Duncan White committed
59
//static void line( char *fmt, long a, long b, long c, long d )
60 61 62 63 64
{
	int i;

	for( i=numtabs; i; i-- ) fputc( '\t', outfile );
	fprintf( outfile, fmt, a, b, c, d );
dcw's avatar
dcw committed
65
	nl();
66 67 68
}


Duncan White's avatar
Duncan White committed
69
static void literalline( char *mesg )
70 71 72 73 74 75 76 77 78
{
	int i;

	for( i=numtabs; i; i-- ) fputc( '\t', outfile );
	fputs( mesg, outfile );
	nl();
}


79
void make_declns( char *exports, char *globals, char *begin, declnlist d, set suppress, char *base )
dcw's avatar
dcw committed
80
{
dcw's avatar
dcw committed
81 82
	printf( "datadec: Making data declarations in %s.[ch]\n", base );
	h_declns( base, exports, *begin != '\0', d );
83
	c_declns( base, globals, begin, suppress, d );
84 85 86
}


87
static void h_declns( char *base, char *exports, bool init, declnlist d )
88 89 90 91 92
{
	char		tempname[256];
	char		*exportptr;
	FILE		*hfile;

dcw's avatar
dcw committed
93
	sprintf( tempname, "%s.h", base );
94
	hfile = fopen( tempname, "w" );
95 96 97 98 99
	if( hfile == NULL )
	{
		fprintf( stderr, "datadec: can't create '%s'\n", tempname );
		exit(1);
	}
100 101 102 103 104 105 106

	usefile( hfile );

	line( "/*" );
	line( " * Automatically Generated by DataDec" );
	line( " */\n" );
	line( "typedef char *string;\n" );
107 108 109 110 111

	//line( "typedef char bool;" );
	//line( "#define TRUE 1" );
	//line( "#define FALSE 0\n" );

112 113
	line( "#define NEW(t) ((t)malloc(sizeof(struct t)))\n\n" );

114
	exportptr = exports;
115
	if( *exports != '\0' )
dcw's avatar
dcw committed
116
	{
117
		line( "\n/* Contents of top part of EXPORT section */" );
118
		for( ; *exportptr; exportptr++ )
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
		{
			if( *exportptr == '@' && exportptr[1] == '@'
			&&   exportptr[2] == '\n' )
			{
				exportptr += 2;
				break;
			}
			outchar( *exportptr );
		}

		nl();
		nl();
	}

	data_decls( d );

135
	line( "\n/* Prototypes for all types */\n" );
136
	protos( init, base, d, true );
137 138 139 140 141

	if( *exportptr != '\0' )
	{
		nl();
		line( "/* Remaining contents of EXPORT section */" );
142
		literalline( exportptr );
143
		nl();
dcw's avatar
dcw committed
144
	}
145 146

	fclose( hfile );
dcw's avatar
dcw committed
147 148 149
}


150
static void c_declns( char *base, char *globals, char *begin, set suppress, declnlist d )
151 152 153 154 155
{
	char	tempname[256];
	FILE	*cfile;
	char	*globalptr;

dcw's avatar
dcw committed
156
	sprintf( tempname, "%s.c", base );
157
	cfile = fopen( tempname, "w" );
158 159 160 161 162
	if( cfile == NULL )
	{
		fprintf( stderr, "datadec: can't create '%s'\n", tempname );
		exit(1);
	}
163 164 165 166 167 168 169

	usefile( cfile );

	line( "/*" );
	line( " * Automatically Generated by DataDec" );
	line( " */\n" );
	line( "#include <stdio.h>" );
170
	line( "#include <stdlib.h>" );
171
	line( "#include <stdbool.h>" );
172
	line( "#include <assert.h>" );
173

174
	globalptr=globals;
175 176
	if( *globals != '\0' )
	{
177
		line( "\n/* Contents of top part of GLOBAL section */" );
178
		for( ; *globalptr; globalptr++ )
179 180 181 182 183 184 185 186 187 188 189 190 191 192
		{
			if( *globalptr == '@' && globalptr[1] == '@'
			&&   globalptr[2] == '\n' )
			{
				globalptr += 2;
				break;
			}
			outchar( *globalptr );
		}

		nl();
		nl();
	}

193 194
	line( "#include \"%s.h\"\n\n", base );

195
	cons_fns( d );
196
	decons_fns( d );
197
	print_fns( d, suppress );
198 199 200 201
	if( makefree )
	{
		free_fns( d );
	}
202 203 204 205 206 207

	if( *globalptr != '\0' )
	{
		nl();
		nl();
		line( "/* Remaining contents of GLOBAL section */" );
208
		literalline( globalptr );
209 210 211
		nl();
	}

dcw's avatar
dcw committed
212 213 214 215 216 217 218 219
	if( *begin != '\0' )
	{
		line( "/* Contents of BEGIN section */" );
		line( "void init_%s()", base );
		line( "{" );
		line( begin );
		line( "}" );
	}
220 221 222 223
	fclose( cfile );
}


224
void make_metadata( declnlist d )
225
{
226
	usefile( stdout );
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	ddtypes( d );
}


static void ddtypes( declnlist d )
{
	for( ; d != NULL; d=d->next )
	{
		shapelist s = d->shapes;
		for( ; s != NULL; s=s->next )
		{
			ddoneshape( d, s );
		}
	}
}


static void ddoneshape( decln d, shapelist s )
{
	paramlist p;
	bool first;

	fprintf( outfile, "%s %s ", d->name, s->name );
	first = true;

	for( p=s->params; p != NULL; p=p->next, first = false )
	{
		if( !first ) fputs( ",", outfile );
		fputs( p->type, outfile );
	}
	fputc( '\n', outfile );
}


261
/* ------------------------ Declare the types ------------------------------ */
262 263


Duncan White's avatar
Duncan White committed
264
static void data_decls( declnlist decs )
dcw's avatar
dcw committed
265
{
266
	declnlist	d;
dcw's avatar
dcw committed
267

dcw's avatar
dcw committed
268
	for( d=decs; d != NULL; d=d->next )
dcw's avatar
dcw committed
269
	{
dcw's avatar
dcw committed
270 271
		if( d->Struct )
		{
272 273
			line("struct %s;", d->name);
			line("typedef struct %s *%s;", d->name, d->name );
dcw's avatar
dcw committed
274 275 276 277
		} else
		{
			line( "typedef int %s;", d->name );
		}
dcw's avatar
dcw committed
278
	}
279 280
	nl();
	nl();
dcw's avatar
dcw committed
281
	for( d=decs; d != NULL; d=d->next )
dcw's avatar
dcw committed
282
	{
283 284 285 286 287
		declare_type( d );
	}
}


Duncan White's avatar
Duncan White committed
288
static void declare_type( decln d )
289 290 291 292 293 294 295 296 297 298 299
{
	shapelist	s;

	line( "/* ---- Type %s ---- */\n", d->name );

	if( d->ManyShapes )
	{
		line( "typedef enum {" );
		indent();

		for( s = d->shapes; s != NULL; s=s->next )
dcw's avatar
dcw committed
300
		{
301
			line( "%s_is_%s,", d->name, s->name );
dcw's avatar
dcw committed
302
		}
303 304 305
		outdent();
		line( "} kind_of_%s;\n", d->name );
	}
306

307 308 309 310 311 312 313 314 315
	if( d->Struct )
	{
		line( "struct %s {", d->name );
		indent();
		if( d->TagField )
		{
			line( "kind_of_%s\ttag;", d->name );
		}
		if( d->Union )
dcw's avatar
dcw committed
316
		{
317
			line( "union {" );
dcw's avatar
dcw committed
318
			indent();
319 320 321 322 323
		}
		for( s = d->shapes; s != NULL; s=s->next )
		{
			if( s->params == NULL ) continue;

dcw's avatar
dcw committed
324 325
			if( d->Union )
			{
326 327 328 329 330 331 332
				if( s->params->next == NULL )
				{
					/* don't need internal struct */
					/* but use {shape name}_{field name} */
					line( "%s\t%s_%s;", s->params->type,
						s->name, s->params->name );
				} else
dcw's avatar
dcw committed
333
				{
334
					/* need internal struct */
dcw's avatar
dcw committed
335 336 337 338 339
					line( "struct {" );
					indent();
					declfields( s->params );
					outdent();
					line( "} %s;", s->name );
dcw's avatar
dcw committed
340
				}
341
			} else
dcw's avatar
dcw committed
342
			{
343 344
				/* only one chunk of data: this one */
				declfields( s->params );
dcw's avatar
dcw committed
345
			}
346 347 348
		}
		if( d->Union )
		{
dcw's avatar
dcw committed
349
			outdent();
350
			line( "} u;" );
dcw's avatar
dcw committed
351
		}
352 353
		outdent();
		line( "};\n" );
dcw's avatar
dcw committed
354 355 356 357
	}
}


Duncan White's avatar
Duncan White committed
358
static void declfields( paramlist p )
359 360 361 362 363 364 365 366
{
	for( ; p != NULL; p=p->next )
	{
		line( "%s\t%s;", p->type, p->name );
	}
}


367
/* ---------------------- Declare all prototypes -------------------------- */
368 369


370
static void protos( bool init, char *base, declnlist d, bool prot )
371 372 373 374 375
{
	for( ; d != NULL; d = d->next )
	{
		proto_type( d, prot );
	}
dcw's avatar
dcw committed
376 377 378 379 380 381 382 383 384
	if( init )
	{
		fprintf( outfile, "extern void init_%s( ", base );
		if( prot )
		{
			fputs( "void ", outfile );
		}
		fputs( ");\n", outfile );
	}
385 386 387
}


388
static void proto_type( decln d, bool prot )
389 390 391
{
	shapelist	s;

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
	s = d->shapes;
	if( d->Struct )
	{
		/* genuine constructor functions needed */
		if( d->UseNull )
		{
			/* except for first shape */
			line( "#define %s_%s() ((%s)NULL)",
				d->name, d->shapes->name, d->name );
			s = s->next;
		}
		for( ; s != NULL; s = s->next )
		{
			cons_fn_proto( d, s, prot );
		}
	} else
	{
		/* enumeration: use #define for all constructors */
		for( ; s != NULL; s = s->next )
		{
			line( "#define %s_%s() ((int)%s_is_%s)",
				d->name, s->name,
				d->name, s->name );
		}
	}
	if( d->ManyShapes )
418
	{
419
		/* need a deconstructor kind function/macro */
420 421
		if( d->Struct )
		{
422 423 424 425 426 427 428 429 430 431 432 433 434 435
			/* a true function is required */
			deconskind_proto( d, prot );
		} else
		{
			/* enumeration: a macro will do */
			line( "#define %s_kind(this) ((kind_of_%s) this)",
				d->name, d->name );
		}
	}
	if( d->Struct )
	{
		for( s = d->shapes; s != NULL; s = s->next )
		{
			if( s->params != NULL )
436
			{
437
				decons_fn_proto( d, s, prot );
438 439
			}
		}
440 441
	}
	print_fn_proto( d->name, prot );
442 443 444 445
	if( makefree )
	{
		free_fn_proto( d->name, prot );
	}
446 447 448 449 450 451
}


/* ------------------------------- Constructors --------------------------- */


Duncan White's avatar
Duncan White committed
452
static void cons_fns( declnlist d )
453 454 455 456 457 458 459 460 461 462 463
{
	shapelist	s;

	for( ; d != NULL; d=d->next )
	{
		/* ignore enumerations: constructors already in .h file */
		if( ! d->Struct ) continue;

		/* We need constructor functions for this type */
		s = d->shapes;
		if( d->UseNull )
464
		{
465 466 467 468 469 470
			/* Null cons func is a #define in .h file: skip it */
			s = s->next;
		}
		for( ; s != NULL; s=s->next )
		{
			cons_fn( d, s );
471 472 473 474 475
		}
	}
}


476
static void cons_fn_proto( decln d, shapelist s, bool prot )
dcw's avatar
dcw committed
477 478
{
	paramlist p;
479
	bool first;
dcw's avatar
dcw committed
480

481 482 483 484 485
	if( ! d->Struct )
	{
		fprintf( stderr, "cons_fn_proto: d->Struct is false!\n" );
		exit(1);
	}
486 487

	fprintf( outfile, "extern %s %s_%s( ", d->name, d->name, s->name );
488
	if( prot )
dcw's avatar
dcw committed
489 490 491
	{
		if( s->params == NULL )
		{
dcw's avatar
dcw committed
492
			fputs( "void ", outfile );
dcw's avatar
dcw committed
493 494
		} else
		{
495 496
			first = true;
			for( p = s->params; p != NULL ; p=p->next, first=false )
dcw's avatar
dcw committed
497
			{
dcw's avatar
dcw committed
498 499 500
				if( !first ) fputs( ", ", outfile );
				fputs( p->type, outfile );
				fputc( ' ', outfile );
dcw's avatar
dcw committed
501 502 503
			}
		}
	}
dcw's avatar
dcw committed
504
	fputs( ");\n", outfile );
dcw's avatar
dcw committed
505 506 507
}


Duncan White's avatar
Duncan White committed
508
static void cons_fn( decln d, shapelist s )
dcw's avatar
dcw committed
509
{
510
	paramlist p;
511
	bool first;
dcw's avatar
dcw committed
512

513 514
	if( ! d->Struct )
	{
515
		fprintf( stderr, "cons_fn: d->Struct is false!\n" );
516 517
		exit(1);
	}
518 519

	fprintf( outfile, "%s %s_%s( ", d->name, d->name, s->name );
520
	first = true;
521 522 523 524 525

	if( s->params == NULL )
	{
		fprintf( outfile, "void" );
	}
526
	for( p=s->params; p != NULL; p=p->next, first = false )
527 528 529 530 531
	{
		if( !first ) fputs( ", ", outfile );
		fprintf( outfile, "%s %s", p->type, p->name );
	}
	fputs( " )", outfile );
532 533 534 535

	line( "\n{" );
	indent();
	line( "%s\tnew = NEW(%s);", d->name, d->name );
536
	fprintf( outfile, "\tassert( new != NULL );\n" );
537 538 539 540 541 542 543 544 545 546 547 548 549 550
	if( d->TagField )
	{
		line( "new->tag = %s_is_%s;", d->name, s->name );
	}
	if( d->Union && s->params != NULL && s->params->next == NULL )
	{
		/* no internal struct needed for this shape */
		line( "new->u.%s_%s = %s;", s->name,
			s->params->name, s->params->name );
	} else
	{
		paramlist p;

		for( p=s->params; p != NULL; p=p->next )
dcw's avatar
dcw committed
551
		{
552
			if( d->Union )
dcw's avatar
dcw committed
553
			{
554 555 556 557
				/* an internal struct */
				line( "new->u.%s.%s = %s;", s->name,
					p->name, p->name );
			} else
dcw's avatar
dcw committed
558
			{
559 560
				/* only one chunk of data: this one */
				line( "new->%s = %s;", p->name, p->name );
dcw's avatar
dcw committed
561
			}
562
		}
dcw's avatar
dcw committed
563
	}
564 565 566
	line( "return new;" );
	outdent();
	line( "}\n\n" );
dcw's avatar
dcw committed
567 568 569
}


570 571 572
/* ------------------------- Deconstructors ------------------------------- */


Duncan White's avatar
Duncan White committed
573
static void decons_fns( declnlist d )
dcw's avatar
dcw committed
574
{
575 576 577 578 579 580 581 582 583
	for( ; d != NULL; d=d->next )
	{
		if( d->Struct )
		{
			decons_fns_type( d );
		}
		/* enumerations need none (decon kind macro already in .h) */
	}
}
dcw's avatar
dcw committed
584

585

Duncan White's avatar
Duncan White committed
586
static void decons_fns_type( decln d )
587 588 589
{
	shapelist	s;

590 591
	if( ! d->Struct )
	{
592
		fprintf( stderr, "decons_fns_type: d->Struct is false!\n" );
593 594
		exit(1);
	}
595 596

	if( d->ManyShapes )
dcw's avatar
dcw committed
597
	{
598 599
		/* We need a true deconstructor kind function */
		deconskind_fn( d );
dcw's avatar
dcw committed
600
	}
601 602
	/* We need (some) deconstructor functions */
	for( s = d->shapes; s != NULL; s=s->next )
dcw's avatar
dcw committed
603
	{
604 605 606 607
		if( s->params != NULL )
		{
			decons_fn( d, s );
		}
dcw's avatar
dcw committed
608 609 610 611
	}
}


612 613 614
/* ------------------- Deconstructor Kind procedure ----------------------- */


615
static void deconskind_proto( decln d, bool prot )
dcw's avatar
dcw committed
616
{
617 618 619
	if( ! d->ManyShapes )
	{
		fprintf( stderr,
620
			"deconskind_proto: d->ManyShapes is false!\n" );
621 622 623 624
		exit(1);
	}
	if( ! d->Struct )
	{
625
		fprintf( stderr, "deconskind_proto: d->Struct is false!\n" );
626 627
		exit(1);
	}
628 629 630 631 632 633 634 635 636 637

	fprintf( outfile, "extern kind_of_%s %s_kind( ", d->name, d->name );
	if( prot )
	{
		fprintf( outfile, "%s ", d->name );
	}
	fputs( ");\n", outfile );
}


Duncan White's avatar
Duncan White committed
638
static void deconskind_fn( decln d )
639 640 641
{
	shapelist s = d->shapes;

642 643
	if( ! d->ManyShapes )
	{
644
		fprintf( stderr, "deconskind_fn: d->ManyShapes is false!\n" );
645 646 647 648
		exit(1);
	}
	if( ! d->Struct )
	{
649
		fprintf( stderr, "deconskind_fn: d->Struct is false!\n" );
650 651
		exit(1);
	}
652

653 654
	fprintf( outfile, "kind_of_%s %s_kind( %s this )\n",
		 d->name, d->name, d->name );
dcw's avatar
dcw committed
655

656 657
	line( "{" );
	indent();
658 659 660 661 662 663 664 665 666 667 668

	if ( d->UseNull )
	{
		line( "if( this == NULL )" );
		line( "{" );
		indent();
		line( "return %s_is_%s;", d->name, s->name );
		outdent();
		line( "}" );
		s = s->next;
	}
dcw's avatar
dcw committed
669 670
	if( d->TagField )
	{
671
		line( "return this->tag;" );
dcw's avatar
dcw committed
672
	}
673
	else
dcw's avatar
dcw committed
674
	{
675 676 677 678 679 680 681 682 683 684
		line( "return %s_is_%s;", d->name, s->name );
	}
	outdent();
	line( "}\n\n" );
}


/* ----------------------- Deconstructor functions ------------------------ */


685
static void decons_fn_proto( decln d, shapelist s, bool prot )
686
{
687 688
	if( ! d->Struct )
	{
689
		fprintf( stderr, "decons_fn_proto: d->Struct is false!\n" );
690 691 692 693 694 695 696
		exit(1);
	}
	if( s->params == NULL )
	{
		fprintf( stderr, "decons_fn_proto: no fields in shape!!\n" );
		exit(1);
	}
697 698 699 700 701 702 703 704

	fprintf( outfile, "extern void get_%s_%s(", d->name, s->name );
	if( prot )
	{
		paramlist p;

		fprintf( outfile, " %s ", d->name );
		for( p = s->params; p != NULL ; p=p->next )
dcw's avatar
dcw committed
705
		{
706 707 708 709 710 711 712
			fprintf( outfile, ", %s * ", p->type );
		}
	}
	fputs( ");\n", outfile );
}


Duncan White's avatar
Duncan White committed
713
static void decons_fn( decln d, shapelist s )
714 715 716
{
	paramlist p;

717 718
	if( ! d->Struct )
	{
719
		fprintf( stderr, "decons_fn: d->Struct is false!\n" );
720 721 722 723 724 725 726
		exit(1);
	}
	if( s->params == NULL )
	{
		fprintf( stderr, "decons_fn: no fields in shape!!\n" );
		exit(1);
	}
727

728 729 730 731 732 733
	fprintf( outfile, "void get_%s_%s( %s this", d->name, s->name, d->name );
	for( p=s->params; p != NULL; p=p->next )
	{
		fprintf( outfile, ", %s *%s", p->type, p->name );
	}
	fprintf( outfile, " )" );
734 735 736 737 738 739 740 741 742 743 744
	line( "\n{" );
	indent();

	if( d->Union && s->params != NULL && s->params->next == NULL )
	{
		/* no internal struct: one field only */
		line( "*%s = this->u.%s_%s;",
			s->params->name, s->name, s->params->name );
	} else
	{
		for( p=s->params; p != NULL; p=p->next )
dcw's avatar
dcw committed
745
		{
746 747 748 749 750 751 752 753 754 755
			if( d->Union )
			{
				/* internal struct */
				line( "*%s = this->u.%s.%s;",
					p->name, s->name, p->name );
			} else
			{
				/* only one chunk of data: this one */
				line( "*%s = this->%s;", p->name, p->name );
			}
dcw's avatar
dcw committed
756
		}
dcw's avatar
dcw committed
757
	}
758
	outdent();
759
	line( "}\n\n" );
dcw's avatar
dcw committed
760 761 762
}


763
/* -------------------------- Print functions ----------------------------- */
dcw's avatar
dcw committed
764 765


766
static void print_fn_proto( char *name, bool prot )
dcw's avatar
dcw committed
767
{
768 769 770
	fprintf( outfile, "extern void print_%s(", name );
	if( prot )
	{
771
		fprintf( outfile, " FILE *, %s ", name );
772 773 774
	}
	fputs( ");\n", outfile );
}
dcw's avatar
dcw committed
775

776

777
static void print_fns( declnlist d, set suppress )
778
{
dcw's avatar
dcw committed
779
	for( ; d != NULL; d = d->next )
dcw's avatar
dcw committed
780
	{
781 782 783 784 785 786 787 788
		char fname[2048];
		sprintf( fname, "print_%s", d->name );
		if( setIn( suppress, fname ) )
		{
			fprintf( stderr, "Suppressing %s\n", fname );
			continue;
		}
		line( "void %s( FILE *f, %s p )", fname, d->name );
789 790
		line( "{" );
		indent();
791
		shapelist s = d->shapes;
dcw's avatar
dcw committed
792
		if( d->UseNull )
dcw's avatar
dcw committed
793
		{
dcw's avatar
dcw committed
794 795 796
			line( "if( p == NULL )" );
			line( "{" );
			indent();
797
			print_all_params( d, s );
dcw's avatar
dcw committed
798 799 800
			line( "return;" );
			outdent();
			line( "}" );
801
			s = s->next;
dcw's avatar
dcw committed
802 803 804 805 806
		}
		if( d->TagField )
		{
			line( "switch( p->tag )" );
			line( "{" );
807
			for( ; s != NULL; s = s->next )
dcw's avatar
dcw committed
808 809 810 811 812 813 814 815 816 817 818
			{
				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( "}" );
819 820
		}
		else if( ! d->TagField && d->Struct )	/* one shape left */
dcw's avatar
dcw committed
821
		{
822 823 824
			print_all_params( d, s );
		}
		else if( ! d->Struct && d->ManyShapes ) /* enumerated type */
dcw's avatar
dcw committed
825 826 827
		{
			line( "switch( p )" );
			line( "{" );
828
			for( ; s != NULL; s = s->next )
dcw's avatar
dcw committed
829
			{
dcw's avatar
dcw committed
830
				line( "case %s_%s():", d->name, s->name );
dcw's avatar
dcw committed
831 832 833 834 835 836
				indent();
				print_all_params( d, s );
				line( "break;" );
				outdent();
			}
			line( "}" );
dcw's avatar
dcw committed
837 838 839 840 841
		} else
		{
			fprintf( stderr,
				 "datadec: internal error in print_fns\n" );
			exit(1);
dcw's avatar
dcw committed
842
		}
843
		outdent();
844
		line( "}\n\n" );
dcw's avatar
dcw committed
845 846 847
	}
}

dcw's avatar
dcw committed
848

Duncan White's avatar
Duncan White committed
849
static void print_fn_shape( declnlist d, shapelist s )
dcw's avatar
dcw committed
850
{
851
	line( "case %s_is_%s:", d->name, s->name );
852 853 854 855
	indent();
	print_all_params( d, s );
	line( "break;" );
	outdent();
dcw's avatar
dcw committed
856 857 858
}


Duncan White's avatar
Duncan White committed
859
static void print_all_params( declnlist d, shapelist s )
dcw's avatar
dcw committed
860
{
861 862 863
	printlist	pl;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed
864

865
	if( s->pl == NULL )
dcw's avatar
dcw committed
866
	{
867 868
		line( "fputs( \"%s\", f );", s->name );
		if( s->params )
dcw's avatar
dcw committed
869
		{
870
			line( "fputc( '(', f );" );
dcw's avatar
dcw committed
871
		}
872
		for( p = s->params; p != NULL; p = p->next )
dcw's avatar
dcw committed
873
		{
874
			print_param( s, p, d->Union );
875 876 877 878
			if( p->next != NULL )
			{
				line( "fputc( ',', f );" );
			}
dcw's avatar
dcw committed
879
		}
880 881 882 883 884
		if( s->params )
		{
			line( "fputc( ')', f );" );
		}
	} else
dcw's avatar
dcw committed
885
	{
886
		for( pl = s->pl; pl != NULL; pl = pl->next )
dcw's avatar
dcw committed
887
		{
888
			if( pl->item->tag == printitem_is_str )
dcw's avatar
dcw committed
889
			{
890 891 892 893 894
				line( "fputs( \"%s\", f );",
					pl->item->str );
			} else
			{
				n = pl->item->num;
895 896 897 898 899
				for( p = s->params; p != NULL && --n;
					p = p->next )
					;

				if( p == NULL )
900
				{
901
					fprintf( stderr,
902 903
	"datadec: bad printitem in shape %s of type %s\n",
	s->name, d->name );
904
					exit(1);
905
				}
906
				print_param( s, p, d->Union );
dcw's avatar
dcw committed
907 908 909
			}
		}
	}
910
}
dcw's avatar
dcw committed
911 912


913
static void print_param( shapelist s, paramlist p, bool Union )
914 915
{
	char pname[200];
dcw's avatar
dcw committed
916

917
	if( Union )
dcw's avatar
dcw committed
918
	{
919 920 921 922 923 924 925 926 927
		if( s->params->next == NULL )
		{
			/* no internal struct */
			sprintf( pname, "p->u.%s_%s", s->name, p->name );
		} else
		{
			/* internal struct */
			sprintf( pname, "p->u.%s.%s", s->name, p->name );
		}
928 929 930
	} else
	{
		sprintf( pname, "p->%s", p->name );
dcw's avatar
dcw committed
931 932
	}

933 934 935 936 937 938
	if( streq( p->type, "int" ) )
	{
		line( "fprintf( f, \"%%d\", %s );", pname );
	} else if( streq( p->type, "char" ) )
	{
		line( "fputc( %s, f );", pname );
939
	} else if( streq( p->type, "BOOL" ) || streq( p->type, "bool" ) )
940 941 942 943 944 945 946 947 948
	{
		line( "fputs( %s?\"true\":\"false\", f );", pname );
	} else if( streq( p->type, "string" ) )
	{
		line( "fputs( %s, f );", pname );
	} else
	{
		line( "print_%s( f, %s );", p->type, pname );
	}
dcw's avatar
dcw committed
949
}
950 951 952 953 954


/* ------------------- experimental free functions ------------------------ */


955
static void free_fn_proto( char *name, bool prot )
956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
{
	fprintf( outfile, "extern void free_%s(", name );
	if( prot )
	{
		fprintf( outfile, " %s ", name );
	}
	fputs( ");\n", outfile );
}


static void free_fns( declnlist d )
{
	for( ; d != NULL; d = d->next )
	{
		shapelist s;

		line( "void free_%s( %s p )",d->name, d->name );
		line( "{" );
		indent();
		s = d->shapes;
		if( d->UseNull )
		{
			line( "if( p == NULL )" );
			line( "{" );
			indent();
			line( "return;" );
			outdent();
			line( "}" );
			s = s->next;
		}
		if( d->TagField )
		{
			line( "switch( p->tag )" );
			line( "{" );
			for( ; s != NULL; s = s->next )
			{
				free_fn_shape( d, s );
			}
			line( "default:" );
			indent();
			line( "fprintf( stderr," );
			line( " \"free_%s: impossible tag %%d\\n\", p->tag );",
				d->name );
			line( "exit(1);" );
			outdent();
			line( "}" );
		}
		else if( ! d->TagField && d->Struct )	/* one shape left */
		{
			free_all_params( d, s );
		}
		else if( ! d->Struct && d->ManyShapes ) /* enumerated type */
		{
			line( "switch( p )" );
			line( "{" );
			for( ; s != NULL; s = s->next )
			{
				line( "case %s_%s():", d->name, s->name );
				indent();
				free_all_params( d, s );
				line( "break;" );
				outdent();
			}
			line( "}" );
		} else
		{
			fprintf( stderr,
				 "datadec: internal error in free_fns\n" );
			exit(1);
		}
		if( d->Struct )		/* now need to free the node itself */
		{
			line( "free( p );" );
		}
		outdent();
		line( "}\n\n" );
	}
}


static void free_fn_shape( declnlist d, shapelist s )
{
	line( "case %s_is_%s:", d->name, s->name );
	indent();
	free_all_params( d, s );
	line( "break;" );
	outdent();
}


static void free_all_params( declnlist d, shapelist s )
{
	paramlist	p;

	for( p = s->params; p != NULL; p = p->next )
	{
		free_param( s, p, d->Union );
	}
}


1057
static void free_param( shapelist s, paramlist p, bool Union )
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
{
	char pname[200];

	if( Union )
	{
		if( s->params->next == NULL )
		{
			/* no internal struct */
			sprintf( pname, "p->u.%s_%s", s->name, p->name );
		} else
		{
			/* internal struct */
			sprintf( pname, "p->u.%s.%s", s->name, p->name );
		}
	} else
	{
		sprintf( pname, "p->%s", p->name );
	}

	if( ! p->dontfree )
	{
		line( "free_%s( %s );", p->type, pname );
	}
}