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 7 8
#include "struct.h"
#include "decs.h"

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

11
//static void line( char * fmt, long a, long b, long c, long d );
Duncan White's avatar
Duncan White committed
12
static void literalline( char * mesg );
13
static void h_declns( char * base, char * exports, bool init, declnlist d );
Duncan White's avatar
Duncan White committed
14
static void c_declns( char * base, char * globals, char * begin, declnlist d );
15 16 17
static void dd_declns( char * base, declnlist d );
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 );
Duncan White's avatar
Duncan White committed
33 34 35
static void print_fns( declnlist d );
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();
}


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


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

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

	usefile( hfile );

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

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

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

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

		nl();
		nl();
	}

	data_decls( d );

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

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

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


Duncan White's avatar
Duncan White committed
151
static void c_declns( char *base, char *globals, char *begin, declnlist d )
152 153 154 155 156
{
	char	tempname[256];
	FILE	*cfile;
	char	*globalptr;

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

	usefile( cfile );

	line( "/*" );
	line( " * Automatically Generated by DataDec" );
	line( " */\n" );
	line( "#include <stdio.h>" );
171
	line( "#include <stdlib.h>" );
172
	line( "#include <stdbool.h>" );
dcw's avatar
dcw committed
173
	line( "#include \"%s.h\"\n\n", base );
174

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

		nl();
		nl();
	}

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

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

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


223 224 225 226 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 261 262 263 264 265 266 267 268 269 270 271 272 273
static void dd_declns( char *base, declnlist d )
{
	char		tempname[256];
	FILE		*file;

	sprintf( tempname, ".%s.dd", base );
	file = fopen( tempname, "w" );
	if( file == NULL )
	{
		fprintf( stderr, "datadec: can't create '%s'\n", tempname );
		exit(1);
	}

	usefile( file );

	ddtypes( d );

	fclose( file );
}


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 );
}


274
/* ------------------------ Declare the types ------------------------------ */
275 276


Duncan White's avatar
Duncan White committed
277
static void data_decls( declnlist decs )
dcw's avatar
dcw committed
278
{
279
	declnlist	d;
dcw's avatar
dcw committed
280

dcw's avatar
dcw committed
281
	for( d=decs; d != NULL; d=d->next )
dcw's avatar
dcw committed
282
	{
dcw's avatar
dcw committed
283 284
		if( d->Struct )
		{
285 286
			line("struct %s;", d->name);
			line("typedef struct %s *%s;", d->name, d->name );
dcw's avatar
dcw committed
287 288 289 290
		} else
		{
			line( "typedef int %s;", d->name );
		}
dcw's avatar
dcw committed
291
	}
292 293
	nl();
	nl();
dcw's avatar
dcw committed
294
	for( d=decs; d != NULL; d=d->next )
dcw's avatar
dcw committed
295
	{
296 297 298 299 300
		declare_type( d );
	}
}


Duncan White's avatar
Duncan White committed
301
static void declare_type( decln d )
302 303 304 305 306 307 308 309 310 311 312
{
	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
313
		{
314
			line( "%s_is_%s,", d->name, s->name );
dcw's avatar
dcw committed
315
		}
316 317 318
		outdent();
		line( "} kind_of_%s;\n", d->name );
	}
319

320 321 322 323 324 325 326 327 328
	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
329
		{
330
			line( "union {" );
dcw's avatar
dcw committed
331
			indent();
332 333 334 335 336
		}
		for( s = d->shapes; s != NULL; s=s->next )
		{
			if( s->params == NULL ) continue;

dcw's avatar
dcw committed
337 338
			if( d->Union )
			{
339 340 341 342 343 344 345
				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
346
				{
347
					/* need internal struct */
dcw's avatar
dcw committed
348 349 350 351 352
					line( "struct {" );
					indent();
					declfields( s->params );
					outdent();
					line( "} %s;", s->name );
dcw's avatar
dcw committed
353
				}
354
			} else
dcw's avatar
dcw committed
355
			{
356 357
				/* only one chunk of data: this one */
				declfields( s->params );
dcw's avatar
dcw committed
358
			}
359 360 361
		}
		if( d->Union )
		{
dcw's avatar
dcw committed
362
			outdent();
363
			line( "} u;" );
dcw's avatar
dcw committed
364
		}
365 366
		outdent();
		line( "};\n" );
dcw's avatar
dcw committed
367 368 369 370
	}
}


Duncan White's avatar
Duncan White committed
371
static void declfields( paramlist p )
372 373 374 375 376 377 378 379
{
	for( ; p != NULL; p=p->next )
	{
		line( "%s\t%s;", p->type, p->name );
	}
}


380
/* ---------------------- Declare all prototypes -------------------------- */
381 382


383
static void protos( bool init, char *base, declnlist d, bool prot )
384 385 386 387 388
{
	for( ; d != NULL; d = d->next )
	{
		proto_type( d, prot );
	}
dcw's avatar
dcw committed
389 390 391 392 393 394 395 396 397
	if( init )
	{
		fprintf( outfile, "extern void init_%s( ", base );
		if( prot )
		{
			fputs( "void ", outfile );
		}
		fputs( ");\n", outfile );
	}
398 399 400
}


401
static void proto_type( decln d, bool prot )
402 403 404
{
	shapelist	s;

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
	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 )
431
	{
432
		/* need a deconstructor kind function/macro */
433 434
		if( d->Struct )
		{
435 436 437 438 439 440 441 442 443 444 445 446 447 448
			/* 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 )
449
			{
450
				decons_fn_proto( d, s, prot );
451 452
			}
		}
453 454
	}
	print_fn_proto( d->name, prot );
455 456 457 458
	if( makefree )
	{
		free_fn_proto( d->name, prot );
	}
459 460 461 462 463 464
}


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


Duncan White's avatar
Duncan White committed
465
static void cons_fns( declnlist d )
466 467 468 469 470 471 472 473 474 475 476
{
	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 )
477
		{
478 479 480 481 482 483
			/* Null cons func is a #define in .h file: skip it */
			s = s->next;
		}
		for( ; s != NULL; s=s->next )
		{
			cons_fn( d, s );
484 485 486 487 488
		}
	}
}


489
static void cons_fn_proto( decln d, shapelist s, bool prot )
dcw's avatar
dcw committed
490 491
{
	paramlist p;
492
	bool first;
dcw's avatar
dcw committed
493

494 495 496 497 498
	if( ! d->Struct )
	{
		fprintf( stderr, "cons_fn_proto: d->Struct is false!\n" );
		exit(1);
	}
499 500

	fprintf( outfile, "extern %s %s_%s( ", d->name, d->name, s->name );
501
	if( prot )
dcw's avatar
dcw committed
502 503 504
	{
		if( s->params == NULL )
		{
dcw's avatar
dcw committed
505
			fputs( "void ", outfile );
dcw's avatar
dcw committed
506 507
		} else
		{
508 509
			first = true;
			for( p = s->params; p != NULL ; p=p->next, first=false )
dcw's avatar
dcw committed
510
			{
dcw's avatar
dcw committed
511 512 513
				if( !first ) fputs( ", ", outfile );
				fputs( p->type, outfile );
				fputc( ' ', outfile );
dcw's avatar
dcw committed
514 515 516
			}
		}
	}
dcw's avatar
dcw committed
517
	fputs( ");\n", outfile );
dcw's avatar
dcw committed
518 519 520
}


Duncan White's avatar
Duncan White committed
521
static void cons_fn( decln d, shapelist s )
dcw's avatar
dcw committed
522
{
523
	paramlist p;
524
	bool first;
dcw's avatar
dcw committed
525

526 527
	if( ! d->Struct )
	{
528
		fprintf( stderr, "cons_fn: d->Struct is false!\n" );
529 530
		exit(1);
	}
531 532

	fprintf( outfile, "%s %s_%s( ", d->name, d->name, s->name );
533
	first = true;
534 535 536 537 538

	if( s->params == NULL )
	{
		fprintf( outfile, "void" );
	}
539
	for( p=s->params; p != NULL; p=p->next, first = false )
540 541 542 543 544
	{
		if( !first ) fputs( ", ", outfile );
		fprintf( outfile, "%s %s", p->type, p->name );
	}
	fputs( " )", outfile );
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562

	line( "\n{" );
	indent();
	line( "%s\tnew = NEW(%s);", d->name, d->name );
	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
563
		{
564
			if( d->Union )
dcw's avatar
dcw committed
565
			{
566 567 568 569
				/* an internal struct */
				line( "new->u.%s.%s = %s;", s->name,
					p->name, p->name );
			} else
dcw's avatar
dcw committed
570
			{
571 572
				/* only one chunk of data: this one */
				line( "new->%s = %s;", p->name, p->name );
dcw's avatar
dcw committed
573
			}
574
		}
dcw's avatar
dcw committed
575
	}
576 577 578
	line( "return new;" );
	outdent();
	line( "}\n\n" );
dcw's avatar
dcw committed
579 580 581
}


582 583 584
/* ------------------------- Deconstructors ------------------------------- */


Duncan White's avatar
Duncan White committed
585
static void decons_fns( declnlist d )
dcw's avatar
dcw committed
586
{
587 588 589 590 591 592 593 594 595
	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
596

597

Duncan White's avatar
Duncan White committed
598
static void decons_fns_type( decln d )
599 600 601
{
	shapelist	s;

602 603
	if( ! d->Struct )
	{
604
		fprintf( stderr, "decons_fns_type: d->Struct is false!\n" );
605 606
		exit(1);
	}
607 608

	if( d->ManyShapes )
dcw's avatar
dcw committed
609
	{
610 611
		/* We need a true deconstructor kind function */
		deconskind_fn( d );
dcw's avatar
dcw committed
612
	}
613 614
	/* We need (some) deconstructor functions */
	for( s = d->shapes; s != NULL; s=s->next )
dcw's avatar
dcw committed
615
	{
616 617 618 619
		if( s->params != NULL )
		{
			decons_fn( d, s );
		}
dcw's avatar
dcw committed
620 621 622 623
	}
}


624 625 626
/* ------------------- Deconstructor Kind procedure ----------------------- */


627
static void deconskind_proto( decln d, bool prot )
dcw's avatar
dcw committed
628
{
629 630 631
	if( ! d->ManyShapes )
	{
		fprintf( stderr,
632
			"deconskind_proto: d->ManyShapes is false!\n" );
633 634 635 636
		exit(1);
	}
	if( ! d->Struct )
	{
637
		fprintf( stderr, "deconskind_proto: d->Struct is false!\n" );
638 639
		exit(1);
	}
640 641 642 643 644 645 646 647 648 649

	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
650
static void deconskind_fn( decln d )
651 652 653
{
	shapelist s = d->shapes;

654 655
	if( ! d->ManyShapes )
	{
656
		fprintf( stderr, "deconskind_fn: d->ManyShapes is false!\n" );
657 658 659 660
		exit(1);
	}
	if( ! d->Struct )
	{
661
		fprintf( stderr, "deconskind_fn: d->Struct is false!\n" );
662 663
		exit(1);
	}
664

665 666
	fprintf( outfile, "kind_of_%s %s_kind( %s this )\n",
		 d->name, d->name, d->name );
dcw's avatar
dcw committed
667

668 669
	line( "{" );
	indent();
670 671 672 673 674 675 676 677 678 679 680

	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
681 682
	if( d->TagField )
	{
683
		line( "return this->tag;" );
dcw's avatar
dcw committed
684
	}
685
	else
dcw's avatar
dcw committed
686
	{
687 688 689 690 691 692 693 694 695 696
		line( "return %s_is_%s;", d->name, s->name );
	}
	outdent();
	line( "}\n\n" );
}


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


697
static void decons_fn_proto( decln d, shapelist s, bool prot )
698
{
699 700
	if( ! d->Struct )
	{
701
		fprintf( stderr, "decons_fn_proto: d->Struct is false!\n" );
702 703 704 705 706 707 708
		exit(1);
	}
	if( s->params == NULL )
	{
		fprintf( stderr, "decons_fn_proto: no fields in shape!!\n" );
		exit(1);
	}
709 710 711 712 713 714 715 716

	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
717
		{
718 719 720 721 722 723 724
			fprintf( outfile, ", %s * ", p->type );
		}
	}
	fputs( ");\n", outfile );
}


Duncan White's avatar
Duncan White committed
725
static void decons_fn( decln d, shapelist s )
726 727 728
{
	paramlist p;

729 730
	if( ! d->Struct )
	{
731
		fprintf( stderr, "decons_fn: d->Struct is false!\n" );
732 733 734 735 736 737 738
		exit(1);
	}
	if( s->params == NULL )
	{
		fprintf( stderr, "decons_fn: no fields in shape!!\n" );
		exit(1);
	}
739

740 741 742 743 744 745
	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, " )" );
746 747 748 749 750 751 752 753 754 755 756
	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
757
		{
758 759 760 761 762 763 764 765 766 767
			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
768
		}
dcw's avatar
dcw committed
769
	}
770
	outdent();
771
	line( "}\n\n" );
dcw's avatar
dcw committed
772 773 774
}


775
/* -------------------------- Print functions ----------------------------- */
dcw's avatar
dcw committed
776 777


778
static void print_fn_proto( char *name, bool prot )
dcw's avatar
dcw committed
779
{
780 781 782
	fprintf( outfile, "extern void print_%s(", name );
	if( prot )
	{
783
		fprintf( outfile, " FILE *, %s ", name );
784 785 786
	}
	fputs( ");\n", outfile );
}
dcw's avatar
dcw committed
787

788

Duncan White's avatar
Duncan White committed
789
static void print_fns( declnlist d )
790
{
dcw's avatar
dcw committed
791
	for( ; d != NULL; d = d->next )
dcw's avatar
dcw committed
792
	{
793 794
		shapelist s;

795
		line( "void print_%s( FILE *f, %s p )",d->name, d->name );
796 797
		line( "{" );
		indent();
798
		s = d->shapes;
dcw's avatar
dcw committed
799
		if( d->UseNull )
dcw's avatar
dcw committed
800
		{
dcw's avatar
dcw committed
801 802 803
			line( "if( p == NULL )" );
			line( "{" );
			indent();
804
			print_all_params( d, s );
dcw's avatar
dcw committed
805 806 807
			line( "return;" );
			outdent();
			line( "}" );
808
			s = s->next;
dcw's avatar
dcw committed
809 810 811 812 813
		}
		if( d->TagField )
		{
			line( "switch( p->tag )" );
			line( "{" );
814
			for( ; s != NULL; s = s->next )
dcw's avatar
dcw committed
815 816 817 818 819 820 821 822 823 824 825
			{
				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( "}" );
826 827
		}
		else if( ! d->TagField && d->Struct )	/* one shape left */
dcw's avatar
dcw committed
828
		{
829 830 831
			print_all_params( d, s );
		}
		else if( ! d->Struct && d->ManyShapes ) /* enumerated type */
dcw's avatar
dcw committed
832 833 834
		{
			line( "switch( p )" );
			line( "{" );
835
			for( ; s != NULL; s = s->next )
dcw's avatar
dcw committed
836
			{
dcw's avatar
dcw committed
837
				line( "case %s_%s():", d->name, s->name );
dcw's avatar
dcw committed
838 839 840 841 842 843
				indent();
				print_all_params( d, s );
				line( "break;" );
				outdent();
			}
			line( "}" );
dcw's avatar
dcw committed
844 845 846 847 848
		} else
		{
			fprintf( stderr,
				 "datadec: internal error in print_fns\n" );
			exit(1);
dcw's avatar
dcw committed
849
		}
850
		outdent();
851
		line( "}\n\n" );
dcw's avatar
dcw committed
852 853 854
	}
}

dcw's avatar
dcw committed
855

Duncan White's avatar
Duncan White committed
856
static void print_fn_shape( declnlist d, shapelist s )
dcw's avatar
dcw committed
857
{
858
	line( "case %s_is_%s:", d->name, s->name );
859 860 861 862
	indent();
	print_all_params( d, s );
	line( "break;" );
	outdent();
dcw's avatar
dcw committed
863 864 865
}


Duncan White's avatar
Duncan White committed
866
static void print_all_params( declnlist d, shapelist s )
dcw's avatar
dcw committed
867
{
868 869 870
	printlist	pl;
	paramlist	p;
	int		n;
dcw's avatar
dcw committed
871

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

				if( p == NULL )
907
				{
908
					fprintf( stderr,
909 910
	"datadec: bad printitem in shape %s of type %s\n",
	s->name, d->name );
911
					exit(1);
912
				}
913
				print_param( s, p, d->Union );
dcw's avatar
dcw committed
914 915 916
			}
		}
	}
917
}
dcw's avatar
dcw committed
918 919


920
static void print_param( shapelist s, paramlist p, bool Union )
921 922
{
	char pname[200];
dcw's avatar
dcw committed
923

924
	if( Union )
dcw's avatar
dcw committed
925
	{
926 927 928 929 930 931 932 933 934
		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 );
		}
935 936 937
	} else
	{
		sprintf( pname, "p->%s", p->name );
dcw's avatar
dcw committed
938 939
	}

940 941 942 943 944 945
	if( streq( p->type, "int" ) )
	{
		line( "fprintf( f, \"%%d\", %s );", pname );
	} else if( streq( p->type, "char" ) )
	{
		line( "fputc( %s, f );", pname );
946
	} else if( streq( p->type, "BOOL" ) || streq( p->type, "bool" ) )
947 948 949 950 951 952 953 954 955
	{
		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
956
}
957 958 959 960 961


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


962
static void free_fn_proto( char *name, bool prot )
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 1057 1058 1059 1060 1061 1062 1063
{
	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 );
	}
}


1064
static void free_param( shapelist s, paramlist p, bool Union )
1065