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
}