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