Michael McConville wrote:
> ksh offers csh-style history aliases when you set csh-history. This
> feature currently works. However, when an alias doesn't exist ksh
> reports only the last digit (thanks to Theo for tipping me off on this):
> 
> > mike:/tmp/tech:1$ set -o csh-history
> > mike:/tmp/tech:2$ ls
> > a  b  c
> > mike:/tmp/tech:3$ !2
> > a  b  c
> > mike:/tmp/tech:4$ !3456789
> > ksh: !9: not found
> 
> The below diff fixes this. Basically, this feature is implemented in the
> lexer, and ksh doesn't rewind through the whole alias after realizing
> that it doesn't exist.
> 
> I don't entirely understand the lexer, so I did this super defensively.
> If anyone knows of a smarter way, please share.
> 
> I moved the var declarations farther out because they're now needed in
> the outer scope.

Ping, with a simpler diff.


Index: lex.c
===================================================================
RCS file: /cvs/src/bin/ksh/lex.c,v
retrieving revision 1.52
diff -u -p -r1.52 lex.c
--- lex.c       15 Sep 2015 18:15:05 -0000      1.52
+++ lex.c       16 Sep 2015 23:11:49 -0000
@@ -163,6 +163,9 @@ yylex(int cf)
                        if (Flag(FCSHHISTORY) && (source->flags & SF_TTY) &&
                            c == '!') {
                                char **replace = NULL;
+                               int get, i;
+                               char match[200], *str = match;
+                               size_t mlen;
 
                                c2 = getsc();
                                if (c2 == '\0' || c2 == ' ' || c2 == '\t')
@@ -171,8 +174,7 @@ yylex(int cf)
                                        replace = hist_get_newest(0);
                                else if (isdigit(c2) || c2 == '-' ||
                                    isalpha(c2)) {
-                                       int get = !isalpha(c2);
-                                       char match[200], *str = match;
+                                       get = !isalpha(c2);
 
                                        *str++ = c2;
                                        do {
@@ -216,8 +218,12 @@ yylex(int cf)
                                        s->u.freeme = NULL;
                                        source = s;
                                        continue;
-                               } else
-                                       ungetsc(c2);
+                               } else {
+                                       /* restore what followed the '!' */
+                                       mlen = strlen(match);
+                                       for (i = mlen-1; i >= 0; i--)
+                                               ungetsc(match[i]);
+                               }
                        }
                        if (c == '[' && (cf & (VARASN|ARRAYVAR))) {
                                *wp = EOS; /* temporary */

Reply via email to