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