* Copyright (c) 1991 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
"@(#) Copyright (c) 1991 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)mkinit.c 5.3 (Berkeley) 3/13/91";
* This program scans all the source files for code to handle various
* special events and combines this code into one file. This (allegedly)
* improves the structure of the program since there is no need for
* anyone outside of a module to know that that module performs special
* operations on particular events. The command is executed iff init.c
* Usage: mkinit command sourcefile...
* OUTFILE is the name of the output file. Output is initially written
* to the file OUTTEMP, which is then moved to OUTFILE if OUTTEMP and
#define OUTTEMP "init.c.new"
* A text structure is basicly just a string that grows as more characters
* are added onto the end of it. It is implemented as a linked list of
* blocks of characters. The routines addstr and addchar append a string
* or a single character, respectively, to a text structure. Writetext
* writes the contents of a text structure to a file.
* There is one event structure for each event that mkinit handles.
char *name
; /* name of event (e.g. INIT) */
char *routine
; /* name of routine called on event */
char *comment
; /* comment describing routine */
struct text code
; /* code for handling event */
* This file was generated by the mkinit program.\n\
* Initialization code.\n\
* This routine is called when an error or an interrupt occurs in an\n\
* interactive shell and control is returned to the main command loop.\n\
* This routine is called to initialize the shell to run a shell procedure.\n\
{"RESET", "reset", reset
},
{"SHELLPROC", "initshellproc", shellproc
},
char *curfile
; /* current file */
int linno
; /* current line */
char *header_files
[200]; /* list of header files */
struct text defines
; /* #define statements */
struct text decls
; /* declarations */
int amiddecls
; /* for formatting */
void readfile(), doevent(), doinclude(), dodecl(), output();
void addstr(), addchar(), writetext();
#define equal(s1, s2) (strcmp(s1, s2) == 0)
void *ckmalloc
__P((int));
error("Usage: mkinit command file...");
header_files
[0] = "\"shell.h\"";
header_files
[1] = "\"mystring.h\"";
for (ap
= argv
+ 2 ; *ap
; ap
++)
exit(0); /* no compilation necessary */
execl("/bin/sh", "sh", "-c", argv
[1], (char *)0);
error("Can't exec shell");
fp
= ckfopen(fname
, "r");
while (fgets(line
, sizeof line
, fp
) != NULL
) {
for (ep
= event
; ep
->name
; ep
++) {
if (line
[0] == ep
->name
[0] && match(ep
->name
, line
)) {
if (line
[0] == 'I' && match("INCLUDE", line
))
if (line
[0] == 'M' && match("MKINIT", line
))
if (line
[0] == '#' && gooddefine(line
))
if (*q
!= '{' && *q
!= ' ' && *q
!= '\t' && *q
!= '\n')
if (! match("#define", line
))
return 0; /* not a define */
while (*p
== ' ' || *p
== '\t')
while (*p
!= ' ' && *p
!= '\t') {
return 0; /* macro definition */
while (*p
!= '\n' && *p
!= '\0')
return 0; /* multi-line definition */
register struct event
*ep
;
sprintf(line
, "\n /* from %s: */\n", fname
);
addstr(" {\n", &ep
->code
);
if (fgets(line
, sizeof line
, fp
) == NULL
)
for (p
= line
; *p
== '\t' ; p
++)
if (*p
== '\n' || *p
== '#')
addchar('\t', &ep
->code
);
addstr(" }\n", &ep
->code
);
for (p
= line
; *p
!= '"' && *p
!= '<' && *p
!= '\0' ; p
++);
error("Expecting '\"' or '<'");
while (*p
!= ' ' && *p
!= '\t' && *p
!= '\n')
if (p
[-1] != '"' && p
[-1] != '>')
error("Missing terminator");
/* name now contains the name of the include file */
for (pp
= header_files
; *pp
&& ! equal(*pp
, name
) ; pp
++);
if (strcmp(line1
, "MKINIT\n") == 0) { /* start of struct/union decl */
if (fgets(line
, sizeof line
, fp
) == NULL
)
error("Unterminated structure declaration");
} while (line
[0] != '}');
for (p
= line1
+ 6 ; *p
!= '=' && *p
!= '/' ; p
++);
if (*p
== '=') { /* eliminate initialization */
for (q
= p
; *q
&& *q
!= ';' ; q
++);
addstr("extern", &decls
);
addstr(line1
+ 6, &decls
);
* Write the output to the file OUTTEMP.
fp
= ckfopen(OUTTEMP
, "w");
for (pp
= header_files
; *pp
; pp
++)
fprintf(fp
, "#include %s\n", *pp
);
for (ep
= event
; ep
->name
; ep
++) {
fprintf(fp
, "\nvoid\n%s() {\n", ep
->routine
);
writetext(&ep
->code
, fp
);
* Return true if the new output file is different from the old one.
if ((f1
= fopen(OUTFILE
, "r")) == NULL
|| (f2
= fopen(OUTTEMP
, "r")) == NULL
)
while ((c
= getc(f1
)) == getc(f2
)) {
* Touch a file. Returns 0 on failure, 1 on success.
if ((fd
= open(file
, O_RDWR
)) < 0)
if (read(fd
, &c
, 1) != 1) {
* A text structure is simply a block of text that is kept in memory.
* Addstr appends a string to the text struct, and addchar appends a single
register struct text
*text
;
register struct text
*text
;
bp
= ckmalloc(sizeof *bp
);
text
->nleft
= BLOCKSIZE
- 1;
* Write the contents of a text structure to a file.
if (text
->start
!= NULL
) {
for (bp
= text
->start
; bp
!= text
->last
; bp
= bp
->next
)
fwrite(bp
->text
, sizeof (char), BLOCKSIZE
, fp
);
fwrite(bp
->text
, sizeof (char), BLOCKSIZE
- text
->nleft
, fp
);
if ((fp
= fopen(file
, mode
)) == NULL
) {
fprintf(stderr
, "Can't open %s\n", file
);
if ((p
= malloc(nbytes
)) == NULL
)
p
= ckmalloc(strlen(s
) + 1);
fprintf(stderr
, "%s:%d: ", curfile
, linno
);
fprintf(stderr
, "%s\n", msg
);