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