]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20111216 snapshot
authorChet Ramey <chet.ramey@case.edu>
Mon, 9 Jan 2012 13:35:52 +0000 (08:35 -0500)
committerChet Ramey <chet.ramey@case.edu>
Mon, 9 Jan 2012 13:35:52 +0000 (08:35 -0500)
42 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
bashline.c
bashline.c~
bashline.h
bashline.h~ [new file with mode: 0644]
builtins/bind.def
builtins/bind.def~ [new file with mode: 0644]
builtins/read.def
builtins/read.def~
doc/bash.1
doc/bash.1~
doc/bashref.texi
doc/bashref.texi~
execute_cmd.c
expr.c
externs.h
externs.h~ [new file with mode: 0644]
lib/readline/bind.c
lib/readline/bind.c~ [new file with mode: 0644]
lib/readline/doc/readline.3
lib/readline/doc/readline.3~ [new file with mode: 0644]
lib/readline/doc/rluser.texi
lib/readline/doc/rluser.texi~
lib/readline/doc/version.texi
lib/readline/doc/version.texi~
lib/readline/funmap.c
lib/readline/funmap.c~
lib/readline/history.c
lib/readline/history.c~ [new file with mode: 0644]
lib/readline/macro.c
lib/readline/macro.c~
lib/readline/readline.h
lib/readline/readline.h~
lib/readline/rlprivate.h
lib/readline/rlprivate.h~
lib/readline/text.c
lib/readline/text.c~ [new file with mode: 0644]
lib/sh/strtrans.c
make_cmd.c
parse.y
parse.y~

index 066808f9603ee69ac90167f58d7ec04d7a89e7a8..aca8a73f977ce90bc46ae1a79c7f47f45678eafa 100644 (file)
@@ -12851,3 +12851,123 @@ lib/readline/rlprivate.h
 lib/readline/doc/rltech.texi
        - documented new variables: rl_executing_key, rl_executing_keyseq,
          rl_key_sequence_length
+
+                                  12/13
+                                  -----
+bashline.c
+       - bash_execute_unix_command: replace ad-hoc code that searches
+         cmd_xmap for correct command with call to rl_function_of_keyseq
+         using rl_executing_keyseq; now supports key sequences longer
+         than two characters.  Fixes bug reported by Michael Kazior
+         <kazikcz@gmail.com>
+
+                                  12/15
+                                  -----
+make_cmd.c
+       - make_function_def: don't null out source_file before calling
+         make_command so it can be used later on when the function definition
+         is executed
+
+execute_cmd.c
+       - execute_intern_function: second argument is now FUNCTION_DEF *
+         instead of COMMAND *
+       - execute_command_internal: call execute_intern_function with the
+         new second argument (the entire FUNCTION_DEF instead of just the
+         command member)
+       - execute_intern_function: if DEBUGGER is defined, call
+         bind_function_def before calling bind_function, just like
+         make_function_def does (might be able to take out the call in
+         make_function_def depending on what the debugger does with it).
+         Fixes bug reported by <dethrophes@motd005>
+
+expr.c
+       - more minor changes to cases of INTMAX_MIN % -1 and INTMAX_MIN / 1;
+         fix typos and logic errors
+
+                                  12/16
+                                  -----
+bashline.c
+       - find_cmd_start: change flags to remove SD_NOSKIPCMD so it skips over
+         command substitutions and doesn't treat them as command separators
+       - attempt_shell_completion: instead of taking first return from
+         find_cmd_name as command name to use for programmable completion,
+         use loop to skip over assignment statements.  Fixes problem reported
+         by Raphael Droz <raphael.droz+floss@gmail.com>
+       - attempt_shell_completion: if we don't find a command name but the
+         command line is non-empty, assume the other words are all assignment
+         statements and flag that point is in a command position so we can
+         do command name completion
+       - attempt_shell_completion: if the word being completed is the first
+         word following a series of assignment statements, and the
+         command line is non-empty, flag that point is in a command position
+         so we can do command name completion
+
+lib/readline/history.c
+       - history_get_time: atol -> strtol
+
+                                  12/18
+                                  -----
+parse.y
+       - parser_in_command_position: external interface to the
+         command_token_position macro for use by other parts of the shell,
+         like the completion mechanism
+
+externs.h
+       - extern declaration for parser_in_command_position
+
+                                  12/19
+                                  -----
+
+builtins/read.def
+       - read_builtin: make sure all calls to bind_read_variable are passed
+         a non-null string.  Fixes bug reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+bashline.c
+       - attempt_shell_completion: mark that we're in a command position if
+         we're at the start of the line and the parser is ready to accept
+         a reserved word or command name.  Feature most recently suggested
+         by Peng Yu <pengyu.ut@gmail.com>
+
+                                  12/21
+                                  -----
+lib/readline/bind.c
+       - _rl_escchar: return the character that would be backslash-escaped
+         to denote the control character passed as an argument ('\n' -> 'n')
+       - _rl_isescape: return 1 if character passed is one that has a
+         backslash escape
+       - _rl_untranslate_macro_value: new second argument: use_escapes, if
+         non-zero translate to backslash escapes where possible instead of
+         using straight \C-x for control character `x'.  Change callers
+       - _rl_untranslate_macro_value: now global
+
+lib/readline/rlprivate.h
+       - _rl_untranslate_macro_value: extern declaration
+
+lib/readline/{macro.c,readline.h}
+       - rl_print_last_kbd_macro: new bindable function, inspired by patch
+         from Mitchel Humpherys
+
+lib/readline/funmap.c
+       - print-last-kbd-macro: new bindable command, bound to
+         rl_print_last_kbd_macro
+
+lib/readline/doc/{rluser.texi,readline.3},doc/bash.1
+       - print-last-kbd-macro: document.
+
+lib/readline/text.c
+       - _rl_insert_next: if we're defining a macro, make sure the key gets
+         added to the macro text (should really audit calls to rl_read_key()
+         and make sure the right thing is happening for all of them)
+
+bashline.[ch]
+       - print_unix_command_map: new function, prints all bound commands in
+         cmd_xmap using rl_macro_dumper in a reusable format
+
+builtins/bind.def
+       - new -X option: print all keysequences bound to Unix commands using
+         print_unix_command_map.  Feature suggested by Dennis Williamson
+         (2/2011)
+
+doc/{bash.1,bashref.texi}
+       - document new `bind -X' option
index 45a31d05003bb6656b0876bf61e2dffd19f7cbf8..2e680646f12f90776c38f356e57524e0d83d05ff 100644 (file)
@@ -12847,3 +12847,126 @@ lib/readline/readline.h
 lib/readline/rlprivate.h
        - new extern declaration for _rl_executing_keyseq_size, buffer size
          for rl_executing_keyseq
+
+lib/readline/doc/rltech.texi
+       - documented new variables: rl_executing_key, rl_executing_keyseq,
+         rl_key_sequence_length
+
+                                  12/13
+                                  -----
+bashline.c
+       - bash_execute_unix_command: replace ad-hoc code that searches
+         cmd_xmap for correct command with call to rl_function_of_keyseq
+         using rl_executing_keyseq; now supports key sequences longer
+         than two characters.  Fixes bug reported by Michael Kazior
+         <kazikcz@gmail.com>
+
+                                  12/15
+                                  -----
+make_cmd.c
+       - make_function_def: don't null out source_file before calling
+         make_command so it can be used later on when the function definition
+         is executed
+
+execute_cmd.c
+       - execute_intern_function: second argument is now FUNCTION_DEF *
+         instead of COMMAND *
+       - execute_command_internal: call execute_intern_function with the
+         new second argument (the entire FUNCTION_DEF instead of just the
+         command member)
+       - execute_intern_function: if DEBUGGER is defined, call
+         bind_function_def before calling bind_function, just like
+         make_function_def does (might be able to take out the call in
+         make_function_def depending on what the debugger does with it).
+         Fixes bug reported by <dethrophes@motd005>
+
+expr.c
+       - more minor changes to cases of INTMAX_MIN % -1 and INTMAX_MIN / 1;
+         fix typos and logic errors
+
+                                  12/16
+                                  -----
+bashline.c
+       - find_cmd_start: change flags to remove SD_NOSKIPCMD so it skips over
+         command substitutions and doesn't treat them as command separators
+       - attempt_shell_completion: instead of taking first return from
+         find_cmd_name as command name to use for programmable completion,
+         use loop to skip over assignment statements.  Fixes problem reported
+         by Raphael Droz <raphael.droz+floss@gmail.com>
+       - attempt_shell_completion: if we don't find a command name but the
+         command line is non-empty, assume the other words are all assignment
+         statements and flag that point is in a command position so we can
+         do command name completion
+       - attempt_shell_completion: if the word being completed is the first
+         word following a series of assignment statements, and the
+         command line is non-empty, flag that point is in a command position
+         so we can do command name completion
+
+lib/readline/history.c
+       - history_get_time: atol -> strtol
+
+                                  12/18
+                                  -----
+parse.y
+       - parser_in_command_position: external interface to the
+         command_token_position macro for use by other parts of the shell,
+         like the completion mechanism
+
+externs.h
+       - extern declaration for parser_in_command_position
+
+                                  12/19
+                                  -----
+builtins/read.def
+       - read_builtin: make sure all calls to bind_read_variable are passed
+         a non-null string.  Fixes bug reported by Dan Douglas
+         <ormaaj@gmail.com>
+
+bashline.c
+       - attempt_shell_completion: mark that we're in a command position if
+         we're at the start of the line and the parser is ready to accept
+         a reserved word or command name.  Feature most recently suggested
+         by Peng Yu <pengyu.ut@gmail.com>
+
+                                  12/21
+                                  -----
+lib/readline/bind.c
+       - _rl_escchar: return the character that would be backslash-escaped
+         to denote the control character passed as an argument ('\n' -> 'n')
+       - _rl_isescape: return 1 if character passed is one that has a
+         backslash escape
+       - _rl_untranslate_macro_value: new second argument: use_escapes, if
+         non-zero translate to backslash escapes where possible instead of
+         using straight \C-x for control character `x'.  Change callers
+       - _rl_untranslate_macro_value: now global
+
+lib/readline/rlprivate.h
+       - _rl_untranslate_macro_value: extern declaration
+
+lib/readline/{macro.c,readline.h}
+       - rl_print_last_kbd_macro: new bindable function, inspired by patch
+         from Mitchel Humpherys
+
+lib/readline/funmap.c
+       - print-last-kbd-macro: new bindable command, bound to
+         rl_print_last_kbd_macro
+
+lib/readline/doc/{rluser.texi,readline.3},doc/bash.1
+       - print-last-kbd-macro: document.
+
+lib/readline/text.c
+       - _rl_insert_next: if we're defining a macro, make sure the key gets
+         added to the macro text (should really audit calls to rl_read_key()
+         and make sure the right thing is happening for all of them)
+
+bashline.[ch]
+       - print_unix_command_map: new function, prints all bound commands in
+         cmd_xmap using rl_macro_dumper in a reusable format
+
+builtins/bind.def
+       - new -X option: print all keysequences bound to Unix commands using
+         print_unix_command_map.  Feature suggested by Dennis Williamson
+         (2/2011)
+
+doc/{bash.1,bashref.texi}
+       - document new `bind -X' option
index 982c82283df7ff154c2296835b4ee2dd6a988892..301561944c58698d818efc9e6649a2070cf4c5f0 100644 (file)
@@ -1232,7 +1232,11 @@ bash_backward_kill_shellword (count, key)
 
 #define COMMAND_SEPARATORS ";|&{(`"
 /* )} */ 
+#define COMMAND_SEPARATORS_PLUS_WS ";|&{(` \t"
+/* )} */ 
 
+/* check for redirections and other character combinations that are not
+   command separators */
 static int
 check_redir (ti)
      int ti;
@@ -1247,8 +1251,19 @@ check_redir (ti)
   if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
       (this_char == '|' && prev_char == '>'))
     return (1);
-  else if ((this_char == '{' && prev_char == '$') || /* } */
-          (char_is_quoted (rl_line_buffer, ti)))
+  else if (this_char == '{' && prev_char == '$') /*}*/
+    return (1);
+#if 0  /* Not yet */
+  else if (this_char == '(' && prev_char == '$') /*)*/
+    return (1);
+  else if (this_char == '(' && prev_char == '<') /*)*/
+    return (1);
+#if defined (EXTENDED_GLOB)
+  else if (extended_glob && this_char == '(' && prev_char == '!') /*)*/
+    return (1);
+#endif
+#endif
+  else if (char_is_quoted (rl_line_buffer, ti))
     return (1);
   return (0);
 }
@@ -1266,7 +1281,10 @@ find_cmd_start (start)
   register int s, os;
 
   os = 0;
-  while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP|SD_NOSKIPCMD)) <= start) &&
+  /* Flags == SD_NOJMP only because we want to skip over command substitutions
+     in assignment statements.  Have to test whether this affects `standalone'
+     command substitutions as individual words. */
+  while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP/*|SD_NOSKIPCMD*/)) <= start) &&
         rl_line_buffer[s])
     os = s+1;
   return os;
@@ -1370,6 +1388,8 @@ attempt_shell_completion (text, start, end)
         are prompting at the top level. */
       if (current_prompt_string == ps1_prompt)
        in_command_position++;
+      else if (parser_in_command_position ())
+       in_command_position++;
     }
   else if (member (rl_line_buffer[ti], command_separator_chars))
     {
@@ -1407,7 +1427,7 @@ attempt_shell_completion (text, start, end)
       prog_completion_enabled && (progcomp_size () > 0) &&
       current_prompt_string == ps1_prompt)
     {
-      int s, e, s1, e1, foundcs;
+      int s, e, s1, e1, os, foundcs;
       char *n;
 
       /* XXX - don't free the members */
@@ -1415,9 +1435,23 @@ attempt_shell_completion (text, start, end)
        free (prog_complete_matches);
       prog_complete_matches = (char **)NULL;
 
-      s = find_cmd_start (start);
+      os = start;
+      n = 0;
+      s = find_cmd_start (os);
       e = find_cmd_end (end);
-      n = find_cmd_name (s, &s1, &e1);
+      do
+       {
+         /* Skip over assignment statements preceding a command name.  If we
+            don't find a command name at all, we can perform command name
+            completion.  If we find a partial command name, we should perform
+            command name completion on it. */
+         FREE (n);
+         n = find_cmd_name (s, &s1, &e1);
+         s = e1 + 1;
+       }
+      while (assignment (n, 0));
+      s = s1;          /* reset to index where name begins */
+
       if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
         foundcs = 0;
       else if (start == end && start == s1 && e != 0 && e1 > end)      /* beginning of command name, leading whitespace */
@@ -1428,6 +1462,16 @@ attempt_shell_completion (text, start, end)
         foundcs = 0;           /* whitespace before command name */
       else if (e > s && assignment (n, 0) == 0)
        prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
+      else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
+        {
+          foundcs = 0; /* empty command name following assignments */
+          in_command_position = 1;
+        }
+      else if (s == start && e == end && STREQ (n, text) && start > 0)
+        {
+          foundcs = 0; /* partial command name following assignments */
+          in_command_position = 1;
+        }
       else
        foundcs = 0;
       FREE (n);
@@ -3734,6 +3778,8 @@ bash_execute_unix_command (count, key)
 {
   Keymap ckmap;                /* current keymap */
   Keymap xkmap;                /* unix command executing keymap */
+  rl_command_func_t *func;
+  int type;
   register int i, r;
   intmax_t mi;
   sh_parser_state_t ps;
@@ -3742,34 +3788,15 @@ bash_execute_unix_command (count, key)
   char ibuf[INT_STRLEN_BOUND(int) + 1];
 
   /* First, we need to find the right command to execute.  This is tricky,
-     because we might have already indirected into another keymap. */
-  ckmap = rl_get_keymap ();
-  if (ckmap != rl_executing_keymap)
-    {
-      /* bogus.  we have to search.  only handle one level of indirection. */
-      for (i = 0; i < KEYMAP_SIZE; i++)
-       {
-         if (ckmap[i].type == ISKMAP && (Keymap)ckmap[i].function == rl_executing_keymap)
-           break;
-       }
-      if (i < KEYMAP_SIZE)
-       xkmap = (Keymap)cmd_xmap[i].function;
-      else
-       {
-         rl_crlf ();
-         internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
-         rl_forced_update_display ();
-         return 1;
-       }
-    }
-  else
-    xkmap = cmd_xmap;
-
-  cmd = (char *)xkmap[key].function;
-
-  if (cmd == 0)
+     because we might have already indirected into another keymap, so we
+     have to walk cmd_xmap using the entire key sequence. */
+  cmd = (char *)rl_function_of_keyseq (rl_executing_keyseq, cmd_xmap, &type);
+    
+  if (cmd == 0 || type != ISMACR)
     {
-      rl_ding ();
+      rl_crlf ();
+      internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
+      rl_forced_update_display ();
       return 1;
     }
 
@@ -3824,6 +3851,18 @@ bash_execute_unix_command (count, key)
   return 0;
 }
 
+int
+print_unix_command_map ()
+{
+  Keymap save;
+
+  save = rl_get_keymap ();
+  rl_set_keymap (cmd_xmap);
+  rl_macro_dumper (1);
+  rl_set_keymap (save);
+  return 0;
+}
+
 static void
 init_unix_command_map ()
 {
index 58c5ba5a545011974c512e233e876cde1f0d7eba..0b4a9ecb43f97c2b958355f305d70e3255a55d06 100644 (file)
@@ -1232,7 +1232,11 @@ bash_backward_kill_shellword (count, key)
 
 #define COMMAND_SEPARATORS ";|&{(`"
 /* )} */ 
+#define COMMAND_SEPARATORS_PLUS_WS ";|&{(` \t"
+/* )} */ 
 
+/* check for redirections and other character combinations that are not
+   command separators */
 static int
 check_redir (ti)
      int ti;
@@ -1247,8 +1251,19 @@ check_redir (ti)
   if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
       (this_char == '|' && prev_char == '>'))
     return (1);
-  else if ((this_char == '{' && prev_char == '$') || /* } */
-          (char_is_quoted (rl_line_buffer, ti)))
+  else if (this_char == '{' && prev_char == '$') /*}*/
+    return (1);
+#if 0  /* Not yet */
+  else if (this_char == '(' && prev_char == '$') /*)*/
+    return (1);
+  else if (this_char == '(' && prev_char == '<') /*)*/
+    return (1);
+#if defined (EXTENDED_GLOB)
+  else if (extended_glob && this_char == '(' && prev_char == '!') /*)*/
+    return (1);
+#endif
+#endif
+  else if (char_is_quoted (rl_line_buffer, ti))
     return (1);
   return (0);
 }
@@ -1266,7 +1281,10 @@ find_cmd_start (start)
   register int s, os;
 
   os = 0;
-  while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP|SD_NOSKIPCMD)) <= start) &&
+  /* Flags == SD_NOJMP only because we want to skip over command substitutions
+     in assignment statements.  Have to test whether this affects `standalone'
+     command substitutions as individual words. */
+  while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP/*|SD_NOSKIPCMD*/)) <= start) &&
         rl_line_buffer[s])
     os = s+1;
   return os;
@@ -1370,6 +1388,8 @@ attempt_shell_completion (text, start, end)
         are prompting at the top level. */
       if (current_prompt_string == ps1_prompt)
        in_command_position++;
+      else if (parser_in_command_position ())
+       in_command_position++;
     }
   else if (member (rl_line_buffer[ti], command_separator_chars))
     {
@@ -1407,7 +1427,7 @@ attempt_shell_completion (text, start, end)
       prog_completion_enabled && (progcomp_size () > 0) &&
       current_prompt_string == ps1_prompt)
     {
-      int s, e, s1, e1, foundcs;
+      int s, e, s1, e1, os, foundcs;
       char *n;
 
       /* XXX - don't free the members */
@@ -1415,9 +1435,23 @@ attempt_shell_completion (text, start, end)
        free (prog_complete_matches);
       prog_complete_matches = (char **)NULL;
 
-      s = find_cmd_start (start);
+      os = start;
+      n = 0;
+      s = find_cmd_start (os);
       e = find_cmd_end (end);
-      n = find_cmd_name (s, &s1, &e1);
+      do
+       {
+         /* Skip over assignment statements preceding a command name.  If we
+            don't find a command name at all, we can perform command name
+            completion.  If we find a partial command name, we should perform
+            command name completion on it. */
+         FREE (n);
+         n = find_cmd_name (s, &s1, &e1);
+         s = e1 + 1;
+       }
+      while (assignment (n, 0));
+      s = s1;          /* reset to index where name begins */
+
       if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
         foundcs = 0;
       else if (start == end && start == s1 && e != 0 && e1 > end)      /* beginning of command name, leading whitespace */
@@ -1428,6 +1462,16 @@ attempt_shell_completion (text, start, end)
         foundcs = 0;           /* whitespace before command name */
       else if (e > s && assignment (n, 0) == 0)
        prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
+      else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
+        {
+          foundcs = 0; /* empty command name following assignments */
+          in_command_position = 1;
+        }
+      else if (s == start && e == end && STREQ (n, text) && start > 0)
+        {
+          foundcs = 0; /* partial command name following assignments */
+          in_command_position = 1;
+        }
       else
        foundcs = 0;
       FREE (n);
@@ -2773,8 +2817,11 @@ bash_directory_expansion (dirname)
 
   d = savestring (*dirname);
 
-  if (rl_directory_rewrite_hook)
-    (*rl_directory_rewrite_hook) (&d);
+  if ((rl_directory_rewrite_hook) &&  (*rl_directory_rewrite_hook) (&d))
+    {
+      free (*dirname);
+      *dirname = d;
+    }
   else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
     {
       free (*dirname);
@@ -3731,6 +3778,8 @@ bash_execute_unix_command (count, key)
 {
   Keymap ckmap;                /* current keymap */
   Keymap xkmap;                /* unix command executing keymap */
+  rl_command_func_t *func;
+  int type;
   register int i, r;
   intmax_t mi;
   sh_parser_state_t ps;
@@ -3739,34 +3788,15 @@ bash_execute_unix_command (count, key)
   char ibuf[INT_STRLEN_BOUND(int) + 1];
 
   /* First, we need to find the right command to execute.  This is tricky,
-     because we might have already indirected into another keymap. */
-  ckmap = rl_get_keymap ();
-  if (ckmap != rl_executing_keymap)
-    {
-      /* bogus.  we have to search.  only handle one level of indirection. */
-      for (i = 0; i < KEYMAP_SIZE; i++)
-       {
-         if (ckmap[i].type == ISKMAP && (Keymap)ckmap[i].function == rl_executing_keymap)
-           break;
-       }
-      if (i < KEYMAP_SIZE)
-       xkmap = (Keymap)cmd_xmap[i].function;
-      else
-       {
-         rl_crlf ();
-         internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
-         rl_forced_update_display ();
-         return 1;
-       }
-    }
-  else
-    xkmap = cmd_xmap;
-
-  cmd = (char *)xkmap[key].function;
-
-  if (cmd == 0)
+     because we might have already indirected into another keymap, so we
+     have to walk cmd_xmap using the entire key sequence. */
+  cmd = (char *)rl_function_of_keyseq (rl_executing_keyseq, cmd_xmap, &type);
+    
+  if (cmd == 0 || type != ISMACR)
     {
-      rl_ding ();
+      rl_crlf ();
+      internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
+      rl_forced_update_display ();
       return 1;
     }
 
@@ -3821,6 +3851,18 @@ bash_execute_unix_command (count, key)
   return 0;
 }
 
+int
+print_unix_command_map ()
+{
+  Keymap save;
+
+  save = rl_get_keymap ();
+  rl_set_keymap (unix_cmdmap);
+  rl_macro_dumper (1);
+  rl_set_keymap (save);
+  return 0;
+}
+
 static void
 init_unix_command_map ()
 {
@@ -3904,12 +3946,16 @@ bind_keyseq_to_unix_command (line)
   if (line[i] != ':')
     {
       builtin_error (_("%s: missing colon separator"), line);
+      FREE (kseq);
       return -1;
     }
 
   i = isolate_sequence (line, i + 1, 0, &kstart);
   if (i < 0)
-    return -1;
+    {
+      FREE (kseq);
+      return -1;
+    }
 
   /* Create the value string containing the command to execute. */
   value = substring (line, kstart, i);
@@ -3920,7 +3966,8 @@ bind_keyseq_to_unix_command (line)
   /* and bind the key sequence in the current keymap to a function that
      understands how to execute from CMD_XMAP */
   rl_bind_keyseq_in_map (kseq, bash_execute_unix_command, kmap);
-  
+
+  free (kseq);  
   return 0;
 }
 
index 38964eaf71a422940c2cbc9a7ad82ad26d5d1bbc..d52dfdfa957f5909a4d282bde63dd78ac18d30fb 100644 (file)
@@ -37,6 +37,7 @@ extern void bashline_set_event_hook __P((void));
 extern void bashline_reset_event_hook __P((void));
 
 extern int bind_keyseq_to_unix_command __P((char *));
+extern int print_unix_command_map __P((void));
 
 extern char **bash_default_completion __P((const char *, int, int, int, int));
 
diff --git a/bashline.h~ b/bashline.h~
new file mode 100644 (file)
index 0000000..38964ea
--- /dev/null
@@ -0,0 +1,56 @@
+/* bashline.h -- interface to the bash readline functions in bashline.c. */
+
+/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#if !defined (_BASHLINE_H_)
+#define _BASHLINE_H_
+
+#include "stdc.h"
+
+extern int bash_readline_initialized;
+
+extern void posix_readline_initialize __P((int));
+extern void reset_completer_word_break_chars __P((void));
+extern int enable_hostname_completion __P((int));
+extern void initialize_readline __P((void));
+extern void bashline_reset __P((void));
+extern void bashline_reinitialize __P((void));
+extern int bash_re_edit __P((char *));
+
+extern void bashline_set_event_hook __P((void));
+extern void bashline_reset_event_hook __P((void));
+
+extern int bind_keyseq_to_unix_command __P((char *));
+
+extern char **bash_default_completion __P((const char *, int, int, int, int));
+
+void set_directory_hook __P((void));
+
+/* Used by programmable completion code. */
+extern char *command_word_completion_function __P((const char *, int));
+extern char *bash_groupname_completion_function __P((const char *, int));
+extern char *bash_servicename_completion_function __P((const char *, int));
+
+extern char **get_hostname_list __P((void));
+extern void clear_hostname_list __P((void));
+
+extern char **bash_directory_completion_matches __P((const char *));
+extern char *bash_dequote_text __P((const char *));
+
+#endif /* _BASHLINE_H_ */
index d0c953bb82176a743bd30cf88292027d30d7bc3a..3a7cc4efd3398185771d59a2ae5223214c3ad736 100644 (file)
@@ -25,7 +25,7 @@ $PRODUCES bind.c
 $BUILTIN bind
 $DEPENDS_ON READLINE
 $FUNCTION bind_builtin
-$SHORT_DOC bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
+$SHORT_DOC bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
 Set Readline key bindings and variables.
 
 Bind a key sequence to a Readline function or a macro, or set a
@@ -54,6 +54,8 @@ Options:
   -f  filename       Read key bindings from FILENAME.
   -x  keyseq:shell-command     Cause SHELL-COMMAND to be executed when
                                KEYSEQ is entered.
+  -X                List key sequences bound with -x and associated commands
+                     in a form that can be reused as input.
 
 Exit Status:
 bind returns 0 unless an unrecognized option is given or an error occurs.
@@ -104,6 +106,7 @@ extern int no_line_editing;
 #define SSFLAG  0x0400
 #define UFLAG  0x0800
 #define XFLAG  0x1000
+#define XXFLAG 0x2000
 
 int
 bind_builtin (list)
@@ -138,7 +141,7 @@ bind_builtin (list)
   rl_outstream = stdout;
 
   reset_internal_getopt ();  
-  while ((opt = internal_getopt (list, "lvpVPsSf:q:u:m:r:x:")) != EOF)
+  while ((opt = internal_getopt (list, "lvpVPsSXf:q:u:m:r:x:")) != EOF)
     {
       switch (opt)
        {
@@ -187,6 +190,9 @@ bind_builtin (list)
          flags |= XFLAG;
          cmd_seq = list_optarg;
          break;
+       case 'X':
+         flags |= XXFLAG;
+         break;
        default:
          builtin_usage ();
          BIND_RETURN (EX_USAGE);
@@ -201,7 +207,7 @@ bind_builtin (list)
   if ((flags & MFLAG) && map_name)
     {
       kmap = rl_get_keymap_by_name (map_name);
-      if (!kmap)
+      if (kmap == 0)
        {
          builtin_error (_("`%s': invalid keymap name"), map_name);
          BIND_RETURN (EXECUTION_FAILURE);
@@ -265,6 +271,9 @@ bind_builtin (list)
   if (flags & XFLAG)
     return_code = bind_keyseq_to_unix_command (cmd_seq);
 
+  if (flags & XXFLAG)
+    return_code = print_unix_command_map ();
+
   /* Process the rest of the arguments as binding specifications. */
   while (list)
     {
diff --git a/builtins/bind.def~ b/builtins/bind.def~
new file mode 100644 (file)
index 0000000..6dcc2f2
--- /dev/null
@@ -0,0 +1,341 @@
+This file is bind.def, from which is created bind.c.
+It implements the builtin "bind" in Bash.
+
+Copyright (C) 1987-2009 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Bash is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+
+$PRODUCES bind.c
+
+#include <config.h>
+
+$BUILTIN bind
+$DEPENDS_ON READLINE
+$FUNCTION bind_builtin
+$SHORT_DOC bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
+Set Readline key bindings and variables.
+
+Bind a key sequence to a Readline function or a macro, or set a
+Readline variable.  The non-option argument syntax is equivalent to
+that found in ~/.inputrc, but must be passed as a single argument:
+e.g., bind '"\C-x\C-r": re-read-init-file'.
+
+Options:
+  -m  keymap         Use KEYMAP as the keymap for the duration of this
+                     command.  Acceptable keymap names are emacs,
+                     emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
+                     vi-command, and vi-insert.
+  -l                 List names of functions.
+  -P                 List function names and bindings.
+  -p                 List functions and bindings in a form that can be
+                     reused as input.
+  -S                 List key sequences that invoke macros and their values
+  -s                 List key sequences that invoke macros and their values
+                     in a form that can be reused as input.
+  -V                 List variable names and values
+  -v                 List variable names and values in a form that can
+                     be reused as input.
+  -q  function-name  Query about which keys invoke the named function.
+  -u  function-name  Unbind all keys which are bound to the named function.
+  -r  keyseq         Remove the binding for KEYSEQ.
+  -f  filename       Read key bindings from FILENAME.
+  -x  keyseq:shell-command     Cause SHELL-COMMAND to be executed when
+                               KEYSEQ is entered.
+  -X                List key sequences bound with -x and associated commands
+                     in a form that can be reused as input.
+
+Exit Status:
+bind returns 0 unless an unrecognized option is given or an error occurs.
+$END
+
+#if defined (READLINE)
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "../bashline.h"
+#include "bashgetopt.h"
+#include "common.h"
+
+static int query_bindings __P((char *));
+static int unbind_command __P((char *));
+
+extern int no_line_editing;
+
+#define BIND_RETURN(x)  do { return_code = x; goto bind_exit; } while (0)
+
+#define LFLAG  0x0001
+#define PFLAG  0x0002
+#define FFLAG  0x0004
+#define VFLAG  0x0008
+#define QFLAG  0x0010
+#define MFLAG  0x0020
+#define RFLAG  0x0040
+#define PPFLAG 0x0080
+#define VVFLAG 0x0100
+#define SFLAG   0x0200
+#define SSFLAG  0x0400
+#define UFLAG  0x0800
+#define XFLAG  0x1000
+#define XXFLAG 0x2000
+
+int
+bind_builtin (list)
+     WORD_LIST *list;
+{
+  int return_code;
+  Keymap kmap, saved_keymap;
+  int flags, opt;
+  char *initfile, *map_name, *fun_name, *unbind_name, *remove_seq, *cmd_seq;
+
+  if (no_line_editing)
+    {
+#if 0
+      builtin_error (_("line editing not enabled"));
+      return (EXECUTION_FAILURE);
+#else
+      builtin_warning (_("line editing not enabled"));
+#endif
+    }
+
+  kmap = saved_keymap = (Keymap) NULL;
+  flags = 0;
+  initfile = map_name = fun_name = unbind_name = remove_seq = (char *)NULL;
+  return_code = EXECUTION_SUCCESS;
+
+  if (bash_readline_initialized == 0)
+    initialize_readline ();
+
+  begin_unwind_frame ("bind_builtin");
+  unwind_protect_var (rl_outstream);
+
+  rl_outstream = stdout;
+
+  reset_internal_getopt ();  
+  while ((opt = internal_getopt (list, "lvpVPsSXf:q:u:m:r:x:")) != EOF)
+    {
+      switch (opt)
+       {
+       case 'l':
+         flags |= LFLAG;
+         break;
+       case 'v':
+         flags |= VFLAG;
+         break;
+       case 'p':
+         flags |= PFLAG;
+         break;
+       case 'f':
+         flags |= FFLAG;
+         initfile = list_optarg;
+         break;
+       case 'm':
+         flags |= MFLAG;
+         map_name = list_optarg;
+         break;
+       case 'q':
+         flags |= QFLAG;
+         fun_name = list_optarg;
+         break;
+       case 'u':
+         flags |= UFLAG;
+         unbind_name = list_optarg;
+         break;
+       case 'r':
+         flags |= RFLAG;
+         remove_seq = list_optarg;
+         break;
+       case 'V':
+         flags |= VVFLAG;
+         break;
+       case 'P':
+         flags |= PPFLAG;
+         break;
+       case 's':
+         flags |= SFLAG;
+         break;
+       case 'S':
+         flags |= SSFLAG;
+         break;
+       case 'x':
+         flags |= XFLAG;
+         cmd_seq = list_optarg;
+         break;
+       case 'X':
+         flags |= XXFLAG;
+         break;
+       default:
+         builtin_usage ();
+         BIND_RETURN (EX_USAGE);
+       }
+    }
+
+  list = loptend;
+
+  /* First, see if we need to install a special keymap for this
+     command.  Then start on the arguments. */
+
+  if ((flags & MFLAG) && map_name)
+    {
+      kmap = rl_get_keymap_by_name (map_name);
+      if (kmap == 0)
+       {
+         builtin_error (_("`%s': invalid keymap name"), map_name);
+         BIND_RETURN (EXECUTION_FAILURE);
+       }
+    }
+  
+  if (kmap)
+    {
+      saved_keymap = rl_get_keymap ();
+      rl_set_keymap (kmap);
+    }
+
+  /* XXX - we need to add exclusive use tests here.  It doesn't make sense
+     to use some of these options together. */
+  /* Now hack the option arguments */
+  if (flags & LFLAG)
+    rl_list_funmap_names ();
+
+  if (flags & PFLAG)
+    rl_function_dumper (1);
+
+  if (flags & PPFLAG)
+    rl_function_dumper (0);
+
+  if (flags & SFLAG)
+    rl_macro_dumper (1);
+
+  if (flags & SSFLAG)
+    rl_macro_dumper (0);
+
+  if (flags & VFLAG)
+    rl_variable_dumper (1);
+
+  if (flags & VVFLAG)
+    rl_variable_dumper (0);
+
+  if ((flags & FFLAG) && initfile)
+    {
+      if (rl_read_init_file (initfile) != 0)
+       {
+         builtin_error (_("%s: cannot read: %s"), initfile, strerror (errno));
+         BIND_RETURN (EXECUTION_FAILURE);
+       }
+    }
+
+  if ((flags & QFLAG) && fun_name)
+    return_code = query_bindings (fun_name);
+
+  if ((flags & UFLAG) && unbind_name)
+    return_code = unbind_command (unbind_name);
+
+  if ((flags & RFLAG) && remove_seq)
+    {
+      if (rl_bind_keyseq (remove_seq, (rl_command_func_t *)NULL) != 0)
+       {
+         builtin_error (_("`%s': cannot unbind"), remove_seq);
+         BIND_RETURN (EXECUTION_FAILURE);
+       }
+    }
+
+  if (flags & XFLAG)
+    return_code = bind_keyseq_to_unix_command (cmd_seq);
+
+  if (flags & XXFLAG)
+    return_code = print_unix_command_map ();
+
+  /* Process the rest of the arguments as binding specifications. */
+  while (list)
+    {
+      rl_parse_and_bind (list->word->word);
+      list = list->next;
+    }
+
+ bind_exit:
+  if (saved_keymap)
+    rl_set_keymap (saved_keymap);
+
+  run_unwind_frame ("bind_builtin");
+
+  return (sh_chkwrite (return_code));
+}
+
+static int
+query_bindings (name)
+     char *name;
+{
+  rl_command_func_t *function;
+  char **keyseqs;
+  int j;
+
+  function = rl_named_function (name);
+  if (function == 0)
+    {
+      builtin_error (_("`%s': unknown function name"), name);
+      return EXECUTION_FAILURE;
+    }
+
+  keyseqs = rl_invoking_keyseqs (function);
+
+  if (!keyseqs)
+    {
+      printf (_("%s is not bound to any keys.\n"), name);
+      return EXECUTION_FAILURE;
+    }
+
+  printf (_("%s can be invoked via "), name);
+  for (j = 0; j < 5 && keyseqs[j]; j++)
+    printf ("\"%s\"%s", keyseqs[j], keyseqs[j + 1] ? ", " : ".\n");
+  if (keyseqs[j])
+    printf ("...\n");
+  strvec_dispose (keyseqs);
+  return EXECUTION_SUCCESS;
+}
+
+static int
+unbind_command (name)
+     char *name;
+{
+  rl_command_func_t *function;
+
+  function = rl_named_function (name);
+  if (function == 0)
+    {
+      builtin_error (_("`%s': unknown function name"), name);
+      return EXECUTION_FAILURE;
+    }
+
+  rl_unbind_function_in_map (function, rl_get_keymap ());
+  return EXECUTION_SUCCESS;
+}
+#endif /* READLINE */
index dcd10a11f5a081e06d7e9fcff4559e200c4672bb..4891ca3afc0c1b60c2dcbaef3c9ece67d1d105d0 100644 (file)
@@ -835,7 +835,7 @@ assign_vars:
       xfree (t);
     }
   else
-    var = bind_read_variable (list->word->word, input_string);
+    var = bind_read_variable (list->word->word, input_string ? input_string : "");
 
   if (var)
     {
index 41757c0c89b828a404c9e92be44fc21d6ce3ef72..0487aff830f89d127e17d859ea7fe1f1d63d1d6d 100644 (file)
@@ -1,7 +1,7 @@
 This file is read.def, from which is created read.c.
 It implements the builtin "read" in Bash.
 
-Copyright (C) 1987-2010 Free Software Foundation, Inc.
+Copyright (C) 1987-2011 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -129,14 +129,26 @@ static sighandler sigalrm __P((int));
 static void reset_alarm __P((void));
 
 static procenv_t alrmbuf;
+static int sigalrm_seen, reading;
 static SigHandler *old_alrm;
 static unsigned char delim;
 
+/* In most cases, SIGALRM just sets a flag that we check periodically.  This
+   avoids problems with the semi-tricky stuff we do with the xfree of
+   input_string at the top of the unwind-protect list (see below). */
+#define CHECK_ALRM \
+  do { \
+    if (sigalrm_seen) \
+      longjmp (alrmbuf, 1); \
+  } while (0)
+
 static sighandler
 sigalrm (s)
      int s;
 {
-  longjmp (alrmbuf, 1);
+  sigalrm_seen = 1;
+  if (reading)         /* do the longjmp if we get SIGALRM while in read() */
+    longjmp (alrmbuf, 1);
 }
 
 static void
@@ -201,6 +213,8 @@ read_builtin (list)
   USE_VAR(list);
   USE_VAR(ps2);
 
+  sigalrm_seen = reading = 0;
+
   i = 0;               /* Index into the string that we are reading. */
   raw = edit = 0;      /* Not reading raw input by default. */
   silent = 0;
@@ -384,9 +398,12 @@ read_builtin (list)
       code = setjmp (alrmbuf);
       if (code)
        {
+         sigalrm_seen = 0;
          /* Tricky.  The top of the unwind-protect stack is the free of
             input_string.  We want to run all the rest and use input_string,
             so we have to remove it from the stack. */
+         orig_input_string = 0;
+
          remove_unwind_protect ();
          run_unwind_frame ("read_builtin");
          input_string[i] = '\0';       /* make sure it's terminated */
@@ -457,6 +474,7 @@ read_builtin (list)
   add_unwind_protect (xfree, input_string);
   interrupt_immediately++;
 
+  CHECK_ALRM;
   unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
 
   if (prompt && edit == 0)
@@ -472,6 +490,8 @@ read_builtin (list)
   ps2 = 0;
   for (print_ps2 = eof = retval = 0;;)
     {
+      CHECK_ALRM;
+
 #if defined (READLINE)
       if (edit)
        {
@@ -482,7 +502,9 @@ read_builtin (list)
            }
          if (rlbuf == 0)
            {
+             reading = 1;
              rlbuf = edit_line (prompt ? prompt : "", itext);
+             reading = 0;
              rlind = 0;
            }
          if (rlbuf == 0)
@@ -505,10 +527,12 @@ read_builtin (list)
          print_ps2 = 0;
        }
 
+      reading = 1;
       if (unbuffered_read)
        retval = zread (fd, &c, 1);
       else
        retval = zreadc (fd, &c);
+      reading = 0;
 
       if (retval <= 0)
        {
@@ -517,15 +541,25 @@ read_builtin (list)
          break;
        }
 
+      CHECK_ALRM;
+
 #if defined (READLINE)
        }
 #endif
 
+      CHECK_ALRM;
       if (i + 4 >= size)       /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
        {
-         input_string = (char *)xrealloc (input_string, size += 128);
-         remove_unwind_protect ();
-         add_unwind_protect (xfree, input_string);
+         char *t;
+         t = (char *)xrealloc (input_string, size += 128);
+
+         /* Only need to change unwind-protect if input_string changes */
+         if (t != input_string)
+           {
+             input_string = t;
+             remove_unwind_protect ();
+             add_unwind_protect (xfree, input_string);
+           }
        }
 
       /* If the next character is to be accepted verbatim, a backslash
@@ -559,6 +593,9 @@ read_builtin (list)
       if ((unsigned char)c == delim)
        break;
 
+      if (c == '\0' && delim != '\0')
+       continue;               /* skip NUL bytes in input */
+
       if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
        {
          saw_escape++;
@@ -567,6 +604,7 @@ read_builtin (list)
 
 add_char:
       input_string[i++] = c;
+      CHECK_ALRM;
 
 #if defined (HANDLE_MULTIBYTE)
       if (nchars > 0 && MB_CUR_MAX > 1)
@@ -582,15 +620,14 @@ add_char:
        break;
     }
   input_string[i] = '\0';
+  CHECK_ALRM;
 
-#if 1
   if (retval < 0)
     {
       builtin_error (_("read error: %d: %s"), fd, strerror (errno));
       run_unwind_frame ("read_builtin");
       return (EXECUTION_FAILURE);
     }
-#endif
 
   if (tmsec > 0 || tmusec > 0)
     reset_alarm ();
@@ -693,7 +730,7 @@ assign_vars:
        var = bind_variable ("REPLY", input_string, 0);
       VUNSETATTR (var, att_invisible);
 
-      free (input_string);
+      xfree (input_string);
       return (retval);
     }
 
@@ -737,12 +774,12 @@ assign_vars:
              xfree (t1);
            }
          else
-           var = bind_read_variable (varname, t);
+           var = bind_read_variable (varname, t ? t : "");
        }
       else
        {
          t = (char *)0;
-         var = bind_read_variable (varname, "");
+         var = bind_read_variable< (varname, "");
        }
 
       FREE (t);
@@ -798,7 +835,7 @@ assign_vars:
       xfree (t);
     }
   else
-    var = bind_read_variable (list->word->word, input_string);
+    var = bind_read_variable (list->word->word, input_string ? input_string : "");
 
   if (var)
     {
index 0e0d08641c8de950fd2882495fd1b1e776538e34..81351f8e5c4db14aa78d49a29d7bb5cff8d44326 100644 (file)
@@ -5,12 +5,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.cwru.edu
 .\"
-.\"    Last Change: Wed Dec  7 17:34:07 EST 2011
+.\"    Last Change: Wed Dec 21 20:32:29 EST 2011
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2011 December 7" "GNU Bash 4.2"
+.TH BASH 1 "2011 December 21" "GNU Bash 4.2"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -1886,6 +1886,7 @@ upon receipt of a
 An array variable from which \fBbash\fP reads the possible completions
 generated by a shell function invoked by the programmable completion
 facility (see \fBProgrammable Completion\fP below).
+Each array element contains one possible completion.
 .TP
 .B EMACS
 If \fBbash\fP finds this variable in the environment when the shell starts
@@ -5908,6 +5909,9 @@ and store the definition.
 .B call\-last\-kbd\-macro (C\-x e)
 Re-execute the last keyboard macro defined, by making the characters
 in the macro appear as if typed at the keyboard.
+.B print\-last\-kbd\-macro ()
+Print the last keyboard macro defined in a format suitable for the
+\fIinputrc\fP file.
 .PD
 .SS Miscellaneous
 .PP
@@ -6117,10 +6121,12 @@ and
 .SM
 .B COMP_CWORD
 variables are also set.
-When the function or command is invoked, the first argument is the
-name of the command whose arguments are being completed, the
-second argument is the word being completed, and the third argument
-is the word preceding the word being completed on the current command line.
+When the function or command is invoked,
+the first argument (\fB$1\fP) is the name of the command whose arguments are
+being completed,
+the second argument (\fB$2\fP) is the word being completed,
+and the third argument (\fB$3\fP) is the word preceding the word being
+completed on the current command line.
 No filtering of the generated completions against the word being completed
 is performed; the function or command has complete freedom in generating
 the matches.
@@ -6131,7 +6137,7 @@ The function may use any of the shell facilities, including the
 It must put the possible completions in the
 .SM
 .B COMPREPLY
-array variable.
+array variable, one per array element.
 .PP
 Next, any command specified with the \fB\-C\fP option is invoked
 in an environment equivalent to command substitution.
@@ -6703,7 +6709,7 @@ returns 0 unless run when job control is disabled or, when run with
 job control enabled, any specified \fIjobspec\fP was not found
 or was started without job control.
 .TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP]
+\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSVX\fP]
 .PD 0
 .TP
 \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-q\fP \fIfunction\fP] [\fB\-u\fP \fIfunction\fP] [\fB\-r\fP \fIkeyseq\fP]
@@ -6798,6 +6804,10 @@ or
 .SM
 .BR READLINE_POINT ,
 those new values will be reflected in the editing state.
+.TP
+.B \-X
+List all key sequences bound to shell commands and the associated commands
+in a format that can be reused as input.
 .PD
 .PP
 The return value is 0 unless an unrecognized option is given or an
@@ -7124,6 +7134,12 @@ used as the possible completions.
 \fB\-F\fP \fIfunction\fP
 The shell function \fIfunction\fP is executed in the current shell
 environment.
+When the function is executed,
+the first argument (\fB$1\fP) is the name of the command whose arguments are
+being completed,
+the second argument (\fB$2\fP) is the word being completed,
+and the third argument (\fB$3\fP) is the word preceding the word being
+completed on the current command line.
 When it finishes, the possible completions are retrieved from the value
 of the
 .SM
@@ -8447,8 +8463,9 @@ are supplied, the line read is assigned to the variable
 .SM
 .BR REPLY .
 The return code is zero, unless end-of-file is encountered, \fBread\fP
-times out (in which case the return code is greater than 128), or an
-invalid file descriptor is supplied as the argument to \fB\-u\fP.
+times out (in which case the return code is greater than 128),
+a variable assignment error (such as assigning to a readonly variable) occurs,
+or an invalid file descriptor is supplied as the argument to \fB\-u\fP.
 .RE
 .TP
 \fBreadonly\fP [\fB\-aAf\fP] [\fB\-p\fP] [\fIname\fP[=\fIword\fP] ...]
index 3689cac34c50f7c486453b1a3c91903489c2ac11..9e3fa80178dcadf7bea712a4bc6f064569232b23 100644 (file)
@@ -5,12 +5,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.cwru.edu
 .\"
-.\"    Last Change: Sat Nov 19 15:15:30 EST 2011
+.\"    Last Change: Wed Dec 21 20:32:29 EST 2011
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2011 November 19" "GNU Bash 4.2"
+.TH BASH 1 "2011 December 21" "GNU Bash 4.2"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -48,7 +48,7 @@ bash \- GNU Bourne-Again SHell
 .SH SYNOPSIS
 .B bash
 [options]
-[file]
+[command_string | file]
 .SH COPYRIGHT
 .if n Bash is Copyright (C) 1989-2011 by the Free Software Foundation, Inc.
 .if t Bash is Copyright \(co 1989-2011 by the Free Software Foundation, Inc.
@@ -75,13 +75,13 @@ interprets the following options when it is invoked:
 .PP
 .PD 0
 .TP 10
-.BI \-c "\| string\^"
+.B \-c
 If the
 .B \-c
-option is present, then commands are read from
-.IR string .
+option is present, then commands are read from the first non-option argument
+.IR command_string .
 If there are arguments after the
-.IR string ,
+.IR command_string ,
 they are assigned to the positional parameters, starting with
 .BR $0 .
 .TP
@@ -1981,7 +1981,7 @@ to contain no more than that number of lines by removing the oldest entries.
 The history file is also truncated to this size after
 writing it when an interactive shell exits.
 If the value is 0, the history file is truncated to zero size.
-Numeric values less than zero are treated as 0.
+Non-numeric values and numeric values less than zero inhibit truncation.
 The shell sets the default value to the value of \fBHISTSIZE\fP
 after reading any startup files.
 .TP
@@ -5908,6 +5908,9 @@ and store the definition.
 .B call\-last\-kbd\-macro (C\-x e)
 Re-execute the last keyboard macro defined, by making the characters
 in the macro appear as if typed at the keyboard.
+.B print\-last\-kbd\-macro ()
+Print the last keyboard macro defined in a format suitable for the
+\fIinputrc\fP file.
 .PD
 .SS Miscellaneous
 .PP
@@ -6117,10 +6120,12 @@ and
 .SM
 .B COMP_CWORD
 variables are also set.
-When the function or command is invoked, the first argument is the
-name of the command whose arguments are being completed, the
-second argument is the word being completed, and the third argument
-is the word preceding the word being completed on the current command line.
+When the function or command is invoked,
+the first argument (\fB$1\fP) is the name of the command whose arguments are
+being completed,
+the second argument (\fB$2\fP) is the word being completed,
+and the third argument (\fB$3\fP) is the word preceding the word being
+completed on the current command line.
 No filtering of the generated completions against the word being completed
 is performed; the function or command has complete freedom in generating
 the matches.
@@ -6131,7 +6136,7 @@ The function may use any of the shell facilities, including the
 It must put the possible completions in the
 .SM
 .B COMPREPLY
-array variable.
+array variable, one per array element.
 .PP
 Next, any command specified with the \fB\-C\fP option is invoked
 in an environment equivalent to command substitution.
@@ -6249,8 +6254,8 @@ is truncated, if necessary, to contain no more than
 the number of lines specified by the value of
 .SM
 .BR HISTFILESIZE .
-If \fBHISTFILESIZE\fP is unset, or set to a null or non-numeric value,
-the history file is not truncated.
+If \fBHISTFILESIZE\fP is unset, or set to null, a non-numeric value,
+or a numeric value less than zero, the history file is not truncated.
 When the history file is read,
 lines beginning with the history comment character followed immediately
 by a digit are interpreted as timestamps for the preceding history line.
@@ -6294,7 +6299,8 @@ to contain no more than
 lines.  If
 .SM
 .B HISTFILESIZE
-is not set, no truncation is performed.
+is unset, or set to null, a non-numeric value,
+or a numeric value less than zero, the history file is not truncated.
 .PP
 The builtin command
 .B fc
@@ -6457,7 +6463,7 @@ history list starting with
 .IR string .
 .TP
 .B !?\fIstring\fR\fB[?]\fR
-Refer to the most recent command preceding the current postition in the
+Refer to the most recent command preceding the current position in the
 history list containing
 .IR string .
 The trailing \fB?\fP may be omitted if
@@ -6702,7 +6708,7 @@ returns 0 unless run when job control is disabled or, when run with
 job control enabled, any specified \fIjobspec\fP was not found
 or was started without job control.
 .TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP]
+\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSVX\fP]
 .PD 0
 .TP
 \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-q\fP \fIfunction\fP] [\fB\-u\fP \fIfunction\fP] [\fB\-r\fP \fIkeyseq\fP]
@@ -6797,6 +6803,10 @@ or
 .SM
 .BR READLINE_POINT ,
 those new values will be reflected in the editing state.
+.TP
+.B \-X
+List all key sequences bound to shell commands and the associated commands
+in a format that can be reused as input.
 .PD
 .PP
 The return value is 0 unless an unrecognized option is given or an
@@ -6845,12 +6855,12 @@ call or \fIexpr\fP does not correspond to a valid position in the
 call stack.
 .TP
 \fBcd\fP [\fB\-L\fP|[\fB\-P\fP [\fB\-e\fP]]] [\fIdir\fP]
-Change the current directory to \fIdir\fP.  The variable
+Change the current directory to \fIdir\fP.
+if \fIdir\fP is not supplied, the value of the
 .SM
 .B HOME
-is the
-default
-.IR dir .
+shell variable is the default.
+Any additional arguments following \fIdir\fP are ignored.
 The variable
 .SM
 .B CDPATH
@@ -7123,6 +7133,12 @@ used as the possible completions.
 \fB\-F\fP \fIfunction\fP
 The shell function \fIfunction\fP is executed in the current shell
 environment.
+When the function is executed,
+the first argument (\fB$1\fP) is the name of the command whose arguments are
+being completed,
+the second argument (\fB$2\fP) is the word being completed,
+and the third argument (\fB$3\fP) is the word preceding the word being
+completed on the current command line.
 When it finishes, the possible completions are retrieved from the value
 of the
 .SM
@@ -8446,8 +8462,9 @@ are supplied, the line read is assigned to the variable
 .SM
 .BR REPLY .
 The return code is zero, unless end-of-file is encountered, \fBread\fP
-times out (in which case the return code is greater than 128), or an
-invalid file descriptor is supplied as the argument to \fB\-u\fP.
+times out (in which case the return code is greater than 128),
+a variable assignment error (such as assigning to a readonly variable) occurs,
+or an invalid file descriptor is supplied as the argument to \fB\-u\fP.
 .RE
 .TP
 \fBreadonly\fP [\fB\-aAf\fP] [\fB\-p\fP] [\fIname\fP[=\fIword\fP] ...]
index 66dae3de38df80a25fdbe7268aabdca3d1d466e6..064cf8eba0db6c5979db72e898d2a85cfaadba71 100644 (file)
@@ -3522,7 +3522,7 @@ Aliases are described in @ref{Aliases}.
 @item bind
 @btindex bind
 @example
-bind [-m @var{keymap}] [-lpsvPSV]
+bind [-m @var{keymap}] [-lpsvPSVX]
 bind [-m @var{keymap}] [-q @var{function}] [-u @var{function}] [-r @var{keyseq}]
 bind [-m @var{keymap}] -f @var{filename}
 bind [-m @var{keymap}] -x @var{keyseq:shell-command}
@@ -3604,6 +3604,10 @@ of the insertion point.
 If the executed command changes the value of @code{READLINE_LINE} or
 @code{READLINE_POINT}, those new values will be reflected in the
 editing state.
+
+@item -X
+List all key sequences bound to shell commands and the associated commands
+in a format that can be reused as input.
 @end table
 
 @noindent
@@ -4031,8 +4035,9 @@ meaning for the next character read and for line continuation.
 If no names are supplied, the line read is assigned to the
 variable @env{REPLY}.
 The return code is zero, unless end-of-file is encountered, @code{read}
-times out (in which case the return code is greater than 128), or an
-invalid file descriptor is supplied as the argument to @option{-u}.
+times out (in which case the return code is greater than 128),
+a variable assignment error (such as assigning to a readonly variable) occurs,
+or an invalid file descriptor is supplied as the argument to @option{-u}.
 
 Options, if supplied, have the following meanings:
 
@@ -5238,6 +5243,7 @@ programmable completion facilities (@pxref{Programmable Completion}).
 An array variable from which Bash reads the possible completions
 generated by a shell function invoked by the programmable completion
 facility (@pxref{Programmable Completion}).
+Each array element contains one possible completion.
 
 @item COPROC
 An array variable created to hold the file descriptors
index f3094649e7202caae96e495f74ce20dbc5ba29b5..4aaa5076dbbfb9aa042dba274e5414d70b213dc6 100644 (file)
@@ -1060,7 +1060,12 @@ will a line containing a @samp{b} anywhere in its value.
 
 Storing the regular expression in a shell variable is often a useful
 way to avoid problems with quoting characters that are special to the
-shell.  For example, the following is equivalent to the above:
+shell.
+It is sometimes difficult to specify a regular expression literally
+without using quotes, or to keep track of the quoting used by regular
+expressions while paying attention to the shell's quote removal.
+Using a shell variable to store the pattern decreases these problems.
+For example, the following is equivalent to the above:
 @example
 pattern='[[:space:]]*(a)?b'
 [[ $line =~ $pattern ]]
@@ -1069,6 +1074,9 @@ pattern='[[:space:]]*(a)?b'
 @noindent
 If you want to match a character that's special to the regular expression
 grammar, it has to be quoted to remove its special meaning.
+This means that in the pattern @samp{xxx.txt}, the @samp{.} matches any
+character in the string (its usual regular expression meaning), but in the
+pattern @samp{"xxx.txt"} it can only match a literal @samp{.}.
 Shell programmers should take special care with backslashes, since backslashes
 are used both by the shell and regular expressions to remove the special
 meaning from the following character.
@@ -3030,8 +3038,9 @@ cd [-L|[-P [-e]]] [@var{directory}]
 @end example
 
 Change the current working directory to @var{directory}.
-If @var{directory} is not given, the value of the @env{HOME} shell
-variable is used.
+If @var{directory} is not supplied, the value of the @env{HOME}
+shell variable is used.
+Any additional arguments following @var{directory} are ignored.
 If the shell variable @env{CDPATH} exists, it is used as a search path.
 If @var{directory} begins with a slash, @env{CDPATH} is not used.
 
@@ -3513,7 +3522,7 @@ Aliases are described in @ref{Aliases}.
 @item bind
 @btindex bind
 @example
-bind [-m @var{keymap}] [-lpsvPSV]
+bind [-m @var{keymap}] [-lpsvPSVX]
 bind [-m @var{keymap}] [-q @var{function}] [-u @var{function}] [-r @var{keyseq}]
 bind [-m @var{keymap}] -f @var{filename}
 bind [-m @var{keymap}] -x @var{keyseq:shell-command}
@@ -3595,6 +3604,10 @@ of the insertion point.
 If the executed command changes the value of @code{READLINE_LINE} or
 @code{READLINE_POINT}, those new values will be reflected in the
 editing state.
+
+@item -X
+List all key sequences bound to shell commands and the associated commands
+in a format that can be reused as input.
 @end table
 
 @noindent
@@ -4022,8 +4035,9 @@ meaning for the next character read and for line continuation.
 If no names are supplied, the line read is assigned to the
 variable @env{REPLY}.
 The return code is zero, unless end-of-file is encountered, @code{read}
-times out (in which case the return code is greater than 128), or an
-invalid file descriptor is supplied as the argument to @option{-u}.
+times out (in which case the return code is greater than 128),
+a variable assignment error (such as assigning to a readonly variable) occurs,
+or an invalid file descriptor is supplied as the argument to @option{-u}.
 
 Options, if supplied, have the following meanings:
 
@@ -5224,6 +5238,7 @@ The line is split into words as Readline would split it, using
 @code{COMP_WORDBREAKS} as described above.
 This variable is available only in shell functions invoked by the
 programmable completion facilities (@pxref{Programmable Completion}).
+Each array element contains one possible completion.
 
 @item COMPREPLY
 An array variable from which Bash reads the possible completions
index e102eee9a0f8c5435b710e209aabb4e617a196d5..adfaa486f01cb301a28ff736c714b7593ffcdd35 100644 (file)
@@ -1,6 +1,6 @@
 /* execute_cmd.c -- Execute a COMMAND structure. */
 
-/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -195,7 +195,7 @@ static int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *));
 
 static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *));
 
-static int execute_intern_function __P((WORD_DESC *, COMMAND *));
+static int execute_intern_function __P((WORD_DESC *, FUNCTION_DEF *));
 
 /* Set to 1 if fd 0 was the subject of redirection to a subshell.  Global
    so that reader_loop can set it to zero before executing a command. */
@@ -970,7 +970,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
     
     case cm_function_def:
       exec_result = execute_intern_function (command->value.Function_def->name,
-                                            command->value.Function_def->command);
+                                            command->value.Function_def);
       break;
 
     default:
@@ -5219,9 +5219,9 @@ shell_execve (command, args, env)
 }
 
 static int
-execute_intern_function (name, function)
+execute_intern_function (name, funcdef)
      WORD_DESC *name;
-     COMMAND *function;
+     FUNCTION_DEF *funcdef;
 {
   SHELL_VAR *var;
 
@@ -5251,7 +5251,11 @@ execute_intern_function (name, function)
       return (EXECUTION_FAILURE);
     }
 
-  bind_function (name->word, function);
+#if defined (DEBUGGER)
+  bind_function_def (name->word, funcdef);
+#endif
+
+  bind_function (name->word, funcdef->command);
   return (EXECUTION_SUCCESS);
 }
 
diff --git a/expr.c b/expr.c
index e18f8cfa18962ed606162b98e173c0eadb1d636c..a8e72a7233831862eb2fdc9a235b6bdd83db4e20 100644 (file)
--- a/expr.c
+++ b/expr.c
@@ -499,13 +499,15 @@ expassign ()
            case DIV:
            case MOD:
              if (lvalue == INTMAX_MIN && value == -1)
-               value = (op == DIV) ? 1 : 0;
+               lvalue = (op == DIV) ? INTMAX_MIN : 0;
              else
 #if HAVE_IMAXDIV
-               idiv = imaxdiv (lvalue, value);
-               lvalue = (op == DIV) ? idiv.quot : idiv.rem;
+               {
+                 idiv = imaxdiv (lvalue, value);
+                 lvalue = (op == DIV) ? idiv.quot : idiv.rem;
+               }
 #else
-               lvalue = (op == DIV) ? lvalue / value : lvalue % value;
+               lvalue = (op == DIV) ? lvalue / value : lvalue % value;
 #endif
              break;
            case PLUS:
@@ -843,8 +845,10 @@ exp2 ()
        val1 *= val2;
       else if (op == DIV || op == MOD)
 #if defined (HAVE_IMAXDIV)
-       idiv = imaxdiv (val1, val2);
-       val1 = (op == DIV) ? idiv.quot : idiv.rem;
+       {
+         idiv = imaxdiv (val1, val2);
+         val1 = (op == DIV) ? idiv.quot : idiv.rem;
+       }
 #else
        val1 = (op == DIV) ? val1 / val2 : val1 % val2;
 #endif
index 2d7e83d3b3a716811ee72800315e1bb59d16c0b6..57f7117f59347dd851614970fdb81a08397e3a8e 100644 (file)
--- a/externs.h
+++ b/externs.h
@@ -106,6 +106,8 @@ extern char *xparse_dolparen __P((char *, char *, int *, int));
 extern void reset_parser __P((void));
 extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
 
+extern int parser_in_command_position __P((void));
+
 extern void free_pushed_string_input __P((void));
 
 extern char *decode_prompt_string __P((char *));
diff --git a/externs.h~ b/externs.h~
new file mode 100644 (file)
index 0000000..2d7e83d
--- /dev/null
@@ -0,0 +1,498 @@
+/* externs.h -- extern function declarations which do not appear in their
+   own header file. */
+
+/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Bash is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* Make sure that this is included *after* config.h! */
+
+#if !defined (_EXTERNS_H_)
+#  define _EXTERNS_H_
+
+#include "stdc.h"
+
+/* Functions from expr.c. */
+extern intmax_t evalexp __P((char *, int *));
+
+/* Functions from print_cmd.c. */
+#define FUNC_MULTILINE 0x01
+#define FUNC_EXTERNAL  0x02
+
+extern char *make_command_string __P((COMMAND *));
+extern char *named_function_string __P((char *, COMMAND *, int));
+
+extern void print_command __P((COMMAND *));
+extern void print_simple_command __P((SIMPLE_COM *));
+extern void print_word_list __P((WORD_LIST *, char *));
+
+/* debugger support */
+extern void print_for_command_head __P((FOR_COM *));
+#if defined (SELECT_COMMAND)
+extern void print_select_command_head __P((SELECT_COM *));
+#endif
+extern void print_case_command_head __P((CASE_COM *));
+#if defined (DPAREN_ARITHMETIC)
+extern void print_arith_command __P((WORD_LIST *));
+#endif
+#if defined (COND_COMMAND)
+extern void print_cond_command __P((COND_COM *));
+#endif
+
+/* set -x support */
+extern void xtrace_init __P((void));
+#ifdef NEED_XTRACE_SET_DECL
+extern void xtrace_set __P((int, FILE *));
+#endif
+extern void xtrace_fdchk __P((int));
+extern void xtrace_reset __P((void));
+extern char *indirection_level_string __P((void));
+extern void xtrace_print_assignment __P((char *, char *, int, int));
+extern void xtrace_print_word_list __P((WORD_LIST *, int));
+extern void xtrace_print_for_command_head __P((FOR_COM *));
+#if defined (SELECT_COMMAND)
+extern void xtrace_print_select_command_head __P((SELECT_COM *));
+#endif
+extern void xtrace_print_case_command_head __P((CASE_COM *));
+#if defined (DPAREN_ARITHMETIC)
+extern void xtrace_print_arith_cmd __P((WORD_LIST *));
+#endif
+#if defined (COND_COMMAND)
+extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
+#endif
+
+/* Functions from shell.c. */
+extern void exit_shell __P((int)) __attribute__((__noreturn__));
+extern void sh_exit __P((int)) __attribute__((__noreturn__));
+extern void disable_priv_mode __P((void));
+extern void unbind_args __P((void));
+
+#if defined (RESTRICTED_SHELL)
+extern int shell_is_restricted __P((char *));
+extern int maybe_make_restricted __P((char *));
+#endif
+
+extern void unset_bash_input __P((int));
+extern void get_current_user_info __P((void));
+
+/* Functions from eval.c. */
+extern int reader_loop __P((void));
+extern int parse_command __P((void));
+extern int read_command __P((void));
+
+/* Functions from braces.c. */
+#if defined (BRACE_EXPANSION)
+extern char **brace_expand __P((char *));
+#endif
+
+/* Miscellaneous functions from parse.y */
+extern int yyparse __P((void));
+extern int return_EOF __P((void));
+extern char *xparse_dolparen __P((char *, char *, int *, int));
+extern void reset_parser __P((void));
+extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
+
+extern void free_pushed_string_input __P((void));
+
+extern char *decode_prompt_string __P((char *));
+
+extern int get_current_prompt_level __P((void));
+extern void set_current_prompt_level __P((int));
+
+#if defined (HISTORY)
+extern char *history_delimiting_chars __P((const char *));
+#endif
+
+/* Declarations for functions defined in locale.c */
+extern void set_default_locale __P((void));
+extern void set_default_locale_vars __P((void));
+extern int set_locale_var __P((char *, char *));
+extern int set_lang __P((char *, char *));
+extern void set_default_lang __P((void));
+extern char *get_locale_var __P((char *));
+extern char *localetrans __P((char *, int, int *));
+extern char *mk_msgstr __P((char *, int *));
+extern char *localeexpand __P((char *, int, int, int, int *));
+
+/* Declarations for functions defined in list.c. */
+extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
+extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
+extern GENERIC_LIST *list_reverse ();
+extern int list_length ();
+extern GENERIC_LIST *list_append ();
+extern GENERIC_LIST *list_remove ();
+
+/* Declarations for functions defined in stringlib.c */
+extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
+extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
+extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
+
+extern char *substring __P((const char *, int, int));
+extern char *strsub __P((char *, char *, char *, int));
+extern char *strcreplace __P((char *, int, char *, int));
+extern void strip_leading __P((char *));
+extern void strip_trailing __P((char *, int, int));
+extern void xbcopy __P((char *, char *, int));
+
+/* Functions from version.c. */
+extern char *shell_version_string __P((void));
+extern void show_shell_version __P((int));
+
+/* Functions from the bash library, lib/sh/libsh.a.  These should really
+   go into a separate include file. */
+
+/* declarations for functions defined in lib/sh/casemod.c */
+extern char *sh_modcase __P((const char *, char *, int));
+
+/* Defines for flags argument to sh_modcase.  These need to agree with what's
+   in lib/sh/casemode.c */
+#define CASE_LOWER     0x0001
+#define CASE_UPPER     0x0002
+#define CASE_CAPITALIZE        0x0004
+#define CASE_UNCAP     0x0008
+#define CASE_TOGGLE    0x0010
+#define CASE_TOGGLEALL 0x0020
+#define CASE_UPFIRST   0x0040
+#define CASE_LOWFIRST  0x0080
+
+#define CASE_USEWORDS  0x1000
+
+/* declarations for functions defined in lib/sh/clktck.c */
+extern long get_clk_tck __P((void));
+
+/* declarations for functions defined in lib/sh/clock.c */
+extern void clock_t_to_secs ();
+extern void print_clock_t ();
+
+/* Declarations for functions defined in lib/sh/dprintf.c */
+#if !defined (HAVE_DPRINTF)
+extern void dprintf __P((int, const char *, ...))  __attribute__((__format__ (printf, 2, 3)));
+#endif
+
+/* Declarations for functions defined in lib/sh/fmtulong.c */
+#define FL_PREFIX     0x01    /* add 0x, 0X, or 0 prefix as appropriate */
+#define FL_ADDBASE    0x02    /* add base# prefix to converted value */
+#define FL_HEXUPPER   0x04    /* use uppercase when converting to hex */
+#define FL_UNSIGNED   0x08    /* don't add any sign */
+
+extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
+
+/* Declarations for functions defined in lib/sh/fmtulong.c */
+#if defined (HAVE_LONG_LONG)
+extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
+#endif
+
+/* Declarations for functions defined in lib/sh/fmtumax.c */
+extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
+
+/* Declarations for functions defined in lib/sh/fnxform.c */
+extern char *fnx_fromfs __P((char *, size_t));
+extern char *fnx_tofs __P((char *, size_t));
+
+/* Declarations for functions defined in lib/sh/fpurge.c */
+
+#if defined NEED_FPURGE_DECL
+#if !HAVE_DECL_FPURGE
+
+#if HAVE_FPURGE
+#  define fpurge _bash_fpurge
+#endif
+extern int fpurge __P((FILE *stream));
+
+#endif /* HAVE_DECL_FPURGE */
+#endif /* NEED_FPURGE_DECL */
+
+/* Declarations for functions defined in lib/sh/getcwd.c */
+#if !defined (HAVE_GETCWD)
+extern char *getcwd __P((char *, size_t));
+#endif
+
+/* Declarations for functions defined in lib/sh/input_avail.c */
+extern int input_avail __P((int));
+
+/* Declarations for functions defined in lib/sh/itos.c */
+extern char *inttostr __P((intmax_t, char *, size_t));
+extern char *itos __P((intmax_t));
+extern char *uinttostr __P((uintmax_t, char *, size_t));
+extern char *uitos __P((uintmax_t));
+
+/* declarations for functions defined in lib/sh/makepath.c */
+#define MP_DOTILDE     0x01
+#define MP_DOCWD       0x02
+#define MP_RMDOT       0x04
+#define MP_IGNDOT      0x08
+
+extern char *sh_makepath __P((const char *, const char *, int));
+
+/* declarations for functions defined in lib/sh/mbscasecmp.c */
+#if !defined (HAVE_MBSCASECMP)
+extern char *mbscasecmp __P((const char *, const char *));
+#endif
+
+/* declarations for functions defined in lib/sh/mbschr.c */
+#if !defined (HAVE_MBSCHR)
+extern char *mbschr __P((const char *, int));
+#endif
+
+/* declarations for functions defined in lib/sh/mbscmp.c */
+#if !defined (HAVE_MBSCMP)
+extern char *mbscmp __P((const char *, const char *));
+#endif
+
+/* declarations for functions defined in lib/sh/netconn.c */
+extern int isnetconn __P((int));
+
+/* declarations for functions defined in lib/sh/netopen.c */
+extern int netopen __P((char *));
+
+/* Declarations for  functions defined in lib/sh/oslib.c */
+
+#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
+extern int dup2 __P((int, int));
+#endif
+
+#if !defined (HAVE_GETDTABLESIZE)
+extern int getdtablesize __P((void));
+#endif /* !HAVE_GETDTABLESIZE */
+
+#if !defined (HAVE_GETHOSTNAME)
+extern int gethostname __P((char *, int));
+#endif /* !HAVE_GETHOSTNAME */
+
+extern int getmaxgroups __P((void));
+extern long getmaxchild __P((void));
+
+/* declarations for functions defined in lib/sh/pathcanon.c */
+#define PATH_CHECKDOTDOT       0x0001
+#define PATH_CHECKEXISTS       0x0002
+#define PATH_HARDPATH          0x0004
+#define PATH_NOALLOC           0x0008
+
+extern char *sh_canonpath __P((char *, int));
+
+/* declarations for functions defined in lib/sh/pathphys.c */
+extern char *sh_physpath __P((char *, int));
+extern char *sh_realpath __P((const char *, char *));
+
+/* declarations for functions defined in lib/sh/setlinebuf.c */
+#ifdef NEED_SH_SETLINEBUF_DECL
+extern int sh_setlinebuf __P((FILE *));
+#endif
+
+/* declarations for functions defined in lib/sh/shaccess.c */
+extern int sh_eaccess __P((char *, int));
+
+/* declarations for functions defined in lib/sh/shmatch.c */
+extern int sh_regmatch __P((const char *, const char *, int));
+
+/* defines for flags argument to sh_regmatch. */
+#define SHMAT_SUBEXP           0x001   /* save subexpressions in SH_REMATCH */
+#define SHMAT_PWARN            0x002   /* print a warning message on invalid regexp */
+
+/* declarations for functions defined in lib/sh/shmbchar.c */
+extern size_t mbstrlen __P((const char *));
+extern char *mbsmbchar __P((const char *));
+
+/* declarations for functions defined in lib/sh/shquote.c */
+extern char *sh_single_quote __P((const char *));
+extern char *sh_double_quote __P((const char *));
+extern char *sh_mkdoublequoted __P((const char *, int, int));
+extern char *sh_un_double_quote __P((char *));
+extern char *sh_backslash_quote __P((char *, const char *));
+extern char *sh_backslash_quote_for_double_quotes __P((char *));
+extern int sh_contains_shell_metas __P((char *));
+
+/* declarations for functions defined in lib/sh/spell.c */
+extern int spname __P((char *, char *));
+extern char *dirspell __P((char *));
+
+/* declarations for functions defined in lib/sh/strcasecmp.c */
+#if !defined (HAVE_STRCASECMP)
+extern int strncasecmp __P((const char *, const char *, int));
+extern int strcasecmp __P((const char *, const char *));
+#endif /* HAVE_STRCASECMP */
+
+/* declarations for functions defined in lib/sh/strcasestr.c */
+#if ! HAVE_STRCASESTR
+extern char *strcasestr __P((const char *, const char *));
+#endif
+
+/* declarations for functions defined in lib/sh/strchrnul.c */
+#if ! HAVE_STRCHRNUL
+extern char *strchrnul __P((const char *, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strerror.c */
+#if !defined (HAVE_STRERROR) && !defined (strerror)
+extern char *strerror __P((int));
+#endif
+
+/* declarations for functions defined in lib/sh/strftime.c */
+#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
+extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
+#endif
+
+/* declarations for functions and structures defined in lib/sh/stringlist.c */
+
+/* This is a general-purpose argv-style array struct. */
+typedef struct _list_of_strings {
+  char **list;
+  int list_size;
+  int list_len;
+} STRINGLIST;
+
+typedef int sh_strlist_map_func_t __P((char *));
+
+extern STRINGLIST *strlist_create __P((int));
+extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
+extern void strlist_flush __P((STRINGLIST *));
+extern void strlist_dispose __P((STRINGLIST *));
+extern int strlist_remove __P((STRINGLIST *, char *));
+extern STRINGLIST *strlist_copy __P((STRINGLIST *));
+extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
+extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
+extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
+extern void strlist_print __P((STRINGLIST *, char *));
+extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
+extern void strlist_sort __P((STRINGLIST *));
+
+/* declarations for functions defined in lib/sh/stringvec.c */
+
+extern char **strvec_create __P((int));
+extern char **strvec_resize __P((char **, int));
+extern void strvec_flush __P((char **));
+extern void strvec_dispose __P((char **));
+extern int strvec_remove __P((char **, char *));
+extern int strvec_len __P((char **));
+extern int strvec_search __P((char **, char *));
+extern char **strvec_copy __P((char **));
+extern int strvec_strcmp __P((char **, char **));
+extern void strvec_sort __P((char **));
+
+extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
+extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
+
+/* declarations for functions defined in lib/sh/strnlen.c */
+#if !defined (HAVE_STRNLEN)
+extern size_t strnlen __P((const char *, size_t));
+#endif
+
+/* declarations for functions defined in lib/sh/strpbrk.c */
+#if !defined (HAVE_STRPBRK)
+extern char *strpbrk __P((const char *, const char *));
+#endif
+
+/* declarations for functions defined in lib/sh/strtod.c */
+#if !defined (HAVE_STRTOD)
+extern double strtod __P((const char *, char **));
+#endif
+
+/* declarations for functions defined in lib/sh/strtol.c */
+#if !HAVE_DECL_STRTOL
+extern long strtol __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtoll.c */
+#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL
+extern long long strtoll __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtoul.c */
+#if !HAVE_DECL_STRTOUL
+extern unsigned long strtoul __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtoull.c */
+#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL
+extern unsigned long long strtoull __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strimax.c */
+#if !HAVE_DECL_STRTOIMAX
+extern intmax_t strtoimax __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strumax.c */
+#if !HAVE_DECL_STRTOUMAX
+extern uintmax_t strtoumax __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtrans.c */
+extern char *ansicstr __P((char *, int, int, int *, int *));
+extern char *ansic_quote __P((char *, int, int *));
+extern int ansic_shouldquote __P((const char *));
+extern char *ansiexpand __P((char *, int, int, int *));
+
+/* declarations for functions defined in lib/sh/timeval.c.  No prototypes
+   so we don't have to count on having a definition of struct timeval in
+   scope when this file is included. */
+extern void timeval_to_secs ();
+extern void print_timeval ();
+
+/* declarations for functions defined in lib/sh/tmpfile.c */
+#define MT_USETMPDIR           0x0001
+#define MT_READWRITE           0x0002
+#define MT_USERANDOM           0x0004
+
+extern char *sh_mktmpname __P((char *, int));
+extern int sh_mktmpfd __P((char *, int, char **));
+/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
+
+/* declarations for functions defined in lib/sh/uconvert.c */
+extern int uconvert __P((char *, long *, long *));
+
+/* declarations for functions defined in lib/sh/ufuncs.c */
+extern unsigned int falarm __P((unsigned int, unsigned int));
+extern unsigned int fsleep __P((unsigned int, unsigned int));
+
+/* declarations for functions defined in lib/sh/unicode.c */
+extern int u32cconv __P((unsigned long, char *));
+
+/* declarations for functions defined in lib/sh/winsize.c */
+extern void get_new_window_size __P((int, int *, int *));
+
+/* declarations for functions defined in lib/sh/zcatfd.c */
+extern int zcatfd __P((int, int, char *));
+
+/* declarations for functions defined in lib/sh/zgetline.c */
+extern ssize_t zgetline __P((int, char **, size_t *, int));
+
+/* declarations for functions defined in lib/sh/zmapfd.c */
+extern int zmapfd __P((int, char **, char *));
+
+/* declarations for functions defined in lib/sh/zread.c */
+extern ssize_t zread __P((int, char *, size_t));
+extern ssize_t zreadretry __P((int, char *, size_t));
+extern ssize_t zreadintr __P((int, char *, size_t));
+extern ssize_t zreadc __P((int, char *));
+extern ssize_t zreadcintr __P((int, char *));
+extern void zreset __P((void));
+extern void zsyncfd __P((int));
+
+/* declarations for functions defined in lib/sh/zwrite.c */
+extern int zwrite __P((int, char *, size_t));
+
+/* declarations for functions defined in lib/glob/gmisc.c */
+extern int match_pattern_char __P((char *, char *));
+extern int umatchlen __P((char *, size_t));
+
+#if defined (HANDLE_MULTIBYTE)
+extern int match_pattern_wchar __P((wchar_t *, wchar_t *));
+extern int wmatchlen __P((wchar_t *, size_t));
+#endif
+
+#endif /* _EXTERNS_H_ */
index 787104613e2eaaa7d3de1ad34fad42d725f820d7..a1a3a5a53b4a0d135dcea03934d6fd40e53505d5 100644 (file)
@@ -571,6 +571,40 @@ rl_translate_keyseq (seq, array, len)
   return (0);
 }
 
+static int
+_rl_isescape (c)
+     int c;
+{
+  switch (c)
+    {
+    case '\007':
+    case '\b':
+    case '\f':
+    case '\n':
+    case '\r':
+    case TAB:
+    case 0x0b:  return (1);
+    default: return (0);
+    }
+}
+
+static int
+_rl_escchar (c)
+     int c;
+{
+  switch (c)
+    {
+    case '\007':  return ('a');
+    case '\b':  return ('b');
+    case '\f':  return ('f');
+    case '\n':  return ('n');
+    case '\r':  return ('r');
+    case TAB:  return ('t');
+    case 0x0b:  return ('v');
+    default: return (c);
+    }
+}
+
 char *
 rl_untranslate_keyseq (seq)
      int seq;
@@ -622,9 +656,10 @@ rl_untranslate_keyseq (seq)
   return kseq;
 }
 
-static char *
-_rl_untranslate_macro_value (seq)
+char *
+_rl_untranslate_macro_value (seq, use_escapes)
      char *seq;
+     int use_escapes;
 {
   char *ret, *r, *s;
   int c;
@@ -648,9 +683,14 @@ _rl_untranslate_macro_value (seq)
       else if (CTRL_CHAR (c))
        {
          *r++ = '\\';
-         *r++ = 'C';
-         *r++ = '-';
-         c = _rl_to_lower (UNCTRL (c));
+         if (use_escapes && _rl_isescape (c))
+           c = _rl_escchar (c);
+         else
+           {
+             *r++ = 'C';
+             *r++ = '-';
+             c = _rl_to_lower (UNCTRL (c));
+           }
        }
       else if (c == RUBOUT)
        {
@@ -2215,7 +2255,7 @@ _rl_macro_dumper_internal (print_readably, map, prefix)
        {
        case ISMACR:
          keyname = _rl_get_keyname (key);
-         out = _rl_untranslate_macro_value ((char *)map[key].function);
+         out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
 
          if (print_readably)
            fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
@@ -2327,7 +2367,7 @@ _rl_get_string_variable_value (name)
     {
       if (_rl_isearch_terminators == 0)
        return 0;
-      ret = _rl_untranslate_macro_value (_rl_isearch_terminators);
+      ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0);
       if (ret)
        {
          strncpy (numbuf, ret, sizeof (numbuf) - 1);
diff --git a/lib/readline/bind.c~ b/lib/readline/bind.c~
new file mode 100644 (file)
index 0000000..89bf446
--- /dev/null
@@ -0,0 +1,2448 @@
+/* bind.c -- key binding and startup file support for the readline library. */
+
+/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library (Readline), a library
+   for reading lines of text with interactive input and history editing.
+
+   Readline is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Readline is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define READLINE_LIBRARY
+
+#if defined (__TANDEM)
+#  include <floss.h>
+#endif
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+/* Variables exported by this file. */
+Keymap rl_binding_keymap;
+
+static int _rl_skip_to_delim PARAMS((char *, int, int));
+
+static char *_rl_read_file PARAMS((char *, size_t *));
+static void _rl_init_file_error PARAMS((const char *));
+static int _rl_read_init_file PARAMS((const char *, int));
+static int glean_key_from_name PARAMS((char *));
+
+static int find_boolean_var PARAMS((const char *));
+static int find_string_var PARAMS((const char *));
+
+static char *_rl_get_string_variable_value PARAMS((const char *));
+static int substring_member_of_array PARAMS((const char *, const char * const *));
+
+static int currently_reading_init_file;
+
+/* used only in this file */
+static int _rl_prefer_visible_bell = 1;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Binding keys                                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* rl_add_defun (char *name, rl_command_func_t *function, int key)
+   Add NAME to the list of named functions.  Make FUNCTION be the function
+   that gets called.  If KEY is not -1, then bind it. */
+int
+rl_add_defun (name, function, key)
+     const char *name;
+     rl_command_func_t *function;
+     int key;
+{
+  if (key != -1)
+    rl_bind_key (key, function);
+  rl_add_funmap_entry (name, function);
+  return 0;
+}
+
+/* Bind KEY to FUNCTION.  Returns non-zero if KEY is out of range. */
+int
+rl_bind_key (key, function)
+     int key;
+     rl_command_func_t *function;
+{
+  if (key < 0)
+    return (key);
+
+  if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+    {
+      if (_rl_keymap[ESC].type == ISKMAP)
+       {
+         Keymap escmap;
+
+         escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
+         key = UNMETA (key);
+         escmap[key].type = ISFUNC;
+         escmap[key].function = function;
+         return (0);
+       }
+      return (key);
+    }
+
+  _rl_keymap[key].type = ISFUNC;
+  _rl_keymap[key].function = function;
+  rl_binding_keymap = _rl_keymap;
+  return (0);
+}
+
+/* Bind KEY to FUNCTION in MAP.  Returns non-zero in case of invalid
+   KEY. */
+int
+rl_bind_key_in_map (key, function, map)
+     int key;
+     rl_command_func_t *function;
+     Keymap map;
+{
+  int result;
+  Keymap oldmap;
+
+  oldmap = _rl_keymap;
+  _rl_keymap = map;
+  result = rl_bind_key (key, function);
+  _rl_keymap = oldmap;
+  return (result);
+}
+
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
+   now, this is always used to attempt to bind the arrow keys, hence the
+   check for rl_vi_movement_mode. */
+int
+rl_bind_key_if_unbound_in_map (key, default_func, kmap)
+     int key;
+     rl_command_func_t *default_func;
+     Keymap kmap;
+{
+  char keyseq[2];
+
+  keyseq[0] = (unsigned char)key;
+  keyseq[1] = '\0';
+  return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
+}
+
+int
+rl_bind_key_if_unbound (key, default_func)
+     int key;
+     rl_command_func_t *default_func;
+{
+  char keyseq[2];
+
+  keyseq[0] = (unsigned char)key;
+  keyseq[1] = '\0';
+  return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
+}
+
+/* Make KEY do nothing in the currently selected keymap.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key (key)
+     int key;
+{
+  return (rl_bind_key (key, (rl_command_func_t *)NULL));
+}
+
+/* Make KEY do nothing in MAP.
+   Returns non-zero in case of error. */
+int
+rl_unbind_key_in_map (key, map)
+     int key;
+     Keymap map;
+{
+  return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map));
+}
+
+/* Unbind all keys bound to FUNCTION in MAP. */
+int
+rl_unbind_function_in_map (func, map)
+     rl_command_func_t *func;
+     Keymap map;
+{
+  register int i, rval;
+
+  for (i = rval = 0; i < KEYMAP_SIZE; i++)
+    {
+      if (map[i].type == ISFUNC && map[i].function == func)
+       {
+         map[i].function = (rl_command_func_t *)NULL;
+         rval = 1;
+       }
+    }
+  return rval;
+}
+
+int
+rl_unbind_command_in_map (command, map)
+     const char *command;
+     Keymap map;
+{
+  rl_command_func_t *func;
+
+  func = rl_named_function (command);
+  if (func == 0)
+    return 0;
+  return (rl_unbind_function_in_map (func, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   FUNCTION, starting in the current keymap.  This makes new
+   keymaps as necessary. */
+int
+rl_bind_keyseq (keyseq, function)
+     const char *keyseq;
+     rl_command_func_t *function;
+{
+  return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   FUNCTION.  This makes new keymaps as necessary.  The initial
+   place to do bindings is in MAP. */
+int
+rl_bind_keyseq_in_map (keyseq, function, map)
+     const char *keyseq;
+     rl_command_func_t *function;
+     Keymap map;
+{
+  return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
+}
+
+/* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */
+int
+rl_set_key (keyseq, function, map)
+     const char *keyseq;
+     rl_command_func_t *function;
+     Keymap map;
+{
+  return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
+}
+
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound.  Right
+   now, this is always used to attempt to bind the arrow keys, hence the
+   check for rl_vi_movement_mode. */
+int
+rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)
+     const char *keyseq;
+     rl_command_func_t *default_func;
+     Keymap kmap;
+{
+  rl_command_func_t *func;
+
+  if (keyseq)
+    {
+      func = rl_function_of_keyseq (keyseq, kmap, (int *)NULL);
+#if defined (VI_MODE)
+      if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
+#else
+      if (!func || func == rl_do_lowercase_version)
+#endif
+       return (rl_bind_keyseq_in_map (keyseq, default_func, kmap));
+      else
+       return 1;
+    }
+  return 0;
+}
+
+int
+rl_bind_keyseq_if_unbound (keyseq, default_func)
+     const char *keyseq;
+     rl_command_func_t *default_func;
+{
+  return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the string of characters MACRO.  This makes new keymaps as
+   necessary.  The initial place to do bindings is in MAP. */
+int
+rl_macro_bind (keyseq, macro, map)
+     const char *keyseq, *macro;
+     Keymap map;
+{
+  char *macro_keys;
+  int macro_keys_len;
+
+  macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
+
+  if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
+    {
+      xfree (macro_keys);
+      return -1;
+    }
+  rl_generic_bind (ISMACR, keyseq, macro_keys, map);
+  return 0;
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+   the arbitrary pointer DATA.  TYPE says what kind of data is
+   pointed to by DATA, right now this can be a function (ISFUNC),
+   a macro (ISMACR), or a keymap (ISKMAP).  This makes new keymaps
+   as necessary.  The initial place to do bindings is in MAP. */
+int
+rl_generic_bind (type, keyseq, data, map)
+     int type;
+     const char *keyseq;
+     char *data;
+     Keymap map;
+{
+  char *keys;
+  int keys_len;
+  register int i;
+  KEYMAP_ENTRY k;
+
+  k.function = 0;
+
+  /* If no keys to bind to, exit right away. */
+  if (keyseq == 0 || *keyseq == 0)
+    {
+      if (type == ISMACR)
+       xfree (data);
+      return -1;
+    }
+
+  keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
+
+  /* Translate the ASCII representation of KEYSEQ into an array of
+     characters.  Stuff the characters into KEYS, and the length of
+     KEYS into KEYS_LEN. */
+  if (rl_translate_keyseq (keyseq, keys, &keys_len))
+    {
+      xfree (keys);
+      return -1;
+    }
+
+  /* Bind keys, making new keymaps as necessary. */
+  for (i = 0; i < keys_len; i++)
+    {
+      unsigned char uc = keys[i];
+      int ic;
+
+      ic = uc;
+      if (ic < 0 || ic >= KEYMAP_SIZE)
+        {
+          xfree (keys);
+         return -1;
+        }
+
+      if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
+       {
+         ic = UNMETA (ic);
+         if (map[ESC].type == ISKMAP)
+           map = FUNCTION_TO_KEYMAP (map, ESC);
+       }
+
+      if ((i + 1) < keys_len)
+       {
+         if (map[ic].type != ISKMAP)
+           {
+             /* We allow subsequences of keys.  If a keymap is being
+                created that will `shadow' an existing function or macro
+                key binding, we save that keybinding into the ANYOTHERKEY
+                index in the new map.  The dispatch code will look there
+                to find the function to execute if the subsequence is not
+                matched.  ANYOTHERKEY was chosen to be greater than
+                UCHAR_MAX. */
+             k = map[ic];
+
+             map[ic].type = ISKMAP;
+             map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
+           }
+         map = FUNCTION_TO_KEYMAP (map, ic);
+         /* The dispatch code will return this function if no matching
+            key sequence is found in the keymap.  This (with a little
+            help from the dispatch code in readline.c) allows `a' to be
+            mapped to something, `abc' to be mapped to something else,
+            and the function bound  to `a' to be executed when the user
+            types `abx', leaving `bx' in the input queue. */
+         if (k.function && ((k.type == ISFUNC && k.function != rl_do_lowercase_version) || k.type == ISMACR))
+           {
+             map[ANYOTHERKEY] = k;
+             k.function = 0;
+           }
+       }
+      else
+       {
+         if (map[ic].type == ISMACR)
+           xfree ((char *)map[ic].function);
+         else if (map[ic].type == ISKMAP)
+           {
+             map = FUNCTION_TO_KEYMAP (map, ic);
+             ic = ANYOTHERKEY;
+             /* If we're trying to override a keymap with a null function
+                (e.g., trying to unbind it), we can't use a null pointer
+                here because that's indistinguishable from having not been
+                overridden.  We use a special bindable function that does
+                nothing. */
+             if (type == ISFUNC && data == 0)
+               data = (char *)_rl_null_function;
+           }
+
+         map[ic].function = KEYMAP_TO_FUNCTION (data);
+         map[ic].type = type;
+       }
+
+      rl_binding_keymap = map;
+    }
+  xfree (keys);
+  return 0;
+}
+
+/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
+   an array of characters.  LEN gets the final length of ARRAY.  Return
+   non-zero if there was an error parsing SEQ. */
+int
+rl_translate_keyseq (seq, array, len)
+     const char *seq;
+     char *array;
+     int *len;
+{
+  register int i, c, l, temp;
+
+  for (i = l = 0; c = seq[i]; i++)
+    {
+      if (c == '\\')
+       {
+         c = seq[++i];
+
+         if (c == 0)
+           break;
+
+         /* Handle \C- and \M- prefixes. */
+         if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
+           {
+             /* Handle special case of backwards define. */
+             if (strncmp (&seq[i], "C-\\M-", 5) == 0)
+               {
+                 array[l++] = ESC;     /* ESC is meta-prefix */
+                 i += 5;
+                 array[l++] = CTRL (_rl_to_upper (seq[i]));
+                 if (seq[i] == '\0')
+                   i--;
+               }
+             else if (c == 'M')
+               {
+                 i++;          /* seq[i] == '-' */
+                 /* XXX - obey convert-meta setting */
+                 if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP)
+                   array[l++] = ESC;   /* ESC is meta-prefix */
+                 else if (seq[i+1] == '\\' && seq[i+2] == 'C' && seq[i+3] == '-')
+                   {
+                     i += 4;
+                     temp = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
+                     array[l++] = META (temp);
+                   }
+                 else
+                   {
+                     /* This doesn't yet handle things like \M-\a, which may
+                        or may not have any reasonable meaning.  You're
+                        probably better off using straight octal or hex. */
+                     i++;
+                     array[l++] = META (seq[i]);
+                   }
+               }
+             else if (c == 'C')
+               {
+                 i += 2;
+                 /* Special hack for C-?... */
+                 array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
+               }
+             continue;
+           }         
+
+         /* Translate other backslash-escaped characters.  These are the
+            same escape sequences that bash's `echo' and `printf' builtins
+            handle, with the addition of \d -> RUBOUT.  A backslash
+            preceding a character that is not special is stripped. */
+         switch (c)
+           {
+           case 'a':
+             array[l++] = '\007';
+             break;
+           case 'b':
+             array[l++] = '\b';
+             break;
+           case 'd':
+             array[l++] = RUBOUT;      /* readline-specific */
+             break;
+           case 'e':
+             array[l++] = ESC;
+             break;
+           case 'f':
+             array[l++] = '\f';
+             break;
+           case 'n':
+             array[l++] = NEWLINE;
+             break;
+           case 'r':
+             array[l++] = RETURN;
+             break;
+           case 't':
+             array[l++] = TAB;
+             break;
+           case 'v':
+             array[l++] = 0x0B;
+             break;
+           case '\\':
+             array[l++] = '\\';
+             break;
+           case '0': case '1': case '2': case '3':
+           case '4': case '5': case '6': case '7':
+             i++;
+             for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++)
+               c = (c * 8) + OCTVALUE (seq[i]);
+             i--;      /* auto-increment in for loop */
+             array[l++] = c & largest_char;
+             break;
+           case 'x':
+             i++;
+             for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++)
+               c = (c * 16) + HEXVALUE (seq[i]);
+             if (temp == 2)
+               c = 'x';
+             i--;      /* auto-increment in for loop */
+             array[l++] = c & largest_char;
+             break;
+           default:    /* backslashes before non-special chars just add the char */
+             array[l++] = c;
+             break;    /* the backslash is stripped */
+           }
+         continue;
+       }
+
+      array[l++] = c;
+    }
+
+  *len = l;
+  array[l] = '\0';
+  return (0);
+}
+
+static int
+_rl_isescape (c)
+     int c;
+{
+  switch (c)
+    {
+    case '\007':
+    case '\b':
+    case '\f':
+    case '\n':
+    case '\r':
+    case TAB:
+    case 0x0b:  return (1);
+    default: return (0);
+    }
+}
+
+static int
+_rl_escchar (c)
+     int c;
+{
+  switch (c)
+    {
+    case '\007':  return ('a');
+    case '\b':  return ('b');
+    case '\f':  return ('f');
+    case '\n':  return ('n');
+    case '\r':  return ('r');
+    case TAB:  return ('t');
+    case 0x0b:  return ('v');
+    default: return (c);
+    }
+}
+
+char *
+rl_untranslate_keyseq (seq)
+     int seq;
+{
+  static char kseq[16];
+  int i, c;
+
+  i = 0;
+  c = seq;
+  if (META_CHAR (c))
+    {
+      kseq[i++] = '\\';
+      kseq[i++] = 'M';
+      kseq[i++] = '-';
+      c = UNMETA (c);
+    }
+  else if (c == ESC)
+    {
+      kseq[i++] = '\\';
+      c = 'e';
+    }
+  else if (CTRL_CHAR (c))
+    {
+      kseq[i++] = '\\';
+      kseq[i++] = 'C';
+      kseq[i++] = '-';
+      c = _rl_to_lower (UNCTRL (c));
+    }
+  else if (c == RUBOUT)
+    {
+      kseq[i++] = '\\';
+      kseq[i++] = 'C';
+      kseq[i++] = '-';
+      c = '?';
+    }
+
+  if (c == ESC)
+    {
+      kseq[i++] = '\\';
+      c = 'e';
+    }
+  else if (c == '\\' || c == '"')
+    {
+      kseq[i++] = '\\';
+    }
+
+  kseq[i++] = (unsigned char) c;
+  kseq[i] = '\0';
+  return kseq;
+}
+
+static char *
+_rl_untranslate_macro_value (seq, use_escapes)
+     char *seq;
+     int use_escapes;
+{
+  char *ret, *r, *s;
+  int c;
+
+  r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
+  for (s = seq; *s; s++)
+    {
+      c = *s;
+      if (META_CHAR (c))
+       {
+         *r++ = '\\';
+         *r++ = 'M';
+         *r++ = '-';
+         c = UNMETA (c);
+       }
+      else if (c == ESC)
+       {
+         *r++ = '\\';
+         c = 'e';
+       }
+      else if (CTRL_CHAR (c))
+       {
+         *r++ = '\\';
+         if (use_escapes && _rl_isescape (c))
+           c = _rl_escchar (c);
+         else
+           {
+             *r++ = 'C';
+             *r++ = '-';
+             c = _rl_to_lower (UNCTRL (c));
+           }
+       }
+      else if (c == RUBOUT)
+       {
+         *r++ = '\\';
+         *r++ = 'C';
+         *r++ = '-';
+         c = '?';
+       }
+
+      if (c == ESC)
+       {
+         *r++ = '\\';
+         c = 'e';
+       }
+      else if (c == '\\' || c == '"')
+       *r++ = '\\';
+
+      *r++ = (unsigned char)c;
+    }
+  *r = '\0';
+  return ret;
+}
+
+/* Return a pointer to the function that STRING represents.
+   If STRING doesn't have a matching function, then a NULL pointer
+   is returned. */
+rl_command_func_t *
+rl_named_function (string)
+     const char *string;
+{
+  register int i;
+
+  rl_initialize_funmap ();
+
+  for (i = 0; funmap[i]; i++)
+    if (_rl_stricmp (funmap[i]->name, string) == 0)
+      return (funmap[i]->function);
+  return ((rl_command_func_t *)NULL);
+}
+
+/* Return the function (or macro) definition which would be invoked via
+   KEYSEQ if executed in MAP.  If MAP is NULL, then the current keymap is
+   used.  TYPE, if non-NULL, is a pointer to an int which will receive the
+   type of the object pointed to.  One of ISFUNC (function), ISKMAP (keymap),
+   or ISMACR (macro). */
+rl_command_func_t *
+rl_function_of_keyseq (keyseq, map, type)
+     const char *keyseq;
+     Keymap map;
+     int *type;
+{
+  register int i;
+
+  if (map == 0)
+    map = _rl_keymap;
+
+  for (i = 0; keyseq && keyseq[i]; i++)
+    {
+      unsigned char ic = keyseq[i];
+
+      if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
+       {
+         if (map[ESC].type == ISKMAP)
+           {
+             map = FUNCTION_TO_KEYMAP (map, ESC);
+             ic = UNMETA (ic);
+           }
+         /* XXX - should we just return NULL here, since this obviously
+            doesn't match? */
+         else
+           {
+             if (type)
+               *type = map[ESC].type;
+
+             return (map[ESC].function);
+           }
+       }
+
+      if (map[ic].type == ISKMAP)
+       {
+         /* If this is the last key in the key sequence, return the
+            map. */
+         if (keyseq[i + 1] == '\0')
+           {
+             if (type)
+               *type = ISKMAP;
+
+             return (map[ic].function);
+           }
+         else
+           map = FUNCTION_TO_KEYMAP (map, ic);
+       }
+      /* If we're not at the end of the key sequence, and the current key
+        is bound to something other than a keymap, then the entire key
+        sequence is not bound. */
+      else if (map[ic].type != ISKMAP && keyseq[i+1])
+       return ((rl_command_func_t *)NULL);
+      else     /* map[ic].type != ISKMAP && keyseq[i+1] == 0 */
+       {
+         if (type)
+           *type = map[ic].type;
+
+         return (map[ic].function);
+       }
+    }
+  return ((rl_command_func_t *) NULL);
+}
+
+/* The last key bindings file read. */
+static char *last_readline_init_file = (char *)NULL;
+
+/* The file we're currently reading key bindings from. */
+static const char *current_readline_init_file;
+static int current_readline_init_include_level;
+static int current_readline_init_lineno;
+
+/* Read FILENAME into a locally-allocated buffer and return the buffer.
+   The size of the buffer is returned in *SIZEP.  Returns NULL if any
+   errors were encountered. */
+static char *
+_rl_read_file (filename, sizep)
+     char *filename;
+     size_t *sizep;
+{
+  struct stat finfo;
+  size_t file_size;
+  char *buffer;
+  int i, file;
+
+  if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
+    return ((char *)NULL);
+
+  file_size = (size_t)finfo.st_size;
+
+  /* check for overflow on very large files */
+  if (file_size != finfo.st_size || file_size + 1 < file_size)
+    {
+      if (file >= 0)
+       close (file);
+#if defined (EFBIG)
+      errno = EFBIG;
+#endif
+      return ((char *)NULL);
+    }
+
+  /* Read the file into BUFFER. */
+  buffer = (char *)xmalloc (file_size + 1);
+  i = read (file, buffer, file_size);
+  close (file);
+
+  if (i < 0)
+    {
+      xfree (buffer);
+      return ((char *)NULL);
+    }
+
+  RL_CHECK_SIGNALS ();
+
+  buffer[i] = '\0';
+  if (sizep)
+    *sizep = i;
+
+  return (buffer);
+}
+
+/* Re-read the current keybindings file. */
+int
+rl_re_read_init_file (count, ignore)
+     int count, ignore;
+{
+  int r;
+  r = rl_read_init_file ((const char *)NULL);
+  rl_set_keymap_from_edit_mode ();
+  return r;
+}
+
+/* Do key bindings from a file.  If FILENAME is NULL it defaults
+   to the first non-null filename from this list:
+     1. the filename used for the previous call
+     2. the value of the shell variable `INPUTRC'
+     3. ~/.inputrc
+     4. /etc/inputrc
+   If the file existed and could be opened and read, 0 is returned,
+   otherwise errno is returned. */
+int
+rl_read_init_file (filename)
+     const char *filename;
+{
+  /* Default the filename. */
+  if (filename == 0)
+    filename = last_readline_init_file;
+  if (filename == 0)
+    filename = sh_get_env_value ("INPUTRC");
+  if (filename == 0 || *filename == 0)
+    {
+      filename = DEFAULT_INPUTRC;
+      /* Try to read DEFAULT_INPUTRC; fall back to SYS_INPUTRC on failure */
+      if (_rl_read_init_file (filename, 0) == 0)
+       return 0;
+      filename = SYS_INPUTRC;
+    }
+
+#if defined (__MSDOS__)
+  if (_rl_read_init_file (filename, 0) == 0)
+    return 0;
+  filename = "~/_inputrc";
+#endif
+  return (_rl_read_init_file (filename, 0));
+}
+
+static int
+_rl_read_init_file (filename, include_level)
+     const char *filename;
+     int include_level;
+{
+  register int i;
+  char *buffer, *openname, *line, *end;
+  size_t file_size;
+
+  current_readline_init_file = filename;
+  current_readline_init_include_level = include_level;
+
+  openname = tilde_expand (filename);
+  buffer = _rl_read_file (openname, &file_size);
+  xfree (openname);
+
+  RL_CHECK_SIGNALS ();
+  if (buffer == 0)
+    return (errno);
+  
+  if (include_level == 0 && filename != last_readline_init_file)
+    {
+      FREE (last_readline_init_file);
+      last_readline_init_file = savestring (filename);
+    }
+
+  currently_reading_init_file = 1;
+
+  /* Loop over the lines in the file.  Lines that start with `#' are
+     comments; all other lines are commands for readline initialization. */
+  current_readline_init_lineno = 1;
+  line = buffer;
+  end = buffer + file_size;
+  while (line < end)
+    {
+      /* Find the end of this line. */
+      for (i = 0; line + i != end && line[i] != '\n'; i++);
+
+#if defined (__CYGWIN__)
+      /* ``Be liberal in what you accept.'' */
+      if (line[i] == '\n' && line[i-1] == '\r')
+       line[i - 1] = '\0';
+#endif
+
+      /* Mark end of line. */
+      line[i] = '\0';
+
+      /* Skip leading whitespace. */
+      while (*line && whitespace (*line))
+        {
+         line++;
+         i--;
+        }
+
+      /* If the line is not a comment, then parse it. */
+      if (*line && *line != '#')
+       rl_parse_and_bind (line);
+
+      /* Move to the next line. */
+      line += i + 1;
+      current_readline_init_lineno++;
+    }
+
+  xfree (buffer);
+  currently_reading_init_file = 0;
+  return (0);
+}
+
+static void
+_rl_init_file_error (msg)
+     const char *msg;
+{
+  if (currently_reading_init_file)
+    _rl_errmsg ("%s: line %d: %s\n", current_readline_init_file,
+                    current_readline_init_lineno, msg);
+  else
+    _rl_errmsg ("%s", msg);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Parser Directives                           */
+/*                                                                 */
+/* **************************************************************** */
+
+typedef int _rl_parser_func_t PARAMS((char *));
+
+/* Things that mean `Control'. */
+const char * const _rl_possible_control_prefixes[] = {
+  "Control-", "C-", "CTRL-", (const char *)NULL
+};
+
+const char * const _rl_possible_meta_prefixes[] = {
+  "Meta", "M-", (const char *)NULL
+};
+
+/* Conditionals. */
+
+/* Calling programs set this to have their argv[0]. */
+const char *rl_readline_name = "other";
+
+/* Stack of previous values of parsing_conditionalized_out. */
+static unsigned char *if_stack = (unsigned char *)NULL;
+static int if_stack_depth;
+static int if_stack_size;
+
+/* Push _rl_parsing_conditionalized_out, and set parser state based
+   on ARGS. */
+static int
+parser_if (args)
+     char *args;
+{
+  register int i;
+
+  /* Push parser state. */
+  if (if_stack_depth + 1 >= if_stack_size)
+    {
+      if (!if_stack)
+       if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
+      else
+       if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
+    }
+  if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
+
+  /* If parsing is turned off, then nothing can turn it back on except
+     for finding the matching endif.  In that case, return right now. */
+  if (_rl_parsing_conditionalized_out)
+    return 0;
+
+  /* Isolate first argument. */
+  for (i = 0; args[i] && !whitespace (args[i]); i++);
+
+  if (args[i])
+    args[i++] = '\0';
+
+  /* Handle "$if term=foo" and "$if mode=emacs" constructs.  If this
+     isn't term=foo, or mode=emacs, then check to see if the first
+     word in ARGS is the same as the value stored in rl_readline_name. */
+  if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
+    {
+      char *tem, *tname;
+
+      /* Terminals like "aaa-60" are equivalent to "aaa". */
+      tname = savestring (rl_terminal_name);
+      tem = strchr (tname, '-');
+      if (tem)
+       *tem = '\0';
+
+      /* Test the `long' and `short' forms of the terminal name so that
+        if someone has a `sun-cmd' and does not want to have bindings
+        that will be executed if the terminal is a `sun', they can put
+        `$if term=sun-cmd' into their .inputrc. */
+      _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
+                                       _rl_stricmp (args + 5, rl_terminal_name);
+      xfree (tname);
+    }
+#if defined (VI_MODE)
+  else if (_rl_strnicmp (args, "mode=", 5) == 0)
+    {
+      int mode;
+
+      if (_rl_stricmp (args + 5, "emacs") == 0)
+       mode = emacs_mode;
+      else if (_rl_stricmp (args + 5, "vi") == 0)
+       mode = vi_mode;
+      else
+       mode = no_mode;
+
+      _rl_parsing_conditionalized_out = mode != rl_editing_mode;
+    }
+#endif /* VI_MODE */
+  /* Check to see if the first word in ARGS is the same as the
+     value stored in rl_readline_name. */
+  else if (_rl_stricmp (args, rl_readline_name) == 0)
+    _rl_parsing_conditionalized_out = 0;
+  else
+    _rl_parsing_conditionalized_out = 1;
+  return 0;
+}
+
+/* Invert the current parser state if there is anything on the stack. */
+static int
+parser_else (args)
+     char *args;
+{
+  register int i;
+
+  if (if_stack_depth == 0)
+    {
+      _rl_init_file_error ("$else found without matching $if");
+      return 0;
+    }
+
+#if 0
+  /* Check the previous (n - 1) levels of the stack to make sure that
+     we haven't previously turned off parsing. */
+  for (i = 0; i < if_stack_depth - 1; i++)
+#else
+  /* Check the previous (n) levels of the stack to make sure that
+     we haven't previously turned off parsing. */
+  for (i = 0; i < if_stack_depth; i++)
+#endif
+    if (if_stack[i] == 1)
+      return 0;
+
+  /* Invert the state of parsing if at top level. */
+  _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
+  return 0;
+}
+
+/* Terminate a conditional, popping the value of
+   _rl_parsing_conditionalized_out from the stack. */
+static int
+parser_endif (args)
+     char *args;
+{
+  if (if_stack_depth)
+    _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
+  else
+    _rl_init_file_error ("$endif without matching $if");
+  return 0;
+}
+
+static int
+parser_include (args)
+     char *args;
+{
+  const char *old_init_file;
+  char *e;
+  int old_line_number, old_include_level, r;
+
+  if (_rl_parsing_conditionalized_out)
+    return (0);
+
+  old_init_file = current_readline_init_file;
+  old_line_number = current_readline_init_lineno;
+  old_include_level = current_readline_init_include_level;
+
+  e = strchr (args, '\n');
+  if (e)
+    *e = '\0';
+  r = _rl_read_init_file ((const char *)args, old_include_level + 1);
+
+  current_readline_init_file = old_init_file;
+  current_readline_init_lineno = old_line_number;
+  current_readline_init_include_level = old_include_level;
+
+  return r;
+}
+  
+/* Associate textual names with actual functions. */
+static const struct {
+  const char * const name;
+  _rl_parser_func_t *function;
+} parser_directives [] = {
+  { "if", parser_if },
+  { "endif", parser_endif },
+  { "else", parser_else },
+  { "include", parser_include },
+  { (char *)0x0, (_rl_parser_func_t *)0x0 }
+};
+
+/* Handle a parser directive.  STATEMENT is the line of the directive
+   without any leading `$'. */
+static int
+handle_parser_directive (statement)
+     char *statement;
+{
+  register int i;
+  char *directive, *args;
+
+  /* Isolate the actual directive. */
+
+  /* Skip whitespace. */
+  for (i = 0; whitespace (statement[i]); i++);
+
+  directive = &statement[i];
+
+  for (; statement[i] && !whitespace (statement[i]); i++);
+
+  if (statement[i])
+    statement[i++] = '\0';
+
+  for (; statement[i] && whitespace (statement[i]); i++);
+
+  args = &statement[i];
+
+  /* Lookup the command, and act on it. */
+  for (i = 0; parser_directives[i].name; i++)
+    if (_rl_stricmp (directive, parser_directives[i].name) == 0)
+      {
+       (*parser_directives[i].function) (args);
+       return (0);
+      }
+
+  /* display an error message about the unknown parser directive */
+  _rl_init_file_error ("unknown parser directive");
+  return (1);
+}
+
+/* Start at STRING[START] and look for DELIM.  Return I where STRING[I] ==
+   DELIM or STRING[I] == 0.  DELIM is usually a double quote. */
+static int
+_rl_skip_to_delim (string, start, delim)
+     char *string;
+     int start, delim;
+{
+  int i, c, passc;
+
+  for (i = start,passc = 0; c = string[i]; i++)
+    {
+      if (passc)
+       {
+         passc = 0;
+         if (c == 0)
+           break;
+         continue;
+       }
+
+      if (c == '\\')
+       {
+         passc = 1;
+         continue;
+       }
+
+      if (c == delim)
+       break;
+    }
+
+  return i;
+}
+
+/* Read the binding command from STRING and perform it.
+   A key binding command looks like: Keyname: function-name\0,
+   a variable binding command looks like: set variable value.
+   A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
+int
+rl_parse_and_bind (string)
+     char *string;
+{
+  char *funname, *kname;
+  register int c, i;
+  int key, equivalency;
+
+  while (string && whitespace (*string))
+    string++;
+
+  if (string == 0 || *string == 0 || *string == '#')
+    return 0;
+
+  /* If this is a parser directive, act on it. */
+  if (*string == '$')
+    {
+      handle_parser_directive (&string[1]);
+      return 0;
+    }
+
+  /* If we aren't supposed to be parsing right now, then we're done. */
+  if (_rl_parsing_conditionalized_out)
+    return 0;
+
+  i = 0;
+  /* If this keyname is a complex key expression surrounded by quotes,
+     advance to after the matching close quote.  This code allows the
+     backslash to quote characters in the key expression. */
+  if (*string == '"')
+    {
+      i = _rl_skip_to_delim (string, 1, '"');
+
+      /* If we didn't find a closing quote, abort the line. */
+      if (string[i] == '\0')
+        {
+          _rl_init_file_error ("no closing `\"' in key binding");
+          return 1;
+        }
+      else
+        i++;   /* skip past closing double quote */
+    }
+
+  /* Advance to the colon (:) or whitespace which separates the two objects. */
+  for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
+
+  equivalency = (c == ':' && string[i + 1] == '=');
+
+  /* Mark the end of the command (or keyname). */
+  if (string[i])
+    string[i++] = '\0';
+
+  /* If doing assignment, skip the '=' sign as well. */
+  if (equivalency)
+    string[i++] = '\0';
+
+  /* If this is a command to set a variable, then do that. */
+  if (_rl_stricmp (string, "set") == 0)
+    {
+      char *var, *value, *e;
+      int s;
+
+      var = string + i;
+      /* Make VAR point to start of variable name. */
+      while (*var && whitespace (*var)) var++;
+
+      /* Make VALUE point to start of value string. */
+      value = var;
+      while (*value && whitespace (*value) == 0) value++;
+      if (*value)
+       *value++ = '\0';
+      while (*value && whitespace (*value)) value++;
+
+      /* Strip trailing whitespace from values of boolean variables. */
+      if (find_boolean_var (var) >= 0)
+       {
+         /* remove trailing whitespace */
+remove_trailing:
+         e = value + strlen (value) - 1;
+         while (e >= value && whitespace (*e))
+           e--;
+         e++;          /* skip back to whitespace or EOS */
+         
+         if (*e && e >= value)
+           *e = '\0';
+       }
+      else if ((i = find_string_var (var)) >= 0)
+       {
+         /* Allow quoted strings in variable values */
+         if (*value == '"')
+           {
+             i = _rl_skip_to_delim (value, 1, *value);
+             value[i] = '\0';
+           }
+         else
+           goto remove_trailing;
+       }
+       
+      rl_variable_bind (var, value);
+      return 0;
+    }
+
+  /* Skip any whitespace between keyname and funname. */
+  for (; string[i] && whitespace (string[i]); i++);
+  funname = &string[i];
+
+  /* Now isolate funname.
+     For straight function names just look for whitespace, since
+     that will signify the end of the string.  But this could be a
+     macro definition.  In that case, the string is quoted, so skip
+     to the matching delimiter.  We allow the backslash to quote the
+     delimiter characters in the macro body. */
+  /* This code exists to allow whitespace in macro expansions, which
+     would otherwise be gobbled up by the next `for' loop.*/
+  /* XXX - it may be desirable to allow backslash quoting only if " is
+     the quoted string delimiter, like the shell. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      i = _rl_skip_to_delim (string, i+1, *funname);
+      if (string[i])
+       i++;
+    }
+
+  /* Advance to the end of the string.  */
+  for (; string[i] && whitespace (string[i]) == 0; i++);
+
+  /* No extra whitespace at the end of the string. */
+  string[i] = '\0';
+
+  /* Handle equivalency bindings here.  Make the left-hand side be exactly
+     whatever the right-hand evaluates to, including keymaps. */
+  if (equivalency)
+    {
+      return 0;
+    }
+
+  /* If this is a new-style key-binding, then do the binding with
+     rl_bind_keyseq ().  Otherwise, let the older code deal with it. */
+  if (*string == '"')
+    {
+      char *seq;
+      register int j, k, passc;
+
+      seq = (char *)xmalloc (1 + strlen (string));
+      for (j = 1, k = passc = 0; string[j]; j++)
+       {
+         /* Allow backslash to quote characters, but leave them in place.
+            This allows a string to end with a backslash quoting another
+            backslash, or with a backslash quoting a double quote.  The
+            backslashes are left in place for rl_translate_keyseq (). */
+         if (passc || (string[j] == '\\'))
+           {
+             seq[k++] = string[j];
+             passc = !passc;
+             continue;
+           }
+
+         if (string[j] == '"')
+           break;
+
+         seq[k++] = string[j];
+       }
+      seq[k] = '\0';
+
+      /* Binding macro? */
+      if (*funname == '\'' || *funname == '"')
+       {
+         j = strlen (funname);
+
+         /* Remove the delimiting quotes from each end of FUNNAME. */
+         if (j && funname[j - 1] == *funname)
+           funname[j - 1] = '\0';
+
+         rl_macro_bind (seq, &funname[1], _rl_keymap);
+       }
+      else
+       rl_bind_keyseq (seq, rl_named_function (funname));
+
+      xfree (seq);
+      return 0;
+    }
+
+  /* Get the actual character we want to deal with. */
+  kname = strrchr (string, '-');
+  if (kname == 0)
+    kname = string;
+  else
+    kname++;
+
+  key = glean_key_from_name (kname);
+
+  /* Add in control and meta bits. */
+  if (substring_member_of_array (string, _rl_possible_control_prefixes))
+    key = CTRL (_rl_to_upper (key));
+
+  if (substring_member_of_array (string, _rl_possible_meta_prefixes))
+    key = META (key);
+
+  /* Temporary.  Handle old-style keyname with macro-binding. */
+  if (*funname == '\'' || *funname == '"')
+    {
+      char useq[2];
+      int fl = strlen (funname);
+
+      useq[0] = key; useq[1] = '\0';
+      if (fl && funname[fl - 1] == *funname)
+       funname[fl - 1] = '\0';
+
+      rl_macro_bind (useq, &funname[1], _rl_keymap);
+    }
+#if defined (PREFIX_META_HACK)
+  /* Ugly, but working hack to keep prefix-meta around. */
+  else if (_rl_stricmp (funname, "prefix-meta") == 0)
+    {
+      char seq[2];
+
+      seq[0] = key;
+      seq[1] = '\0';
+      rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
+    }
+#endif /* PREFIX_META_HACK */
+  else
+    rl_bind_key (key, rl_named_function (funname));
+  return 0;
+}
+
+/* Simple structure for boolean readline variables (i.e., those that can
+   have one of two values; either "On" or 1 for truth, or "Off" or 0 for
+   false. */
+
+#define V_SPECIAL      0x1
+
+static const struct {
+  const char * const name;
+  int *value;
+  int flags;
+} boolean_varlist [] = {
+  { "bind-tty-special-chars",  &_rl_bind_stty_chars,           0 },
+  { "blink-matching-paren",    &rl_blink_matching_paren,       V_SPECIAL },
+  { "byte-oriented",           &rl_byte_oriented,              0 },
+  { "completion-ignore-case",  &_rl_completion_case_fold,      0 },
+  { "completion-map-case",     &_rl_completion_case_map,       0 },
+  { "convert-meta",            &_rl_convert_meta_chars_to_ascii, 0 },
+  { "disable-completion",      &rl_inhibit_completion,         0 },
+  { "echo-control-characters", &_rl_echo_control_chars,        0 },
+  { "enable-keypad",           &_rl_enable_keypad,             0 },
+  { "enable-meta-key",         &_rl_enable_meta,               0 },
+  { "expand-tilde",            &rl_complete_with_tilde_expansion, 0 },
+  { "history-preserve-point",  &_rl_history_preserve_point,    0 },
+  { "horizontal-scroll-mode",  &_rl_horizontal_scroll_mode,    0 },
+  { "input-meta",              &_rl_meta_flag,                 0 },
+  { "mark-directories",                &_rl_complete_mark_directories, 0 },
+  { "mark-modified-lines",     &_rl_mark_modified_lines,       0 },
+  { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
+  { "match-hidden-files",      &_rl_match_hidden_files,        0 },
+  { "menu-complete-display-prefix", &_rl_menu_complete_prefix_first, 0 },
+  { "meta-flag",               &_rl_meta_flag,                 0 },
+  { "output-meta",             &_rl_output_meta_chars,         0 },
+  { "page-completions",                &_rl_page_completions,          0 },
+  { "prefer-visible-bell",     &_rl_prefer_visible_bell,       V_SPECIAL },
+  { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
+  { "revert-all-at-newline",   &_rl_revert_all_at_newline,     0 },
+  { "show-all-if-ambiguous",   &_rl_complete_show_all,         0 },
+  { "show-all-if-unmodified",  &_rl_complete_show_unmodified,  0 },
+  { "skip-completed-text",     &_rl_skip_completed_text,       0 },
+#if defined (VISIBLE_STATS)
+  { "visible-stats",           &rl_visible_stats,              0 },
+#endif /* VISIBLE_STATS */
+  { (char *)NULL, (int *)NULL, 0 }
+};
+
+static int
+find_boolean_var (name)
+     const char *name;
+{
+  register int i;
+
+  for (i = 0; boolean_varlist[i].name; i++)
+    if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
+      return i;
+  return -1;
+}
+
+/* Hooks for handling special boolean variables, where a
+   function needs to be called or another variable needs
+   to be changed when they're changed. */
+static void
+hack_special_boolean_var (i)
+     int i;
+{
+  const char *name;
+
+  name = boolean_varlist[i].name;
+
+  if (_rl_stricmp (name, "blink-matching-paren") == 0)
+    _rl_enable_paren_matching (rl_blink_matching_paren);
+  else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
+    {
+      if (_rl_prefer_visible_bell)
+       _rl_bell_preference = VISIBLE_BELL;
+      else
+       _rl_bell_preference = AUDIBLE_BELL;
+    }
+}
+
+typedef int _rl_sv_func_t PARAMS((const char *));
+
+/* These *must* correspond to the array indices for the appropriate
+   string variable.  (Though they're not used right now.) */
+#define V_BELLSTYLE    0
+#define V_COMBEGIN     1
+#define V_EDITMODE     2
+#define V_ISRCHTERM    3
+#define V_KEYMAP       4
+
+#define        V_STRING        1
+#define V_INT          2
+
+/* Forward declarations */
+static int sv_bell_style PARAMS((const char *));
+static int sv_combegin PARAMS((const char *));
+static int sv_dispprefix PARAMS((const char *));
+static int sv_compquery PARAMS((const char *));
+static int sv_compwidth PARAMS((const char *));
+static int sv_editmode PARAMS((const char *));
+static int sv_histsize PARAMS((const char *));
+static int sv_isrchterm PARAMS((const char *));
+static int sv_keymap PARAMS((const char *));
+
+static const struct {
+  const char * const name;
+  int flags;
+  _rl_sv_func_t *set_func;
+} string_varlist[] = {
+  { "bell-style",      V_STRING,       sv_bell_style },
+  { "comment-begin",   V_STRING,       sv_combegin },
+  { "completion-display-width", V_INT, sv_compwidth },
+  { "completion-prefix-display-length", V_INT, sv_dispprefix },
+  { "completion-query-items", V_INT,   sv_compquery },
+  { "editing-mode",    V_STRING,       sv_editmode },
+  { "history-size",    V_INT,          sv_histsize },
+  { "isearch-terminators", V_STRING,   sv_isrchterm },
+  { "keymap",          V_STRING,       sv_keymap },
+  { (char *)NULL,      0, (_rl_sv_func_t *)0 }
+};
+
+static int
+find_string_var (name)
+     const char *name;
+{
+  register int i;
+
+  for (i = 0; string_varlist[i].name; i++)
+    if (_rl_stricmp (name, string_varlist[i].name) == 0)
+      return i;
+  return -1;
+}
+
+/* A boolean value that can appear in a `set variable' command is true if
+   the value is null or empty, `on' (case-insenstive), or "1".  Any other
+   values result in 0 (false). */
+static int
+bool_to_int (value)
+     const char *value;
+{
+  return (value == 0 || *value == '\0' ||
+               (_rl_stricmp (value, "on") == 0) ||
+               (value[0] == '1' && value[1] == '\0'));
+}
+
+char *
+rl_variable_value (name)
+     const char *name;
+{
+  register int i;
+
+  /* Check for simple variables first. */
+  i = find_boolean_var (name);
+  if (i >= 0)
+    return (*boolean_varlist[i].value ? "on" : "off");
+
+  i = find_string_var (name);
+  if (i >= 0)
+    return (_rl_get_string_variable_value (string_varlist[i].name));
+
+  /* Unknown variable names return NULL. */
+  return 0;
+}
+
+int
+rl_variable_bind (name, value)
+     const char *name, *value;
+{
+  register int i;
+  int  v;
+
+  /* Check for simple variables first. */
+  i = find_boolean_var (name);
+  if (i >= 0)
+    {
+      *boolean_varlist[i].value = bool_to_int (value);
+      if (boolean_varlist[i].flags & V_SPECIAL)
+       hack_special_boolean_var (i);
+      return 0;
+    }
+
+  i = find_string_var (name);
+
+  /* For the time being, unknown variable names or string names without a
+     handler function are simply ignored. */
+  if (i < 0 || string_varlist[i].set_func == 0)
+    return 0;
+
+  v = (*string_varlist[i].set_func) (value);
+  return v;
+}
+
+static int
+sv_editmode (value)
+     const char *value;
+{
+  if (_rl_strnicmp (value, "vi", 2) == 0)
+    {
+#if defined (VI_MODE)
+      _rl_keymap = vi_insertion_keymap;
+      rl_editing_mode = vi_mode;
+#endif /* VI_MODE */
+      return 0;
+    }
+  else if (_rl_strnicmp (value, "emacs", 5) == 0)
+    {
+      _rl_keymap = emacs_standard_keymap;
+      rl_editing_mode = emacs_mode;
+      return 0;
+    }
+  return 1;
+}
+
+static int
+sv_combegin (value)
+     const char *value;
+{
+  if (value && *value)
+    {
+      FREE (_rl_comment_begin);
+      _rl_comment_begin = savestring (value);
+      return 0;
+    }
+  return 1;
+}
+
+static int
+sv_dispprefix (value)
+     const char *value;
+{
+  int nval = 0;
+
+  if (value && *value)
+    {
+      nval = atoi (value);
+      if (nval < 0)
+       nval = 0;
+    }
+  _rl_completion_prefix_display_length = nval;
+  return 0;
+}
+
+static int
+sv_compquery (value)
+     const char *value;
+{
+  int nval = 100;
+
+  if (value && *value)
+    {
+      nval = atoi (value);
+      if (nval < 0)
+       nval = 0;
+    }
+  rl_completion_query_items = nval;
+  return 0;
+}
+
+static int
+sv_compwidth (value)
+     const char *value;
+{
+  int nval = -1;
+
+  if (value && *value)
+    nval = atoi (value);
+
+  _rl_completion_columns = nval;
+  return 0;
+}
+
+static int
+sv_histsize (value)
+     const char *value;
+{
+  int nval = 500;
+
+  if (value && *value)
+    {
+      nval = atoi (value);
+      if (nval < 0)
+       return 1;
+    }
+  stifle_history (nval);
+  return 0;
+}
+
+static int
+sv_keymap (value)
+     const char *value;
+{
+  Keymap kmap;
+
+  kmap = rl_get_keymap_by_name (value);
+  if (kmap)
+    {
+      rl_set_keymap (kmap);
+      return 0;
+    }
+  return 1;
+}
+
+static int
+sv_bell_style (value)
+     const char *value;
+{
+  if (value == 0 || *value == '\0')
+    _rl_bell_preference = AUDIBLE_BELL;
+  else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
+    _rl_bell_preference = NO_BELL;
+  else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
+    _rl_bell_preference = AUDIBLE_BELL;
+  else if (_rl_stricmp (value, "visible") == 0)
+    _rl_bell_preference = VISIBLE_BELL;
+  else
+    return 1;
+  return 0;
+}
+
+static int
+sv_isrchterm (value)
+     const char *value;
+{
+  int beg, end, delim;
+  char *v;
+
+  if (value == 0)
+    return 1;
+
+  /* Isolate the value and translate it into a character string. */
+  v = savestring (value);
+  FREE (_rl_isearch_terminators);
+  if (v[0] == '"' || v[0] == '\'')
+    {
+      delim = v[0];
+      for (beg = end = 1; v[end] && v[end] != delim; end++)
+       ;
+    }
+  else
+    {
+      for (beg = end = 0; whitespace (v[end]) == 0; end++)
+       ;
+    }
+
+  v[end] = '\0';
+
+  /* The value starts at v + beg.  Translate it into a character string. */
+  _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1);
+  rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end);
+  _rl_isearch_terminators[end] = '\0';
+
+  xfree (v);
+  return 0;
+}
+      
+/* Return the character which matches NAME.
+   For example, `Space' returns ' '. */
+
+typedef struct {
+  const char * const name;
+  int value;
+} assoc_list;
+
+static const assoc_list name_key_alist[] = {
+  { "DEL", 0x7f },
+  { "ESC", '\033' },
+  { "Escape", '\033' },
+  { "LFD", '\n' },
+  { "Newline", '\n' },
+  { "RET", '\r' },
+  { "Return", '\r' },
+  { "Rubout", 0x7f },
+  { "SPC", ' ' },
+  { "Space", ' ' },
+  { "Tab", 0x09 },
+  { (char *)0x0, 0 }
+};
+
+static int
+glean_key_from_name (name)
+     char *name;
+{
+  register int i;
+
+  for (i = 0; name_key_alist[i].name; i++)
+    if (_rl_stricmp (name, name_key_alist[i].name) == 0)
+      return (name_key_alist[i].value);
+
+  return (*(unsigned char *)name);     /* XXX was return (*name) */
+}
+
+/* Auxiliary functions to manage keymaps. */
+static const struct {
+  const char * const name;
+  Keymap map;
+} keymap_names[] = {
+  { "emacs", emacs_standard_keymap },
+  { "emacs-standard", emacs_standard_keymap },
+  { "emacs-meta", emacs_meta_keymap },
+  { "emacs-ctlx", emacs_ctlx_keymap },
+#if defined (VI_MODE)
+  { "vi", vi_movement_keymap },
+  { "vi-move", vi_movement_keymap },
+  { "vi-command", vi_movement_keymap },
+  { "vi-insert", vi_insertion_keymap },
+#endif /* VI_MODE */
+  { (char *)0x0, (Keymap)0x0 }
+};
+
+Keymap
+rl_get_keymap_by_name (name)
+     const char *name;
+{
+  register int i;
+
+  for (i = 0; keymap_names[i].name; i++)
+    if (_rl_stricmp (name, keymap_names[i].name) == 0)
+      return (keymap_names[i].map);
+  return ((Keymap) NULL);
+}
+
+char *
+rl_get_keymap_name (map)
+     Keymap map;
+{
+  register int i;
+  for (i = 0; keymap_names[i].name; i++)
+    if (map == keymap_names[i].map)
+      return ((char *)keymap_names[i].name);
+  return ((char *)NULL);
+}
+  
+void
+rl_set_keymap (map)
+     Keymap map;
+{
+  if (map)
+    _rl_keymap = map;
+}
+
+Keymap
+rl_get_keymap ()
+{
+  return (_rl_keymap);
+}
+
+void
+rl_set_keymap_from_edit_mode ()
+{
+  if (rl_editing_mode == emacs_mode)
+    _rl_keymap = emacs_standard_keymap;
+#if defined (VI_MODE)
+  else if (rl_editing_mode == vi_mode)
+    _rl_keymap = vi_insertion_keymap;
+#endif /* VI_MODE */
+}
+
+char *
+rl_get_keymap_name_from_edit_mode ()
+{
+  if (rl_editing_mode == emacs_mode)
+    return "emacs";
+#if defined (VI_MODE)
+  else if (rl_editing_mode == vi_mode)
+    return "vi";
+#endif /* VI_MODE */
+  else
+    return "none";
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*               Key Binding and Function Information              */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Each of the following functions produces information about the
+   state of keybindings and functions known to Readline.  The info
+   is always printed to rl_outstream, and in such a way that it can
+   be read back in (i.e., passed to rl_parse_and_bind ()). */
+
+/* Print the names of functions known to Readline. */
+void
+rl_list_funmap_names ()
+{
+  register int i;
+  const char **funmap_names;
+
+  funmap_names = rl_funmap_names ();
+
+  if (!funmap_names)
+    return;
+
+  for (i = 0; funmap_names[i]; i++)
+    fprintf (rl_outstream, "%s\n", funmap_names[i]);
+
+  xfree (funmap_names);
+}
+
+static char *
+_rl_get_keyname (key)
+     int key;
+{
+  char *keyname;
+  int i, c;
+
+  keyname = (char *)xmalloc (8);
+
+  c = key;
+  /* Since this is going to be used to write out keysequence-function
+     pairs for possible inclusion in an inputrc file, we don't want to
+     do any special meta processing on KEY. */
+
+#if 1
+  /* XXX - Experimental */
+  /* We might want to do this, but the old version of the code did not. */
+
+  /* If this is an escape character, we don't want to do any more processing.
+     Just add the special ESC key sequence and return. */
+  if (c == ESC)
+    {
+      keyname[0] = '\\';
+      keyname[1] = 'e';
+      keyname[2] = '\0';
+      return keyname;
+    }
+#endif
+
+  /* RUBOUT is translated directly into \C-? */
+  if (key == RUBOUT)
+    {
+      keyname[0] = '\\';
+      keyname[1] = 'C';
+      keyname[2] = '-';
+      keyname[3] = '?';
+      keyname[4] = '\0';
+      return keyname;
+    }
+
+  i = 0;
+  /* Now add special prefixes needed for control characters.  This can
+     potentially change C. */
+  if (CTRL_CHAR (c))
+    {
+      keyname[i++] = '\\';
+      keyname[i++] = 'C';
+      keyname[i++] = '-';
+      c = _rl_to_lower (UNCTRL (c));
+    }
+
+  /* XXX experimental code.  Turn the characters that are not ASCII or
+     ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
+     This changes C. */
+  if (c >= 128 && c <= 159)
+    {
+      keyname[i++] = '\\';
+      keyname[i++] = '2';
+      c -= 128;
+      keyname[i++] = (c / 8) + '0';
+      c = (c % 8) + '0';
+    }
+
+  /* Now, if the character needs to be quoted with a backslash, do that. */
+  if (c == '\\' || c == '"')
+    keyname[i++] = '\\';
+
+  /* Now add the key, terminate the string, and return it. */
+  keyname[i++] = (char) c;
+  keyname[i] = '\0';
+
+  return keyname;
+}
+
+/* Return a NULL terminated array of strings which represent the key
+   sequences that are used to invoke FUNCTION in MAP. */
+char **
+rl_invoking_keyseqs_in_map (function, map)
+     rl_command_func_t *function;
+     Keymap map;
+{
+  register int key;
+  char **result;
+  int result_index, result_size;
+
+  result = (char **)NULL;
+  result_index = result_size = 0;
+
+  for (key = 0; key < KEYMAP_SIZE; key++)
+    {
+      switch (map[key].type)
+       {
+       case ISMACR:
+         /* Macros match, if, and only if, the pointers are identical.
+            Thus, they are treated exactly like functions in here. */
+       case ISFUNC:
+         /* If the function in the keymap is the one we are looking for,
+            then add the current KEY to the list of invoking keys. */
+         if (map[key].function == function)
+           {
+             char *keyname;
+
+             keyname = _rl_get_keyname (key);
+
+             if (result_index + 2 > result_size)
+               {
+                 result_size += 10;
+                 result = (char **)xrealloc (result, result_size * sizeof (char *));
+               }
+
+             result[result_index++] = keyname;
+             result[result_index] = (char *)NULL;
+           }
+         break;
+
+       case ISKMAP:
+         {
+           char **seqs;
+           register int i;
+
+           /* Find the list of keyseqs in this map which have FUNCTION as
+              their target.  Add the key sequences found to RESULT. */
+           if (map[key].function)
+             seqs =
+               rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
+           else
+             break;
+
+           if (seqs == 0)
+             break;
+
+           for (i = 0; seqs[i]; i++)
+             {
+               char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
+
+               if (key == ESC)
+                 {
+                   /* If ESC is the meta prefix and we're converting chars
+                      with the eighth bit set to ESC-prefixed sequences, then
+                      we can use \M-.  Otherwise we need to use the sequence
+                      for ESC. */
+                   if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP)
+                     sprintf (keyname, "\\M-");
+                   else
+                     sprintf (keyname, "\\e");
+                 }
+               else if (CTRL_CHAR (key))
+                 sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
+               else if (key == RUBOUT)
+                 sprintf (keyname, "\\C-?");
+               else if (key == '\\' || key == '"')
+                 {
+                   keyname[0] = '\\';
+                   keyname[1] = (char) key;
+                   keyname[2] = '\0';
+                 }
+               else
+                 {
+                   keyname[0] = (char) key;
+                   keyname[1] = '\0';
+                 }
+               
+               strcat (keyname, seqs[i]);
+               xfree (seqs[i]);
+
+               if (result_index + 2 > result_size)
+                 {
+                   result_size += 10;
+                   result = (char **)xrealloc (result, result_size * sizeof (char *));
+                 }
+
+               result[result_index++] = keyname;
+               result[result_index] = (char *)NULL;
+             }
+
+           xfree (seqs);
+         }
+         break;
+       }
+    }
+  return (result);
+}
+
+/* Return a NULL terminated array of strings which represent the key
+   sequences that can be used to invoke FUNCTION using the current keymap. */
+char **
+rl_invoking_keyseqs (function)
+     rl_command_func_t *function;
+{
+  return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
+}
+
+/* Print all of the functions and their bindings to rl_outstream.  If
+   PRINT_READABLY is non-zero, then print the output in such a way
+   that it can be read back in. */
+void
+rl_function_dumper (print_readably)
+     int print_readably;
+{
+  register int i;
+  const char **names;
+  const char *name;
+
+  names = rl_funmap_names ();
+
+  fprintf (rl_outstream, "\n");
+
+  for (i = 0; name = names[i]; i++)
+    {
+      rl_command_func_t *function;
+      char **invokers;
+
+      function = rl_named_function (name);
+      invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
+
+      if (print_readably)
+       {
+         if (!invokers)
+           fprintf (rl_outstream, "# %s (not bound)\n", name);
+         else
+           {
+             register int j;
+
+             for (j = 0; invokers[j]; j++)
+               {
+                 fprintf (rl_outstream, "\"%s\": %s\n",
+                          invokers[j], name);
+                 xfree (invokers[j]);
+               }
+
+             xfree (invokers);
+           }
+       }
+      else
+       {
+         if (!invokers)
+           fprintf (rl_outstream, "%s is not bound to any keys\n",
+                    name);
+         else
+           {
+             register int j;
+
+             fprintf (rl_outstream, "%s can be found on ", name);
+
+             for (j = 0; invokers[j] && j < 5; j++)
+               {
+                 fprintf (rl_outstream, "\"%s\"%s", invokers[j],
+                          invokers[j + 1] ? ", " : ".\n");
+               }
+
+             if (j == 5 && invokers[j])
+               fprintf (rl_outstream, "...\n");
+
+             for (j = 0; invokers[j]; j++)
+               xfree (invokers[j]);
+
+             xfree (invokers);
+           }
+       }
+    }
+
+  xfree (names);
+}
+
+/* Print all of the current functions and their bindings to
+   rl_outstream.  If an explicit argument is given, then print
+   the output in such a way that it can be read back in. */
+int
+rl_dump_functions (count, key)
+     int count, key;
+{
+  if (rl_dispatching)
+    fprintf (rl_outstream, "\r\n");
+  rl_function_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
+static void
+_rl_macro_dumper_internal (print_readably, map, prefix)
+     int print_readably;
+     Keymap map;
+     char *prefix;
+{
+  register int key;
+  char *keyname, *out;
+  int prefix_len;
+
+  for (key = 0; key < KEYMAP_SIZE; key++)
+    {
+      switch (map[key].type)
+       {
+       case ISMACR:
+         keyname = _rl_get_keyname (key);
+         out = _rl_untranslate_macro_value ((char *)map[key].function, 0);
+
+         if (print_readably)
+           fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
+                                                        keyname,
+                                                        out ? out : "");
+         else
+           fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
+                                                       keyname,
+                                                       out ? out : "");
+         xfree (keyname);
+         xfree (out);
+         break;
+       case ISFUNC:
+         break;
+       case ISKMAP:
+         prefix_len = prefix ? strlen (prefix) : 0;
+         if (key == ESC)
+           {
+             keyname = (char *)xmalloc (3 + prefix_len);
+             if (prefix)
+               strcpy (keyname, prefix);
+             keyname[prefix_len] = '\\';
+             keyname[prefix_len + 1] = 'e';
+             keyname[prefix_len + 2] = '\0';
+           }
+         else
+           {
+             keyname = _rl_get_keyname (key);
+             if (prefix)
+               {
+                 out = (char *)xmalloc (strlen (keyname) + prefix_len + 1);
+                 strcpy (out, prefix);
+                 strcpy (out + prefix_len, keyname);
+                 xfree (keyname);
+                 keyname = out;
+               }
+           }
+
+         _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
+         xfree (keyname);
+         break;
+       }
+    }
+}
+
+void
+rl_macro_dumper (print_readably)
+     int print_readably;
+{
+  _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
+}
+
+int
+rl_dump_macros (count, key)
+     int count, key;
+{
+  if (rl_dispatching)
+    fprintf (rl_outstream, "\r\n");
+  rl_macro_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
+static char *
+_rl_get_string_variable_value (name)
+     const char *name;
+{
+  static char numbuf[32];
+  char *ret;
+
+  if (_rl_stricmp (name, "bell-style") == 0)
+    {
+      switch (_rl_bell_preference)
+       {
+         case NO_BELL:
+           return "none";
+         case VISIBLE_BELL:
+           return "visible";
+         case AUDIBLE_BELL:
+         default:
+           return "audible";
+       }
+    }
+  else if (_rl_stricmp (name, "comment-begin") == 0)
+    return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
+  else if (_rl_stricmp (name, "completion-display-width") == 0)
+    {
+      sprintf (numbuf, "%d", _rl_completion_columns);
+      return (numbuf);
+    }
+  else if (_rl_stricmp (name, "completion-prefix-display-length") == 0)
+    {
+      sprintf (numbuf, "%d", _rl_completion_prefix_display_length);
+      return (numbuf);
+    }
+  else if (_rl_stricmp (name, "completion-query-items") == 0)
+    {
+      sprintf (numbuf, "%d", rl_completion_query_items);
+      return (numbuf);
+    }
+  else if (_rl_stricmp (name, "editing-mode") == 0)
+    return (rl_get_keymap_name_from_edit_mode ());
+  else if (_rl_stricmp (name, "history-size") == 0)
+    {
+      sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : 0);
+      return (numbuf);
+    }
+  else if (_rl_stricmp (name, "isearch-terminators") == 0)
+    {
+      if (_rl_isearch_terminators == 0)
+       return 0;
+      ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0);
+      if (ret)
+       {
+         strncpy (numbuf, ret, sizeof (numbuf) - 1);
+         xfree (ret);
+         numbuf[sizeof(numbuf) - 1] = '\0';
+       }
+      else
+       numbuf[0] = '\0';
+      return numbuf;
+    }
+  else if (_rl_stricmp (name, "keymap") == 0)
+    {
+      ret = rl_get_keymap_name (_rl_keymap);
+      if (ret == 0)
+       ret = rl_get_keymap_name_from_edit_mode ();
+      return (ret ? ret : "none");
+    }
+  else
+    return (0);
+}
+
+void
+rl_variable_dumper (print_readably)
+     int print_readably;
+{
+  int i;
+  char *v;
+
+  for (i = 0; boolean_varlist[i].name; i++)
+    {
+      if (print_readably)
+        fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
+                              *boolean_varlist[i].value ? "on" : "off");
+      else
+        fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
+                              *boolean_varlist[i].value ? "on" : "off");
+    }
+
+  for (i = 0; string_varlist[i].name; i++)
+    {
+      v = _rl_get_string_variable_value (string_varlist[i].name);
+      if (v == 0)      /* _rl_isearch_terminators can be NULL */
+       continue;
+      if (print_readably)
+        fprintf (rl_outstream, "set %s %s\n", string_varlist[i].name, v);
+      else
+        fprintf (rl_outstream, "%s is set to `%s'\n", string_varlist[i].name, v);
+    }
+}
+
+/* Print all of the current variables and their values to
+   rl_outstream.  If an explicit argument is given, then print
+   the output in such a way that it can be read back in. */
+int
+rl_dump_variables (count, key)
+     int count, key;
+{
+  if (rl_dispatching)
+    fprintf (rl_outstream, "\r\n");
+  rl_variable_dumper (rl_explicit_arg);
+  rl_on_new_line ();
+  return (0);
+}
+
+/* Return non-zero if any members of ARRAY are a substring in STRING. */
+static int
+substring_member_of_array (string, array)
+     const char *string;
+     const char * const *array;
+{
+  while (*array)
+    {
+      if (_rl_strindex (string, *array))
+       return (1);
+      array++;
+    }
+  return (0);
+}
index 2b2cb71a2045e343893d849d38aef585b45d604d..8477c9fa37fda671339d1fb71467ea083fd8a83b 100644 (file)
@@ -1011,6 +1011,9 @@ and store the definition.
 .B call\-last\-kbd\-macro (C\-x e)
 Re-execute the last keyboard macro defined, by making the characters
 in the macro appear as if typed at the keyboard.
+.B print\-last\-kbd\-macro ()
+Print the last keyboard macro defined in a format suitable for the
+\fIinputrc\fP file.
 .PD
 .SS Miscellaneous
 .PP
diff --git a/lib/readline/doc/readline.3~ b/lib/readline/doc/readline.3~
new file mode 100644 (file)
index 0000000..2b2cb71
--- /dev/null
@@ -0,0 +1,1396 @@
+.\"
+.\" MAN PAGE COMMENTS to
+.\"
+.\"    Chet Ramey
+.\"    Information Network Services
+.\"    Case Western Reserve University
+.\"    chet@ins.CWRU.Edu
+.\"
+.\"    Last Change: Sat Aug 28 18:56:32 EDT 2010
+.\"
+.TH READLINE 3 "2010 August 28" "GNU Readline 6.2"
+.\"
+.\" File Name macro.  This used to be `.PN', for Path Name,
+.\" but Sun doesn't seem to like that very much.
+.\"
+.de FN
+\fI\|\\$1\|\fP
+..
+.SH NAME
+readline \- get a line from a user with editing
+.SH SYNOPSIS
+.LP
+.nf
+.ft B
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+.ft
+.fi
+.LP
+.nf
+\fIchar *\fP
+.br
+\fBreadline\fP (\fIconst char *prompt\fP);
+.fi
+.SH COPYRIGHT
+.if n Readline is Copyright (C) 1989\-2011 Free Software Foundation,  Inc.
+.if t Readline is Copyright \(co 1989\-2011 Free Software Foundation, Inc.
+.SH DESCRIPTION
+.LP
+.B readline
+will read a line from the terminal
+and return it, using
+.B prompt
+as a prompt.  If 
+.B prompt
+is \fBNULL\fP or the empty string, no prompt is issued.
+The line returned is allocated with
+.IR malloc (3);
+the caller must free it when finished.  The line returned
+has the final newline removed, so only the text of the line
+remains.
+.LP
+.B readline
+offers editing capabilities while the user is entering the
+line.
+By default, the line editing commands
+are similar to those of emacs.
+A vi\-style line editing interface is also available.
+.LP
+This manual page describes only the most basic use of \fBreadline\fP.
+Much more functionality is available; see
+\fIThe GNU Readline Library\fP and \fIThe GNU History Library\fP
+for additional information.
+.SH RETURN VALUE
+.LP
+.B readline
+returns the text of the line read.  A blank line
+returns the empty string.  If
+.B EOF
+is encountered while reading a line, and the line is empty,
+.B NULL
+is returned.  If an
+.B EOF
+is read with a non\-empty line, it is
+treated as a newline.
+.SH NOTATION
+.LP
+An Emacs-style notation is used to denote
+keystrokes.  Control keys are denoted by C\-\fIkey\fR, e.g., C\-n
+means Control\-N.  Similarly, 
+.I meta
+keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X.  (On keyboards
+without a 
+.I meta
+key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key
+then the
+.I x
+key.  This makes ESC the \fImeta prefix\fP.
+The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP,
+or press the Escape key
+then hold the Control key while pressing the
+.I x
+key.)
+.PP
+Readline commands may be given numeric
+.IR arguments ,
+which normally act as a repeat count.  Sometimes, however, it is the
+sign of the argument that is significant.  Passing a negative argument
+to a command that acts in the forward direction (e.g., \fBkill\-line\fP)
+causes that command to act in a backward direction.  Commands whose
+behavior with arguments deviates from this are noted.
+.PP
+When a command is described as \fIkilling\fP text, the text
+deleted is saved for possible future retrieval
+(\fIyanking\fP).  The killed text is saved in a
+\fIkill ring\fP.  Consecutive kills cause the text to be
+accumulated into one unit, which can be yanked all at once. 
+Commands which do not kill text separate the chunks of text
+on the kill ring.
+.SH INITIALIZATION FILE
+.LP
+Readline is customized by putting commands in an initialization
+file (the \fIinputrc\fP file).
+The name of this file is taken from the value of the
+.B INPUTRC
+environment variable.  If that variable is unset, the default is
+.IR ~/.inputrc .
+If that file  does not exist or cannot be read, the ultimate default is
+.IR /etc/inputrc .
+When a program which uses the readline library starts up, the
+init file is read, and the key bindings and variables are set.
+There are only a few basic constructs allowed in the
+readline init file.  Blank lines are ignored.
+Lines beginning with a \fB#\fP are comments.
+Lines beginning with a \fB$\fP indicate conditional constructs.
+Other lines denote key bindings and variable settings.
+Each program using this library may add its own commands
+and bindings.
+.PP
+For example, placing
+.RS
+.PP
+M\-Control\-u: universal\-argument
+.RE
+or
+.RS
+C\-Meta\-u: universal\-argument
+.RE
+.sp
+into the 
+.I inputrc
+would make M\-C\-u execute the readline command
+.IR universal\-argument .
+.PP
+The following symbolic character names are recognized while
+processing key bindings:
+.IR DEL ,
+.IR ESC ,
+.IR ESCAPE ,
+.IR LFD ,
+.IR NEWLINE ,
+.IR RET ,
+.IR RETURN ,
+.IR RUBOUT ,
+.IR SPACE ,
+.IR SPC ,
+and
+.IR TAB .
+.PP
+In addition to command names, readline allows keys to be bound
+to a string that is inserted when the key is pressed (a \fImacro\fP).
+.PP
+.SS Key Bindings
+.PP
+The syntax for controlling key bindings in the
+.I inputrc
+file is simple.  All that is required is the name of the
+command or the text of a macro and a key sequence to which
+it should be bound. The name may be specified in one of two ways:
+as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP
+prefixes, or as a key sequence.
+The name and key sequence are separated by a colon.  There can be no
+whitespace between the name and the colon.
+.PP
+When using the form \fBkeyname\fP:\^\fIfunction-name\fP or \fImacro\fP,
+.I keyname
+is the name of a key spelled out in English.  For example:
+.sp
+.RS
+Control\-u: universal\-argument
+.br
+Meta\-Rubout: backward\-kill\-word
+.br
+Control\-o: "> output"
+.RE
+.LP
+In the above example,
+.I C\-u
+is bound to the function
+.BR universal\-argument ,
+.I M-DEL
+is bound to the function
+.BR backward\-kill\-word ,
+and
+.I C\-o
+is bound to run the macro
+expressed on the right hand side (that is, to insert the text
+.if t \f(CW> output\fP
+.if n ``> output''
+into the line).
+.PP
+In the second form, \fB"keyseq"\fP:\^\fIfunction\-name\fP or \fImacro\fP,
+.B keyseq
+differs from
+.B keyname
+above in that strings denoting
+an entire key sequence may be specified by placing the sequence
+within double quotes.  Some GNU Emacs style key escapes can be
+used, as in the following example, but the symbolic character names
+are not recognized.
+.sp
+.RS
+"\eC\-u": universal\-argument
+.br
+"\eC\-x\eC\-r": re\-read\-init\-file
+.br
+"\ee[11~": "Function Key 1"
+.RE
+.PP
+In this example,
+.I C-u
+is again bound to the function
+.BR universal\-argument .
+.I "C-x C-r"
+is bound to the function
+.BR re\-read\-init\-file ,
+and 
+.I "ESC [ 1 1 ~"
+is bound to insert the text
+.if t \f(CWFunction Key 1\fP.
+.if n ``Function Key 1''.
+.PP
+The full set of GNU Emacs style escape sequences available when specifying
+key sequences is
+.RS
+.PD 0
+.TP
+.B \eC\-
+control prefix
+.TP
+.B \eM\-
+meta prefix
+.TP
+.B \ee
+an escape character
+.TP
+.B \e\e
+backslash
+.TP
+.B \e"
+literal ", a double quote
+.TP
+.B \e'
+literal ', a single quote
+.RE
+.PD
+.PP
+In addition to the GNU Emacs style escape sequences, a second
+set of backslash escapes is available:
+.RS
+.PD 0
+.TP
+.B \ea
+alert (bell)
+.TP
+.B \eb
+backspace
+.TP
+.B \ed
+delete
+.TP
+.B \ef
+form feed
+.TP
+.B \en
+newline
+.TP
+.B \er
+carriage return
+.TP
+.B \et
+horizontal tab
+.TP
+.B \ev
+vertical tab
+.TP
+.B \e\fInnn\fP
+the eight-bit character whose value is the octal value \fInnn\fP
+(one to three digits)
+.TP
+.B \ex\fIHH\fP
+the eight-bit character whose value is the hexadecimal value \fIHH\fP
+(one or two hex digits)
+.RE
+.PD
+.PP
+When entering the text of a macro, single or double quotes should
+be used to indicate a macro definition.  Unquoted text
+is assumed to be a function name.
+In the macro body, the backslash escapes described above are expanded.
+Backslash will quote any other character in the macro text,
+including " and '.
+.PP
+.B Bash
+allows the current readline key bindings to be displayed or modified
+with the
+.B bind
+builtin command.  The editing mode may be switched during interactive
+use by using the
+.B \-o
+option to the
+.B set
+builtin command.  Other programs using this library provide
+similar mechanisms.  The
+.I inputrc
+file may be edited and re-read if a program does not provide
+any other means to incorporate new bindings.
+.SS Variables
+.PP
+Readline has variables that can be used to further customize its
+behavior.  A variable may be set in the
+.I inputrc
+file with a statement of the form
+.RS
+.PP
+\fBset\fP \fIvariable\-name\fP \fIvalue\fP
+.RE
+.PP
+Except where noted, readline variables can take the values
+.B On
+or
+.B Off
+(without regard to case).
+Unrecognized variable names are ignored.
+When a variable value is read, empty or null values, "on" (case-insensitive),
+and "1" are equivalent to \fBOn\fP.  All other values are equivalent to
+\fBOff\fP.
+The variables and their default values are:
+.PP
+.PD 0
+.TP
+.B bell\-style (audible)
+Controls what happens when readline wants to ring the terminal bell.
+If set to \fBnone\fP, readline never rings the bell.  If set to
+\fBvisible\fP, readline uses a visible bell if one is available.
+If set to \fBaudible\fP, readline attempts to ring the terminal's bell.
+.TP
+.B bind\-tty\-special\-chars (On)
+If set to \fBOn\fP, readline attempts to bind the control characters  
+treated specially by the kernel's terminal driver to their readline
+equivalents.
+.TP
+.B comment\-begin (``#'')
+The string that is inserted in \fBvi\fP mode when the
+.B insert\-comment
+command is executed.
+This command is bound to
+.B M\-#
+in emacs mode and to
+.B #
+in vi command mode.
+.TP
+.B completion\-display\-width (-1)
+The number of screen columns used to display possible matches
+when performing completion.
+The value is ignored if it is less than 0 or greater than the terminal
+screen width.
+A value of 0 will cause matches to be displayed one per line.
+The default value is -1.
+.TP 
+.B completion\-ignore\-case (Off)
+If set to \fBOn\fP, readline performs filename matching and completion
+in a case\-insensitive fashion.
+.TP
+.B completion\-map\-case (Off)
+If set to \fBOn\fP, and \fBcompletion\-ignore\-case\fP is enabled, readline
+treats hyphens (\fI\-\fP) and underscores (\fI_\fP) as equivalent when
+performing case\-insensitive filename matching and completion.
+.TP
+.B completion\-prefix\-display\-length (0)
+The length in characters of the common prefix of a list of possible
+completions that is displayed without modification.  When set to a
+value greater than zero, common prefixes longer than this value are
+replaced with an ellipsis when displaying possible completions.
+.TP
+.B completion\-query\-items (100)
+This determines when the user is queried about viewing
+the number of possible completions
+generated by the \fBpossible\-completions\fP command.
+It may be set to any integer value greater than or equal to
+zero.  If the number of possible completions is greater than
+or equal to the value of this variable, the user is asked whether
+or not he wishes to view them; otherwise they are simply listed
+on the terminal.  A negative value causes readline to never ask.
+.TP
+.B convert\-meta (On)
+If set to \fBOn\fP, readline will convert characters with the
+eighth bit set to an ASCII key sequence
+by stripping the eighth bit and prefixing it with an
+escape character (in effect, using escape as the \fImeta prefix\fP).
+.TP
+.B disable\-completion (Off)
+If set to \fBOn\fP, readline will inhibit word completion.  Completion 
+characters will be inserted into the line as if they had been
+mapped to \fBself-insert\fP.
+.TP
+.B editing\-mode (emacs)
+Controls whether readline begins with a set of key bindings similar
+to \fIEmacs\fP or \fIvi\fP.
+.B editing\-mode
+can be set to either
+.B emacs
+or
+.BR vi .
+.TP
+.B echo\-control\-characters (On)
+When set to \fBOn\fP, on operating systems that indicate they support it,
+readline echoes a character corresponding to a signal generated from the
+keyboard.
+.TP
+.B enable\-keypad (Off)
+When set to \fBOn\fP, readline will try to enable the application
+keypad when it is called.  Some systems need this to enable the
+arrow keys.
+.TP
+.B enable\-meta\-key (On)
+When set to \fBOn\fP, readline will try to enable any meta modifier
+key the terminal claims to support when it is called.  On many terminals,
+the meta key is used to send eight-bit characters.
+.TP
+.B expand\-tilde (Off)
+If set to \fBOn\fP, tilde expansion is performed when readline
+attempts word completion.
+.TP
+.B history\-preserve\-point (Off)
+If set to \fBOn\fP, the history code attempts to place point at the 
+same location on each history line retrieved with \fBprevious-history\fP 
+or \fBnext-history\fP.
+.TP
+.B history\-size (0)
+Set the maximum number of history entries saved in the history list.  If
+set to zero, the number of entries in the history list is not limited.
+.TP
+.B horizontal\-scroll\-mode (Off)
+When set to \fBOn\fP, makes readline use a single line for display,
+scrolling the input horizontally on a single screen line when it
+becomes longer than the screen width rather than wrapping to a new line.
+.TP
+.B input\-meta (Off)
+If set to \fBOn\fP, readline will enable eight-bit input (that is,
+it will not clear the eighth bit in the characters it reads),
+regardless of what the terminal claims it can support.  The name
+.B meta\-flag
+is a synonym for this variable.
+.TP
+.B isearch\-terminators (``C\-[ C\-J'')
+The string of characters that should terminate an incremental
+search without subsequently executing the character as a command.
+If this variable has not been given a value, the characters
+\fIESC\fP and \fIC\-J\fP will terminate an incremental search.
+.TP
+.B keymap (emacs)
+Set the current readline keymap.  The set of legal keymap names is
+\fIemacs, emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,
+vi-command\fP, and
+.IR vi-insert .
+\fIvi\fP is equivalent to \fIvi-command\fP; \fIemacs\fP is
+equivalent to \fIemacs-standard\fP.  The default value is
+.IR emacs .
+The value of
+.B editing\-mode
+also affects the default keymap.
+.TP
+.B mark\-directories (On)
+If set to \fBOn\fP, completed directory names have a slash
+appended.
+.TP
+.B mark\-modified\-lines (Off)
+If set to \fBOn\fP, history lines that have been modified are displayed
+with a preceding asterisk (\fB*\fP).
+.TP
+.B mark\-symlinked\-directories (Off)
+If set to \fBOn\fP, completed names which are symbolic links to directories
+have a slash appended (subject to the value of
+\fBmark\-directories\fP).
+.TP
+.B match\-hidden\-files (On)
+This variable, when set to \fBOn\fP, causes readline to match files whose 
+names begin with a `.' (hidden files) when performing filename     
+completion.
+If set to \fBOff\fP, the leading `.' must be
+supplied by the user in the filename to be completed.
+.TP
+.B menu\-complete\-display\-prefix (Off)
+If set to \fBOn\fP, menu completion displays the common prefix of the
+list of possible completions (which may be empty) before cycling through
+the list.
+.TP
+.B output\-meta (Off)
+If set to \fBOn\fP, readline will display characters with the
+eighth bit set directly rather than as a meta-prefixed escape
+sequence.
+.TP
+.B page\-completions (On)
+If set to \fBOn\fP, readline uses an internal \fImore\fP-like pager
+to display a screenful of possible completions at a time.
+.TP
+.B print\-completions\-horizontally (Off)
+If set to \fBOn\fP, readline will display completions with matches
+sorted horizontally in alphabetical order, rather than down the screen.
+.TP
+.B revert\-all\-at\-newline (Off)
+If set to \fBOn\fP, readline will undo all changes to history lines
+before returning when \fBaccept\-line\fP is executed.  By default,
+history lines may be modified and retain individual undo lists across
+calls to \fBreadline\fP.
+.TP
+.B show\-all\-if\-ambiguous (Off)
+This alters the default behavior of the completion functions.  If
+set to
+.BR On ,
+words which have more than one possible completion cause the
+matches to be listed immediately instead of ringing the bell.
+.TP
+.B show\-all\-if\-unmodified (Off)
+This alters the default behavior of the completion functions in
+a fashion similar to \fBshow\-all\-if\-ambiguous\fP.
+If set to
+.BR On , 
+words which have more than one possible completion without any
+possible partial completion (the possible completions don't share 
+a common prefix) cause the matches to be listed immediately instead
+of ringing the bell.
+.TP
+.B skip\-completed\-text (Off)
+If set to \fBOn\fP, this alters the default completion behavior when
+inserting a single match into the line.  It's only active when
+performing completion in the middle of a word.  If enabled, readline
+does not insert characters from the completion that match characters
+after point in the word being completed, so portions of the word
+following the cursor are not duplicated.
+.TP
+.B visible\-stats (Off)
+If set to \fBOn\fP, a character denoting a file's type as reported  
+by \fIstat\fP(2) is appended to the filename when listing possible
+completions.
+.PD
+.SS Conditional Constructs
+.PP
+Readline implements a facility similar in spirit to the conditional
+compilation features of the C preprocessor which allows key
+bindings and variable settings to be performed as the result
+of tests.  There are four parser directives used.
+.IP \fB$if\fP
+The 
+.B $if
+construct allows bindings to be made based on the
+editing mode, the terminal being used, or the application using
+readline.  The text of the test extends to the end of the line;
+no characters are required to isolate it.
+.RS
+.IP \fBmode\fP
+The \fBmode=\fP form of the \fB$if\fP directive is used to test
+whether readline is in emacs or vi mode.
+This may be used in conjunction
+with the \fBset keymap\fP command, for instance, to set bindings in
+the \fIemacs-standard\fP and \fIemacs-ctlx\fP keymaps only if
+readline is starting out in emacs mode.
+.IP \fBterm\fP
+The \fBterm=\fP form may be used to include terminal-specific
+key bindings, perhaps to bind the key sequences output by the
+terminal's function keys.  The word on the right side of the
+.B =
+is tested against the full name of the terminal and the portion
+of the terminal name before the first \fB\-\fP.  This allows
+.I sun
+to match both
+.I sun
+and
+.IR sun\-cmd ,
+for instance.
+.IP \fBapplication\fP
+The \fBapplication\fP construct is used to include
+application-specific settings.  Each program using the readline
+library sets the \fIapplication name\fP, and an initialization
+file can test for a particular value.
+This could be used to bind key sequences to functions useful for
+a specific program.  For instance, the following command adds a
+key sequence that quotes the current or previous word in \fBbash\fP:
+.sp 1
+.RS
+.nf
+\fB$if\fP Bash
+# Quote the current or previous word
+"\eC-xq": "\eeb\e"\eef\e""
+\fB$endif\fP
+.fi
+.RE
+.RE
+.IP \fB$endif\fP
+This command, as seen in the previous example, terminates an
+\fB$if\fP command.
+.IP \fB$else\fP
+Commands in this branch of the \fB$if\fP directive are executed if
+the test fails.
+.IP \fB$include\fP
+This directive takes a single filename as an argument and reads commands
+and bindings from that file.  For example, the following directive
+would read \fI/etc/inputrc\fP:
+.sp 1
+.RS
+.nf
+\fB$include\fP \^ \fI/etc/inputrc\fP
+.fi 
+.RE
+.SH SEARCHING
+.PP
+Readline provides commands for searching through the command history
+for lines containing a specified string.
+There are two search modes:
+.I incremental
+and
+.IR non-incremental .
+.PP
+Incremental searches begin before the user has finished typing the
+search string.
+As each character of the search string is typed, readline displays
+the next entry from the history matching the string typed so far.
+An incremental search requires only as many characters as needed to
+find the desired history entry.
+To search backward in the history for a particular string, type
+\fBC\-r\fP.  Typing \fBC\-s\fP searches forward through the history.
+The characters present in the value of the \fBisearch-terminators\fP
+variable are used to terminate an incremental search.
+If that variable has not been assigned a value the \fIEscape\fP and
+\fBC\-J\fP characters will terminate an incremental search.
+\fBC\-G\fP will abort an incremental search and restore the original
+line.
+When the search is terminated, the history entry containing the
+search string becomes the current line.
+.PP
+To find other matching entries in the history list, type \fBC\-s\fP or
+\fBC\-r\fP as appropriate.
+This will search backward or forward in the history for the next
+line matching the search string typed so far.
+Any other key sequence bound to a readline command will terminate
+the search and execute that command.
+For instance, a newline will terminate the search and accept
+the line, thereby executing the command from the history list.
+A movement command will terminate the search, make the last line found
+the current line, and begin editing.
+.PP
+Non-incremental searches read the entire search string before starting
+to search for matching history lines.  The search string may be
+typed by the user or be part of the contents of the current line.
+.SH EDITING COMMANDS
+.PP
+The following is a list of the names of the commands and the default
+key sequences to which they are bound.
+Command names without an accompanying key sequence are unbound by default.
+.PP
+In the following descriptions, \fIpoint\fP refers to the current cursor
+position, and \fImark\fP refers to a cursor position saved by the
+\fBset\-mark\fP command.
+The text between the point and mark is referred to as the \fIregion\fP.
+.SS Commands for Moving
+.PP
+.PD 0
+.TP
+.B beginning\-of\-line (C\-a)
+Move to the start of the current line.
+.TP
+.B end\-of\-line (C\-e)
+Move to the end of the line.
+.TP
+.B forward\-char (C\-f)
+Move forward a character.
+.TP
+.B backward\-char (C\-b)
+Move back a character.
+.TP
+.B forward\-word (M\-f)
+Move forward to the end of the next word.  Words are composed of
+alphanumeric characters (letters and digits).
+.TP
+.B backward\-word (M\-b)
+Move back to the start of the current or previous word.  Words are
+composed of alphanumeric characters (letters and digits).
+.TP
+.B clear\-screen (C\-l)
+Clear the screen leaving the current line at the top of the screen.
+With an argument, refresh the current line without clearing the
+screen.
+.TP
+.B redraw\-current\-line
+Refresh the current line.
+.PD
+.SS Commands for Manipulating the History
+.PP
+.PD 0
+.TP
+.B accept\-line (Newline, Return)
+Accept the line regardless of where the cursor is.
+If this line is
+non-empty, it may be added to the history list for future recall with
+\fBadd_history()\fP.
+If the line is a modified history line, the history line is restored to its original state.
+.TP
+.B previous\-history (C\-p)
+Fetch the previous command from the history list, moving back in
+the list.
+.TP
+.B next\-history (C\-n)
+Fetch the next command from the history list, moving forward in the
+list.
+.TP
+.B beginning\-of\-history (M\-<)
+Move to the first line in the history.
+.TP
+.B end\-of\-history (M\->)
+Move to the end of the input history, i.e., the line currently being
+entered.
+.TP
+.B reverse\-search\-history (C\-r)
+Search backward starting at the current line and moving `up' through
+the history as necessary.  This is an incremental search.
+.TP
+.B forward\-search\-history (C\-s)
+Search forward starting at the current line and moving `down' through
+the history as necessary.  This is an incremental search.
+.TP
+.B non\-incremental\-reverse\-search\-history (M\-p)
+Search backward through the history starting at the current line
+using a non-incremental search for a string supplied by the user.
+.TP
+.B non\-incremental\-forward\-search\-history (M\-n)
+Search forward through the history using a non-incremental search
+for a string supplied by the user.
+.TP
+.B history\-search\-backward
+Search backward through the history for the string of characters
+between the start of the current line and the current cursor
+position (the \fIpoint\fP).
+The search string must match at the beginning of a history line.
+This is a non-incremental search.
+.TP
+.B history\-search\-forward
+Search forward through the history for the string of characters
+between the start of the current line and the point.
+The search string must match at the beginning of a history line.
+This is a non-incremental search.
+.TP
+.B history\-substring\-search\-backward
+Search backward through the history for the string of characters
+between the start of the current line and the current cursor
+position (the \fIpoint\fP).
+The search string may match anywhere in a history line.
+This is a non-incremental search.
+.TP
+.B history\-substring\-search\-forward
+Search forward through the history for the string of characters
+between the start of the current line and the point.
+The search string may match anywhere in a history line.
+This is a non-incremental search.
+.TP
+.B yank\-nth\-arg (M\-C\-y)
+Insert the first argument to the previous command (usually
+the second word on the previous line) at point.
+With an argument
+.IR n ,
+insert the \fIn\fPth word from the previous command (the words
+in the previous command begin with word 0).  A negative argument
+inserts the \fIn\fPth word from the end of the previous command.
+Once the argument \fIn\fP is computed, the argument is extracted
+as if the "!\fIn\fP" history expansion had been specified.
+.TP
+.B
+yank\-last\-arg (M\-.\^, M\-_\^)
+Insert the last argument to the previous command (the last word of
+the previous history entry).
+With a numeric argument, behave exactly like \fByank\-nth\-arg\fP.
+Successive calls to \fByank\-last\-arg\fP move back through the history
+list, inserting the last word (or the word specified by the argument to
+the first call) of each line in turn.
+Any numeric argument supplied to these successive calls determines
+the direction to move through the history.  A negative argument switches
+the direction through the history (back or forward).
+The history expansion facilities are used to extract the last argument,
+as if the "!$" history expansion had been specified.
+.PD
+.SS Commands for Changing Text
+.PP
+.PD 0
+.TP
+.B delete\-char (C\-d)
+Delete the character at point.  If point is at the
+beginning of the line, there are no characters in the line, and
+the last character typed was not bound to \fBdelete\-char\fP, then return
+.SM
+.BR EOF .
+.TP
+.B backward\-delete\-char (Rubout)
+Delete the character behind the cursor.  When given a numeric argument,
+save the deleted text on the kill ring.
+.TP
+.B forward\-backward\-delete\-char   
+Delete the character under the cursor, unless the cursor is at the
+end of the line, in which case the character behind the cursor is
+deleted.
+.TP
+.B quoted\-insert (C\-q, C\-v)
+Add the next character that you type to the line verbatim.  This is
+how to insert characters like \fBC\-q\fP, for example.
+.TP
+.B tab\-insert (M-TAB)
+Insert a tab character.
+.TP
+.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...)
+Insert the character typed.
+.TP
+.B transpose\-chars (C\-t)
+Drag the character before point forward over the character at point,
+moving point forward as well.
+If point is at the end of the line, then this transposes
+the two characters before point.
+Negative arguments have no effect.
+.TP
+.B transpose\-words (M\-t)
+Drag the word before point past the word after point,
+moving point over that word as well.
+If point is at the end of the line, this transposes
+the last two words on the line.
+.TP
+.B upcase\-word (M\-u)
+Uppercase the current (or following) word.  With a negative argument,
+uppercase the previous word, but do not move point.
+.TP
+.B downcase\-word (M\-l)
+Lowercase the current (or following) word.  With a negative argument,
+lowercase the previous word, but do not move point.
+.TP
+.B capitalize\-word (M\-c)
+Capitalize the current (or following) word.  With a negative argument,
+capitalize the previous word, but do not move point.
+.TP
+.B overwrite\-mode
+Toggle overwrite mode.  With an explicit positive numeric argument,
+switches to overwrite mode.  With an explicit non-positive numeric
+argument, switches to insert mode.  This command affects only
+\fBemacs\fP mode; \fBvi\fP mode does overwrite differently.
+Each call to \fIreadline()\fP starts in insert mode.
+In overwrite mode, characters bound to \fBself\-insert\fP replace   
+the text at point rather than pushing the text to the right.
+Characters bound to \fBbackward\-delete\-char\fP replace the character
+before point with a space.  By default, this command is unbound.
+.PD
+.SS Killing and Yanking
+.PP
+.PD 0
+.TP
+.B kill\-line (C\-k)
+Kill the text from point to the end of the line.
+.TP
+.B backward\-kill\-line (C\-x Rubout)
+Kill backward to the beginning of the line.
+.TP
+.B unix\-line\-discard (C\-u)
+Kill backward from point to the beginning of the line.
+The killed text is saved on the kill-ring.
+.\" There is no real difference between this and backward-kill-line
+.TP
+.B kill\-whole\-line
+Kill all characters on the current line, no matter where point is.
+.TP
+.B kill\-word  (M\-d)
+Kill from point the end of the current word, or if between
+words, to the end of the next word.  Word boundaries are the same as
+those used by \fBforward\-word\fP.
+.TP
+.B backward\-kill\-word (M\-Rubout)
+Kill the word behind point.
+Word boundaries are the same as those used by \fBbackward\-word\fP.
+.TP
+.B unix\-word\-rubout (C\-w)
+Kill the word behind point, using white space as a word boundary.
+The killed text is saved on the kill-ring.
+.TP
+.B unix\-filename\-rubout
+Kill the word behind point, using white space and the slash character
+as the word boundaries.
+The killed text is saved on the kill-ring.
+.TP
+.B delete\-horizontal\-space (M\-\e)
+Delete all spaces and tabs around point.
+.TP
+.B kill\-region
+Kill the text between the point and \fImark\fP (saved cursor position).
+This text is referred to as the \fIregion\fP.
+.TP
+.B copy\-region\-as\-kill
+Copy the text in the region to the kill buffer.
+.TP
+.B copy\-backward\-word
+Copy the word before point to the kill buffer.
+The word boundaries are the same as \fBbackward\-word\fP.
+.TP
+.B copy\-forward\-word
+Copy the word following point to the kill buffer.
+The word boundaries are the same as \fBforward\-word\fP.
+.TP
+.B yank (C\-y)
+Yank the top of the kill ring into the buffer at point.
+.TP
+.B yank\-pop (M\-y)
+Rotate the kill ring, and yank the new top.  Only works following
+.B yank
+or
+.BR yank\-pop .
+.PD
+.SS Numeric Arguments
+.PP
+.PD 0
+.TP
+.B digit\-argument (M\-0, M\-1, ..., M\-\-)
+Add this digit to the argument already accumulating, or start a new
+argument.  M\-\- starts a negative argument.
+.TP
+.B universal\-argument
+This is another way to specify an argument.
+If this command is followed by one or more digits, optionally with a
+leading minus sign, those digits define the argument.
+If the command is followed by digits, executing
+.B universal\-argument
+again ends the numeric argument, but is otherwise ignored.
+As a special case, if this command is immediately followed by a
+character that is neither a digit or minus sign, the argument count
+for the next command is multiplied by four.
+The argument count is initially one, so executing this function the
+first time makes the argument count four, a second time makes the
+argument count sixteen, and so on.
+.PD
+.SS Completing
+.PP
+.PD 0
+.TP
+.B complete (TAB)
+Attempt to perform completion on the text before point.
+The actual completion performed is application-specific.
+.BR Bash ,
+for instance, attempts completion treating the text as a variable
+(if the text begins with \fB$\fP), username (if the text begins with
+\fB~\fP), hostname (if the text begins with \fB@\fP), or
+command (including aliases and functions) in turn.  If none
+of these produces a match, filename completion is attempted.
+.BR Gdb ,
+on the other hand,
+allows completion of program functions and variables, and
+only attempts filename completion under certain circumstances.
+.TP
+.B possible\-completions (M\-?)
+List the possible completions of the text before point.
+When displaying completions, readline sets the number of columns used
+for display to the value of \fBcompletion-display-width\fP, the value of
+the environment variable
+.SM
+.BR COLUMNS ,
+or the screen width, in that order.
+.TP
+.B insert\-completions (M\-*)
+Insert all completions of the text before point
+that would have been generated by
+\fBpossible\-completions\fP.
+.TP
+.B menu\-complete
+Similar to \fBcomplete\fP, but replaces the word to be completed
+with a single match from the list of possible completions.
+Repeated execution of \fBmenu\-complete\fP steps through the list
+of possible completions, inserting each match in turn.
+At the end of the list of completions, the bell is rung
+(subject to the setting of \fBbell\-style\fP)
+and the original text is restored.
+An argument of \fIn\fP moves \fIn\fP positions forward in the list
+of matches; a negative argument may be used to move backward 
+through the list.
+This command is intended to be bound to \fBTAB\fP, but is unbound
+by default.
+.TP
+.B menu\-complete\-backward
+Identical to \fBmenu\-complete\fP, but moves backward through the list
+of possible completions, as if \fBmenu\-complete\fP had been given a
+negative argument.  This command is unbound by default.
+.TP
+.B delete\-char\-or\-list
+Deletes the character under the cursor if not at the beginning or
+end of the line (like \fBdelete-char\fP).
+If at the end of the line, behaves identically to
+\fBpossible-completions\fP.
+.PD
+.SS Keyboard Macros
+.PP
+.PD 0
+.TP
+.B start\-kbd\-macro (C\-x (\^)
+Begin saving the characters typed into the current keyboard macro.
+.TP
+.B end\-kbd\-macro (C\-x )\^)
+Stop saving the characters typed into the current keyboard macro
+and store the definition.
+.TP
+.B call\-last\-kbd\-macro (C\-x e)
+Re-execute the last keyboard macro defined, by making the characters
+in the macro appear as if typed at the keyboard.
+.PD
+.SS Miscellaneous
+.PP
+.PD 0
+.TP
+.B re\-read\-init\-file (C\-x C\-r)
+Read in the contents of the \fIinputrc\fP file, and incorporate
+any bindings or variable assignments found there.
+.TP
+.B abort (C\-g)
+Abort the current editing command and
+ring the terminal's bell (subject to the setting of
+.BR bell\-style ).
+.TP
+.B do\-uppercase\-version (M\-a, M\-b, M\-\fIx\fP, ...)
+If the metafied character \fIx\fP is lowercase, run the command
+that is bound to the corresponding uppercase character.
+.TP
+.B prefix\-meta (ESC)
+Metafy the next character typed.
+.SM
+.B ESC
+.B f
+is equivalent to
+.BR Meta\-f .
+.TP
+.B undo (C\-_, C\-x C\-u)
+Incremental undo, separately remembered for each line.
+.TP
+.B revert\-line (M\-r)
+Undo all changes made to this line.  This is like executing the
+.B undo
+command enough times to return the line to its initial state.
+.TP
+.B tilde\-expand (M\-&)
+Perform tilde expansion on the current word.
+.TP
+.B set\-mark (C\-@, M\-<space>)
+Set the mark to the point.  If a
+numeric argument is supplied, the mark is set to that position.
+.TP
+.B exchange\-point\-and\-mark (C\-x C\-x)
+Swap the point with the mark.  The current cursor position is set to
+the saved position, and the old cursor position is saved as the mark.
+.TP
+.B character\-search (C\-])
+A character is read and point is moved to the next occurrence of that
+character.  A negative count searches for previous occurrences.
+.TP
+.B character\-search\-backward (M\-C\-])
+A character is read and point is moved to the previous occurrence of that
+character.  A negative count searches for subsequent occurrences.
+.TP
+.B skip\-csi\-sequence
+Read enough characters to consume a multi-key sequence such as those
+defined for keys like Home and End.  Such sequences begin with a
+Control Sequence Indicator (CSI), usually ESC\-[.  If this sequence is
+bound to "\e[", keys producing such sequences will have no effect
+unless explicitly bound to a readline command, instead of inserting
+stray characters into the editing buffer.  This is unbound by default,
+but usually bound to ESC\-[.
+.TP
+.B insert\-comment (M\-#)
+Without a numeric argument, the value of the readline
+.B comment\-begin
+variable is inserted at the beginning of the current line.
+If a numeric argument is supplied, this command acts as a toggle:  if
+the characters at the beginning of the line do not match the value   
+of \fBcomment\-begin\fP, the value is inserted, otherwise             
+the characters in \fBcomment-begin\fP are deleted from the beginning of
+the line.
+In either case, the line is accepted as if a newline had been typed.
+The default value of
+.B comment\-begin
+makes the current line a shell comment.
+If a numeric argument causes the comment character to be removed, the line
+will be executed by the shell.
+.TP
+.B dump\-functions
+Print all of the functions and their key bindings to the
+readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an \fIinputrc\fP file.
+.TP
+.B dump\-variables
+Print all of the settable variables and their values to the
+readline output stream.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an \fIinputrc\fP file.
+.TP
+.B dump\-macros
+Print all of the readline key sequences bound to macros and the
+strings they output.  If a numeric argument is supplied,
+the output is formatted in such a way that it can be made part
+of an \fIinputrc\fP file.
+.TP
+.B emacs\-editing\-mode (C\-e)
+When in
+.B vi
+command mode, this causes a switch to
+.B emacs
+editing mode.
+.TP
+.B vi\-editing\-mode (M\-C\-j)
+When in
+.B emacs
+editing mode, this causes a switch to
+.B vi
+editing mode.
+.PD
+.SH DEFAULT KEY BINDINGS
+.LP
+The following is a list of the default emacs and vi bindings.
+Characters with the eighth bit set are written as M\-<character>, and
+are referred to as
+.I metafied
+characters.
+The printable ASCII characters not mentioned in the list of emacs
+standard bindings are bound to the
+.B self\-insert
+function, which just inserts the given character into the input line.
+In vi insertion mode, all characters not specifically mentioned are
+bound to
+.BR self\-insert .
+Characters assigned to signal generation by
+.IR stty (1)
+or the terminal driver, such as C-Z or C-C,
+retain that function.
+Upper and lower case metafied characters are bound to the same function in
+the emacs mode meta keymap.
+The remaining characters are unbound, which causes readline
+to ring the bell (subject to the setting of the
+.B bell\-style
+variable).
+.SS Emacs Mode
+.RS +.6i
+.nf
+.ta 2.5i
+.sp
+Emacs Standard bindings
+.sp
+"C-@"  set-mark
+"C-A"  beginning-of-line
+"C-B"  backward-char
+"C-D"  delete-char
+"C-E"  end-of-line
+"C-F"  forward-char
+"C-G"  abort
+"C-H"  backward-delete-char
+"C-I"  complete
+"C-J"  accept-line
+"C-K"  kill-line
+"C-L"  clear-screen
+"C-M"  accept-line
+"C-N"  next-history
+"C-P"  previous-history
+"C-Q"  quoted-insert
+"C-R"  reverse-search-history
+"C-S"  forward-search-history
+"C-T"  transpose-chars
+"C-U"  unix-line-discard
+"C-V"  quoted-insert
+"C-W"  unix-word-rubout
+"C-Y"  yank
+"C-]"  character-search
+"C-_"  undo
+"\^ " to "/"  self-insert
+"0"  to "9"  self-insert
+":"  to "~"  self-insert
+"C-?"  backward-delete-char
+.PP
+Emacs Meta bindings
+.sp
+"M-C-G"  abort
+"M-C-H"  backward-kill-word
+"M-C-I"  tab-insert
+"M-C-J"  vi-editing-mode
+"M-C-M"  vi-editing-mode
+"M-C-R"  revert-line
+"M-C-Y"  yank-nth-arg
+"M-C-["  complete
+"M-C-]"  character-search-backward
+"M-space"  set-mark
+"M-#"  insert-comment
+"M-&"  tilde-expand
+"M-*"  insert-completions
+"M--"  digit-argument
+"M-."  yank-last-arg
+"M-0"  digit-argument
+"M-1"  digit-argument
+"M-2"  digit-argument
+"M-3"  digit-argument
+"M-4"  digit-argument
+"M-5"  digit-argument
+"M-6"  digit-argument
+"M-7"  digit-argument
+"M-8"  digit-argument
+"M-9"  digit-argument
+"M-<"  beginning-of-history
+"M-="  possible-completions
+"M->"  end-of-history
+"M-?"  possible-completions
+"M-B"  backward-word
+"M-C"  capitalize-word
+"M-D"  kill-word
+"M-F"  forward-word
+"M-L"  downcase-word
+"M-N"  non-incremental-forward-search-history
+"M-P"  non-incremental-reverse-search-history
+"M-R"  revert-line
+"M-T"  transpose-words
+"M-U"  upcase-word
+"M-Y"  yank-pop
+"M-\e"  delete-horizontal-space
+"M-~"  tilde-expand
+"M-C-?"  backward-kill-word
+"M-_"  yank-last-arg
+.PP
+Emacs Control-X bindings
+.sp
+"C-XC-G"  abort
+"C-XC-R"  re-read-init-file
+"C-XC-U"  undo
+"C-XC-X"  exchange-point-and-mark
+"C-X("  start-kbd-macro
+"C-X)"  end-kbd-macro
+"C-XE"  call-last-kbd-macro
+"C-XC-?"  backward-kill-line
+.sp
+.RE
+.SS VI Mode bindings
+.RS +.6i
+.nf
+.ta 2.5i
+.sp
+.PP
+VI Insert Mode functions
+.sp
+"C-D"  vi-eof-maybe
+"C-H"  backward-delete-char
+"C-I"  complete
+"C-J"  accept-line
+"C-M"  accept-line
+"C-R"  reverse-search-history
+"C-S"  forward-search-history
+"C-T"  transpose-chars
+"C-U"  unix-line-discard
+"C-V"  quoted-insert
+"C-W"  unix-word-rubout
+"C-Y"  yank
+"C-["  vi-movement-mode
+"C-_"  undo
+"\^ " to "~"  self-insert
+"C-?"  backward-delete-char
+.PP
+VI Command Mode functions
+.sp
+"C-D"  vi-eof-maybe
+"C-E"  emacs-editing-mode
+"C-G"  abort
+"C-H"  backward-char
+"C-J"  accept-line
+"C-K"  kill-line
+"C-L"  clear-screen
+"C-M"  accept-line
+"C-N"  next-history
+"C-P"  previous-history
+"C-Q"  quoted-insert
+"C-R"  reverse-search-history
+"C-S"  forward-search-history
+"C-T"  transpose-chars
+"C-U"  unix-line-discard
+"C-V"  quoted-insert
+"C-W"  unix-word-rubout
+"C-Y"  yank
+"C-_"  vi-undo
+"\^ "  forward-char
+"#"  insert-comment
+"$"  end-of-line
+"%"  vi-match
+"&"  vi-tilde-expand
+"*"  vi-complete
+"+"  next-history
+","  vi-char-search
+"-"  previous-history
+"."  vi-redo
+"/"  vi-search
+"0"  beginning-of-line
+"1" to "9"  vi-arg-digit
+";"  vi-char-search
+"="  vi-complete
+"?"  vi-search
+"A"  vi-append-eol
+"B"  vi-prev-word
+"C"  vi-change-to
+"D"  vi-delete-to
+"E"  vi-end-word
+"F"  vi-char-search
+"G"  vi-fetch-history
+"I"  vi-insert-beg
+"N"  vi-search-again
+"P"  vi-put
+"R"  vi-replace
+"S"  vi-subst
+"T"  vi-char-search
+"U"  revert-line
+"W"  vi-next-word
+"X"  backward-delete-char
+"Y"  vi-yank-to
+"\e"  vi-complete
+"^"  vi-first-print
+"_"  vi-yank-arg
+"`"  vi-goto-mark
+"a"  vi-append-mode
+"b"  vi-prev-word
+"c"  vi-change-to
+"d"  vi-delete-to
+"e"  vi-end-word
+"f"  vi-char-search
+"h"  backward-char
+"i"  vi-insertion-mode
+"j"  next-history
+"k"  prev-history
+"l"  forward-char
+"m"  vi-set-mark
+"n"  vi-search-again
+"p"  vi-put
+"r"  vi-change-char
+"s"  vi-subst
+"t"  vi-char-search
+"u"  vi-undo
+"w"  vi-next-word
+"x"  vi-delete
+"y"  vi-yank-to
+"|"  vi-column
+"~"  vi-change-case
+.RE
+.SH "SEE ALSO"
+.PD 0
+.TP
+\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey
+.TP
+\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey
+.TP
+\fIbash\fP(1)
+.PD
+.SH FILES
+.PD 0
+.TP
+.FN ~/.inputrc
+Individual \fBreadline\fP initialization file
+.PD
+.SH AUTHORS
+Brian Fox, Free Software Foundation
+.br
+bfox@gnu.org
+.PP
+Chet Ramey, Case Western Reserve University
+.br
+chet@ins.CWRU.Edu
+.SH BUG REPORTS
+If you find a bug in
+.B readline,
+you should report it.  But first, you should
+make sure that it really is a bug, and that it appears in the latest
+version of the
+.B readline
+library that you have.
+.PP
+Once you have determined that a bug actually exists, mail a
+bug report to \fIbug\-readline\fP@\fIgnu.org\fP.
+If you have a fix, you are welcome to mail that
+as well!  Suggestions and `philosophical' bug reports may be mailed
+to \fPbug-readline\fP@\fIgnu.org\fP or posted to the Usenet
+newsgroup
+.BR gnu.bash.bug .
+.PP
+Comments and bug reports concerning
+this manual page should be directed to
+.IR chet@ins.CWRU.Edu .
+.SH BUGS
+.PP
+It's too big and too slow.
index 2fd7499f8185a90e360c02fdc81e8b761558ae4d..7680600ed6b71af8b7390b0df0daf3ed228c4b8b 100644 (file)
@@ -1452,6 +1452,10 @@ and save the definition.
 Re-execute the last keyboard macro defined, by making the characters
 in the macro appear as if typed at the keyboard.
 
+@item print-last-kbd-macro ()
+Print the last keboard macro defined in a format suitable for the
+@var{inputrc} file.
+
 @end ftable
 
 @node Miscellaneous Commands
@@ -1800,8 +1804,9 @@ complete -D -F _completion_loader
 @section Programmable Completion Builtins
 @cindex completion builtins
 
-Two builtin commands are available to manipulate the programmable completion
-facilities.
+Three builtin commands are available to manipulate the programmable completion
+facilities: one to specify how the arguments to a particular command are to
+be completed, and two to modify the completion as it is happening.
 
 @table @code
 @item compgen
index e75c12c0bcea9ababb4bd9a9527f4a75ea3f27ac..97ce871623b25260364df698d41879034e37f3e2 100644 (file)
@@ -1800,8 +1800,9 @@ complete -D -F _completion_loader
 @section Programmable Completion Builtins
 @cindex completion builtins
 
-Two builtin commands are available to manipulate the programmable completion
-facilities.
+Three builtin commands are available to manipulate the programmable completion
+facilities: one to specify how the arguments to a particular command are to
+be completed, and two to modify the completion as it is happening.
 
 @table @code
 @item compgen
@@ -1888,6 +1889,10 @@ quoting special characters, or suppressing trailing spaces).
 This option is intended to be used with shell functions specified
 with @option{-F}.
 
+@item noquote
+Tell Readline not to quote the completed words if they are filenames
+(quoting filenames is the default).
+
 @item nospace
 Tell Readline not to append a space (the default) to words completed at
 the end of the line.
index aabab71365793833398c52915deaf8814c7181e0..c7a6bc46c0a3d6787dbb967bb53ad01056448add 100644 (file)
@@ -4,7 +4,7 @@ Copyright (C) 1988-2011 Free Software Foundation, Inc.
 
 @set EDITION 6.2
 @set VERSION 6.2
-@set UPDATED December 10 2011
+@set UPDATED December 21 2011
 @set UPDATED-MONTH December 2011
 
-@set LASTCHANGE Sat Dec 10 21:53:20 EST 2011
+@set LASTCHANGE Wed Dec 21 21:04:12 EST 2011
index bcd6b47297baafe9da7a81a723e21d998861a998..aabab71365793833398c52915deaf8814c7181e0 100644 (file)
@@ -4,7 +4,7 @@ Copyright (C) 1988-2011 Free Software Foundation, Inc.
 
 @set EDITION 6.2
 @set VERSION 6.2
-@set UPDATED October 2 2011
-@set UPDATED-MONTH October 2011
+@set UPDATED December 10 2011
+@set UPDATED-MONTH December 2011
 
-@set LASTCHANGE Sun Oct  2 15:54:47 EDT 2011
+@set LASTCHANGE Sat Dec 10 21:53:20 EST 2011
index bd306f4355175b9a5f4d57d60fb349efcf30b7d5..363507b86778d8fb27b1b56b15194e61a28dd85f 100644 (file)
@@ -120,6 +120,7 @@ static const FUNMAP default_funmap[] = {
 #endif
   { "possible-completions", rl_possible_completions },
   { "previous-history", rl_get_previous_history },
+  { "print-last-kbd-macro", rl_print_last_kbd_macro },
   { "quoted-insert", rl_quoted_insert },
   { "re-read-init-file", rl_re_read_init_file },
   { "redraw-current-line", rl_refresh_line},
index f7b20371dd4e2d800e9501b9b91d8973a10fce07..bd306f4355175b9a5f4d57d60fb349efcf30b7d5 100644 (file)
@@ -238,7 +238,7 @@ rl_initialize_funmap ()
 
 /* Produce a NULL terminated array of known function names.  The array
    is sorted.  The array itself is allocated, but not the strings inside.
-   You should free () the array when you done, but not the pointrs. */
+   You should free () the array when you done, but not the pointers. */
 const char **
 rl_funmap_names ()
 {
index d7894cfd0a4202bacfff38ecd6c871f03a9be2cf..83d56949eefa960423558f8fb3ec309274c47297 100644 (file)
@@ -1,6 +1,6 @@
 /* history.c -- standalone history library */
 
-/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2011 Free Software Foundation, Inc.
 
    This file contains the GNU History Library (History), a set of
    routines for managing the text of previously typed lines.
@@ -236,7 +236,7 @@ history_get_time (hist)
   ts = hist->timestamp;
   if (ts[0] != history_comment_char)
     return 0;
-  t = (time_t) atol (ts + 1);          /* XXX - should use strtol() here */
+  t = (time_t) strtol (ts + 1, (char **)NULL, 10);             /* XXX - should use strtol() here */
   return t;
 }
 
diff --git a/lib/readline/history.c~ b/lib/readline/history.c~
new file mode 100644 (file)
index 0000000..d7894cf
--- /dev/null
@@ -0,0 +1,519 @@
+/* history.c -- standalone history library */
+
+/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
+
+   This file contains the GNU History Library (History), a set of
+   routines for managing the text of previously typed lines.
+
+   History is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   History is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with History.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* The goal is to make the implementation transparent, so that you
+   don't have to know what data types are used, just what functions
+   you can call.  I think I have done that. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include "history.h"
+#include "histlib.h"
+
+#include "xmalloc.h"
+
+/* The number of slots to increase the_history by. */
+#define DEFAULT_HISTORY_GROW_SIZE 50
+
+static char *hist_inittime PARAMS((void));
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* An array of HIST_ENTRY.  This is where we store the history. */
+static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
+
+/* Non-zero means that we have enforced a limit on the amount of
+   history that we save. */
+static int history_stifled;
+
+/* The current number of slots allocated to the input_history. */
+static int history_size;
+
+/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
+   entries to remember. */
+int history_max_entries;
+int max_input_history; /* backwards compatibility */
+
+/* The current location of the interactive history pointer.  Just makes
+   life easier for outside callers. */
+int history_offset;
+
+/* The number of strings currently stored in the history list. */
+int history_length;
+
+/* The logical `base' of the history array.  It defaults to 1. */
+int history_base = 1;
+
+/* Return the current HISTORY_STATE of the history. */
+HISTORY_STATE *
+history_get_history_state ()
+{
+  HISTORY_STATE *state;
+
+  state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
+  state->entries = the_history;
+  state->offset = history_offset;
+  state->length = history_length;
+  state->size = history_size;
+  state->flags = 0;
+  if (history_stifled)
+    state->flags |= HS_STIFLED;
+
+  return (state);
+}
+
+/* Set the state of the current history array to STATE. */
+void
+history_set_history_state (state)
+     HISTORY_STATE *state;
+{
+  the_history = state->entries;
+  history_offset = state->offset;
+  history_length = state->length;
+  history_size = state->size;
+  if (state->flags & HS_STIFLED)
+    history_stifled = 1;
+}
+
+/* Begin a session in which the history functions might be used.  This
+   initializes interactive variables. */
+void
+using_history ()
+{
+  history_offset = history_length;
+}
+
+/* Return the number of bytes that the primary history entries are using.
+   This just adds up the lengths of the_history->lines and the associated
+   timestamps. */
+int
+history_total_bytes ()
+{
+  register int i, result;
+
+  for (i = result = 0; the_history && the_history[i]; i++)
+    result += HISTENT_BYTES (the_history[i]);
+
+  return (result);
+}
+
+/* Returns the magic number which says what history element we are
+   looking at now.  In this implementation, it returns history_offset. */
+int
+where_history ()
+{
+  return (history_offset);
+}
+
+/* Make the current history item be the one at POS, an absolute index.
+   Returns zero if POS is out of range, else non-zero. */
+int
+history_set_pos (pos)
+     int pos;
+{
+  if (pos > history_length || pos < 0 || !the_history)
+    return (0);
+  history_offset = pos;
+  return (1);
+}
+/* Return the current history array.  The caller has to be careful, since this
+   is the actual array of data, and could be bashed or made corrupt easily.
+   The array is terminated with a NULL pointer. */
+HIST_ENTRY **
+history_list ()
+{
+  return (the_history);
+}
+
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *
+current_history ()
+{
+  return ((history_offset == history_length) || the_history == 0)
+               ? (HIST_ENTRY *)NULL
+               : the_history[history_offset];
+}
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry then return
+   a NULL pointer. */
+HIST_ENTRY *
+previous_history ()
+{
+  return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
+}
+
+/* Move history_offset forward to the next history entry, and return
+   a pointer to that entry.  If there is no next entry then return a
+   NULL pointer. */
+HIST_ENTRY *
+next_history ()
+{
+  return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
+}
+
+/* Return the history entry which is logically at OFFSET in the history array.
+   OFFSET is relative to history_base. */
+HIST_ENTRY *
+history_get (offset)
+     int offset;
+{
+  int local_index;
+
+  local_index = offset - history_base;
+  return (local_index >= history_length || local_index < 0 || the_history == 0)
+               ? (HIST_ENTRY *)NULL
+               : the_history[local_index];
+}
+
+HIST_ENTRY *
+alloc_history_entry (string, ts)
+     char *string;
+     char *ts;
+{
+  HIST_ENTRY *temp;
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+
+  temp->line = string ? savestring (string) : string;
+  temp->data = (char *)NULL;
+  temp->timestamp = ts;
+
+  return temp;
+}
+
+time_t
+history_get_time (hist)
+     HIST_ENTRY *hist;
+{
+  char *ts;
+  time_t t;
+
+  if (hist == 0 || hist->timestamp == 0)
+    return 0;
+  ts = hist->timestamp;
+  if (ts[0] != history_comment_char)
+    return 0;
+  t = (time_t) atol (ts + 1);          /* XXX - should use strtol() here */
+  return t;
+}
+
+static char *
+hist_inittime ()
+{
+  time_t t;
+  char ts[64], *ret;
+
+  t = (time_t) time ((time_t *)0);
+#if defined (HAVE_VSNPRINTF)           /* assume snprintf if vsnprintf exists */
+  snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
+#else
+  sprintf (ts, "X%lu", (unsigned long) t);
+#endif
+  ret = savestring (ts);
+  ret[0] = history_comment_char;
+
+  return ret;
+}
+
+/* Place STRING at the end of the history list.  The data field
+   is  set to NULL. */
+void
+add_history (string)
+     const char *string;
+{
+  HIST_ENTRY *temp;
+
+  if (history_stifled && (history_length == history_max_entries))
+    {
+      register int i;
+
+      /* If the history is stifled, and history_length is zero,
+        and it equals history_max_entries, we don't save items. */
+      if (history_length == 0)
+       return;
+
+      /* If there is something in the slot, then remove it. */
+      if (the_history[0])
+       (void) free_history_entry (the_history[0]);
+
+      /* Copy the rest of the entries, moving down one slot. */
+      for (i = 0; i < history_length; i++)
+       the_history[i] = the_history[i + 1];
+
+      history_base++;
+    }
+  else
+    {
+      if (history_size == 0)
+       {
+         history_size = DEFAULT_HISTORY_GROW_SIZE;
+         the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
+         history_length = 1;
+       }
+      else
+       {
+         if (history_length == (history_size - 1))
+           {
+             history_size += DEFAULT_HISTORY_GROW_SIZE;
+             the_history = (HIST_ENTRY **)
+               xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
+           }
+         history_length++;
+       }
+    }
+
+  temp = alloc_history_entry (string, hist_inittime ());
+
+  the_history[history_length] = (HIST_ENTRY *)NULL;
+  the_history[history_length - 1] = temp;
+}
+
+/* Change the time stamp of the most recent history entry to STRING. */
+void
+add_history_time (string)
+     const char *string;
+{
+  HIST_ENTRY *hs;
+
+  if (string == 0)
+    return;
+  hs = the_history[history_length - 1];
+  FREE (hs->timestamp);
+  hs->timestamp = savestring (string);
+}
+
+/* Free HIST and return the data so the calling application can free it
+   if necessary and desired. */
+histdata_t
+free_history_entry (hist)
+     HIST_ENTRY *hist;
+{
+  histdata_t x;
+
+  if (hist == 0)
+    return ((histdata_t) 0);
+  FREE (hist->line);
+  FREE (hist->timestamp);
+  x = hist->data;
+  xfree (hist);
+  return (x);
+}
+
+HIST_ENTRY *
+copy_history_entry (hist)
+     HIST_ENTRY *hist;
+{
+  HIST_ENTRY *ret;
+  char *ts;
+
+  if (hist == 0)
+    return hist;
+
+  ret = alloc_history_entry (hist->line, (char *)NULL);
+
+  ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp;
+  ret->timestamp = ts;
+
+  ret->data = hist->data;
+
+  return ret;
+}
+  
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+HIST_ENTRY *
+replace_history_entry (which, line, data)
+     int which;
+     const char *line;
+     histdata_t data;
+{
+  HIST_ENTRY *temp, *old_value;
+
+  if (which < 0 || which >= history_length)
+    return ((HIST_ENTRY *)NULL);
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  old_value = the_history[which];
+
+  temp->line = savestring (line);
+  temp->data = data;
+  temp->timestamp = savestring (old_value->timestamp);
+  the_history[which] = temp;
+
+  return (old_value);
+}
+
+/* Replace the DATA in the specified history entries, replacing OLD with
+   NEW.  WHICH says which one(s) to replace:  WHICH == -1 means to replace
+   all of the history entries where entry->data == OLD; WHICH == -2 means
+   to replace the `newest' history entry where entry->data == OLD; and
+   WHICH >= 0 means to replace that particular history entry's data, as
+   long as it matches OLD. */
+void
+replace_history_data (which,old, new)
+     int which;
+     histdata_t *old, *new;
+{
+  HIST_ENTRY *entry;
+  register int i, last;
+
+  if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
+    return;
+
+  if (which >= 0)
+    {
+      entry = the_history[which];
+      if (entry && entry->data == old)
+       entry->data = new;
+      return;
+    }
+
+  last = -1;
+  for (i = 0; i < history_length; i++)
+    {
+      entry = the_history[i];
+      if (entry == 0)
+       continue;
+      if (entry->data == old)
+       {
+         last = i;
+         if (which == -1)
+           entry->data = new;
+       }
+    }
+  if (which == -2 && last >= 0)
+    {
+      entry = the_history[last];
+      entry->data = new;       /* XXX - we don't check entry->old */
+    }
+}      
+  
+/* Remove history element WHICH from the history.  The removed
+   element is returned to you so you can free the line, data,
+   and containing structure. */
+HIST_ENTRY *
+remove_history (which)
+     int which;
+{
+  HIST_ENTRY *return_value;
+  register int i;
+
+  if (which < 0 || which >= history_length || history_length ==  0 || the_history == 0)
+    return ((HIST_ENTRY *)NULL);
+
+  return_value = the_history[which];
+
+  for (i = which; i < history_length; i++)
+    the_history[i] = the_history[i + 1];
+
+  history_length--;
+
+  return (return_value);
+}
+
+/* Stifle the history list, remembering only MAX number of lines. */
+void
+stifle_history (max)
+     int max;
+{
+  register int i, j;
+
+  if (max < 0)
+    max = 0;
+
+  if (history_length > max)
+    {
+      /* This loses because we cannot free the data. */
+      for (i = 0, j = history_length - max; i < j; i++)
+       free_history_entry (the_history[i]);
+
+      history_base = i;
+      for (j = 0, i = history_length - max; j < max; i++, j++)
+       the_history[j] = the_history[i];
+      the_history[j] = (HIST_ENTRY *)NULL;
+      history_length = j;
+    }
+
+  history_stifled = 1;
+  max_input_history = history_max_entries = max;
+}
+
+/* Stop stifling the history.  This returns the previous maximum
+   number of history entries.  The value is positive if the history
+   was stifled, negative if it wasn't. */
+int
+unstifle_history ()
+{
+  if (history_stifled)
+    {
+      history_stifled = 0;
+      return (history_max_entries);
+    }
+  else
+    return (-history_max_entries);
+}
+
+int
+history_is_stifled ()
+{
+  return (history_stifled);
+}
+
+void
+clear_history ()
+{
+  register int i;
+
+  /* This loses because we cannot free the data. */
+  for (i = 0; i < history_length; i++)
+    {
+      free_history_entry (the_history[i]);
+      the_history[i] = (HIST_ENTRY *)NULL;
+    }
+
+  history_offset = history_length = 0;
+}
index 1e6e54294cce47ab1b183d59bf6a524569fb14c9..9f72706578f6ad9610e1b8282e2d3956e874a661 100644 (file)
@@ -263,6 +263,29 @@ rl_call_last_kbd_macro (count, ignore)
   return 0;
 }
 
+int
+rl_print_last_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  char *m;
+
+  if (current_macro == 0)
+    {
+      rl_ding ();
+      return 0;
+    }
+  m = _rl_untranslate_macro_value (current_macro, 1);
+  rl_crlf ();
+  printf ("%s", m);
+  fflush (stdout);
+  rl_crlf ();
+  FREE (m);
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
 void
 rl_push_macro_input (macro)
      char *macro;
index c2fac8addbe9b552ab9c6a73ec327d46d5504623..fea37615e366a23c9c77bfec0d5c6e7554fc56d1 100644 (file)
@@ -234,7 +234,7 @@ rl_end_kbd_macro (count, ignore)
       return -1;
     }
 
-  current_macro_index -= rl_key_sequence_length - 1;
+  current_macro_index -= rl_key_sequence_length;
   current_macro[current_macro_index] = '\0';
 
   RL_UNSETSTATE(RL_STATE_MACRODEF);
@@ -263,6 +263,28 @@ rl_call_last_kbd_macro (count, ignore)
   return 0;
 }
 
+int
+rl_print_last_kbd_macro (count, ignore)
+     int count, ignore;
+{
+  char *m;
+
+  if (current_macro == 0)
+    {
+      rl_ding ();
+      return 0;
+    }
+  m = _rl_untranslate_macro_value (current_macro, 1);
+  rl_crlf ();
+  printf ("%s", m);
+  rl_crlf ();
+  FREE (m);
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
 void
 rl_push_macro_input (macro)
      char *macro;
index 963957e26e0cfc4487f824a56d9c1d68be6aa846..bde2978961249157f020a71f9792bdf3bd131e68 100644 (file)
@@ -185,6 +185,7 @@ extern int rl_forward_search_history PARAMS((int, int));
 extern int rl_start_kbd_macro PARAMS((int, int));
 extern int rl_end_kbd_macro PARAMS((int, int));
 extern int rl_call_last_kbd_macro PARAMS((int, int));
+extern int rl_print_last_kbd_macro PARAMS((int, int));
 
 /* Bindable undo commands. */
 extern int rl_revert_line PARAMS((int, int));
index 2cf83b46a09932c28a4d1ae4c4d44b706d220303..963957e26e0cfc4487f824a56d9c1d68be6aa846 100644 (file)
@@ -577,6 +577,7 @@ extern Keymap rl_binding_keymap;
 
 extern int rl_executing_key;
 extern char *rl_executing_keyseq;
+extern int rl_key_sequence_length;
 
 /* Display variables. */
 /* If non-zero, readline will erase the entire line, including any prompt,
index ea9eeecd88c65650d93dd3b70006725399b83110..dfdc881d6e18bd17524994a05adb8a4bd3df04e3 100644 (file)
@@ -246,6 +246,7 @@ extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *));
 #endif /* READLINE_CALLBACKS */
 
 /* bind.c */
+extern char *_rl_untranslate_macro_value PARAMS((char *, int));
 
 /* complete.c */
 extern void _rl_reset_completion_state PARAMS((void));
index f705cece523781bd477c749ef45ee2e5d49dd9ac..1c7f356c3fc7db53050fe088f4f87af1948e1bf4 100644 (file)
@@ -185,7 +185,6 @@ extern int rl_visible_stats;
 extern int rl_line_buffer_len;
 extern int rl_arg_sign;
 extern int rl_visible_prompt_length;
-extern int rl_key_sequence_length;
 extern int rl_byte_oriented;
 
 /* display.c */
@@ -247,6 +246,7 @@ extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *));
 #endif /* READLINE_CALLBACKS */
 
 /* bind.c */
+extern char *_rl_untranslate_macro_value PARAMS ((char *, int));
 
 /* complete.c */
 extern void _rl_reset_completion_state PARAMS((void));
index 536e31af602da96b33ceb16a9b0c8433f75a5850..807a0659ec903f5862224e4c4b6ad16861ddbcc6 100644 (file)
@@ -908,6 +908,9 @@ _rl_insert_next (count)
   if (c < 0)
     return -1;
 
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
+    _rl_add_macro_char (c);
+
 #if defined (HANDLE_SIGNALS)
   if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
     _rl_restore_tty_signals ();
diff --git a/lib/readline/text.c~ b/lib/readline/text.c~
new file mode 100644 (file)
index 0000000..f70a61a
--- /dev/null
@@ -0,0 +1,1705 @@
+/* text.c -- text handling commands for readline. */
+
+/* Copyright (C) 1987-2010 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library (Readline), a library
+   for reading lines of text with interactive input and history editing.      
+
+   Readline is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Readline is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Readline.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_LOCALE_H)
+#  include <locale.h>
+#endif
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#if defined (__EMX__)
+#  define INCL_DOSPROCESS
+#  include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Forward declarations. */
+static int rl_change_case PARAMS((int, int));
+static int _rl_char_search PARAMS((int, int, int));
+
+#if defined (READLINE_CALLBACKS)
+static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *));
+static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *));
+#endif
+
+/* The largest chunk of text that can be inserted in one call to
+   rl_insert_text.  Text blocks larger than this are divided. */
+#define TEXT_COUNT_MAX 1024
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Insert and Delete                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point.  This is the only
+   way that you should do insertion.  _rl_insert_char () calls this
+   function.  Returns the number of characters inserted. */
+int
+rl_insert_text (string)
+     const char *string;
+{
+  register int i, l;
+
+  l = (string && *string) ? strlen (string) : 0;
+  if (l == 0)
+    return 0;
+
+  if (rl_end + l >= rl_line_buffer_len)
+    rl_extend_line_buffer (rl_end + l);
+
+  for (i = rl_end; i >= rl_point; i--)
+    rl_line_buffer[i + l] = rl_line_buffer[i];
+  strncpy (rl_line_buffer + rl_point, string, l);
+
+  /* Remember how to undo this if we aren't undoing something. */
+  if (_rl_doing_an_undo == 0)
+    {
+      /* If possible and desirable, concatenate the undos. */
+      if ((l == 1) &&
+         rl_undo_list &&
+         (rl_undo_list->what == UNDO_INSERT) &&
+         (rl_undo_list->end == rl_point) &&
+         (rl_undo_list->end - rl_undo_list->start < 20))
+       rl_undo_list->end++;
+      else
+       rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+    }
+  rl_point += l;
+  rl_end += l;
+  rl_line_buffer[rl_end] = '\0';
+  return l;
+}
+
+/* Delete the string between FROM and TO.  FROM is inclusive, TO is not.
+   Returns the number of characters deleted. */
+int
+rl_delete_text (from, to)
+     int from, to;
+{
+  register char *text;
+  register int diff, i;
+
+  /* Fix it if the caller is confused. */
+  if (from > to)
+    SWAP (from, to);
+
+  /* fix boundaries */
+  if (to > rl_end)
+    {
+      to = rl_end;
+      if (from > to)
+       from = to;
+    }
+  if (from < 0)
+    from = 0;
+
+  text = rl_copy_text (from, to);
+
+  /* Some versions of strncpy() can't handle overlapping arguments. */
+  diff = to - from;
+  for (i = from; i < rl_end - diff; i++)
+    rl_line_buffer[i] = rl_line_buffer[i + diff];
+
+  /* Remember how to undo this delete. */
+  if (_rl_doing_an_undo == 0)
+    rl_add_undo (UNDO_DELETE, from, to, text);
+  else
+    xfree (text);
+
+  rl_end -= diff;
+  rl_line_buffer[rl_end] = '\0';
+  return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+   text.  If FIX_MARK_TOO is non-zero, the mark is forced within line
+   boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+       do { \
+       if (x > rl_end) \
+         x = rl_end; \
+       else if (x < 0) \
+         x = 0; \
+       } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+     int fix_mark_too;
+{
+  _RL_FIX_POINT (rl_point);
+  if (fix_mark_too)
+    _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+/* Replace the contents of the line buffer between START and END with
+   TEXT.  The operation is undoable.  To replace the entire line in an
+   undoable mode, use _rl_replace_text(text, 0, rl_end); */
+int
+_rl_replace_text (text, start, end)
+     const char *text;
+     int start, end;
+{
+  int n;
+
+  n = 0;
+  rl_begin_undo_group ();
+  if (start <= end)
+    rl_delete_text (start, end + 1);
+  rl_point = start;
+  if (*text)
+    n = rl_insert_text (text);
+  rl_end_undo_group ();
+
+  return n;
+}
+
+/* Replace the current line buffer contents with TEXT.  If CLEAR_UNDO is
+   non-zero, we free the current undo list. */
+void
+rl_replace_line (text, clear_undo)
+     const char *text;
+     int clear_undo;
+{
+  int len;
+
+  len = strlen (text);
+  if (len >= rl_line_buffer_len)
+    rl_extend_line_buffer (len);
+  strcpy (rl_line_buffer, text);
+  rl_end = len;
+
+  if (clear_undo)
+    rl_free_undo_list ();
+
+  _rl_fix_point (1);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Readline character functions                */
+/*                                                                 */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine.  No hair
+   is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+   rl_end is the place in the string that we would place '\0';
+   i.e., it is always safe to place '\0' there.
+
+   rl_point is the place in the string where the cursor is.  Sometimes
+   this is the same as rl_end.
+
+   Any command that is called interactively receives two arguments.
+   The first is a count: the numeric arg pased to this command.
+   The second is the key which invoked this command.
+*/
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Movement Commands                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+   use said functions in other functions which do not do optimizing display.
+   I.e., you will have to update the data base for rl_redisplay, and you
+   might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT bytes. */
+int
+rl_forward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_backward_byte (-count, key));
+
+  if (count > 0)
+    {
+      int end, lend;
+
+      end = rl_point + count;
+#if defined (VI_MODE)
+      lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
+#else
+      lend = rl_end;
+#endif
+
+      if (end > lend)
+       {
+         rl_point = lend;
+         rl_ding ();
+       }
+      else
+       rl_point = end;
+    }
+
+  if (rl_end < 0)
+    rl_end = 0;
+
+  return 0;
+}
+
+int
+_rl_forward_char_internal (count)
+     int count;
+{
+  int point;
+
+#if defined (HANDLE_MULTIBYTE)
+  point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+#if defined (VI_MODE)
+  if (point >= rl_end && VI_COMMAND_MODE())
+    point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
+#endif
+
+    if (rl_end < 0)
+       rl_end = 0;
+#else
+  point = rl_point + count;
+  if (point > rl_end)
+    point = rl_end;
+#endif
+
+  return (point);
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move forward COUNT characters. */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_forward_byte (count, key));
+
+  if (count < 0)
+    return (rl_backward_char (-count, key));
+
+  if (count > 0)
+    {
+      if (rl_point == rl_end && EMACS_MODE())
+       {
+         rl_ding ();
+         return 0;
+       }
+
+      point = _rl_forward_char_internal (count);
+
+      if (rl_point == point)
+       rl_ding ();
+
+      rl_point = point;
+    }
+
+  return 0;
+}
+#else /* !HANDLE_MULTIBYTE */
+int
+rl_forward_char (count, key)
+     int count, key;
+{
+  return (rl_forward_byte (count, key));
+}
+#endif /* !HANDLE_MULTIBYTE */
+  
+/* Backwards compatibility. */
+int
+rl_forward (count, key)
+     int count, key;
+{
+  return (rl_forward_char (count, key));
+}
+
+/* Move backward COUNT bytes. */
+int
+rl_backward_byte (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_forward_byte (-count, key));
+
+  if (count > 0)
+    {
+      if (rl_point < count)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+       rl_point -= count;
+    }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move backward COUNT characters. */
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  int point;
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    return (rl_backward_byte (count, key));
+
+  if (count < 0)
+    return (rl_forward_char (-count, key));
+
+  if (count > 0)
+    {
+      point = rl_point;
+
+      while (count > 0 && point > 0)
+       {
+         point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
+         count--;
+       }
+      if (count > 0)
+       {
+         rl_point = 0;
+         rl_ding ();
+       }
+      else
+        rl_point = point;
+    }
+
+  return 0;
+}
+#else
+int
+rl_backward_char (count, key)
+     int count, key;
+{
+  return (rl_backward_byte (count, key));
+}
+#endif
+
+/* Backwards compatibility. */
+int
+rl_backward (count, key)
+     int count, key;
+{
+  return (rl_backward_char (count, key));
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+     int count, key;
+{
+  rl_point = 0;
+  return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+     int count, key;
+{
+  rl_point = rl_end;
+  return 0;
+}
+
+/* Move forward a word.  We do what Emacs does.  Handles multibyte chars. */
+int
+rl_forward_word (count, key)
+     int count, key;
+{
+  int c;
+
+  if (count < 0)
+    return (rl_backward_word (-count, key));
+
+  while (count)
+    {
+      if (rl_point == rl_end)
+       return 0;
+
+      /* If we are not in a word, move forward until we are in one.
+        Then, move forward until we hit a non-alphabetic character. */
+      c = _rl_char_value (rl_line_buffer, rl_point);
+
+      if (_rl_walphabetic (c) == 0)
+       {
+         rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+         while (rl_point < rl_end)
+           {
+             c = _rl_char_value (rl_line_buffer, rl_point);
+             if (_rl_walphabetic (c))
+               break;
+             rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+           }
+       }
+
+      if (rl_point == rl_end)
+       return 0;
+
+      rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+      while (rl_point < rl_end)
+       {
+         c = _rl_char_value (rl_line_buffer, rl_point);
+         if (_rl_walphabetic (c) == 0)
+           break;
+         rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Move backward a word.  We do what Emacs does.  Handles multibyte chars. */
+int
+rl_backward_word (count, key)
+     int count, key;
+{
+  int c, p;
+
+  if (count < 0)
+    return (rl_forward_word (-count, key));
+
+  while (count)
+    {
+      if (rl_point == 0)
+       return 0;
+
+      /* Like rl_forward_word (), except that we look at the characters
+        just before point. */
+
+      p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      c = _rl_char_value (rl_line_buffer, p);
+
+      if (_rl_walphabetic (c) == 0)
+       {
+         rl_point = p;
+         while (rl_point > 0)
+           {
+             p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+             c = _rl_char_value (rl_line_buffer, p);
+             if (_rl_walphabetic (c))
+               break;
+             rl_point = p;
+           }
+       }
+
+      while (rl_point)
+       {
+         p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+         c = _rl_char_value (rl_line_buffer, p);         
+         if (_rl_walphabetic (c) == 0)
+           break;
+         else
+           rl_point = p;
+       }
+
+      --count;
+    }
+
+  return 0;
+}
+
+/* Clear the current line.  Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  int curr_line;
+
+  curr_line = _rl_current_display_line ();
+
+  _rl_move_vert (curr_line);
+  _rl_move_cursor_relative (0, rl_line_buffer);   /* XXX is this right */
+
+  _rl_clear_to_eol (0);                /* arg of 0 means to not use spaces */
+
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+   the prompt and the current input line.  Given a numeric arg, redraw only
+   the current line. */
+int
+rl_clear_screen (count, key)
+     int count, key;
+{
+  if (rl_explicit_arg)
+    {
+      rl_refresh_line (count, key);
+      return 0;
+    }
+
+  _rl_clear_screen ();         /* calls termcap function to clear screen */
+  rl_forced_update_display ();
+  rl_display_fixed = 1;
+
+  return 0;
+}
+
+int
+rl_skip_csi_sequence (count, key)
+     int count, key;
+{
+  int ch;
+
+  RL_SETSTATE (RL_STATE_MOREINPUT);
+  do
+    ch = rl_read_key ();
+  while (ch >= 0x20 && ch < 0x40);
+  RL_UNSETSTATE (RL_STATE_MOREINPUT);
+
+  return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+     int count, c;
+{
+  int ch;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  ch = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  switch (_rl_to_upper (ch))
+    {
+    case 'A':
+      rl_get_previous_history (count, ch);
+      break;
+
+    case 'B':
+      rl_get_next_history (count, ch);
+      break;
+
+    case 'C':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, ch);
+      else
+       rl_forward_byte (count, ch);
+      break;
+
+    case 'D':
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_backward_char (count, ch);
+      else
+       rl_backward_byte (count, ch);
+      break;
+
+    default:
+      rl_ding ();
+    }
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Text commands                               */
+/*                                                                 */
+/* **************************************************************** */
+
+#ifdef HANDLE_MULTIBYTE
+static char pending_bytes[MB_LEN_MAX];
+static int pending_bytes_length = 0;
+static mbstate_t ps = {0};
+#endif
+
+/* Insert the character C at the current location, moving point forward.
+   If C introduces a multibyte sequence, we read the whole sequence and
+   then insert the multibyte char into the line buffer. */
+int
+_rl_insert_char (count, c)
+     int count, c;
+{
+  register int i;
+  char *string;
+#ifdef HANDLE_MULTIBYTE
+  int string_size;
+  char incoming[MB_LEN_MAX + 1];
+  int incoming_length = 0;
+  mbstate_t ps_back;
+  static int stored_count = 0;
+#endif
+
+  if (count <= 0)
+    return 0;
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      incoming[0] = c;
+      incoming[1] = '\0';
+      incoming_length = 1;
+    }
+  else
+    {
+      wchar_t wc;
+      size_t ret;
+
+      if (stored_count <= 0)
+       stored_count = count;
+      else
+       count = stored_count;
+
+      ps_back = ps;
+      pending_bytes[pending_bytes_length++] = c;
+      ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
+
+      if (ret == (size_t)-2)
+       {
+         /* Bytes too short to compose character, try to wait for next byte.
+            Restore the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         ps = ps_back;
+         return 1;
+       }
+      else if (ret == (size_t)-1)
+       {
+         /* Invalid byte sequence for the current locale.  Treat first byte
+            as a single character. */
+         incoming[0] = pending_bytes[0];
+         incoming[1] = '\0';
+         incoming_length = 1;
+         pending_bytes_length--;
+         memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else if (ret == (size_t)0)
+       {
+         incoming[0] = '\0';
+         incoming_length = 0;
+         pending_bytes_length--;
+         /* Clear the state of the byte sequence, because in this case the
+            effect of mbstate is undefined. */
+         memset (&ps, 0, sizeof (mbstate_t));
+       }
+      else
+       {
+         /* We successfully read a single multibyte character. */
+         memcpy (incoming, pending_bytes, pending_bytes_length);
+         incoming[pending_bytes_length] = '\0';
+         incoming_length = pending_bytes_length;
+         pending_bytes_length = 0;
+       }
+    }
+#endif /* HANDLE_MULTIBYTE */
+         
+  /* If we can optimize, then do it.  But don't let people crash
+     readline because of extra large arguments. */
+  if (count > 1 && count <= TEXT_COUNT_MAX)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      string_size = count * incoming_length;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      string = (char *)xmalloc (1 + count);
+
+      for (i = 0; i < count; i++)
+       string[i] = c;
+#endif /* !HANDLE_MULTIBYTE */
+
+      string[i] = '\0';
+      rl_insert_text (string);
+      xfree (string);
+
+      return 0;
+    }
+
+  if (count > TEXT_COUNT_MAX)
+    {
+      int decreaser;
+#if defined (HANDLE_MULTIBYTE)
+      string_size = incoming_length * TEXT_COUNT_MAX;
+      string = (char *)xmalloc (1 + string_size);
+
+      i = 0;
+      while (i < string_size)
+       {
+         strncpy (string + i, incoming, incoming_length);
+         i += incoming_length;
+       }
+
+      while (count)
+       {
+         decreaser = (count > TEXT_COUNT_MAX) ? TEXT_COUNT_MAX : count;
+         string[decreaser*incoming_length] = '\0';
+         rl_insert_text (string);
+         count -= decreaser;
+       }
+
+      xfree (string);
+      incoming_length = 0;
+      stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+      char str[TEXT_COUNT_MAX+1];
+
+      for (i = 0; i < TEXT_COUNT_MAX; i++)
+       str[i] = c;
+
+      while (count)
+       {
+         decreaser = (count > TEXT_COUNT_MAX ? TEXT_COUNT_MAX : count);
+         str[decreaser] = '\0';
+         rl_insert_text (str);
+         count -= decreaser;
+       }
+#endif /* !HANDLE_MULTIBYTE */
+
+      return 0;
+    }
+
+  if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      /* We are inserting a single character.
+        If there is pending input, then make a string of all of the
+        pending characters that are bound to rl_insert, and insert
+        them all.  Don't do this if we're current reading input from
+        a macro. */
+      if ((RL_ISSTATE (RL_STATE_MACROINPUT) == 0) && _rl_any_typein ())
+       _rl_insert_typein (c);
+      else
+       {
+         /* Inserting a single character. */
+         char str[2];
+
+         str[1] = '\0';
+         str[0] = c;
+         rl_insert_text (str);
+       }
+    }
+#if defined (HANDLE_MULTIBYTE)
+  else
+    {
+      rl_insert_text (incoming);
+      stored_count = 0;
+    }
+#endif
+
+  return 0;
+}
+
+/* Overwrite the character at point (or next COUNT characters) with C.
+   If C introduces a multibyte character sequence, read the entire sequence
+   before starting the overwrite loop. */
+int
+_rl_overwrite_char (count, c)
+     int count, c;
+{
+  int i;
+#if defined (HANDLE_MULTIBYTE)
+  char mbkey[MB_LEN_MAX];
+  int k;
+
+  /* Read an entire multibyte character sequence to insert COUNT times. */
+  if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
+#endif
+
+  rl_begin_undo_group ();
+
+  for (i = 0; i < count; i++)
+    {
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_insert_text (mbkey);
+      else
+#endif
+       _rl_insert_char (1, c);
+
+      if (rl_point < rl_end)
+       rl_delete (1, c);
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+
+int
+rl_insert (count, c)
+     int count, c;
+{
+  return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
+                                        : _rl_overwrite_char (count, c));
+}
+
+/* Insert the next typed character verbatim. */
+static int
+_rl_insert_next (count)
+     int count;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (c < 0)
+    return -1;
+
+  if (RL_ISSTATE (RL_STATE_MACRODEF))
+    _rl_add_macro_char (key);
+
+#if defined (HANDLE_SIGNALS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+    _rl_restore_tty_signals ();
+#endif
+
+  return (_rl_insert_char (count, c));  
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_insert_next_callback (data)
+     _rl_callback_generic_arg *data;
+{
+  int count;
+
+  count = data->count;
+
+  /* Deregister function, let rl_callback_read_char deallocate data */
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+  return _rl_insert_next (count);
+}
+#endif
+  
+int
+rl_quoted_insert (count, key)
+     int count, key;
+{
+  /* Let's see...should the callback interface futz with signal handling? */
+#if defined (HANDLE_SIGNALS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+    _rl_disable_tty_signals ();
+#endif
+
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_func = _rl_insert_next_callback;
+      return (0);
+    }
+#endif
+      
+  return _rl_insert_next (count);
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+     int count, key;
+{
+  return (_rl_insert_char (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed.  We accept the whole line.
+   KEY is the key that invoked this command.  I guess it could have
+   meaning in the future. */
+int
+rl_newline (count, key)
+     int count, key;
+{
+  rl_done = 1;
+
+  if (_rl_history_preserve_point)
+    _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+  RL_SETSTATE(RL_STATE_DONE);
+
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    {
+      _rl_vi_done_inserting ();
+      if (_rl_vi_textmod_command (_rl_vi_last_command) == 0)   /* XXX */
+       _rl_vi_reset_last ();
+    }
+#endif /* VI_MODE */
+
+  /* If we've been asked to erase empty lines, suppress the final update,
+     since _rl_update_final calls rl_crlf(). */
+  if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+    return 0;
+
+  if (_rl_echoing_p)
+    _rl_update_final ();
+  return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+   and some characters appearing in emacs_ctlx_keymap.  This function
+   is just a stub, you bind keys to it and the code in _rl_dispatch ()
+   is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+     int ignore1, ignore2;
+{
+  return 0;
+}
+
+/* This is different from what vi does, so the code's not shared.  Emacs
+   rubout in overwrite mode has one oddity:  it replaces a control
+   character that's displayed as two characters (^X) with two spaces. */
+int
+_rl_overwrite_rubout (count, key)
+     int count, key;
+{
+  int opoint;
+  int i, l;
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return 1;
+    }
+
+  opoint = rl_point;
+
+  /* L == number of spaces to insert */
+  for (i = l = 0; i < count; i++)
+    {
+      rl_backward_char (1, key);
+      l += rl_character_len (rl_line_buffer[rl_point], rl_point);      /* not exactly right */
+    }
+
+  rl_begin_undo_group ();
+
+  if (count > 1 || rl_explicit_arg)
+    rl_kill_text (opoint, rl_point);
+  else
+    rl_delete_text (opoint, rl_point);
+
+  /* Emacs puts point at the beginning of the sequence of spaces. */
+  if (rl_point < rl_end)
+    {
+      opoint = rl_point;
+      _rl_insert_char (l, ' ');
+      rl_point = opoint;
+    }
+
+  rl_end_undo_group ();
+
+  return 0;
+}
+  
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (!rl_point)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (rl_insert_mode == RL_IM_OVERWRITE)
+    return (_rl_overwrite_rubout (count, key));
+
+  return (_rl_rubout_char (count, key));
+}
+
+int
+_rl_rubout_char (count, key)
+     int count, key;
+{
+  int orig_point;
+  unsigned char c;
+
+  /* Duplicated code because this is called from other parts of the library. */
+  if (count < 0)
+    return (rl_delete (-count, key));
+
+  if (rl_point == 0)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  orig_point = rl_point;
+  if (count > 1 || rl_explicit_arg)
+    {
+      rl_backward_char (count, key);
+      rl_kill_text (orig_point, rl_point);
+    }
+  else if (MB_CUR_MAX == 1 || rl_byte_oriented)
+    {
+      c = rl_line_buffer[--rl_point];
+      rl_delete_text (rl_point, orig_point);
+      /* The erase-at-end-of-line hack is of questionable merit now. */
+      if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
+       {
+         int l;
+         l = rl_character_len (c, rl_point);
+         _rl_erase_at_end_of_line (l);
+       }
+    }
+  else
+    {
+      rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      rl_delete_text (rl_point, orig_point);
+    }
+
+  return 0;
+}
+
+/* Delete the character under the cursor.  Given a numeric argument,
+   kill that many characters instead. */
+int
+rl_delete (count, key)
+     int count, key;
+{
+  int xpoint;
+
+  if (count < 0)
+    return (_rl_rubout_char (-count, key));
+
+  if (rl_point == rl_end)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (count > 1 || rl_explicit_arg)
+    {
+      xpoint = rl_point;
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_forward_char (count, key);
+      else
+       rl_forward_byte (count, key);
+
+      rl_kill_text (xpoint, rl_point);
+      rl_point = xpoint;
+    }
+  else
+    {
+      xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+      rl_delete_text (rl_point, xpoint);
+    }
+  return 0;
+}
+
+/* Delete the character under the cursor, unless the insertion
+   point is at the end of the line, in which case the character
+   behind the cursor is deleted.  COUNT is obeyed and may be used
+   to delete forward or backward that many characters. */      
+int
+rl_rubout_or_delete (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (_rl_rubout_char (count, key));
+  else
+    return (rl_delete (count, key));
+}  
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+     int count, ignore;
+{
+  int start;
+
+  while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+    rl_point--;
+
+  start = rl_point;
+
+  while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+    rl_point++;
+
+  if (start != rl_point)
+    {
+      rl_delete_text (start, rl_point);
+      rl_point = start;
+    }
+
+  if (rl_point < 0)
+    rl_point = 0;
+
+  return 0;
+}
+
+/* Like the tcsh editing function delete-char-or-list.  The eof character
+   is caught before this is invoked, so this really does the same thing as
+   delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
+     int count, key;
+{
+  if (rl_end != 0 && rl_point == rl_end)
+    return (rl_possible_completions (count, key));
+  else
+    return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+   A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+     int count, key;
+{
+  char *rl_comment_text;
+  int rl_comment_len;
+
+  rl_beg_of_line (1, key);
+  rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+
+  if (rl_explicit_arg == 0)
+    rl_insert_text (rl_comment_text);
+  else
+    {
+      rl_comment_len = strlen (rl_comment_text);
+      if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
+       rl_delete_text (rl_point, rl_point + rl_comment_len);
+      else
+       rl_insert_text (rl_comment_text);
+    }
+
+  (*rl_redisplay_function) ();
+  rl_newline (1, '\n');
+
+  return (0);
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Changing Case                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+     int count, key;
+{
+  return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+     int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+   Change the case of COUNT words, performing OP on them.
+   OP is one of UpCase, DownCase, or CapCase.
+   If a negative argument is given, leave point where it started,
+   otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+     int count, op;
+{
+  int start, next, end;
+  int inword, c, nc, nop;
+#if defined (HANDLE_MULTIBYTE)
+  wchar_t wc, nwc;
+  char mb[MB_LEN_MAX+1];
+  int mlen;
+  size_t m;
+  mbstate_t mps;
+#endif
+
+  start = rl_point;
+  rl_forward_word (count, 0);
+  end = rl_point;
+
+  if (op != UpCase && op != DownCase && op != CapCase)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  if (count < 0)
+    SWAP (start, end);
+
+#if defined (HANDLE_MULTIBYTE)
+  memset (&mps, 0, sizeof (mbstate_t));
+#endif
+
+  /* We are going to modify some text, so let's prepare to undo it. */
+  rl_modifying (start, end);
+
+  inword = 0;
+  while (start < end)
+    {
+      c = _rl_char_value (rl_line_buffer, start);
+      /*  This assumes that the upper and lower case versions are the same width. */
+      next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
+
+      if (_rl_walphabetic (c) == 0)
+       {
+         inword = 0;
+         start = next;
+         continue;
+       }
+
+      if (op == CapCase)
+       {
+         nop = inword ? DownCase : UpCase;
+         inword = 1;
+       }
+      else
+       nop = op;
+      if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c))
+       {
+         nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
+         rl_line_buffer[start] = nc;
+       }
+#if defined (HANDLE_MULTIBYTE)
+      else
+       {
+         m = mbrtowc (&wc, rl_line_buffer + start, end - start, &mps);
+         if (MB_INVALIDCH (m))
+           wc = (wchar_t)rl_line_buffer[start];
+         else if (MB_NULLWCH (m))
+           wc = L'\0';
+         nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
+         if  (nwc != wc)       /*  just skip unchanged characters */
+           {
+             mlen = wcrtomb (mb, nwc, &mps);
+             if (mlen > 0)
+               mb[mlen] = '\0';
+             /* Assume the same width */
+             strncpy (rl_line_buffer + start, mb, mlen);
+           }
+       }
+#endif
+
+      start = next;
+    }
+
+  rl_point = end;
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Transposition                               */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Transpose the words at point.  If point is at the end of the line,
+   transpose the two words before point. */
+int
+rl_transpose_words (count, key)
+     int count, key;
+{
+  char *word1, *word2;
+  int w1_beg, w1_end, w2_beg, w2_end;
+  int orig_point = rl_point;
+
+  if (!count)
+    return 0;
+
+  /* Find the two words. */
+  rl_forward_word (count, key);
+  w2_end = rl_point;
+  rl_backward_word (1, key);
+  w2_beg = rl_point;
+  rl_backward_word (count, key);
+  w1_beg = rl_point;
+  rl_forward_word (1, key);
+  w1_end = rl_point;
+
+  /* Do some check to make sure that there really are two words. */
+  if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+    {
+      rl_ding ();
+      rl_point = orig_point;
+      return -1;
+    }
+
+  /* Get the text of the words. */
+  word1 = rl_copy_text (w1_beg, w1_end);
+  word2 = rl_copy_text (w2_beg, w2_end);
+
+  /* We are about to do many insertions and deletions.  Remember them
+     as one operation. */
+  rl_begin_undo_group ();
+
+  /* Do the stuff at word2 first, so that we don't have to worry
+     about word1 moving. */
+  rl_point = w2_beg;
+  rl_delete_text (w2_beg, w2_end);
+  rl_insert_text (word1);
+
+  rl_point = w1_beg;
+  rl_delete_text (w1_beg, w1_end);
+  rl_insert_text (word2);
+
+  /* This is exactly correct since the text before this point has not
+     changed in length. */
+  rl_point = w2_end;
+
+  /* I think that does it. */
+  rl_end_undo_group ();
+  xfree (word1);
+  xfree (word2);
+
+  return 0;
+}
+
+/* Transpose the characters at point.  If point is at the end of the line,
+   then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+     int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+  char *dummy;
+  int i;
+#else
+  char dummy[2];
+#endif
+  int char_length, prev_point;
+
+  if (count == 0)
+    return 0;
+
+  if (!rl_point || rl_end < 2)
+    {
+      rl_ding ();
+      return -1;
+    }
+
+  rl_begin_undo_group ();
+
+  if (rl_point == rl_end)
+    {
+      rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+      count = 1;
+    }
+
+  prev_point = rl_point;
+  rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+
+#if defined (HANDLE_MULTIBYTE)
+  char_length = prev_point - rl_point;
+  dummy = (char *)xmalloc (char_length + 1);
+  for (i = 0; i < char_length; i++)
+    dummy[i] = rl_line_buffer[rl_point + i];
+  dummy[i] = '\0';
+#else
+  dummy[0] = rl_line_buffer[rl_point];
+  dummy[char_length = 1] = '\0';
+#endif
+
+  rl_delete_text (rl_point, rl_point + char_length);
+
+  rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+  _rl_fix_point (0);
+  rl_insert_text (dummy);
+  rl_end_undo_group ();
+
+#if defined (HANDLE_MULTIBYTE)
+  xfree (dummy);
+#endif
+
+  return 0;
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Character Searching                         */
+/*                                                                 */
+/* **************************************************************** */
+
+int
+#if defined (HANDLE_MULTIBYTE)
+_rl_char_search_internal (count, dir, smbchar, len)
+     int count, dir;
+     char *smbchar;
+     int len;
+#else
+_rl_char_search_internal (count, dir, schar)
+     int count, dir, schar;
+#endif
+{
+  int pos, inc;
+#if defined (HANDLE_MULTIBYTE)
+  int prepos;
+#endif
+
+  if (dir == 0)
+    return -1;
+
+  pos = rl_point;
+  inc = (dir < 0) ? -1 : 1;
+  while (count)
+    {
+      if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+       {
+         rl_ding ();
+         return -1;
+       }
+
+#if defined (HANDLE_MULTIBYTE)
+      pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                     : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+#else
+      pos += inc;
+#endif
+      do
+       {
+#if defined (HANDLE_MULTIBYTE)
+         if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
+#else
+         if (rl_line_buffer[pos] == schar)
+#endif
+           {
+             count--;
+             if (dir < 0)
+               rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+                                       : pos;
+             else
+               rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
+                                       : pos;
+             break;
+           }
+#if defined (HANDLE_MULTIBYTE)
+         prepos = pos;
+#endif
+       }
+#if defined (HANDLE_MULTIBYTE)
+      while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
+                      : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
+#else
+      while ((dir < 0) ? pos-- : ++pos < rl_end);
+#endif
+    }
+  return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+   FDIR is the direction to search if COUNT is non-negative; otherwise
+   the search goes in BDIR.  So much is dependent on HANDLE_MULTIBYTE
+   that there are two separate versions of this function. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  char mbchar[MB_LEN_MAX];
+  int mb_len;
+
+  mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
+
+  if (mb_len <= 0)
+    return -1;
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
+  else
+    return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
+}
+#else /* !HANDLE_MULTIBYTE */
+static int
+_rl_char_search (count, fdir, bdir)
+     int count, fdir, bdir;
+{
+  int c;
+
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+  if (c < 0)
+    return -1;
+
+  if (count < 0)
+    return (_rl_char_search_internal (-count, bdir, c));
+  else
+    return (_rl_char_search_internal (count, fdir, c));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_char_search_callback (data)
+     _rl_callback_generic_arg *data;
+{
+  _rl_callback_func = 0;
+  _rl_want_redisplay = 1;
+
+  return (_rl_char_search (data->count, data->i1, data->i2));
+}
+#endif
+
+int
+rl_char_search (count, key)
+     int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_data->i1 = FFIND;
+      _rl_callback_data->i2 = BFIND;
+      _rl_callback_func = _rl_char_search_callback;
+      return (0);
+    }
+#endif
+  
+  return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+     int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    {
+      _rl_callback_data = _rl_callback_data_alloc (count);
+      _rl_callback_data->i1 = BFIND;
+      _rl_callback_data->i2 = FFIND;
+      _rl_callback_func = _rl_char_search_callback;
+      return (0);
+    }
+#endif
+
+  return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/*                                                                 */
+/*                The Mark and the Region.                         */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+     int position;
+{
+  if (position > rl_end)
+    return -1;
+
+  rl_mark = position;
+  return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+     int count, key;
+{
+  return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+     int count, key;
+{
+  if (rl_mark > rl_end)
+    rl_mark = -1;
+
+  if (rl_mark == -1)
+    {
+      rl_ding ();
+      return -1;
+    }
+  else
+    SWAP (rl_point, rl_mark);
+
+  return 0;
+}
index 9b0bdd89a0674611d0110e234f177aa5f4702048..676548c92bcc73894dd9d3fc2cc42dc9c577df8e 100644 (file)
@@ -316,7 +316,7 @@ ansic_wshouldquote (string)
       }
 
   free (wcstr);
-  return 0;    
+  return 0;
 }
 #endif
 
index c984c8aed93fb63c41fe686375bd8c9323d23244..3bc5408576da61634014e4db14ff850a53b94845 100644 (file)
@@ -793,7 +793,7 @@ make_function_def (name, command, lineno, lstart)
   bind_function_def (name->word, temp);
 #endif
 
-  temp->source_file = 0;
+  temp->source_file = temp->source_file ? savestring (temp->source_file) : 0;
   return (make_command (cm_function_def, (SIMPLE_COM *)temp));
 }
 
diff --git a/parse.y b/parse.y
index 4358a5f34a1d11f642a739f93808a9e239330c9b..f59f8f930a3c2fd80854d52dce463a225db5f860 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -4833,6 +4833,14 @@ find_reserved_word (tokstr)
   return -1;
 }
 
+/* An interface to let the rest of the shell (primarily the completion
+   system) know what the parser is expecting. */
+int
+parser_in_command_position ()
+{
+  return (command_token_position (last_read_token));
+}
+
 #if 0
 #if defined (READLINE)
 /* Called after each time readline is called.  This insures that whatever
index 16e72184cf72b3f866ec56edab291ca488ee7ec3..4358a5f34a1d11f642a739f93808a9e239330c9b 100644 (file)
--- a/parse.y~
+++ b/parse.y~
@@ -5989,6 +5989,8 @@ save_input_line_state (ls)
   /* force reallocation */
   shell_input_line = 0;
   shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
+
+  return ls;
 }
 
 void