00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef lint
00038 char copyright[] =
00039 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\
00040 All rights reserved.\n";
00041 #endif
00042
00043 #ifndef lint
00044 static char sccsid[] = "@(#)mkinit.c 5.3 (Berkeley) 3/13/91";
00045 #endif
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #include <sys/cdefs.h>
00060
00061 #include <sys/types.h>
00062 #include <stdio.h>
00063 #include <fcntl.h>
00064
00065
00066
00067
00068
00069
00070
00071
00072 #define OUTFILE "init.c"
00073 #define OUTTEMP "init.c.new"
00074 #define OUTOBJ "init.o"
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #define BLOCKSIZE 512
00086
00087 struct text {
00088 char *nextc;
00089 int nleft;
00090 struct block *start;
00091 struct block *last;
00092 };
00093
00094 struct block {
00095 struct block *next;
00096 char text[BLOCKSIZE];
00097 };
00098
00099
00100
00101
00102
00103
00104 struct event {
00105 char *name;
00106 char *routine;
00107 char *comment;
00108 struct text code;
00109 };
00110
00111
00112 char writer[] = "\
00113 /*\n\
00114 * This file was generated by the mkinit program.\n\
00115 */\n\
00116 \n";
00117
00118 char init[] = "\
00119 /*\n\
00120 * Initialization code.\n\
00121 */\n";
00122
00123 char reset[] = "\
00124 /*\n\
00125 * This routine is called when an error or an interrupt occurs in an\n\
00126 * interactive shell and control is returned to the main command loop.\n\
00127 */\n";
00128
00129 char shellproc[] = "\
00130 /*\n\
00131 * This routine is called to initialize the shell to run a shell procedure.\n\
00132 */\n";
00133
00134
00135 struct event event[] = {
00136 {"INIT", "init", init},
00137 {"RESET", "reset", reset},
00138 {"SHELLPROC", "initshellproc", shellproc},
00139 {NULL, NULL}
00140 };
00141
00142
00143 char *curfile;
00144 int linno;
00145 char *header_files[200];
00146 struct text defines;
00147 struct text decls;
00148 int amiddecls;
00149
00150
00151 void readfile(), doevent(), doinclude(), dodecl(), output();
00152 void addstr(), addchar(), writetext();
00153
00154 #define equal(s1, s2) (strcmp(s1, s2) == 0)
00155
00156 FILE *ckfopen();
00157 char *savestr();
00158 void *ckmalloc __P((int));
00159 void error();
00160
00161 main(argc, argv)
00162 char **argv;
00163 {
00164 char **ap;
00165 int fd;
00166 char c;
00167
00168 if (argc < 2)
00169 error("Usage: mkinit command file...");
00170 header_files[0] = "\"shell.h\"";
00171 header_files[1] = "\"mystring.h\"";
00172 for (ap = argv + 2 ; *ap ; ap++)
00173 readfile(*ap);
00174 output();
00175 if (file_changed()) {
00176 unlink(OUTFILE);
00177 link(OUTTEMP, OUTFILE);
00178 unlink(OUTTEMP);
00179 } else {
00180 unlink(OUTTEMP);
00181 if (touch(OUTOBJ))
00182 exit(0);
00183 }
00184 printf("%s\n", argv[1]);
00185 execl("/bin/sh", "sh", "-c", argv[1], (char *)0);
00186 error("Can't exec shell");
00187 }
00188
00189
00190
00191
00192
00193
00194 void
00195 readfile(fname)
00196 char *fname;
00197 {
00198 FILE *fp;
00199 char line[1024];
00200 struct event *ep;
00201
00202 fp = ckfopen(fname, "r");
00203 curfile = fname;
00204 linno = 0;
00205 amiddecls = 0;
00206 while (fgets(line, sizeof line, fp) != NULL) {
00207 linno++;
00208 for (ep = event ; ep->name ; ep++) {
00209 if (line[0] == ep->name[0] && match(ep->name, line)) {
00210 doevent(ep, fp, fname);
00211 break;
00212 }
00213 }
00214 if (line[0] == 'I' && match("INCLUDE", line))
00215 doinclude(line);
00216 if (line[0] == 'M' && match("MKINIT", line))
00217 dodecl(line, fp);
00218 if (line[0] == '#' && gooddefine(line))
00219 addstr(line, &defines);
00220 }
00221 fclose(fp);
00222 }
00223
00224
00225 int
00226 match(name, line)
00227 char *name;
00228 char *line;
00229 {
00230 register char *p, *q;
00231
00232 p = name, q = line;
00233 while (*p) {
00234 if (*p++ != *q++)
00235 return 0;
00236 }
00237 if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
00238 return 0;
00239 return 1;
00240 }
00241
00242
00243 int
00244 gooddefine(line)
00245 char *line;
00246 {
00247 register char *p;
00248
00249 if (! match("#define", line))
00250 return 0;
00251 p = line + 7;
00252 while (*p == ' ' || *p == '\t')
00253 p++;
00254 while (*p != ' ' && *p != '\t') {
00255 if (*p == '(')
00256 return 0;
00257 p++;
00258 }
00259 while (*p != '\n' && *p != '\0')
00260 p++;
00261 if (p[-1] == '\\')
00262 return 0;
00263 return 1;
00264 }
00265
00266
00267 void
00268 doevent(ep, fp, fname)
00269 register struct event *ep;
00270 FILE *fp;
00271 char *fname;
00272 {
00273 char line[1024];
00274 int indent;
00275 char *p;
00276
00277 sprintf(line, "\n /* from %s: */\n", fname);
00278 addstr(line, &ep->code);
00279 addstr(" {\n", &ep->code);
00280 for (;;) {
00281 linno++;
00282 if (fgets(line, sizeof line, fp) == NULL)
00283 error("Unexpected EOF");
00284 if (equal(line, "}\n"))
00285 break;
00286 indent = 6;
00287 for (p = line ; *p == '\t' ; p++)
00288 indent += 8;
00289 for ( ; *p == ' ' ; p++)
00290 indent++;
00291 if (*p == '\n' || *p == '#')
00292 indent = 0;
00293 while (indent >= 8) {
00294 addchar('\t', &ep->code);
00295 indent -= 8;
00296 }
00297 while (indent > 0) {
00298 addchar(' ', &ep->code);
00299 indent--;
00300 }
00301 addstr(p, &ep->code);
00302 }
00303 addstr(" }\n", &ep->code);
00304 }
00305
00306
00307 void
00308 doinclude(line)
00309 char *line;
00310 {
00311 register char *p;
00312 char *name;
00313 register char **pp;
00314
00315 for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
00316 if (*p == '\0')
00317 error("Expecting '\"' or '<'");
00318 name = p;
00319 while (*p != ' ' && *p != '\t' && *p != '\n')
00320 p++;
00321 if (p[-1] != '"' && p[-1] != '>')
00322 error("Missing terminator");
00323 *p = '\0';
00324
00325
00326 for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
00327 if (*pp == NULL)
00328 *pp = savestr(name);
00329 }
00330
00331
00332 void
00333 dodecl(line1, fp)
00334 char *line1;
00335 FILE *fp;
00336 {
00337 char line[1024];
00338 register char *p, *q;
00339
00340 if (strcmp(line1, "MKINIT\n") == 0) {
00341 addchar('\n', &decls);
00342 do {
00343 linno++;
00344 if (fgets(line, sizeof line, fp) == NULL)
00345 error("Unterminated structure declaration");
00346 addstr(line, &decls);
00347 } while (line[0] != '}');
00348 amiddecls = 0;
00349 } else {
00350 if (! amiddecls)
00351 addchar('\n', &decls);
00352 q = NULL;
00353 for (p = line1 + 6 ; *p != '=' && *p != '/' ; p++);
00354 if (*p == '=') {
00355 for (q = p ; *q && *q != ';' ; q++);
00356 if (*q == '\0')
00357 q = NULL;
00358 else {
00359 while (p[-1] == ' ')
00360 p--;
00361 *p = '\0';
00362 }
00363 }
00364 addstr("extern", &decls);
00365 addstr(line1 + 6, &decls);
00366 if (q != NULL)
00367 addstr(q, &decls);
00368 amiddecls = 1;
00369 }
00370 }
00371
00372
00373
00374
00375
00376
00377
00378 void
00379 output() {
00380 FILE *fp;
00381 char **pp;
00382 struct event *ep;
00383
00384 fp = ckfopen(OUTTEMP, "w");
00385 fputs(writer, fp);
00386 for (pp = header_files ; *pp ; pp++)
00387 fprintf(fp, "#include %s\n", *pp);
00388 fputs("\n\n\n", fp);
00389 writetext(&defines, fp);
00390 fputs("\n\n", fp);
00391 writetext(&decls, fp);
00392 for (ep = event ; ep->name ; ep++) {
00393 fputs("\n\n\n", fp);
00394 fputs(ep->comment, fp);
00395 fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
00396 writetext(&ep->code, fp);
00397 fprintf(fp, "}\n");
00398 }
00399 fclose(fp);
00400 }
00401
00402
00403
00404
00405
00406
00407 int
00408 file_changed() {
00409 register FILE *f1, *f2;
00410 register int c;
00411
00412 if ((f1 = fopen(OUTFILE, "r")) == NULL
00413 || (f2 = fopen(OUTTEMP, "r")) == NULL)
00414 return 1;
00415 while ((c = getc(f1)) == getc(f2)) {
00416 if (c == EOF)
00417 return 0;
00418 }
00419 return 1;
00420 }
00421
00422
00423
00424
00425
00426
00427 int
00428 touch(file)
00429 char *file;
00430 {
00431 int fd;
00432 char c;
00433
00434 if ((fd = open(file, O_RDWR)) < 0)
00435 return 0;
00436 if (read(fd, &c, 1) != 1) {
00437 close(fd);
00438 return 0;
00439 }
00440 lseek(fd, 0L, 0);
00441 write(fd, &c, 1);
00442 close(fd);
00443 return 1;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 void
00455 addstr(s, text)
00456 register char *s;
00457 register struct text *text;
00458 {
00459 while (*s) {
00460 if (--text->nleft < 0)
00461 addchar(*s++, text);
00462 else
00463 *text->nextc++ = *s++;
00464 }
00465 }
00466
00467
00468 void
00469 addchar(c, text)
00470 register struct text *text;
00471 {
00472 struct block *bp;
00473
00474 if (--text->nleft < 0) {
00475 bp = ckmalloc(sizeof *bp);
00476 if (text->start == NULL)
00477 text->start = bp;
00478 else
00479 text->last->next = bp;
00480 text->last = bp;
00481 text->nextc = bp->text;
00482 text->nleft = BLOCKSIZE - 1;
00483 }
00484 *text->nextc++ = c;
00485 }
00486
00487
00488
00489
00490 void
00491 writetext(text, fp)
00492 struct text *text;
00493 FILE *fp;
00494 {
00495 struct block *bp;
00496
00497 if (text->start != NULL) {
00498 for (bp = text->start ; bp != text->last ; bp = bp->next)
00499 fwrite(bp->text, sizeof (char), BLOCKSIZE, fp);
00500 fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp);
00501 }
00502 }
00503
00504 FILE *
00505 ckfopen(file, mode)
00506 char *file;
00507 char *mode;
00508 {
00509 FILE *fp;
00510
00511 if ((fp = fopen(file, mode)) == NULL) {
00512 fprintf(stderr, "Can't open %s\n", file);
00513 exit(2);
00514 }
00515 return fp;
00516 }
00517
00518 void *
00519 ckmalloc(nbytes) {
00520 register char *p;
00521 char *malloc();
00522
00523 if ((p = malloc(nbytes)) == NULL)
00524 error("Out of space");
00525 return p;
00526 }
00527
00528 char *
00529 savestr(s)
00530 char *s;
00531 {
00532 register char *p;
00533
00534 p = ckmalloc(strlen(s) + 1);
00535 strcpy(p, s);
00536 return p;
00537 }
00538
00539 void
00540 error(msg)
00541 char *msg;
00542 {
00543 if (curfile != NULL)
00544 fprintf(stderr, "%s:%d: ", curfile, linno);
00545 fprintf(stderr, "%s\n", msg);
00546 exit(2);
00547 }