This fixes a few issues with macros in ksh emacs input mode. I'm sure
it's not widely used but I'd be glad if someone could have a look at
it so I can get the diff out of my tree.

Ok, so what does it do? Here goes:

1. Expanding a macro containing characters that themselves are macros

   $ bind -m X=123
   $ bind -m 2=Y

   pre: 'X' => '13'
   post: 'X' => '123'

2. Expanding a macro having itself as the last character

   $ bind -m X=YX

   pre: 'X' => hard hang requiring kill -9 to stop
   post: 'X' => 'YX'

3. Having a macro that spans multiple input lines (newline,
   newline-and-next) (normally ^M, ^J, ^O)

   $ bind -m X=^A^Kclear^J^Y # clear the screen and continue editing

   pre: 'X' => $ _
   post: 'X' => $ mplayer humppa.mp3_

Comments?

/Alexander

( diffed with -U10 to make some parts more clear )

Index: emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.41
diff -u -p -U10 -r1.41 emacs.c
--- emacs.c     2 Aug 2007 10:50:25 -0000       1.41
+++ emacs.c     2 Jun 2009 00:59:55 -0000
@@ -97,21 +97,21 @@ static      char   **x_histp;       /* history posi
 static int     x_nextcmd;      /* for newline-and-next */
 static char    *xmp;           /* mark pointer */
 static u_char  x_last_command;
 static u_char  (*x_tab)[X_TABSZ];      /* key definition */
 static char    *(*x_atab)[X_TABSZ];    /* macro definitions */
 static unsigned char   x_bound[(X_TABSZ * X_NTABS + 7) / 8];
 #define        KILLSIZE        20
 static char    *killstack[KILLSIZE];
 static int     killsp, killtp;
 static int     x_curprefix;
-static char    *macroptr;
+static char    *macroptr = NULL;
 static int     prompt_skip;
 static int     prompt_redraw;
 
 static int      x_ins(char *);
 static void     x_delete(int, int);
 static int     x_bword(void);
 static int     x_fword(void);
 static void     x_goto(char *);
 static void     x_bs(int);
 static int      x_size_str(char *);
@@ -312,21 +312,20 @@ x_emacs(char *buf, size_t len)
        const char *p;
        int     i;
        u_char f;
 
        xbp = xbuf = buf; xend = buf + len;
        xlp = xcp = xep = buf;
        *xcp = 0;
        xlp_valid = true;
        xmp = NULL;
        x_curprefix = 0;
-       macroptr = (char *) 0;
        x_histp = histptr + 1;
        x_last_command = XFUNC_error;
 
        xx_cols = x_cols;
        x_col = promptlen(prompt, &p);
        prompt_skip = p - prompt;
        x_adj_ok = 1;
        prompt_redraw = 1;
        if (x_col > xx_cols)
                x_col = x_col - (x_col / xx_cols) * xx_cols;
@@ -354,20 +353,23 @@ x_emacs(char *buf, size_t len)
                        return 0;
 
                if (ISMETA(c)) {
                        c = META(c);
                        x_curprefix = 1;
                }
 
                f = x_curprefix == -1 ? XFUNC_insert :
                    x_tab[x_curprefix][c&CHARMASK];
 
+               if (macroptr && f == XFUNC_ins_string)
+                   f = XFUNC_insert;
+
                if (!(x_ftab[f].xf_flags & XF_PREFIX) &&
                    x_last_command != XFUNC_set_arg) {
                        x_arg = 1;
                        x_arg_defaulted = 1;
                }
                i = c | (x_curprefix << 8);
                x_curprefix = 0;
                switch (i = (*x_ftab[f].xf_func)(i)) {
                case KSTD:
                        if (!(x_ftab[f].xf_flags & XF_PREFIX))
@@ -1755,22 +1757,24 @@ static int
 x_e_getc(void)
 {
        int c;
 
        if (unget_char >= 0) {
                c = unget_char;
                unget_char = -1;
        } else {
                if (macroptr) {
                        c = *macroptr++;
-                       if (!*macroptr)
-                               macroptr = (char *) 0;
+                       if (!c) {
+                               macroptr = NULL;
+                               c = x_getc();
+                       }
                } else
                        c = x_getc();
        }
 
        return c <= CHARMASK ? c : (c & CHARMASK);
 }
 
 static void
 x_e_putc(int c)
 {

Reply via email to