⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkinit.c

📁 操作系统源代码
💻 C
字号:
/*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 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 * SUCH DAMAGE. */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1991 The Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)mkinit.c	5.3 (Berkeley) 3/13/91";#endif /* not lint *//* * 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 * is actually changed. * * Usage:  mkinit command sourcefile... */#include <sys/cdefs.h>#include <sys/types.h>#include <stdio.h>#include <fcntl.h>/* * 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 * OUTFILE are different. */#define OUTFILE "init.c"#define OUTTEMP "init.c.new"#define OUTOBJ "init.o"/* * 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. */#define BLOCKSIZE 512struct text {	char *nextc;	int nleft;	struct block *start;	struct block *last;};      struct block {	struct block *next;	char text[BLOCKSIZE];};/* * There is one event structure for each event that mkinit handles. */struct event {	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 */};char writer[] = "\/*\n\ * This file was generated by the mkinit program.\n\ */\n\\n";char init[] = "\/*\n\ * Initialization code.\n\ */\n";char reset[] = "\/*\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\ */\n";char shellproc[] = "\/*\n\ * This routine is called to initialize the shell to run a shell procedure.\n\ */\n";struct event event[] = {	{"INIT", "init", init},	{"RESET", "reset", reset},	{"SHELLPROC", "initshellproc", shellproc},	{NULL, NULL}};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)FILE *ckfopen();char *savestr();void *ckmalloc __P((int));void error();main(argc, argv)	char **argv;	{	char **ap;	int fd;	char c;	if (argc < 2)		error("Usage:  mkinit command file...");	header_files[0] = "\"shell.h\"";	header_files[1] = "\"mystring.h\"";	for (ap = argv + 2 ; *ap ; ap++)		readfile(*ap);	output();	if (file_changed()) {		unlink(OUTFILE);		link(OUTTEMP, OUTFILE);		unlink(OUTTEMP);	} else {		unlink(OUTTEMP);		if (touch(OUTOBJ))			exit(0);		/* no compilation necessary */	}	printf("%s\n", argv[1]);	execl("/bin/sh", "sh", "-c", argv[1], (char *)0);	error("Can't exec shell");}/* * Parse an input file. */voidreadfile(fname)	char *fname;	{	FILE *fp;	char line[1024];	struct event *ep;	fp = ckfopen(fname, "r");	curfile = fname;	linno = 0;	amiddecls = 0;	while (fgets(line, sizeof line, fp) != NULL) {		linno++;		for (ep = event ; ep->name ; ep++) {			if (line[0] == ep->name[0] && match(ep->name, line)) {				doevent(ep, fp, fname);				break;			}		}		if (line[0] == 'I' && match("INCLUDE", line))			doinclude(line);		if (line[0] == 'M' && match("MKINIT", line))			dodecl(line, fp);		if (line[0] == '#' && gooddefine(line))			addstr(line, &defines);	}	fclose(fp);}intmatch(name, line)	char *name;	char *line;	{	register char *p, *q;	p = name, q = line;	while (*p) {		if (*p++ != *q++)			return 0;	}	if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')		return 0;	return 1;}intgooddefine(line)	char *line;	{	register char *p;	if (! match("#define", line))		return 0;			/* not a define */	p = line + 7;	while (*p == ' ' || *p == '\t')		p++;	while (*p != ' ' && *p != '\t') {		if (*p == '(')			return 0;		/* macro definition */		p++;	}	while (*p != '\n' && *p != '\0')		p++;	if (p[-1] == '\\')		return 0;			/* multi-line definition */	return 1;}voiddoevent(ep, fp, fname)	register struct event *ep;	FILE *fp;	char *fname;	{	char line[1024];	int indent;	char *p;	sprintf(line, "\n      /* from %s: */\n", fname);	addstr(line, &ep->code);	addstr("      {\n", &ep->code);	for (;;) {		linno++;		if (fgets(line, sizeof line, fp) == NULL)			error("Unexpected EOF");		if (equal(line, "}\n"))			break;		indent = 6;		for (p = line ; *p == '\t' ; p++)			indent += 8;		for ( ; *p == ' ' ; p++)			indent++;		if (*p == '\n' || *p == '#')			indent = 0;		while (indent >= 8) {			addchar('\t', &ep->code);			indent -= 8;		}		while (indent > 0) {			addchar(' ', &ep->code);			indent--;		}		addstr(p, &ep->code);	}	addstr("      }\n", &ep->code);}voiddoinclude(line)	char *line;	{	register char *p;	char *name;	register char **pp;	for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);	if (*p == '\0')		error("Expecting '\"' or '<'");	name = p;	while (*p != ' ' && *p != '\t' && *p != '\n')		p++;	if (p[-1] != '"' && p[-1] != '>')		error("Missing terminator");	*p = '\0';	/* name now contains the name of the include file */	for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);	if (*pp == NULL)		*pp = savestr(name);}voiddodecl(line1, fp)	char *line1;	FILE *fp;	{	char line[1024];	register char *p, *q;	if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */		addchar('\n', &decls);		do {			linno++;			if (fgets(line, sizeof line, fp) == NULL)				error("Unterminated structure declaration");			addstr(line, &decls);		} while (line[0] != '}');		amiddecls = 0;	} else {		if (! amiddecls)			addchar('\n', &decls);		q = NULL;		for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++);		if (*p == '=') {		/* eliminate initialization */			for (q = p ; *q && *q != ';' ; q++);			if (*q == '\0')				q = NULL;			else {				while (p[-1] == ' ')					p--;				*p = '\0';			}		}		addstr("extern", &decls);		addstr(line1 + 6, &decls);		if (q != NULL)			addstr(q, &decls);		amiddecls = 1;	}}/* * Write the output to the file OUTTEMP. */voidoutput() {	FILE *fp;	char **pp;	struct event *ep;	fp = ckfopen(OUTTEMP, "w");	fputs(writer, fp);	for (pp = header_files ; *pp ; pp++)		fprintf(fp, "#include %s\n", *pp);	fputs("\n\n\n", fp);	writetext(&defines, fp);	fputs("\n\n", fp);	writetext(&decls, fp);	for (ep = event ; ep->name ; ep++) {		fputs("\n\n\n", fp);		fputs(ep->comment, fp);		fprintf(fp, "\nvoid\n%s() {\n", ep->routine);		writetext(&ep->code, fp);		fprintf(fp, "}\n");	}	fclose(fp);}/* * Return true if the new output file is different from the old one. */intfile_changed() {	register FILE *f1, *f2;	register int c;	if ((f1 = fopen(OUTFILE, "r")) == NULL	 || (f2 = fopen(OUTTEMP, "r")) == NULL)		return 1;	while ((c = getc(f1)) == getc(f2)) {		if (c == EOF)			return 0;	}	return 1;}/* * Touch a file.  Returns 0 on failure, 1 on success. */inttouch(file)	char *file;	{	int fd;	char c;	if ((fd = open(file, O_RDWR)) < 0)		return 0;	if (read(fd, &c, 1) != 1) {		close(fd);		return 0;	}	lseek(fd, 0L, 0);	write(fd, &c, 1);	close(fd);	return 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 * character. */voidaddstr(s, text)	register char *s;	register struct text *text;	{	while (*s) {		if (--text->nleft < 0)			addchar(*s++, text);		else			*text->nextc++ = *s++;	}}voidaddchar(c, text)	register struct text *text;	{	struct block *bp;	if (--text->nleft < 0) {		bp = ckmalloc(sizeof *bp);		if (text->start == NULL)			text->start = bp;		else			text->last->next = bp;		text->last = bp;		text->nextc = bp->text;		text->nleft = BLOCKSIZE - 1;	}	*text->nextc++ = c;}/* * Write the contents of a text structure to a file. */voidwritetext(text, fp)	struct text *text;	FILE *fp;	{	struct block *bp;	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);	}}FILE *ckfopen(file, mode)	char *file;	char *mode;	{	FILE *fp;	if ((fp = fopen(file, mode)) == NULL) {		fprintf(stderr, "Can't open %s\n", file);		exit(2);	}	return fp;}void *ckmalloc(nbytes) {	register char *p;	char *malloc();	if ((p = malloc(nbytes)) == NULL)		error("Out of space");	return p;}char *savestr(s)	char *s;	{	register char *p;	p = ckmalloc(strlen(s) + 1);	strcpy(p, s);	return p;}voiderror(msg)	char *msg;	{	if (curfile != NULL)		fprintf(stderr, "%s:%d: ", curfile, linno);	fprintf(stderr, "%s\n", msg);	exit(2);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -