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    51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA. */
22 
23 #define READLINE_LIBRARY
24 
25 #if defined (HAVE_CONFIG_H)
26 #  include "config_readline.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 static char error_pointer;
60 
61 static char *subst_lhs;
62 static char *subst_rhs;
63 static int subst_lhs_len;
64 static int subst_rhs_len;
65 
66 static char *get_history_word_specifier PARAMS((char *, char *, int *));
67 static char *history_find_word PARAMS((char *, int));
68 static int history_tokenize_word PARAMS((const char *, int));
69 static char *history_substring PARAMS((const char *, int, int));
70 
71 static char *quote_breaks PARAMS((char *));
72 
73 /* Variables exported by this file. */
74 /* The character that represents the start of a history expansion
75    request.  This is usually `!'. */
76 char history_expansion_char = '!';
77 
78 /* The character that invokes word substitution if found at the start of
79    a line.  This is usually `^'. */
80 char history_subst_char = '^';
81 
82 /* During tokenization, if this character is seen as the first character
83    of a word, then it, and all subsequent characters upto a newline are
84    ignored.  For a Bourne shell, this should be '#'.  Bash special cases
85    the interactive comment character to not be a comment delimiter. */
86 char history_comment_char = '\0';
87 
88 /* The list of characters which inhibit the expansion of text if found
89    immediately following history_expansion_char. */
90 const char *history_no_expand_chars = " \t\n\r=";
91 
92 /* If set to a non-zero value, single quotes inhibit history expansion.
93    The default is 0. */
94 int history_quotes_inhibit_expansion = 0;
95 
96 /* Used to split words by history_tokenize_internal. */
97 const char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
98 
99 /* If set, this points to a function that is called to verify that a
100    particular history expansion should be performed. */
101 rl_linebuf_func_t *history_inhibit_expansion_function;
102 
103 /* **************************************************************** */
104 /*								    */
105 /*			History Expansion			    */
106 /*								    */
107 /* **************************************************************** */
108 
109 /* Hairy history expansion on text, not tokens.  This is of general
110    use, and thus belongs in this library. */
111 
112 /* The last string searched for by a !?string? search. */
113 static char *search_string;
114 
115 /* The last string matched by a !?string? search. */
116 static char *search_match;
117 
118 /* Return the event specified at TEXT + OFFSET modifying OFFSET to
119    point to after the event specifier.  Just a pointer to the history
120    line is returned; NULL is returned in the event of a bad specifier.
121    You pass STRING with *INDEX equal to the history_expansion_char that
122    begins this specification.
123    DELIMITING_QUOTE is a character that is allowed to end the string
124    specification for what to search for in addition to the normal
125    characters `:', ` ', `\t', `\n', and sometimes `?'.
126    So you might call this function like:
127    line = get_history_event ("!echo:p", &index, 0);  */
128 char *
get_history_event(string,caller_index,delimiting_quote)129 get_history_event (string, caller_index, delimiting_quote)
130      const char *string;
131      int *caller_index;
132      int delimiting_quote;
133 {
134   register int i;
135   register char c;
136   HIST_ENTRY *entry;
137   int which, sign, local_index, substring_okay;
138   _hist_search_func_t *search_func;
139   char *temp;
140 
141   /* The event can be specified in a number of ways.
142 
143      !!   the previous command
144      !n   command line N
145      !-n  current command-line minus N
146      !str the most recent command starting with STR
147      !?str[?]
148 	  the most recent command containing STR
149 
150      All values N are determined via HISTORY_BASE. */
151 
152   i = *caller_index;
153 
154   if (string[i] != history_expansion_char)
155     return ((char *)NULL);
156 
157   /* Move on to the specification. */
158   i++;
159 
160   sign = 1;
161   substring_okay = 0;
162 
163 #define RETURN_ENTRY(e, w) \
164 	return ((e = history_get (w)) ? e->line : (char *)NULL)
165 
166   /* Handle !! case. */
167   if (string[i] == history_expansion_char)
168     {
169       i++;
170       which = history_base + (history_length - 1);
171       *caller_index = i;
172       RETURN_ENTRY (entry, which);
173     }
174 
175   /* Hack case of numeric line specification. */
176   if (string[i] == '-')
177     {
178       sign = -1;
179       i++;
180     }
181 
182   if (_rl_digit_p (string[i]))
183     {
184       /* Get the extent of the digits and compute the value. */
185       for (which = 0; _rl_digit_p (string[i]); i++)
186 	which = (which * 10) + _rl_digit_value (string[i]);
187 
188       *caller_index = i;
189 
190       if (sign < 0)
191 	which = (history_length + history_base) - which;
192 
193       RETURN_ENTRY (entry, which);
194     }
195 
196   /* This must be something to search for.  If the spec begins with
197      a '?', then the string may be anywhere on the line.  Otherwise,
198      the string must be found at the start of a line. */
199   if (string[i] == '?')
200     {
201       substring_okay++;
202       i++;
203     }
204 
205   /* Only a closing `?' or a newline delimit a substring search string. */
206   for (local_index = i; (c = string[i]); i++)
207     {
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. */
308 static void
hist_string_extract_single_quoted(string,sindex)309 hist_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 
321 static char *
quote_breaks(s)322 quote_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 
363 static char *
hist_error(s,start,current,errtype)364 hist_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 
422 static char *
get_subst_pattern(str,iptr,delimiter,is_rhs,lenptr)423 get_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 
479 static void
postproc_subst_rhs()480 postproc_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. */
516 static int
history_expand_internal(string,start,end_index_ptr,ret_string,current_line)517 history_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, 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 		    we = history_tokenize_word (temp, si);
796 		  }
797 
798 		if (STREQN (temp+si, subst_lhs, subst_lhs_len))
799 		  {
800 		    int len = subst_rhs_len - subst_lhs_len + l_temp;
801 		    new_event = (char *)xmalloc (1 + len);
802 		    strncpy (new_event, temp, si);
803 		    strncpy (new_event + si, subst_rhs, subst_rhs_len);
804 		    strncpy (new_event + si + subst_rhs_len,
805 			     temp + si + subst_lhs_len,
806 			     l_temp - (si + subst_lhs_len));
807 		    new_event[len] = '\0';
808 		    free (temp);
809 		    temp = new_event;
810 
811 		    failed = 0;
812 
813 		    if (substitute_globally)
814 		      {
815 			/* Reported to fix a bug that causes it to skip every
816 			   other match when matching a single character.  Was
817 			   si += subst_rhs_len previously. */
818 			si += subst_rhs_len - 1;
819 			l_temp = strlen (temp);
820 			substitute_globally++;
821 			continue;
822 		      }
823 		    else if (subst_bywords)
824 		      {
825 			si = we;
826 			l_temp = strlen (temp);
827 			continue;
828 		      }
829 		    else
830 		      break;
831 		  }
832 	      }
833 
834 	    if (substitute_globally > 1)
835 	      {
836 		substitute_globally = 0;
837 		continue;	/* don't want to increment i */
838 	      }
839 
840 	    if (failed == 0)
841 	      continue;		/* don't want to increment i */
842 
843 	    *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
844 	    free (result);
845 	    free (temp);
846 	    return (-1);
847 	  }
848 	}
849       i += 2;
850     }
851   /* Done with modfiers. */
852   /* Believe it or not, we have to back the pointer up by one. */
853   --i;
854 
855   if (want_quotes)
856     {
857       char *x;
858 
859       if (want_quotes == 'q')
860 	x = sh_single_quote (temp);
861       else if (want_quotes == 'x')
862 	x = quote_breaks (temp);
863       else
864 	x = savestring (temp);
865 
866       free (temp);
867       temp = x;
868     }
869 
870   n = strlen (temp);
871   if (n >= result_len)
872     result = (char *)xrealloc (result, n + 2);
873   strcpy (result, temp);
874   free (temp);
875 
876   *end_index_ptr = i;
877   *ret_string = result;
878   return (print_only);
879 }
880 
881 /* Expand the string STRING, placing the result into OUTPUT, a pointer
882    to a string.  Returns:
883 
884   -1) If there was an error in expansion.
885    0) If no expansions took place (or, if the only change in
886       the text was the de-slashifying of the history expansion
887       character)
888    1) If expansions did take place
889    2) If the `p' modifier was given and the caller should print the result
890 
891   If an error ocurred in expansion, then OUTPUT contains a descriptive
892   error message. */
893 
894 #define ADD_STRING(s) \
895 	do \
896 	  { \
897 	    int sl = strlen (s); \
898 	    j += sl; \
899 	    if (j >= result_len) \
900 	      { \
901 		while (j >= result_len) \
902 		  result_len += 128; \
903 		result = (char *)xrealloc (result, result_len); \
904 	      } \
905 	    strcpy (result + j - sl, s); \
906 	  } \
907 	while (0)
908 
909 #define ADD_CHAR(c) \
910 	do \
911 	  { \
912 	    if (j >= result_len - 1) \
913 	      result = (char *)xrealloc (result, result_len += 64); \
914 	    result[j++] = c; \
915 	    result[j] = '\0'; \
916 	  } \
917 	while (0)
918 
919 int
history_expand(hstring,output)920 history_expand (hstring, output)
921      char *hstring;
922      char **output;
923 {
924   register int j;
925   int i, r, l, passc, cc, modified, eindex, only_printing, dquote;
926   char *string;
927 
928   /* The output string, and its length. */
929   int result_len;
930   char *result;
931 
932 #if defined (HANDLE_MULTIBYTE)
933   char mb[MB_LEN_MAX];
934   mbstate_t ps;
935 #endif
936 
937   /* Used when adding the string. */
938   char *temp;
939 
940   if (output == 0)
941     return 0;
942 
943   /* Setting the history expansion character to 0 inhibits all
944      history expansion. */
945   if (history_expansion_char == 0)
946     {
947       *output = savestring (hstring);
948       return (0);
949     }
950 
951   /* Prepare the buffer for printing error messages. */
952   result = (char *)xmalloc (result_len = 256);
953   result[0] = '\0';
954 
955   only_printing = modified = 0;
956   l = strlen (hstring);
957 
958   /* Grovel the string.  Only backslash and single quotes can quote the
959      history escape character.  We also handle arg specifiers. */
960 
961   /* Before we grovel forever, see if the history_expansion_char appears
962      anywhere within the text. */
963 
964   /* The quick substitution character is a history expansion all right.  That
965      is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
966      that is the substitution that we do. */
967   if (hstring[0] == history_subst_char)
968     {
969       string = (char *)xmalloc (l + 5);
970 
971       string[0] = string[1] = history_expansion_char;
972       string[2] = ':';
973       string[3] = 's';
974       strcpy (string + 4, hstring);
975       l += 4;
976     }
977   else
978     {
979 #if defined (HANDLE_MULTIBYTE)
980       memset (&ps, 0, sizeof (mbstate_t));
981 #endif
982 
983       string = hstring;
984       /* If not quick substitution, still maybe have to do expansion. */
985 
986       /* `!' followed by one of the characters in history_no_expand_chars
987 	 is NOT an expansion. */
988       for (i = dquote = 0; string[i]; i++)
989 	{
990 #if defined (HANDLE_MULTIBYTE)
991 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
992 	    {
993 	      int v;
994 	      v = _rl_get_char_len (string + i, &ps);
995 	      if (v > 1)
996 		{
997 		  i += v - 1;
998 		  continue;
999 		}
1000 	    }
1001 #endif /* HANDLE_MULTIBYTE */
1002 
1003 	  cc = string[i + 1];
1004 	  /* The history_comment_char, if set, appearing at the beginning
1005 	     of a word signifies that the rest of the line should not have
1006 	     history expansion performed on it.
1007 	     Skip the rest of the line and break out of the loop. */
1008 	  if (history_comment_char && string[i] == history_comment_char &&
1009 	      (i == 0 || member (string[i - 1], history_word_delimiters)))
1010 	    {
1011 	      while (string[i])
1012 		i++;
1013 	      break;
1014 	    }
1015 	  else if (string[i] == history_expansion_char)
1016 	    {
1017 	      if (!cc || member (cc, history_no_expand_chars))
1018 		continue;
1019 	      /* If the calling application has set
1020 		 history_inhibit_expansion_function to a function that checks
1021 		 for special cases that should not be history expanded,
1022 		 call the function and skip the expansion if it returns a
1023 		 non-zero value. */
1024 	      else if (history_inhibit_expansion_function &&
1025 			(*history_inhibit_expansion_function) (string, i))
1026 		continue;
1027 	      else
1028 		break;
1029 	    }
1030 	  /* Shell-like quoting: allow backslashes to quote double quotes
1031 	     inside a double-quoted string. */
1032 	  else if (dquote && string[i] == '\\' && cc == '"')
1033 	    i++;
1034 	  /* More shell-like quoting:  if we're paying attention to single
1035 	     quotes and letting them quote the history expansion character,
1036 	     then we need to pay attention to double quotes, because single
1037 	     quotes are not special inside double-quoted strings. */
1038 	  else if (history_quotes_inhibit_expansion && string[i] == '"')
1039 	    {
1040 	      dquote = 1 - dquote;
1041 	    }
1042 	  else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')
1043 	    {
1044 	      /* If this is bash, single quotes inhibit history expansion. */
1045 	      i++;
1046 	      hist_string_extract_single_quoted (string, &i);
1047 	    }
1048 	  else if (history_quotes_inhibit_expansion && string[i] == '\\')
1049 	    {
1050 	      /* If this is bash, allow backslashes to quote single
1051 		 quotes and the history expansion character. */
1052 	      if (cc == '\'' || cc == history_expansion_char)
1053 		i++;
1054 	    }
1055 
1056 	}
1057 
1058       if (string[i] != history_expansion_char)
1059 	{
1060 	  free (result);
1061 	  *output = savestring (string);
1062 	  return (0);
1063 	}
1064     }
1065 
1066   /* Extract and perform the substitution. */
1067   for (passc = dquote = i = j = 0; i < l; i++)
1068     {
1069       int tchar = string[i];
1070 
1071       if (passc)
1072 	{
1073 	  passc = 0;
1074 	  ADD_CHAR (tchar);
1075 	  continue;
1076 	}
1077 
1078 #if defined (HANDLE_MULTIBYTE)
1079       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1080 	{
1081 	  int k, c;
1082 
1083 	  c = tchar;
1084 	  memset (mb, 0, sizeof (mb));
1085 	  for (k = 0; k < MB_LEN_MAX; k++)
1086 	    {
1087 	      mb[k] = (char)c;
1088 	      memset (&ps, 0, sizeof (mbstate_t));
1089 	      if (_rl_get_char_len (mb, &ps) == -2)
1090 		c = string[++i];
1091 	      else
1092 		break;
1093 	    }
1094 	  if (strlen (mb) > 1)
1095 	    {
1096 	      ADD_STRING (mb);
1097 	      break;
1098 	    }
1099 	}
1100 #endif /* HANDLE_MULTIBYTE */
1101 
1102       if (tchar == history_expansion_char)
1103 	tchar = -3;
1104       else if (tchar == history_comment_char)
1105 	tchar = -2;
1106 
1107       switch (tchar)
1108 	{
1109 	default:
1110 	  ADD_CHAR (string[i]);
1111 	  break;
1112 
1113 	case '\\':
1114 	  passc++;
1115 	  ADD_CHAR (tchar);
1116 	  break;
1117 
1118 	case '"':
1119 	  dquote = 1 - dquote;
1120 	  ADD_CHAR (tchar);
1121 	  break;
1122 
1123 	case '\'':
1124 	  {
1125 	    /* If history_quotes_inhibit_expansion is set, single quotes
1126 	       inhibit history expansion. */
1127 	    if (dquote == 0 && history_quotes_inhibit_expansion)
1128 	      {
1129 		int quote, slen;
1130 
1131 		quote = i++;
1132 		hist_string_extract_single_quoted (string, &i);
1133 
1134 		slen = i - quote + 2;
1135 		temp = (char *)xmalloc (slen);
1136 		strncpy (temp, string + quote, slen);
1137 		temp[slen - 1] = '\0';
1138 		ADD_STRING (temp);
1139 		free (temp);
1140 	      }
1141 	    else
1142 	      ADD_CHAR (string[i]);
1143 	    break;
1144 	  }
1145 
1146 	case -2:		/* history_comment_char */
1147 	  if (i == 0 || member (string[i - 1], history_word_delimiters))
1148 	    {
1149 	      temp = (char *)xmalloc (l - i + 1);
1150 	      strcpy (temp, string + i);
1151 	      ADD_STRING (temp);
1152 	      free (temp);
1153 	      i = l;
1154 	    }
1155 	  else
1156 	    ADD_CHAR (string[i]);
1157 	  break;
1158 
1159 	case -3:		/* history_expansion_char */
1160 	  cc = string[i + 1];
1161 
1162 	  /* If the history_expansion_char is followed by one of the
1163 	     characters in history_no_expand_chars, then it is not a
1164 	     candidate for expansion of any kind. */
1165 	  if (member (cc, history_no_expand_chars))
1166 	    {
1167 	      ADD_CHAR (string[i]);
1168 	      break;
1169 	    }
1170 
1171 #if defined (NO_BANG_HASH_MODIFIERS)
1172 	  /* There is something that is listed as a `word specifier' in csh
1173 	     documentation which means `the expanded text to this point'.
1174 	     That is not a word specifier, it is an event specifier.  If we
1175 	     don't want to allow modifiers with `!#', just stick the current
1176 	     output line in again. */
1177 	  if (cc == '#')
1178 	    {
1179 	      if (result)
1180 		{
1181 		  temp = (char *)xmalloc (1 + strlen (result));
1182 		  strcpy (temp, result);
1183 		  ADD_STRING (temp);
1184 		  free (temp);
1185 		}
1186 	      i++;
1187 	      break;
1188 	    }
1189 #endif
1190 
1191 	  r = history_expand_internal (string, i, &eindex, &temp, result);
1192 	  if (r < 0)
1193 	    {
1194 	      *output = temp;
1195 	      free (result);
1196 	      if (string != hstring)
1197 		free (string);
1198 	      return -1;
1199 	    }
1200 	  else
1201 	    {
1202 	      if (temp)
1203 		{
1204 		  modified++;
1205 		  if (*temp)
1206 		    ADD_STRING (temp);
1207 		  free (temp);
1208 		}
1209 	      only_printing = r == 1;
1210 	      i = eindex;
1211 	    }
1212 	  break;
1213 	}
1214     }
1215 
1216   *output = result;
1217   if (string != hstring)
1218     free (string);
1219 
1220   if (only_printing)
1221     {
1222 #if 0
1223       add_history (result);
1224 #endif
1225       return (2);
1226     }
1227 
1228   return (modified != 0);
1229 }
1230 
1231 /* Return a consed string which is the word specified in SPEC, and found
1232    in FROM.  NULL is returned if there is no spec.  The address of
1233    ERROR_POINTER is returned if the word specified cannot be found.
1234    CALLER_INDEX is the offset in SPEC to start looking; it is updated
1235    to point to just after the last character parsed. */
1236 static char *
get_history_word_specifier(spec,from,caller_index)1237 get_history_word_specifier (spec, from, caller_index)
1238      char *spec, *from;
1239      int *caller_index;
1240 {
1241   register int i = *caller_index;
1242   int first, last;
1243   int expecting_word_spec = 0;
1244   char *result;
1245 
1246   /* The range of words to return doesn't exist yet. */
1247   first = last = 0;
1248   result = (char *)NULL;
1249 
1250   /* If we found a colon, then this *must* be a word specification.  If
1251      it isn't, then it is an error. */
1252   if (spec[i] == ':')
1253     {
1254       i++;
1255       expecting_word_spec++;
1256     }
1257 
1258   /* Handle special cases first. */
1259 
1260   /* `%' is the word last searched for. */
1261   if (spec[i] == '%')
1262     {
1263       *caller_index = i + 1;
1264       return (search_match ? savestring (search_match) : savestring (""));
1265     }
1266 
1267   /* `*' matches all of the arguments, but not the command. */
1268   if (spec[i] == '*')
1269     {
1270       *caller_index = i + 1;
1271       result = history_arg_extract (1, '$', from);
1272       return (result ? result : savestring (""));
1273     }
1274 
1275   /* `$' is last arg. */
1276   if (spec[i] == '$')
1277     {
1278       *caller_index = i + 1;
1279       return (history_arg_extract ('$', '$', from));
1280     }
1281 
1282   /* Try to get FIRST and LAST figured out. */
1283 
1284   if (spec[i] == '-')
1285     first = 0;
1286   else if (spec[i] == '^')
1287     {
1288       first = 1;
1289       i++;
1290     }
1291   else if (_rl_digit_p (spec[i]) && expecting_word_spec)
1292     {
1293       for (first = 0; _rl_digit_p (spec[i]); i++)
1294 	first = (first * 10) + _rl_digit_value (spec[i]);
1295     }
1296   else
1297     return ((char *)NULL);	/* no valid `first' for word specifier */
1298 
1299   if (spec[i] == '^' || spec[i] == '*')
1300     {
1301       last = (spec[i] == '^') ? 1 : '$';	/* x* abbreviates x-$ */
1302       i++;
1303     }
1304   else if (spec[i] != '-')
1305     last = first;
1306   else
1307     {
1308       i++;
1309 
1310       if (_rl_digit_p (spec[i]))
1311 	{
1312 	  for (last = 0; _rl_digit_p (spec[i]); i++)
1313 	    last = (last * 10) + _rl_digit_value (spec[i]);
1314 	}
1315       else if (spec[i] == '$')
1316 	{
1317 	  i++;
1318 	  last = '$';
1319 	}
1320 #if 0
1321       else if (!spec[i] || spec[i] == ':')
1322 	/* check against `:' because there could be a modifier separator */
1323 #else
1324       else
1325 	/* csh seems to allow anything to terminate the word spec here,
1326 	   leaving it as an abbreviation. */
1327 #endif
1328 	last = -1;		/* x- abbreviates x-$ omitting word `$' */
1329     }
1330 
1331   *caller_index = i;
1332 
1333   if (last >= first || last == '$' || last < 0)
1334     result = history_arg_extract (first, last, from);
1335 
1336   return (result ? result : (char *)&error_pointer);
1337 }
1338 
1339 /* Extract the args specified, starting at FIRST, and ending at LAST.
1340    The args are taken from STRING.  If either FIRST or LAST is < 0,
1341    then make that arg count from the right (subtract from the number of
1342    tokens, so that FIRST = -1 means the next to last token on the line).
1343    If LAST is `$' the last arg from STRING is used. */
1344 char *
history_arg_extract(first,last,string)1345 history_arg_extract (first, last, string)
1346      int first, last;
1347      const char *string;
1348 {
1349   register int i, len;
1350   char *result;
1351   int size, offset;
1352   char **list;
1353 
1354   /* XXX - think about making history_tokenize return a struct array,
1355      each struct in array being a string and a length to avoid the
1356      calls to strlen below. */
1357   if ((list = history_tokenize (string)) == NULL)
1358     return ((char *)NULL);
1359 
1360   for (len = 0; list[len]; len++)
1361     ;
1362 
1363   if (last < 0)
1364     last = len + last - 1;
1365 
1366   if (first < 0)
1367     first = len + first - 1;
1368 
1369   if (last == '$')
1370     last = len - 1;
1371 
1372   if (first == '$')
1373     first = len - 1;
1374 
1375   last++;
1376 
1377   if (first >= len || last > len || first < 0 || last < 0 || first > last)
1378     result = ((char *)NULL);
1379   else
1380     {
1381       for (size = 0, i = first; i < last; i++)
1382 	size += strlen (list[i]) + 1;
1383       result = (char *)xmalloc (size + 1);
1384       result[0] = '\0';
1385 
1386       for (i = first, offset = 0; i < last; i++)
1387 	{
1388 	  strcpy (result + offset, list[i]);
1389 	  offset += strlen (list[i]);
1390 	  if (i + 1 < last)
1391 	    {
1392       	      result[offset++] = ' ';
1393 	      result[offset] = 0;
1394 	    }
1395 	}
1396     }
1397 
1398   for (i = 0; i < len; i++)
1399     free (list[i]);
1400   free (list);
1401 
1402   return (result);
1403 }
1404 
1405 static int
history_tokenize_word(string,ind)1406 history_tokenize_word (string, ind)
1407      const char *string;
1408      int ind;
1409 {
1410   register int i;
1411   int delimiter;
1412 
1413   i = ind;
1414   delimiter = 0;
1415 
1416   if (member (string[i], "()\n"))
1417     {
1418       i++;
1419       return i;
1420     }
1421 
1422   if (member (string[i], "<>;&|$"))
1423     {
1424       int peek = string[i + 1];
1425 
1426       if (peek == string[i] && peek != '$')
1427 	{
1428 	  if (peek == '<' && string[i + 2] == '-')
1429 	    i++;
1430 	  else if (peek == '<' && string[i + 2] == '<')
1431 	    i++;
1432 	  i += 2;
1433 	  return i;
1434 	}
1435       else
1436 	{
1437 	  if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
1438 	      (peek == '>' && string[i] == '&') ||
1439 	      (peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
1440 	      (peek == '(' && string[i] == '$')) /* ) */
1441 	    {
1442 	      i += 2;
1443 	      return i;
1444 	    }
1445 	}
1446 
1447       if (string[i] != '$')
1448 	{
1449 	  i++;
1450 	  return i;
1451 	}
1452     }
1453 
1454   /* Get word from string + i; */
1455 
1456   if (member (string[i], HISTORY_QUOTE_CHARACTERS))
1457     delimiter = string[i++];
1458 
1459   for (; string[i]; i++)
1460     {
1461       if (string[i] == '\\' && string[i + 1] == '\n')
1462 	{
1463 	  i++;
1464 	  continue;
1465 	}
1466 
1467       if (string[i] == '\\' && delimiter != '\'' &&
1468 	  (delimiter != '"' || member (string[i], slashify_in_quotes)))
1469 	{
1470 	  i++;
1471 	  continue;
1472 	}
1473 
1474       if (delimiter && string[i] == delimiter)
1475 	{
1476 	  delimiter = 0;
1477 	  continue;
1478 	}
1479 
1480       if (!delimiter && (member (string[i], history_word_delimiters)))
1481 	break;
1482 
1483       if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
1484 	delimiter = string[i];
1485     }
1486 
1487   return i;
1488 }
1489 
1490 static char *
history_substring(string,start,end)1491 history_substring (string, start, end)
1492      const char *string;
1493      int start, end;
1494 {
1495   register int len;
1496   register char *result;
1497 
1498   len = end - start;
1499   result = (char *)xmalloc (len + 1);
1500   strncpy (result, string + start, len);
1501   result[len] = '\0';
1502   return result;
1503 }
1504 
1505 /* Parse STRING into tokens and return an array of strings.  If WIND is
1506    not -1 and INDP is not null, we also want the word surrounding index
1507    WIND.  The position in the returned array of strings is returned in
1508    *INDP. */
1509 static char **
history_tokenize_internal(string,wind,indp)1510 history_tokenize_internal (string, wind, indp)
1511      const char *string;
1512      int wind, *indp;
1513 {
1514   char **result;
1515   register int i, start, result_index, size;
1516 
1517   /* If we're searching for a string that's not part of a word (e.g., " "),
1518      make sure we set *INDP to a reasonable value. */
1519   if (indp && wind != -1)
1520     *indp = -1;
1521 
1522   /* Get a token, and stuff it into RESULT.  The tokens are split
1523      exactly where the shell would split them. */
1524   for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
1525     {
1526       /* Skip leading whitespace. */
1527       for (; string[i] && whitespace (string[i]); i++)
1528 	;
1529       if (string[i] == 0 || string[i] == history_comment_char)
1530 	return (result);
1531 
1532       start = i;
1533 
1534       i = history_tokenize_word (string, start);
1535 
1536       /* If we have a non-whitespace delimiter character (which would not be
1537 	 skipped by the loop above), use it and any adjacent delimiters to
1538 	 make a separate field.  Any adjacent white space will be skipped the
1539 	 next time through the loop. */
1540       if (i == start && history_word_delimiters)
1541 	{
1542 	  i++;
1543 	  while (string[i] && member (string[i], history_word_delimiters))
1544 	    i++;
1545 	}
1546 
1547       /* If we are looking for the word in which the character at a
1548 	 particular index falls, remember it. */
1549       if (indp && wind != -1 && wind >= start && wind < i)
1550         *indp = result_index;
1551 
1552       if (result_index + 2 >= size)
1553 	result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
1554 
1555       result[result_index++] = history_substring (string, start, i);
1556       result[result_index] = (char *)NULL;
1557     }
1558 
1559   return (result);
1560 }
1561 
1562 /* Return an array of tokens, much as the shell might.  The tokens are
1563    parsed out of STRING. */
1564 char **
history_tokenize(string)1565 history_tokenize (string)
1566      const char *string;
1567 {
1568   return (history_tokenize_internal (string, -1, (int *)NULL));
1569 }
1570 
1571 /* Find and return the word which contains the character at index IND
1572    in the history line LINE.  Used to save the word matched by the
1573    last history !?string? search. */
1574 static char *
history_find_word(line,ind)1575 history_find_word (line, ind)
1576      char *line;
1577      int ind;
1578 {
1579   char **words, *s;
1580   int i, wind;
1581 
1582   words = history_tokenize_internal (line, ind, &wind);
1583   if (wind == -1 || words == 0)
1584     return ((char *)NULL);
1585   s = words[wind];
1586   for (i = 0; i < wind; i++)
1587     free (words[i]);
1588   for (i = wind + 1; words[i]; i++)
1589     free (words[i]);
1590   free (words);
1591   return s;
1592 }
1593