mkinit.c revision 20425
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1991, 1993
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * This code is derived from software contributed to Berkeley by
61556Srgrimes * Kenneth Almquist.
71556Srgrimes *
81556Srgrimes * Redistribution and use in source and binary forms, with or without
91556Srgrimes * modification, are permitted provided that the following conditions
101556Srgrimes * are met:
111556Srgrimes * 1. Redistributions of source code must retain the above copyright
121556Srgrimes *    notice, this list of conditions and the following disclaimer.
131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141556Srgrimes *    notice, this list of conditions and the following disclaimer in the
151556Srgrimes *    documentation and/or other materials provided with the distribution.
161556Srgrimes * 3. All advertising materials mentioning features or use of this software
171556Srgrimes *    must display the following acknowledgement:
181556Srgrimes *	This product includes software developed by the University of
191556Srgrimes *	California, Berkeley and its contributors.
201556Srgrimes * 4. Neither the name of the University nor the names of its contributors
211556Srgrimes *    may be used to endorse or promote products derived from this software
221556Srgrimes *    without specific prior written permission.
231556Srgrimes *
241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
271556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
341556Srgrimes * SUCH DAMAGE.
353044Sdg *
3620425Ssteve *	$Id: mkinit.c,v 1.6 1996/09/01 10:20:50 peter Exp $
371556Srgrimes */
381556Srgrimes
391556Srgrimes#ifndef lint
4020425Sstevestatic char const copyright[] =
411556Srgrimes"@(#) Copyright (c) 1991, 1993\n\
421556Srgrimes	The Regents of the University of California.  All rights reserved.\n";
431556Srgrimes#endif /* not lint */
441556Srgrimes
451556Srgrimes#ifndef lint
4620425Sstevestatic char const sccsid[] = "@(#)mkinit.c	8.2 (Berkeley) 5/4/95";
471556Srgrimes#endif /* not lint */
481556Srgrimes
491556Srgrimes/*
501556Srgrimes * This program scans all the source files for code to handle various
511556Srgrimes * special events and combines this code into one file.  This (allegedly)
521556Srgrimes * improves the structure of the program since there is no need for
531556Srgrimes * anyone outside of a module to know that that module performs special
5417987Speter * operations on particular events.
551556Srgrimes *
5617987Speter * Usage:  mkinit sourcefile...
571556Srgrimes */
581556Srgrimes
591556Srgrimes
601556Srgrimes#include <sys/cdefs.h>
611556Srgrimes#include <sys/types.h>
621556Srgrimes#include <stdio.h>
6317987Speter#include <stdlib.h>
6417987Speter#include <string.h>
651556Srgrimes#include <fcntl.h>
661556Srgrimes#include <unistd.h>
671556Srgrimes
681556Srgrimes
691556Srgrimes/*
701556Srgrimes * OUTFILE is the name of the output file.  Output is initially written
7120425Ssteve * to the file OUTTEMP, which is then moved to OUTFILE.
721556Srgrimes */
731556Srgrimes
741556Srgrimes#define OUTFILE "init.c"
751556Srgrimes#define OUTTEMP "init.c.new"
761556Srgrimes
771556Srgrimes
781556Srgrimes/*
791556Srgrimes * A text structure is basicly just a string that grows as more characters
801556Srgrimes * are added onto the end of it.  It is implemented as a linked list of
811556Srgrimes * blocks of characters.  The routines addstr and addchar append a string
821556Srgrimes * or a single character, respectively, to a text structure.  Writetext
831556Srgrimes * writes the contents of a text structure to a file.
841556Srgrimes */
851556Srgrimes
861556Srgrimes#define BLOCKSIZE 512
871556Srgrimes
881556Srgrimesstruct text {
891556Srgrimes	char *nextc;
901556Srgrimes	int nleft;
911556Srgrimes	struct block *start;
921556Srgrimes	struct block *last;
938855Srgrimes};
941556Srgrimes
951556Srgrimesstruct block {
961556Srgrimes	struct block *next;
971556Srgrimes	char text[BLOCKSIZE];
981556Srgrimes};
991556Srgrimes
1001556Srgrimes
1011556Srgrimes/*
1021556Srgrimes * There is one event structure for each event that mkinit handles.
1031556Srgrimes */
1041556Srgrimes
1051556Srgrimesstruct event {
1061556Srgrimes	char *name;		/* name of event (e.g. INIT) */
1071556Srgrimes	char *routine;		/* name of routine called on event */
1081556Srgrimes	char *comment;		/* comment describing routine */
10920425Ssteve	struct text code;	/* code for handling event */
1101556Srgrimes};
1111556Srgrimes
1121556Srgrimes
1131556Srgrimeschar writer[] = "\
1141556Srgrimes/*\n\
1151556Srgrimes * This file was generated by the mkinit program.\n\
1161556Srgrimes */\n\
1171556Srgrimes\n";
1181556Srgrimes
1191556Srgrimeschar init[] = "\
1201556Srgrimes/*\n\
1211556Srgrimes * Initialization code.\n\
1221556Srgrimes */\n";
1231556Srgrimes
1241556Srgrimeschar reset[] = "\
1251556Srgrimes/*\n\
1261556Srgrimes * This routine is called when an error or an interrupt occurs in an\n\
1271556Srgrimes * interactive shell and control is returned to the main command loop.\n\
1281556Srgrimes */\n";
1291556Srgrimes
1301556Srgrimeschar shellproc[] = "\
1311556Srgrimes/*\n\
1321556Srgrimes * This routine is called to initialize the shell to run a shell procedure.\n\
1331556Srgrimes */\n";
1341556Srgrimes
1351556Srgrimes
1361556Srgrimesstruct event event[] = {
1371556Srgrimes	{"INIT", "init", init},
1381556Srgrimes	{"RESET", "reset", reset},
1391556Srgrimes	{"SHELLPROC", "initshellproc", shellproc},
1401556Srgrimes	{NULL, NULL}
1411556Srgrimes};
1421556Srgrimes
1431556Srgrimes
1441556Srgrimeschar *curfile;				/* current file */
1451556Srgrimesint linno;				/* current line */
1461556Srgrimeschar *header_files[200];		/* list of header files */
1471556Srgrimesstruct text defines;			/* #define statements */
1481556Srgrimesstruct text decls;			/* declarations */
1491556Srgrimesint amiddecls;				/* for formatting */
1501556Srgrimes
1511556Srgrimes
15217987Spetervoid readfile __P((char *));
15317987Speterint match __P((char *, char *));
15417987Speterint gooddefine __P((char *));
15517987Spetervoid doevent __P((struct event *, FILE *, char *));
15617987Spetervoid doinclude __P((char *));
15717987Spetervoid dodecl __P((char *, FILE *));
15817987Spetervoid output __P((void));
15917987Spetervoid addstr __P((char *, struct text *));
16017987Spetervoid addchar __P((int, struct text *));
16117987Spetervoid writetext __P((struct text *, FILE *));
16217987SpeterFILE *ckfopen __P((char *, char *));
16317987Spetervoid *ckmalloc __P((int));
16420425Sstevechar *savestr __P((char *));
16520425Sstevevoid error __P((char *));
1661556Srgrimes
1671556Srgrimes#define equal(s1, s2)	(strcmp(s1, s2) == 0)
1681556Srgrimes
16917987Speterint
1701556Srgrimesmain(argc, argv)
17117987Speter	int argc;
1721556Srgrimes	char **argv;
17317987Speter{
1741556Srgrimes	char **ap;
1751556Srgrimes
1761556Srgrimes	header_files[0] = "\"shell.h\"";
1771556Srgrimes	header_files[1] = "\"mystring.h\"";
17817987Speter	for (ap = argv + 1 ; *ap ; ap++)
1791556Srgrimes		readfile(*ap);
1801556Srgrimes	output();
18120425Ssteve	rename(OUTTEMP, OUTFILE);
18217987Speter	exit(0);
1831556Srgrimes}
1841556Srgrimes
1851556Srgrimes
1861556Srgrimes/*
1871556Srgrimes * Parse an input file.
1881556Srgrimes */
1891556Srgrimes
1901556Srgrimesvoid
1911556Srgrimesreadfile(fname)
1921556Srgrimes	char *fname;
1931556Srgrimes	{
1941556Srgrimes	FILE *fp;
19520425Ssteve	char line[1024];
1961556Srgrimes	struct event *ep;
1971556Srgrimes
1981556Srgrimes	fp = ckfopen(fname, "r");
1991556Srgrimes	curfile = fname;
2001556Srgrimes	linno = 0;
2011556Srgrimes	amiddecls = 0;
2021556Srgrimes	while (fgets(line, sizeof line, fp) != NULL) {
2031556Srgrimes		linno++;
2041556Srgrimes		for (ep = event ; ep->name ; ep++) {
2051556Srgrimes			if (line[0] == ep->name[0] && match(ep->name, line)) {
2061556Srgrimes				doevent(ep, fp, fname);
2071556Srgrimes				break;
2081556Srgrimes			}
2091556Srgrimes		}
2101556Srgrimes		if (line[0] == 'I' && match("INCLUDE", line))
2111556Srgrimes			doinclude(line);
2121556Srgrimes		if (line[0] == 'M' && match("MKINIT", line))
2131556Srgrimes			dodecl(line, fp);
21411113Sjoerg		if (line[0] == '#' && gooddefine(line)) {
21511113Sjoerg			char *cp;
21620425Ssteve			char line2[1024];
21720425Ssteve			static const char undef[] = "#undef ";
21811113Sjoerg
21911113Sjoerg			strcpy(line2, line);
22020425Ssteve			memcpy(line2, undef, sizeof(undef) - 1);
22120425Ssteve			cp = line2 + sizeof(undef) - 1;
22211113Sjoerg			while(*cp && (*cp == ' ' || *cp == '\t'))
22320425Ssteve			        cp++;
22411113Sjoerg			while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
22520425Ssteve			        cp++;
22611113Sjoerg			*cp++ = '\n'; *cp = '\0';
22711113Sjoerg			addstr(line2, &defines);
2281556Srgrimes			addstr(line, &defines);
22911113Sjoerg		}
2301556Srgrimes	}
2311556Srgrimes	fclose(fp);
2321556Srgrimes}
2331556Srgrimes
2341556Srgrimes
2351556Srgrimesint
2361556Srgrimesmatch(name, line)
2371556Srgrimes	char *name;
2381556Srgrimes	char *line;
23917987Speter{
2401556Srgrimes	register char *p, *q;
2411556Srgrimes
2421556Srgrimes	p = name, q = line;
2431556Srgrimes	while (*p) {
2441556Srgrimes		if (*p++ != *q++)
2451556Srgrimes			return 0;
2461556Srgrimes	}
2471556Srgrimes	if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
2481556Srgrimes		return 0;
2491556Srgrimes	return 1;
2501556Srgrimes}
2511556Srgrimes
2521556Srgrimes
2531556Srgrimesint
2541556Srgrimesgooddefine(line)
2551556Srgrimes	char *line;
25617987Speter{
2571556Srgrimes	register char *p;
2581556Srgrimes
2591556Srgrimes	if (! match("#define", line))
2601556Srgrimes		return 0;			/* not a define */
2611556Srgrimes	p = line + 7;
2621556Srgrimes	while (*p == ' ' || *p == '\t')
2631556Srgrimes		p++;
2641556Srgrimes	while (*p != ' ' && *p != '\t') {
2651556Srgrimes		if (*p == '(')
2661556Srgrimes			return 0;		/* macro definition */
2671556Srgrimes		p++;
2681556Srgrimes	}
2691556Srgrimes	while (*p != '\n' && *p != '\0')
2701556Srgrimes		p++;
2711556Srgrimes	if (p[-1] == '\\')
2721556Srgrimes		return 0;			/* multi-line definition */
2731556Srgrimes	return 1;
2741556Srgrimes}
2751556Srgrimes
2761556Srgrimes
2771556Srgrimesvoid
2781556Srgrimesdoevent(ep, fp, fname)
2791556Srgrimes	register struct event *ep;
2801556Srgrimes	FILE *fp;
2811556Srgrimes	char *fname;
2821556Srgrimes	{
2831556Srgrimes	char line[1024];
2841556Srgrimes	int indent;
2851556Srgrimes	char *p;
2861556Srgrimes
2871556Srgrimes	sprintf(line, "\n      /* from %s: */\n", fname);
2881556Srgrimes	addstr(line, &ep->code);
2891556Srgrimes	addstr("      {\n", &ep->code);
2901556Srgrimes	for (;;) {
2911556Srgrimes		linno++;
2921556Srgrimes		if (fgets(line, sizeof line, fp) == NULL)
2931556Srgrimes			error("Unexpected EOF");
2941556Srgrimes		if (equal(line, "}\n"))
2951556Srgrimes			break;
2961556Srgrimes		indent = 6;
2971556Srgrimes		for (p = line ; *p == '\t' ; p++)
2981556Srgrimes			indent += 8;
2991556Srgrimes		for ( ; *p == ' ' ; p++)
3001556Srgrimes			indent++;
3011556Srgrimes		if (*p == '\n' || *p == '#')
3021556Srgrimes			indent = 0;
3031556Srgrimes		while (indent >= 8) {
3041556Srgrimes			addchar('\t', &ep->code);
3051556Srgrimes			indent -= 8;
3061556Srgrimes		}
3071556Srgrimes		while (indent > 0) {
3081556Srgrimes			addchar(' ', &ep->code);
3091556Srgrimes			indent--;
3101556Srgrimes		}
3111556Srgrimes		addstr(p, &ep->code);
3121556Srgrimes	}
3131556Srgrimes	addstr("      }\n", &ep->code);
3141556Srgrimes}
3151556Srgrimes
3161556Srgrimes
3171556Srgrimesvoid
3181556Srgrimesdoinclude(line)
3191556Srgrimes	char *line;
3201556Srgrimes	{
3211556Srgrimes	register char *p;
3221556Srgrimes	char *name;
3231556Srgrimes	register char **pp;
3241556Srgrimes
3251556Srgrimes	for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
3261556Srgrimes	if (*p == '\0')
3271556Srgrimes		error("Expecting '\"' or '<'");
3281556Srgrimes	name = p;
3291556Srgrimes	while (*p != ' ' && *p != '\t' && *p != '\n')
3301556Srgrimes		p++;
3311556Srgrimes	if (p[-1] != '"' && p[-1] != '>')
3321556Srgrimes		error("Missing terminator");
3331556Srgrimes	*p = '\0';
3341556Srgrimes
3351556Srgrimes	/* name now contains the name of the include file */
3361556Srgrimes	for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
3371556Srgrimes	if (*pp == NULL)
3381556Srgrimes		*pp = savestr(name);
3391556Srgrimes}
3401556Srgrimes
3411556Srgrimes
3421556Srgrimesvoid
3431556Srgrimesdodecl(line1, fp)
3441556Srgrimes	char *line1;
3451556Srgrimes	FILE *fp;
3461556Srgrimes	{
3471556Srgrimes	char line[1024];
3481556Srgrimes	register char *p, *q;
3491556Srgrimes
3501556Srgrimes	if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
3511556Srgrimes		addchar('\n', &decls);
3521556Srgrimes		do {
3531556Srgrimes			linno++;
3541556Srgrimes			if (fgets(line, sizeof line, fp) == NULL)
3551556Srgrimes				error("Unterminated structure declaration");
3561556Srgrimes			addstr(line, &decls);
3571556Srgrimes		} while (line[0] != '}');
3581556Srgrimes		amiddecls = 0;
3591556Srgrimes	} else {
3601556Srgrimes		if (! amiddecls)
3611556Srgrimes			addchar('\n', &decls);
3621556Srgrimes		q = NULL;
36320425Ssteve		for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
36420425Ssteve			continue;
3651556Srgrimes		if (*p == '=') {		/* eliminate initialization */
3661556Srgrimes			for (q = p ; *q && *q != ';' ; q++);
3671556Srgrimes			if (*q == '\0')
3681556Srgrimes				q = NULL;
3691556Srgrimes			else {
3701556Srgrimes				while (p[-1] == ' ')
3711556Srgrimes					p--;
3721556Srgrimes				*p = '\0';
3731556Srgrimes			}
3741556Srgrimes		}
3751556Srgrimes		addstr("extern", &decls);
3761556Srgrimes		addstr(line1 + 6, &decls);
3771556Srgrimes		if (q != NULL)
3781556Srgrimes			addstr(q, &decls);
3791556Srgrimes		amiddecls = 1;
3801556Srgrimes	}
3811556Srgrimes}
3821556Srgrimes
3831556Srgrimes
3841556Srgrimes
3851556Srgrimes/*
3861556Srgrimes * Write the output to the file OUTTEMP.
3871556Srgrimes */
3881556Srgrimes
3891556Srgrimesvoid
3901556Srgrimesoutput() {
3911556Srgrimes	FILE *fp;
3921556Srgrimes	char **pp;
3931556Srgrimes	struct event *ep;
3941556Srgrimes
3951556Srgrimes	fp = ckfopen(OUTTEMP, "w");
3961556Srgrimes	fputs(writer, fp);
3971556Srgrimes	for (pp = header_files ; *pp ; pp++)
3981556Srgrimes		fprintf(fp, "#include %s\n", *pp);
3991556Srgrimes	fputs("\n\n\n", fp);
4001556Srgrimes	writetext(&defines, fp);
4011556Srgrimes	fputs("\n\n", fp);
4021556Srgrimes	writetext(&decls, fp);
4031556Srgrimes	for (ep = event ; ep->name ; ep++) {
4041556Srgrimes		fputs("\n\n\n", fp);
4051556Srgrimes		fputs(ep->comment, fp);
4061556Srgrimes		fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
4071556Srgrimes		writetext(&ep->code, fp);
4081556Srgrimes		fprintf(fp, "}\n");
4091556Srgrimes	}
4101556Srgrimes	fclose(fp);
4111556Srgrimes}
4121556Srgrimes
4131556Srgrimes
4141556Srgrimes/*
4151556Srgrimes * A text structure is simply a block of text that is kept in memory.
4161556Srgrimes * Addstr appends a string to the text struct, and addchar appends a single
4171556Srgrimes * character.
4181556Srgrimes */
4191556Srgrimes
4201556Srgrimesvoid
4211556Srgrimesaddstr(s, text)
4221556Srgrimes	register char *s;
4231556Srgrimes	register struct text *text;
4241556Srgrimes	{
4251556Srgrimes	while (*s) {
4261556Srgrimes		if (--text->nleft < 0)
4271556Srgrimes			addchar(*s++, text);
4281556Srgrimes		else
4291556Srgrimes			*text->nextc++ = *s++;
4301556Srgrimes	}
4311556Srgrimes}
4321556Srgrimes
4331556Srgrimes
4341556Srgrimesvoid
4351556Srgrimesaddchar(c, text)
43617987Speter	int c;
4371556Srgrimes	register struct text *text;
43817987Speter{
4391556Srgrimes	struct block *bp;
4401556Srgrimes
4411556Srgrimes	if (--text->nleft < 0) {
4421556Srgrimes		bp = ckmalloc(sizeof *bp);
4431556Srgrimes		if (text->start == NULL)
4441556Srgrimes			text->start = bp;
4451556Srgrimes		else
4461556Srgrimes			text->last->next = bp;
4471556Srgrimes		text->last = bp;
4481556Srgrimes		text->nextc = bp->text;
4491556Srgrimes		text->nleft = BLOCKSIZE - 1;
4501556Srgrimes	}
4511556Srgrimes	*text->nextc++ = c;
4521556Srgrimes}
4531556Srgrimes
4541556Srgrimes/*
4551556Srgrimes * Write the contents of a text structure to a file.
4561556Srgrimes */
4571556Srgrimesvoid
4581556Srgrimeswritetext(text, fp)
4591556Srgrimes	struct text *text;
4601556Srgrimes	FILE *fp;
4611556Srgrimes	{
4621556Srgrimes	struct block *bp;
4631556Srgrimes
4641556Srgrimes	if (text->start != NULL) {
4651556Srgrimes		for (bp = text->start ; bp != text->last ; bp = bp->next)
4661556Srgrimes			fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
4671556Srgrimes		fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
4681556Srgrimes	}
4691556Srgrimes}
4701556Srgrimes
4711556SrgrimesFILE *
4721556Srgrimesckfopen(file, mode)
4731556Srgrimes	char *file;
4741556Srgrimes	char *mode;
4751556Srgrimes	{
4761556Srgrimes	FILE *fp;
4771556Srgrimes
4781556Srgrimes	if ((fp = fopen(file, mode)) == NULL) {
4791556Srgrimes		fprintf(stderr, "Can't open %s\n", file);
4801556Srgrimes		exit(2);
4811556Srgrimes	}
4821556Srgrimes	return fp;
4831556Srgrimes}
4841556Srgrimes
4851556Srgrimesvoid *
48620425Ssteveckmalloc(nbytes)
48717987Speter	int nbytes;
48817987Speter{
4891556Srgrimes	register char *p;
4901556Srgrimes
4911556Srgrimes	if ((p = malloc(nbytes)) == NULL)
4921556Srgrimes		error("Out of space");
4931556Srgrimes	return p;
4941556Srgrimes}
4951556Srgrimes
4961556Srgrimeschar *
4971556Srgrimessavestr(s)
4981556Srgrimes	char *s;
4991556Srgrimes	{
5001556Srgrimes	register char *p;
5011556Srgrimes
5021556Srgrimes	p = ckmalloc(strlen(s) + 1);
5031556Srgrimes	strcpy(p, s);
5041556Srgrimes	return p;
5051556Srgrimes}
5061556Srgrimes
5071556Srgrimesvoid
5081556Srgrimeserror(msg)
5091556Srgrimes	char *msg;
5101556Srgrimes	{
5111556Srgrimes	if (curfile != NULL)
5121556Srgrimes		fprintf(stderr, "%s:%d: ", curfile, linno);
5131556Srgrimes	fprintf(stderr, "%s\n", msg);
5141556Srgrimes	exit(2);
5151556Srgrimes}
516