~ubuntu-branches/ubuntu/hardy/klibc/hardy-updates

« back to all changes in this revision

Viewing changes to dash/mkinit.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeff Bailey
  • Date: 2006-01-04 20:24:52 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104202452-ec4v3n829rymukuv
Tags: 1.1.15-0ubuntu1
* New upstream version.

* Patch to fix compilation on parisc64 kernels.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 1991, 1993
 
3
 *      The Regents of the University of California.  All rights reserved.
 
4
 * Copyright (c) 1997-2005
 
5
 *      Herbert Xu <herbert@gondor.apana.org.au>.  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. Neither the name of the University nor the names of its contributors
 
19
 *    may be used to endorse or promote products derived from this software
 
20
 *    without specific prior written permission.
 
21
 *
 
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
32
 * SUCH DAMAGE.
 
33
 */
 
34
 
 
35
/*
 
36
 * This program scans all the source files for code to handle various
 
37
 * special events and combines this code into one file.  This (allegedly)
 
38
 * improves the structure of the program since there is no need for
 
39
 * anyone outside of a module to know that that module performs special
 
40
 * operations on particular events.
 
41
 *
 
42
 * Usage:  mkinit sourcefile...
 
43
 */
 
44
 
 
45
 
 
46
#include <sys/types.h>
 
47
#include <stdio.h>
 
48
#include <stdlib.h>
 
49
#include <string.h>
 
50
#include <fcntl.h>
 
51
#include <unistd.h>
 
52
 
 
53
 
 
54
/*
 
55
 * OUTFILE is the name of the output file.  Output is initially written
 
56
 * to the file OUTTEMP, which is then moved to OUTFILE.
 
57
 */
 
58
 
 
59
#define OUTFILE "init.c"
 
60
#define OUTTEMP "init.c.new"
 
61
 
 
62
 
 
63
/*
 
64
 * A text structure is basicly just a string that grows as more characters
 
65
 * are added onto the end of it.  It is implemented as a linked list of
 
66
 * blocks of characters.  The routines addstr and addchar append a string
 
67
 * or a single character, respectively, to a text structure.  Writetext
 
68
 * writes the contents of a text structure to a file.
 
69
 */
 
70
 
 
71
#define BLOCKSIZE 512
 
72
 
 
73
struct text {
 
74
        char *nextc;
 
75
        int nleft;
 
76
        struct block *start;
 
77
        struct block *last;
 
78
};
 
79
 
 
80
struct block {
 
81
        struct block *next;
 
82
        char text[BLOCKSIZE];
 
83
};
 
84
 
 
85
 
 
86
/*
 
87
 * There is one event structure for each event that mkinit handles.
 
88
 */
 
89
 
 
90
struct event {
 
91
        char *name;             /* name of event (e.g. INIT) */
 
92
        char *routine;          /* name of routine called on event */
 
93
        char *comment;          /* comment describing routine */
 
94
        struct text code;       /* code for handling event */
 
95
};
 
96
 
 
97
 
 
98
char writer[] = "\
 
99
/*\n\
 
100
 * This file was generated by the mkinit program.\n\
 
101
 */\n\
 
102
\n";
 
103
 
 
104
char init[] = "\
 
105
/*\n\
 
106
 * Initialization code.\n\
 
107
 */\n";
 
108
 
 
109
char reset[] = "\
 
110
/*\n\
 
111
 * This routine is called when an error or an interrupt occurs in an\n\
 
112
 * interactive shell and control is returned to the main command loop.\n\
 
113
 */\n";
 
114
 
 
115
 
 
116
struct event event[] = {
 
117
        {"INIT", "init", init},
 
118
        {"RESET", "reset", reset},
 
119
        {NULL, NULL}
 
120
};
 
121
 
 
122
 
 
123
char *curfile;                          /* current file */
 
124
int linno;                              /* current line */
 
125
char *header_files[200];                /* list of header files */
 
126
struct text defines;                    /* #define statements */
 
127
struct text decls;                      /* declarations */
 
128
int amiddecls;                          /* for formatting */
 
129
 
 
130
 
 
131
void readfile(char *);
 
132
int match(char *, char *);
 
133
int gooddefine(char *);
 
134
void doevent(struct event *, FILE *, char *);
 
135
void doinclude(char *);
 
136
void dodecl(char *, FILE *);
 
137
void output(void);
 
138
void addstr(char *, struct text *);
 
139
void addchar(int, struct text *);
 
140
void writetext(struct text *, FILE *);
 
141
FILE *ckfopen(char *, char *);
 
142
void *ckmalloc(int);
 
143
char *savestr(char *);
 
144
static void error(char *);
 
145
int main(int, char **);
 
146
 
 
147
#define equal(s1, s2)   (strcmp(s1, s2) == 0)
 
148
 
 
149
int
 
150
main(int argc, char **argv)
 
151
{
 
152
        char **ap;
 
153
 
 
154
        header_files[0] = "\"shell.h\"";
 
155
        header_files[1] = "\"mystring.h\"";
 
156
        header_files[2] = "\"init.h\"";
 
157
        for (ap = argv + 1 ; *ap ; ap++)
 
158
                readfile(*ap);
 
159
        output();
 
160
        rename(OUTTEMP, OUTFILE);
 
161
        exit(0);
 
162
        /* NOTREACHED */
 
163
}
 
164
 
 
165
 
 
166
/*
 
167
 * Parse an input file.
 
168
 */
 
169
 
 
170
void
 
171
readfile(char *fname)
 
172
{
 
173
        FILE *fp;
 
174
        char line[1024];
 
175
        struct event *ep;
 
176
 
 
177
        fp = ckfopen(fname, "r");
 
178
        curfile = fname;
 
179
        linno = 0;
 
180
        amiddecls = 0;
 
181
        while (fgets(line, sizeof line, fp) != NULL) {
 
182
                linno++;
 
183
                for (ep = event ; ep->name ; ep++) {
 
184
                        if (line[0] == ep->name[0] && match(ep->name, line)) {
 
185
                                doevent(ep, fp, fname);
 
186
                                break;
 
187
                        }
 
188
                }
 
189
                if (line[0] == 'I' && match("INCLUDE", line))
 
190
                        doinclude(line);
 
191
                if (line[0] == 'M' && match("MKINIT", line))
 
192
                        dodecl(line, fp);
 
193
                if (line[0] == '#' && gooddefine(line)) {
 
194
                        char *cp;
 
195
                        char line2[1024];
 
196
                        static const char undef[] = "#undef ";
 
197
 
 
198
                        strcpy(line2, line);
 
199
                        memcpy(line2, undef, sizeof(undef) - 1);
 
200
                        cp = line2 + sizeof(undef) - 1;
 
201
                        while(*cp && (*cp == ' ' || *cp == '\t'))
 
202
                                cp++;
 
203
                        while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
 
204
                                cp++;
 
205
                        *cp++ = '\n'; *cp = '\0';
 
206
                        addstr(line2, &defines);
 
207
                        addstr(line, &defines);
 
208
                }
 
209
        }
 
210
        fclose(fp);
 
211
}
 
212
 
 
213
 
 
214
int
 
215
match(char *name, char *line)
 
216
{
 
217
        char *p, *q;
 
218
 
 
219
        p = name, q = line;
 
220
        while (*p) {
 
221
                if (*p++ != *q++)
 
222
                        return 0;
 
223
        }
 
224
        if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
 
225
                return 0;
 
226
        return 1;
 
227
}
 
228
 
 
229
 
 
230
int
 
231
gooddefine(char *line)
 
232
{
 
233
        char *p;
 
234
 
 
235
        if (! match("#define", line))
 
236
                return 0;                       /* not a define */
 
237
        p = line + 7;
 
238
        while (*p == ' ' || *p == '\t')
 
239
                p++;
 
240
        while (*p != ' ' && *p != '\t') {
 
241
                if (*p == '(')
 
242
                        return 0;               /* macro definition */
 
243
                p++;
 
244
        }
 
245
        while (*p != '\n' && *p != '\0')
 
246
                p++;
 
247
        if (p[-1] == '\\')
 
248
                return 0;                       /* multi-line definition */
 
249
        return 1;
 
250
}
 
251
 
 
252
 
 
253
void
 
254
doevent(struct event *ep, FILE *fp, char *fname)
 
255
{
 
256
        char line[1024];
 
257
        int indent;
 
258
        char *p;
 
259
 
 
260
        sprintf(line, "\n      /* from %s: */\n", fname);
 
261
        addstr(line, &ep->code);
 
262
        addstr("      {\n", &ep->code);
 
263
        for (;;) {
 
264
                linno++;
 
265
                if (fgets(line, sizeof line, fp) == NULL)
 
266
                        error("Unexpected EOF");
 
267
                if (equal(line, "}\n"))
 
268
                        break;
 
269
                indent = 6;
 
270
                for (p = line ; *p == '\t' ; p++)
 
271
                        indent += 8;
 
272
                for ( ; *p == ' ' ; p++)
 
273
                        indent++;
 
274
                if (*p == '\n' || *p == '#')
 
275
                        indent = 0;
 
276
                while (indent >= 8) {
 
277
                        addchar('\t', &ep->code);
 
278
                        indent -= 8;
 
279
                }
 
280
                while (indent > 0) {
 
281
                        addchar(' ', &ep->code);
 
282
                        indent--;
 
283
                }
 
284
                addstr(p, &ep->code);
 
285
        }
 
286
        addstr("      }\n", &ep->code);
 
287
}
 
288
 
 
289
 
 
290
void
 
291
doinclude(char *line)
 
292
{
 
293
        char *p;
 
294
        char *name;
 
295
        char **pp;
 
296
 
 
297
        for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
 
298
        if (*p == '\0')
 
299
                error("Expecting '\"' or '<'");
 
300
        name = p;
 
301
        while (*p != ' ' && *p != '\t' && *p != '\n')
 
302
                p++;
 
303
        if (p[-1] != '"' && p[-1] != '>')
 
304
                error("Missing terminator");
 
305
        *p = '\0';
 
306
 
 
307
        /* name now contains the name of the include file */
 
308
        for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
 
309
        if (*pp == NULL)
 
310
                *pp = savestr(name);
 
311
}
 
312
 
 
313
 
 
314
void
 
315
dodecl(char *line1, FILE *fp)
 
316
{
 
317
        char line[1024];
 
318
        char *p, *q;
 
319
 
 
320
        if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
 
321
                addchar('\n', &decls);
 
322
                do {
 
323
                        linno++;
 
324
                        if (fgets(line, sizeof line, fp) == NULL)
 
325
                                error("Unterminated structure declaration");
 
326
                        addstr(line, &decls);
 
327
                } while (line[0] != '}');
 
328
                amiddecls = 0;
 
329
        } else {
 
330
                if (! amiddecls)
 
331
                        addchar('\n', &decls);
 
332
                q = NULL;
 
333
                for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
 
334
                        continue;
 
335
                if (*p == '=') {                /* eliminate initialization */
 
336
                        for (q = p ; *q && *q != ';' ; q++);
 
337
                        if (*q == '\0')
 
338
                                q = NULL;
 
339
                        else {
 
340
                                while (p[-1] == ' ')
 
341
                                        p--;
 
342
                                *p = '\0';
 
343
                        }
 
344
                }
 
345
                addstr("extern", &decls);
 
346
                addstr(line1 + 6, &decls);
 
347
                if (q != NULL)
 
348
                        addstr(q, &decls);
 
349
                amiddecls = 1;
 
350
        }
 
351
}
 
352
 
 
353
 
 
354
 
 
355
/*
 
356
 * Write the output to the file OUTTEMP.
 
357
 */
 
358
 
 
359
void
 
360
output(void)
 
361
{
 
362
        FILE *fp;
 
363
        char **pp;
 
364
        struct event *ep;
 
365
 
 
366
        fp = ckfopen(OUTTEMP, "w");
 
367
        fputs(writer, fp);
 
368
        for (pp = header_files ; *pp ; pp++)
 
369
                fprintf(fp, "#include %s\n", *pp);
 
370
        fputs("\n\n\n", fp);
 
371
        writetext(&defines, fp);
 
372
        fputs("\n\n", fp);
 
373
        writetext(&decls, fp);
 
374
        for (ep = event ; ep->name ; ep++) {
 
375
                fputs("\n\n\n", fp);
 
376
                fputs(ep->comment, fp);
 
377
                fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
 
378
                writetext(&ep->code, fp);
 
379
                fprintf(fp, "}\n");
 
380
        }
 
381
        fclose(fp);
 
382
}
 
383
 
 
384
 
 
385
/*
 
386
 * A text structure is simply a block of text that is kept in memory.
 
387
 * Addstr appends a string to the text struct, and addchar appends a single
 
388
 * character.
 
389
 */
 
390
 
 
391
void
 
392
addstr(char *s, struct text *text)
 
393
{
 
394
        while (*s) {
 
395
                if (--text->nleft < 0)
 
396
                        addchar(*s++, text);
 
397
                else
 
398
                        *text->nextc++ = *s++;
 
399
        }
 
400
}
 
401
 
 
402
 
 
403
void
 
404
addchar(int c, struct text *text)
 
405
{
 
406
        struct block *bp;
 
407
 
 
408
        if (--text->nleft < 0) {
 
409
                bp = ckmalloc(sizeof *bp);
 
410
                if (text->start == NULL)
 
411
                        text->start = bp;
 
412
                else
 
413
                        text->last->next = bp;
 
414
                text->last = bp;
 
415
                text->nextc = bp->text;
 
416
                text->nleft = BLOCKSIZE - 1;
 
417
        }
 
418
        *text->nextc++ = c;
 
419
}
 
420
 
 
421
/*
 
422
 * Write the contents of a text structure to a file.
 
423
 */
 
424
void
 
425
writetext(struct text *text, FILE *fp)
 
426
{
 
427
        struct block *bp;
 
428
 
 
429
        if (text->start != NULL) {
 
430
                for (bp = text->start ; bp != text->last ; bp = bp->next)
 
431
                        fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
 
432
                fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
 
433
        }
 
434
}
 
435
 
 
436
FILE *
 
437
ckfopen(char *file, char *mode)
 
438
{
 
439
        FILE *fp;
 
440
 
 
441
        if ((fp = fopen(file, mode)) == NULL) {
 
442
                fprintf(stderr, "Can't open %s\n", file);
 
443
                exit(2);
 
444
        }
 
445
        return fp;
 
446
}
 
447
 
 
448
void *
 
449
ckmalloc(int nbytes)
 
450
{
 
451
        char *p;
 
452
 
 
453
        if ((p = malloc(nbytes)) == NULL)
 
454
                error("Out of space");
 
455
        return p;
 
456
}
 
457
 
 
458
char *
 
459
savestr(char *s)
 
460
{
 
461
        char *p;
 
462
 
 
463
        p = ckmalloc(strlen(s) + 1);
 
464
        strcpy(p, s);
 
465
        return p;
 
466
}
 
467
 
 
468
static void
 
469
error(char *msg)
 
470
{
 
471
        if (curfile != NULL)
 
472
                fprintf(stderr, "%s:%d: ", curfile, linno);
 
473
        fprintf(stderr, "%s\n", msg);
 
474
        exit(2);
 
475
        /* NOTREACHED */
 
476
}