import pdksh 5.2.11

This commit is contained in:
jtc 1996-10-09 15:29:01 +00:00
parent dc22bec48e
commit 0de5aac478
5 changed files with 142 additions and 71 deletions

View File

@ -286,9 +286,11 @@ c_read(wp)
if ((cp = strchr(*wp, '?')) != NULL) { if ((cp = strchr(*wp, '?')) != NULL) {
*cp = 0; *cp = 0;
if (Flag(FTALKING)) { if (isatty(fd)) {
/* at&t says it prints prompt on fd if its open /* at&t ksh says it prints prompt on fd if it's open
* for writing and is a tty, but it doesn't do it * for writing and is a tty, but it doesn't do it
* (it also doesn't check the interactive flag,
* as is indicated in the Kornshell book).
*/ */
shellf("%s", cp+1); shellf("%s", cp+1);
} }

View File

@ -6,20 +6,22 @@
#include <ctype.h> #include <ctype.h>
static void readhere ARGS((struct ioword *iop)); static void readhere ARGS((struct ioword *iop));
static int getsc_ ARGS((void)); static int getsc__ ARGS((void));
static void getsc_line ARGS((Source *s)); static void getsc_line ARGS((Source *s));
static char *get_brace_var ARGS((XString *wsp, char *wp)); static char *get_brace_var ARGS((XString *wsp, char *wp));
static int arraysub ARGS((char **strp)); static int arraysub ARGS((char **strp));
static const char *ungetsc_ ARGS((int c)); static const char *ungetsc ARGS((int c));
static int getsc_bn_ ARGS((void)); static int getsc_bn ARGS((void));
static void gethere ARGS((void));
static void gethere ARGS((void)); static int backslash_skip;
static int ignore_backslash_newline;
/* optimized getsc_() */ /* optimized getsc_bn() */
#define getsc() ((*source->str != '\0') ? *source->str++ : getsc_()) #define getsc() (*source->str != '\0' && *source->str != '\\' \
#define getsc_bn() (*source->str != '\0' && *source->str != '\\' \ && !backslash_skip ? *source->str++ : getsc_bn())
? *source->str++ : getsc_bn_()) /* optimized getsc__() */
#define ungetsc(c) (source->str > source->start ? source->str-- : ungetsc_(c)) #define getsc_() ((*source->str != '\0') ? *source->str++ : getsc__())
/* /*
@ -50,6 +52,9 @@ yylex(cf)
Again: Again:
Xinit(ws, wp, 64, ATEMP); Xinit(ws, wp, 64, ATEMP);
backslash_skip = 0;
ignore_backslash_newline = 0;
if (cf&ONEWORD) if (cf&ONEWORD)
istate = SWORD; istate = SWORD;
#ifdef KSH #ifdef KSH
@ -63,9 +68,12 @@ yylex(cf)
istate = (cf & HEREDELIM) ? SHEREDELIM : SBASE; istate = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
while ((c = getsc()) == ' ' || c == '\t') while ((c = getsc()) == ' ' || c == '\t')
; ;
if (c == '#') if (c == '#') {
ignore_backslash_newline++;
while ((c = getsc()) != '\0' && c != '\n') while ((c = getsc()) != '\0' && c != '\n')
; ;
ignore_backslash_newline--;
}
ungetsc(c); ungetsc(c);
} }
if (source->flags & SF_ALIAS) { /* trailing ' ' in alias definition */ if (source->flags & SF_ALIAS) { /* trailing ' ' in alias definition */
@ -137,23 +145,19 @@ yylex(cf)
switch (c) { switch (c) {
case '\\': case '\\':
c = getsc(); c = getsc();
if (c != '\n') {
#ifdef OS2 #ifdef OS2
if (isalnum(c)) { if (isalnum(c)) {
*wp++ = CHAR, *wp++ = '\\'; *wp++ = CHAR, *wp++ = '\\';
*wp++ = CHAR, *wp++ = c; *wp++ = CHAR, *wp++ = c;
} else } else
#endif #endif
*wp++ = QCHAR, *wp++ = c; if (c) /* trailing \ is lost */
} else *wp++ = QCHAR, *wp++ = c;
if (wp == Xstring(ws, wp)) {
Xfree(ws, wp); /* free word */
goto Again;
}
break; break;
case '\'': case '\'':
*++statep = state = SSQUOTE; *++statep = state = SSQUOTE;
*wp++ = OQUOTE; *wp++ = OQUOTE;
ignore_backslash_newline++;
break; break;
case '"': case '"':
*++statep = state = SDQUOTE; *++statep = state = SDQUOTE;
@ -169,16 +173,16 @@ yylex(cf)
case '\\': case '\\':
c = getsc(); c = getsc();
switch (c) { switch (c) {
case '\n':
break;
case '"': case '\\': case '"': case '\\':
case '$': case '`': case '$': case '`':
*wp++ = QCHAR, *wp++ = c; *wp++ = QCHAR, *wp++ = c;
break; break;
default: default:
Xcheck(ws, wp); Xcheck(ws, wp);
*wp++ = CHAR, *wp++ = '\\'; if (c) { /* trailing \ is lost */
*wp++ = CHAR, *wp++ = c; *wp++ = CHAR, *wp++ = '\\';
*wp++ = CHAR, *wp++ = c;
}
break; break;
} }
break; break;
@ -205,10 +209,10 @@ yylex(cf)
* wrap @(...) around the pattern * wrap @(...) around the pattern
* (allows easy handling of ${a#b|c}) * (allows easy handling of ${a#b|c})
*/ */
c = getsc_bn(); c = getsc();
if (c == '#' || c == '%') { if (c == '#' || c == '%') {
*wp++ = CHAR, *wp++ = c; *wp++ = CHAR, *wp++ = c;
if ((c2 = getsc_bn()) == c) if ((c2 = getsc()) == c)
*wp++ = CHAR, *wp++ = c; *wp++ = CHAR, *wp++ = c;
else else
ungetsc(c2); ungetsc(c2);
@ -261,6 +265,7 @@ yylex(cf)
if (c == '\'') { if (c == '\'') {
state = *--statep; state = *--statep;
*wp++ = CQUOTE; *wp++ = CQUOTE;
ignore_backslash_newline--;
} else } else
*wp++ = QCHAR, *wp++ = c; *wp++ = QCHAR, *wp++ = c;
break; break;
@ -296,6 +301,7 @@ yylex(cf)
break; break;
case '\'': case '\'':
csstate = 4; csstate = 4;
ignore_backslash_newline++;
break; break;
} }
break; break;
@ -313,8 +319,10 @@ yylex(cf)
break; break;
case 4: /* single quotes */ case 4: /* single quotes */
if (c == '\'') if (c == '\'') {
csstate = 0; csstate = 0;
ignore_backslash_newline--;
}
break; break;
} }
if (nparen == 0) { if (nparen == 0) {
@ -388,8 +396,6 @@ yylex(cf)
state = *--statep; state = *--statep;
} else if (c == '\\') { } else if (c == '\\') {
switch (c = getsc()) { switch (c = getsc()) {
case '\n':
break;
case '\\': case '\\':
case '$': case '`': case '$': case '`':
*wp++ = c; *wp++ = c;
@ -401,8 +407,10 @@ yylex(cf)
} }
/* fall through.. */ /* fall through.. */
default: default:
*wp++ = '\\'; if (c) { /* trailing \ is lost */
*wp++ = c; *wp++ = '\\';
*wp++ = c;
}
break; break;
} }
} else } else
@ -445,13 +453,14 @@ yylex(cf)
*/ */
if (c == '\\') { if (c == '\\') {
c = getsc(); c = getsc();
if (c != '\n') { if (c) { /* trailing \ is lost */
*wp++ = QCHAR; *wp++ = QCHAR;
*wp++ = c; *wp++ = c;
} }
} else if (c == '\'') { } else if (c == '\'') {
*++statep = state = SSQUOTE; *++statep = state = SSQUOTE;
*wp++ = OQUOTE; *wp++ = OQUOTE;
ignore_backslash_newline++;
} else if (c == '"') { } else if (c == '"') {
state = SHEREDQUOTE; state = SHEREDQUOTE;
*wp++ = OQUOTE; *wp++ = OQUOTE;
@ -466,8 +475,19 @@ yylex(cf)
*wp++ = CQUOTE; *wp++ = CQUOTE;
state = SHEREDELIM; state = SHEREDELIM;
} else { } else {
if (c == '\\' && (c = getsc()) == '\n') if (c == '\\') {
break; switch (c = getsc()) {
case '\\': case '"':
case '$': case '`':
break;
default:
if (c) { /* trailing \ lost */
*wp++ = CHAR;
*wp++ = '\\';
}
break;
}
}
*wp++ = CHAR; *wp++ = CHAR;
*wp++ = c; *wp++ = c;
} }
@ -538,7 +558,7 @@ Done:
iop->flag = c == c2 ? iop->flag = c == c2 ?
(c == '>' ? IOCAT : IOHERE) : IORDWR; (c == '>' ? IOCAT : IOHERE) : IORDWR;
if (iop->flag == IOHERE) if (iop->flag == IOHERE)
if (getsc() == '-') if ((c2 = getsc()) == '-')
iop->flag |= IOSKIP; iop->flag |= IOSKIP;
else else
ungetsc(c2); ungetsc(c2);
@ -651,7 +671,7 @@ readhere(iop)
register int c; register int c;
char *volatile eof; char *volatile eof;
char *eofp; char *eofp;
int skiptabs, bn; int skiptabs;
int i; int i;
eof = evalstr(iop->delim, 0); eof = evalstr(iop->delim, 0);
@ -678,11 +698,13 @@ readhere(iop)
unwind(i); unwind(i);
} }
bn = iop->flag & IOEVAL; if (!(iop->flag & IOEVAL))
ignore_backslash_newline++;
for (;;) { for (;;) {
eofp = eof; eofp = eof;
skiptabs = iop->flag & IOSKIP; skiptabs = iop->flag & IOSKIP;
while ((c = (bn ? getsc_bn() : getsc())) != 0) { while ((c = getsc()) != 0) {
if (skiptabs) { if (skiptabs) {
if (c == '\t') if (c == '\t')
continue; continue;
@ -699,7 +721,7 @@ readhere(iop)
break; break;
ungetsc(c); ungetsc(c);
shf_write(eof, eofp - eof, shf); shf_write(eof, eofp - eof, shf);
while ((c = (bn ? getsc_bn() : getsc())) != '\n') { while ((c = getsc()) != '\n') {
if (c == 0) if (c == 0)
yyerror("here document `%s' unclosed\n", eof); yyerror("here document `%s' unclosed\n", eof);
shf_putc(c, shf); shf_putc(c, shf);
@ -713,6 +735,8 @@ readhere(iop)
/*XXX add similar checks for write errors everywhere */ /*XXX add similar checks for write errors everywhere */
quitenv(); quitenv();
shf_close(shf); shf_close(shf);
if (!(iop->flag & IOEVAL))
ignore_backslash_newline--;
} }
void void
@ -769,7 +793,7 @@ pushs(type, areap)
} }
static int static int
getsc_() getsc__()
{ {
register Source *s = source; register Source *s = source;
register int c; register int c;
@ -817,21 +841,40 @@ getsc_()
&& isspace(strchr(s->u.tblp->val.s, 0)[-1])) && isspace(strchr(s->u.tblp->val.s, 0)[-1]))
{ {
source = s = s->next; /* pop source stack */ source = s = s->next; /* pop source stack */
/* Note that this alias ended with a space,
* enabling alias expansion on the following
* word.
*/
s->flags |= SF_ALIAS; s->flags |= SF_ALIAS;
} else { } else {
/* put a fake space at the end of the alias. /* At this point, we need to keep the current
* This keeps the current alias in the source * alias in the source list so recursive
* list so recursive aliases can be detected. * aliases can be detected and we also need
* The addition of a space after an alias * to return the next character. Do this
* never affects anything (I think). * by temporarily popping the alias to get
* the next character and then put it back
* in the source list with the SF_ALIASEND
* flag set.
*/ */
s->flags |= SF_ALIASEND; source = s->next; /* pop source stack */
s->start = s->str = space; source->flags |= s->flags & SF_ALIAS;
c = getsc__();
if (c) {
s->flags |= SF_ALIASEND;
s->ugbuf[0] = c; s->ugbuf[1] = '\0';
s->start = s->str = s->ugbuf;
s->next = source;
source = s;
} else {
s = source;
/* avoid reading eof twice */
s->str = NULL;
}
} }
continue; continue;
case SREREAD: case SREREAD:
if (s->start != s->u.ugbuf) /* yuck */ if (s->start != s->ugbuf) /* yuck */
afree(s->u.freeme, ATEMP); afree(s->u.freeme, ATEMP);
source = s = s->next; source = s = s->next;
continue; continue;
@ -1086,7 +1129,7 @@ get_brace_var(wsp, wp)
state = PS_INITIAL; state = PS_INITIAL;
while (1) { while (1) {
c = getsc_bn(); c = getsc();
/* State machine to figure out where the variable part ends. */ /* State machine to figure out where the variable part ends. */
switch (state) { switch (state) {
case PS_INITIAL: case PS_INITIAL:
@ -1119,7 +1162,7 @@ get_brace_var(wsp, wp)
*wp++ = *p++; *wp++ = *p++;
} }
afree(tmp, ATEMP); afree(tmp, ATEMP);
c = getsc(); c = getsc(); /* the ] */
} }
} }
break; break;
@ -1161,7 +1204,7 @@ arraysub(strp)
Xinit(ws, wp, 32, ATEMP); Xinit(ws, wp, 32, ATEMP);
do { do {
c = getsc_bn(); c = getsc();
Xcheck(ws, wp); Xcheck(ws, wp);
*wp++ = c; *wp++ = c;
if (c == '[') if (c == '[')
@ -1178,9 +1221,11 @@ arraysub(strp)
/* Unget a char: handles case when we are already at the start of the buffer */ /* Unget a char: handles case when we are already at the start of the buffer */
static const char * static const char *
ungetsc_(c) ungetsc(c)
int c; int c;
{ {
if (backslash_skip)
backslash_skip--;
/* Don't unget eof... */ /* Don't unget eof... */
if (source->str == null && c == '\0') if (source->str == null && c == '\0')
return source->str; return source->str;
@ -1190,29 +1235,40 @@ ungetsc_(c)
Source *s; Source *s;
s = pushs(SREREAD, source->areap); s = pushs(SREREAD, source->areap);
s->u.ugbuf[0] = c; s->u.ugbuf[1] = '\0'; s->ugbuf[0] = c; s->ugbuf[1] = '\0';
s->start = s->str = s->u.ugbuf; s->start = s->str = s->ugbuf;
s->next = source; s->next = source;
source = s; source = s;
} }
return source->str; return source->str;
} }
/* Called to get a char that isn't a \newline sequence. */ /* Called to get a char that isn't a \newline sequence. */
static int static int
getsc_bn_ ARGS((void)) getsc_bn ARGS((void))
{ {
int c; int c, c2;
if (ignore_backslash_newline)
return getsc_();
if (backslash_skip == 1) {
backslash_skip = 2;
return getsc_();
}
backslash_skip = 0;
while (1) { while (1) {
c = getsc_(); c = getsc_();
if (c != '\\') if (c == '\\') {
return c; if ((c2 = getsc_()) == '\n')
c = getsc(); /* ignore the \newline; get the next char... */
if (c != '\n') { continue;
ungetsc(c); ungetsc(c2);
return '\\'; backslash_skip = 1;
} }
/* ignore the \newline; get the next char... */ return c;
} }
} }

View File

@ -2,7 +2,7 @@
* Source input, lexer and parser * Source input, lexer and parser
*/ */
/* $Id: lex.h,v 1.1.1.2 1996/10/09 15:12:48 jtc Exp $ */ /* $Id: lex.h,v 1.1.1.3 1996/10/09 15:29:20 jtc Exp $ */
#define IDENT 64 #define IDENT 64
@ -12,12 +12,13 @@ struct source {
int type; /* input type */ int type; /* input type */
char const *start; /* start of current buffer */ char const *start; /* start of current buffer */
union { union {
char ugbuf[2]; /* buffer for ungetsc() (SREREAD) */
char **strv; /* string [] */ char **strv; /* string [] */
struct shf *shf; /* shell file */ struct shf *shf; /* shell file */
struct tbl *tblp; /* alias */ struct tbl *tblp; /* alias (SALIAS) */
char *freeme; /* also for SREREAD */ char *freeme; /* also for SREREAD */
} u; } u;
char ugbuf[2]; /* buffer for ungetsc() (SREREAD) and
* alias (SALIAS) */
int line; /* line number */ int line; /* line number */
int errline; /* line the error occured on (0 if not set) */ int errline; /* line the error occured on (0 if not set) */
const char *file; /* input file name */ const char *file; /* input file name */

View File

@ -34,6 +34,7 @@ static void syntaxerr ARGS((const char *what))
static void multiline_push ARGS((struct multiline_state *save, int tok)); static void multiline_push ARGS((struct multiline_state *save, int tok));
static void multiline_pop ARGS((struct multiline_state *saved)); static void multiline_pop ARGS((struct multiline_state *saved));
static int assign_command ARGS((char *s)); static int assign_command ARGS((char *s));
static int inalias ARGS((struct source *s));
#ifdef KSH #ifdef KSH
static int dbtestp_isa ARGS((Test_env *te, Test_meta meta)); static int dbtestp_isa ARGS((Test_env *te, Test_meta meta));
static const char *dbtestp_getopnd ARGS((Test_env *te, Test_op op, static const char *dbtestp_getopnd ARGS((Test_env *te, Test_op op,
@ -121,7 +122,7 @@ c_list()
t = andor(); t = andor();
if (t != NULL) { if (t != NULL) {
while ((c = token(0)) == ';' || c == '&' || c == COPROC || while ((c = token(0)) == ';' || c == '&' || c == COPROC ||
(c == '\n' && (multiline.on || source->type == SALIAS))) (c == '\n' && (multiline.on || inalias(source))))
{ {
if (c == '&' || c == COPROC) { if (c == '&' || c == COPROC) {
int type = c == '&' ? TASYNC : TCOPROC; int type = c == '&' ? TASYNC : TCOPROC;
@ -810,6 +811,17 @@ assign_command(s)
|| (c == 't' && strcmp(s, "typeset") == 0); || (c == 't' && strcmp(s, "typeset") == 0);
} }
/* Check if we are in the middle of reading an alias */
static int
inalias(s)
struct source *s;
{
for (; s && s->type == SALIAS; s = s->next)
if (!(s->flags & SF_ALIASEND))
return 1;
return 0;
}
#ifdef KSH #ifdef KSH
/* Order important - indexed by Test_meta values /* Order important - indexed by Test_meta values

View File

@ -5,4 +5,4 @@
#include "sh.h" #include "sh.h"
const char ksh_version [] = const char ksh_version [] =
"@(#)PD KSH v5.2.9 96/09/30"; "@(#)PD KSH v5.2.11 96/10/08";