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