decs.c 8.67 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 * );
dcw's avatar
dcw committed
17
#else
dcw's avatar
dcw committed
18
19
20
21
22
23
24
25
26
27
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
28
29
30
#endif


dcw's avatar
dcw committed
31
static void init( h, c, basename ) FILE *c, *h; char *basename;
dcw's avatar
dcw committed
32
33
34
35
{
	fprintf( h, "/*\n" );
	fprintf( h, "\tAutomatically Generated by DataDec\n" );
	fprintf( h, " */\n\n");
dcw's avatar
dcw committed
36
37
	fprintf( h, "typedef char *string;\n\n" );
	fprintf( h, "typedef char BOOL;\n" );
dcw's avatar
dcw committed
38
39
	fprintf( h, "#define TRUE 1\n" );
	fprintf( h, "#define FALSE 0\n\n" );
dcw's avatar
dcw committed
40
	fprintf( h, "#define NEW(t) ((t *)malloc(sizeof(t)))\n\n\n" );
dcw's avatar
dcw committed
41
42
43
44
45

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

dcw's avatar
dcw committed
46
47
	fprintf( c, "#include <stdio.h>\n" );
	fprintf( c, "#include \"%s.h\"\n\n\n", basename );
dcw's avatar
dcw committed
48
49
50
}


dcw's avatar
dcw committed
51
static void data_decls( f, dl ) FILE *f; declnlist dl;
dcw's avatar
dcw committed
52
53
54
55
56
57
58
59
{
	declnlist d;
	char *name;
	shapelist s;
	int n;
	char *tag;
	paramlist p;

dcw's avatar
dcw committed
60
61
	for( d=dl; d; d=d->next )
	{
dcw's avatar
dcw committed
62
		fprintf( f, "typedef struct %s_str *%s;\n", d->name, d->name );
dcw's avatar
dcw committed
63
	}
dcw's avatar
dcw committed
64
65
66
	fprintf( f, "\n\n" );
	for( d=dl; d; d=d->next )
	{
dcw's avatar
dcw committed
67
68
69
		name = d->name;
		fprintf( f, "/* ---- Type %s ---- */\n\n", name );
		n = 0;
dcw's avatar
dcw committed
70
71
		for( s = d->shapes; s; s=s->next )
		{
dcw's avatar
dcw committed
72
73
74
75
76
			fprintf( f, "#define %s_%s_tag %d\n",
				name, s->tagname, n++ );
		}
		fprintf( f, "\nstruct %s_str {\n", name );
		fprintf( f, "\tint\ttag;\n" );
dcw's avatar
dcw committed
77
		fprintf( f, "\tunion {\n" );
dcw's avatar
dcw committed
78
79
		for( s = d->shapes; s; s=s->next )
		{
dcw's avatar
dcw committed
80
			if( s->params )
dcw's avatar
dcw committed
81
			{
dcw's avatar
dcw committed
82
83
84
85
86
87
88
				fprintf( f, "\t\tstruct {\n" );
				for( p = s->params; p; p=p->next )
				{
					fprintf( f, "\t\t\t%s\t%s;\n",
						p->type, p->name );
				}
				fprintf( f, "\t\t} %s;\n", s->tagname );
dcw's avatar
dcw committed
89
90
			}
		}
dcw's avatar
dcw committed
91
		fprintf( f, "\t} u;\n};\n\n" );
dcw's avatar
dcw committed
92
93
94
95
	}
}


dcw's avatar
dcw committed
96
static void one_proto( f, name, s, protos ) FILE *f; char *name; shapelist s; BOOL protos;
dcw's avatar
dcw committed
97
98
99
100
101
102
103
{
	char *tag;
	paramlist p;
	BOOL first;

	tag = s->tagname;
	fprintf( f, "extern %s %s_%s( ", name, name, tag );
dcw's avatar
dcw committed
104
105
106
107
108
109
110
	if( protos )
	{
		if( s->params == NULL )
		{
			fprintf( f, "void " );
		} else
		{
dcw's avatar
dcw committed
111
			first = TRUE;
dcw's avatar
dcw committed
112
113
			for( p = s->params; p ; p=p->next, first=FALSE )
			{
dcw's avatar
dcw committed
114
				if( !first ) fprintf( f, ", " );
dcw's avatar
dcw committed
115
				fprintf( f, "%s ", p->type );
dcw's avatar
dcw committed
116
117
118
			}
		}
	}
dcw's avatar
dcw committed
119
	fprintf( f, ");\n" );
dcw's avatar
dcw committed
120
121
122
}


dcw's avatar
dcw committed
123
static void protos( f, d, protos ) FILE *f; declnlist d; BOOL protos;
dcw's avatar
dcw committed
124
125
{
	char *name;
dcw's avatar
dcw committed
126
	declnlist dl;
dcw's avatar
dcw committed
127
128
	shapelist s;

dcw's avatar
dcw committed
129
130
131
132
133
134
	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
135
136
		}
	}
dcw's avatar
dcw committed
137
138
139
140
141
142
	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
143
144
145
}


dcw's avatar
dcw committed
146
static void cons_fn_hdr( f, name, s ) FILE *f; char *name; shapelist s;
dcw's avatar
dcw committed
147
148
149
150
151
152
153
154
{
	char *tag;
	paramlist p;
	BOOL first;

	tag = s->tagname;
	fprintf( f, "%s %s_%s( ", name, name, tag );
	first = TRUE;
dcw's avatar
dcw committed
155
156
	for( p=s->params; p; p=p->next, first=FALSE )
	{
dcw's avatar
dcw committed
157
158
159
160
		if( !first ) fprintf( f, ", " );
		fprintf( f, "%s", p->name );
	}
	fprintf( f, " ) " );
dcw's avatar
dcw committed
161
162
163
	for( p=s->params; p; p=p->next )
	{
		fprintf( f, "%s %s; ", p->type, p->name );
dcw's avatar
dcw committed
164
165
166
167
168
	}
	fputc( '\n', f );
}


dcw's avatar
dcw committed
169
static void cons_fn_body( f, name, s ) FILE *f; char *name; shapelist s;
dcw's avatar
dcw committed
170
171
172
173
174
175
176
177
{
	char *tag;
	paramlist p;

	tag = s->tagname;
	fprintf( f, "{\n\t%s new;\n\n", name );
	fprintf( f, "\tnew = NEW( struct %s_str );\n", name );
	fprintf( f, "\tnew->tag = %s_%s_tag;\n", name, tag );
dcw's avatar
dcw committed
178
179
	for( p=s->params; p; p=p->next )
	{
dcw's avatar
dcw committed
180
		fprintf( f, "\tnew->u.%s.%s = %s;\n", tag, p->name, p->name );
dcw's avatar
dcw committed
181
182
183
184
185
	}
	fprintf( f, "\treturn new;\n}\n" );
}


dcw's avatar
dcw committed
186
static void cons_fns( f, d ) FILE *f; declnlist d;
dcw's avatar
dcw committed
187
188
189
190
{
	char *name;
	shapelist s;

dcw's avatar
dcw committed
191
192
	for( ; d; d=d->next )
	{
dcw's avatar
dcw committed
193
		name = d->name;
dcw's avatar
dcw committed
194
195
196
197
		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
198
199
200
201
202
203
			fprintf( f, "\n\n" );
		}
	}
}


dcw's avatar
dcw committed
204
205
206
207
static void print_param( f, shape, ftype, fname ) FILE *f; char *shape, *ftype, *fname;
{
	char pname[200];

dcw's avatar
dcw committed
208
	sprintf( pname, "p->u.%s.%s", shape, fname );
dcw's avatar
dcw committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
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
274
275
276
277
278
279
280
	if( streq( ftype, "int" ) )
	{
		fprintf( f, "\t\tfprintf( f, \"%%d\", %s );\n", pname );
	} else if( streq( ftype, "char" ) )
	{
		fprintf( f, "\t\tfprintf( f, \"%%c\", %s );\n", pname );
	} else if( streq( ftype, "BOOL" ) )
	{
		fprintf( f, "\t\tfprintf( f, \"%%s\", %s?\"true\":\"false\" );\n",
			pname );
	} else if( streq( ftype, "string" ) )
	{
		fprintf( f, "\t\tfprintf( f, \"%%s\", %s );\n", pname );
	} else
	{
		fprintf( f, "\t\tprint_%s( f, %s );\n", ftype, pname );
	}
}


static void print_fn_shape( f, typename, s ) FILE *f; char *typename; shapelist s;
{
	printlist pl;
	paramlist p;
	int n;

	fprintf( f, "\tcase %s_%s_tag:\n", typename, s->tagname );

	if( s->pl == NULL )
	{
		for( p = s->params; p; p = p->next )
		{
			print_param( f, s->tagname, p->type, p->name );
		}
	} else
	{
		for( pl = s->pl; pl; pl = pl->next )
		{
			if( pl->item->tag == printitem_is_str )
			{
				fprintf( f, "\t\tfprintf( f, \"%s\" );\n",
					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));
				}
				print_param( f, s->tagname, p->type, p->name );
			}
		}
	}
	fprintf( f, "\t\tbreak;\n" );
}


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

	for( ; d; d = d->next )
	{
		fprintf( f, "void print_%s( f, p ) FILE *f; %s p;\n",
			d->name, d->name );
		fprintf( f, "{\n\tswitch( p->tag )\n\t{\n" );
		for( s = d->shapes; s; s = s->next )
		{
			print_fn_shape( f, d->name, s );
		}
		fprintf( f, "\tdefault:\n" );
dcw's avatar
dcw committed
281
		fprintf( f, "\t\tfprintf( stderr," );
dcw's avatar
dcw committed
282
		fprintf( f,
dcw's avatar
dcw committed
283
284
285
		" \"print_%s: impossible tag %%d\\n\", p->tag );\n",
		d->name );
		fprintf( f, "\t\texit(1);\n\t}\n}\n\n" );
dcw's avatar
dcw committed
286
287
288
	}
}

dcw's avatar
dcw committed
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
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

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
374
375
376
377
void make_declns( d, c, h, basename ) declnlist d; FILE *c, *h; char *basename;
{
	printf( "Making data declarations\n" );

dcw's avatar
dcw committed
378
	init( h, c, basename );
dcw's avatar
dcw committed
379

dcw's avatar
dcw committed
380
381
	optimize( d );

dcw's avatar
dcw committed
382
	data_decls( h, d );
dcw's avatar
dcw committed
383
384

	fprintf( h, "#ifdef HASPROTOS\n" );
dcw's avatar
dcw committed
385
	protos( h, d, TRUE );
dcw's avatar
dcw committed
386
	fprintf( h, "#else\n" );
dcw's avatar
dcw committed
387
	protos( h, d, FALSE );
dcw's avatar
dcw committed
388
389
	fprintf( h, "#endif\n" );

dcw's avatar
dcw committed
390
391
	cons_fns( c, d );
	print_fns( c, d );
dcw's avatar
dcw committed
392
}