From 0de5aac478f8891929e24f6031ef21da226b92d9 Mon Sep 17 00:00:00 2001 From: jtc Date: Wed, 9 Oct 1996 15:29:01 +0000 Subject: [PATCH] import pdksh 5.2.11 --- bin/ksh/c_sh.c | 6 +- bin/ksh/lex.c | 184 ++++++++++++++++++++++++++++++---------------- bin/ksh/lex.h | 7 +- bin/ksh/syn.c | 14 +++- bin/ksh/version.c | 2 +- 5 files changed, 142 insertions(+), 71 deletions(-) diff --git a/bin/ksh/c_sh.c b/bin/ksh/c_sh.c index e126e4702075..787e3f9a3ac7 100644 --- a/bin/ksh/c_sh.c +++ b/bin/ksh/c_sh.c @@ -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); } diff --git a/bin/ksh/lex.c b/bin/ksh/lex.c index 180c882f6582..0f7df422e560 100644 --- a/bin/ksh/lex.c +++ b/bin/ksh/lex.c @@ -6,20 +6,22 @@ #include 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; } } diff --git a/bin/ksh/lex.h b/bin/ksh/lex.h index cfb34a53d2c8..1e73f6c0f280 100644 --- a/bin/ksh/lex.h +++ b/bin/ksh/lex.h @@ -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 */ diff --git a/bin/ksh/syn.c b/bin/ksh/syn.c index 11de99a2806c..4ee7c41209b3 100644 --- a/bin/ksh/syn.c +++ b/bin/ksh/syn.c @@ -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 diff --git a/bin/ksh/version.c b/bin/ksh/version.c index a22628f77682..1f8b11dd937d 100644 --- a/bin/ksh/version.c +++ b/bin/ksh/version.c @@ -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";