|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 6259 (0x1873)
Types: TextFile
Notes: UNIX file
Names: »eval.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/rsh/eval.c«
└─⟦this⟧ »cmd/sh/eval.c«
#include "sh.h"
/*
* Evaluation of parameter substitution, command substitution,
* blank interpretation, and file name generation.
*/
char *arcp; /* character position in argument */
int argf = 1; /* First argument flag */
int argg = 0; /* Glob seek, escape quoted glob chars */
int argq = 0; /* Quotation flag, no blanks or glob */
/*
* Evaluate a string.
*/
eval(cp, f)
char *cp;
{
register int m, c;
strp = strt;
arcp = cp;
argf = 1;
if (f==EHERE) {
m = MHERE;
argq = 2;
} else if (f==EWORD) {
m = MNQUO;
argq = 2;
} else {
m = MNQUO;
argq = 0;
}
if (f==EARGS || f==EPATT)
argg = 1;
else
argg = 0;
while ((c=*arcp++) != '\0') {
if (!class(c, m)) {
breakup(c);
continue;
}
switch (c) {
case '"': /* m == MNQUO || m == MDQUO */
m = ((argq^=1)&1) ? MDQUO : MNQUO;
if (m==MDQUO && strcmp(arcp, "$@\"")!=0)
argf = 0;
continue;
case '\'': /* m == MNQUO */
while ((c=*arcp++) != '\'')
qbreakup(c);
argf = 0;
continue;
case '\\': /* m == MDQUO || m == MNQUO */
c = *arcp++;
if (m != MNQUO && ! class(c, m)) {
breakup('\\');
breakup(c);
} else
qbreakup(c);
argf = 0;
continue;
case '$': /* m == MNQUO || m = MDQUO */
evalvar();
continue;
case '`': /* m == MNQUO || m = MDQUO */
evalcom();
continue;
default:
breakup(c);
continue;
}
}
if (f==EARGS)
addlist();
else
*strp++ = '\0';
}
/*
* Read the name of a shell variable and perform the appropriate
* substitution.
* Doesn't check for end of buffer.
*/
evalvar()
{
VAR *vp;
int s;
char *wp;
register int c;
register char *cp, *pp;
cp = strp;
s = '\0';
c = *arcp++;
if (class(c, MSVAR)) {
specvar(c);
return;
} else if (c != '{') {
while (class(c, MRVAR)) {
*cp++ = c;
c = *arcp++;
}
--arcp;
} else {
while (index("}-=?+", c=*arcp++) == NULL)
*cp++ = c;
if (c != '}') {
s = c;
*cp++ = '=';
wp = cp;
while ((c=*arcp++) != '}')
*cp++ = c;
}
}
*cp++ = '\0';
if (class((c = *strp), MDIGI)) {
if ((c -= '1') >= sargc)
pp = NULL;
else
pp = sargp[c];
} else if (namevar(strp) == 0) {
eillvar(strp);
return;
} else {
pp = NULL;
if ((vp=findvar(strp)) != NULL) {
pp = convvar(vp);
}
}
switch (s) {
case '\0':
if (uflag!=0 && pp==NULL)
enotdef(strp);
break;
case '-':
if (pp == NULL)
pp = wp;
break;
case '=':
if (pp == NULL) {
pp = wp;
if (class(*strp, MDIGI)) {
printe("Illegal substitution");
return;
}
setsvar(strp);
}
break;
case '?':
if (pp != NULL)
break;
if (*wp != '\0')
prints("%s\n", wp);
else {
*--wp = '\0';
enotdef(strp);
}
reset(RUABORT);
NOTREACHED;
case '+':
if (pp != NULL)
pp = wp;
break;
}
if (pp == NULL)
return;
while ((c=*pp++) != '\0')
breakup(c);
}
/*
* Return the value of the special shell variables.
* No check for end of buffer.
*/
specvar(n)
register int n;
{
register char *sp;
register int flag;
sp = strp;
switch (n) {
case '#':
n = sargc;
goto maked;
case '?':
n = slret;
goto maked;
case '$':
n = shpid;
goto maked;
case '!':
n = sback;
goto maked;
maked:
sprintf(sp, "%d", n);
break;
case '-':
for (sp = &eflag; sp <= &xflag; sp += 1)
if (*sp)
breakup(*sp);
return;
case '@':
case '*':
flag = (argq == 1 && n == '@') ? 1 : 0;
for (n=0; n<sargc; n++) {
if (n) {
argq ^= flag;
breakup(' ');
argq ^= flag;
}
sp = sargp[n];
while (*sp)
breakup(*sp++);
}
return;
case '0':
sp = sarg0;
break;
default:
if ((n-='1') >= sargc) {
if (uflag)
printe("Unset parameter: %c", n+'1');
return;
}
sp = sargp[n];
break;
}
while (*sp)
breakup(*sp++);
}
/*
* Read and evaluate a command found between graves.
*/
evalcom()
{
int pipev[2], f;
register FILE *fp;
register int c;
register int nnl;
char *cmdp;
cmdp = arcp;
while ((c=*arcp++) != '`');
if ((f = pipeline(pipev)) == 0) {
dup2(pipev[1], 1);
close(pipev[0]);
close(pipev[1]);
*--arcp = '\0';
exit(session(SARGS, cmdp));
NOTREACHED;
}
close(pipev[1]);
if ((fp=fdopen(pipev[0], "r")) == NULL) {
close(pipev[0]);
ecantfdop();
return;
}
argf = 1;
nnl = 0;
while ((c=getc(fp)) != EOF) {
if ( ! recover(IEVAL)) {
#ifdef VERBOSE
if (xflag) prints("Interrupt in eval\n");
#endif
errflag++;
break;
}
if (c=='\n')
++nnl;
else {
while (nnl) {
nnl--;
breakup('\n');
}
breakup(c);
}
}
fclose(fp);
waitc(f);
}
/*
* breakup adds characters to the current argument.
* If no quotation is set, it picks off blanks and globs.
*/
breakup(c)
register int c;
{
if (argq==0) {
if (index(vifs, c) != NULL) {
addlist();
return;
}
if (argg && class(c, MGLOB)) {
dobreakup(c);
return;
}
}
qbreakup(c);
}
/*
* qbreakup adds quoted characters to the current argument.
* if argg is set, then glob characters are quoted with a
* \, as well as \ itself.
*/
qbreakup(c)
register int c;
{
if (argg && (class(c, MGLOB) || c == '\\'))
dobreakup('\\');
dobreakup(c);
}
/*
* dobreakup actually adds characters to the current argument
* and checks for end of buffer.
*/
dobreakup(c)
register int c;
{
if (strp >= &strt[STRSIZE]) /* Should do more */
etoolong();
else
*strp++ = c;
argf = 0;
}
/*
* Addlist terminates the current argument if it is non-empty.
* If argg is set, then we glob the argument to expand globs or
* to simply remove any quotes.
*/
addlist()
{
if (argf != 0)
return;
*strp++ = '\0';
if (argg)
glob1(duplstr(strt, 0));
else {
nargv = addargl(nargv, duplstr(strt, 0));
nargc += 1;
}
strp = strt;
argf = 1;
return;
}
/*
* Evaluate a here document.
* Unevaluated document is on u2, put the evaluated document there, too.
*/
evalhere(u2)
{
register int u1;
register FILE *f2;
char buf[128];
char *tmp;
tmp = shtmp();
if ((u1=creat(tmp, 0666))<0) {
ecantmake(tmp);
return (-1);
}
if ((f2=fdopen(u2, "r"))==NULL) {
ecantfdop();
close(u1);
close(u2);
return (-1);
}
while (fgets(buf, 128, f2) != NULL) {
eval(buf, EHERE);
write(u1, strt, strp-1-strt);
}
close(u1);
fclose(f2);
if ((u2 = open(tmp, 0))<0) {
ecantopen(tmp);
u2 = -1;
}
unlink(tmp);
return (u2);
}