Subversion Repositories HelenOS

Rev

Rev 2714 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2714 cejka 1
/*  $NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $ */
2
 
3
/*-
4
 * Copyright (c) 1991, 1993
5
 *  The Regents of the University of California.  All rights reserved.
6
 *
7
 * This code is derived from software contributed to Berkeley by
8
 * Kenneth Almquist.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. All advertising materials mentioning features or use of this software
19
 *    must display the following acknowledgement:
20
 *  This product includes software developed by the University of
21
 *  California, Berkeley and its contributors.
22
 * 4. Neither the name of the University nor the names of its contributors
23
 *    may be used to endorse or promote products derived from this software
24
 *    without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
 * SUCH DAMAGE.
37
 */
38
 
39
#ifndef lint
40
static const char copyright[] =
41
    "@(#) Copyright (c) 1991, 1993\n\
42
    The Regents of the University of California.  All rights reserved.\n";
43
#endif /* not lint */
44
 
45
#ifndef lint
46
#if 0
47
static char sccsid[] = "@(#)mknodes.c   8.2 (Berkeley) 5/4/95";
48
#else
49
static const char rcsid[] =
50
    "$NetBSD: mknodes.c,v 1.18 2000/07/27 04:06:49 cgd Exp $";
51
#endif
52
#endif /* not lint */
53
 
54
/*
55
 * This program reads the nodetypes file and nodes.c.pat file.  It generates
56
 * the files nodes.h and nodes.c.
57
 */
58
 
59
#include <stdio.h>
60
#include <stdlib.h>
61
#include <string.h>
62
#ifdef __STDC__
63
#include <stdarg.h>
64
#else
65
#include <varargs.h>
66
#endif
67
 
68
 
69
#define MAXTYPES 50     /* max number of node types */
70
#define MAXFIELDS 20        /* max fields in a structure */
71
#define BUFLEN 100      /* size of character buffers */
72
 
73
/* field types */
74
#define T_NODE 1        /* union node *field */
75
#define T_NODELIST 2        /* struct nodelist *field */
76
#define T_STRING 3
77
#define T_INT 4         /* int field */
78
#define T_OTHER 5       /* other */
79
#define T_TEMP 6        /* don't copy this field */
80
 
81
 
82
struct field {          /* a structure field */
83
    char *name;     /* name of field */
84
    int type;           /* type of field */
85
    char *decl;     /* declaration of field */
86
};
87
 
88
 
89
struct str {            /* struct representing a node structure */
90
    char *tag;      /* structure tag */
91
    int nfields;        /* number of fields in the structure */
92
    struct field field[MAXFIELDS];  /* the fields of the structure */
93
    int done;           /* set if fully parsed */
94
};
95
 
96
 
97
static int ntypes;          /* number of node types */
98
static char *nodename[MAXTYPES];    /* names of the nodes */
99
static struct str *nodestr[MAXTYPES];   /* type of structure used by the node */
100
static int nstr;            /* number of structures */
101
static struct str str[MAXTYPES];    /* the structures */
102
static struct str *curstr;      /* current structure */
103
static FILE *infp;
104
static char line[1024];
105
static int linno;
106
static char *linep;
107
 
108
static void parsenode(void);
109
static void parsefield(void);
110
static void output(char *);
111
static void outsizes(FILE *);
112
static void outfunc(FILE *, int);
113
static void indent(int, FILE *);
114
static int nextfield(char *);
115
static void skipbl(void);
116
static int readline(void);
117
static void error(const char *, ...);
118
static char *savestr(const char *);
119
int main(int, char **);
120
 
121
 
122
int
123
main(argc, argv)
124
    int argc;
125
    char **argv;
126
{
127
 
128
    /*
129
     * some versions of linux complain: initializer element is not
130
     * constant if this is done at compile time.
131
     */
132
    infp = stdin;
133
 
134
    if (argc != 3)
135
        error("usage: mknodes file");
136
    if ((infp = fopen(argv[1], "r")) == NULL)
137
        error("Can't open %s", argv[1]);
138
    while (readline()) {
139
        if (line[0] == ' ' || line[0] == '\t')
140
            parsefield();
141
        else if (line[0] != '\0')
142
            parsenode();
143
    }
144
    output(argv[2]);
145
    exit(0);
146
    /* NOTREACHED */
147
}
148
 
149
 
150
 
151
static void
152
parsenode()
153
{
154
    char name[BUFLEN];
155
    char tag[BUFLEN];
156
    struct str *sp;
157
 
158
    if (curstr && curstr->nfields > 0)
159
        curstr->done = 1;
160
    nextfield(name);
161
    if (! nextfield(tag))
162
        error("Tag expected");
163
    if (*linep != '\0')
164
        error("Garbage at end of line");
165
    nodename[ntypes] = savestr(name);
166
    for (sp = str ; sp < str + nstr ; sp++) {
167
        if (strcmp(sp->tag, tag) == 0)
168
            break;
169
    }
170
    if (sp >= str + nstr) {
171
        sp->tag = savestr(tag);
172
        sp->nfields = 0;
173
        curstr = sp;
174
        nstr++;
175
    }
176
    nodestr[ntypes] = sp;
177
    ntypes++;
178
}
179
 
180
 
181
static void
182
parsefield()
183
{
184
    char name[BUFLEN];
185
    char type[BUFLEN];
186
    char decl[2 * BUFLEN];
187
    struct field *fp;
188
 
189
    if (curstr == NULL || curstr->done)
190
        error("No current structure to add field to");
191
    if (! nextfield(name))
192
        error("No field name");
193
    if (! nextfield(type))
194
        error("No field type");
195
    fp = &curstr->field[curstr->nfields];
196
    fp->name = savestr(name);
197
    if (strcmp(type, "nodeptr") == 0) {
198
        fp->type = T_NODE;
199
        sprintf(decl, "union node *%s", name);
200
    } else if (strcmp(type, "nodelist") == 0) {
201
        fp->type = T_NODELIST;
202
        sprintf(decl, "struct nodelist *%s", name);
203
    } else if (strcmp(type, "string") == 0) {
204
        fp->type = T_STRING;
205
        sprintf(decl, "char *%s", name);
206
    } else if (strcmp(type, "int") == 0) {
207
        fp->type = T_INT;
208
        sprintf(decl, "int %s", name);
209
    } else if (strcmp(type, "other") == 0) {
210
        fp->type = T_OTHER;
211
    } else if (strcmp(type, "temp") == 0) {
212
        fp->type = T_TEMP;
213
    } else {
214
        error("Unknown type %s", type);
215
    }
216
    if (fp->type == T_OTHER || fp->type == T_TEMP) {
217
        skipbl();
218
        fp->decl = savestr(linep);
219
    } else {
220
        if (*linep)
221
            error("Garbage at end of line");
222
        fp->decl = savestr(decl);
223
    }
224
    curstr->nfields++;
225
}
226
 
227
 
228
char writer[] = "\
229
/*\n\
230
 * This file was generated by the mknodes program.\n\
231
 */\n\
232
\n";
233
 
234
static void
235
output(file)
236
    char *file;
237
{
238
    FILE *hfile;
239
    FILE *cfile;
240
    FILE *patfile;
241
    int i;
242
    struct str *sp;
243
    struct field *fp;
244
    char *p;
245
 
246
    if ((patfile = fopen(file, "r")) == NULL)
247
        error("Can't open %s", file);
248
    if ((hfile = fopen("nodes.h", "w")) == NULL)
249
        error("Can't create nodes.h");
250
    if ((cfile = fopen("nodes.c", "w")) == NULL)
251
        error("Can't create nodes.c");
252
    fputs(writer, hfile);
253
    for (i = 0 ; i < ntypes ; i++)
254
        fprintf(hfile, "#define %s %d\n", nodename[i], i);
255
    fputs("\n\n\n", hfile);
256
    for (sp = str ; sp < &str[nstr] ; sp++) {
257
        fprintf(hfile, "struct %s {\n", sp->tag);
258
        for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
259
            fprintf(hfile, "      %s;\n", fp->decl);
260
        }
261
        fputs("};\n\n\n", hfile);
262
    }
263
    fputs("union node {\n", hfile);
264
    fprintf(hfile, "      int type;\n");
265
    for (sp = str ; sp < &str[nstr] ; sp++) {
266
        fprintf(hfile, "      struct %s %s;\n", sp->tag, sp->tag);
267
    }
268
    fputs("};\n\n\n", hfile);
269
    fputs("struct nodelist {\n", hfile);
270
    fputs("\tstruct nodelist *next;\n", hfile);
271
    fputs("\tunion node *n;\n", hfile);
272
    fputs("};\n\n\n", hfile);
273
    fputs("#ifdef __STDC__\n", hfile);
274
    fputs("union node *copyfunc(union node *);\n", hfile);
275
    fputs("void freefunc(union node *);\n", hfile);
276
    fputs("#else\n", hfile);
277
    fputs("union node *copyfunc();\n", hfile);
278
    fputs("void freefunc();\n", hfile);
279
    fputs("#endif\n", hfile);
280
 
281
    fputs(writer, cfile);
282
    while (fgets(line, sizeof line, patfile) != NULL) {
283
        for (p = line ; *p == ' ' || *p == '\t' ; p++);
284
        if (strcmp(p, "%SIZES\n") == 0)
285
            outsizes(cfile);
286
        else if (strcmp(p, "%CALCSIZE\n") == 0)
287
            outfunc(cfile, 1);
288
        else if (strcmp(p, "%COPY\n") == 0)
289
            outfunc(cfile, 0);
290
        else
291
            fputs(line, cfile);
292
    }
293
}
294
 
295
 
296
 
297
static void
298
outsizes(cfile)
299
    FILE *cfile;
300
{
301
    int i;
302
 
303
    fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
304
    for (i = 0 ; i < ntypes ; i++) {
305
        fprintf(cfile, "      ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
306
    }
307
    fprintf(cfile, "};\n");
308
}
309
 
310
 
311
static void
312
outfunc(cfile, calcsize)
313
    FILE *cfile;
314
    int calcsize;
315
{
316
    struct str *sp;
317
    struct field *fp;
318
    int i;
319
 
320
    fputs("      if (n == NULL)\n", cfile);
321
    if (calcsize)
322
        fputs("     return;\n", cfile);
323
    else
324
        fputs("     return NULL;\n", cfile);
325
    if (calcsize)
326
        fputs("      funcblocksize += nodesize[n->type];\n", cfile);
327
    else {
328
        fputs("      new = funcblock;\n", cfile);
329
        fputs("      funcblock = (char *) funcblock + nodesize[n->type];\n", cfile);
330
    }
331
    fputs("      switch (n->type) {\n", cfile);
332
    for (sp = str ; sp < &str[nstr] ; sp++) {
333
        for (i = 0 ; i < ntypes ; i++) {
334
            if (nodestr[i] == sp)
335
                fprintf(cfile, "      case %s:\n", nodename[i]);
336
        }
337
        for (i = sp->nfields ; --i >= 1 ; ) {
338
            fp = &sp->field[i];
339
            switch (fp->type) {
340
            case T_NODE:
341
                if (calcsize) {
342
                    indent(12, cfile);
343
                    fprintf(cfile, "calcsize(n->%s.%s);\n",
344
                        sp->tag, fp->name);
345
                } else {
346
                    indent(12, cfile);
347
                    fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
348
                        sp->tag, fp->name, sp->tag, fp->name);
349
                }
350
                break;
351
            case T_NODELIST:
352
                if (calcsize) {
353
                    indent(12, cfile);
354
                    fprintf(cfile, "sizenodelist(n->%s.%s);\n",
355
                        sp->tag, fp->name);
356
                } else {
357
                    indent(12, cfile);
358
                    fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
359
                        sp->tag, fp->name, sp->tag, fp->name);
360
                }
361
                break;
362
            case T_STRING:
363
                if (calcsize) {
364
                    indent(12, cfile);
365
                    fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
366
                        sp->tag, fp->name);
367
                } else {
368
                    indent(12, cfile);
369
                    fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
370
                        sp->tag, fp->name, sp->tag, fp->name);
371
                }
372
                break;
373
            case T_INT:
374
            case T_OTHER:
375
                if (! calcsize) {
376
                    indent(12, cfile);
377
                    fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
378
                        sp->tag, fp->name, sp->tag, fp->name);
379
                }
380
                break;
381
            }
382
        }
383
        indent(12, cfile);
384
        fputs("break;\n", cfile);
385
    }
386
    fputs("      };\n", cfile);
387
    if (! calcsize)
388
        fputs("      new->type = n->type;\n", cfile);
389
}
390
 
391
 
392
static void
393
indent(amount, fp)
394
    int amount;
395
    FILE *fp;
396
{
397
    while (amount >= 8) {
398
        putc('\t', fp);
399
        amount -= 8;
400
    }
401
    while (--amount >= 0) {
402
        putc(' ', fp);
403
    }
404
}
405
 
406
 
407
static int
408
nextfield(buf)
409
    char *buf;
410
{
411
    char *p, *q;
412
 
413
    p = linep;
414
    while (*p == ' ' || *p == '\t')
415
        p++;
416
    q = buf;
417
    while (*p != ' ' && *p != '\t' && *p != '\0')
418
        *q++ = *p++;
419
    *q = '\0';
420
    linep = p;
421
    return (q > buf);
422
}
423
 
424
 
425
static void
426
skipbl()
427
{
428
    while (*linep == ' ' || *linep == '\t')
429
        linep++;
430
}
431
 
432
 
433
static int
434
readline()
435
{
436
    char *p;
437
 
438
    if (fgets(line, 1024, infp) == NULL)
439
        return 0;
440
    for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
441
    while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
442
        p--;
443
    *p = '\0';
444
    linep = line;
445
    linno++;
446
    if (p - line > BUFLEN)
447
        error("Line too long");
448
    return 1;
449
}
450
 
451
 
452
 
453
static void
454
#ifdef __STDC__
455
error(const char *msg, ...)
456
#else
457
error(va_alist)
458
    va_dcl
459
#endif
460
{
461
    va_list va;
462
#ifdef __STDC__
463
    va_start(va, msg);
464
#else
465
    char *msg;
466
    va_start(va);
467
    msg = va_arg(va, char *);
468
#endif
469
 
470
    (void) fprintf(stderr, "line %d: ", linno);
471
    (void) vfprintf(stderr, msg, va);
472
    (void) fputc('\n', stderr);
473
 
474
    va_end(va);
475
 
476
    exit(2);
477
    /* NOTREACHED */
478
}
479
 
480
 
481
 
482
static char *
483
savestr(s)
484
    const char *s;
485
{
486
    char *p;
487
 
488
    if ((p = malloc(strlen(s) + 1)) == NULL)
489
        error("Out of space");
490
    (void) strcpy(p, s);
491
    return p;
492
}