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 * 4. Neither the name of the University nor the names of its contributors 171556Srgrimes * may be used to endorse or promote products derived from this software 181556Srgrimes * without specific prior written permission. 191556Srgrimes * 201556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301556Srgrimes * SUCH DAMAGE. 311556Srgrimes */ 321556Srgrimes 331556Srgrimes#ifndef lint 3420425Sstevestatic char const copyright[] = 351556Srgrimes"@(#) Copyright (c) 1991, 1993\n\ 361556Srgrimes The Regents of the University of California. All rights reserved.\n"; 371556Srgrimes#endif /* not lint */ 381556Srgrimes 391556Srgrimes#ifndef lint 4036150Scharnier#if 0 4136150Scharnierstatic char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95"; 4236150Scharnier#endif 431556Srgrimes#endif /* not lint */ 4499110Sobrien#include <sys/cdefs.h> 4599110Sobrien__FBSDID("$FreeBSD$"); 461556Srgrimes 471556Srgrimes/* 481556Srgrimes * This program scans all the source files for code to handle various 491556Srgrimes * special events and combines this code into one file. This (allegedly) 501556Srgrimes * improves the structure of the program since there is no need for 511556Srgrimes * anyone outside of a module to know that that module performs special 5217987Speter * operations on particular events. 531556Srgrimes * 5417987Speter * Usage: mkinit sourcefile... 551556Srgrimes */ 561556Srgrimes 571556Srgrimes 581556Srgrimes#include <sys/types.h> 591556Srgrimes#include <stdio.h> 6017987Speter#include <stdlib.h> 6117987Speter#include <string.h> 621556Srgrimes#include <fcntl.h> 631556Srgrimes#include <unistd.h> 6453891Scracauer#include <errno.h> 651556Srgrimes 661556Srgrimes 671556Srgrimes/* 681556Srgrimes * OUTFILE is the name of the output file. Output is initially written 6920425Ssteve * to the file OUTTEMP, which is then moved to OUTFILE. 701556Srgrimes */ 711556Srgrimes 721556Srgrimes#define OUTFILE "init.c" 731556Srgrimes#define OUTTEMP "init.c.new" 741556Srgrimes 751556Srgrimes 761556Srgrimes/* 77222178Suqs * A text structure is basically just a string that grows as more characters 781556Srgrimes * are added onto the end of it. It is implemented as a linked list of 791556Srgrimes * blocks of characters. The routines addstr and addchar append a string 801556Srgrimes * or a single character, respectively, to a text structure. Writetext 811556Srgrimes * writes the contents of a text structure to a file. 821556Srgrimes */ 831556Srgrimes 841556Srgrimes#define BLOCKSIZE 512 851556Srgrimes 861556Srgrimesstruct text { 871556Srgrimes char *nextc; 881556Srgrimes int nleft; 891556Srgrimes struct block *start; 901556Srgrimes struct block *last; 918855Srgrimes}; 921556Srgrimes 931556Srgrimesstruct block { 941556Srgrimes struct block *next; 951556Srgrimes char text[BLOCKSIZE]; 961556Srgrimes}; 971556Srgrimes 981556Srgrimes 991556Srgrimes/* 1001556Srgrimes * There is one event structure for each event that mkinit handles. 1011556Srgrimes */ 1021556Srgrimes 1031556Srgrimesstruct event { 104201053Sjilles const char *name; /* name of event (e.g. INIT) */ 105201053Sjilles const char *routine; /* name of routine called on event */ 106201053Sjilles const char *comment; /* comment describing routine */ 10720425Ssteve struct text code; /* code for handling event */ 1081556Srgrimes}; 1091556Srgrimes 1101556Srgrimes 1111556Srgrimeschar writer[] = "\ 1121556Srgrimes/*\n\ 1131556Srgrimes * This file was generated by the mkinit program.\n\ 1141556Srgrimes */\n\ 1151556Srgrimes\n"; 1161556Srgrimes 1171556Srgrimeschar init[] = "\ 1181556Srgrimes/*\n\ 1191556Srgrimes * Initialization code.\n\ 1201556Srgrimes */\n"; 1211556Srgrimes 1221556Srgrimeschar reset[] = "\ 1231556Srgrimes/*\n\ 1241556Srgrimes * This routine is called when an error or an interrupt occurs in an\n\ 1251556Srgrimes * interactive shell and control is returned to the main command loop.\n\ 1261556Srgrimes */\n"; 1271556Srgrimes 1281556Srgrimes 1291556Srgrimesstruct event event[] = { 130149019Sstefanf { "INIT", "init", init, { NULL, 0, NULL, NULL } }, 131149019Sstefanf { "RESET", "reset", reset, { NULL, 0, NULL, NULL } }, 132149019Sstefanf { NULL, NULL, NULL, { NULL, 0, NULL, NULL } } 1331556Srgrimes}; 1341556Srgrimes 1351556Srgrimes 136201053Sjillesconst char *curfile; /* current file */ 1371556Srgrimesint linno; /* current line */ 1381556Srgrimeschar *header_files[200]; /* list of header files */ 1391556Srgrimesstruct text defines; /* #define statements */ 1401556Srgrimesstruct text decls; /* declarations */ 1411556Srgrimesint amiddecls; /* for formatting */ 1421556Srgrimes 1431556Srgrimes 144201053Sjillesvoid readfile(const char *); 145201053Sjillesint match(const char *, const char *); 146201053Sjillesint gooddefine(const char *); 147201053Sjillesvoid doevent(struct event *, FILE *, const char *); 14890111Simpvoid doinclude(char *); 14990111Simpvoid dodecl(char *, FILE *); 15090111Simpvoid output(void); 151201053Sjillesvoid addstr(const char *, struct text *); 15290111Simpvoid addchar(int, struct text *); 15390111Simpvoid writetext(struct text *, FILE *); 154201053SjillesFILE *ckfopen(const char *, const char *); 155193221Srsevoid *ckmalloc(size_t); 156201053Sjilleschar *savestr(const char *); 157201053Sjillesvoid error(const char *); 1581556Srgrimes 1591556Srgrimes#define equal(s1, s2) (strcmp(s1, s2) == 0) 1601556Srgrimes 16117987Speterint 16290111Simpmain(int argc __unused, char *argv[]) 16317987Speter{ 1641556Srgrimes char **ap; 1651556Srgrimes 166201053Sjilles header_files[0] = savestr("\"shell.h\""); 167201053Sjilles header_files[1] = savestr("\"mystring.h\""); 168201053Sjilles header_files[2] = savestr("\"init.h\""); 16917987Speter for (ap = argv + 1 ; *ap ; ap++) 1701556Srgrimes readfile(*ap); 1711556Srgrimes output(); 17220425Ssteve rename(OUTTEMP, OUTFILE); 17317987Speter exit(0); 1741556Srgrimes} 1751556Srgrimes 1761556Srgrimes 1771556Srgrimes/* 1781556Srgrimes * Parse an input file. 1791556Srgrimes */ 1801556Srgrimes 1811556Srgrimesvoid 182201053Sjillesreadfile(const char *fname) 18390111Simp{ 1841556Srgrimes FILE *fp; 18520425Ssteve char line[1024]; 1861556Srgrimes struct event *ep; 1871556Srgrimes 1881556Srgrimes fp = ckfopen(fname, "r"); 1891556Srgrimes curfile = fname; 1901556Srgrimes linno = 0; 1911556Srgrimes amiddecls = 0; 1921556Srgrimes while (fgets(line, sizeof line, fp) != NULL) { 1931556Srgrimes linno++; 1941556Srgrimes for (ep = event ; ep->name ; ep++) { 1951556Srgrimes if (line[0] == ep->name[0] && match(ep->name, line)) { 1961556Srgrimes doevent(ep, fp, fname); 1971556Srgrimes break; 1981556Srgrimes } 1991556Srgrimes } 2001556Srgrimes if (line[0] == 'I' && match("INCLUDE", line)) 2011556Srgrimes doinclude(line); 2021556Srgrimes if (line[0] == 'M' && match("MKINIT", line)) 2031556Srgrimes dodecl(line, fp); 20411113Sjoerg if (line[0] == '#' && gooddefine(line)) { 20511113Sjoerg char *cp; 20620425Ssteve char line2[1024]; 20720425Ssteve static const char undef[] = "#undef "; 20811113Sjoerg 20911113Sjoerg strcpy(line2, line); 21020425Ssteve memcpy(line2, undef, sizeof(undef) - 1); 21120425Ssteve cp = line2 + sizeof(undef) - 1; 21211113Sjoerg while(*cp && (*cp == ' ' || *cp == '\t')) 21320425Ssteve cp++; 21411113Sjoerg while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n') 21520425Ssteve cp++; 21611113Sjoerg *cp++ = '\n'; *cp = '\0'; 21711113Sjoerg addstr(line2, &defines); 2181556Srgrimes addstr(line, &defines); 21911113Sjoerg } 2201556Srgrimes } 2211556Srgrimes fclose(fp); 2221556Srgrimes} 2231556Srgrimes 2241556Srgrimes 2251556Srgrimesint 226201053Sjillesmatch(const char *name, const char *line) 22717987Speter{ 228201053Sjilles const char *p, *q; 2291556Srgrimes 2301556Srgrimes p = name, q = line; 2311556Srgrimes while (*p) { 2321556Srgrimes if (*p++ != *q++) 2331556Srgrimes return 0; 2341556Srgrimes } 2351556Srgrimes if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n') 2361556Srgrimes return 0; 2371556Srgrimes return 1; 2381556Srgrimes} 2391556Srgrimes 2401556Srgrimes 2411556Srgrimesint 242201053Sjillesgooddefine(const char *line) 24317987Speter{ 244201053Sjilles const char *p; 2451556Srgrimes 2461556Srgrimes if (! match("#define", line)) 2471556Srgrimes return 0; /* not a define */ 2481556Srgrimes p = line + 7; 2491556Srgrimes while (*p == ' ' || *p == '\t') 2501556Srgrimes p++; 2511556Srgrimes while (*p != ' ' && *p != '\t') { 2521556Srgrimes if (*p == '(') 2531556Srgrimes return 0; /* macro definition */ 2541556Srgrimes p++; 2551556Srgrimes } 2561556Srgrimes while (*p != '\n' && *p != '\0') 2571556Srgrimes p++; 2581556Srgrimes if (p[-1] == '\\') 2591556Srgrimes return 0; /* multi-line definition */ 2601556Srgrimes return 1; 2611556Srgrimes} 2621556Srgrimes 2631556Srgrimes 2641556Srgrimesvoid 265201053Sjillesdoevent(struct event *ep, FILE *fp, const char *fname) 26690111Simp{ 2671556Srgrimes char line[1024]; 2681556Srgrimes int indent; 269201053Sjilles const char *p; 2701556Srgrimes 2711556Srgrimes sprintf(line, "\n /* from %s: */\n", fname); 2721556Srgrimes addstr(line, &ep->code); 2731556Srgrimes addstr(" {\n", &ep->code); 2741556Srgrimes for (;;) { 2751556Srgrimes linno++; 2761556Srgrimes if (fgets(line, sizeof line, fp) == NULL) 2771556Srgrimes error("Unexpected EOF"); 2781556Srgrimes if (equal(line, "}\n")) 2791556Srgrimes break; 2801556Srgrimes indent = 6; 2811556Srgrimes for (p = line ; *p == '\t' ; p++) 2821556Srgrimes indent += 8; 2831556Srgrimes for ( ; *p == ' ' ; p++) 2841556Srgrimes indent++; 2851556Srgrimes if (*p == '\n' || *p == '#') 2861556Srgrimes indent = 0; 2871556Srgrimes while (indent >= 8) { 2881556Srgrimes addchar('\t', &ep->code); 2891556Srgrimes indent -= 8; 2901556Srgrimes } 2911556Srgrimes while (indent > 0) { 2921556Srgrimes addchar(' ', &ep->code); 2931556Srgrimes indent--; 2941556Srgrimes } 2951556Srgrimes addstr(p, &ep->code); 2961556Srgrimes } 2971556Srgrimes addstr(" }\n", &ep->code); 2981556Srgrimes} 2991556Srgrimes 3001556Srgrimes 3011556Srgrimesvoid 30290111Simpdoinclude(char *line) 30390111Simp{ 30425222Ssteve char *p; 3051556Srgrimes char *name; 30625222Ssteve char **pp; 3071556Srgrimes 3081556Srgrimes for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++); 3091556Srgrimes if (*p == '\0') 3101556Srgrimes error("Expecting '\"' or '<'"); 3111556Srgrimes name = p; 3121556Srgrimes while (*p != ' ' && *p != '\t' && *p != '\n') 3131556Srgrimes p++; 3141556Srgrimes if (p[-1] != '"' && p[-1] != '>') 3151556Srgrimes error("Missing terminator"); 3161556Srgrimes *p = '\0'; 3171556Srgrimes 3181556Srgrimes /* name now contains the name of the include file */ 3191556Srgrimes for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++); 3201556Srgrimes if (*pp == NULL) 3211556Srgrimes *pp = savestr(name); 3221556Srgrimes} 3231556Srgrimes 3241556Srgrimes 3251556Srgrimesvoid 32690111Simpdodecl(char *line1, FILE *fp) 32790111Simp{ 3281556Srgrimes char line[1024]; 32925222Ssteve char *p, *q; 3301556Srgrimes 3311556Srgrimes if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */ 3321556Srgrimes addchar('\n', &decls); 3331556Srgrimes do { 3341556Srgrimes linno++; 3351556Srgrimes if (fgets(line, sizeof line, fp) == NULL) 3361556Srgrimes error("Unterminated structure declaration"); 3371556Srgrimes addstr(line, &decls); 3381556Srgrimes } while (line[0] != '}'); 3391556Srgrimes amiddecls = 0; 3401556Srgrimes } else { 3411556Srgrimes if (! amiddecls) 3421556Srgrimes addchar('\n', &decls); 3431556Srgrimes q = NULL; 34420425Ssteve for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++) 34520425Ssteve continue; 3461556Srgrimes if (*p == '=') { /* eliminate initialization */ 3471556Srgrimes for (q = p ; *q && *q != ';' ; q++); 3481556Srgrimes if (*q == '\0') 3491556Srgrimes q = NULL; 3501556Srgrimes else { 3511556Srgrimes while (p[-1] == ' ') 3521556Srgrimes p--; 3531556Srgrimes *p = '\0'; 3541556Srgrimes } 3551556Srgrimes } 3561556Srgrimes addstr("extern", &decls); 3571556Srgrimes addstr(line1 + 6, &decls); 3581556Srgrimes if (q != NULL) 3591556Srgrimes addstr(q, &decls); 3601556Srgrimes amiddecls = 1; 3611556Srgrimes } 3621556Srgrimes} 3631556Srgrimes 3641556Srgrimes 3651556Srgrimes 3661556Srgrimes/* 3671556Srgrimes * Write the output to the file OUTTEMP. 3681556Srgrimes */ 3691556Srgrimes 3701556Srgrimesvoid 37190111Simpoutput(void) 37290111Simp{ 3731556Srgrimes FILE *fp; 3741556Srgrimes char **pp; 3751556Srgrimes struct event *ep; 3761556Srgrimes 3771556Srgrimes fp = ckfopen(OUTTEMP, "w"); 3781556Srgrimes fputs(writer, fp); 3791556Srgrimes for (pp = header_files ; *pp ; pp++) 3801556Srgrimes fprintf(fp, "#include %s\n", *pp); 3811556Srgrimes fputs("\n\n\n", fp); 3821556Srgrimes writetext(&defines, fp); 3831556Srgrimes fputs("\n\n", fp); 3841556Srgrimes writetext(&decls, fp); 3851556Srgrimes for (ep = event ; ep->name ; ep++) { 3861556Srgrimes fputs("\n\n\n", fp); 3871556Srgrimes fputs(ep->comment, fp); 388149019Sstefanf fprintf(fp, "\nvoid\n%s(void)\n{\n", ep->routine); 3891556Srgrimes writetext(&ep->code, fp); 3901556Srgrimes fprintf(fp, "}\n"); 3911556Srgrimes } 3921556Srgrimes fclose(fp); 3931556Srgrimes} 3941556Srgrimes 3951556Srgrimes 3961556Srgrimes/* 3971556Srgrimes * A text structure is simply a block of text that is kept in memory. 3981556Srgrimes * Addstr appends a string to the text struct, and addchar appends a single 3991556Srgrimes * character. 4001556Srgrimes */ 4011556Srgrimes 4021556Srgrimesvoid 403201053Sjillesaddstr(const char *s, struct text *text) 40490111Simp{ 4051556Srgrimes while (*s) { 4061556Srgrimes if (--text->nleft < 0) 4071556Srgrimes addchar(*s++, text); 4081556Srgrimes else 4091556Srgrimes *text->nextc++ = *s++; 4101556Srgrimes } 4111556Srgrimes} 4121556Srgrimes 4131556Srgrimes 4141556Srgrimesvoid 41590111Simpaddchar(int c, struct text *text) 41617987Speter{ 4171556Srgrimes struct block *bp; 4181556Srgrimes 4191556Srgrimes if (--text->nleft < 0) { 4201556Srgrimes bp = ckmalloc(sizeof *bp); 4211556Srgrimes if (text->start == NULL) 4221556Srgrimes text->start = bp; 4231556Srgrimes else 4241556Srgrimes text->last->next = bp; 4251556Srgrimes text->last = bp; 4261556Srgrimes text->nextc = bp->text; 4271556Srgrimes text->nleft = BLOCKSIZE - 1; 4281556Srgrimes } 4291556Srgrimes *text->nextc++ = c; 4301556Srgrimes} 4311556Srgrimes 4321556Srgrimes/* 4331556Srgrimes * Write the contents of a text structure to a file. 4341556Srgrimes */ 4351556Srgrimesvoid 43690111Simpwritetext(struct text *text, FILE *fp) 43790111Simp{ 4381556Srgrimes struct block *bp; 4391556Srgrimes 4401556Srgrimes if (text->start != NULL) { 4411556Srgrimes for (bp = text->start ; bp != text->last ; bp = bp->next) 4421556Srgrimes fwrite(bp->text, sizeof (char), BLOCKSIZE, fp); 4431556Srgrimes fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp); 4441556Srgrimes } 4451556Srgrimes} 4461556Srgrimes 4471556SrgrimesFILE * 448201053Sjillesckfopen(const char *file, const char *mode) 44990111Simp{ 4501556Srgrimes FILE *fp; 4511556Srgrimes 4521556Srgrimes if ((fp = fopen(file, mode)) == NULL) { 45353891Scracauer fprintf(stderr, "Can't open %s: %s\n", file, strerror(errno)); 4541556Srgrimes exit(2); 4551556Srgrimes } 4561556Srgrimes return fp; 4571556Srgrimes} 4581556Srgrimes 4591556Srgrimesvoid * 460193221Srseckmalloc(size_t nbytes) 46117987Speter{ 46225222Ssteve char *p; 4631556Srgrimes 4641556Srgrimes if ((p = malloc(nbytes)) == NULL) 4651556Srgrimes error("Out of space"); 4661556Srgrimes return p; 4671556Srgrimes} 4681556Srgrimes 4691556Srgrimeschar * 470201053Sjillessavestr(const char *s) 47190111Simp{ 47225222Ssteve char *p; 4731556Srgrimes 4741556Srgrimes p = ckmalloc(strlen(s) + 1); 4751556Srgrimes strcpy(p, s); 4761556Srgrimes return p; 4771556Srgrimes} 4781556Srgrimes 4791556Srgrimesvoid 480201053Sjilleserror(const char *msg) 48190111Simp{ 4821556Srgrimes if (curfile != NULL) 4831556Srgrimes fprintf(stderr, "%s:%d: ", curfile, linno); 4841556Srgrimes fprintf(stderr, "%s\n", msg); 4851556Srgrimes exit(2); 4861556Srgrimes} 487