home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i005: A reimplementation of the System V shell, Part05/08
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: ka@june.cs.washington.edu (Kenneth Almquist)
- Posting-number: Volume 19, Issue 5
- Archive-name: ash/part05
-
- # This is part 5 of ash. To unpack, feed it into the shell (not csh).
- # The ash distribution consists of eight pieces. Be sure you get them all.
- # After you unpack everything, read the file README.
-
- echo extracting mkinit.c
- cat > mkinit.c <<\EOF
- /*
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- *
- * Usage: mkinit command sourcefile...
- *
- * 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.
- */
-
-
- #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 512
-
- struct 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();
- #ifdef __STDC__
- void *ckmalloc(int);
- #else
- char *ckmalloc();
- #endif
- 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.
- */
-
- void
- readfile(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);
- }
-
-
- int
- match(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;
- }
-
-
- int
- gooddefine(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;
- }
-
-
- void
- doevent(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);
- }
-
-
- void
- doinclude(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);
- }
-
-
- void
- dodecl(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.
- */
-
- void
- output() {
- 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.
- */
-
- int
- file_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.
- */
-
- int
- touch(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.
- */
-
- void
- addstr(s, text)
- register char *s;
- register struct text *text;
- {
- while (*s) {
- if (--text->nleft < 0)
- addchar(*s++, text);
- else
- *text->nextc++ = *s++;
- }
- }
-
-
- void
- addchar(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.
- */
-
- void
- writetext(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;
- }
-
-
-
- #ifdef __STDC__
- void *
- #else
- char *
- #endif
- 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;
- }
-
-
-
- void
- error(msg)
- char *msg;
- {
- if (curfile != NULL)
- fprintf(stderr, "%s:%d: ", curfile, linno);
- fprintf(stderr, "%s\n", msg);
- exit(2);
- }
- EOF
- if test `wc -c < mkinit.c` -ne 10550
- then echo 'mkinit.c is the wrong size'
- fi
- echo extracting mknodes.c
- cat > mknodes.c <<\EOF
- /*
- * This program reads the nodetypes file and nodes.c.pat file. It generates
- * the files nodes.h and nodes.c.
- *
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
-
- #include <stdio.h>
-
-
- #define MAXTYPES 50 /* max number of node types */
- #define MAXFIELDS 20 /* max fields in a structure */
- #define BUFLEN 100 /* size of character buffers */
-
- /* field types */
- #define T_NODE 1 /* union node *field */
- #define T_NODELIST 2 /* struct nodelist *field */
- #define T_STRING 3
- #define T_INT 4 /* int field */
- #define T_OTHER 5 /* other */
- #define T_TEMP 6 /* don't copy this field */
-
-
- struct field { /* a structure field */
- char *name; /* name of field */
- int type; /* type of field */
- char *decl; /* declaration of field */
- };
-
-
- struct str { /* struct representing a node structure */
- char *tag; /* structure tag */
- int nfields; /* number of fields in the structure */
- struct field field[MAXFIELDS]; /* the fields of the structure */
- int done; /* set if fully parsed */
- };
-
-
- int ntypes; /* number of node types */
- char *nodename[MAXTYPES]; /* names of the nodes */
- struct str *nodestr[MAXTYPES]; /* type of structure used by the node */
- int nstr; /* number of structures */
- struct str str[MAXTYPES]; /* the structures */
- struct str *curstr; /* current structure */
-
-
- FILE *infp = stdin;
- char line[1024];
- int linno;
- char *linep;
-
-
- char *savestr();
- #define equal(s1, s2) (strcmp(s1, s2) == 0)
-
-
- main(argc, argv)
- char **argv;
- {
- if ((infp = fopen("nodetypes", "r")) == NULL)
- error("Can't open nodetypes");
- while (readline()) {
- if (line[0] == ' ' || line[0] == '\t')
- parsefield();
- else if (line[0] != '\0')
- parsenode();
- }
- output();
- }
-
-
-
- parsenode() {
- char name[BUFLEN];
- char tag[BUFLEN];
- struct str *sp;
-
- if (curstr && curstr->nfields > 0)
- curstr->done = 1;
- nextfield(name);
- if (! nextfield(tag))
- error("Tag expected");
- if (*linep != '\0')
- error("Garbage at end of line");
- nodename[ntypes] = savestr(name);
- for (sp = str ; sp < str + nstr ; sp++) {
- if (equal(sp->tag, tag))
- break;
- }
- if (sp >= str + nstr) {
- sp->tag = savestr(tag);
- sp->nfields = 0;
- curstr = sp;
- nstr++;
- }
- nodestr[ntypes] = sp;
- ntypes++;
- }
-
-
- parsefield() {
- char name[BUFLEN];
- char type[BUFLEN];
- char decl[2 * BUFLEN];
- struct field *fp;
-
- if (curstr == NULL || curstr->done)
- error("No current structure to add field to");
- if (! nextfield(name))
- error("No field name");
- if (! nextfield(type))
- error("No field type");
- fp = &curstr->field[curstr->nfields];
- fp->name = savestr(name);
- if (equal(type, "nodeptr")) {
- fp->type = T_NODE;
- sprintf(decl, "union node *%s", name);
- } else if (equal(type, "nodelist")) {
- fp->type = T_NODELIST;
- sprintf(decl, "struct nodelist *%s", name);
- } else if (equal(type, "string")) {
- fp->type = T_STRING;
- sprintf(decl, "char *%s", name);
- } else if (equal(type, "int")) {
- fp->type = T_INT;
- sprintf(decl, "int %s", name);
- } else if (equal(type, "other")) {
- fp->type = T_OTHER;
- } else if (equal(type, "temp")) {
- fp->type = T_TEMP;
- } else {
- error("Unknown type %s", type);
- }
- if (fp->type == T_OTHER || fp->type == T_TEMP) {
- skipbl();
- fp->decl = savestr(linep);
- } else {
- if (*linep)
- error("Garbage at end of line");
- fp->decl = savestr(decl);
- }
- curstr->nfields++;
- }
-
-
- char writer[] = "\
- /*\n\
- * This file was generated by the mknodes program.\n\
- */\n\
- \n";
-
- output() {
- FILE *hfile;
- FILE *cfile;
- FILE *patfile;
- int i;
- struct str *sp;
- struct field *fp;
- char *p;
-
- if ((patfile = fopen("nodes.c.pat", "r")) == NULL)
- error("Can't open nodes.c.pat");
- if ((hfile = fopen("nodes.h", "w")) == NULL)
- error("Can't create nodes.h");
- if ((cfile = fopen("nodes.c", "w")) == NULL)
- error("Can't create nodes.c");
- fputs(writer, hfile);
- for (i = 0 ; i < ntypes ; i++)
- fprintf(hfile, "#define %s %d\n", nodename[i], i);
- fputs("\n\n\n", hfile);
- for (sp = str ; sp < &str[nstr] ; sp++) {
- fprintf(hfile, "struct %s {\n", sp->tag);
- for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
- fprintf(hfile, " %s;\n", fp->decl);
- }
- fputs("};\n\n\n", hfile);
- }
- fputs("union node {\n", hfile);
- fprintf(hfile, " int type;\n");
- for (sp = str ; sp < &str[nstr] ; sp++) {
- fprintf(hfile, " struct %s %s;\n", sp->tag, sp->tag);
- }
- fputs("};\n\n\n", hfile);
- fputs("struct nodelist {\n", hfile);
- fputs("\tstruct nodelist *next;\n", hfile);
- fputs("\tunion node *n;\n", hfile);
- fputs("};\n\n\n", hfile);
- fputs("#ifdef __STDC__\n", hfile);
- fputs("union node *copyfunc(union node *);\n", hfile);
- fputs("void freefunc(union node *);\n", hfile);
- fputs("#else\n", hfile);
- fputs("union node *copyfunc();\n", hfile);
- fputs("void freefunc();\n", hfile);
- fputs("#endif\n", hfile);
-
- fputs(writer, cfile);
- while (fgets(line, sizeof line, patfile) != NULL) {
- for (p = line ; *p == ' ' || *p == '\t' ; p++);
- if (equal(p, "%SIZES\n"))
- outsizes(cfile);
- else if (equal(p, "%CALCSIZE\n"))
- outfunc(cfile, 1);
- else if (equal(p, "%COPY\n"))
- outfunc(cfile, 0);
- else
- fputs(line, cfile);
- }
- }
-
-
-
- outsizes(cfile)
- FILE *cfile;
- {
- int i;
-
- fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
- for (i = 0 ; i < ntypes ; i++) {
- fprintf(cfile, " ALIGN(sizeof (struct %s)),\n", nodestr[i]->tag);
- }
- fprintf(cfile, "};\n");
- }
-
-
- outfunc(cfile, calcsize)
- FILE *cfile;
- {
- struct str *sp;
- struct field *fp;
- int i;
-
- fputs(" if (n == NULL)\n", cfile);
- if (calcsize)
- fputs(" return;\n", cfile);
- else
- fputs(" return NULL;\n", cfile);
- if (calcsize)
- fputs(" funcblocksize += nodesize[n->type];\n", cfile);
- else {
- fputs(" new = funcblock;\n", cfile);
- fputs(" funcblock += nodesize[n->type];\n", cfile);
- }
- fputs(" switch (n->type) {\n", cfile);
- for (sp = str ; sp < &str[nstr] ; sp++) {
- for (i = 0 ; i < ntypes ; i++) {
- if (nodestr[i] == sp)
- fprintf(cfile, " case %s:\n", nodename[i]);
- }
- for (i = sp->nfields ; --i >= 1 ; ) {
- fp = &sp->field[i];
- switch (fp->type) {
- case T_NODE:
- if (calcsize) {
- indent(12, cfile);
- fprintf(cfile, "calcsize(n->%s.%s);\n",
- sp->tag, fp->name);
- } else {
- indent(12, cfile);
- fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
- sp->tag, fp->name, sp->tag, fp->name);
- }
- break;
- case T_NODELIST:
- if (calcsize) {
- indent(12, cfile);
- fprintf(cfile, "sizenodelist(n->%s.%s);\n",
- sp->tag, fp->name);
- } else {
- indent(12, cfile);
- fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
- sp->tag, fp->name, sp->tag, fp->name);
- }
- break;
- case T_STRING:
- if (calcsize) {
- indent(12, cfile);
- fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
- sp->tag, fp->name);
- } else {
- indent(12, cfile);
- fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
- sp->tag, fp->name, sp->tag, fp->name);
- }
- break;
- case T_INT:
- case T_OTHER:
- if (! calcsize) {
- indent(12, cfile);
- fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
- sp->tag, fp->name, sp->tag, fp->name);
- }
- break;
- }
- }
- indent(12, cfile);
- fputs("break;\n", cfile);
- }
- fputs(" };\n", cfile);
- if (! calcsize)
- fputs(" new->type = n->type;\n", cfile);
- }
-
-
- indent(amount, fp)
- FILE *fp;
- {
- while (amount >= 8) {
- putc('\t', fp);
- amount -= 8;
- }
- while (--amount >= 0) {
- putc(' ', fp);
- }
- }
-
-
- int
- nextfield(buf)
- char *buf;
- {
- register char *p, *q;
-
- p = linep;
- while (*p == ' ' || *p == '\t')
- p++;
- q = buf;
- while (*p != ' ' && *p != '\t' && *p != '\0')
- *q++ = *p++;
- *q = '\0';
- linep = p;
- return (q > buf);
- }
-
-
- skipbl() {
- while (*linep == ' ' || *linep == '\t')
- linep++;
- }
-
-
- int
- readline() {
- register char *p;
-
- if (fgets(line, 1024, infp) == NULL)
- return 0;
- for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
- while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
- p--;
- *p = '\0';
- linep = line;
- linno++;
- if (p - line > BUFLEN)
- error("Line too long");
- return 1;
- }
-
-
-
- error(msg, a1, a2, a3, a4, a5, a6)
- char *msg;
- {
- fprintf(stderr, "line %d: ", linno);
- fprintf(stderr, msg, a1, a2, a3, a4, a5, a6);
- putc('\n', stderr);
- exit(2);
- }
-
-
-
- char *
- savestr(s)
- char *s;
- {
- register char *p;
- char *malloc();
-
- if ((p = malloc(strlen(s) + 1)) == NULL)
- error("Out of space");
- strcpy(p, s);
- return p;
- }
- EOF
- if test `wc -c < mknodes.c` -ne 9481
- then echo 'mknodes.c is the wrong size'
- fi
- echo extracting mksignames.c
- cat > mksignames.c <<\EOF
- /*
- * This program generates the signames.h and signames.c files.
- *
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
- #include <stdio.h>
- #include <signal.h>
-
-
-
- struct sig {
- int signo; /* signal number */
- char *name; /* signal name (without leading "SIG") */
- char *mesg; /* description */
- };
-
-
- struct sig sigtab[] = {
- SIGHUP, "HUP", "Hangup",
- SIGINT, "INT", "Interrupt", /* normally don't print message */
- SIGQUIT, "QUIT", "Quit",
- SIGILL, "ILL", "Illegal instruction",
- SIGTRAP, "TRAP", "Trace/BPT trap",
- #ifdef SIGABRT
- SIGABRT, "ABRT", "abort",
- #endif
- #if defined(SIGIOT) && (! defined(SIGABRT) || SIGABRT != SIGIOT)
- SIGIOT, "IOT", "abort",
- #endif
- #ifdef SIGEMT
- SIGEMT, "EMT", "EMT trap",
- #endif
- SIGFPE, "FPE", "Floating exception",
- SIGKILL, "KILL", "Killed",
- SIGBUS, "BUS", "Bus error",
- SIGSEGV, "SEGV", "Memory fault",
- SIGSYS, "SYS", "Bad system call",
- SIGPIPE, "PIPE", "Broken pipe", /* normally don't print message */
- SIGALRM, "ALRM", "Alarm call",
- SIGTERM, "TERM", "Terminated",
- #ifdef SIGUSR1
- SIGUSR1, "USR1", "User signal 1",
- #endif
- #ifdef SIGUSR2
- SIGUSR2, "USR2", "User signal 2",
- #endif
- #ifdef SIGCLD
- SIGCLD, "CLD", NULL,
- #endif
- #if defined(SIGCHLD) && ! defined(SIGCLD)
- SIGCHLD, "CLD", NULL,
- #endif
- #ifdef SIGPWR
- SIGPWR, "PWR", "Power fail",
- #endif
- #ifdef SIGPOLL
- SIGPOLL, "POLL", "Poll",
- #endif
- /* Now for the BSD signals */
- #ifdef SIGURG
- SIGURG, "URG", NULL,
- #endif
- #ifdef SIGSTOP
- SIGSTOP, "STOP", "Stopped",
- #endif
- #ifdef SIGTSTP
- SIGTSTP, "TSTP", "Stopped",
- #endif
- #ifdef SIGCONT
- SIGCONT, "CONT", NULL,
- #endif
- #ifdef SIGTTIN
- SIGTTIN, "TTIN", "Stopped (input)",
- #endif
- #ifdef SIGTTOU
- SIGTTOU, "TTOU", "Stopped (output)",
- #endif
- #ifdef SIGIO
- SIGIO, "IO", NULL,
- #endif
- #ifdef SIGXCPU
- SIGXCPU, "XCPU", "Time limit exceeded",
- #endif
- #ifdef SIGXFSZ
- SIGXFSZ, "XFSZ", NULL,
- #endif
- #ifdef SIGVTALARM
- SIGVTALARM, "VTALARM", "Virtual alarm",
- #endif
- #ifdef SIGPROF
- SIGPROF, "PROF", "Profiling alarm",
- #endif
- #ifdef SIGWINCH
- SIGWINCH, "WINCH", NULL,
- #endif
- 0, NULL, NULL
- };
-
-
- #define MAXSIG 64
-
-
- char *sigmesg[MAXSIG + 1];
-
-
- char writer[] = "\
- /*\n\
- * This file was generated by the mksignames program.\n\
- */\n\
- \n";
-
-
-
- main(argc, argv) char **argv; {
- FILE *cfile, *hfile;
- struct sig *sigp;
- int maxsig;
- int i;
-
- if ((cfile = fopen("signames.c", "w")) == NULL) {
- fputs("Can't create signames.c\n", stderr);
- exit(2);
- }
- if ((hfile = fopen("signames.h", "w")) == NULL) {
- fputs("Can't create signames.h\n", stderr);
- exit(2);
- }
- maxsig = 0;
- for (sigp = sigtab ; sigp->signo != 0 ; sigp++) {
- if (sigp->signo < 0 || sigp->signo > MAXSIG)
- continue;
- sigmesg[sigp->signo] = sigp->mesg;
- if (maxsig < sigp->signo)
- maxsig = sigp->signo;
- }
-
- fputs(writer, hfile);
- fprintf(hfile, "#define MAXSIG %d\n\n", maxsig);
- fprintf(hfile, "extern char *const sigmesg[MAXSIG+1];\n");
-
- fputs(writer, cfile);
- fprintf(cfile, "#include \"shell.h\"\n\n");
- fprintf(cfile, "char *const sigmesg[%d] = {\n", maxsig + 1);
- for (i = 0 ; i <= maxsig ; i++) {
- if (sigmesg[i] == NULL) {
- fprintf(cfile, " 0,\n");
- } else {
- fprintf(cfile, " \"%s\",\n", sigmesg[i]);
- }
- }
- fprintf(cfile, "};\n");
- exit(0);
- }
- EOF
- if test `wc -c < mksignames.c` -ne 3662
- then echo 'mksignames.c is the wrong size'
- fi
- echo extracting mksyntax.c
- cat > mksyntax.c <<\EOF
- /*
- * This program creates syntax.h and syntax.c.
- *
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
-
- #include <stdio.h>
- #include "parser.h"
-
-
- struct synclass {
- char *name;
- char *comment;
- };
-
- /* Syntax classes */
- struct synclass synclass[] = {
- "CWORD", "character is nothing special",
- "CNL", "newline character",
- "CBACK", "a backslash character",
- "CSQUOTE", "single quote",
- "CDQUOTE", "double quote",
- "CENDQUOTE", "a terminating quote",
- "CBQUOTE", "backwards single quote",
- "CVAR", "a dollar sign",
- "CENDVAR", "a '}' character",
- "CEOF", "end of file",
- "CCTL", "like CWORD, except it must be escaped",
- "CSPCL", "these terminate a word",
- NULL, NULL
- };
-
-
- /*
- * Syntax classes for is_ functions. Warning: if you add new classes
- * you may have to change the definition of the is_in_name macro.
- */
- struct synclass is_entry[] = {
- "ISDIGIT", "a digit",
- "ISUPPER", "an upper case letter",
- "ISLOWER", "a lower case letter",
- "ISUNDER", "an underscore",
- "ISSPECL", "the name of a special parameter",
- NULL, NULL,
- };
-
- char writer[] = "\
- /*\n\
- * This file was generated by the mksyntax program.\n\
- */\n\
- \n";
-
-
- FILE *cfile;
- FILE *hfile;
- char *syntax[513];
- int base;
- int size; /* number of values which a char variable can have */
- int nbits; /* number of bits in a character */
- int digit_contig; /* true if digits are contiguous */
-
-
- main() {
- char c;
- char d;
- int sign;
- int i;
- char buf[80];
- int pos;
- static char digit[] = "0123456789";
-
- /* Create output files */
- if ((cfile = fopen("syntax.c", "w")) == NULL) {
- perror("syntax.c");
- exit(2);
- }
- if ((hfile = fopen("syntax.h", "w")) == NULL) {
- perror("syntax.h");
- exit(2);
- }
- fputs(writer, hfile);
- fputs(writer, cfile);
-
- /* Determine the characteristics of chars. */
- c = -1;
- if (c < 0)
- sign = 1;
- else
- sign = 0;
- for (nbits = 1 ; ; nbits++) {
- d = (1 << nbits) - 1;
- if (d == c)
- break;
- }
- printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
- if (nbits > 9) {
- fputs("Characters can't have more than 9 bits\n", stderr);
- exit(2);
- }
- size = (1 << nbits) + 1;
- base = 1;
- if (sign)
- base += 1 << (nbits - 1);
- digit_contig = 1;
- for (i = 0 ; i < 10 ; i++) {
- if (digit[i] != '0' + i)
- digit_contig = 0;
- }
-
- /* Generate the #define statements in the header file */
- fputs("/* Syntax classes */\n", hfile);
- for (i = 0 ; synclass[i].name ; i++) {
- sprintf(buf, "#define %s %d", synclass[i].name, i);
- fputs(buf, hfile);
- for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
- putc('\t', hfile);
- fprintf(hfile, "/* %s */\n", synclass[i].comment);
- }
- putc('\n', hfile);
- fputs("/* Syntax classes for is_ functions */\n", hfile);
- for (i = 0 ; is_entry[i].name ; i++) {
- sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
- fputs(buf, hfile);
- for (pos = strlen(buf) ; pos < 32 ; pos = pos + 8 &~ 07)
- putc('\t', hfile);
- fprintf(hfile, "/* %s */\n", is_entry[i].comment);
- }
- putc('\n', hfile);
- fprintf(hfile, "#define SYNBASE %d\n", base);
- fprintf(hfile, "#define PEOF %d\n\n", -base);
- putc('\n', hfile);
- fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
- fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
- fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
- putc('\n', hfile);
- output_type_macros(); /* is_digit, etc. */
- putc('\n', hfile);
-
- /* Generate the syntax tables. */
- fputs("#include \"shell.h\"\n", cfile);
- fputs("#include \"syntax.h\"\n\n", cfile);
- init();
- fputs("/* syntax table used when not in quotes */\n", cfile);
- add("\n", "CNL");
- add("\\", "CBACK");
- add("'", "CSQUOTE");
- add("\"", "CDQUOTE");
- add("`", "CBQUOTE");
- add("$", "CVAR");
- add("}", "CENDVAR");
- add("<>();&| \t", "CSPCL");
- print("basesyntax");
- init();
- fputs("\n/* syntax table used when in double quotes */\n", cfile);
- add("\n", "CNL");
- add("\\", "CBACK");
- add("\"", "CENDQUOTE");
- add("`", "CBQUOTE");
- add("$", "CVAR");
- add("}", "CENDVAR");
- add("!*?[=", "CCTL");
- print("dqsyntax");
- init();
- fputs("\n/* syntax table used when in single quotes */\n", cfile);
- add("\n", "CNL");
- add("'", "CENDQUOTE");
- add("!*?[=", "CCTL");
- print("sqsyntax");
- filltable("0");
- fputs("\n/* character classification table */\n", cfile);
- add("0123456789", "ISDIGIT");
- add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
- add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
- add("_", "ISUNDER");
- add("#?$!-*@", "ISSPECL");
- print("is_type");
- if (! digit_contig)
- digit_convert();
- exit(0);
- }
-
-
-
- /*
- * Clear the syntax table.
- */
-
- filltable(dftval)
- char *dftval;
- {
- int i;
-
- for (i = 0 ; i < size ; i++)
- syntax[i] = dftval;
- }
-
-
- /*
- * Initialize the syntax table with default values.
- */
-
- init() {
- filltable("CWORD");
- syntax[0] = "CEOF";
- syntax[base + CTLESC] = "CCTL";
- syntax[base + CTLVAR] = "CCTL";
- syntax[base + CTLENDVAR] = "CCTL";
- syntax[base + CTLBACKQ] = "CCTL";
- syntax[base + CTLBACKQ + CTLQUOTE] = "CCTL";
- }
-
-
- /*
- * Add entries to the syntax table.
- */
-
- add(p, type)
- char *p, *type;
- {
- while (*p)
- syntax[*p++ + base] = type;
- }
-
-
-
- /*
- * Output the syntax table.
- */
-
- print(name)
- char *name;
- {
- int i;
- int col;
-
- fprintf(hfile, "extern const char %s[];\n", name);
- fprintf(cfile, "const char %s[%d] = {\n", name, size);
- col = 0;
- for (i = 0 ; i < size ; i++) {
- if (i == 0) {
- fputs(" ", cfile);
- } else if ((i & 03) == 0) {
- fputs(",\n ", cfile);
- col = 0;
- } else {
- putc(',', cfile);
- while (++col < 9 * (i & 03))
- putc(' ', cfile);
- }
- fputs(syntax[i], cfile);
- col += strlen(syntax[i]);
- }
- fputs("\n};\n", cfile);
- }
-
-
-
- /*
- * Output character classification macros (e.g. is_digit). If digits are
- * contiguous, we can test for them quickly.
- */
-
- char *macro[] = {
- "#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
- "#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
- "#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
- "#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
- "#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
- NULL
- };
-
- output_type_macros() {
- char **pp;
-
- if (digit_contig)
- macro[0] = "#define is_digit(c)\t((unsigned)((c) - '0') <= 9)";
- for (pp = macro ; *pp ; pp++)
- fprintf(hfile, "%s\n", *pp);
- if (digit_contig)
- fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
- else
- fputs("#define digit_val(c)\t(digit_value[c])\n", hfile);
- }
-
-
-
- /*
- * Output digit conversion table (if digits are not contiguous).
- */
-
- digit_convert() {
- int maxdigit;
- static char digit[] = "0123456789";
- char *p;
- int i;
-
- maxdigit = 0;
- for (p = digit ; *p ; p++)
- if (*p > maxdigit)
- maxdigit = *p;
- fputs("extern const char digit_value[];\n", hfile);
- fputs("\n\nconst char digit_value[] = {\n", cfile);
- for (i = 0 ; i <= maxdigit ; i++) {
- for (p = digit ; *p && *p != i ; p++);
- if (*p == '\0')
- p = digit;
- fprintf(cfile, " %d,\n", p - digit);
- }
- fputs("};\n", cfile);
- }
- EOF
- if test `wc -c < mksyntax.c` -ne 7949
- then echo 'mksyntax.c is the wrong size'
- fi
- echo extracting mktokens
- cat > mktokens <<\EOF
- # Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- # This file is part of ash, which is distributed under the terms specified
- # by the Ash General Public License. See the file named LICENSE.
-
- # The following is a list of tokens. The second column is nonzero if the
- # token marks the end of a list. The third column is the name to print in
- # error messages.
-
- cat > /tmp/ka$$ <<\!
- TEOF 1 end of file
- TNL 0 newline
- TSEMI 0 ";"
- TBACKGND 0 "&"
- TAND 0 "&&"
- TOR 0 "||"
- TPIPE 0 "|"
- TLP 0 "("
- TRP 1 ")"
- TENDCASE 1 ";;"
- TENDBQUOTE 1 "`"
- TREDIR 0 redirection
- TWORD 0 word
- TIF 0 "if"
- TTHEN 1 "then"
- TELSE 1 "else"
- TELIF 1 "elif"
- TFI 1 "fi"
- TWHILE 0 "while"
- TUNTIL 0 "until"
- TFOR 0 "for"
- TDO 1 "do"
- TDONE 1 "done"
- TBEGIN 0 "{"
- TEND 1 "}"
- TCASE 0 "case"
- TESAC 1 "esac"
- !
- nl=`wc -l /tmp/ka$$`
- exec > token.def
- awk '{print "#define " $1 " " NR-1}' /tmp/ka$$
- echo '
- /* Array indicating which tokens mark the end of a list */
- const char tokendlist[] = {'
- awk '{print "\t" $2 ","}' /tmp/ka$$
- echo '};
-
- char *const tokname[] = {'
- sed -e 's/"/\\"/g' \
- -e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \
- /tmp/ka$$
- echo '};
- '
- sed 's/"//g' /tmp/ka$$ | awk '
- /TIF/{print "#define KWDOFFSET " NR-1; print ""; print "char *const parsekwd[] = {"}
- /TIF/,/neverfound/{print " \"" $3 "\","}'
- echo ' 0
- };'
-
- rm /tmp/ka$$
- EOF
- if test `wc -c < mktokens` -ne 1315
- then echo 'mktokens is the wrong size'
- fi
- chmod 755 mktokens
- echo extracting myerrno.h
- cat > myerrno.h <<\EOF
- /*
- * Some versions of errno.h don't declare errno, so we do it ourself.
- *
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
-
- #include <sys/errno.h>
-
- extern int errno;
- EOF
- if test `wc -c < myerrno.h` -ne 331
- then echo 'myerrno.h is the wrong size'
- fi
- echo extracting mymalloc.c
- cat > mymalloc.c <<\EOF
- /*
- * First fit memory allocation. (Generally uses memory pretty efficiently,
- * although it is slower than some other memory allocators.)
- *
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
-
-
- #include "shell.h"
- #include "machdep.h"
- #include "mystring.h"
- #include <sys/types.h>
-
-
- /*
- * The free memory pool consists of a collection of contiguous blocks.
- * Each block has an integer at the beginning of it which specifies the
- * size of the block. If the block is allocated, the integer contains
- * the negative of the size. After the last block comes an integer with
- * a value of zero.
- *
- * To allocate a block, we want to scan the list of blocks starting with
- * the first block, merging adjacent free blocks, until we get a free
- * block which is large enough. The actual implementation uses some
- * hacks to decrease the amount of scanning required. Startfree always
- * points to the first free block or a block before it. This keeps us
- * from repeatedly scanning allocated block at the start of the memory
- * pool. In a similar vein, startbig points to what we believe is the
- * first free block whose size is >= BIG or a block before it. Startbig
- * can actually point to some location after the first large free if the
- * first large free block was formed by freeing several small blocks
- * which have not yet been merged into a single free block. To make this
- * less likely, the free routine will merge a freed block with any free
- * blocks after it, but the free routine cannot merge a freed block with
- * free blocks which precede it because there is no (efficient) way for
- * free to locate the preceding block.
- *
- * The variables lastsize and lastloc are used to implement one final
- * method to cut down on scanning. When a malloc is performed, the
- * variable lastsize is set to the size of the largest block skipped
- * during the scan, and the variable lastloc is set to the end of the
- * scan. The next call to malloc can start where the preceding one left
- * off if the number of bytes reqested is larger than the size of any
- * blocks skipped on the preceding malloc. When a block is freed with a
- * lower address than lastloc, free assumes that the block is adjacent to
- * the largest free block skipped by malloc, and updates lastsize
- * accordingly. This is necessary to ensure that starting at lastloc
- * will never cause a block that could be allocated to be skipped; a more
- * aggressive policy could be used.
- */
-
-
-
- /*
- * Machine dependent stuff:
- *
- * PAGE_SIZE is the size of a page. Malloc will try to keep the break
- * location on a page boundary to avoid wasting space (since the operating
- * system presumably has to allocate a whole page even if we only request
- * part of one). PAGE_SIZE must be a power of 2.
- *
- * Head_t is a signed integer type that is capable of holding a value one
- * less than the maximum size of the pool. Type int works fine on a VAX
- * because on a VAX processes only get 31 bits of address space. In
- * practice most other 32 bit machines aren't going to allow processes to
- * allocate more that 2 gigabytes either.
- *
- * Machines generally have alignment restrictions which malloc must
- * obey. ALIGN(n) returns the value of n rounded up to the minimum
- * value that malloc must allocate to keep things aligned.
- *
- * The code here assumes a linear address space, with sbrk allocating
- * successively higher addresses.
- */
-
-
- #define PAGE_SIZE 1024
- #define PAGE_MASK (PAGE_SIZE - 1)
-
-
- #define head_t int
- #define HEADSIZE ALIGN(sizeof (head_t))
-
- #define DEREF(p) (*(head_t *)(p))
-
-
- #ifndef ALIGN
- union align {
- long l;
- char *cp;
- };
-
- #define ALIGN(nbytes) ((nbytes) + sizeof(union align) - 1 &~ (sizeof(union align) - 1))
- #endif
-
-
- /*
- * Tunable paramaters. SLOP is the smallest free block that malloc or
- * realloc will create. If they would have to create a smaller free
- * block to satisfy the caller's request, they allocate the extra bytes
- * to the caller rather than forming a free block. BIG is the smallest
- * block size that will cause the scan to start at startbig; this is
- * used to keep requests for large blocks from scanning lots of small
- * blocks. MINSBRK is the smallest number of pages that will be requested
- * from sbrk at a time. A larger value can cut down the number of calls
- * to sbrk. MINSBRK should be a multiple of PAGE_SIZE.
- */
-
- #define SLOP 8
- #define BIG 500
- #define MINSBRK (2 * PAGE_SIZE)
-
-
- pointer startfree; /* where to start search for n < BIG */
- pointer startbig; /* where to start search for n >= BIG */
- pointer lastloc; /* where last search terminated */
- head_t lastsize; /* largest block skipped on last search */
-
-
-
- pointer realloc();
- void free();
- caddr_t sbrk();
-
-
-
- pointer
- malloc(n)
- unsigned n;
- {
- return realloc((pointer)0, n);
- }
-
-
-
- pointer
- realloc(old, nbytes)
- pointer old;
- unsigned nbytes;
- {
- head_t n = nbytes + HEADSIZE;
- pointer p, q;
- head_t i;
- head_t size;
- head_t largest;
- pointer next;
- head_t allocsize;
-
- if (n < 0)
- return NULL; /* nbytes out of range */
- n = ALIGN(n);
- if (startfree == NULL) { /* first time called */
- p = sbrk(0);
- allocsize = PAGE_SIZE - ((int)p & PAGE_MASK);
- if (allocsize < n + 2 * HEADSIZE)
- allocsize += MINSBRK;
- if (sbrk(allocsize) != p)
- return NULL;
- DEREF(p) = allocsize - HEADSIZE;
- startfree = startbig = lastloc = p;
- lastsize = 0;
- }
- if (old) { /* it's a realloc; try resizing */
- p = old - HEADSIZE;
- q = p - DEREF(p);
- while (DEREF(q) > 0) {
- if (startbig == q)
- startbig = p;
- if (startfree == q)
- startfree = p;
- if (lastloc == q)
- lastloc = p;
- q += DEREF(q);
- }
- size = q - p;
- if (size >= n) {
- if (size - n <= SLOP) {
- DEREF(p) = -size;
- } else {
- next = p + n;
- DEREF(p) = -n;
- DEREF(next) = size - n;
- }
- return old;
- }
- }
- if (n > lastsize) {
- p = lastloc;
- largest = lastsize;
- } else {
- p = startfree;
- largest = 0;
- }
- if (n >= BIG && p < startbig) {
- p = startbig;
- largest = BIG - 1;
- }
- for (;;) {
- while ((size = DEREF(p)) < 0)
- p -= size;
- if (largest < BIG) {
- if (largest == 0)
- startfree = p;
- if (p > startbig)
- startbig = p;
- }
- q = p + size;
- if (DEREF(q) > 0) {
- do {
- if (startbig == q)
- startbig = p;
- q += DEREF(q);
- } while (DEREF(q) > 0);
- size = q - p;
- DEREF(p) = size;
- }
- if (size >= n) { /* found a block that's large enough */
- if (size - n <= SLOP) {
- DEREF(p) = -size;
- next = q;
- } else {
- next = p + n;
- DEREF(p) = -n;
- DEREF(next) = size - n;
- }
- if (next < startbig && size - n >= BIG)
- startbig = next;
- lastsize = largest;
- lastloc = next;
- break;
- }
- if (DEREF(q) == 0) { /* out of space; must get some from sbrk */
- if (old && old + DEREF(old - HEADSIZE) == p) {
- p = old - HEADSIZE;
- size += -DEREF(p);
- old = NULL;
- }
- allocsize = (n - size - 1 + PAGE_SIZE) &~ PAGE_MASK;
- if (allocsize < MINSBRK)
- allocsize = MINSBRK;
- if ((next = sbrk(allocsize)) == (caddr_t)-1)
- return NULL;
- if (next != q + HEADSIZE) {
- if (largest < size)
- largest = size;
- if (allocsize < n + HEADSIZE) {
- if (sbrk(PAGE_SIZE) == (caddr_t)-1) {
- sbrk(-allocsize);
- return NULL;
- }
- allocsize += PAGE_SIZE;
- }
- DEREF(q) = -(next - q);
- p = next;
- }
- q = next + allocsize - HEADSIZE;
- DEREF(q) = 0; /* delete */
- next = p + n;
- DEREF(p) = -n;
- DEREF(next) = q - next;
- lastsize = largest;
- lastloc = next;
- break;
- }
- if (largest < size)
- largest = size;
- p = q;
- }
- /* allocated a block */
- p += HEADSIZE;
- if (old) {
- size = -DEREF(old - HEADSIZE);
- bcopy(old, p, size);
- free(old);
- }
- return p;
- }
-
-
-
- void
- free(p)
- pointer p;
- {
- pointer q;
- head_t size;
-
- if (p == (pointer)0)
- return;
- p -= HEADSIZE;
- if (DEREF(p) >= 0)
- abort();
- q = p - DEREF(p);
- for (;;) {
- if (startbig == q)
- startbig = p;
- if (lastloc == q)
- lastloc = p;
- if (DEREF(q) <= 0)
- break;
- q += DEREF(q);
- }
- size = q - p;
- DEREF(p) = size;
- if (startfree > p)
- startfree = p;
- if (size >= BIG && startbig > p)
- startbig = p;
- if (p < lastloc)
- lastsize += size;
- }
- EOF
- if test `wc -c < mymalloc.c` -ne 8670
- then echo 'mymalloc.c is the wrong size'
- fi
- echo extracting mystring.h
- cat > mystring.h <<\EOF
- /*
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
-
- #ifndef SYSV
- #define strchr mystrchr
- #endif
-
- #ifdef __STDC__
- void scopyn(const char *, char *, int);
- char *strchr(const char *, int);
- void mybcopy(const pointer, pointer, int);
- int prefix(const char *, const char *);
- int number(const char *);
- int is_number(const char *);
- int strcmp(const char *, const char *); /* from C library */
- char *strcpy(char *, const char *); /* from C library */
- int strlen(const char *); /* from C library */
- char *strcat(char *, const char *); /* from C library */
- #else
- void scopyn();
- char *strchr();
- void mybcopy();
- int prefix();
- int number();
- int is_number();
- int strcmp();
- char *strcpy();
- int strlen();
- char *strcat();
- #endif
-
- #define equal(s1, s2) (strcmp(s1, s2) == 0)
- #define scopy(s1, s2) ((void)strcpy(s2, s1))
- #define bcopy(src, dst, n) mybcopy((pointer)(src), (pointer)(dst), n)
- EOF
- if test `wc -c < mystring.h` -ne 1036
- then echo 'mystring.h is the wrong size'
- fi
- echo extracting mystring.c
- cat > mystring.c <<\EOF
- /*
- * String functions.
- *
- * equal(s1, s2) Return true if strings are equal.
- * scopy(from, to) Copy a string.
- * scopyn(from, to, n) Like scopy, but checks for overflow.
- * strchr(s, c) Find first occurance of c in s.
- * bcopy(from, to, n) Copy a block of memory.
- * number(s) Convert a string of digits to an integer.
- * is_number(s) Return true if s is a string of digits.
- *
- * Copyright (C) 1989 by Kenneth Almquist. All rights reserved.
- * This file is part of ash, which is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
-
- #include "shell.h"
- #include "syntax.h"
- #include "error.h"
- #include "mystring.h"
-
-
- char nullstr[1]; /* zero length string */
-
-
- /*
- * scopyn - copy a string from "from" to "to", truncating the string
- * if necessary. "To" is always nul terminated, even if
- * truncation is performed. "Size" is the size of "to".
- */
-
- void
- scopyn(from, to, size)
- register char const *from;
- register char *to;
- register int size;
- {
-
- while (--size > 0) {
- if ((*to++ = *from++) == '\0')
- return;
- }
- *to = '\0';
- }
-
-
- /*
- * strchr - find first occurrence of a character in a string.
- */
-
- #ifndef SYS5
- char *
- mystrchr(s, charwanted)
- char const *s;
- register char charwanted;
- {
- register char const *scan;
-
- /*
- * The odd placement of the two tests is so NUL is findable.
- */
- for (scan = s ; *scan != charwanted ; ) /* ++ moved down for opt. */
- if (*scan++ == '\0')
- return NULL;
- return (char *)scan;
- }
- #endif
-
-
-
- /*
- * bcopy - copy bytes
- *
- * This routine was derived from code by Henry Spencer.
- */
-
- void
- mybcopy(src, dst, length)
- pointer dst;
- const pointer src;
- register int length;
- {
- register char *d = dst;
- register char *s = src;
-
- while (--length >= 0)
- *d++ = *s++;
- }
-
-
- /*
- * prefix -- see if pfx is a prefix of string.
- */
-
- int
- prefix(pfx, string)
- register char const *pfx;
- register char const *string;
- {
- while (*pfx) {
- if (*pfx++ != *string++)
- return 0;
- }
- return 1;
- }
-
-
- /*
- * Convert a string of digits to an integer, printing an error message on
- * failure.
- */
-
- int
- number(s)
- const char *s;
- {
-
- if (! is_number(s))
- error2("Illegal number", (char *)s);
- return atoi(s);
- }
-
-
-
- /*
- * Check for a valid number. This should be elsewhere.
- */
-
- int
- is_number(p)
- register const char *p;
- {
- do {
- if (! is_digit(*p))
- return 0;
- } while (*++p != '\0');
- return 1;
- }
- EOF
- if test `wc -c < mystring.c` -ne 2651
- then echo 'mystring.c is the wrong size'
- fi
- echo extracting nodes.c.pat
- cat > nodes.c.pat <<\EOF
- /*
- * Routine for dealing with parsed shell commands.
- *
- * Copyright 1989 by Kenneth Almquist. All rights reserved.
- *
- * This file is part of ash. Ash is distributed under the terms specified
- * by the Ash General Public License. See the file named LICENSE.
- */
-
- #include "shell.h"
- #include "nodes.h"
- #include "memalloc.h"
- #include "machdep.h"
- #include "mystring.h"
-
-
- int funcblocksize; /* size of structures in function */
- int funcstringsize; /* size of strings in node */
- pointer funcblock; /* block to allocate function from */
- char *funcstring; /* block to allocate strings from */
-
- %SIZES
-
-
- #ifdef __STDC__
- STATIC void calcsize(union node *);
- STATIC void sizenodelist(struct nodelist *);
- STATIC union node *copynode(union node *);
- STATIC struct nodelist *copynodelist(struct nodelist *);
- STATIC char *nodesavestr(char *);
- #else
- STATIC void calcsize();
- STATIC void sizenodelist();
- STATIC union node *copynode();
- STATIC struct nodelist *copynodelist();
- STATIC char *nodesavestr();
- #endif
-
-
-
- /*
- * Make a copy of a parse tree.
- */
-
- union node *
- copyfunc(n)
- union node *n;
- {
- if (n == NULL)
- return NULL;
- funcblocksize = 0;
- funcstringsize = 0;
- calcsize(n);
- funcblock = ckmalloc(funcblocksize + funcstringsize);
- funcstring = funcblock + funcblocksize;
- return copynode(n);
- }
-
-
-
- STATIC void
- calcsize(n)
- union node *n;
- {
- %CALCSIZE
- }
-
-
-
- STATIC void
- sizenodelist(lp)
- struct nodelist *lp;
- {
- while (lp) {
- funcblocksize += ALIGN(sizeof (struct nodelist));
- calcsize(lp->n);
- lp = lp->next;
- }
- }
-
-
-
- STATIC union node *
- copynode(n)
- union node *n;
- {
- union node *new;
-
- %COPY
- return new;
- }
-
-
- STATIC struct nodelist *
- copynodelist(lp)
- struct nodelist *lp;
- {
- struct nodelist *start;
- struct nodelist **lpp;
-
- lpp = &start;
- while (lp) {
- *lpp = funcblock;
- funcblock += ALIGN(sizeof (struct nodelist));
- (*lpp)->n = copynode(lp->n);
- lp = lp->next;
- lpp = &(*lpp)->next;
- }
- *lpp = NULL;
- return start;
- }
-
-
-
- STATIC char *
- nodesavestr(s)
- char *s;
- {
- register char *p = s;
- register char *q = funcstring;
- char *rtn = funcstring;
-
- while (*q++ = *p++);
- funcstring = q;
- return rtn;
- }
-
-
-
- /*
- * Free a parse tree.
- */
-
- void
- freefunc(n)
- union node *n;
- {
- if (n)
- ckfree(n);
- }
- EOF
- if test `wc -c < nodes.c.pat` -ne 2438
- then echo 'nodes.c.pat is the wrong size'
- fi
- echo extracting nodetypes
- cat > nodetypes <<\EOF
- # This file describes the nodes used in parse trees. Unindented lines
- # contain a node type followed by a structure tag. Subsequent indented
- # lines specify the fields of the structure. Several node types can share
- # the same structure, in which case the fields of the structure should be
- # specified only once.
- #
- # A field of a structure is described by the name of the field followed
- # by a type. The currently implemented types are:
- # nodeptr - a pointer to a node
- # nodelist - a pointer to a list of nodes
- # string - a pointer to a nul terminated string
- # int - an integer
- # other - any type that can be copied by assignment
- # temp - a field that doesn't have to be copied when the node is copied
- # The last two types should be followed by the text of a C declaration for
- # the field.
- #
- #
- # Copyright 1989 by Kenneth Almquist. All rights reserved.
- #
- # This file is part of ash. Ash is distributed under the terms specified
- # by the Ash General Public License. See the file named LICENSE.
-
-
-
- NSEMI nbinary # two commands separated by a semicolon
- type int
- ch1 nodeptr # the first child
- ch2 nodeptr # the second child
-
- NCMD ncmd # a simple command
- type int
- backgnd int # set to run command in background
- args nodeptr # the arguments
- redirect nodeptr # list of file redirections
-
- NPIPE npipe # a pipeline
- type int
- backgnd int # set to run pipeline in background
- cmdlist nodelist # the commands in the pipeline
-
- NREDIR nredir # redirection (of a compex command)
- type int
- n nodeptr # the command
- redirect nodeptr # list of file redirections
-
- NBACKGND nredir # run command in background
- NSUBSHELL nredir # run command in a subshell
-
- NAND nbinary # the && operator
- NOR nbinary # the || operator
-
- NIF nif # the if statement. Elif clauses are handled
- type int # using multiple if nodes.
- test nodeptr # if test
- ifpart nodeptr # then ifpart
- elsepart nodeptr # else elsepart
-
- NWHILE nbinary # the while statement. First child is the test
- NUNTIL nbinary # the until statement
-
- NFOR nfor # the for statement
- type int
- args nodeptr # for var in args
- body nodeptr # do body; done
- var string # the for variable
-
- NCASE ncase # a case statement
- type int
- expr nodeptr # the word to switch on
- cases nodeptr # the list of cases (NCLIST nodes)
-
- NCLIST nclist # a case
- type int
- next nodeptr # the next case in list
- pattern nodeptr # list of patterns for this case
- body nodeptr # code to execute for this case
-
-
- NDEFUN narg # define a function. The "next" field contains
- # the body of the function.
-
- NARG narg # represents a word
- type int
- next nodeptr # next word in list
- text string # the text of the word
- backquote nodelist # list of commands in back quotes
-
- NTO nfile # fd> fname
- NFROM nfile # fd< fname
- NAPPEND nfile # fd>> fname
- type int
- next nodeptr # next redirection in list
- fd int # file descriptor being redirected
- fname nodeptr # file name, in a NARG node
- expfname temp char *expfname # actual file name
-
- NTOFD ndup # fd<&dupfd
- NFROMFD ndup # fd>&dupfd
- type int
- next nodeptr # next redirection in list
- fd int # file descriptor being redirected
- dupfd int # file descriptor to duplicate
-
- NHERE nhere # fd<<\!
- NXHERE nhere # fd<<!
- type int
- next nodeptr # next redirection in list
- fd int # file descriptor being redirected
- doc nodeptr # input to command (NARG node)
- EOF
- if test `wc -c < nodetypes` -ne 3482
- then echo 'nodetypes is the wrong size'
- fi
- echo extracting ocdecl.el
- cat > ocdecl.el <<\EOF
- (defun ocdecl ()
- "Update the old style C declarations from the new style ones. This assumes
- that you set up your declarations as follows:
- #ifdef __STDC__
- [ANSI style function prototypes]
- #else
- [Old style function prototypes]
- #endif
- Then if you add or change a function, you can edit the ANSI style prototypes
- and then run this function to make the old style prototypes match the new
- style ones. Normally bound to ESC D."
- (interactive)
- (let (ostart oend nstart nend+1 eol)
- (end-of-line)
- (search-backward "#ifdef __STDC__")
- (forward-line 1)
- (setq ostart (point))
- (search-forward "#else")
- (beginning-of-line)
- (setq oend (point))
- (forward-line 1)
- (setq nstart (point))
- (search-forward "#endif")
- (beginning-of-line)
- (setq nend+1 (make-marker))
- (set-marker nend+1 (1+ (point)))
- (goto-char nstart)
- (insert (buffer-substring ostart oend))
- (delete-region (point) (1- nend+1))
- (goto-char nstart)
- (while (< (point) (1- nend+1))
- (end-of-line)
- (setq eol (point))
- (beginning-of-line)
- (re-search-forward "[a-zA-Z0-9_] *(" eol)
- (setq ostart (point))
- (backward-char 1)
- (forward-sexp 1)
- (delete-region ostart (1- (point)))
- (forward-line 1))
- (set-marker nend+1 nil)
- nil))
-
- (define-key esc-map "D" 'ocdecl)
- EOF
- if test `wc -c < ocdecl.el` -ne 1334
- then echo 'ocdecl.el is the wrong size'
- fi
- echo Archive 5 unpacked
- exit
-
-