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
}