import pdksh 5.2.11
This commit is contained in:
parent
dc22bec48e
commit
0de5aac478
@ -286,9 +286,11 @@ c_read(wp)
|
||||
|
||||
if ((cp = strchr(*wp, '?')) != NULL) {
|
||||
*cp = 0;
|
||||
if (Flag(FTALKING)) {
|
||||
/* at&t says it prints prompt on fd if its open
|
||||
if (isatty(fd)) {
|
||||
/* 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
|
||||
* (it also doesn't check the interactive flag,
|
||||
* as is indicated in the Kornshell book).
|
||||
*/
|
||||
shellf("%s", cp+1);
|
||||
}
|
||||
|
184
bin/ksh/lex.c
184
bin/ksh/lex.c
@ -6,20 +6,22 @@
|
||||
#include <ctype.h>
|
||||
|
||||
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 char *get_brace_var ARGS((XString *wsp, char *wp));
|
||||
static int arraysub ARGS((char **strp));
|
||||
static const char *ungetsc_ ARGS((int c));
|
||||
static int getsc_bn_ ARGS((void));
|
||||
static const char *ungetsc ARGS((int c));
|
||||
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_() */
|
||||
#define getsc() ((*source->str != '\0') ? *source->str++ : getsc_())
|
||||
#define getsc_bn() (*source->str != '\0' && *source->str != '\\' \
|
||||
? *source->str++ : getsc_bn_())
|
||||
#define ungetsc(c) (source->str > source->start ? source->str-- : ungetsc_(c))
|
||||
/* optimized getsc_bn() */
|
||||
#define getsc() (*source->str != '\0' && *source->str != '\\' \
|
||||
&& !backslash_skip ? *source->str++ : getsc_bn())
|
||||
/* optimized getsc__() */
|
||||
#define getsc_() ((*source->str != '\0') ? *source->str++ : getsc__())
|
||||
|
||||
|
||||
/*
|
||||
@ -50,6 +52,9 @@ yylex(cf)
|
||||
Again:
|
||||
Xinit(ws, wp, 64, ATEMP);
|
||||
|
||||
backslash_skip = 0;
|
||||
ignore_backslash_newline = 0;
|
||||
|
||||
if (cf&ONEWORD)
|
||||
istate = SWORD;
|
||||
#ifdef KSH
|
||||
@ -63,9 +68,12 @@ yylex(cf)
|
||||
istate = (cf & HEREDELIM) ? SHEREDELIM : SBASE;
|
||||
while ((c = getsc()) == ' ' || c == '\t')
|
||||
;
|
||||
if (c == '#')
|
||||
if (c == '#') {
|
||||
ignore_backslash_newline++;
|
||||
while ((c = getsc()) != '\0' && c != '\n')
|
||||
;
|
||||
ignore_backslash_newline--;
|
||||
}
|
||||
ungetsc(c);
|
||||
}
|
||||
if (source->flags & SF_ALIAS) { /* trailing ' ' in alias definition */
|
||||
@ -137,23 +145,19 @@ yylex(cf)
|
||||
switch (c) {
|
||||
case '\\':
|
||||
c = getsc();
|
||||
if (c != '\n') {
|
||||
#ifdef OS2
|
||||
if (isalnum(c)) {
|
||||
*wp++ = CHAR, *wp++ = '\\';
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
} else
|
||||
if (isalnum(c)) {
|
||||
*wp++ = CHAR, *wp++ = '\\';
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
} else
|
||||
#endif
|
||||
*wp++ = QCHAR, *wp++ = c;
|
||||
} else
|
||||
if (wp == Xstring(ws, wp)) {
|
||||
Xfree(ws, wp); /* free word */
|
||||
goto Again;
|
||||
}
|
||||
if (c) /* trailing \ is lost */
|
||||
*wp++ = QCHAR, *wp++ = c;
|
||||
break;
|
||||
case '\'':
|
||||
*++statep = state = SSQUOTE;
|
||||
*wp++ = OQUOTE;
|
||||
ignore_backslash_newline++;
|
||||
break;
|
||||
case '"':
|
||||
*++statep = state = SDQUOTE;
|
||||
@ -169,16 +173,16 @@ yylex(cf)
|
||||
case '\\':
|
||||
c = getsc();
|
||||
switch (c) {
|
||||
case '\n':
|
||||
break;
|
||||
case '"': case '\\':
|
||||
case '$': case '`':
|
||||
*wp++ = QCHAR, *wp++ = c;
|
||||
break;
|
||||
default:
|
||||
Xcheck(ws, wp);
|
||||
*wp++ = CHAR, *wp++ = '\\';
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
if (c) { /* trailing \ is lost */
|
||||
*wp++ = CHAR, *wp++ = '\\';
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -205,10 +209,10 @@ yylex(cf)
|
||||
* wrap @(...) around the pattern
|
||||
* (allows easy handling of ${a#b|c})
|
||||
*/
|
||||
c = getsc_bn();
|
||||
c = getsc();
|
||||
if (c == '#' || c == '%') {
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
if ((c2 = getsc_bn()) == c)
|
||||
if ((c2 = getsc()) == c)
|
||||
*wp++ = CHAR, *wp++ = c;
|
||||
else
|
||||
ungetsc(c2);
|
||||
@ -261,6 +265,7 @@ yylex(cf)
|
||||
if (c == '\'') {
|
||||
state = *--statep;
|
||||
*wp++ = CQUOTE;
|
||||
ignore_backslash_newline--;
|
||||
} else
|
||||
*wp++ = QCHAR, *wp++ = c;
|
||||
break;
|
||||
@ -296,6 +301,7 @@ yylex(cf)
|
||||
break;
|
||||
case '\'':
|
||||
csstate = 4;
|
||||
ignore_backslash_newline++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -313,8 +319,10 @@ yylex(cf)
|
||||
break;
|
||||
|
||||
case 4: /* single quotes */
|
||||
if (c == '\'')
|
||||
if (c == '\'') {
|
||||
csstate = 0;
|
||||
ignore_backslash_newline--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (nparen == 0) {
|
||||
@ -388,8 +396,6 @@ yylex(cf)
|
||||
state = *--statep;
|
||||
} else if (c == '\\') {
|
||||
switch (c = getsc()) {
|
||||
case '\n':
|
||||
break;
|
||||
case '\\':
|
||||
case '$': case '`':
|
||||
*wp++ = c;
|
||||
@ -401,8 +407,10 @@ yylex(cf)
|
||||
}
|
||||
/* fall through.. */
|
||||
default:
|
||||
*wp++ = '\\';
|
||||
*wp++ = c;
|
||||
if (c) { /* trailing \ is lost */
|
||||
*wp++ = '\\';
|
||||
*wp++ = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else
|
||||
@ -445,13 +453,14 @@ yylex(cf)
|
||||
*/
|
||||
if (c == '\\') {
|
||||
c = getsc();
|
||||
if (c != '\n') {
|
||||
if (c) { /* trailing \ is lost */
|
||||
*wp++ = QCHAR;
|
||||
*wp++ = c;
|
||||
}
|
||||
} else if (c == '\'') {
|
||||
*++statep = state = SSQUOTE;
|
||||
*wp++ = OQUOTE;
|
||||
ignore_backslash_newline++;
|
||||
} else if (c == '"') {
|
||||
state = SHEREDQUOTE;
|
||||
*wp++ = OQUOTE;
|
||||
@ -466,8 +475,19 @@ yylex(cf)
|
||||
*wp++ = CQUOTE;
|
||||
state = SHEREDELIM;
|
||||
} else {
|
||||
if (c == '\\' && (c = getsc()) == '\n')
|
||||
break;
|
||||
if (c == '\\') {
|
||||
switch (c = getsc()) {
|
||||
case '\\': case '"':
|
||||
case '$': case '`':
|
||||
break;
|
||||
default:
|
||||
if (c) { /* trailing \ lost */
|
||||
*wp++ = CHAR;
|
||||
*wp++ = '\\';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*wp++ = CHAR;
|
||||
*wp++ = c;
|
||||
}
|
||||
@ -538,7 +558,7 @@ Done:
|
||||
iop->flag = c == c2 ?
|
||||
(c == '>' ? IOCAT : IOHERE) : IORDWR;
|
||||
if (iop->flag == IOHERE)
|
||||
if (getsc() == '-')
|
||||
if ((c2 = getsc()) == '-')
|
||||
iop->flag |= IOSKIP;
|
||||
else
|
||||
ungetsc(c2);
|
||||
@ -651,7 +671,7 @@ readhere(iop)
|
||||
register int c;
|
||||
char *volatile eof;
|
||||
char *eofp;
|
||||
int skiptabs, bn;
|
||||
int skiptabs;
|
||||
int i;
|
||||
|
||||
eof = evalstr(iop->delim, 0);
|
||||
@ -678,11 +698,13 @@ readhere(iop)
|
||||
unwind(i);
|
||||
}
|
||||
|
||||
bn = iop->flag & IOEVAL;
|
||||
if (!(iop->flag & IOEVAL))
|
||||
ignore_backslash_newline++;
|
||||
|
||||
for (;;) {
|
||||
eofp = eof;
|
||||
skiptabs = iop->flag & IOSKIP;
|
||||
while ((c = (bn ? getsc_bn() : getsc())) != 0) {
|
||||
while ((c = getsc()) != 0) {
|
||||
if (skiptabs) {
|
||||
if (c == '\t')
|
||||
continue;
|
||||
@ -699,7 +721,7 @@ readhere(iop)
|
||||
break;
|
||||
ungetsc(c);
|
||||
shf_write(eof, eofp - eof, shf);
|
||||
while ((c = (bn ? getsc_bn() : getsc())) != '\n') {
|
||||
while ((c = getsc()) != '\n') {
|
||||
if (c == 0)
|
||||
yyerror("here document `%s' unclosed\n", eof);
|
||||
shf_putc(c, shf);
|
||||
@ -713,6 +735,8 @@ readhere(iop)
|
||||
/*XXX add similar checks for write errors everywhere */
|
||||
quitenv();
|
||||
shf_close(shf);
|
||||
if (!(iop->flag & IOEVAL))
|
||||
ignore_backslash_newline--;
|
||||
}
|
||||
|
||||
void
|
||||
@ -769,7 +793,7 @@ pushs(type, areap)
|
||||
}
|
||||
|
||||
static int
|
||||
getsc_()
|
||||
getsc__()
|
||||
{
|
||||
register Source *s = source;
|
||||
register int c;
|
||||
@ -817,21 +841,40 @@ getsc_()
|
||||
&& isspace(strchr(s->u.tblp->val.s, 0)[-1]))
|
||||
{
|
||||
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;
|
||||
} else {
|
||||
/* put a fake space at the end of the alias.
|
||||
* This keeps the current alias in the source
|
||||
* list so recursive aliases can be detected.
|
||||
* The addition of a space after an alias
|
||||
* never affects anything (I think).
|
||||
/* At this point, we need to keep the current
|
||||
* alias in the source list so recursive
|
||||
* aliases can be detected and we also need
|
||||
* to return the next character. Do this
|
||||
* 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;
|
||||
s->start = s->str = space;
|
||||
source = s->next; /* pop source stack */
|
||||
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;
|
||||
|
||||
case SREREAD:
|
||||
if (s->start != s->u.ugbuf) /* yuck */
|
||||
if (s->start != s->ugbuf) /* yuck */
|
||||
afree(s->u.freeme, ATEMP);
|
||||
source = s = s->next;
|
||||
continue;
|
||||
@ -1086,7 +1129,7 @@ get_brace_var(wsp, wp)
|
||||
|
||||
state = PS_INITIAL;
|
||||
while (1) {
|
||||
c = getsc_bn();
|
||||
c = getsc();
|
||||
/* State machine to figure out where the variable part ends. */
|
||||
switch (state) {
|
||||
case PS_INITIAL:
|
||||
@ -1119,7 +1162,7 @@ get_brace_var(wsp, wp)
|
||||
*wp++ = *p++;
|
||||
}
|
||||
afree(tmp, ATEMP);
|
||||
c = getsc();
|
||||
c = getsc(); /* the ] */
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1161,7 +1204,7 @@ arraysub(strp)
|
||||
Xinit(ws, wp, 32, ATEMP);
|
||||
|
||||
do {
|
||||
c = getsc_bn();
|
||||
c = getsc();
|
||||
Xcheck(ws, wp);
|
||||
*wp++ = c;
|
||||
if (c == '[')
|
||||
@ -1178,9 +1221,11 @@ arraysub(strp)
|
||||
|
||||
/* Unget a char: handles case when we are already at the start of the buffer */
|
||||
static const char *
|
||||
ungetsc_(c)
|
||||
ungetsc(c)
|
||||
int c;
|
||||
{
|
||||
if (backslash_skip)
|
||||
backslash_skip--;
|
||||
/* Don't unget eof... */
|
||||
if (source->str == null && c == '\0')
|
||||
return source->str;
|
||||
@ -1190,29 +1235,40 @@ ungetsc_(c)
|
||||
Source *s;
|
||||
|
||||
s = pushs(SREREAD, source->areap);
|
||||
s->u.ugbuf[0] = c; s->u.ugbuf[1] = '\0';
|
||||
s->start = s->str = s->u.ugbuf;
|
||||
s->ugbuf[0] = c; s->ugbuf[1] = '\0';
|
||||
s->start = s->str = s->ugbuf;
|
||||
s->next = source;
|
||||
source = s;
|
||||
}
|
||||
return source->str;
|
||||
}
|
||||
|
||||
|
||||
/* Called to get a char that isn't a \newline sequence. */
|
||||
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) {
|
||||
c = getsc_();
|
||||
if (c != '\\')
|
||||
return c;
|
||||
c = getsc();
|
||||
if (c != '\n') {
|
||||
ungetsc(c);
|
||||
return '\\';
|
||||
if (c == '\\') {
|
||||
if ((c2 = getsc_()) == '\n')
|
||||
/* ignore the \newline; get the next char... */
|
||||
continue;
|
||||
ungetsc(c2);
|
||||
backslash_skip = 1;
|
||||
}
|
||||
/* ignore the \newline; get the next char... */
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* 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
|
||||
|
||||
@ -12,12 +12,13 @@ struct source {
|
||||
int type; /* input type */
|
||||
char const *start; /* start of current buffer */
|
||||
union {
|
||||
char ugbuf[2]; /* buffer for ungetsc() (SREREAD) */
|
||||
char **strv; /* string [] */
|
||||
struct shf *shf; /* shell file */
|
||||
struct tbl *tblp; /* alias */
|
||||
struct tbl *tblp; /* alias (SALIAS) */
|
||||
char *freeme; /* also for SREREAD */
|
||||
} u;
|
||||
char ugbuf[2]; /* buffer for ungetsc() (SREREAD) and
|
||||
* alias (SALIAS) */
|
||||
int line; /* line number */
|
||||
int errline; /* line the error occured on (0 if not set) */
|
||||
const char *file; /* input file name */
|
||||
|
@ -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_pop ARGS((struct multiline_state *saved));
|
||||
static int assign_command ARGS((char *s));
|
||||
static int inalias ARGS((struct source *s));
|
||||
#ifdef KSH
|
||||
static int dbtestp_isa ARGS((Test_env *te, Test_meta meta));
|
||||
static const char *dbtestp_getopnd ARGS((Test_env *te, Test_op op,
|
||||
@ -121,7 +122,7 @@ c_list()
|
||||
t = andor();
|
||||
if (t != NULL) {
|
||||
while ((c = token(0)) == ';' || c == '&' || c == COPROC ||
|
||||
(c == '\n' && (multiline.on || source->type == SALIAS)))
|
||||
(c == '\n' && (multiline.on || inalias(source))))
|
||||
{
|
||||
if (c == '&' || c == COPROC) {
|
||||
int type = c == '&' ? TASYNC : TCOPROC;
|
||||
@ -810,6 +811,17 @@ assign_command(s)
|
||||
|| (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
|
||||
/* Order important - indexed by Test_meta values
|
||||
|
@ -5,4 +5,4 @@
|
||||
#include "sh.h"
|
||||
|
||||
const char ksh_version [] =
|
||||
"@(#)PD KSH v5.2.9 96/09/30";
|
||||
"@(#)PD KSH v5.2.11 96/10/08";
|
||||
|
Loading…
Reference in New Issue
Block a user