BSD 3 development
[unix-history] / usr / src / cmd / csh / sh.exp.c
/* Copyright (c) 1979 Regents of the University of California */
#include "sh.h"
/*
* C shell
*/
#define ADDOP 1
#define MULOP 2
#define EQOP 4
#define RELOP 8
#define RESTOP 16
#define ANYOP 31
#define EQEQ 1
#define GTR 2
#define LSS 4
#define NOTEQ 6
exp(vp)
register char ***vp;
{
return (exp0(vp, 0));
}
exp0(vp, ignore)
register char ***vp;
bool ignore;
{
register int p1 = exp1(vp, ignore);
#ifdef EDEBUG
etraci("exp0 p1", p1, vp);
#endif
if (**vp && eq(**vp, "||")) {
register int p2;
(*vp)++;
p2 = exp0(vp, ignore || p1);
#ifdef EDEBUG
etraci("exp0 p2", p2, vp);
#endif
return (p1 || p2);
}
return (p1);
}
exp1(vp, ignore)
register char ***vp;
{
register int p1 = exp2(vp, ignore);
#ifdef EDEBUG
etraci("exp1 p1", p1, vp);
#endif
if (**vp && eq(**vp, "&&")) {
register int p2;
(*vp)++;
p2 = exp1(vp, ignore || !p1);
#ifdef EDEBUG
etraci("exp1 p2", p2, vp);
#endif
return (p1 && p2);
}
return (p1);
}
exp2(vp, ignore)
register char ***vp;
bool ignore;
{
register int p1 = exp2a(vp, ignore);
#ifdef EDEBUG
etraci("exp3 p1", p1, vp);
#endif
if (**vp && eq(**vp, "|")) {
register int p2;
(*vp)++;
p2 = exp2(vp, ignore);
#ifdef EDEBUG
etraci("exp3 p2", p2, vp);
#endif
return (p1 | p2);
}
return (p1);
}
exp2a(vp, ignore)
register char ***vp;
bool ignore;
{
register int p1 = exp2b(vp, ignore);
#ifdef EDEBUG
etraci("exp2a p1", p1, vp);
#endif
if (**vp && eq(**vp, "^")) {
register int p2;
(*vp)++;
p2 = exp2a(vp, ignore);
#ifdef EDEBUG
etraci("exp2a p2", p2, vp);
#endif
return (p1 ^ p2);
}
return (p1);
}
exp2b(vp, ignore)
register char ***vp;
bool ignore;
{
register int p1 = exp2c(vp, ignore);
#ifdef EDEBUG
etraci("exp2b p1", p1, vp);
#endif
if (**vp && eq(**vp, "&")) {
register int p2;
(*vp)++;
p2 = exp2b(vp, ignore);
#ifdef EDEBUG
etraci("exp2b p2", p2, vp);
#endif
return (p1 & p2);
}
return (p1);
}
exp2c(vp, ignore)
register char ***vp;
bool ignore;
{
register char *p1 = exp3(vp, ignore);
register char *p2;
register int i;
#ifdef EDEBUG
etracc("exp2c p1", p1, vp);
#endif
if (i = isa(**vp, EQOP)) {
(*vp)++;
p2 = exp3(vp, ignore);
#ifdef EDEBUG
etracc("exp2c p2", p2, vp);
#endif
if (!ignore) switch (i) {
case EQEQ:
i = eq(p1, p2);
break;
case NOTEQ:
i = !eq(p1, p2);
break;
}
xfree(p1), xfree(p2);
return (i);
}
i = egetn(p1);
xfree(p1);
return (i);
}
char *
exp3(vp, ignore)
register char ***vp;
bool ignore;
{
register char *p1, *p2;
register int i;
p1 = exp3a(vp, ignore);
#ifdef EDEBUG
etracc("exp3 p1", p1, vp);
#endif
if (i = isa(**vp, RELOP)) {
(*vp)++;
if (**vp && eq(**vp, "="))
i |= 1, (*vp)++;
p2 = exp3(vp, ignore);
#ifdef EDEBUG
etracc("exp3 p2", p2, vp);
#endif
if (!ignore) switch (i) {
case GTR:
i = egetn(p1) > egetn(p2);
break;
case GTR|1:
i = egetn(p1) >= egetn(p2);
break;
case LSS:
i = egetn(p1) < egetn(p2);
break;
case LSS|1:
i = egetn(p1) <= egetn(p2);
break;
}
xfree(p1), xfree(p2);
return (putn(i));
}
return (p1);
}
char *
exp3a(vp, ignore)
register char ***vp;
bool ignore;
{
register char *p1, *p2, *op;
register int i;
p1 = exp4(vp, ignore);
#ifdef EDEBUG
etracc("exp3a p1", p1, vp);
#endif
op = **vp;
if (op && any(op[0], "<>") && op[0] == op[1]) {
(*vp)++;
p2 = exp3a(vp, ignore);
#ifdef EDEBUG
etracc("exp3a p2", p2, vp);
#endif
if (op[0] == '<')
i = egetn(p1) << egetn(p2);
else
i = egetn(p1) >> egetn(p2);
xfree(p1), xfree(p2);
return (putn(i));
}
return (p1);
}
char *
exp4(vp, ignore)
register char ***vp;
bool ignore;
{
register char *p1, *p2;
register int i = 0;
p1 = exp5(vp, ignore);
#ifdef EDEBUG
etracc("exp4 p1", p1, vp);
#endif
if (isa(**vp, ADDOP)) {
register char *op = *(*vp)++;
p2 = exp4(vp, ignore);
#ifdef EDEBUG
etracc("exp4 p2", p2, vp);
#endif
if (!ignore) switch (op[0]) {
case '+':
i = egetn(p1) + egetn(p2);
break;
case '-':
i = egetn(p1) - egetn(p2);
break;
}
xfree(p1), xfree(p2);
return (putn(i));
}
return (p1);
}
char *
exp5(vp, ignore)
register char ***vp;
bool ignore;
{
register char *p1, *p2;
register int i = 0;
p1 = exp6(vp, ignore);
#ifdef EDEBUG
etracc("exp5 p1", p1, vp);
#endif
if (isa(**vp, MULOP)) {
register char *op = *(*vp)++;
p2 = exp5(vp, ignore);
#ifdef EDEBUG
etracc("exp5 p2", p2, vp);
#endif
if (!ignore) switch (op[0]) {
case '*':
i = egetn(p1) * egetn(p2);
break;
case '/':
i = egetn(p2);
if (i == 0)
error("Divide by 0");
i = egetn(p1) / i;
break;
case '%':
i = egetn(p2);
if (i == 0)
error("Mod by 0");
i = egetn(p1) % i;
break;
}
xfree(p1), xfree(p2);
return (putn(i));
}
return (p1);
}
char *
exp6(vp, ignore)
register char ***vp;
{
int ccode, i;
register char *cp, *dp, *ep;
if (eq(**vp, "!")) {
(*vp)++;
cp = exp6(vp, ignore);
#ifdef EDEBUG
etracc("exp6 ! cp", cp, vp);
#endif
i = egetn(cp);
xfree(cp);
return (putn(!i));
}
if (eq(**vp, "~")) {
(*vp)++;
cp = exp6(vp, ignore);
#ifdef EDEBUG
etracc("exp6 ~ cp", cp, vp);
#endif
i = egetn(cp);
xfree(cp);
return (putn(~i));
}
if (eq(**vp, "(")) {
(*vp)++;
ccode = exp0(vp, ignore);
#ifdef EDEBUG
etraci("exp6 () ccode", ccode, vp);
#endif
if (*vp == 0 || **vp == 0 || ***vp != ')')
bferr("Expression syntax");
(*vp)++;
return (putn(ccode));
}
if (eq(**vp, "{")) {
int pid;
register char **v;
(*vp)++;
v = *vp;
for (;;) {
if (!**vp)
bferr("Missing }");
if (eq(*(*vp)++, "}"))
break;
}
if (ignore)
return ("");
pid = fork();
if (pid < 0)
Perror("fork");
if (pid == 0) {
if (setintr)
signal(SIGINT, SIG_DFL);
*--(*vp) = 0;
evalav(v);
exitstat();
}
cadd(pid, "{}");
pwait(pid);
#ifdef EDEBUG
etraci("exp6 {} status", egetn(value("status")), vp);
#endif
return (putn(egetn(value("status")) == 0));
}
if (isa(**vp, ANYOP))
return ("");
cp = *(*vp)++;
if (*cp == '-' && any(cp[1], "erwxfdzo")) {
struct stat stb;
if (isa(**vp, ANYOP))
bferr("Missing file name");
dp = *(*vp)++;
if (ignore)
return ("");
ep = globone(dp);
switch (cp[1]) {
case 'r':
i = !access(ep, 4);
break;
case 'w':
i = !access(ep, 2);
break;
case 'x':
i = !access(ep, 1);
break;
default:
if (stat(ep, &stb)) {
xfree(ep);
return ("0");
}
switch (cp[1]) {
case 'f':
i = (stb.st_mode & S_IFMT) == S_IFREG;
break;
case 'd':
i = (stb.st_mode & S_IFMT) == S_IFDIR;
break;
case 'z':
i = stb.st_size == 0;
break;
case 'e':
i = 1;
break;
case 'o':
i = stb.st_uid == uid;
break;
}
}
#ifdef EDEBUG
etraci("exp6 -? i", i, vp);
#endif
xfree(ep);
return (putn(i));
}
#ifdef EDEBUG
etracc("exp6 default", cp, vp);
#endif
return (globone(cp));
}
evalav(v)
register char **v;
{
struct wordent paraml;
register struct wordent *hp = &paraml;
struct command *t;
register struct wordent *wdp = hp;
child++;
set("status", "0");
hp->prev = hp->next = hp;
hp->word = "";
while (*v) {
register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp);
new->prev = wdp;
new->next = hp;
wdp->next = new;
wdp = new;
wdp->word = savestr(*v++);
}
hp->prev = wdp;
alias(&paraml);
t = syntax(paraml.next, &paraml);
if (err)
error(err);
execute(t);
freelex(&paraml), freesyn(t);
}
isa(cp, what)
register char *cp;
register int what;
{
if (cp == 0)
return ((what & RESTOP) != 0);
if (cp[1] == 0) {
if ((what & ADDOP) && any(cp[0], "+-"))
return (1);
if ((what & MULOP) && any(cp[0], "*/%"))
return (1);
if ((what & RESTOP) && any(cp[0], "()!~^"))
return (1);
}
if ((what & RESTOP) && (any(cp[0], "|&") || eq(cp, "<<") || eq(cp, ">>")))
return (1);
if (what & EQOP) {
if (eq(cp, "=="))
return (EQEQ);
if (eq(cp, "!="))
return (NOTEQ);
}
if (!(what & RELOP))
return (0);
if (*cp == '<')
return (LSS);
if (*cp == '>')
return (GTR);
return (0);
}
egetn(cp)
register char *cp;
{
if (*cp && *cp != '-' && !digit(*cp))
bferr("Expression syntax");
return (getn(cp));
}
/* Phew! */
#ifdef EDEBUG
etraci(str, i, vp)
char *str;
int i;
char ***vp;
{
printf("%s=%d\t", str, i);
blkpr(*vp);
printf("\n");
}
etracc(str, cp, vp)
char *str, *cp;
char ***vp;
{
printf("%s=%s\t", str, cp);
blkpr(*vp);
printf("\n");
}
#endif