-
-static void sizenodelist(const struct nodelist *);
-static struct nodelist *copynodelist(const struct nodelist *);
-static char *nodexstrdup(const char *);
-
-#define CALCSIZE_TABLE
-#define COPYNODE_TABLE
-#if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
-/*
- * To collect a lot of redundant code in case statements for copynode()
- * and calcsize(), we implement a mini language here. Each type of node
- * struct has an associated instruction sequence that operates on its
- * members via their offsets. The instruction are pack in unsigned chars
- * with format IIDDDDDE where the bits are
- * I : part of the instruction opcode, which are
- * 00 : member is a pointer to another node
- * 40 : member is an integer
- * 80 : member is a pointer to a nodelist
- * CC : member is a pointer to a char string
- * D : data - the actual offset of the member to operate on in the struct
- * (since we assume bit 0 is set, it is not shifted)
- * E : flag signaling end of instruction sequence
- *
- * WARNING: In order to handle larger offsets for 64bit archs, this code
- * assumes that no offset can be an odd number and stores the
- * end-of-instructions flag in bit 0.
- */
-
-#define NODE_INTEGER 0x40
-#define NODE_NODELIST 0x80
-#define NODE_CHARPTR 0xC0
-#define NODE_NOMORE 0x01 /* Note: no offset should be odd (aligned) */
-#define NODE_MBRMASK 0xC0
-#define NODE_OFFSETMASK 0x3E
-
-static const unsigned char copynode_ops[35] = {
-#define COPYNODE_OPS0 0
- offsetof(union node, nbinary.ch2),
- offsetof(union node, nbinary.ch1) | NODE_NOMORE,
-#define COPYNODE_OPS1 (COPYNODE_OPS0 + 2)
- offsetof(union node, ncmd.redirect),
- offsetof(union node, ncmd.args),
- offsetof(union node, ncmd.assign),
- offsetof(union node, ncmd.backgnd) | NODE_INTEGER | NODE_NOMORE,
-#define COPYNODE_OPS2 (COPYNODE_OPS1 + 4)
- offsetof(union node, npipe.cmdlist) | NODE_NODELIST,
- offsetof(union node, npipe.backgnd) | NODE_INTEGER | NODE_NOMORE,
-#define COPYNODE_OPS3 (COPYNODE_OPS2 + 2)
- offsetof(union node, nredir.redirect),
- offsetof(union node, nredir.n) | NODE_NOMORE,
-#define COPYNODE_OPS4 (COPYNODE_OPS3 + 2)
- offsetof(union node, nif.elsepart),
- offsetof(union node, nif.ifpart),
- offsetof(union node, nif.test) | NODE_NOMORE,
-#define COPYNODE_OPS5 (COPYNODE_OPS4 + 3)
- offsetof(union node, nfor.var) | NODE_CHARPTR,
- offsetof(union node, nfor.body),
- offsetof(union node, nfor.args) | NODE_NOMORE,
-#define COPYNODE_OPS6 (COPYNODE_OPS5 + 3)
- offsetof(union node, ncase.cases),
- offsetof(union node, ncase.expr) | NODE_NOMORE,
-#define COPYNODE_OPS7 (COPYNODE_OPS6 + 2)
- offsetof(union node, nclist.body),
- offsetof(union node, nclist.pattern),
- offsetof(union node, nclist.next) | NODE_NOMORE,
-#define COPYNODE_OPS8 (COPYNODE_OPS7 + 3)
- offsetof(union node, narg.backquote) | NODE_NODELIST,
- offsetof(union node, narg.text) | NODE_CHARPTR,
- offsetof(union node, narg.next) | NODE_NOMORE,
-#define COPYNODE_OPS9 (COPYNODE_OPS8 + 3)
- offsetof(union node, nfile.fname),
- offsetof(union node, nfile.fd) | NODE_INTEGER,
- offsetof(union node, nfile.next) | NODE_NOMORE,
-#define COPYNODE_OPS10 (COPYNODE_OPS9 + 3)
- offsetof(union node, ndup.vname),
- offsetof(union node, ndup.dupfd) | NODE_INTEGER,
- offsetof(union node, ndup.fd) | NODE_INTEGER,
- offsetof(union node, ndup.next) | NODE_NOMORE,
-#define COPYNODE_OPS11 (COPYNODE_OPS10 + 4)
- offsetof(union node, nhere.doc),
- offsetof(union node, nhere.fd) | NODE_INTEGER,
- offsetof(union node, nhere.next) | NODE_NOMORE,
-#define COPYNODE_OPS12 (COPYNODE_OPS11 + 3)
- offsetof(union node, nnot.com) | NODE_NOMORE,
-};
-
-#if COPYNODE_OPS12 != 34
-#error COPYNODE_OPS12 is incorrect
-#endif
-
-static const unsigned char copynode_ops_index[26] = {
- COPYNODE_OPS0, /* NSEMI */
- COPYNODE_OPS1, /* NCMD */
- COPYNODE_OPS2, /* NPIPE */
- COPYNODE_OPS3, /* NREDIR */
- COPYNODE_OPS3, /* NBACKGND */
- COPYNODE_OPS3, /* NSUBSHELL */
- COPYNODE_OPS0, /* NAND */
- COPYNODE_OPS0, /* NOR */
- COPYNODE_OPS4, /* NIF */
- COPYNODE_OPS0, /* NWHILE */
- COPYNODE_OPS0, /* NUNTIL */
- COPYNODE_OPS5, /* NFOR */
- COPYNODE_OPS6, /* NCASE */
- COPYNODE_OPS7, /* NCLIST */
- COPYNODE_OPS8, /* NDEFUN */
- COPYNODE_OPS8, /* NARG */
- COPYNODE_OPS9, /* NTO */
- COPYNODE_OPS9, /* NFROM */
- COPYNODE_OPS9, /* NFROMTO */
- COPYNODE_OPS9, /* NAPPEND */
- COPYNODE_OPS9, /* NTOOV */
- COPYNODE_OPS10, /* NTOFD */
- COPYNODE_OPS10, /* NFROMFD */
- COPYNODE_OPS11, /* NHERE */
- COPYNODE_OPS11, /* NXHERE */
- COPYNODE_OPS12, /* NNOT */
-};
-
-#if NODE_CHARPTR != NODE_MBRMASK
-#error NODE_CHARPTR != NODE_MBRMASK!!!
-#endif
-#endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
-
-#ifdef COPYNODE_TABLE
-static union node *copynode(const union node *n)
-{
- union node *new;
- const unsigned char *p;
-
- if (n == NULL) {
- return NULL;
- }
- new = funcblock;
- new->type = n->type;
- funcblock = (char *) funcblock + (int) nodesize[n->type];
- p = copynode_ops + (int) copynode_ops_index[n->type];
- do {
- char *nn = ((char *) new) + ((int) (*p & NODE_OFFSETMASK));
- const char *no = ((const char *) n) + ((int) (*p & NODE_OFFSETMASK));
-
- if (!(*p & NODE_MBRMASK)) { /* standard node */
- *((union node **) nn) = copynode(*((const union node **) no));
- } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
- *((const char **) nn) = nodexstrdup(*((const char **) no));
- } else if (*p & NODE_NODELIST) { /* nodelist */
- *((struct nodelist **) nn)
- = copynodelist(*((const struct nodelist **) no));
- } else { /* integer */
- *((int *) nn) = *((int *) no);
- }
- } while (!(*p++ & NODE_NOMORE));
- return new;
-}
-#else /* COPYNODE_TABLE */
-static union node *copynode(const union node *n)
-{
- union node *new;
-
- if (n == NULL)
- return NULL;
- new = funcblock;
- funcblock = (char *) funcblock + nodesize[n->type];
- switch (n->type) {
- case NSEMI:
- case NAND:
- case NOR:
- case NWHILE:
- case NUNTIL:
- new->nbinary.ch2 = copynode(n->nbinary.ch2);
- new->nbinary.ch1 = copynode(n->nbinary.ch1);
- break;
- case NCMD:
- new->ncmd.redirect = copynode(n->ncmd.redirect);
- new->ncmd.args = copynode(n->ncmd.args);
- new->ncmd.assign = copynode(n->ncmd.assign);
- new->ncmd.backgnd = n->ncmd.backgnd;
- break;
- case NPIPE:
- new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
- new->npipe.backgnd = n->npipe.backgnd;
- break;
- case NREDIR:
- case NBACKGND:
- case NSUBSHELL:
- new->nredir.redirect = copynode(n->nredir.redirect);
- new->nredir.n = copynode(n->nredir.n);
- break;
- case NIF:
- new->nif.elsepart = copynode(n->nif.elsepart);
- new->nif.ifpart = copynode(n->nif.ifpart);
- new->nif.test = copynode(n->nif.test);
- break;
- case NFOR:
- new->nfor.var = nodexstrdup(n->nfor.var);
- new->nfor.body = copynode(n->nfor.body);
- new->nfor.args = copynode(n->nfor.args);
- break;
- case NCASE:
- new->ncase.cases = copynode(n->ncase.cases);
- new->ncase.expr = copynode(n->ncase.expr);
- break;
- case NCLIST:
- new->nclist.body = copynode(n->nclist.body);
- new->nclist.pattern = copynode(n->nclist.pattern);
- new->nclist.next = copynode(n->nclist.next);
- break;
- case NDEFUN:
- case NARG:
- new->narg.backquote = copynodelist(n->narg.backquote);
- new->narg.text = nodexstrdup(n->narg.text);
- new->narg.next = copynode(n->narg.next);
- break;
- case NTO:
- case NFROM:
- case NFROMTO:
- case NAPPEND:
- case NTOOV:
- new->nfile.fname = copynode(n->nfile.fname);
- new->nfile.fd = n->nfile.fd;
- new->nfile.next = copynode(n->nfile.next);
- break;
- case NTOFD:
- case NFROMFD:
- new->ndup.vname = copynode(n->ndup.vname);
- new->ndup.dupfd = n->ndup.dupfd;
- new->ndup.fd = n->ndup.fd;
- new->ndup.next = copynode(n->ndup.next);
- break;
- case NHERE:
- case NXHERE:
- new->nhere.doc = copynode(n->nhere.doc);
- new->nhere.fd = n->nhere.fd;
- new->nhere.next = copynode(n->nhere.next);
- break;
- case NNOT:
- new->nnot.com = copynode(n->nnot.com);
- break;
- };
- new->type = n->type;
- return new;
-}
-#endif /* COPYNODE_TABLE */
-
-#ifdef CALCSIZE_TABLE
-static void calcsize(const union node *n)
-{
- const unsigned char *p;
-
- if (n == NULL)
- return;
- funcblocksize += (int) nodesize[n->type];
-
- p = copynode_ops + (int) copynode_ops_index[n->type];
- do {
- const char *no = ((const char *) n) + ((int) (*p & NODE_OFFSETMASK));
-
- if (!(*p & NODE_MBRMASK)) { /* standard node */
- calcsize(*((const union node **) no));
- } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
- funcstringsize += strlen(*((const char **) no)) + 1;
- } else if (*p & NODE_NODELIST) { /* nodelist */
- sizenodelist(*((const struct nodelist **) no));
- } /* else integer -- ignore */
- } while (!(*p++ & NODE_NOMORE));
-}
-#else /* CALCSIZE_TABLE */
-static void calcsize(const union node *n)
-{
- if (n == NULL)
- return;
- funcblocksize += nodesize[n->type];
- switch (n->type) {
- case NSEMI:
- case NAND:
- case NOR:
- case NWHILE:
- case NUNTIL:
- calcsize(n->nbinary.ch2);
- calcsize(n->nbinary.ch1);
- break;
- case NCMD:
- calcsize(n->ncmd.redirect);
- calcsize(n->ncmd.args);
- calcsize(n->ncmd.assign);
- break;
- case NPIPE:
- sizenodelist(n->npipe.cmdlist);
- break;
- case NREDIR:
- case NBACKGND:
- case NSUBSHELL:
- calcsize(n->nredir.redirect);
- calcsize(n->nredir.n);
- break;
- case NIF:
- calcsize(n->nif.elsepart);
- calcsize(n->nif.ifpart);
- calcsize(n->nif.test);
- break;
- case NFOR:
- funcstringsize += strlen(n->nfor.var) + 1;
- calcsize(n->nfor.body);
- calcsize(n->nfor.args);
- break;
- case NCASE:
- calcsize(n->ncase.cases);
- calcsize(n->ncase.expr);
- break;
- case NCLIST:
- calcsize(n->nclist.body);
- calcsize(n->nclist.pattern);
- calcsize(n->nclist.next);
- break;
- case NDEFUN:
- case NARG:
- sizenodelist(n->narg.backquote);
- funcstringsize += strlen(n->narg.text) + 1;
- calcsize(n->narg.next);
- break;
- case NTO:
- case NFROM:
- case NFROMTO:
- case NAPPEND:
- case NTOOV:
- calcsize(n->nfile.fname);
- calcsize(n->nfile.next);
- break;
- case NTOFD:
- case NFROMFD:
- calcsize(n->ndup.vname);
- calcsize(n->ndup.next);
- break;
- case NHERE:
- case NXHERE:
- calcsize(n->nhere.doc);
- calcsize(n->nhere.next);
- break;
- case NNOT:
- calcsize(n->nnot.com);
- break;
- };
-}
-#endif /* CALCSIZE_TABLE */
-
-static void sizenodelist(const struct nodelist *lp)
-{
- while (lp) {
- funcblocksize += ALIGN(sizeof(struct nodelist));
- calcsize(lp->n);
- lp = lp->next;
- }
-}
-
-
-static struct nodelist *copynodelist(const struct nodelist *lp)
-{
- struct nodelist *start;
- struct nodelist **lpp;
-
- lpp = &start;
- while (lp) {
- *lpp = funcblock;
- funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
- (*lpp)->n = copynode(lp->n);
- lp = lp->next;
- lpp = &(*lpp)->next;
- }
- *lpp = NULL;
- return start;
-}
-
-
-static char *nodexstrdup(const char *s)
-{
- const char *p = s;
- char *q = funcstring;
- char *rtn = funcstring;
-
- while ((*q++ = *p++) != '\0')
- continue;
- funcstring = q;
- return rtn;
-}
-
-#ifdef CONFIG_ASH_GETOPTS
-static int getopts(char *, char *, char **, int *, int *);
-#endif
-
-/*
- * Process the shell command line arguments.
- */
-
-static void procargs(int argc, char **argv)
-{
- int i;
-
- argptr = argv;
- if (argc > 0)
- argptr++;
- for (i = 0; i < NOPTS; i++)
- optent_val(i) = 2;
- options(1);
- if (*argptr == NULL && minusc == NULL)
- sflag = 1;
- if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
- iflag = 1;
- if (mflag == 2)
- mflag = iflag;
- for (i = 0; i < NOPTS; i++)
- if (optent_val(i) == 2)
- optent_val(i) = 0;
- arg0 = argv[0];
- if (sflag == 0 && minusc == NULL) {
- commandname = argv[0];
- arg0 = *argptr++;
- setinputfile(arg0, 0);
- commandname = arg0;
- }
- /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
- if (argptr && minusc && *argptr)
- arg0 = *argptr++;
-
- shellparam.p = argptr;
- shellparam.optind = 1;
- shellparam.optoff = -1;
- /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
- while (*argptr) {
- shellparam.nparam++;
- argptr++;
- }
- optschanged();
-}
-
-
-
-/*
- * Process shell options. The global variable argptr contains a pointer
- * to the argument list; we advance it past the options.
- */
-
-static inline void minus_o(const char *name, int val)
-{
- int i;
-
- if (name == NULL) {
- out1str("Current option settings\n");
- for (i = 0; i < NOPTS; i++)
- printf("%-16s%s\n", optent_name(optlist[i]),
- optent_val(i) ? "on" : "off");
- } else {
- for (i = 0; i < NOPTS; i++)
- if (equal(name, optent_name(optlist[i]))) {
- setoption(optent_letter(optlist[i]), val);
- return;
- }
- error("Illegal option -o %s", name);
- }
-}
-
-
-static void options(int cmdline)