* readline.h (rl_completer_quote_characters): Add declaration.
[external/binutils.git] / readline / readline.c
index 517b95a..de1142f 100644 (file)
@@ -179,7 +179,7 @@ typedef sighandler SigHandler ();
 #define HANDLE_SIGNALS
 
 #ifdef __GO32__
-#include <pc.h>
+#include <sys/pc.h>
 #undef HANDLE_SIGNALS
 #endif
 
@@ -241,7 +241,7 @@ static jmp_buf readline_top_level;
 static FILE *in_stream, *out_stream;
 
 /* The names of the streams that we do input and output to. */
-FILE *rl_instream = stdin, *rl_outstream = stdout;
+FILE *rl_instream, *rl_outstream;
 
 /* Non-zero means echo characters as they are read. */
 int readline_echoing_p = 1;
@@ -292,6 +292,7 @@ static unsigned char parsing_conditionalized_out = 0;
 
 /* Caseless strcmp (). */
 static int stricmp (), strnicmp ();
+static char *strpbrk ();
 
 /* Non-zero means to save keys that we dispatch on in a kbd macro. */
 static int defining_kbd_macro = 0;
@@ -1119,6 +1120,12 @@ readline_initialize_everything ()
   /* Find out if we are running in Emacs. */
   running_in_emacs = getenv ("EMACS");
 
+  /* Set up input and output if they aren't already.  */
+  if (!rl_instream)
+    rl_instream = stdin;
+  if (!rl_outstream)
+    rl_outstream = stdout;
+
   /* Allocate data structures. */
   if (!rl_line_buffer)
     rl_line_buffer =
@@ -3619,6 +3626,12 @@ char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(";
    rl_basic_word_break_characters.  */
 char *rl_completer_word_break_characters = (char *)NULL;
 
+/* The list of characters which are used to quote a substring of the command
+   line.  Command completion occurs on the entire substring, and within the
+   substring rl_completer_word_break_characters are treated as any other
+   character, unless they also appear within this list. */
+char *rl_completer_quote_characters = (char *)NULL;
+
 /* List of characters that are word break characters, but should be left
    in TEXT when it is passed to the completion function.  The shell uses
    this to help determine what kind of completing to do. */
@@ -3654,8 +3667,10 @@ rl_complete_internal (what_to_do)
   char *filename_completion_function ();
   char **completion_matches (), **matches;
   Function *our_func;
-  int start, end, delimiter = 0;
+  int start, scan, end, delimiter = 0;
   char *text, *saved_line_buffer;
+  char quote_char = '\0';
+  char *replacement;
 
   if (the_line)
     saved_line_buffer = savestring (the_line);
@@ -3675,8 +3690,41 @@ rl_complete_internal (what_to_do)
 
   if (rl_point)
     {
-      while (--rl_point &&
-            !rindex (rl_completer_word_break_characters, the_line[rl_point]));
+      if (rl_completer_quote_characters)
+       {
+         /* We have a list of characters which can be used in pairs to quote
+            substrings for completion.  Try to find the start of an unclosed
+            quoted substring.
+            FIXME:  Doesn't yet handle '\' escapes to hid embedded quotes */
+         for (scan = 0; scan < end; scan++)
+           {
+             if (quote_char != '\0')
+               {
+                 /* Ignore everything until the matching close quote char */
+                 if (the_line[scan] == quote_char)
+                   {
+                     /* Found matching close quote. Abandon this substring. */
+                     quote_char = '\0';
+                     rl_point = end;
+                   }
+               }
+             else if (rindex (rl_completer_quote_characters, the_line[scan]))
+               {
+                 /* Found start of a quoted substring. */
+                 quote_char = the_line[scan];
+                 rl_point = scan + 1;
+               }
+           }
+       }
+      if (rl_point == end)
+       {
+         /* We didn't find an unclosed quoted substring upon which to do
+            completion, so use the word break characters to find the
+            substring on which to do completion. */
+         while (--rl_point &&
+                !rindex (rl_completer_word_break_characters,
+                         the_line[rl_point])) {;}
+       }
 
       /* If we are at a word break, then advance past it. */
       if (rindex (rl_completer_word_break_characters, the_line[rl_point]))
@@ -3728,7 +3776,7 @@ rl_complete_internal (what_to_do)
     some_matches:
 
       /* It seems to me that in all the cases we handle we would like
-        to ignore duplicate possiblilities.  Scan for the text to
+        to ignore duplicate possibilities.  Scan for the text to
         insert being identical to the other completions. */
       if (rl_ignore_completion_duplicates)
        {
@@ -3801,11 +3849,40 @@ rl_complete_internal (what_to_do)
              our_func == (int (*)())filename_completion_function)
            (void)(*rl_ignore_some_completions_function)(matches);
 
-         if (matches[0])
+         /* If we are doing completions on quoted substrings, and any matches
+            contain any of the completer word break characters, then auto-
+            matically prepend the substring with a quote character (just
+            pick the first one from the list of such) if it does not already
+            begin with a quote string.  FIXME:  Need to remove any such
+            automatically inserted quote character when it no longer is
+            necessary, such as if we change the string we are completing on
+            and the new set of matches don't require a quoted substring? */
+
+         replacement = matches[0];
+         if (matches[0] != NULL
+             && rl_completer_quote_characters != NULL
+             && (quote_char == '\0'))
+           {
+             for (i = 1; matches[i] != NULL; i++)
+               {
+                 if (strpbrk (matches[i], rl_completer_word_break_characters))
+                   {
+                     /* Found an embedded word break character in a potential
+                        match, so need to prepend a quote character if we are
+                        replacing the completion string. */
+                     replacement = alloca (strlen (matches[0]) + 2);
+                     quote_char = *rl_completer_quote_characters;
+                     *replacement = quote_char;
+                     strcpy (replacement + 1, matches[0]);
+                     break;
+                   }
+               }
+           }
+         if (replacement)
            {
              rl_delete_text (start, rl_point);
              rl_point = start;
-             rl_insert_text (matches[0]);
+             rl_insert_text (replacement);
            }
 
          /* If there are more matches, ring the bell to indicate.
@@ -3819,10 +3896,15 @@ rl_complete_internal (what_to_do)
            }
          else
            {
-             char temp_string[2];
+             char temp_string[16];
+             int temp_index = 0;
 
-             temp_string[0] = delimiter ? delimiter : ' ';
-             temp_string[1] = '\0';
+             if (quote_char)
+               {
+                 temp_string[temp_index++] = quote_char;
+               }
+             temp_string[temp_index++] = delimiter ? delimiter : ' ';
+             temp_string[temp_index++] = '\0';
 
              if (rl_filename_completion_desired)
                {
@@ -5559,8 +5641,10 @@ rl_named_function (string)
 
 /* The last key bindings file read. */
 #ifdef __MSDOS__
-static char *last_readline_init_file = "~/inputrc";
+/* Don't know what to do, but this is a guess */
+static char *last_readline_init_file = "/INPUTRC";
 #else
+static char *last_readline_init_file = "~/inputrc";
 #endif
 
 /* Re-read the current keybindings file. */
@@ -6310,6 +6394,27 @@ rl_function_dumper (print_readably)
 
 static char *strindex ();
 
+/* Return pointer to first occurance in STRING1 of any character from STRING2,
+   or NULL if no occurance found. */
+static char *
+strpbrk (string1, string2)
+     char *string1, *string2;
+{
+  register char *scan;
+
+  for (; *string1 != '\0'; string1++)
+    {
+      for (scan = string2; *scan != '\0'; scan++)
+       {
+         if (*string1 == *scan)
+           {
+             return (string1);
+           }
+       }
+    }
+  return (NULL);
+}
+
 /* Return non-zero if any members of ARRAY are a substring in STRING. */
 static int
 substring_member_of_array (string, array)