fixed bug in realloc: copy the min size of the new and old block.
[unix-history] / usr / src / bin / csh / lex.c
index 2620409..dcafbe0 100644 (file)
@@ -6,11 +6,24 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)lex.c      5.12 (Berkeley) %G%";
-
-#endif                         /* not lint */
+static char sccsid[] = "@(#)lex.c      5.26 (Berkeley) %G%";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#if __STDC__
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
 
 
-#include "sh.h"
+#include "csh.h"
+#include "extern.h"
 
 /*
  * These lexical routines read input and form lists of words.
 
 /*
  * These lexical routines read input and form lists of words.
@@ -18,20 +31,24 @@ static char sccsid[] = "@(#)lex.c   5.12 (Berkeley) %G%";
  * of input buffering, and especially because of history substitution.
  */
 
  * of input buffering, and especially because of history substitution.
  */
 
-static Char *word();
-static int getC1();
-static void getdol();
-static void getexcl();
-static struct Hist *findev();
-static void setexclp();
-static int bgetc();
-static void bfree();
-static struct wordent *gethent();
-static int matchs();
-static int getsel();
-static struct wordent *getsub();
-static Char *subword();
-static struct wordent *dosub();
+static Char    *word __P((void));
+static int      getC1 __P((int));
+static void     getdol __P((void));
+static void     getexcl __P((int));
+static struct Hist
+               *findev __P((Char *, bool));
+static void     setexclp __P((Char *));
+static int      bgetc __P((void));
+static void     bfree __P((void));
+static struct wordent
+               *gethent __P((int));
+static int      matchs __P((Char *, Char *));
+static int      getsel __P((int *, int *, int));
+static struct wordent
+               *getsub __P((struct wordent *));
+static Char    *subword __P((Char *, int, bool *));
+static struct wordent
+               *dosub __P((int, struct wordent *, bool));
 
 /*
  * Peekc is a peek character for getC, peekread for readc.
 
 /*
  * Peekc is a peek character for getC, peekread for readc.
@@ -54,16 +71,17 @@ static Char peekc = 0, peekd = 0;
 static Char peekread = 0;
 
 /* (Tail of) current word from ! subst */
 static Char peekread = 0;
 
 /* (Tail of) current word from ! subst */
-static Char *exclp = (Char *) 0;
+static Char *exclp = NULL;
 
 /* The rest of the ! subst words */
 
 /* The rest of the ! subst words */
-static struct wordent *exclnxt = (struct wordent *) 0;
+static struct wordent *exclnxt = NULL;
 
 /* Count of remaining words in ! subst */
 static int exclc = 0;
 
 /* "Globp" for alias resubstitution */
 
 /* Count of remaining words in ! subst */
 static int exclc = 0;
 
 /* "Globp" for alias resubstitution */
-static Char *alvecp = (Char *) 0;
+Char *alvecp = NULL;
+int aret = F_SEEK;
 
 /*
  * Labuf implements a general buffer for lookahead during lexical operations.
 
 /*
  * Labuf implements a general buffer for lookahead during lexical operations.
@@ -101,10 +119,10 @@ lex(hp)
     register struct wordent *wdp;
     int     c;
 
     register struct wordent *wdp;
     int     c;
 
-    lineloc = btell();
+    btell(&lineloc);
     hp->next = hp->prev = hp;
     hp->word = STRNULL;
     hp->next = hp->prev = hp;
     hp->word = STRNULL;
-    alvecp = 0, hadhist = 0;
+    hadhist = 0;
     do
        c = readc(0);
     while (c == ' ' || c == '\t');
     do
        c = readc(0);
     while (c == ' ' || c == '\t');
@@ -134,18 +152,19 @@ lex(hp)
 }
 
 void
 }
 
 void
-prlex(sp0)
+prlex(fp, sp0)
+    FILE *fp;
     struct wordent *sp0;
 {
     register struct wordent *sp = sp0->next;
 
     for (;;) {
     struct wordent *sp0;
 {
     register struct wordent *sp = sp0->next;
 
     for (;;) {
-       xprintf("%s", short2str(sp->word));
+       (void) fprintf(fp, "%s", vis_str(sp->word));
        sp = sp->next;
        if (sp == sp0)
            break;
        if (sp->word[0] != '\n')
        sp = sp->next;
        if (sp == sp0)
            break;
        if (sp->word[0] != '\n')
-           xputchar(' ');
+           (void) fputc(' ', fp);
     }
 }
 
     }
 }
 
@@ -199,7 +218,8 @@ word()
     wp = wbuf;
     i = BUFSIZ - 4;
 loop:
     wp = wbuf;
     i = BUFSIZ - 4;
 loop:
-    while ((c = getC(DOALL)) == ' ' || c == '\t');
+    while ((c = getC(DOALL)) == ' ' || c == '\t')
+       continue;
     if (cmap(c, _META | _ESC))
        switch (c) {
        case '&':
     if (cmap(c, _META | _ESC))
        switch (c) {
        case '&':
@@ -390,6 +410,7 @@ getdol()
 
     case '<':
     case '$':
 
     case '<':
     case '$':
+    case '!':
        if (special)
            seterror(ERR_SPDOLLT);
        *np = 0;
        if (special)
            seterror(ERR_SPDOLLT);
        *np = 0;
@@ -502,20 +523,58 @@ getdol()
         * -strike
         */
 
         * -strike
         */
 
-       int     gmodflag = 0;
+       int     gmodflag = 0, amodflag = 0;
 
 
-       *np++ = c, c = getC(DOEXCL);
-       if (c == 'g')
-           gmodflag++, *np++ = c, c = getC(DOEXCL);
-       *np++ = c;
-       if (!any("htrqxe", c)) {
-           if (gmodflag && c == '\n')
-               stderror(ERR_VARSYN);   /* strike */
-           seterror(ERR_VARMOD, c);
-           *np = 0;
-           addla(name);
-           return;
+       do {
+           *np++ = c, c = getC(DOEXCL);
+           if (c == 'g' || c == 'a') {
+               if (c == 'g')
+                   gmodflag++;
+               else
+                   amodflag++;
+               *np++ = c; c = getC(DOEXCL);
+           }
+           if ((c == 'g' && !gmodflag) || (c == 'a' && !amodflag)) {
+               if (c == 'g')
+                   gmodflag++;
+               else
+                   amodflag++;
+               *np++ = c; c = getC(DOEXCL);
+           }
+           *np++ = c;
+           /* scan s// [eichin:19910926.0512EST] */
+           if (c == 's') {
+               int delimcnt = 2;
+               int delim = getC(0);
+               *np++ = delim;
+               
+               if (!delim || letter(delim)
+                   || Isdigit(delim) || any(" \t\n", delim)) {
+                   seterror(ERR_BADSUBST);
+                   break;
+               }       
+               while ((c = getC(0)) != (-1)) {
+                   *np++ = c;
+                   if(c == delim) delimcnt--;
+                   if(!delimcnt) break;
+               }
+               if(delimcnt) {
+                   seterror(ERR_BADSUBST);
+                   break;
+               }
+               c = 's';
+           }
+           if (!any("htrqxes", c)) {
+               if ((amodflag || gmodflag) && c == '\n')
+                   stderror(ERR_VARSYN);       /* strike */
+               seterror(ERR_VARMOD, c);
+               *np = 0;
+               addla(name);
+               return;
+           }
        }
        }
+       while ((c = getC(DOEXCL)) == ':');
+       ungetD(c);
     }
     else
        ungetD(c);
     }
     else
        ungetD(c);
@@ -561,7 +620,7 @@ static int quesarg;
 
 static void
 getexcl(sc)
 
 static void
 getexcl(sc)
-    Char    sc;
+    int    sc;
 {
     register struct wordent *hp, *ip;
     int     left, right, dol;
 {
     register struct wordent *hp, *ip;
     int     left, right, dol;
@@ -644,123 +703,135 @@ getsub(en)
     int     delim;
     register int c;
     int     sc;
     int     delim;
     register int c;
     int     sc;
-    bool global = 0;
+    bool global;
     Char    orhsb[sizeof(rhsb) / sizeof(Char)];
 
     Char    orhsb[sizeof(rhsb) / sizeof(Char)];
 
-    exclnxt = 0;
-    sc = c = getC(0);
-    if (c == 'g')
-       global ++, sc = c = getC(0);
+    do {
+       exclnxt = 0;
+       global = 0;
+       sc = c = getC(0);
+       if (c == 'g' || c == 'a') {
+           global |= (c == 'g') ? 1 : 2;
+           sc = c = getC(0);
+       }
+       if (((c =='g') && !(global & 1)) || ((c == 'a') && !(global & 2))) {
+           global |= (c == 'g') ? 1 : 2;
+           sc = c = getC(0);
+       }
 
 
-    switch (c) {
-    case 'p':
-       justpr++;
-       return (en);
+       switch (c) {
+       case 'p':
+           justpr++;
+           return (en);
 
 
-    case 'x':
-    case 'q':
-       global ++;
+       case 'x':
+       case 'q':
+           global |= 1;
 
 
-       /* fall into ... */
+           /* fall into ... */
 
 
-    case 'h':
-    case 'r':
-    case 't':
-    case 'e':
-       break;
+       case 'h':
+       case 'r':
+       case 't':
+       case 'e':
+           break;
 
 
-    case '&':
-       if (slhs[0] == 0) {
-           seterror(ERR_NOSUBST);
-           return (en);
-       }
-       (void) Strcpy(lhsb, slhs);
-       break;
+       case '&':
+           if (slhs[0] == 0) {
+               seterror(ERR_NOSUBST);
+               return (en);
+           }
+           (void) Strcpy(lhsb, slhs);
+           break;
 
 #ifdef notdef
 
 #ifdef notdef
-    case '~':
-       if (lhsb[0] == 0)
-           goto badlhs;
-       break;
+       case '~':
+           if (lhsb[0] == 0)
+               goto badlhs;
+           break;
 #endif
 
 #endif
 
-    case 's':
-       delim = getC(0);
-       if (letter(delim) || Isdigit(delim) || any(" \t\n", delim)) {
-           unreadc(delim);
-           lhsb[0] = 0;
-           seterror(ERR_BADSUBST);
-           return (en);
-       }
-       cp = lhsb;
-       for (;;) {
-           c = getC(0);
-           if (c == '\n') {
-               unreadc(c);
-               break;
-           }
-           if (c == delim)
-               break;
-           if (cp > &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) {
+       case 's':
+           delim = getC(0);
+           if (letter(delim) || Isdigit(delim) || any(" \t\n", delim)) {
+               unreadc(delim);
                lhsb[0] = 0;
                seterror(ERR_BADSUBST);
                return (en);
            }
                lhsb[0] = 0;
                seterror(ERR_BADSUBST);
                return (en);
            }
-           if (c == '\\') {
+           cp = lhsb;
+           for (;;) {
                c = getC(0);
                c = getC(0);
-               if (c != delim && c != '\\')
-                   *cp++ = '\\';
-           }
-           *cp++ = c;
-       }
-       if (cp != lhsb)
-           *cp++ = 0;
-       else if (lhsb[0] == 0) {
-           seterror(ERR_LHS);
-           return (en);
-       }
-       cp = rhsb;
-       (void) Strcpy(orhsb, cp);
-       for (;;) {
-           c = getC(0);
-           if (c == '\n') {
-               unreadc(c);
-               break;
-           }
-           if (c == delim)
-               break;
-#ifdef notdef
-           if (c == '~') {
-               if (&cp[Strlen(orhsb)] > &rhsb[sizeof(rhsb) / sizeof(Char) - 2])
-                   goto toorhs;
-               (void) Strcpy(cp, orhsb);
-               cp = Strend(cp);
-               continue;
+               if (c == '\n') {
+                   unreadc(c);
+                   break;
+               }
+               if (c == delim)
+                   break;
+               if (cp > &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) {
+                   lhsb[0] = 0;
+                   seterror(ERR_BADSUBST);
+                   return (en);
+               }
+               if (c == '\\') {
+                   c = getC(0);
+                   if (c != delim && c != '\\')
+                       *cp++ = '\\';
+               }
+               *cp++ = c;
            }
            }
-#endif
-           if (cp > &rhsb[sizeof(rhsb) / sizeof(Char) - 2]) {
-               seterror(ERR_RHSLONG);
+           if (cp != lhsb)
+               *cp++ = 0;
+           else if (lhsb[0] == 0) {
+               seterror(ERR_LHS);
                return (en);
            }
                return (en);
            }
-           if (c == '\\') {
+           cp = rhsb;
+           (void) Strcpy(orhsb, cp);
+           for (;;) {
                c = getC(0);
                c = getC(0);
-               if (c != delim /* && c != '~' */ )
-                   *cp++ = '\\';
+               if (c == '\n') {
+                   unreadc(c);
+                   break;
+               }
+               if (c == delim)
+                   break;
+#ifdef notdef
+               if (c == '~') {
+                   if (&cp[Strlen(orhsb)] > &rhsb[sizeof(rhsb) /
+                                                  sizeof(Char) - 2])
+                       goto toorhs;
+                   (void) Strcpy(cp, orhsb);
+                   cp = Strend(cp);
+                   continue;
+               }
+#endif
+               if (cp > &rhsb[sizeof(rhsb) / sizeof(Char) - 2]) {
+                   seterror(ERR_RHSLONG);
+                   return (en);
+               }
+               if (c == '\\') {
+                   c = getC(0);
+                   if (c != delim /* && c != '~' */ )
+                       *cp++ = '\\';
+               }
+               *cp++ = c;
            }
            }
-           *cp++ = c;
-       }
-       *cp++ = 0;
-       break;
+           *cp++ = 0;
+           break;
 
 
-    default:
-       if (c == '\n')
-           unreadc(c);
-       seterror(ERR_BADBANGMOD, c);
-       return (en);
+       default:
+           if (c == '\n')
+               unreadc(c);
+           seterror(ERR_BADBANGMOD, c);
+           return (en);
+       }
+       (void) Strcpy(slhs, lhsb);
+       if (exclc)
+           en = dosub(sc, en, global);
     }
     }
-    (void) Strcpy(slhs, lhsb);
-    if (exclc)
-       en = dosub(sc, en, global);
+    while ((c = getC(0)) == ':');
+    unreadc(c);
     return (en);
 }
 
     return (en);
 }
 
@@ -771,24 +842,46 @@ dosub(sc, en, global)
     bool global;
 {
     struct wordent lexi;
     bool global;
 {
     struct wordent lexi;
-    bool    didsub = 0;
+    bool    didsub = 0, didone = 0;
     struct wordent *hp = &lexi;
     register struct wordent *wdp;
     register int i = exclc;
 
     wdp = hp;
     while (--i >= 0) {
     struct wordent *hp = &lexi;
     register struct wordent *wdp;
     register int i = exclc;
 
     wdp = hp;
     while (--i >= 0) {
-       register struct wordent *new;
+       register struct wordent *new = 
+               (struct wordent *) xcalloc(1, sizeof *wdp);
 
 
-       new = (struct wordent *) xcalloc(1, sizeof *wdp);
        new->word = 0;
        new->prev = wdp;
        new->next = hp;
        wdp->next = new;
        wdp = new;
        en = en->next;
        new->word = 0;
        new->prev = wdp;
        new->next = hp;
        wdp->next = new;
        wdp = new;
        en = en->next;
-       wdp->word = (en->word && (global ||didsub == 0)) ?
-           subword(en->word, sc, &didsub) : Strsave(en->word);
+       if (en->word) {
+           Char *tword, *otword;
+
+           if ((global & 1) || didsub == 0) {
+               tword = subword(en->word, sc, &didone);
+               if (didone)
+                   didsub = 1;
+               if (global & 2) {
+                   while (didone && tword != STRNULL) {
+                       otword = tword;
+                       tword = subword(otword, sc, &didone);
+                       if (Strcmp(tword, otword) == 0) {
+                           xfree((ptr_t) otword);
+                           break;
+                       }
+                       else
+                           xfree((ptr_t) otword);
+                   }
+               }
+           }
+           else
+               tword = Strsave(en->word);
+           wdp->word = tword;
+       }
     }
     if (didsub == 0)
        seterror(ERR_MODFAIL);
     }
     if (didsub == 0)
        seterror(ERR_MODFAIL);
@@ -806,6 +899,7 @@ subword(cp, type, adid)
     register Char *wp, *mp, *np;
     register int i;
 
     register Char *wp, *mp, *np;
     register int i;
 
+    *adid = 0;
     switch (type) {
 
     case 'r':
     switch (type) {
 
     case 'r':
@@ -912,6 +1006,8 @@ domod(cp, type)
                return (xp);
            }
        return (Strsave(type == 'e' ? STRNULL : cp));
                return (xp);
            }
        return (Strsave(type == 'e' ? STRNULL : cp));
+    default:
+       break;
     }
     return (0);
 }
     }
     return (0);
 }
@@ -1063,7 +1159,7 @@ gethent(sc)
            }
            np = lhsb;
            event = 0;
            }
            np = lhsb;
            event = 0;
-           while (!any(": \t\\\n}", c)) {
+           while (!cmap(c, _ESC | _META | _Q | _Q1) && !any("${}:", c)) {
                if (event != -1 && Isdigit(c))
                    event = event * 10 + c - '0';
                else
                if (event != -1 && Isdigit(c))
                    event = event * 10 + c - '0';
                else
@@ -1125,7 +1221,7 @@ gethent(sc)
            return (&hp->Hlex);
        }
     np = putn(event);
            return (&hp->Hlex);
        }
     np = putn(event);
-    seterror(ERR_NOEVENT, short2str(np));
+    seterror(ERR_NOEVENT, vis_str(np));
     return (0);
 }
 
     return (0);
 }
 
@@ -1176,7 +1272,7 @@ findev(cp, anyarg)
            argno++;
        } while (lp->word[0] != '\n');
     }
            argno++;
        } while (lp->word[0] != '\n');
     }
-    seterror(ERR_NOEVENT, short2str(cp));
+    seterror(ERR_NOEVENT, vis_str(cp));
     return (0);
 }
 
     return (0);
 }
 
@@ -1192,7 +1288,7 @@ setexclp(cp)
 
 void
 unreadc(c)
 
 void
 unreadc(c)
-    Char    c;
+    int    c;
 {
     peekread = c;
 }
 {
     peekread = c;
 }
@@ -1204,17 +1300,25 @@ readc(wanteof)
     register int c;
     static  sincereal;
 
     register int c;
     static  sincereal;
 
+    aret = F_SEEK;
     if (c = peekread) {
        peekread = 0;
        return (c);
     }
 top:
     if (c = peekread) {
        peekread = 0;
        return (c);
     }
 top:
+    aret = F_SEEK;
     if (alvecp) {
     if (alvecp) {
+       aret = A_SEEK;
        if (c = *alvecp++)
            return (c);
        if (c = *alvecp++)
            return (c);
-       if (*alvec) {
-           alvecp = *alvec++;
-           return (' ');
+       if (alvec && *alvec) {
+               alvecp = *alvec++;
+               return (' ');
+       }
+       else {
+           aret = F_SEEK;
+           alvecp = NULL;
+           return('\n');
        }
     }
     if (alvec) {
        }
     }
     if (alvec) {
@@ -1226,12 +1330,14 @@ top:
        return ('\n');
     }
     if (evalp) {
        return ('\n');
     }
     if (evalp) {
+       aret = E_SEEK;
        if (c = *evalp++)
            return (c);
        if (c = *evalp++)
            return (c);
-       if (*evalvec) {
+       if (evalvec && *evalvec) {
            evalp = *evalvec++;
            return (' ');
        }
            evalp = *evalvec++;
            return (' ');
        }
+       aret = F_SEEK;
        evalp = 0;
     }
     if (evalvec) {
        evalp = 0;
     }
     if (evalvec) {
@@ -1262,20 +1368,11 @@ top:
 reread:
        c = bgetc();
        if (c < 0) {
 reread:
        c = bgetc();
        if (c < 0) {
-#ifdef TERMIOS
            struct termios tty;
            struct termios tty;
-#else
-           struct sgttyb tty;
-#endif
            if (wanteof)
                return (-1);
            /* was isatty but raw with ignoreeof yields problems */
            if (wanteof)
                return (-1);
            /* was isatty but raw with ignoreeof yields problems */
-#ifdef TERMIOS
            if (tcgetattr(SHIN, &tty) == 0 && (tty.c_lflag & ICANON))
            if (tcgetattr(SHIN, &tty) == 0 && (tty.c_lflag & ICANON))
-#else
-           if (ioctl(SHIN, TIOCGETP, (ioctl_t) & tty) == 0 &&
-               (tty.sg_flags & RAW) == 0)
-#endif
            {
                /* was 'short' for FILEC */
                int     ctpgrp;
            {
                /* was 'short' for FILEC */
                int     ctpgrp;
@@ -1287,14 +1384,15 @@ reread:
                    tpgrp != ctpgrp) {
                    (void) tcsetpgrp(FSHTTY, tpgrp);
                    (void) killpg((pid_t) ctpgrp, SIGHUP);
                    tpgrp != ctpgrp) {
                    (void) tcsetpgrp(FSHTTY, tpgrp);
                    (void) killpg((pid_t) ctpgrp, SIGHUP);
-                   xprintf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp);
+                   (void) fprintf(csherr, "Reset tty pgrp from %d to %d\n",
+                                  ctpgrp, tpgrp);
                    goto reread;
                }
                if (adrof(STRignoreeof)) {
                    if (loginsh)
                    goto reread;
                }
                if (adrof(STRignoreeof)) {
                    if (loginsh)
-                       xprintf("\nUse \"logout\" to logout.\n");
+                       (void) fprintf(csherr,"\nUse \"logout\" to logout.\n");
                    else
                    else
-                       xprintf("\nUse \"exit\" to leave csh.\n");
+                       (void) fprintf(csherr,"\nUse \"exit\" to leave csh.\n");
                    reset();
                }
                if (chkstop == 0)
                    reset();
                }
                if (chkstop == 0)
@@ -1442,46 +1540,59 @@ bfree()
 
 void
 bseek(l)
 
 void
 bseek(l)
-    off_t   l;
-
+    struct Ain   *l;
 {
 {
-
-    fseekp = l;
-    if (!cantell) {
-#ifdef notdef
-       register struct whyle *wp;
-#endif
-
-       if (!whyles)
-           return;
-#ifdef notdef
-       /*
-        * Christos: I don't understand this? both wp and l are local. What is
-        * this used for? I suspect the author meant fseek = wp->w_start
-        * This seek/tell stuff needs to be re-written...
-        */
-       for (wp = whyles; wp->w_next; wp = wp->w_next)
-           continue;
-       if (wp->w_start > l)
-           l = wp->w_start;
-#endif
+    switch (aret = l->type) {
+    case E_SEEK:
+       evalvec = l->a_seek;
+       evalp = (Char *) l->f_seek;
+       return;
+    case A_SEEK:
+       alvec = l->a_seek;
+       alvecp = (Char *) l->f_seek;
+       return;
+    case F_SEEK:
+       fseekp = l->f_seek;
+       return;
+    default:
+       (void) fprintf(csherr, "Bad seek type %d\n", aret);
+       abort();
     }
 }
 
     }
 }
 
-/* any similarity to bell telephone is purely accidental */
-#ifndef btell
-off_t
-btell()
+void
+btell(l)
+    struct Ain *l;
 {
 {
-    return (fseekp);
+    switch (l->type = aret) {
+    case E_SEEK:
+       l->a_seek = evalvec;
+       l->f_seek = (off_t) evalp;
+       return;
+    case A_SEEK:
+       l->a_seek = alvec;
+       l->f_seek = (off_t) alvecp;
+       return;
+    case F_SEEK:
+       l->f_seek = fseekp;
+       l->a_seek = NULL;
+       return;
+    default:
+       (void) fprintf(csherr, "Bad seek type %d\n", aret);
+       abort();
+    }
 }
 }
-#endif
 
 void
 btoeof()
 {
     (void) lseek(SHIN, (off_t) 0, L_XTND);
 
 void
 btoeof()
 {
     (void) lseek(SHIN, (off_t) 0, L_XTND);
+    aret = F_SEEK;
     fseekp = feobp;
     fseekp = feobp;
+    alvec = NULL;
+    alvecp = NULL;
+    evalvec = NULL;
+    evalp = NULL;
     wfree();
     bfree();
 }
     wfree();
     bfree();
 }