msh: reduce global data/bss usage

(add/remove: 1/5 grow/shrink: 28/6 up/down: 464/-394)          Total: 70 bytes
   text    data     bss     dec     hex filename
 778077     908    7568  786553   c0079 busybox_old
 778330     860    7408  786598   c00a6 busybox_unstripped
This commit is contained in:
Denis Vlasenko 2007-12-16 17:21:29 +00:00
parent 0163111325
commit c794c51a1a

View File

@ -270,22 +270,6 @@ struct brkcon {
}; };
/*
* flags:
* -e: quit on error
* -k: look for name=value everywhere on command line
* -n: no execution
* -t: exit after reading and executing one command
* -v: echo as read
* -x: trace
* -u: unset variables net diagnostic
*/
static char flags['z' - 'a' + 1] ALIGN1;
/* this looks weird, but is OK ... we index FLAG with 'a'...'z' */
#define FLAG (flags - 'a')
/* moved to G: static char *trap[_NSIG + 1]; */
/* moved to G: static char ourtrap[_NSIG + 1]; */
static int trapset; /* trap pending */ static int trapset; /* trap pending */
static int yynerrs; /* yacc */ static int yynerrs; /* yacc */
@ -422,10 +406,6 @@ static int yyparse(void);
static int execute(struct op *t, int *pin, int *pout, int act); static int execute(struct op *t, int *pin, int *pout, int act);
#define AFID_NOBUF (~0)
#define AFID_ID 0
/* -------- io.h -------- */ /* -------- io.h -------- */
/* io buffer */ /* io buffer */
struct iobuf { struct iobuf {
@ -455,24 +435,12 @@ struct io {
char xchar; /* for `'s */ char xchar; /* for `'s */
char task; /* reason for pushed IO */ char task; /* reason for pushed IO */
}; };
/* ->task: */
#define XOTHER 0 /* none of the below */ #define XOTHER 0 /* none of the below */
#define XDOLL 1 /* expanding ${} */ #define XDOLL 1 /* expanding ${} */
#define XGRAVE 2 /* expanding `'s */ #define XGRAVE 2 /* expanding `'s */
#define XIO 3 /* file IO */ #define XIO 3 /* file IO */
/* in substitution */
#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
/* moved to G: static struct ioarg ioargstack[NPUSH]; */
static struct io iostack[NPUSH];
/* moved to G: static struct iobuf sharedbuf = { AFID_NOBUF }; */
/* moved to G: static struct iobuf mainbuf = { AFID_NOBUF }; */
static unsigned bufid = AFID_ID; /* buffer id counter */
#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
/* /*
* input generators for IO structure * input generators for IO structure
@ -597,33 +565,6 @@ static const char *const signame[] = {
}; };
struct res {
const char *r_name;
int r_val;
};
static const struct res restab[] = {
{ "for" , FOR },
{ "case" , CASE },
{ "esac" , ESAC },
{ "while", WHILE },
{ "do" , DO },
{ "done" , DONE },
{ "if" , IF },
{ "in" , IN },
{ "then" , THEN },
{ "else" , ELSE },
{ "elif" , ELIF },
{ "until", UNTIL },
{ "fi" , FI },
{ ";;" , BREAK },
{ "||" , LOGOR },
{ "&&" , LOGAND },
{ "{" , '{' },
{ "}" , '}' },
{ "." , DOT },
{ NULL , 0 },
};
struct builtincmd { struct builtincmd {
const char *name; const char *name;
int (*builtinfunc)(struct op *t); int (*builtinfunc)(struct op *t);
@ -704,6 +645,10 @@ static struct region *areanxt; /* starting point of scan */
static void *brktop; static void *brktop;
static void *brkaddr; static void *brkaddr;
#define AFID_NOBUF (~0)
#define AFID_ID 0
/* /*
* parsing & execution environment * parsing & execution environment
*/ */
@ -716,44 +661,68 @@ struct env {
struct env *oenv; struct env *oenv;
}; };
static struct env e = {
NULL /* set to line in main() */, /* linep: char ptr */
iostack, /* iobase: struct io ptr */
iostack - 1, /* iop: struct io ptr */
(xint *) NULL, /* errpt: void ptr for errors? */
FDBASE, /* iofd: file desc */
(struct env *) NULL /* oenv: struct env ptr */
};
struct globals { struct globals {
struct env global_env;
struct ioarg temparg; // = { .afid = AFID_NOBUF }; /* temporary for PUSHIO */
unsigned bufid; // = AFID_ID; /* buffer id counter */
char ourtrap[_NSIG + 1]; char ourtrap[_NSIG + 1];
char *trap[_NSIG + 1]; char *trap[_NSIG + 1];
struct iobuf sharedbuf; /* in main(): set to { AFID_NOBUF } */ struct iobuf sharedbuf; /* in main(): set to { AFID_NOBUF } */
struct iobuf mainbuf; /* in main(): set to { AFID_NOBUF } */ struct iobuf mainbuf; /* in main(): set to { AFID_NOBUF } */
struct ioarg ioargstack[NPUSH]; struct ioarg ioargstack[NPUSH];
/*
* flags:
* -e: quit on error
* -k: look for name=value everywhere on command line
* -n: no execution
* -t: exit after reading and executing one command
* -v: echo as read
* -x: trace
* -u: unset variables net diagnostic
*/
char flags['z' - 'a' + 1];
char filechar_cmdbuf[BUFSIZ]; char filechar_cmdbuf[BUFSIZ];
char line[LINELIM]; char line[LINELIM];
char child_cmd[LINELIM]; char child_cmd[LINELIM];
struct io iostack[NPUSH];
char grave__var_name[LINELIM]; char grave__var_name[LINELIM];
char grave__alt_value[LINELIM]; char grave__alt_value[LINELIM];
}; };
#define G (*ptr_to_globals) #define G (*ptr_to_globals)
#define global_env (G.global_env )
#define temparg (G.temparg )
#define bufid (G.bufid )
#define ourtrap (G.ourtrap ) #define ourtrap (G.ourtrap )
#define trap (G.trap ) #define trap (G.trap )
#define sharedbuf (G.sharedbuf ) #define sharedbuf (G.sharedbuf )
#define mainbuf (G.mainbuf ) #define mainbuf (G.mainbuf )
#define ioargstack (G.ioargstack ) #define ioargstack (G.ioargstack )
/* this looks weird, but is OK ... we index FLAG with 'a'...'z' */
#define FLAG (G.flags - 'a' )
#define filechar_cmdbuf (G.filechar_cmdbuf) #define filechar_cmdbuf (G.filechar_cmdbuf)
#define line (G.line ) #define line (G.line )
#define child_cmd (G.child_cmd ) #define child_cmd (G.child_cmd )
#define iostack (G.iostack )
#define INIT_G() do { \ #define INIT_G() do { \
PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
global_env.linep = line; \
global_env.iobase = iostack; \
global_env.iop = iostack - 1; \
global_env.iofd = FDBASE; \
temparg.afid = AFID_NOBUF; \
bufid = AFID_ID; \
} while (0) } while (0)
/* in substitution */
#define INSUB() (global_env.iop->task == XGRAVE || global_env.iop->task == XDOLL)
#define RUN(what, arg, gen) ((temparg.what = (arg)), run(&temparg, (gen)))
#ifdef MSHDEBUG #ifdef MSHDEBUG
void print_t(struct op *t) void print_t(struct op *t)
{ {
@ -867,10 +836,10 @@ static void err(const char *s)
return; return;
if (!interactive) if (!interactive)
leave(); leave();
if (e.errpt) if (global_env.errpt)
longjmp(e.errpt, 1); longjmp(global_env.errpt, 1);
closeall(); closeall();
e.iop = e.iobase = iostack; global_env.iop = global_env.iobase = iostack;
} }
@ -1364,7 +1333,7 @@ static void onecommand(void)
DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree)); DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
while (e.oenv) while (global_env.oenv)
quitenv(); quitenv();
areanum = 1; areanum = 1;
@ -1373,8 +1342,8 @@ static void onecommand(void)
garbage(); garbage();
wdlist = 0; wdlist = 0;
iolist = 0; iolist = 0;
e.errpt = 0; global_env.errpt = 0;
e.linep = line; global_env.linep = line;
yynerrs = 0; yynerrs = 0;
multiline = 0; multiline = 0;
inparse = 1; inparse = 1;
@ -1387,7 +1356,7 @@ static void onecommand(void)
if (setjmp(failpt) || yyparse() || intr) { if (setjmp(failpt) || yyparse() || intr) {
DBGPRINTF(("ONECOMMAND: this is not good.\n")); DBGPRINTF(("ONECOMMAND: this is not good.\n"));
while (e.oenv) while (global_env.oenv)
quitenv(); quitenv();
scraphere(); scraphere();
if (!interactive && intr) if (!interactive && intr)
@ -1433,13 +1402,13 @@ static int newenv(int f)
ep = (struct env *) space(sizeof(*ep)); ep = (struct env *) space(sizeof(*ep));
if (ep == NULL) { if (ep == NULL) {
while (e.oenv) while (global_env.oenv)
quitenv(); quitenv();
fail(); fail();
} }
*ep = e; *ep = global_env;
e.oenv = ep; global_env.oenv = ep;
e.errpt = errpt; global_env.errpt = errpt;
return 0; return 0;
} }
@ -1449,15 +1418,15 @@ static void quitenv(void)
struct env *ep; struct env *ep;
int fd; int fd;
DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv)); DBGPRINTF(("QUITENV: global_env.oenv=%p\n", global_env.oenv));
ep = e.oenv; ep = global_env.oenv;
if (ep != NULL) { if (ep != NULL) {
fd = e.iofd; fd = global_env.iofd;
e = *ep; global_env = *ep;
/* should close `'d files */ /* should close `'d files */
DELETE(ep); DELETE(ep);
while (--fd >= e.iofd) while (--fd >= global_env.iofd)
close(fd); close(fd);
} }
} }
@ -1593,7 +1562,7 @@ static void yyerror(const char *s) ATTRIBUTE_NORETURN;
static void yyerror(const char *s) static void yyerror(const char *s)
{ {
yynerrs++; yynerrs++;
if (interactive && e.iop <= iostack) { if (interactive && global_env.iop <= iostack) {
multiline = 0; multiline = 0;
while (eofc() == 0 && yylex(0) != '\n'); while (eofc() == 0 && yylex(0) != '\n');
} }
@ -2085,11 +2054,38 @@ static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
/* See if given string is a shell multiline (FOR, IF, etc) */ /* See if given string is a shell multiline (FOR, IF, etc) */
static int rlookup(char *n) static int rlookup(char *n)
{ {
struct res {
char r_name[6];
int16_t r_val;
};
static const struct res restab[] = {
{ "for" , FOR },
{ "case" , CASE },
{ "esac" , ESAC },
{ "while", WHILE },
{ "do" , DO },
{ "done" , DONE },
{ "if" , IF },
{ "in" , IN },
{ "then" , THEN },
{ "else" , ELSE },
{ "elif" , ELIF },
{ "until", UNTIL },
{ "fi" , FI },
{ ";;" , BREAK },
{ "||" , LOGOR },
{ "&&" , LOGAND },
{ "{" , '{' },
{ "}" , '}' },
{ "." , DOT },
{ },
};
const struct res *rp; const struct res *rp;
DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n)); DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
for (rp = restab; rp->r_name; rp++) for (rp = restab; rp->r_name[0]; rp++)
if (strcmp(rp->r_name, n) == 0) { if (strcmp(rp->r_name, n) == 0) {
DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val)); DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
return rp->r_val; /* Return numeric code for shell multiline */ return rp->r_val; /* Return numeric code for shell multiline */
@ -2194,7 +2190,7 @@ static int yylex(int cf)
atstart = startl; atstart = startl;
startl = 0; startl = 0;
yylval.i = 0; yylval.i = 0;
e.linep = line; global_env.linep = line;
/* MALAMO */ /* MALAMO */
line[LINELIM - 1] = '\0'; line[LINELIM - 1] = '\0';
@ -2212,7 +2208,7 @@ static int yylex(int cf)
iounit = c - '0'; iounit = c - '0';
goto loop; goto loop;
} }
*e.linep++ = c; *global_env.linep++ = c;
c = c1; c = c1;
} }
break; break;
@ -2228,7 +2224,7 @@ static int yylex(int cf)
case '$': case '$':
DBGPRINTF9(("YYLEX: found $\n")); DBGPRINTF9(("YYLEX: found $\n"));
*e.linep++ = c; *global_env.linep++ = c;
c = my_getc(0); c = my_getc(0);
if (c == '{') { if (c == '{') {
c = collect(c, '}'); c = collect(c, '}');
@ -2269,7 +2265,7 @@ static int yylex(int cf)
gethere(); gethere();
startl = 1; startl = 1;
if (multiline || cf & CONTIN) { if (multiline || cf & CONTIN) {
if (interactive && e.iop <= iostack) { if (interactive && global_env.iop <= iostack) {
#if ENABLE_FEATURE_EDITING #if ENABLE_FEATURE_EDITING
current_prompt = cprompt->value; current_prompt = cprompt->value;
#else #else
@ -2291,10 +2287,10 @@ static int yylex(int cf)
pack: pack:
while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) { while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) {
if (e.linep >= elinep) if (global_env.linep >= elinep)
err("word too long"); err("word too long");
else else
*e.linep++ = c; *global_env.linep++ = c;
}; };
unget(c); unget(c);
@ -2302,7 +2298,7 @@ static int yylex(int cf)
if (any(c, "\"'`$")) if (any(c, "\"'`$"))
goto loop; goto loop;
*e.linep++ = '\0'; *global_env.linep++ = '\0';
if (atstart) { if (atstart) {
c = rlookup(line); c = rlookup(line);
@ -2323,7 +2319,7 @@ static int collect(int c, int c1)
DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1)); DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
*e.linep++ = c; *global_env.linep++ = c;
while ((c = my_getc(c1)) != c1) { while ((c = my_getc(c1)) != c1) {
if (c == 0) { if (c == 0) {
unget(c); unget(c);
@ -2333,17 +2329,17 @@ static int collect(int c, int c1)
yyerror(s); yyerror(s);
return YYERRCODE; return YYERRCODE;
} }
if (interactive && c == '\n' && e.iop <= iostack) { if (interactive && c == '\n' && global_env.iop <= iostack) {
#if ENABLE_FEATURE_EDITING #if ENABLE_FEATURE_EDITING
current_prompt = cprompt->value; current_prompt = cprompt->value;
#else #else
prs(cprompt->value); prs(cprompt->value);
#endif #endif
} }
*e.linep++ = c; *global_env.linep++ = c;
} }
*e.linep++ = c; *global_env.linep++ = c;
DBGPRINTF8(("COLLECT: return 0, line is %s\n", line)); DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
@ -3077,7 +3073,7 @@ static const char *rexecve(char *c, char **v, char **envp)
asis = (*sp == '\0'); asis = (*sp == '\0');
while (asis || *sp != '\0') { while (asis || *sp != '\0') {
asis = 0; asis = 0;
tp = e.linep; tp = global_env.linep;
for (; *sp != '\0'; tp++) { for (; *sp != '\0'; tp++) {
*tp = *sp++; *tp = *sp++;
if (*tp == ':') { if (*tp == ':') {
@ -3085,19 +3081,19 @@ static const char *rexecve(char *c, char **v, char **envp)
break; break;
} }
} }
if (tp != e.linep) if (tp != global_env.linep)
*tp++ = '/'; *tp++ = '/';
for (i = 0; (*tp++ = c[i++]) != '\0';); for (i = 0; (*tp++ = c[i++]) != '\0';);
DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep)); DBGPRINTF3(("REXECVE: global_env.linep is %s\n", global_env.linep));
execve(e.linep, v, envp); execve(global_env.linep, v, envp);
switch (errno) { switch (errno) {
case ENOEXEC: case ENOEXEC:
*v = e.linep; *v = global_env.linep;
tp = *--v; tp = *--v;
*v = e.linep; *v = global_env.linep;
execve(DEFAULT_SHELL, v, envp); execve(DEFAULT_SHELL, v, envp);
*v = tp; *v = tp;
return "no Shell"; return "no Shell";
@ -3149,7 +3145,7 @@ static int run(struct ioarg *argp, int (*f) (struct ioarg *))
wdlist = 0; wdlist = 0;
iolist = 0; iolist = 0;
pushio(argp, f); pushio(argp, f);
e.iobase = e.iop; global_env.iobase = global_env.iop;
yynerrs = 0; yynerrs = 0;
failpt = rt; failpt = rt;
if (setjmp(failpt) == 0 && yyparse() == 0) if (setjmp(failpt) == 0 && yyparse() == 0)
@ -3319,7 +3315,8 @@ static int dodot(struct op *t)
char *cp; char *cp;
int maltmp; int maltmp;
DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep))); DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, global_env.linep is %s\n",
t, t->left, t->right, ((global_env.linep == NULL) ? "NULL" : global_env.linep)));
cp = t->words[1]; cp = t->words[1];
if (cp == NULL) { if (cp == NULL) {
@ -3330,25 +3327,26 @@ static int dodot(struct op *t)
sp = any('/', cp) ? ":" : path->value; sp = any('/', cp) ? ":" : path->value;
DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n", DBGPRINTF(("DODOT: sp is %s, global_env.linep is %s\n",
((sp == NULL) ? "NULL" : sp), ((sp == NULL) ? "NULL" : sp),
((e.linep == NULL) ? "NULL" : e.linep))); ((global_env.linep == NULL) ? "NULL" : global_env.linep)));
while (*sp) { while (*sp) {
tp = e.linep; tp = global_env.linep;
while (*sp && (*tp = *sp++) != ':') while (*sp && (*tp = *sp++) != ':')
tp++; tp++;
if (tp != e.linep) if (tp != global_env.linep)
*tp++ = '/'; *tp++ = '/';
for (i = 0; (*tp++ = cp[i++]) != '\0';); for (i = 0; (*tp++ = cp[i++]) != '\0';);
/* Original code */ /* Original code */
i = open(e.linep, O_RDONLY); i = open(global_env.linep, O_RDONLY);
if (i >= 0) { if (i >= 0) {
exstat = 0; exstat = 0;
maltmp = remap(i); maltmp = remap(i);
DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep)); DBGPRINTF(("DODOT: remap=%d, exstat=%d, global_env.iofd %d, i %d, global_env.linep is %s\n",
maltmp, exstat, global_env.iofd, i, global_env.linep));
next(maltmp); /* Basically a PUSHIO */ next(maltmp); /* Basically a PUSHIO */
@ -3391,7 +3389,7 @@ static int doread(struct op *t)
return 1; return 1;
} }
for (wp = t->words + 1; *wp; wp++) { for (wp = t->words + 1; *wp; wp++) {
for (cp = e.linep; !nl && cp < elinep - 1; cp++) { for (cp = global_env.linep; !nl && cp < elinep - 1; cp++) {
nb = read(0, cp, sizeof(*cp)); nb = read(0, cp, sizeof(*cp));
if (nb != sizeof(*cp)) if (nb != sizeof(*cp))
break; break;
@ -3402,7 +3400,7 @@ static int doread(struct op *t)
*cp = '\0'; *cp = '\0';
if (nb <= 0) if (nb <= 0)
break; break;
setval(lookup(*wp), e.linep); setval(lookup(*wp), global_env.linep);
} }
return nb <= 0; return nb <= 0;
} }
@ -3760,9 +3758,9 @@ static int expand(const char *cp, struct wdblock **wbp, int f)
errpt = ev; errpt = ev;
if (newenv(setjmp(errpt)) == 0) { if (newenv(setjmp(errpt)) == 0) {
PUSHIO(aword, cp, strchar); PUSHIO(aword, cp, strchar);
e.iobase = e.iop; global_env.iobase = global_env.iop;
while ((xp = blank(f)) && gflg == 0) { while ((xp = blank(f)) && gflg == 0) {
e.linep = xp; global_env.linep = xp;
xp = strsave(xp, areanum); xp = strsave(xp, areanum);
if ((f & DOGLOB) == 0) { if ((f & DOGLOB) == 0) {
if (f & DOTRIM) if (f & DOTRIM)
@ -3811,7 +3809,7 @@ static char *blank(int f)
DBGPRINTF3(("BLANK: enter, f=%d\n", f)); DBGPRINTF3(("BLANK: enter, f=%d\n", f));
sp = e.linep; sp = global_env.linep;
scanequals = f & DOKEY; scanequals = f & DOKEY;
foundequals = 0; foundequals = 0;
@ -3819,9 +3817,9 @@ static char *blank(int f)
c = subgetc('"', foundequals); c = subgetc('"', foundequals);
switch (c) { switch (c) {
case 0: case 0:
if (sp == e.linep) if (sp == global_env.linep)
return 0; return 0;
*e.linep++ = 0; *global_env.linep++ = 0;
return sp; return sp;
default: default:
@ -3839,7 +3837,7 @@ static char *blank(int f)
break; break;
if (c == '\'' || !any(c, "$`\"")) if (c == '\'' || !any(c, "$`\""))
c |= QUOTE; c |= QUOTE;
*e.linep++ = c; *global_env.linep++ = c;
} }
c = 0; c = 0;
} }
@ -3864,9 +3862,9 @@ static char *blank(int f)
} else if (!isalnum(c) && c != '_') } else if (!isalnum(c) && c != '_')
scanequals = 0; scanequals = 0;
} }
*e.linep++ = c; *global_env.linep++ = c;
} }
*e.linep++ = 0; *global_env.linep++ = 0;
return sp; return sp;
} }
@ -3885,13 +3883,13 @@ static int subgetc(char ec, int quoted)
if (c == '`') { if (c == '`') {
if (grave(quoted) == 0) if (grave(quoted) == 0)
return 0; return 0;
e.iop->task = XGRAVE; global_env.iop->task = XGRAVE;
goto again; goto again;
} }
if (c == '$') { if (c == '$') {
c = dollar(quoted); c = dollar(quoted);
if (c == 0) { if (c == 0) {
e.iop->task = XDOLL; global_env.iop->task = XDOLL;
goto again; goto again;
} }
} }
@ -3913,38 +3911,38 @@ static int dollar(int quoted)
DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted)); DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
c = readc(); c = readc();
s = e.linep; s = global_env.linep;
if (c != '{') { if (c != '{') {
*e.linep++ = c; *global_env.linep++ = c;
if (isalpha(c) || c == '_') { if (isalpha(c) || c == '_') {
while ((c = readc()) != 0 && (isalnum(c) || c == '_')) while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
if (e.linep < elinep) if (global_env.linep < elinep)
*e.linep++ = c; *global_env.linep++ = c;
unget(c); unget(c);
} }
c = 0; c = 0;
} else { } else {
oiop = e.iop; oiop = global_env.iop;
otask = e.iop->task; otask = global_env.iop->task;
e.iop->task = XOTHER; global_env.iop->task = XOTHER;
while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n') while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
if (e.linep < elinep) if (global_env.linep < elinep)
*e.linep++ = c; *global_env.linep++ = c;
if (oiop == e.iop) if (oiop == global_env.iop)
e.iop->task = otask; global_env.iop->task = otask;
if (c != '}') { if (c != '}') {
err("unclosed ${"); err("unclosed ${");
gflg++; gflg++;
return c; return c;
} }
} }
if (e.linep >= elinep) { if (global_env.linep >= elinep) {
err("string in ${} too long"); err("string in ${} too long");
gflg++; gflg++;
e.linep -= 10; global_env.linep -= 10;
} }
*e.linep = 0; *global_env.linep = 0;
if (*s) if (*s)
for (cp = s + 1; *cp; cp++) for (cp = s + 1; *cp; cp++)
if (any(*cp, "=-+?")) { if (any(*cp, "=-+?")) {
@ -3956,7 +3954,7 @@ static int dollar(int quoted)
if (dolc > 1) { if (dolc > 1) {
/* currently this does not distinguish $* and $@ */ /* currently this does not distinguish $* and $@ */
/* should check dollar */ /* should check dollar */
e.linep = s; global_env.linep = s;
PUSHIO(awordlist, dolv + 1, dolchar); PUSHIO(awordlist, dolv + 1, dolchar);
return 0; return 0;
} else { /* trap the nasty ${=} */ } else { /* trap the nasty ${=} */
@ -3998,7 +3996,7 @@ static int dollar(int quoted)
err(s); err(s);
gflg++; gflg++;
} }
e.linep = s; global_env.linep = s;
PUSHIO(aword, dolp, quoted ? qstrchar : strchar); PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
return 0; return 0;
} }
@ -4028,7 +4026,7 @@ static int grave(int quoted)
(void) &cp; (void) &cp;
#endif #endif
for (cp = e.iop->argp->aword; *cp != '`'; cp++) { for (cp = global_env.iop->argp->aword; *cp != '`'; cp++) {
if (*cp == 0) { if (*cp == 0) {
err("no closing `"); err("no closing `");
return 0; return 0;
@ -4036,7 +4034,7 @@ static int grave(int quoted)
} }
/* string copy with dollar expansion */ /* string copy with dollar expansion */
src = e.iop->argp->aword; src = global_env.iop->argp->aword;
dest = child_cmd; dest = child_cmd;
count = 0; count = 0;
ignore = 0; ignore = 0;
@ -4165,7 +4163,7 @@ static int grave(int quoted)
} }
if (i != 0) { if (i != 0) {
waitpid(i, NULL, 0); waitpid(i, NULL, 0);
e.iop->argp->aword = ++cp; global_env.iop->argp->aword = ++cp;
close(pf[1]); close(pf[1]);
PUSHIO(afile, remap(pf[0]), PUSHIO(afile, remap(pf[0]),
(int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar)); (int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar));
@ -4535,14 +4533,14 @@ static int my_getc(int ec)
{ {
int c; int c;
if (e.linep > elinep) { if (global_env.linep > elinep) {
while ((c = readc()) != '\n' && c); while ((c = readc()) != '\n' && c);
err("input line too long"); err("input line too long");
gflg++; gflg++;
return c; return c;
} }
c = readc(); c = readc();
if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) { if ((ec != '\'') && (ec != '`') && (global_env.iop->task != XGRAVE)) {
if (c == '\\') { if (c == '\\') {
c = readc(); c = readc();
if (c == '\n' && ec != '\"') if (c == '\n' && ec != '\"')
@ -4555,53 +4553,53 @@ static int my_getc(int ec)
static void unget(int c) static void unget(int c)
{ {
if (e.iop >= e.iobase) if (global_env.iop >= global_env.iobase)
e.iop->peekc = c; global_env.iop->peekc = c;
} }
static int eofc(void) static int eofc(void)
{ {
return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0); return global_env.iop < global_env.iobase || (global_env.iop->peekc == 0 && global_env.iop->prev == 0);
} }
static int readc(void) static int readc(void)
{ {
int c; int c;
RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase)); RCPRINTF(("READC: global_env.iop %p, global_env.iobase %p\n", global_env.iop, global_env.iobase));
for (; e.iop >= e.iobase; e.iop--) { for (; global_env.iop >= global_env.iobase; global_env.iop--) {
RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc)); RCPRINTF(("READC: global_env.iop %p, peekc 0x%x\n", global_env.iop, global_env.iop->peekc));
c = e.iop->peekc; c = global_env.iop->peekc;
if (c != '\0') { if (c != '\0') {
e.iop->peekc = 0; global_env.iop->peekc = 0;
return c; return c;
} }
if (e.iop->prev != 0) { if (global_env.iop->prev != 0) {
c = (*e.iop->iofn)(e.iop->argp, e.iop); c = (*global_env.iop->iofn)(global_env.iop->argp, global_env.iop);
if (c != '\0') { if (c != '\0') {
if (c == -1) { if (c == -1) {
e.iop++; global_env.iop++;
continue; continue;
} }
if (e.iop == iostack) if (global_env.iop == iostack)
ioecho(c); ioecho(c);
e.iop->prev = c; global_env.iop->prev = c;
return e.iop->prev; return global_env.iop->prev;
} }
if (e.iop->task == XIO && e.iop->prev != '\n') { if (global_env.iop->task == XIO && global_env.iop->prev != '\n') {
e.iop->prev = 0; global_env.iop->prev = 0;
if (e.iop == iostack) if (global_env.iop == iostack)
ioecho('\n'); ioecho('\n');
return '\n'; return '\n';
} }
} }
if (e.iop->task == XIO) { if (global_env.iop->task == XIO) {
if (multiline) { if (multiline) {
e.iop->prev = 0; global_env.iop->prev = 0;
return e.iop->prev; return global_env.iop->prev;
} }
if (interactive && e.iop == iostack + 1) { if (interactive && global_env.iop == iostack + 1) {
#if ENABLE_FEATURE_EDITING #if ENABLE_FEATURE_EDITING
current_prompt = prompt->value; current_prompt = prompt->value;
#else #else
@ -4611,8 +4609,8 @@ static int readc(void)
} }
} /* FOR */ } /* FOR */
if (e.iop >= iostack) { if (global_env.iop >= iostack) {
RCPRINTF(("READC: return 0, e.iop %p\n", e.iop)); RCPRINTF(("READC: return 0, global_env.iop %p\n", global_env.iop));
return 0; return 0;
} }
@ -4632,12 +4630,12 @@ static void ioecho(char c)
static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *)) static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
{ {
DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp, DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, global_env.iop %p\n", argp,
argp->afid, e.iop)); argp->afid, global_env.iop));
/* Set env ptr for io source to next array spot and check for array overflow */ /* Set env ptr for io source to next array spot and check for array overflow */
if (++e.iop >= &iostack[NPUSH]) { if (++global_env.iop >= &iostack[NPUSH]) {
e.iop--; global_env.iop--;
err("Shell input nested too deeply"); err("Shell input nested too deeply");
gflg++; gflg++;
return; return;
@ -4645,60 +4643,60 @@ static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
/* We did not overflow the NPUSH array spots so setup data structs */ /* We did not overflow the NPUSH array spots so setup data structs */
e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */ global_env.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
if (argp->afid != AFID_NOBUF) if (argp->afid != AFID_NOBUF)
e.iop->argp = argp; global_env.iop->argp = argp;
else { else {
e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */ global_env.iop->argp = ioargstack + (global_env.iop - iostack); /* MAL - index into stack */
*e.iop->argp = *argp; /* copy data from temp area into stack spot */ *global_env.iop->argp = *argp; /* copy data from temp area into stack spot */
/* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */ /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
if (e.iop == &iostack[0]) if (global_env.iop == &iostack[0])
e.iop->argp->afbuf = &mainbuf; global_env.iop->argp->afbuf = &mainbuf;
else else
e.iop->argp->afbuf = &sharedbuf; global_env.iop->argp->afbuf = &sharedbuf;
/* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */ /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
/* This line appears to be active when running scripts from command line */ /* This line appears to be active when running scripts from command line */
if ((isatty(e.iop->argp->afile) == 0) if ((isatty(global_env.iop->argp->afile) == 0)
&& (e.iop == &iostack[0] && (global_env.iop == &iostack[0]
|| lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) { || lseek(global_env.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */ if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
bufid = AFID_ID; /* AFID_ID = 0 */ bufid = AFID_ID; /* AFID_ID = 0 */
e.iop->argp->afid = bufid; /* assign buffer id */ global_env.iop->argp->afid = bufid; /* assign buffer id */
} }
DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n", DBGPRINTF(("PUSHIO: iostack %p, global_env.iop %p, afbuf %p\n",
iostack, e.iop, e.iop->argp->afbuf)); iostack, global_env.iop, global_env.iop->argp->afbuf));
DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n", DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, global_env.iop %p\n",
&mainbuf, &sharedbuf, bufid, e.iop)); &mainbuf, &sharedbuf, bufid, global_env.iop));
} }
e.iop->prev = ~'\n'; global_env.iop->prev = ~'\n';
e.iop->peekc = 0; global_env.iop->peekc = 0;
e.iop->xchar = 0; global_env.iop->xchar = 0;
e.iop->nlcount = 0; global_env.iop->nlcount = 0;
if (fn == filechar || fn == linechar) if (fn == filechar || fn == linechar)
e.iop->task = XIO; global_env.iop->task = XIO;
else if (fn == (int (*)(struct ioarg *)) gravechar else if (fn == (int (*)(struct ioarg *)) gravechar
|| fn == (int (*)(struct ioarg *)) qgravechar) || fn == (int (*)(struct ioarg *)) qgravechar)
e.iop->task = XGRAVE; global_env.iop->task = XGRAVE;
else else
e.iop->task = XOTHER; global_env.iop->task = XOTHER;
} }
static struct io *setbase(struct io *ip) static struct io *setbase(struct io *ip)
{ {
struct io *xp; struct io *xp;
xp = e.iobase; xp = global_env.iobase;
e.iobase = ip; global_env.iobase = ip;
return xp; return xp;
} }
@ -4929,9 +4927,9 @@ static int remap(int fd)
int map[NOFILE]; int map[NOFILE];
int newfd; int newfd;
DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd)); DBGPRINTF(("REMAP: fd=%d, global_env.iofd=%d\n", fd, global_env.iofd));
if (fd < e.iofd) { if (fd < global_env.iofd) {
for (i = 0; i < NOFILE; i++) for (i = 0; i < NOFILE; i++)
map[i] = 0; map[i] = 0;
@ -4939,7 +4937,7 @@ static int remap(int fd)
map[fd] = 1; map[fd] = 1;
newfd = dup(fd); newfd = dup(fd);
fd = newfd; fd = newfd;
} while (fd >= 0 && fd < e.iofd); } while (fd >= 0 && fd < global_env.iofd);
for (i = 0; i < NOFILE; i++) for (i = 0; i < NOFILE; i++)
if (map[i]) if (map[i])
@ -5052,10 +5050,10 @@ static void readhere(char **name, char *s, int ec)
if (newenv(setjmp(errpt)) != 0) if (newenv(setjmp(errpt)) != 0)
unlink(tname); unlink(tname);
else { else {
pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn); pushio(global_env.iop->argp, (int (*)(struct ioarg *)) global_env.iop->iofn);
e.iobase = e.iop; global_env.iobase = global_env.iop;
for (;;) { for (;;) {
if (interactive && e.iop <= iostack) { if (interactive && global_env.iop <= iostack) {
#if ENABLE_FEATURE_EDITING #if ENABLE_FEATURE_EDITING
current_prompt = cprompt->value; current_prompt = cprompt->value;
#else #else
@ -5121,7 +5119,7 @@ static int herein(char *hname, int xdoll)
errpt = ev; errpt = ev;
if (newenv(setjmp(errpt)) == 0) { if (newenv(setjmp(errpt)) == 0) {
PUSHIO(afile, hf, herechar); PUSHIO(afile, hf, herechar);
setbase(e.iop); setbase(global_env.iop);
while ((c = subgetc(0, 0)) != 0) { while ((c = subgetc(0, 0)) != 0) {
c &= ~QUOTE; c &= ~QUOTE;
write(tf, &c, sizeof c); write(tf, &c, sizeof c);
@ -5189,7 +5187,6 @@ int msh_main(int argc, char **argv)
sharedbuf.id = AFID_NOBUF; sharedbuf.id = AFID_NOBUF;
mainbuf.id = AFID_NOBUF; mainbuf.id = AFID_NOBUF;
e.linep = line;
elinep = line + sizeof(line) - 5; elinep = line + sizeof(line) - 5;
#if ENABLE_FEATURE_EDITING #if ENABLE_FEATURE_EDITING
@ -5321,7 +5318,7 @@ int msh_main(int argc, char **argv)
setdash(); setdash();
/* This won't be true if PUSHIO has been called, say from newfile() above */ /* This won't be true if PUSHIO has been called, say from newfile() above */
if (e.iop < iostack) { if (global_env.iop < iostack) {
PUSHIO(afile, 0, iof); PUSHIO(afile, 0, iof);
if (isatty(0) && isatty(1) && !cflag) { if (isatty(0) && isatty(1) && !cflag) {
interactive++; interactive++;
@ -5366,10 +5363,10 @@ int msh_main(int argc, char **argv)
} }
setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc)); setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack)); DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, global_env.iop %p, iostack %p\n", interactive, global_env.iop, iostack));
for (;;) { for (;;) {
if (interactive && e.iop <= iostack) { if (interactive && global_env.iop <= iostack) {
#if ENABLE_FEATURE_EDITING #if ENABLE_FEATURE_EDITING
current_prompt = prompt->value; current_prompt = prompt->value;
#else #else