04f6478e41ae2d6ef06206281556d37d3aefb91f
[platform/upstream/bash.git] / lib / readline / histexpand.c
1 /* histexpand.c -- history expansion. */
2
3 /* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
4
5    This file contains the GNU History Library (the Library), a set of
6    routines for managing the text of previously typed lines.
7
8    The Library is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2, or (at your option)
11    any later version.
12
13    The Library is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    The GNU General Public License is often shipped with GNU software, and
19    is generally kept in a file called COPYING or LICENSE.  If you do not
20    have a copy of the license, write to the Free Software Foundation,
21    59 Temple Place, Suite 330, Boston, MA 02111 USA. */
22
23 #define READLINE_LIBRARY
24
25 #if defined (HAVE_CONFIG_H)
26 #  include <config.h>
27 #endif
28
29 #include <stdio.h>
30
31 #if defined (HAVE_STDLIB_H)
32 #  include <stdlib.h>
33 #else
34 #  include "ansi_stdlib.h"
35 #endif /* HAVE_STDLIB_H */
36
37 #if defined (HAVE_UNISTD_H)
38 #  ifndef _MINIX
39 #    include <sys/types.h>
40 #  endif
41 #  include <unistd.h>
42 #endif
43
44 #if defined (HAVE_STRING_H)
45 #  include <string.h>
46 #else
47 #  include <strings.h>
48 #endif /* !HAVE_STRING_H */
49
50 #include "history.h"
51 #include "histlib.h"
52
53 #include "rlshell.h"
54 #include "xmalloc.h"
55
56 #define HISTORY_WORD_DELIMITERS         " \t\n;&()|<>"
57 #define HISTORY_QUOTE_CHARACTERS        "\"'`"
58
59 typedef int _hist_search_func_t PARAMS((const char *, int));
60
61 static char error_pointer;
62
63 static char *subst_lhs;
64 static char *subst_rhs;
65 static int subst_lhs_len;
66 static int subst_rhs_len;
67
68 static char *get_history_word_specifier PARAMS((char *, char *, int *));
69 static char *history_find_word PARAMS((char *, int));
70
71 static char *quote_breaks PARAMS((char *));
72
73 /* Variables exported by this file. */
74 /* The character that represents the start of a history expansion
75    request.  This is usually `!'. */
76 char history_expansion_char = '!';
77
78 /* The character that invokes word substitution if found at the start of
79    a line.  This is usually `^'. */
80 char history_subst_char = '^';
81
82 /* During tokenization, if this character is seen as the first character
83    of a word, then it, and all subsequent characters upto a newline are
84    ignored.  For a Bourne shell, this should be '#'.  Bash special cases
85    the interactive comment character to not be a comment delimiter. */
86 char history_comment_char = '\0';
87
88 /* The list of characters which inhibit the expansion of text if found
89    immediately following history_expansion_char. */
90 char *history_no_expand_chars = " \t\n\r=";
91
92 /* If set to a non-zero value, single quotes inhibit history expansion.
93    The default is 0. */
94 int history_quotes_inhibit_expansion = 0;
95
96 /* Used to split words by history_tokenize_internal. */
97 char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
98
99 /* If set, this points to a function that is called to verify that a
100    particular history expansion should be performed. */
101 rl_linebuf_func_t *history_inhibit_expansion_function;
102
103 /* **************************************************************** */
104 /*                                                                  */
105 /*                      History Expansion                           */
106 /*                                                                  */
107 /* **************************************************************** */
108
109 /* Hairy history expansion on text, not tokens.  This is of general
110    use, and thus belongs in this library. */
111
112 /* The last string searched for by a !?string? search. */
113 static char *search_string;
114
115 /* The last string matched by a !?string? search. */
116 static char *search_match;
117
118 /* Return the event specified at TEXT + OFFSET modifying OFFSET to
119    point to after the event specifier.  Just a pointer to the history
120    line is returned; NULL is returned in the event of a bad specifier.
121    You pass STRING with *INDEX equal to the history_expansion_char that
122    begins this specification.
123    DELIMITING_QUOTE is a character that is allowed to end the string
124    specification for what to search for in addition to the normal
125    characters `:', ` ', `\t', `\n', and sometimes `?'.
126    So you might call this function like:
127    line = get_history_event ("!echo:p", &index, 0);  */
128 char *
129 get_history_event (string, caller_index, delimiting_quote)
130      const char *string;
131      int *caller_index;
132      int delimiting_quote;
133 {
134   register int i;
135   register char c;
136   HIST_ENTRY *entry;
137   int which, sign, local_index, substring_okay;
138   _hist_search_func_t *search_func;
139   char *temp;
140
141   /* The event can be specified in a number of ways.
142
143      !!   the previous command
144      !n   command line N
145      !-n  current command-line minus N
146      !str the most recent command starting with STR
147      !?str[?]
148           the most recent command containing STR
149
150      All values N are determined via HISTORY_BASE. */
151
152   i = *caller_index;
153
154   if (string[i] != history_expansion_char)
155     return ((char *)NULL);
156
157   /* Move on to the specification. */
158   i++;
159
160   sign = 1;
161   substring_okay = 0;
162
163 #define RETURN_ENTRY(e, w) \
164         return ((e = history_get (w)) ? e->line : (char *)NULL)
165
166   /* Handle !! case. */
167   if (string[i] == history_expansion_char)
168     {
169       i++;
170       which = history_base + (history_length - 1);
171       *caller_index = i;
172       RETURN_ENTRY (entry, which);
173     }
174
175   /* Hack case of numeric line specification. */
176   if (string[i] == '-')
177     {
178       sign = -1;
179       i++;
180     }
181
182   if (_rl_digit_p (string[i]))
183     {
184       /* Get the extent of the digits and compute the value. */
185       for (which = 0; _rl_digit_p (string[i]); i++)
186         which = (which * 10) + _rl_digit_value (string[i]);
187
188       *caller_index = i;
189
190       if (sign < 0)
191         which = (history_length + history_base) - which;
192
193       RETURN_ENTRY (entry, which);
194     }
195
196   /* This must be something to search for.  If the spec begins with
197      a '?', then the string may be anywhere on the line.  Otherwise,
198      the string must be found at the start of a line. */
199   if (string[i] == '?')
200     {
201       substring_okay++;
202       i++;
203     }
204
205   /* Only a closing `?' or a newline delimit a substring search string. */
206   for (local_index = i; c = string[i]; i++)
207     if ((!substring_okay && (whitespace (c) || c == ':' ||
208         (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
209         string[i] == delimiting_quote)) ||
210         string[i] == '\n' ||
211         (substring_okay && string[i] == '?'))
212       break;
213
214   which = i - local_index;
215   temp = (char *)xmalloc (1 + which);
216   if (which)
217     strncpy (temp, string + local_index, which);
218   temp[which] = '\0';
219
220   if (substring_okay && string[i] == '?')
221     i++;
222
223   *caller_index = i;
224
225 #define FAIL_SEARCH() \
226   do { \
227     history_offset = history_length; free (temp) ; return (char *)NULL; \
228   } while (0)
229
230   /* If there is no search string, try to use the previous search string,
231      if one exists.  If not, fail immediately. */
232   if (*temp == '\0' && substring_okay)
233     {
234       if (search_string)
235         {
236           free (temp);
237           temp = savestring (search_string);
238         }
239       else
240         FAIL_SEARCH ();
241     }
242
243   search_func = substring_okay ? history_search : history_search_prefix;
244   while (1)
245     {
246       local_index = (*search_func) (temp, -1);
247
248       if (local_index < 0)
249         FAIL_SEARCH ();
250
251       if (local_index == 0 || substring_okay)
252         {
253           entry = current_history ();
254           history_offset = history_length;
255         
256           /* If this was a substring search, then remember the
257              string that we matched for word substitution. */
258           if (substring_okay)
259             {
260               FREE (search_string);
261               search_string = temp;
262
263               FREE (search_match);
264               search_match = history_find_word (entry->line, local_index);
265             }
266           else
267             free (temp);
268
269           return (entry->line);
270         }
271
272       if (history_offset)
273         history_offset--;
274       else
275         FAIL_SEARCH ();
276     }
277 #undef FAIL_SEARCH
278 #undef RETURN_ENTRY
279 }
280
281 /* Function for extracting single-quoted strings.  Used for inhibiting
282    history expansion within single quotes. */
283
284 /* Extract the contents of STRING as if it is enclosed in single quotes.
285    SINDEX, when passed in, is the offset of the character immediately
286    following the opening single quote; on exit, SINDEX is left pointing
287    to the closing single quote. */
288 static void
289 hist_string_extract_single_quoted (string, sindex)
290      char *string;
291      int *sindex;
292 {
293   register int i;
294
295   for (i = *sindex; string[i] && string[i] != '\''; i++)
296     ;
297
298   *sindex = i;
299 }
300
301 static char *
302 quote_breaks (s)
303      char *s;
304 {
305   register char *p, *r;
306   char *ret;
307   int len = 3;
308
309   for (p = s; p && *p; p++, len++)
310     {
311       if (*p == '\'')
312         len += 3;
313       else if (whitespace (*p) || *p == '\n')
314         len += 2;
315     }
316
317   r = ret = (char *)xmalloc (len);
318   *r++ = '\'';
319   for (p = s; p && *p; )
320     {
321       if (*p == '\'')
322         {
323           *r++ = '\'';
324           *r++ = '\\';
325           *r++ = '\'';
326           *r++ = '\'';
327           p++;
328         }
329       else if (whitespace (*p) || *p == '\n')
330         {
331           *r++ = '\'';
332           *r++ = *p++;
333           *r++ = '\'';
334         }
335       else
336         *r++ = *p++;
337     }
338   *r++ = '\'';
339   *r = '\0';
340   return ret;
341 }
342
343 static char *
344 hist_error(s, start, current, errtype)
345       char *s;
346       int start, current, errtype;
347 {
348   char *temp;
349   const char *emsg;
350   int ll, elen;
351
352   ll = current - start;
353
354   switch (errtype)
355     {
356     case EVENT_NOT_FOUND:
357       emsg = "event not found";
358       elen = 15;
359       break;
360     case BAD_WORD_SPEC:
361       emsg = "bad word specifier";
362       elen = 18;
363       break;
364     case SUBST_FAILED:
365       emsg = "substitution failed";
366       elen = 19;
367       break;
368     case BAD_MODIFIER:
369       emsg = "unrecognized history modifier";
370       elen = 29;
371       break;
372     case NO_PREV_SUBST:
373       emsg = "no previous substitution";
374       elen = 24;
375       break;
376     default:
377       emsg = "unknown expansion error";
378       elen = 23;
379       break;
380     }
381
382   temp = (char *)xmalloc (ll + elen + 3);
383   strncpy (temp, s + start, ll);
384   temp[ll] = ':';
385   temp[ll + 1] = ' ';
386   strcpy (temp + ll + 2, emsg);
387   return (temp);
388 }
389
390 /* Get a history substitution string from STR starting at *IPTR
391    and return it.  The length is returned in LENPTR.
392
393    A backslash can quote the delimiter.  If the string is the
394    empty string, the previous pattern is used.  If there is
395    no previous pattern for the lhs, the last history search
396    string is used.
397
398    If IS_RHS is 1, we ignore empty strings and set the pattern
399    to "" anyway.  subst_lhs is not changed if the lhs is empty;
400    subst_rhs is allowed to be set to the empty string. */
401
402 static char *
403 get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
404      char *str;
405      int *iptr, delimiter, is_rhs, *lenptr;
406 {
407   register int si, i, j, k;
408   char *s = (char *) NULL;
409
410   i = *iptr;
411
412   for (si = i; str[si] && str[si] != delimiter; si++)
413     if (str[si] == '\\' && str[si + 1] == delimiter)
414       si++;
415
416   if (si > i || is_rhs)
417     {
418       s = (char *)xmalloc (si - i + 1);
419       for (j = 0, k = i; k < si; j++, k++)
420         {
421           /* Remove a backslash quoting the search string delimiter. */
422           if (str[k] == '\\' && str[k + 1] == delimiter)
423             k++;
424           s[j] = str[k];
425         }
426       s[j] = '\0';
427       if (lenptr)
428         *lenptr = j;
429     }
430
431   i = si;
432   if (str[i])
433     i++;
434   *iptr = i;
435
436   return s;
437 }
438
439 static void
440 postproc_subst_rhs ()
441 {
442   char *new;
443   int i, j, new_size;
444
445   new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len);
446   for (i = j = 0; i < subst_rhs_len; i++)
447     {
448       if (subst_rhs[i] == '&')
449         {
450           if (j + subst_lhs_len >= new_size)
451             new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
452           strcpy (new + j, subst_lhs);
453           j += subst_lhs_len;
454         }
455       else
456         {
457           /* a single backslash protects the `&' from lhs interpolation */
458           if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
459             i++;
460           if (j >= new_size)
461             new = (char *)xrealloc (new, new_size *= 2);
462           new[j++] = subst_rhs[i];
463         }
464     }
465   new[j] = '\0';
466   free (subst_rhs);
467   subst_rhs = new;
468   subst_rhs_len = j;
469 }
470
471 /* Expand the bulk of a history specifier starting at STRING[START].
472    Returns 0 if everything is OK, -1 if an error occurred, and 1
473    if the `p' modifier was supplied and the caller should just print
474    the returned string.  Returns the new index into string in
475    *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
476 static int
477 history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
478      char *string;
479      int start, *end_index_ptr;
480      char **ret_string;
481      char *current_line;        /* for !# */
482 {
483   int i, n, starting_index;
484   int substitute_globally, want_quotes, print_only;
485   char *event, *temp, *result, *tstr, *t, c, *word_spec;
486   int result_len;
487
488   result = (char *)xmalloc (result_len = 128);
489
490   i = start;
491
492   /* If it is followed by something that starts a word specifier,
493      then !! is implied as the event specifier. */
494
495   if (member (string[i + 1], ":$*%^"))
496     {
497       char fake_s[3];
498       int fake_i = 0;
499       i++;
500       fake_s[0] = fake_s[1] = history_expansion_char;
501       fake_s[2] = '\0';
502       event = get_history_event (fake_s, &fake_i, 0);
503     }
504   else if (string[i + 1] == '#')
505     {
506       i += 2;
507       event = current_line;
508     }
509   else
510     {
511       int quoted_search_delimiter = 0;
512
513       /* If the character before this `!' is a double or single
514          quote, then this expansion takes place inside of the
515          quoted string.  If we have to search for some text ("!foo"),
516          allow the delimiter to end the search string. */
517       if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
518         quoted_search_delimiter = string[i - 1];
519       event = get_history_event (string, &i, quoted_search_delimiter);
520     }
521           
522   if (event == 0)
523     {
524       *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
525       free (result);
526       return (-1);
527     }
528
529   /* If a word specifier is found, then do what that requires. */
530   starting_index = i;
531   word_spec = get_history_word_specifier (string, event, &i);
532
533   /* There is no such thing as a `malformed word specifier'.  However,
534      it is possible for a specifier that has no match.  In that case,
535      we complain. */
536   if (word_spec == (char *)&error_pointer)
537     {
538       *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
539       free (result);
540       return (-1);
541     }
542
543   /* If no word specifier, than the thing of interest was the event. */
544   temp = word_spec ? savestring (word_spec) : savestring (event);
545   FREE (word_spec);
546
547   /* Perhaps there are other modifiers involved.  Do what they say. */
548   want_quotes = substitute_globally = print_only = 0;
549   starting_index = i;
550
551   while (string[i] == ':')
552     {
553       c = string[i + 1];
554
555       if (c == 'g')
556         {
557           substitute_globally = 1;
558           i++;
559           c = string[i + 1];
560         }
561
562       switch (c)
563         {
564         default:
565           *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
566           free (result);
567           free (temp);
568           return -1;
569
570         case 'q':
571           want_quotes = 'q';
572           break;
573
574         case 'x':
575           want_quotes = 'x';
576           break;
577
578           /* :p means make this the last executed line.  So we
579              return an error state after adding this line to the
580              history. */
581         case 'p':
582           print_only++;
583           break;
584
585           /* :t discards all but the last part of the pathname. */
586         case 't':
587           tstr = strrchr (temp, '/');
588           if (tstr)
589             {
590               tstr++;
591               t = savestring (tstr);
592               free (temp);
593               temp = t;
594             }
595           break;
596
597           /* :h discards the last part of a pathname. */
598         case 'h':
599           tstr = strrchr (temp, '/');
600           if (tstr)
601             *tstr = '\0';
602           break;
603
604           /* :r discards the suffix. */
605         case 'r':
606           tstr = strrchr (temp, '.');
607           if (tstr)
608             *tstr = '\0';
609           break;
610
611           /* :e discards everything but the suffix. */
612         case 'e':
613           tstr = strrchr (temp, '.');
614           if (tstr)
615             {
616               t = savestring (tstr);
617               free (temp);
618               temp = t;
619             }
620           break;
621
622         /* :s/this/that substitutes `that' for the first
623            occurrence of `this'.  :gs/this/that substitutes `that'
624            for each occurrence of `this'.  :& repeats the last
625            substitution.  :g& repeats the last substitution
626            globally. */
627
628         case '&':
629         case 's':
630           {
631             char *new_event;
632             int delimiter, failed, si, l_temp;
633
634             if (c == 's')
635               {
636                 if (i + 2 < (int)strlen (string))
637                   delimiter = string[i + 2];
638                 else
639                   break;        /* no search delimiter */
640
641                 i += 3;
642
643                 t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
644                 /* An empty substitution lhs with no previous substitution
645                    uses the last search string as the lhs. */
646                 if (t)
647                   {
648                     FREE (subst_lhs);
649                     subst_lhs = t;
650                   }
651                 else if (!subst_lhs)
652                   {
653                     if (search_string && *search_string)
654                       {
655                         subst_lhs = savestring (search_string);
656                         subst_lhs_len = strlen (subst_lhs);
657                       }
658                     else
659                       {
660                         subst_lhs = (char *) NULL;
661                         subst_lhs_len = 0;
662                       }
663                   }
664
665                 FREE (subst_rhs);
666                 subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
667
668                 /* If `&' appears in the rhs, it's supposed to be replaced
669                    with the lhs. */
670                 if (member ('&', subst_rhs))
671                   postproc_subst_rhs ();
672               }
673             else
674               i += 2;
675
676             /* If there is no lhs, the substitution can't succeed. */
677             if (subst_lhs_len == 0)
678               {
679                 *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
680                 free (result);
681                 free (temp);
682                 return -1;
683               }
684
685             l_temp = strlen (temp);
686             /* Ignore impossible cases. */
687             if (subst_lhs_len > l_temp)
688               {
689                 *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
690                 free (result);
691                 free (temp);
692                 return (-1);
693               }
694
695             /* Find the first occurrence of THIS in TEMP. */
696             si = 0;
697             for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
698               if (STREQN (temp+si, subst_lhs, subst_lhs_len))
699                 {
700                   int len = subst_rhs_len - subst_lhs_len + l_temp;
701                   new_event = (char *)xmalloc (1 + len);
702                   strncpy (new_event, temp, si);
703                   strncpy (new_event + si, subst_rhs, subst_rhs_len);
704                   strncpy (new_event + si + subst_rhs_len,
705                            temp + si + subst_lhs_len,
706                            l_temp - (si + subst_lhs_len));
707                   new_event[len] = '\0';
708                   free (temp);
709                   temp = new_event;
710
711                   failed = 0;
712
713                   if (substitute_globally)
714                     {
715                       si += subst_rhs_len;
716                       l_temp = strlen (temp);
717                       substitute_globally++;
718                       continue;
719                     }
720                   else
721                     break;
722                 }
723
724             if (substitute_globally > 1)
725               {
726                 substitute_globally = 0;
727                 continue;       /* don't want to increment i */
728               }
729
730             if (failed == 0)
731               continue;         /* don't want to increment i */
732
733             *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
734             free (result);
735             free (temp);
736             return (-1);
737           }
738         }
739       i += 2;
740     }
741   /* Done with modfiers. */
742   /* Believe it or not, we have to back the pointer up by one. */
743   --i;
744
745   if (want_quotes)
746     {
747       char *x;
748
749       if (want_quotes == 'q')
750         x = sh_single_quote (temp);
751       else if (want_quotes == 'x')
752         x = quote_breaks (temp);
753       else
754         x = savestring (temp);
755
756       free (temp);
757       temp = x;
758     }
759
760   n = strlen (temp);
761   if (n >= result_len)
762     result = (char *)xrealloc (result, n + 2);
763   strcpy (result, temp);
764   free (temp);
765
766   *end_index_ptr = i;
767   *ret_string = result;
768   return (print_only);
769 }
770
771 /* Expand the string STRING, placing the result into OUTPUT, a pointer
772    to a string.  Returns:
773
774   -1) If there was an error in expansion.
775    0) If no expansions took place (or, if the only change in
776       the text was the de-slashifying of the history expansion
777       character)
778    1) If expansions did take place
779    2) If the `p' modifier was given and the caller should print the result
780
781   If an error ocurred in expansion, then OUTPUT contains a descriptive
782   error message. */
783
784 #define ADD_STRING(s) \
785         do \
786           { \
787             int sl = strlen (s); \
788             j += sl; \
789             if (j >= result_len) \
790               { \
791                 while (j >= result_len) \
792                   result_len += 128; \
793                 result = (char *)xrealloc (result, result_len); \
794               } \
795             strcpy (result + j - sl, s); \
796           } \
797         while (0)
798
799 #define ADD_CHAR(c) \
800         do \
801           { \
802             if (j >= result_len - 1) \
803               result = (char *)xrealloc (result, result_len += 64); \
804             result[j++] = c; \
805             result[j] = '\0'; \
806           } \
807         while (0)
808
809 int
810 history_expand (hstring, output)
811      char *hstring;
812      char **output;
813 {
814   register int j;
815   int i, r, l, passc, cc, modified, eindex, only_printing;
816   char *string;
817
818   /* The output string, and its length. */
819   int result_len;
820   char *result;
821
822   /* Used when adding the string. */
823   char *temp;
824
825   if (output == 0)
826     return 0;
827
828   /* Setting the history expansion character to 0 inhibits all
829      history expansion. */
830   if (history_expansion_char == 0)
831     {
832       *output = savestring (hstring);
833       return (0);
834     }
835     
836   /* Prepare the buffer for printing error messages. */
837   result = (char *)xmalloc (result_len = 256);
838   result[0] = '\0';
839
840   only_printing = modified = 0;
841   l = strlen (hstring);
842
843   /* Grovel the string.  Only backslash and single quotes can quote the
844      history escape character.  We also handle arg specifiers. */
845
846   /* Before we grovel forever, see if the history_expansion_char appears
847      anywhere within the text. */
848
849   /* The quick substitution character is a history expansion all right.  That
850      is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
851      that is the substitution that we do. */
852   if (hstring[0] == history_subst_char)
853     {
854       string = (char *)xmalloc (l + 5);
855
856       string[0] = string[1] = history_expansion_char;
857       string[2] = ':';
858       string[3] = 's';
859       strcpy (string + 4, hstring);
860       l += 4;
861     }
862   else
863     {
864       string = hstring;
865       /* If not quick substitution, still maybe have to do expansion. */
866
867       /* `!' followed by one of the characters in history_no_expand_chars
868          is NOT an expansion. */
869       for (i = 0; string[i]; i++)
870         {
871           cc = string[i + 1];
872           /* The history_comment_char, if set, appearing that the beginning
873              of a word signifies that the rest of the line should not have
874              history expansion performed on it.
875              Skip the rest of the line and break out of the loop. */
876           if (history_comment_char && string[i] == history_comment_char &&
877               (i == 0 || member (string[i - 1], history_word_delimiters)))
878             {
879               while (string[i])
880                 i++;
881               break;
882             }
883           else if (string[i] == history_expansion_char)
884             {
885               if (!cc || member (cc, history_no_expand_chars))
886                 continue;
887               /* If the calling application has set
888                  history_inhibit_expansion_function to a function that checks
889                  for special cases that should not be history expanded,
890                  call the function and skip the expansion if it returns a
891                  non-zero value. */
892               else if (history_inhibit_expansion_function &&
893                         (*history_inhibit_expansion_function) (string, i))
894                 continue;
895               else
896                 break;
897             }
898           /* XXX - at some point, might want to extend this to handle
899                    double quotes as well. */
900           else if (history_quotes_inhibit_expansion && string[i] == '\'')
901             {
902               /* If this is bash, single quotes inhibit history expansion. */
903               i++;
904               hist_string_extract_single_quoted (string, &i);
905             }
906           else if (history_quotes_inhibit_expansion && string[i] == '\\')
907             {
908               /* If this is bash, allow backslashes to quote single
909                  quotes and the history expansion character. */
910               if (cc == '\'' || cc == history_expansion_char)
911                 i++;
912             }
913         }
914           
915       if (string[i] != history_expansion_char)
916         {
917           free (result);
918           *output = savestring (string);
919           return (0);
920         }
921     }
922
923   /* Extract and perform the substitution. */
924   for (passc = i = j = 0; i < l; i++)
925     {
926       int tchar = string[i];
927
928       if (passc)
929         {
930           passc = 0;
931           ADD_CHAR (tchar);
932           continue;
933         }
934
935       if (tchar == history_expansion_char)
936         tchar = -3;
937       else if (tchar == history_comment_char)
938         tchar = -2;
939
940       switch (tchar)
941         {
942         default:
943           ADD_CHAR (string[i]);
944           break;
945
946         case '\\':
947           passc++;
948           ADD_CHAR (tchar);
949           break;
950
951         case '\'':
952           {
953             /* If history_quotes_inhibit_expansion is set, single quotes
954                inhibit history expansion. */
955             if (history_quotes_inhibit_expansion)
956               {
957                 int quote, slen;
958
959                 quote = i++;
960                 hist_string_extract_single_quoted (string, &i);
961
962                 slen = i - quote + 2;
963                 temp = (char *)xmalloc (slen);
964                 strncpy (temp, string + quote, slen);
965                 temp[slen - 1] = '\0';
966                 ADD_STRING (temp);
967                 free (temp);
968               }
969             else
970               ADD_CHAR (string[i]);
971             break;
972           }
973
974         case -2:                /* history_comment_char */
975           if (i == 0 || member (string[i - 1], history_word_delimiters))
976             {
977               temp = (char *)xmalloc (l - i + 1);
978               strcpy (temp, string + i);
979               ADD_STRING (temp);
980               free (temp);
981               i = l;
982             }
983           else
984             ADD_CHAR (string[i]);
985           break;
986
987         case -3:                /* history_expansion_char */
988           cc = string[i + 1];
989
990           /* If the history_expansion_char is followed by one of the
991              characters in history_no_expand_chars, then it is not a
992              candidate for expansion of any kind. */
993           if (member (cc, history_no_expand_chars))
994             {
995               ADD_CHAR (string[i]);
996               break;
997             }
998
999 #if defined (NO_BANG_HASH_MODIFIERS)
1000           /* There is something that is listed as a `word specifier' in csh
1001              documentation which means `the expanded text to this point'.
1002              That is not a word specifier, it is an event specifier.  If we
1003              don't want to allow modifiers with `!#', just stick the current
1004              output line in again. */
1005           if (cc == '#')
1006             {
1007               if (result)
1008                 {
1009                   temp = (char *)xmalloc (1 + strlen (result));
1010                   strcpy (temp, result);
1011                   ADD_STRING (temp);
1012                   free (temp);
1013                 }
1014               i++;
1015               break;
1016             }
1017 #endif
1018
1019           r = history_expand_internal (string, i, &eindex, &temp, result);
1020           if (r < 0)
1021             {
1022               *output = temp;
1023               free (result);
1024               if (string != hstring)
1025                 free (string);
1026               return -1;
1027             }
1028           else
1029             {
1030               if (temp)
1031                 {
1032                   modified++;
1033                   if (*temp)
1034                     ADD_STRING (temp);
1035                   free (temp);
1036                 }
1037               only_printing = r == 1;
1038               i = eindex;
1039             }
1040           break;
1041         }
1042     }
1043
1044   *output = result;
1045   if (string != hstring)
1046     free (string);
1047
1048   if (only_printing)
1049     {
1050       add_history (result);
1051       return (2);
1052     }
1053
1054   return (modified != 0);
1055 }
1056
1057 /* Return a consed string which is the word specified in SPEC, and found
1058    in FROM.  NULL is returned if there is no spec.  The address of
1059    ERROR_POINTER is returned if the word specified cannot be found.
1060    CALLER_INDEX is the offset in SPEC to start looking; it is updated
1061    to point to just after the last character parsed. */
1062 static char *
1063 get_history_word_specifier (spec, from, caller_index)
1064      char *spec, *from;
1065      int *caller_index;
1066 {
1067   register int i = *caller_index;
1068   int first, last;
1069   int expecting_word_spec = 0;
1070   char *result;
1071
1072   /* The range of words to return doesn't exist yet. */
1073   first = last = 0;
1074   result = (char *)NULL;
1075
1076   /* If we found a colon, then this *must* be a word specification.  If
1077      it isn't, then it is an error. */
1078   if (spec[i] == ':')
1079     {
1080       i++;
1081       expecting_word_spec++;
1082     }
1083
1084   /* Handle special cases first. */
1085
1086   /* `%' is the word last searched for. */
1087   if (spec[i] == '%')
1088     {
1089       *caller_index = i + 1;
1090       return (search_match ? savestring (search_match) : savestring (""));
1091     }
1092
1093   /* `*' matches all of the arguments, but not the command. */
1094   if (spec[i] == '*')
1095     {
1096       *caller_index = i + 1;
1097       result = history_arg_extract (1, '$', from);
1098       return (result ? result : savestring (""));
1099     }
1100
1101   /* `$' is last arg. */
1102   if (spec[i] == '$')
1103     {
1104       *caller_index = i + 1;
1105       return (history_arg_extract ('$', '$', from));
1106     }
1107
1108   /* Try to get FIRST and LAST figured out. */
1109
1110   if (spec[i] == '-')
1111     first = 0;
1112   else if (spec[i] == '^')
1113     first = 1;
1114   else if (_rl_digit_p (spec[i]) && expecting_word_spec)
1115     {
1116       for (first = 0; _rl_digit_p (spec[i]); i++)
1117         first = (first * 10) + _rl_digit_value (spec[i]);
1118     }
1119   else
1120     return ((char *)NULL);      /* no valid `first' for word specifier */
1121
1122   if (spec[i] == '^' || spec[i] == '*')
1123     {
1124       last = (spec[i] == '^') ? 1 : '$';        /* x* abbreviates x-$ */
1125       i++;
1126     }
1127   else if (spec[i] != '-')
1128     last = first;
1129   else
1130     {
1131       i++;
1132
1133       if (_rl_digit_p (spec[i]))
1134         {
1135           for (last = 0; _rl_digit_p (spec[i]); i++)
1136             last = (last * 10) + _rl_digit_value (spec[i]);
1137         }
1138       else if (spec[i] == '$')
1139         {
1140           i++;
1141           last = '$';
1142         }
1143 #if 0
1144       else if (!spec[i] || spec[i] == ':')
1145         /* check against `:' because there could be a modifier separator */
1146 #else
1147       else
1148         /* csh seems to allow anything to terminate the word spec here,
1149            leaving it as an abbreviation. */
1150 #endif
1151         last = -1;              /* x- abbreviates x-$ omitting word `$' */
1152     }
1153
1154   *caller_index = i;
1155
1156   if (last >= first || last == '$' || last < 0)
1157     result = history_arg_extract (first, last, from);
1158
1159   return (result ? result : (char *)&error_pointer);
1160 }
1161
1162 /* Extract the args specified, starting at FIRST, and ending at LAST.
1163    The args are taken from STRING.  If either FIRST or LAST is < 0,
1164    then make that arg count from the right (subtract from the number of
1165    tokens, so that FIRST = -1 means the next to last token on the line).
1166    If LAST is `$' the last arg from STRING is used. */
1167 char *
1168 history_arg_extract (first, last, string)
1169      int first, last;
1170      const char *string;
1171 {
1172   register int i, len;
1173   char *result;
1174   int size, offset;
1175   char **list;
1176
1177   /* XXX - think about making history_tokenize return a struct array,
1178      each struct in array being a string and a length to avoid the
1179      calls to strlen below. */
1180   if ((list = history_tokenize (string)) == NULL)
1181     return ((char *)NULL);
1182
1183   for (len = 0; list[len]; len++)
1184     ;
1185
1186   if (last < 0)
1187     last = len + last - 1;
1188
1189   if (first < 0)
1190     first = len + first - 1;
1191
1192   if (last == '$')
1193     last = len - 1;
1194
1195   if (first == '$')
1196     first = len - 1;
1197
1198   last++;
1199
1200   if (first >= len || last > len || first < 0 || last < 0 || first > last)
1201     result = ((char *)NULL);
1202   else
1203     {
1204       for (size = 0, i = first; i < last; i++)
1205         size += strlen (list[i]) + 1;
1206       result = (char *)xmalloc (size + 1);
1207       result[0] = '\0';
1208
1209       for (i = first, offset = 0; i < last; i++)
1210         {
1211           strcpy (result + offset, list[i]);
1212           offset += strlen (list[i]);
1213           if (i + 1 < last)
1214             {
1215               result[offset++] = ' ';
1216               result[offset] = 0;
1217             }
1218         }
1219     }
1220
1221   for (i = 0; i < len; i++)
1222     free (list[i]);
1223   free (list);
1224
1225   return (result);
1226 }
1227
1228 #define slashify_in_quotes "\\`\"$"
1229
1230 /* Parse STRING into tokens and return an array of strings.  If WIND is
1231    not -1 and INDP is not null, we also want the word surrounding index
1232    WIND.  The position in the returned array of strings is returned in
1233    *INDP. */
1234 static char **
1235 history_tokenize_internal (string, wind, indp)
1236      const char *string;
1237      int wind, *indp;
1238 {
1239   char **result;
1240   register int i, start, result_index, size;
1241   int len, delimiter;
1242
1243   /* If we're searching for a string that's not part of a word (e.g., " "),
1244      make sure we set *INDP to a reasonable value. */
1245   if (indp && wind != -1)
1246     *indp = -1;
1247
1248   /* Get a token, and stuff it into RESULT.  The tokens are split
1249      exactly where the shell would split them. */
1250   for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
1251     {
1252       delimiter = 0;
1253
1254       /* Skip leading whitespace. */
1255       for (; string[i] && whitespace (string[i]); i++)
1256         ;
1257       if (string[i] == 0 || string[i] == history_comment_char)
1258         return (result);
1259
1260       start = i;
1261       
1262       if (member (string[i], "()\n"))
1263         {
1264           i++;
1265           goto got_token;
1266         }
1267
1268       if (member (string[i], "<>;&|$"))
1269         {
1270           int peek = string[i + 1];
1271
1272           if (peek == string[i] && peek != '$')
1273             {
1274               if (peek == '<' && string[i + 2] == '-')
1275                 i++;
1276               i += 2;
1277               goto got_token;
1278             }
1279           else
1280             {
1281               if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
1282                   ((peek == '>') && (string[i] == '&')) ||
1283                   ((peek == '(') && (string[i] == '$')))
1284                 {
1285                   i += 2;
1286                   goto got_token;
1287                 }
1288             }
1289           if (string[i] != '$')
1290             {
1291               i++;
1292               goto got_token;
1293             }
1294         }
1295
1296       /* Get word from string + i; */
1297
1298       if (member (string[i], HISTORY_QUOTE_CHARACTERS))
1299         delimiter = string[i++];
1300
1301       for (; string[i]; i++)
1302         {
1303           if (string[i] == '\\' && string[i + 1] == '\n')
1304             {
1305               i++;
1306               continue;
1307             }
1308
1309           if (string[i] == '\\' && delimiter != '\'' &&
1310               (delimiter != '"' || member (string[i], slashify_in_quotes)))
1311             {
1312               i++;
1313               continue;
1314             }
1315
1316           if (delimiter && string[i] == delimiter)
1317             {
1318               delimiter = 0;
1319               continue;
1320             }
1321
1322           if (!delimiter && (member (string[i], history_word_delimiters)))
1323             break;
1324
1325           if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
1326             delimiter = string[i];
1327         }
1328
1329     got_token:
1330
1331       /* If we are looking for the word in which the character at a
1332          particular index falls, remember it. */
1333       if (indp && wind != -1 && wind >= start && wind < i)
1334         *indp = result_index;
1335
1336       len = i - start;
1337       if (result_index + 2 >= size)
1338         result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
1339       result[result_index] = (char *)xmalloc (1 + len);
1340       strncpy (result[result_index], string + start, len);
1341       result[result_index][len] = '\0';
1342       result[++result_index] = (char *)NULL;
1343     }
1344
1345   return (result);
1346 }
1347
1348 /* Return an array of tokens, much as the shell might.  The tokens are
1349    parsed out of STRING. */
1350 char **
1351 history_tokenize (string)
1352      const char *string;
1353 {
1354   return (history_tokenize_internal (string, -1, (int *)NULL));
1355 }
1356
1357 /* Find and return the word which contains the character at index IND
1358    in the history line LINE.  Used to save the word matched by the
1359    last history !?string? search. */
1360 static char *
1361 history_find_word (line, ind)
1362      char *line;
1363      int ind;
1364 {
1365   char **words, *s;
1366   int i, wind;
1367
1368   words = history_tokenize_internal (line, ind, &wind);
1369   if (wind == -1 || words == 0)
1370     return ((char *)NULL);
1371   s = words[wind];
1372   for (i = 0; i < wind; i++)
1373     free (words[i]);
1374   for (i = wind + 1; words[i]; i++)
1375     free (words[i]);
1376   free (words);
1377   return s;
1378 }