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 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 static char const copyright
[] =
35 "@(#) Copyright (c) 1991, 1993\n\
36 The Regents of the University of California. All rights reserved.\n";
41 static char sccsid
[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
45 #include <sys/cdefs.h>
46 __FBSDID("$FreeBSD: src/bin/sh/mkinit.c,v 1.17 2004/04/06 20:06:51 markm Exp $");
50 * This program scans all the source files for code to handle various
51 * special events and combines this code into one file. This (allegedly)
52 * improves the structure of the program since there is no need for
53 * anyone outside of a module to know that that module performs special
54 * operations on particular events.
56 * Usage: mkinit sourcefile...
60 #include <sys/types.h>
73 * OUTFILE is the name of the output file. Output is initially written
74 * to the file OUTTEMP, which is then moved to OUTFILE.
77 #define OUTFILE "init.c"
78 #define OUTTEMP "init.c.new"
82 * A text structure is basicly just a string that grows as more characters
83 * are added onto the end of it. It is implemented as a linked list of
84 * blocks of characters. The routines addstr and addchar append a string
85 * or a single character, respectively, to a text structure. Writetext
86 * writes the contents of a text structure to a file.
100 char text
[BLOCKSIZE
];
105 * There is one event structure for each event that mkinit handles.
109 char *name
; /* name of event (e.g. INIT) */
110 char *routine
; /* name of routine called on event */
111 char *comment
; /* comment describing routine */
112 struct text code
; /* code for handling event */
118 * This file was generated by the mkinit program.\n\
124 * Initialization code.\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\
133 char shellproc
[] = "\
135 * This routine is called to initialize the shell to run a shell procedure.\n\
139 struct event event
[] = {
140 {"INIT", "init", init
},
141 {"RESET", "reset", reset
},
142 {"SHELLPROC", "initshellproc", shellproc
},
147 char *curfile
; /* current file */
148 int linno
; /* current line */
149 char *header_files
[200]; /* list of header files */
150 struct text defines
; /* #define statements */
151 struct text decls
; /* declarations */
152 int amiddecls
; /* for formatting */
155 static void readfile(char *);
156 static int match(char *, char *);
157 static int gooddefine(char *);
158 static void doevent(struct event
*, FILE *, char *);
159 static void doinclude(char *);
160 static void dodecl(char *, FILE *);
161 static void output(void);
162 static void addstr(char *, struct text
*);
163 static void addchar(int, struct text
*);
164 static void writetext(struct text
*, FILE *);
165 static FILE *ckfopen(char *, char *);
166 static void *ckmalloc(int);
167 static char *savestr(char *);
168 static void error(char *);
170 #define equal(s1, s2) (strcmp(s1, s2) == 0)
173 main(int argc __unused
, char *argv
[])
177 header_files
[0] = "\"shell.h\"";
178 header_files
[1] = "\"mystring.h\"";
179 for (ap
= argv
+ 1 ; *ap
; ap
++)
182 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(void) {\n", ep
->routine
);
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 fwrite(bp
->text
, sizeof (char), BLOCKSIZE
, fp
);
453 fwrite(bp
->text
, sizeof (char), BLOCKSIZE
- text
->nleft
, fp
);
458 ckfopen(char *file
, char *mode
)
462 if ((fp
= fopen(file
, mode
)) == NULL
) {
463 fprintf(stderr
, "Can't open %s: %s\n", file
, strerror(errno
));
474 if ((p
= malloc(nbytes
)) == NULL
)
475 error("Out of space");
484 p
= ckmalloc(strlen(s
) + 1);
493 fprintf(stderr
, "%s:%d: ", curfile
, linno
);
494 fprintf(stderr
, "%s\n", msg
);
499 * $PchId: mkinit.c,v 1.6 2006/05/22 12:16:50 philip Exp $