decs.c 9.28 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
8
9
10
11
12
13
14
15
16
static void init( FILE * , FILE * , char * );
static void data_decls( FILE * , declnlist );
static void one_proto( FILE * , char * , shapelist , BOOL );
static void protos( FILE * , declnlist , BOOL );
static void cons_fn_hdr( FILE * , char * , shapelist );
static void cons_fn_body( FILE * , char * , shapelist );
static void cons_fns( FILE * , declnlist );
static void print_fns( FILE * , declnlist );
static void print_fn_shape( FILE * , char * , shapelist );
static void print_param( FILE *, char * , char * , char * );
17
18
19
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
20
#else
dcw's avatar
dcw committed
21
22
23
24
25
26
27
28
29
30
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();
31
32
33
static void count_empty_non();
static void optimize();
static void line();
dcw's avatar
dcw committed
34
35
36
#endif


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
static int numtabs = 0;
static FILE *outfile;


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

#define usefile( f ) outfile = f


/*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
58
static void init( h, c, basename ) FILE *c, *h; char *basename;
dcw's avatar
dcw committed
59
60
61
62
{
	fprintf( h, "/*\n" );
	fprintf( h, "\tAutomatically Generated by DataDec\n" );
	fprintf( h, " */\n\n");
dcw's avatar
dcw committed
63
64
	fprintf( h, "typedef char *string;\n\n" );
	fprintf( h, "typedef char BOOL;\n" );
dcw's avatar
dcw committed
65
66
	fprintf( h, "#define TRUE 1\n" );
	fprintf( h, "#define FALSE 0\n\n" );
dcw's avatar
dcw committed
67
	fprintf( h, "#define NEW(t) ((t *)malloc(sizeof(t)))\n\n\n" );
dcw's avatar
dcw committed
68
69
70
71
72

	fprintf( c, "/*\n" );
	fprintf( c, "\tAutomatically Generated by DataDec\n" );
	fprintf( c, " */\n\n");

dcw's avatar
dcw committed
73
74
	fprintf( c, "#include <stdio.h>\n" );
	fprintf( c, "#include \"%s.h\"\n\n\n", basename );
75
76

	numtabs = 0;
dcw's avatar
dcw committed
77
78
79
}


dcw's avatar
dcw committed
80
static void data_decls( f, dl ) FILE *f; declnlist dl;
dcw's avatar
dcw committed
81
82
83
84
85
86
87
88
{
	declnlist d;
	char *name;
	shapelist s;
	int n;
	char *tag;
	paramlist p;

dcw's avatar
dcw committed
89
90
	for( d=dl; d; d=d->next )
	{
dcw's avatar
dcw committed
91
		fprintf( f, "typedef struct %s_str *%s;\n", d->name, d->name );
dcw's avatar
dcw committed
92
	}
dcw's avatar
dcw committed
93
94
95
	fprintf( f, "\n\n" );
	for( d=dl; d; d=d->next )
	{
dcw's avatar
dcw committed
96
97
98
		name = d->name;
		fprintf( f, "/* ---- Type %s ---- */\n\n", name );
		n = 0;
dcw's avatar
dcw committed
99
100
		for( s = d->shapes; s; s=s->next )
		{
dcw's avatar
dcw committed
101
102
103
			fprintf( f, "#define %s_%s_tag %d\n",
				name, s->tagname, n++ );
		}
104
105
106
107
108
109
110
111
112
113
		fputc( '\n', f );

		usefile( f );
		numtabs = 0;

		line( "struct %s_str {", name );
		indent();
		line( "int\ttag;" );
		line( "union {" );
		indent();
dcw's avatar
dcw committed
114
115
		for( s = d->shapes; s; s=s->next )
		{
dcw's avatar
dcw committed
116
			if( s->params )
dcw's avatar
dcw committed
117
			{
118
119
				line( "struct {" );
				indent();
dcw's avatar
dcw committed
120
121
				for( p = s->params; p; p=p->next )
				{
122
					line( "%s\t%s;",
dcw's avatar
dcw committed
123
124
						p->type, p->name );
				}
125
126
				outdent();
				line( "} %s;", s->tagname );
dcw's avatar
dcw committed
127
128
			}
		}
129
130
131
132
		outdent();
		line( "} u;" );
		outdent();
		line( "};\n" );
dcw's avatar
dcw committed
133
134
135
136
	}
}


dcw's avatar
dcw committed
137
static void one_proto( f, name, s, protos ) FILE *f; char *name; shapelist s; BOOL protos;
dcw's avatar
dcw committed
138
139
140
141
142
143
144
{
	char *tag;
	paramlist p;
	BOOL first;

	tag = s->tagname;
	fprintf( f, "extern %s %s_%s( ", name, name, tag );
dcw's avatar
dcw committed
145
146
147
148
149
150
151
	if( protos )
	{
		if( s->params == NULL )
		{
			fprintf( f, "void " );
		} else
		{
dcw's avatar
dcw committed
152
			first = TRUE;
dcw's avatar
dcw committed
153
154
			for( p = s->params; p ; p=p->next, first=FALSE )
			{
dcw's avatar
dcw committed
155
				if( !first ) fprintf( f, ", " );
dcw's avatar
dcw committed
156
				fprintf( f, "%s ", p->type );
dcw's avatar
dcw committed
157
158
159
			}
		}
	}
dcw's avatar
dcw committed
160
	fprintf( f, ");\n" );
dcw's avatar
dcw committed
161
162
163
}


dcw's avatar
dcw committed
164
static void protos( f, d, protos ) FILE *f; declnlist d; BOOL protos;
dcw's avatar
dcw committed
165
166
{
	char *name;
dcw's avatar
dcw committed
167
	declnlist dl;
dcw's avatar
dcw committed
168
169
	shapelist s;

dcw's avatar
dcw committed
170
171
172
173
174
175
	for( dl=d; dl; dl = dl->next )
	{
		name = dl->name;
		for( s = dl->shapes; s; s=s->next )
		{
			one_proto( f, name, s, protos );
dcw's avatar
dcw committed
176
177
		}
	}
dcw's avatar
dcw committed
178
179
180
181
182
183
	for( dl=d; dl; dl = dl->next )
	{
		fprintf( f, "extern void print_%s( ", dl->name );
		if( protos ) fprintf( f, "%s ", dl->name );
		fprintf( f, ");\n" );
	}
dcw's avatar
dcw committed
184
185
186
}


dcw's avatar
dcw committed
187
static void cons_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
dcw's avatar
dcw committed
188
189
190
191
192
193
194
195
{
	char *tag;
	paramlist p;
	BOOL first;

	tag = s->tagname;
	fprintf( f, "%s %s_%s( ", name, name, tag );
	first = TRUE;
dcw's avatar
dcw committed
196
197
	for( p=s->params; p; p=p->next, first=FALSE )
	{
dcw's avatar
dcw committed
198
199
200
201
		if( !first ) fprintf( f, ", " );
		fprintf( f, "%s", p->name );
	}
	fprintf( f, " ) " );
dcw's avatar
dcw committed
202
203
204
	for( p=s->params; p; p=p->next )
	{
		fprintf( f, "%s %s; ", p->type, p->name );
dcw's avatar
dcw committed
205
206
207
208
209
	}
	fputc( '\n', f );
}


dcw's avatar
dcw committed
210
static void cons_fn_body( f, name, s ) FILE *f; char *name; shapelist s;
dcw's avatar
dcw committed
211
212
213
214
215
{
	char *tag;
	paramlist p;

	tag = s->tagname;
216
217
218
219
220
221
222
223
224

	numtabs = 0;
	usefile( f );

	line( "{" );
	indent();
	line( "%s new;\n", name );
	line( "new = NEW( struct %s_str );", name );
	line( "new->tag = %s_%s_tag;", name, tag );
dcw's avatar
dcw committed
225
226
	for( p=s->params; p; p=p->next )
	{
227
		line( "new->u.%s.%s = %s;", tag, p->name, p->name );
dcw's avatar
dcw committed
228
	}
229
230
231
	line( "return new;" );
	outdent();
	line( "}" );
dcw's avatar
dcw committed
232
233
234
}


dcw's avatar
dcw committed
235
static void cons_fns( f, d ) FILE *f; declnlist d;
dcw's avatar
dcw committed
236
237
238
239
{
	char *name;
	shapelist s;

dcw's avatar
dcw committed
240
241
	for( ; d; d=d->next )
	{
dcw's avatar
dcw committed
242
		name = d->name;
dcw's avatar
dcw committed
243
244
245
246
		for( s = d->shapes; s; s=s->next )
		{
			cons_fn_hdr( f, name, s );
			cons_fn_body( f, name, s );
dcw's avatar
dcw committed
247
248
249
250
251
252
			fprintf( f, "\n\n" );
		}
	}
}


253
static void print_param( shape, ftype, fname ) char *shape, *ftype, *fname;
dcw's avatar
dcw committed
254
255
256
{
	char pname[200];

dcw's avatar
dcw committed
257
	sprintf( pname, "p->u.%s.%s", shape, fname );
dcw's avatar
dcw committed
258
259
	if( streq( ftype, "int" ) )
	{
260
		line( "fprintf( f, \"%%d\", %s );", pname );
dcw's avatar
dcw committed
261
262
	} else if( streq( ftype, "char" ) )
	{
263
		line( "fprintf( f, \"%%c\", %s );", pname );
dcw's avatar
dcw committed
264
265
	} else if( streq( ftype, "BOOL" ) )
	{
266
		line( "fprintf( f, \"%%s\", %s?\"true\":\"false\" );",
dcw's avatar
dcw committed
267
268
269
			pname );
	} else if( streq( ftype, "string" ) )
	{
270
		line( "fprintf( f, \"%%s\", %s );", pname );
dcw's avatar
dcw committed
271
272
	} else
	{
273
		line( "print_%s( f, %s );", ftype, pname );
dcw's avatar
dcw committed
274
275
276
277
	}
}


278
static void print_fn_shape( typename, s ) char *typename; shapelist s;
dcw's avatar
dcw committed
279
280
281
282
283
{
	printlist pl;
	paramlist p;
	int n;

284
	line( "case %s_%s_tag:", typename, s->tagname );
dcw's avatar
dcw committed
285

286
	indent();
dcw's avatar
dcw committed
287
288
289
290
	if( s->pl == NULL )
	{
		for( p = s->params; p; p = p->next )
		{
291
			print_param( s->tagname, p->type, p->name );
dcw's avatar
dcw committed
292
293
294
295
296
297
298
		}
	} else
	{
		for( pl = s->pl; pl; pl = pl->next )
		{
			if( pl->item->tag == printitem_is_str )
			{
299
				line( "fprintf( f, \"%s\" );",
dcw's avatar
dcw committed
300
301
302
303
304
305
306
307
308
					pl->item->str );
			} else
			{
				n = pl->item->num;
				for( p = s->params; --n; p = p->next )
				{
					ASSERT( p != NULL,
("datadec: bad printitem in shape %s of type %s\n",s->tagname,typename));
				}
309
				print_param( s->tagname, p->type, p->name );
dcw's avatar
dcw committed
310
311
312
			}
		}
	}
313
314
	line( "break;" );
	outdent();
dcw's avatar
dcw committed
315
316
317
318
319
320
321
}


static void print_fns( f, d ) FILE *f ; declnlist d;
{
	shapelist s;

322
323
324
	usefile( f );
	numtabs = 0;

dcw's avatar
dcw committed
325
326
	for( ; d; d = d->next )
	{
327
328
329
330
331
		line( "void print_%s( f, p ) FILE *f; %s p;",d->name, d->name );
		line( "{" );
		indent();
		line( "switch( p->tag )" );
		line( "{" );
dcw's avatar
dcw committed
332
333
		for( s = d->shapes; s; s = s->next )
		{
334
			print_fn_shape( d->name, s );
dcw's avatar
dcw committed
335
		}
336
337
338
339
340
341
342
343
344
345
		line( "default:" );
		indent();
		line( "fprintf( stderr," );
		line( " \"print_%s: impossible tag %%d\\n\", p->tag );",
			d->name );
		line( "exit(1);" );
		outdent();
		line( "}" );
		outdent();
		line( "}\n" );
dcw's avatar
dcw committed
346
347
348
	}
}

dcw's avatar
dcw committed
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
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
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

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 )
	{
		count_empty_non( d->shapes, &e, &ne );
		t = e+ne;

		d->Defines = d->TagField = d->Struct =
		d->Union = d->UseNull = FALSE;

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

		if( t==1 && ne==1 )
/* ONE, NON EMPTY, eg. 'data x = fred(string z)' */
		{
			d->Struct = TRUE;
			/* !Defines, !TagField, !Union, !UseNull */
		} else if( t>1 && ne==0 )
/* >1, ALL EMPTY, eg. 'data x = a | b | c | d | e' */
		{
			d->Defines = TRUE;
			/* !TagField, !Struct, !Union, !UseNull */
		} else if( d->shapes->params == NULL ) /* 1st is empty */
		{
			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 )
			{
/* >TWO, 1ST EMPTY, ONLY ONE NE, eg. 'data x = a | b | c(char z) | d | e' */
				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;
			}
		} else
/* ELSE */
		{
			d->Defines = d->TagField = d->Struct =
			d->Union = TRUE;
		}
		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) );

#define eek(x)	( (x)?' ':'~')
		printf( "type %s: %cDefines, %cTagField, %cStruct, %cUnion, %cUseNull\n",
			d->name, eek(d->Defines), eek(d->TagField),
			eek(d->Struct), eek(d->Union), eek(d->UseNull)
		);
	}
}


dcw's avatar
dcw committed
434
435
436
437
void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
{
	printf( "Making data declarations\n" );

dcw's avatar
dcw committed
438
	init( h, c, basename );
dcw's avatar
dcw committed
439

dcw's avatar
dcw committed
440
441
	optimize( d );

dcw's avatar
dcw committed
442
	data_decls( h, d );
dcw's avatar
dcw committed
443
444

	fprintf( h, "#ifdef HASPROTOS\n" );
dcw's avatar
dcw committed
445
	protos( h, d, TRUE );
dcw's avatar
dcw committed
446
	fprintf( h, "#else\n" );
dcw's avatar
dcw committed
447
	protos( h, d, FALSE );
dcw's avatar
dcw committed
448
449
	fprintf( h, "#endif\n" );

dcw's avatar
dcw committed
450
451
	cons_fns( c, d );
	print_fns( c, d );
dcw's avatar
dcw committed
452
}