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) {