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.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
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.
42 * Usage: mkinit sourcefile...
46 #include <sys/types.h>
55 * OUTFILE is the name of the output file. Output is initially written
56 * to the file OUTTEMP, which is then moved to OUTFILE.
59 #define OUTFILE "init.c"
60 #define OUTTEMP "init.c.new"
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.
87 * There is one event structure for each event that mkinit handles.
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 char *args
; /* arguments to routine */
95 struct text code
; /* code for handling event */
101 * This file was generated by the mkinit program.\n\
107 * Initialization code.\n\
110 char exitreset
[] = "\
112 * This routine is called when an error or an interrupt occurs in an\n\
113 * interactive shell and control is returned to the main command loop\n\
114 * but prior to exitshell. \n\
117 char forkreset
[] = "\
119 * This routine is called when we enter a subshell.\n\
122 char postexitreset
[] = "\
124 * This routine is called in exitshell.\n\
129 * This routine is called when an error or an interrupt occurs in an\n\
130 * interactive shell and control is returned to the main command loop.\n\
134 struct event event
[] = {
135 {"INIT", "init", init
},
136 {"EXITRESET", "exitreset", exitreset
},
137 {"FORKRESET", "forkreset", forkreset
, "union node *n"},
138 {"POSTEXITRESET", "postexitreset", postexitreset
},
139 {"RESET", "reset", reset
},
144 char *curfile
; /* current file */
145 int linno
; /* current line */
146 char *header_files
[200]; /* list of header files */
147 struct text defines
; /* #define statements */
148 struct text decls
; /* declarations */
149 int amiddecls
; /* for formatting */
152 void readfile(char *);
153 int match(char *, char *);
154 int gooddefine(char *);
155 void doevent(struct event
*, FILE *, char *);
156 void doinclude(char *);
157 void dodecl(char *, FILE *);
159 void addstr(char *, struct text
*);
160 void addchar(int, struct text
*);
161 void writetext(struct text
*, FILE *);
162 FILE *ckfopen(char *, char *);
164 char *savestr(char *);
165 static void error(char *);
166 int main(int, char **);
168 #define equal(s1, s2) (strcmp(s1, s2) == 0)
171 main(int argc
, char **argv
)
175 header_files
[0] = "\"shell.h\"";
176 header_files
[1] = "\"mystring.h\"";
177 header_files
[2] = "\"init.h\"";
178 for (ap
= argv
+ 1 ; *ap
; ap
++)
181 rename(OUTTEMP
, OUTFILE
);
188 * Parse an input file.
192 readfile(char *fname
)
198 fp
= ckfopen(fname
, "r");
202 while (fgets(line
, sizeof line
, fp
) != NULL
) {
204 for (ep
= event
; ep
->name
; ep
++) {
205 if (line
[0] == ep
->name
[0] && match(ep
->name
, line
)) {
206 doevent(ep
, fp
, fname
);
210 if (line
[0] == 'I' && match("INCLUDE", line
))
212 if (line
[0] == 'M' && match("MKINIT", line
))
214 if (line
[0] == '#' && gooddefine(line
)) {
217 static const char undef
[] = "#undef ";
220 memcpy(line2
, undef
, sizeof(undef
) - 1);
221 cp
= line2
+ sizeof(undef
) - 1;
222 while(*cp
&& (*cp
== ' ' || *cp
== '\t'))
224 while(*cp
&& *cp
!= ' ' && *cp
!= '\t' && *cp
!= '\n')
226 *cp
++ = '\n'; *cp
= '\0';
227 addstr(line2
, &defines
);
228 addstr(line
, &defines
);
236 match(char *name
, char *line
)
245 if (*q
!= '{' && *q
!= ' ' && *q
!= '\t' && *q
!= '\n')
252 gooddefine(char *line
)
256 if (! match("#define", line
))
257 return 0; /* not a define */
259 while (*p
== ' ' || *p
== '\t')
261 while (*p
!= ' ' && *p
!= '\t') {
263 return 0; /* macro definition */
266 while (*p
!= '\n' && *p
!= '\0')
269 return 0; /* multi-line definition */
275 doevent(struct event
*ep
, FILE *fp
, char *fname
)
281 sprintf(line
, "\n /* from %s: */\n", fname
);
282 addstr(line
, &ep
->code
);
283 addstr(" {\n", &ep
->code
);
286 if (fgets(line
, sizeof line
, fp
) == NULL
)
287 error("Unexpected EOF");
288 if (equal(line
, "}\n"))
291 for (p
= line
; *p
== '\t' ; p
++)
293 for ( ; *p
== ' ' ; p
++)
295 if (*p
== '\n' || *p
== '#')
297 while (indent
>= 8) {
298 addchar('\t', &ep
->code
);
302 addchar(' ', &ep
->code
);
305 addstr(p
, &ep
->code
);
307 addstr(" }\n", &ep
->code
);
312 doinclude(char *line
)
318 for (p
= line
; *p
!= '"' && *p
!= '<' && *p
!= '\0' ; p
++);
320 error("Expecting '\"' or '<'");
322 while (*p
!= ' ' && *p
!= '\t' && *p
!= '\n')
324 if (p
[-1] != '"' && p
[-1] != '>')
325 error("Missing terminator");
328 /* name now contains the name of the include file */
329 for (pp
= header_files
; *pp
&& ! equal(*pp
, name
) ; pp
++);
336 dodecl(char *line1
, FILE *fp
)
341 if (strcmp(line1
, "MKINIT\n") == 0) { /* start of struct/union decl */
342 addchar('\n', &decls
);
345 if (fgets(line
, sizeof line
, fp
) == NULL
)
346 error("Unterminated structure declaration");
347 addstr(line
, &decls
);
348 } while (line
[0] != '}');
352 addchar('\n', &decls
);
354 for (p
= line1
+ 6 ; *p
&& strchr("=/\n", *p
) == NULL
; p
++)
356 if (*p
== '=') { /* eliminate initialization */
357 for (q
= p
; *q
&& *q
!= ';' ; q
++);
366 addstr("extern", &decls
);
367 addstr(line1
+ 6, &decls
);
377 * Write the output to the file OUTTEMP.
387 fp
= ckfopen(OUTTEMP
, "w");
389 for (pp
= header_files
; *pp
; pp
++)
390 fprintf(fp
, "#include %s\n", *pp
);
392 writetext(&defines
, fp
);
394 writetext(&decls
, fp
);
395 for (ep
= event
; ep
->name
; ep
++) {
397 fputs(ep
->comment
, fp
);
398 fprintf(fp
, "\nvoid\n%s(%s) {\n", ep
->routine
, ep
->args
?: "");
399 writetext(&ep
->code
, fp
);
407 * A text structure is simply a block of text that is kept in memory.
408 * Addstr appends a string to the text struct, and addchar appends a single
413 addstr(char *s
, struct text
*text
)
416 if (--text
->nleft
< 0)
419 *text
->nextc
++ = *s
++;
425 addchar(int c
, struct text
*text
)
429 if (--text
->nleft
< 0) {
430 bp
= ckmalloc(sizeof *bp
);
431 if (text
->start
== NULL
)
434 text
->last
->next
= bp
;
436 text
->nextc
= bp
->text
;
437 text
->nleft
= BLOCKSIZE
- 1;
443 * Write the contents of a text structure to a file.
446 writetext(struct text
*text
, FILE *fp
)
450 if (text
->start
!= NULL
) {
451 for (bp
= text
->start
; bp
!= text
->last
; bp
= bp
->next
) {
452 if ((fwrite(bp
->text
, sizeof (char), BLOCKSIZE
, fp
)) != BLOCKSIZE
)
453 error("Can't write data\n");
455 if ((fwrite(bp
->text
, sizeof (char), BLOCKSIZE
- text
->nleft
, fp
)) != (BLOCKSIZE
- text
->nleft
))
456 error("Can't write data\n");
461 ckfopen(char *file
, char *mode
)
465 if ((fp
= fopen(file
, mode
)) == NULL
) {
466 fprintf(stderr
, "Can't open %s\n", file
);
477 if ((p
= malloc(nbytes
)) == NULL
)
478 error("Out of space");
487 p
= ckmalloc(strlen(s
) + 1);
496 fprintf(stderr
, "%s:%d: ", curfile
, linno
);
497 fprintf(stderr
, "%s\n", msg
);