Subversion Repositories HelenOS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2714 cejka 1
/*  $NetBSD: mkinit.c,v 1.20 2000/07/18 19:13:20 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
 
40
#ifndef lint
41
static const char copyright[] =
42
    "@(#) Copyright (c) 1991, 1993\n\
43
    The Regents of the University of California.  All rights reserved.\n";
44
#endif /* not lint */
45
 
46
#ifndef lint
47
#if 0
48
static char sccsid[] = "@(#)mkinit.c    8.2 (Berkeley) 5/4/95";
49
#else
50
static const char rcsid[] =
51
    "$NetBSD: mkinit.c,v 1.20 2000/07/18 19:13:20 cgd Exp $";
52
#endif
53
#endif /* not lint */
54
 
55
/*
56
 * This program scans all the source files for code to handle various
57
 * special events and combines this code into one file.  This (allegedly)
58
 * improves the structure of the program since there is no need for
59
 * anyone outside of a module to know that that module performs special
60
 * operations on particular events.
61
 *
62
 * Usage:  mkinit sourcefile...
63
 */
64
 
65
#include <sys/types.h>
66
#include <stdio.h>
67
#include <stdlib.h>
68
#include <string.h>
69
#include <fcntl.h>
70
#include <unistd.h>
71
 
72
 
73
/*
74
 * OUTFILE is the name of the output file.  Output is initially written
75
 * to the file OUTTEMP, which is then moved to OUTFILE.
76
 */
77
 
78
#define OUTFILE "init.c"
79
#define OUTTEMP "init.c.new"
80
 
81
 
82
/*
83
 * A text structure is basicly just a string that grows as more characters
84
 * are added onto the end of it.  It is implemented as a linked list of
85
 * blocks of characters.  The routines addstr and addchar append a string
86
 * or a single character, respectively, to a text structure.  Writetext
87
 * writes the contents of a text structure to a file.
88
 */
89
 
90
#define BLOCKSIZE 512
91
 
92
struct text {
93
    char *nextc;
94
    int nleft;
95
    struct block *start;
96
    struct block *last;
97
};
98
 
99
struct block {
100
    struct block *next;
101
    char text[BLOCKSIZE];
102
};
103
 
104
 
105
/*
106
 * There is one event structure for each event that mkinit handles.
107
 */
108
 
109
struct event {
110
    char *name;     /* name of event (e.g. INIT) */
111
    char *routine;      /* name of routine called on event */
112
    char *comment;      /* comment describing routine */
113
    struct text code;   /* code for handling event */
114
};
115
 
116
 
117
char writer[] = "\
118
/*\n\
119
 * This file was generated by the mkinit program.\n\
120
 */\n\
121
\n";
122
 
123
char init[] = "\
124
/*\n\
125
 * Initialization code.\n\
126
 */\n";
127
 
128
char reset[] = "\
129
/*\n\
130
 * This routine is called when an error or an interrupt occurs in an\n\
131
 * interactive shell and control is returned to the main command loop.\n\
132
 */\n";
133
 
134
char shellproc[] = "\
135
/*\n\
136
 * This routine is called to initialize the shell to run a shell procedure.\n\
137
 */\n";
138
 
139
 
140
struct event event[] = {
141
    {"INIT", "init", init},
142
    {"RESET", "reset", reset},
143
    {"SHELLPROC", "initshellproc", shellproc},
144
    {NULL, NULL}
145
};
146
 
147
 
148
char *curfile;              /* current file */
149
int linno;              /* current line */
150
char *header_files[200];        /* list of header files */
151
struct text defines;            /* #define statements */
152
struct text decls;          /* declarations */
153
int amiddecls;              /* for formatting */
154
 
155
 
156
void readfile(char *);
157
int match(char *, char *);
158
int gooddefine(char *);
159
void doevent(struct event *, FILE *, char *);
160
void doinclude(char *);
161
void dodecl(char *, FILE *);
162
void output(void);
163
void addstr(char *, struct text *);
164
void addchar(int, struct text *);
165
void writetext(struct text *, FILE *);
166
FILE *ckfopen(char *, char *);
167
void *ckmalloc(int);
168
char *savestr(char *);
169
void error(char *);
170
int main(int, char **);
171
 
172
#define equal(s1, s2)   (strcmp(s1, s2) == 0)
173
 
174
int
175
main(argc, argv)
176
    int argc;
177
    char **argv;
178
{
179
    char **ap;
180
 
181
    header_files[0] = "\"shell.h\"";
182
    header_files[1] = "\"mystring.h\"";
183
    header_files[2] = "\"init.h\"";
184
    for (ap = argv + 1 ; *ap ; ap++)
185
        readfile(*ap);
186
    output();
187
    rename(OUTTEMP, OUTFILE);
188
    exit(0);
189
    /* NOTREACHED */
190
}
191
 
192
 
193
/*
194
 * Parse an input file.
195
 */
196
 
197
void
198
readfile(fname)
199
    char *fname;
200
    {
201
    FILE *fp;
202
    char line[1024];
203
    struct event *ep;
204
 
205
    fp = ckfopen(fname, "r");
206
    curfile = fname;
207
    linno = 0;
208
    amiddecls = 0;
209
    while (fgets(line, sizeof line, fp) != NULL) {
210
        linno++;
211
        for (ep = event ; ep->name ; ep++) {
212
            if (line[0] == ep->name[0] && match(ep->name, line)) {
213
                doevent(ep, fp, fname);
214
                break;
215
            }
216
        }
217
        if (line[0] == 'I' && match("INCLUDE", line))
218
            doinclude(line);
219
        if (line[0] == 'M' && match("MKINIT", line))
220
            dodecl(line, fp);
221
        if (line[0] == '#' && gooddefine(line))
222
            addstr(line, &defines);
223
        if (line[0] == '#' && gooddefine(line)) {
224
                char *cp;
225
            char line2[1024];
226
            static const char undef[] = "#undef ";
227
 
228
            strcpy(line2, line);
229
            memcpy(line2, undef, sizeof(undef) - 1);
230
            cp = line2 + sizeof(undef) - 1;
231
            while(*cp && (*cp == ' ' || *cp == '\t'))
232
                    cp++;
233
            while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
234
                    cp++;
235
            *cp++ = '\n'; *cp = '\0';
236
            addstr(line2, &defines);
237
            addstr(line, &defines);
238
        }
239
    }
240
    fclose(fp);
241
}
242
 
243
 
244
int
245
match(name, line)
246
    char *name;
247
    char *line;
248
{
249
    char *p, *q;
250
 
251
    p = name, q = line;
252
    while (*p) {
253
        if (*p++ != *q++)
254
            return 0;
255
    }
256
    if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
257
        return 0;
258
    return 1;
259
}
260
 
261
 
262
int
263
gooddefine(line)
264
    char *line;
265
{
266
    char *p;
267
 
268
    if (! match("#define", line))
269
        return 0;           /* not a define */
270
    p = line + 7;
271
    while (*p == ' ' || *p == '\t')
272
        p++;
273
    while (*p != ' ' && *p != '\t') {
274
        if (*p == '(')
275
            return 0;       /* macro definition */
276
        p++;
277
    }
278
    while (*p != '\n' && *p != '\0')
279
        p++;
280
    if (p[-1] == '\\')
281
        return 0;           /* multi-line definition */
282
    return 1;
283
}
284
 
285
 
286
void
287
doevent(ep, fp, fname)
288
    struct event *ep;
289
    FILE *fp;
290
    char *fname;
291
    {
292
    char line[1024];
293
    int indent;
294
    char *p;
295
 
296
    sprintf(line, "\n      /* from %s: */\n", fname);
297
    addstr(line, &ep->code);
298
    addstr("      {\n", &ep->code);
299
    for (;;) {
300
        linno++;
301
        if (fgets(line, sizeof line, fp) == NULL)
302
            error("Unexpected EOF");
303
        if (equal(line, "}\n"))
304
            break;
305
        indent = 6;
306
        for (p = line ; *p == '\t' ; p++)
307
            indent += 8;
308
        for ( ; *p == ' ' ; p++)
309
            indent++;
310
        if (*p == '\n' || *p == '#')
311
            indent = 0;
312
        while (indent >= 8) {
313
            addchar('\t', &ep->code);
314
            indent -= 8;
315
        }
316
        while (indent > 0) {
317
            addchar(' ', &ep->code);
318
            indent--;
319
        }
320
        addstr(p, &ep->code);
321
    }
322
    addstr("      }\n", &ep->code);
323
}
324
 
325
 
326
void
327
doinclude(line)
328
    char *line;
329
    {
330
    char *p;
331
    char *name;
332
    char **pp;
333
 
334
    for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
335
    if (*p == '\0')
336
        error("Expecting '\"' or '<'");
337
    name = p;
338
    while (*p != ' ' && *p != '\t' && *p != '\n')
339
        p++;
340
    if (p[-1] != '"' && p[-1] != '>')
341
        error("Missing terminator");
342
    *p = '\0';
343
 
344
    /* name now contains the name of the include file */
345
    for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
346
    if (*pp == NULL)
347
        *pp = savestr(name);
348
}
349
 
350
 
351
void
352
dodecl(line1, fp)
353
    char *line1;
354
    FILE *fp;
355
    {
356
    char line[1024];
357
    char *p, *q;
358
 
359
    if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
360
        addchar('\n', &decls);
361
        do {
362
            linno++;
363
            if (fgets(line, sizeof line, fp) == NULL)
364
                error("Unterminated structure declaration");
365
            addstr(line, &decls);
366
        } while (line[0] != '}');
367
        amiddecls = 0;
368
    } else {
369
        if (! amiddecls)
370
            addchar('\n', &decls);
371
        q = NULL;
372
        for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
373
            continue;
374
        if (*p == '=') {        /* eliminate initialization */
375
            for (q = p ; *q && *q != ';' ; q++);
376
            if (*q == '\0')
377
                q = NULL;
378
            else {
379
                while (p[-1] == ' ')
380
                    p--;
381
                *p = '\0';
382
            }
383
        }
384
        addstr("extern", &decls);
385
        addstr(line1 + 6, &decls);
386
        if (q != NULL)
387
            addstr(q, &decls);
388
        amiddecls = 1;
389
    }
390
}
391
 
392
 
393
 
394
/*
395
 * Write the output to the file OUTTEMP.
396
 */
397
 
398
void
399
output() {
400
    FILE *fp;
401
    char **pp;
402
    struct event *ep;
403
 
404
    fp = ckfopen(OUTTEMP, "w");
405
    fputs(writer, fp);
406
    for (pp = header_files ; *pp ; pp++)
407
        fprintf(fp, "#include %s\n", *pp);
408
    fputs("\n\n\n", fp);
409
    writetext(&defines, fp);
410
    fputs("\n\n", fp);
411
    writetext(&decls, fp);
412
    for (ep = event ; ep->name ; ep++) {
413
        fputs("\n\n\n", fp);
414
        fputs(ep->comment, fp);
415
        fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
416
        writetext(&ep->code, fp);
417
        fprintf(fp, "}\n");
418
    }
419
    fclose(fp);
420
}
421
 
422
 
423
/*
424
 * A text structure is simply a block of text that is kept in memory.
425
 * Addstr appends a string to the text struct, and addchar appends a single
426
 * character.
427
 */
428
 
429
void
430
addstr(s, text)
431
    char *s;
432
    struct text *text;
433
    {
434
    while (*s) {
435
        if (--text->nleft < 0)
436
            addchar(*s++, text);
437
        else
438
            *text->nextc++ = *s++;
439
    }
440
}
441
 
442
 
443
void
444
addchar(c, text)
445
    int c;
446
    struct text *text;
447
{
448
    struct block *bp;
449
 
450
    if (--text->nleft < 0) {
451
        bp = ckmalloc(sizeof *bp);
452
        if (text->start == NULL)
453
            text->start = bp;
454
        else
455
            text->last->next = bp;
456
        text->last = bp;
457
        text->nextc = bp->text;
458
        text->nleft = BLOCKSIZE - 1;
459
    }
460
    *text->nextc++ = c;
461
}
462
 
463
/*
464
 * Write the contents of a text structure to a file.
465
 */
466
void
467
writetext(text, fp)
468
    struct text *text;
469
    FILE *fp;
470
    {
471
    struct block *bp;
472
 
473
    if (text->start != NULL) {
474
        for (bp = text->start ; bp != text->last ; bp = bp->next)
475
            fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
476
        fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
477
    }
478
}
479
 
480
FILE *
481
ckfopen(file, mode)
482
    char *file;
483
    char *mode;
484
    {
485
    FILE *fp;
486
 
487
    if ((fp = fopen(file, mode)) == NULL) {
488
        fprintf(stderr, "Can't open %s\n", file);
489
        exit(2);
490
    }
491
    return fp;
492
}
493
 
494
void *
495
ckmalloc(nbytes)
496
    int nbytes;
497
{
498
    char *p;
499
 
500
    if ((p = malloc(nbytes)) == NULL)
501
        error("Out of space");
502
    return p;
503
}
504
 
505
char *
506
savestr(s)
507
    char *s;
508
    {
509
    char *p;
510
 
511
    p = ckmalloc(strlen(s) + 1);
512
    strcpy(p, s);
513
    return p;
514
}
515
 
516
void
517
error(msg)
518
    char *msg;
519
    {
520
    if (curfile != NULL)
521
        fprintf(stderr, "%s:%d: ", curfile, linno);
522
    fprintf(stderr, "%s\n", msg);
523
    exit(2);
524
    /* NOTREACHED */
525
}