2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#) Copyright (c) 1991, 1993 The Regents of the University of California. All rights reserved.
37 * @(#)mkinit.c 8.2 (Berkeley) 5/4/95
38 * $FreeBSD: src/bin/sh/mkinit.c,v 1.14.2.1 2002/07/19 04:38:51 tjr Exp $
39 * $DragonFly: src/bin/sh/mkinit.c,v 1.4 2005/04/19 07:18:19 cpressey Exp $
43 * This program scans all the source files for code to handle various
44 * special events and combines this code into one file. This (allegedly)
45 * improves the structure of the program since there is no need for
46 * anyone outside of a module to know that that module performs special
47 * operations on particular events.
49 * Usage: mkinit sourcefile...
53 #include <sys/cdefs.h>
54 #include <sys/types.h>
64 * OUTFILE is the name of the output file. Output is initially written
65 * to the file OUTTEMP, which is then moved to OUTFILE.
68 #define OUTFILE "init.c"
69 #define OUTTEMP "init.c.new"
73 * A text structure is basicly just a string that grows as more characters
74 * are added onto the end of it. It is implemented as a linked list of
75 * blocks of characters. The routines addstr and addchar append a string
76 * or a single character, respectively, to a text structure. Writetext
77 * writes the contents of a text structure to a file.
96 * There is one event structure for each event that mkinit handles.
100 const char *name
; /* name of event (e.g. INIT) */
101 const char *routine
; /* name of routine called on event */
102 const char *comment
; /* comment describing routine */
103 struct text code
; /* code for handling event */
109 * This file was generated by the mkinit program.\n\
115 * Initialization code.\n\
120 * This routine is called when an error or an interrupt occurs in an\n\
121 * interactive shell and control is returned to the main command loop.\n\
124 char shellproc
[] = "\
126 * This routine is called to initialize the shell to run a shell procedure.\n\
130 struct event event
[] = {
131 {"INIT", "init", init
, {NULL
, 0, NULL
, NULL
}},
132 {"RESET", "reset", reset
, {NULL
, 0, NULL
, NULL
}},
133 {"SHELLPROC", "initshellproc", shellproc
, {NULL
, 0, NULL
, NULL
}},
134 {NULL
, NULL
, NULL
, {NULL
, 0, NULL
, NULL
}}
138 const char *curfile
; /* current file */
139 int linno
; /* current line */
140 const char *header_files
[200]; /* list of header files */
141 struct text defines
; /* #define statements */
142 struct text decls
; /* declarations */
143 int amiddecls
; /* for formatting */
146 void readfile(const char *);
147 int match(const char *, const char *);
148 int gooddefine(const char *);
149 void doevent(struct event
*, FILE *, const char *);
150 void doinclude(char *);
151 void dodecl(char *, FILE *);
153 void addstr(const char *, struct text
*);
154 void addchar(int, struct text
*);
155 void writetext(struct text
*, FILE *);
156 FILE *ckfopen(const char *, const char *);
158 char *savestr(const char *);
159 void error(const char *);
161 #define equal(s1, s2) (strcmp(s1, s2) == 0)
164 main(int argc __unused
, char *argv
[])
168 header_files
[0] = "\"shell.h\"";
169 header_files
[1] = "\"mystring.h\"";
170 header_files
[2] = "\"init.h\"";
171 for (ap
= argv
+ 1 ; *ap
; ap
++)
174 rename(OUTTEMP
, OUTFILE
);
180 * Parse an input file.
184 readfile(const char *fname
)
190 fp
= ckfopen(fname
, "r");
194 while (fgets(line
, sizeof line
, fp
) != NULL
) {
196 for (ep
= event
; ep
->name
; ep
++) {
197 if (line
[0] == ep
->name
[0] && match(ep
->name
, line
)) {
198 doevent(ep
, fp
, fname
);
202 if (line
[0] == 'I' && match("INCLUDE", line
))
204 if (line
[0] == 'M' && match("MKINIT", line
))
206 if (line
[0] == '#' && gooddefine(line
)) {
209 static const char undef
[] = "#undef ";
212 memcpy(line2
, undef
, sizeof(undef
) - 1);
213 cp
= line2
+ sizeof(undef
) - 1;
214 while(*cp
&& (*cp
== ' ' || *cp
== '\t'))
216 while(*cp
&& *cp
!= ' ' && *cp
!= '\t' && *cp
!= '\n')
218 *cp
++ = '\n'; *cp
= '\0';
219 addstr(line2
, &defines
);
220 addstr(line
, &defines
);
228 match(const char *name
, const char *line
)
237 if (*q
!= '{' && *q
!= ' ' && *q
!= '\t' && *q
!= '\n')
244 gooddefine(const char *line
)
248 if (! match("#define", line
))
249 return 0; /* not a define */
251 while (*p
== ' ' || *p
== '\t')
253 while (*p
!= ' ' && *p
!= '\t') {
255 return 0; /* macro definition */
258 while (*p
!= '\n' && *p
!= '\0')
261 return 0; /* multi-line definition */
267 doevent(struct event
*ep
, FILE *fp
, const char *fname
)
273 sprintf(line
, "\n /* from %s: */\n", fname
);
274 addstr(line
, &ep
->code
);
275 addstr(" {\n", &ep
->code
);
278 if (fgets(line
, sizeof line
, fp
) == NULL
)
279 error("Unexpected EOF");
280 if (equal(line
, "}\n"))
283 for (p
= line
; *p
== '\t' ; p
++)
285 for ( ; *p
== ' ' ; p
++)
287 if (*p
== '\n' || *p
== '#')
289 while (indent
>= 8) {
290 addchar('\t', &ep
->code
);
294 addchar(' ', &ep
->code
);
297 addstr(p
, &ep
->code
);
299 addstr(" }\n", &ep
->code
);
304 doinclude(char *line
)
310 for (p
= line
; *p
!= '"' && *p
!= '<' && *p
!= '\0' ; p
++);
312 error("Expecting '\"' or '<'");
314 while (*p
!= ' ' && *p
!= '\t' && *p
!= '\n')
316 if (p
[-1] != '"' && p
[-1] != '>')
317 error("Missing terminator");
320 /* name now contains the name of the include file */
321 for (pp
= header_files
; *pp
&& ! equal(*pp
, name
) ; pp
++);
328 dodecl(char *line1
, FILE *fp
)
333 if (strcmp(line1
, "MKINIT\n") == 0) { /* start of struct/union decl */
334 addchar('\n', &decls
);
337 if (fgets(line
, sizeof line
, fp
) == NULL
)
338 error("Unterminated structure declaration");
339 addstr(line
, &decls
);
340 } while (line
[0] != '}');
344 addchar('\n', &decls
);
346 for (p
= line1
+ 6 ; *p
&& strchr("=/\n", *p
) == NULL
; p
++)
348 if (*p
== '=') { /* eliminate initialization */
349 for (q
= p
; *q
&& *q
!= ';' ; q
++);
358 addstr("extern", &decls
);
359 addstr(line1
+ 6, &decls
);
369 * Write the output to the file OUTTEMP.
376 const char * const *pp
;
379 fp
= ckfopen(OUTTEMP
, "w");
381 for (pp
= header_files
; *pp
; pp
++)
382 fprintf(fp
, "#include %s\n", *pp
);
384 writetext(&defines
, fp
);
386 writetext(&decls
, fp
);
387 for (ep
= event
; ep
->name
; ep
++) {
389 fputs(ep
->comment
, fp
);
390 fprintf(fp
, "\nvoid\n%s(void) {\n", ep
->routine
);
391 writetext(&ep
->code
, fp
);
399 * A text structure is simply a block of text that is kept in memory.
400 * Addstr appends a string to the text struct, and addchar appends a single
405 addstr(const char *s
, struct text
*text
)
408 if (--text
->nleft
< 0)
411 *text
->nextc
++ = *s
++;
417 addchar(int c
, struct text
*text
)
421 if (--text
->nleft
< 0) {
422 bp
= ckmalloc(sizeof *bp
);
423 if (text
->start
== NULL
)
426 text
->last
->next
= bp
;
428 text
->nextc
= bp
->text
;
429 text
->nleft
= BLOCKSIZE
- 1;
435 * Write the contents of a text structure to a file.
438 writetext(struct text
*text
, FILE *fp
)
442 if (text
->start
!= NULL
) {
443 for (bp
= text
->start
; bp
!= text
->last
; bp
= bp
->next
)
444 fwrite(bp
->text
, sizeof (char), BLOCKSIZE
, fp
);
445 fwrite(bp
->text
, sizeof (char), BLOCKSIZE
- text
->nleft
, fp
);
450 ckfopen(const char *file
, const char *mode
)
454 if ((fp
= fopen(file
, mode
)) == NULL
) {
455 fprintf(stderr
, "Can't open %s: %s\n", file
, strerror(errno
));
466 if ((p
= malloc(nbytes
)) == NULL
)
467 error("Out of space");
472 savestr(const char *s
)
476 p
= ckmalloc(strlen(s
) + 1);
482 error(const char *msg
)
485 fprintf(stderr
, "%s:%d: ", curfile
, linno
);
486 fprintf(stderr
, "%s\n", msg
);