any -> index (use the faster library routine)
[unix-history] / usr / src / bin / csh / exp.c
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley Software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
static char *sccsid = "@(#)exp.c 5.4 (Berkeley) %G%";
#endif
#include "sh.h"
/*
* C shell
*/
#define IGNORE 1 /* in ignore, it means to ignore value, just parse */
#define NOGLOB 2 /* in ignore, it means not to globone */
#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
#define EQMATCH 7
#define NOTEQMATCH 8
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&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&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)++;
if (i == EQMATCH || i == NOTEQMATCH)
ignore |= NOGLOB;
p2 = exp3(vp, ignore);
#ifdef EDEBUG
etracc("exp2c p2", p2, vp);
#endif
if (!(ignore&IGNORE)) switch (i) {
case EQEQ:
i = eq(p1, p2);
break;
case NOTEQ:
i = !eq(p1, p2);
break;
case EQMATCH:
i = Gmatch(p1, p2);
break;
case NOTEQMATCH:
i = !Gmatch(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&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 && index("<>", 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&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&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 (**vp == 0)
bferr("Expression syntax");
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, "{")) {
register char **v;
struct command faket;
char *fakecom[2];
faket.t_dtyp = TCOM;
faket.t_dflg = 0;
faket.t_dcar = faket.t_dcdr = faket.t_dspr = (struct command *)0;
faket.t_dcom = fakecom;
fakecom[0] = "{ ... }";
fakecom[1] = NOSTR;
(*vp)++;
v = *vp;
for (;;) {
if (!**vp)
bferr("Missing }");
if (eq(*(*vp)++, "}"))
break;
}
if (ignore&IGNORE)
return ("");
psavejob();
if (pfork(&faket, -1) == 0) {
*--(*vp) = 0;
evalav(v);
exitstat();
}
pwait();
prestjob();
#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 == '-' && index("erwxfdzo", cp[1])) {
struct stat stb;
if (isa(**vp, ANYOP))
bferr("Missing file name");
dp = *(*vp)++;
if (ignore&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 (ignore&NOGLOB ? savestr(cp) : globone(cp));
}
evalav(v)
register char **v;
{
struct wordent paraml;
register struct wordent *hp = &paraml;
struct command *t;
register struct wordent *wdp = hp;
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, 0);
if (err)
error(err);
execute(t, -1);
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 && (*cp == '+' || *cp == '-'))
return (1);
if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
return (1);
if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
*cp == '~' || *cp == '^' || *cp == '"'))
return (1);
} else if (cp[2] == 0) {
if (what & RESTOP) {
if (cp[0] == '|' && cp[1] == '&')
return (1);
if (cp[0] == '<' && cp[1] == '<')
return (1);
if (cp[0] == '>' && cp[1] == '>')
return (1);
}
if (what & EQOP) {
if (cp[0] == '=') {
if (cp[1] == '=')
return (EQEQ);
if (cp[1] == '~')
return (EQMATCH);
} else if (cp[0] == '!') {
if (cp[1] == '=')
return (NOTEQ);
if (cp[1] == '~')
return (NOTEQMATCH);
}
}
}
if (what & RELOP) {
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