1 /* histexpand.c -- history expansion. */
3 /* Copyright (C) 1989-2012 Free Software Foundation, Inc.
5 This file contains the GNU History Library (History), a set of
6 routines for managing the text of previously typed lines.
8 History 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 3 of the License, or
11 (at your option) any later version.
13 History is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with History. If not, see <http://www.gnu.org/licenses/>.
22 #define READLINE_LIBRARY
24 #if defined (HAVE_CONFIG_H)
30 #if defined (HAVE_STDLIB_H)
33 # include "ansi_stdlib.h"
34 #endif /* HAVE_STDLIB_H */
36 #if defined (HAVE_UNISTD_H)
38 # include <sys/types.h>
51 #define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
52 #define HISTORY_QUOTE_CHARACTERS "\"'`"
53 #define HISTORY_EVENT_DELIMITERS "^$*%-"
55 #define slashify_in_quotes "\\`\"$"
57 typedef int _hist_search_func_t
PARAMS((const char *, int));
59 static char error_pointer
;
61 static char *subst_lhs
;
62 static char *subst_rhs
;
63 static int subst_lhs_len
;
64 static int subst_rhs_len
;
66 /* Characters that delimit history event specifications and separate event
67 specifications from word designators. Static for now */
68 static char *history_event_delimiter_chars
= HISTORY_EVENT_DELIMITERS
;
70 static char *get_history_word_specifier
PARAMS((char *, char *, int *));
71 static int history_tokenize_word
PARAMS((const char *, int));
72 static char **history_tokenize_internal
PARAMS((const char *, int, int *));
73 static char *history_substring
PARAMS((const char *, int, int));
74 static void freewords
PARAMS((char **, int));
75 static char *history_find_word
PARAMS((char *, int));
77 static char *quote_breaks
PARAMS((char *));
79 /* Variables exported by this file. */
80 /* The character that represents the start of a history expansion
81 request. This is usually `!'. */
82 char history_expansion_char
= '!';
84 /* The character that invokes word substitution if found at the start of
85 a line. This is usually `^'. */
86 char history_subst_char
= '^';
88 /* During tokenization, if this character is seen as the first character
89 of a word, then it, and all subsequent characters upto a newline are
90 ignored. For a Bourne shell, this should be '#'. Bash special cases
91 the interactive comment character to not be a comment delimiter. */
92 char history_comment_char
= '\0';
94 /* The list of characters which inhibit the expansion of text if found
95 immediately following history_expansion_char. */
96 char *history_no_expand_chars
= " \t\n\r=";
98 /* If set to a non-zero value, single quotes inhibit history expansion.
100 int history_quotes_inhibit_expansion
= 0;
102 /* Used to split words by history_tokenize_internal. */
103 char *history_word_delimiters
= HISTORY_WORD_DELIMITERS
;
105 /* If set, this points to a function that is called to verify that a
106 particular history expansion should be performed. */
107 rl_linebuf_func_t
*history_inhibit_expansion_function
;
109 /* **************************************************************** */
111 /* History Expansion */
113 /* **************************************************************** */
115 /* Hairy history expansion on text, not tokens. This is of general
116 use, and thus belongs in this library. */
118 /* The last string searched for by a !?string? search. */
119 static char *search_string
;
120 /* The last string matched by a !?string? search. */
121 static char *search_match
;
123 /* Return the event specified at TEXT + OFFSET modifying OFFSET to
124 point to after the event specifier. Just a pointer to the history
125 line is returned; NULL is returned in the event of a bad specifier.
126 You pass STRING with *INDEX equal to the history_expansion_char that
127 begins this specification.
128 DELIMITING_QUOTE is a character that is allowed to end the string
129 specification for what to search for in addition to the normal
130 characters `:', ` ', `\t', `\n', and sometimes `?'.
131 So you might call this function like:
132 line = get_history_event ("!echo:p", &index, 0); */
134 get_history_event (string
, caller_index
, delimiting_quote
)
137 int delimiting_quote
;
142 int which
, sign
, local_index
, substring_okay
;
143 _hist_search_func_t
*search_func
;
146 /* The event can be specified in a number of ways.
148 !! the previous command
150 !-n current command-line minus N
151 !str the most recent command starting with STR
153 the most recent command containing STR
155 All values N are determined via HISTORY_BASE. */
159 if (string
[i
] != history_expansion_char
)
160 return ((char *)NULL
);
162 /* Move on to the specification. */
168 #define RETURN_ENTRY(e, w) \
169 return ((e = history_get (w)) ? e->line : (char *)NULL)
171 /* Handle !! case. */
172 if (string
[i
] == history_expansion_char
)
175 which
= history_base
+ (history_length
- 1);
177 RETURN_ENTRY (entry
, which
);
180 /* Hack case of numeric line specification. */
181 if (string
[i
] == '-')
187 if (_rl_digit_p (string
[i
]))
189 /* Get the extent of the digits and compute the value. */
190 for (which
= 0; _rl_digit_p (string
[i
]); i
++)
191 which
= (which
* 10) + _rl_digit_value (string
[i
]);
196 which
= (history_length
+ history_base
) - which
;
198 RETURN_ENTRY (entry
, which
);
201 /* This must be something to search for. If the spec begins with
202 a '?', then the string may be anywhere on the line. Otherwise,
203 the string must be found at the start of a line. */
204 if (string
[i
] == '?')
210 /* Only a closing `?' or a newline delimit a substring search string. */
211 for (local_index
= i
; c
= string
[i
]; i
++)
213 #if defined (HANDLE_MULTIBYTE)
214 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
219 memset (&ps
, 0, sizeof (mbstate_t));
220 /* These produce warnings because we're passing a const string to a
221 function that takes a non-const string. */
222 _rl_adjust_point ((char *)string
, i
, &ps
);
223 if ((v
= _rl_get_char_len ((char *)string
+ i
, &ps
)) > 1)
230 #endif /* HANDLE_MULTIBYTE */
231 if ((!substring_okay
&& (whitespace (c
) || c
== ':' ||
232 (history_event_delimiter_chars
&& member (c
, history_event_delimiter_chars
)) ||
233 (history_search_delimiter_chars
&& member (c
, history_search_delimiter_chars
)) ||
234 string
[i
] == delimiting_quote
)) ||
236 (substring_okay
&& string
[i
] == '?'))
240 which
= i
- local_index
;
241 temp
= (char *)xmalloc (1 + which
);
243 strncpy (temp
, string
+ local_index
, which
);
246 if (substring_okay
&& string
[i
] == '?')
251 #define FAIL_SEARCH() \
253 history_offset = history_length; xfree (temp) ; return (char *)NULL; \
256 /* If there is no search string, try to use the previous search string,
257 if one exists. If not, fail immediately. */
258 if (*temp
== '\0' && substring_okay
)
263 temp
= savestring (search_string
);
269 search_func
= substring_okay
? history_search
: history_search_prefix
;
272 local_index
= (*search_func
) (temp
, -1);
277 if (local_index
== 0 || substring_okay
)
279 entry
= current_history ();
282 history_offset
= history_length
;
284 /* If this was a substring search, then remember the
285 string that we matched for word substitution. */
288 FREE (search_string
);
289 search_string
= temp
;
292 search_match
= history_find_word (entry
->line
, local_index
);
297 return (entry
->line
);
309 /* Function for extracting single-quoted strings. Used for inhibiting
310 history expansion within single quotes. */
312 /* Extract the contents of STRING as if it is enclosed in single quotes.
313 SINDEX, when passed in, is the offset of the character immediately
314 following the opening single quote; on exit, SINDEX is left pointing
315 to the closing single quote. FLAGS currently used to allow backslash
316 to escape a single quote (e.g., for bash $'...'). */
318 hist_string_extract_single_quoted (string
, sindex
, flags
)
324 for (i
= *sindex
; string
[i
] && string
[i
] != '\''; i
++)
326 if ((flags
& 1) && string
[i
] == '\\' && string
[i
+1])
337 register char *p
, *r
;
341 for (p
= s
; p
&& *p
; p
++, len
++)
345 else if (whitespace (*p
) || *p
== '\n')
349 r
= ret
= (char *)xmalloc (len
);
351 for (p
= s
; p
&& *p
; )
361 else if (whitespace (*p
) || *p
== '\n')
376 hist_error(s
, start
, current
, errtype
)
378 int start
, current
, errtype
;
384 ll
= current
- start
;
388 case EVENT_NOT_FOUND
:
389 emsg
= "event not found";
393 emsg
= "bad word specifier";
397 emsg
= "substitution failed";
401 emsg
= "unrecognized history modifier";
405 emsg
= "no previous substitution";
409 emsg
= "unknown expansion error";
414 temp
= (char *)xmalloc (ll
+ elen
+ 3);
415 strncpy (temp
, s
+ start
, ll
);
418 strcpy (temp
+ ll
+ 2, emsg
);
422 /* Get a history substitution string from STR starting at *IPTR
423 and return it. The length is returned in LENPTR.
425 A backslash can quote the delimiter. If the string is the
426 empty string, the previous pattern is used. If there is
427 no previous pattern for the lhs, the last history search
430 If IS_RHS is 1, we ignore empty strings and set the pattern
431 to "" anyway. subst_lhs is not changed if the lhs is empty;
432 subst_rhs is allowed to be set to the empty string. */
435 get_subst_pattern (str
, iptr
, delimiter
, is_rhs
, lenptr
)
437 int *iptr
, delimiter
, is_rhs
, *lenptr
;
439 register int si
, i
, j
, k
;
441 #if defined (HANDLE_MULTIBYTE)
448 #if defined (HANDLE_MULTIBYTE)
449 memset (&ps
, 0, sizeof (mbstate_t));
450 _rl_adjust_point (str
, i
, &ps
);
453 for (si
= i
; str
[si
] && str
[si
] != delimiter
; si
++)
454 #if defined (HANDLE_MULTIBYTE)
455 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
458 if ((v
= _rl_get_char_len (str
+ si
, &ps
)) > 1)
460 else if (str
[si
] == '\\' && str
[si
+ 1] == delimiter
)
464 #endif /* HANDLE_MULTIBYTE */
465 if (str
[si
] == '\\' && str
[si
+ 1] == delimiter
)
468 if (si
> i
|| is_rhs
)
470 s
= (char *)xmalloc (si
- i
+ 1);
471 for (j
= 0, k
= i
; k
< si
; j
++, k
++)
473 /* Remove a backslash quoting the search string delimiter. */
474 if (str
[k
] == '\\' && str
[k
+ 1] == delimiter
)
492 postproc_subst_rhs ()
497 new = (char *)xmalloc (new_size
= subst_rhs_len
+ subst_lhs_len
);
498 for (i
= j
= 0; i
< subst_rhs_len
; i
++)
500 if (subst_rhs
[i
] == '&')
502 if (j
+ subst_lhs_len
>= new_size
)
503 new = (char *)xrealloc (new, (new_size
= new_size
* 2 + subst_lhs_len
));
504 strcpy (new + j
, subst_lhs
);
509 /* a single backslash protects the `&' from lhs interpolation */
510 if (subst_rhs
[i
] == '\\' && subst_rhs
[i
+ 1] == '&')
513 new = (char *)xrealloc (new, new_size
*= 2);
514 new[j
++] = subst_rhs
[i
];
523 /* Expand the bulk of a history specifier starting at STRING[START].
524 Returns 0 if everything is OK, -1 if an error occurred, and 1
525 if the `p' modifier was supplied and the caller should just print
526 the returned string. Returns the new index into string in
527 *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
529 history_expand_internal (string
, start
, qc
, end_index_ptr
, ret_string
, current_line
)
531 int start
, qc
, *end_index_ptr
;
533 char *current_line
; /* for !# */
535 int i
, n
, starting_index
;
536 int substitute_globally
, subst_bywords
, want_quotes
, print_only
;
537 char *event
, *temp
, *result
, *tstr
, *t
, c
, *word_spec
;
539 #if defined (HANDLE_MULTIBYTE)
542 memset (&ps
, 0, sizeof (mbstate_t));
545 result
= (char *)xmalloc (result_len
= 128);
549 /* If it is followed by something that starts a word specifier,
550 then !! is implied as the event specifier. */
552 if (member (string
[i
+ 1], ":$*%^"))
557 fake_s
[0] = fake_s
[1] = history_expansion_char
;
559 event
= get_history_event (fake_s
, &fake_i
, 0);
561 else if (string
[i
+ 1] == '#')
564 event
= current_line
;
567 event
= get_history_event (string
, &i
, qc
);
571 *ret_string
= hist_error (string
, start
, i
, EVENT_NOT_FOUND
);
576 /* If a word specifier is found, then do what that requires. */
578 word_spec
= get_history_word_specifier (string
, event
, &i
);
580 /* There is no such thing as a `malformed word specifier'. However,
581 it is possible for a specifier that has no match. In that case,
583 if (word_spec
== (char *)&error_pointer
)
585 *ret_string
= hist_error (string
, starting_index
, i
, BAD_WORD_SPEC
);
590 /* If no word specifier, than the thing of interest was the event. */
591 temp
= word_spec
? savestring (word_spec
) : savestring (event
);
594 /* Perhaps there are other modifiers involved. Do what they say. */
595 want_quotes
= substitute_globally
= subst_bywords
= print_only
= 0;
598 while (string
[i
] == ':')
602 if (c
== 'g' || c
== 'a')
604 substitute_globally
= 1;
618 *ret_string
= hist_error (string
, i
+1, i
+2, BAD_MODIFIER
);
631 /* :p means make this the last executed line. So we
632 return an error state after adding this line to the
638 /* :t discards all but the last part of the pathname. */
640 tstr
= strrchr (temp
, '/');
644 t
= savestring (tstr
);
650 /* :h discards the last part of a pathname. */
652 tstr
= strrchr (temp
, '/');
657 /* :r discards the suffix. */
659 tstr
= strrchr (temp
, '.');
664 /* :e discards everything but the suffix. */
666 tstr
= strrchr (temp
, '.');
669 t
= savestring (tstr
);
675 /* :s/this/that substitutes `that' for the first
676 occurrence of `this'. :gs/this/that substitutes `that'
677 for each occurrence of `this'. :& repeats the last
678 substitution. :g& repeats the last substitution
685 int delimiter
, failed
, si
, l_temp
, ws
, we
;
689 if (i
+ 2 < (int)strlen (string
))
691 #if defined (HANDLE_MULTIBYTE)
692 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
694 _rl_adjust_point (string
, i
+ 2, &ps
);
695 if (_rl_get_char_len (string
+ i
+ 2, &ps
) > 1)
698 delimiter
= string
[i
+ 2];
701 #endif /* HANDLE_MULTIBYTE */
702 delimiter
= string
[i
+ 2];
705 break; /* no search delimiter */
709 t
= get_subst_pattern (string
, &i
, delimiter
, 0, &subst_lhs_len
);
710 /* An empty substitution lhs with no previous substitution
711 uses the last search string as the lhs. */
719 if (search_string
&& *search_string
)
721 subst_lhs
= savestring (search_string
);
722 subst_lhs_len
= strlen (subst_lhs
);
726 subst_lhs
= (char *) NULL
;
732 subst_rhs
= get_subst_pattern (string
, &i
, delimiter
, 1, &subst_rhs_len
);
734 /* If `&' appears in the rhs, it's supposed to be replaced
736 if (member ('&', subst_rhs
))
737 postproc_subst_rhs ();
742 /* If there is no lhs, the substitution can't succeed. */
743 if (subst_lhs_len
== 0)
745 *ret_string
= hist_error (string
, starting_index
, i
, NO_PREV_SUBST
);
751 l_temp
= strlen (temp
);
752 /* Ignore impossible cases. */
753 if (subst_lhs_len
> l_temp
)
755 *ret_string
= hist_error (string
, starting_index
, i
, SUBST_FAILED
);
761 /* Find the first occurrence of THIS in TEMP. */
762 /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
765 1. substitute_globally == subst_bywords == 0
766 2. substitute_globally == 1 && subst_bywords == 0
767 3. substitute_globally == 0 && subst_bywords == 1
769 In the first case, we substitute for the first occurrence only.
770 In the second case, we substitute for every occurrence.
771 In the third case, we tokenize into words and substitute the
772 first occurrence of each word. */
775 for (failed
= 1; (si
+ subst_lhs_len
) <= l_temp
; si
++)
777 /* First skip whitespace and find word boundaries if
778 we're past the end of the word boundary we found
780 if (subst_bywords
&& si
> we
)
782 for (; temp
[si
] && whitespace (temp
[si
]); si
++)
785 we
= history_tokenize_word (temp
, si
);
788 if (STREQN (temp
+si
, subst_lhs
, subst_lhs_len
))
790 int len
= subst_rhs_len
- subst_lhs_len
+ l_temp
;
791 new_event
= (char *)xmalloc (1 + len
);
792 strncpy (new_event
, temp
, si
);
793 strncpy (new_event
+ si
, subst_rhs
, subst_rhs_len
);
794 strncpy (new_event
+ si
+ subst_rhs_len
,
795 temp
+ si
+ subst_lhs_len
,
796 l_temp
- (si
+ subst_lhs_len
));
797 new_event
[len
] = '\0';
803 if (substitute_globally
)
805 /* Reported to fix a bug that causes it to skip every
806 other match when matching a single character. Was
807 si += subst_rhs_len previously. */
808 si
+= subst_rhs_len
- 1;
809 l_temp
= strlen (temp
);
810 substitute_globally
++;
813 else if (subst_bywords
)
816 l_temp
= strlen (temp
);
824 if (substitute_globally
> 1)
826 substitute_globally
= 0;
827 continue; /* don't want to increment i */
831 continue; /* don't want to increment i */
833 *ret_string
= hist_error (string
, starting_index
, i
, SUBST_FAILED
);
841 /* Done with modifiers. */
842 /* Believe it or not, we have to back the pointer up by one. */
849 if (want_quotes
== 'q')
850 x
= sh_single_quote (temp
);
851 else if (want_quotes
== 'x')
852 x
= quote_breaks (temp
);
854 x
= savestring (temp
);
862 result
= (char *)xrealloc (result
, n
+ 2);
863 strcpy (result
, temp
);
867 *ret_string
= result
;
871 /* Expand the string STRING, placing the result into OUTPUT, a pointer
872 to a string. Returns:
874 -1) If there was an error in expansion.
875 0) If no expansions took place (or, if the only change in
876 the text was the de-slashifying of the history expansion
878 1) If expansions did take place
879 2) If the `p' modifier was given and the caller should print the result
881 If an error occurred in expansion, then OUTPUT contains a descriptive
884 #define ADD_STRING(s) \
887 int sl = strlen (s); \
889 if (j >= result_len) \
891 while (j >= result_len) \
893 result = (char *)xrealloc (result, result_len); \
895 strcpy (result + j - sl, s); \
899 #define ADD_CHAR(c) \
902 if (j >= result_len - 1) \
903 result = (char *)xrealloc (result, result_len += 64); \
910 history_expand (hstring
, output
)
915 int i
, r
, l
, passc
, cc
, modified
, eindex
, only_printing
, dquote
, squote
, flag
;
918 /* The output string, and its length. */
922 #if defined (HANDLE_MULTIBYTE)
927 /* Used when adding the string. */
933 /* Setting the history expansion character to 0 inhibits all
934 history expansion. */
935 if (history_expansion_char
== 0)
937 *output
= savestring (hstring
);
941 /* Prepare the buffer for printing error messages. */
942 result
= (char *)xmalloc (result_len
= 256);
945 only_printing
= modified
= 0;
946 l
= strlen (hstring
);
948 /* Grovel the string. Only backslash and single quotes can quote the
949 history escape character. We also handle arg specifiers. */
951 /* Before we grovel forever, see if the history_expansion_char appears
952 anywhere within the text. */
954 /* The quick substitution character is a history expansion all right. That
955 is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
956 that is the substitution that we do. */
957 if (hstring
[0] == history_subst_char
)
959 string
= (char *)xmalloc (l
+ 5);
961 string
[0] = string
[1] = history_expansion_char
;
964 strcpy (string
+ 4, hstring
);
969 #if defined (HANDLE_MULTIBYTE)
970 memset (&ps
, 0, sizeof (mbstate_t));
974 /* If not quick substitution, still maybe have to do expansion. */
976 /* `!' followed by one of the characters in history_no_expand_chars
977 is NOT an expansion. */
978 for (i
= dquote
= squote
= 0; string
[i
]; i
++)
980 #if defined (HANDLE_MULTIBYTE)
981 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
984 v
= _rl_get_char_len (string
+ i
, &ps
);
991 #endif /* HANDLE_MULTIBYTE */
994 /* The history_comment_char, if set, appearing at the beginning
995 of a word signifies that the rest of the line should not have
996 history expansion performed on it.
997 Skip the rest of the line and break out of the loop. */
998 if (history_comment_char
&& string
[i
] == history_comment_char
&&
1000 (i
== 0 || member (string
[i
- 1], history_word_delimiters
)))
1006 else if (string
[i
] == history_expansion_char
)
1008 if (cc
== 0 || member (cc
, history_no_expand_chars
))
1010 /* DQUOTE won't be set unless history_quotes_inhibit_expansion
1011 is set. The idea here is to treat double-quoted strings the
1012 same as the word outside double quotes; in effect making the
1013 double quote part of history_no_expand_chars when DQUOTE is
1015 else if (dquote
&& cc
== '"')
1017 /* If the calling application has set
1018 history_inhibit_expansion_function to a function that checks
1019 for special cases that should not be history expanded,
1020 call the function and skip the expansion if it returns a
1022 else if (history_inhibit_expansion_function
&&
1023 (*history_inhibit_expansion_function
) (string
, i
))
1028 /* Shell-like quoting: allow backslashes to quote double quotes
1029 inside a double-quoted string. */
1030 else if (dquote
&& string
[i
] == '\\' && cc
== '"')
1032 /* More shell-like quoting: if we're paying attention to single
1033 quotes and letting them quote the history expansion character,
1034 then we need to pay attention to double quotes, because single
1035 quotes are not special inside double-quoted strings. */
1036 else if (history_quotes_inhibit_expansion
&& string
[i
] == '"')
1038 dquote
= 1 - dquote
;
1040 else if (dquote
== 0 && history_quotes_inhibit_expansion
&& string
[i
] == '\'')
1042 /* If this is bash, single quotes inhibit history expansion. */
1043 flag
= (i
> 0 && string
[i
- 1] == '$');
1045 hist_string_extract_single_quoted (string
, &i
, flag
);
1047 else if (history_quotes_inhibit_expansion
&& string
[i
] == '\\')
1049 /* If this is bash, allow backslashes to quote single
1050 quotes and the history expansion character. */
1051 if (cc
== '\'' || cc
== history_expansion_char
)
1057 if (string
[i
] != history_expansion_char
)
1060 *output
= savestring (string
);
1065 /* Extract and perform the substitution. */
1066 for (passc
= dquote
= squote
= i
= j
= 0; i
< l
; i
++)
1068 int qc
, tchar
= string
[i
];
1077 #if defined (HANDLE_MULTIBYTE)
1078 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1083 memset (mb
, 0, sizeof (mb
));
1084 for (k
= 0; k
< MB_LEN_MAX
; k
++)
1087 memset (&ps
, 0, sizeof (mbstate_t));
1088 if (_rl_get_char_len (mb
, &ps
) == -2)
1093 if (strlen (mb
) > 1)
1099 #endif /* HANDLE_MULTIBYTE */
1101 if (tchar
== history_expansion_char
)
1103 else if (tchar
== history_comment_char
)
1109 ADD_CHAR (string
[i
]);
1118 dquote
= 1 - dquote
;
1124 /* If history_quotes_inhibit_expansion is set, single quotes
1125 inhibit history expansion, otherwise they are treated like
1132 else if (dquote
== 0 && history_quotes_inhibit_expansion
)
1136 flag
= (i
> 0 && string
[i
- 1] == '$');
1138 hist_string_extract_single_quoted (string
, &i
, flag
);
1140 slen
= i
- quote
+ 2;
1141 temp
= (char *)xmalloc (slen
);
1142 strncpy (temp
, string
+ quote
, slen
);
1143 temp
[slen
- 1] = '\0';
1147 else if (dquote
== 0 && squote
== 0 && history_quotes_inhibit_expansion
== 0)
1150 ADD_CHAR (string
[i
]);
1153 ADD_CHAR (string
[i
]);
1157 case -2: /* history_comment_char */
1158 if ((dquote
== 0 || history_quotes_inhibit_expansion
== 0) &&
1159 (i
== 0 || member (string
[i
- 1], history_word_delimiters
)))
1161 temp
= (char *)xmalloc (l
- i
+ 1);
1162 strcpy (temp
, string
+ i
);
1168 ADD_CHAR (string
[i
]);
1171 case -3: /* history_expansion_char */
1174 /* If the history_expansion_char is followed by one of the
1175 characters in history_no_expand_chars, then it is not a
1176 candidate for expansion of any kind. */
1177 if (cc
== 0 || member (cc
, history_no_expand_chars
) ||
1178 (dquote
&& cc
== '"') ||
1179 (history_inhibit_expansion_function
&& (*history_inhibit_expansion_function
) (string
, i
)))
1181 ADD_CHAR (string
[i
]);
1185 #if defined (NO_BANG_HASH_MODIFIERS)
1186 /* There is something that is listed as a `word specifier' in csh
1187 documentation which means `the expanded text to this point'.
1188 That is not a word specifier, it is an event specifier. If we
1189 don't want to allow modifiers with `!#', just stick the current
1190 output line in again. */
1195 temp
= (char *)xmalloc (1 + strlen (result
));
1196 strcpy (temp
, result
);
1204 qc
= squote
? '\'' : (dquote
? '"' : 0);
1205 r
= history_expand_internal (string
, i
, qc
, &eindex
, &temp
, result
);
1210 if (string
!= hstring
)
1223 only_printing
= r
== 1;
1231 if (string
!= hstring
)
1237 add_history (result
);
1242 return (modified
!= 0);
1245 /* Return a consed string which is the word specified in SPEC, and found
1246 in FROM. NULL is returned if there is no spec. The address of
1247 ERROR_POINTER is returned if the word specified cannot be found.
1248 CALLER_INDEX is the offset in SPEC to start looking; it is updated
1249 to point to just after the last character parsed. */
1251 get_history_word_specifier (spec
, from
, caller_index
)
1255 register int i
= *caller_index
;
1257 int expecting_word_spec
= 0;
1260 /* The range of words to return doesn't exist yet. */
1262 result
= (char *)NULL
;
1264 /* If we found a colon, then this *must* be a word specification. If
1265 it isn't, then it is an error. */
1269 expecting_word_spec
++;
1272 /* Handle special cases first. */
1274 /* `%' is the word last searched for. */
1277 *caller_index
= i
+ 1;
1278 return (search_match
? savestring (search_match
) : savestring (""));
1281 /* `*' matches all of the arguments, but not the command. */
1284 *caller_index
= i
+ 1;
1285 result
= history_arg_extract (1, '$', from
);
1286 return (result
? result
: savestring (""));
1289 /* `$' is last arg. */
1292 *caller_index
= i
+ 1;
1293 return (history_arg_extract ('$', '$', from
));
1296 /* Try to get FIRST and LAST figured out. */
1300 else if (spec
[i
] == '^')
1305 else if (_rl_digit_p (spec
[i
]) && expecting_word_spec
)
1307 for (first
= 0; _rl_digit_p (spec
[i
]); i
++)
1308 first
= (first
* 10) + _rl_digit_value (spec
[i
]);
1311 return ((char *)NULL
); /* no valid `first' for word specifier */
1313 if (spec
[i
] == '^' || spec
[i
] == '*')
1315 last
= (spec
[i
] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
1318 else if (spec
[i
] != '-')
1324 if (_rl_digit_p (spec
[i
]))
1326 for (last
= 0; _rl_digit_p (spec
[i
]); i
++)
1327 last
= (last
* 10) + _rl_digit_value (spec
[i
]);
1329 else if (spec
[i
] == '$')
1335 else if (!spec
[i
] || spec
[i
] == ':')
1336 /* check against `:' because there could be a modifier separator */
1339 /* csh seems to allow anything to terminate the word spec here,
1340 leaving it as an abbreviation. */
1342 last
= -1; /* x- abbreviates x-$ omitting word `$' */
1347 if (last
>= first
|| last
== '$' || last
< 0)
1348 result
= history_arg_extract (first
, last
, from
);
1350 return (result
? result
: (char *)&error_pointer
);
1353 /* Extract the args specified, starting at FIRST, and ending at LAST.
1354 The args are taken from STRING. If either FIRST or LAST is < 0,
1355 then make that arg count from the right (subtract from the number of
1356 tokens, so that FIRST = -1 means the next to last token on the line).
1357 If LAST is `$' the last arg from STRING is used. */
1359 history_arg_extract (first
, last
, string
)
1363 register int i
, len
;
1368 /* XXX - think about making history_tokenize return a struct array,
1369 each struct in array being a string and a length to avoid the
1370 calls to strlen below. */
1371 if ((list
= history_tokenize (string
)) == NULL
)
1372 return ((char *)NULL
);
1374 for (len
= 0; list
[len
]; len
++)
1378 last
= len
+ last
- 1;
1381 first
= len
+ first
- 1;
1391 if (first
>= len
|| last
> len
|| first
< 0 || last
< 0 || first
> last
)
1392 result
= ((char *)NULL
);
1395 for (size
= 0, i
= first
; i
< last
; i
++)
1396 size
+= strlen (list
[i
]) + 1;
1397 result
= (char *)xmalloc (size
+ 1);
1400 for (i
= first
, offset
= 0; i
< last
; i
++)
1402 strcpy (result
+ offset
, list
[i
]);
1403 offset
+= strlen (list
[i
]);
1406 result
[offset
++] = ' ';
1412 for (i
= 0; i
< len
; i
++)
1420 history_tokenize_word (string
, ind
)
1425 int delimiter
, nestdelim
, delimopen
;
1428 delimiter
= nestdelim
= 0;
1430 if (member (string
[i
], "()\n"))
1436 if (member (string
[i
], "<>;&|$"))
1438 int peek
= string
[i
+ 1];
1440 if (peek
== string
[i
] && peek
!= '$')
1442 if (peek
== '<' && string
[i
+ 2] == '-')
1444 else if (peek
== '<' && string
[i
+ 2] == '<')
1449 else if ((peek
== '&' && (string
[i
] == '>' || string
[i
] == '<')) ||
1450 (peek
== '>' && string
[i
] == '&'))
1455 /* XXX - separated out for later -- bash-4.2 */
1456 else if ((peek
== '(' && (string
[i
] == '>' || string
[i
] == '<')) || /* ) */
1457 (peek
== '(' && string
[i
] == '$')) /*)*/
1466 else if (peek
== '\'' && string
[i
] == '$')
1473 if (string
[i
] != '$')
1480 /* same code also used for $(...)/<(...)/>(...) above */
1481 if (member (string
[i
], "!@?+*"))
1483 int peek
= string
[i
+ 1];
1485 if (peek
== '(') /*)*/
1487 /* Shell extended globbing patterns */
1490 delimiter
= ')'; /* XXX - not perfect */
1496 /* Get word from string + i; */
1498 if (delimiter
== 0 && member (string
[i
], HISTORY_QUOTE_CHARACTERS
))
1499 delimiter
= string
[i
++];
1501 for (; string
[i
]; i
++)
1503 if (string
[i
] == '\\' && string
[i
+ 1] == '\n')
1509 if (string
[i
] == '\\' && delimiter
!= '\'' &&
1510 (delimiter
!= '"' || member (string
[i
], slashify_in_quotes
)))
1516 /* delimiter must be set and set to something other than a quote if
1517 nestdelim is set, so these tests are safe. */
1518 if (nestdelim
&& string
[i
] == delimopen
)
1523 if (nestdelim
&& string
[i
] == delimiter
)
1531 if (delimiter
&& string
[i
] == delimiter
)
1537 if (delimiter
== 0 && (member (string
[i
], history_word_delimiters
)))
1540 if (delimiter
== 0 && member (string
[i
], HISTORY_QUOTE_CHARACTERS
))
1541 delimiter
= string
[i
];
1548 history_substring (string
, start
, end
)
1553 register char *result
;
1556 result
= (char *)xmalloc (len
+ 1);
1557 strncpy (result
, string
+ start
, len
);
1562 /* Parse STRING into tokens and return an array of strings. If WIND is
1563 not -1 and INDP is not null, we also want the word surrounding index
1564 WIND. The position in the returned array of strings is returned in
1567 history_tokenize_internal (string
, wind
, indp
)
1572 register int i
, start
, result_index
, size
;
1574 /* If we're searching for a string that's not part of a word (e.g., " "),
1575 make sure we set *INDP to a reasonable value. */
1576 if (indp
&& wind
!= -1)
1579 /* Get a token, and stuff it into RESULT. The tokens are split
1580 exactly where the shell would split them. */
1581 for (i
= result_index
= size
= 0, result
= (char **)NULL
; string
[i
]; )
1583 /* Skip leading whitespace. */
1584 for (; string
[i
] && whitespace (string
[i
]); i
++)
1586 if (string
[i
] == 0 || string
[i
] == history_comment_char
)
1591 i
= history_tokenize_word (string
, start
);
1593 /* If we have a non-whitespace delimiter character (which would not be
1594 skipped by the loop above), use it and any adjacent delimiters to
1595 make a separate field. Any adjacent white space will be skipped the
1596 next time through the loop. */
1597 if (i
== start
&& history_word_delimiters
)
1600 while (string
[i
] && member (string
[i
], history_word_delimiters
))
1604 /* If we are looking for the word in which the character at a
1605 particular index falls, remember it. */
1606 if (indp
&& wind
!= -1 && wind
>= start
&& wind
< i
)
1607 *indp
= result_index
;
1609 if (result_index
+ 2 >= size
)
1610 result
= (char **)xrealloc (result
, ((size
+= 10) * sizeof (char *)));
1612 result
[result_index
++] = history_substring (string
, start
, i
);
1613 result
[result_index
] = (char *)NULL
;
1619 /* Return an array of tokens, much as the shell might. The tokens are
1620 parsed out of STRING. */
1622 history_tokenize (string
)
1625 return (history_tokenize_internal (string
, -1, (int *)NULL
));
1628 /* Free members of WORDS from START to an empty string */
1630 freewords (words
, start
)
1636 for (i
= start
; words
[i
]; i
++)
1640 /* Find and return the word which contains the character at index IND
1641 in the history line LINE. Used to save the word matched by the
1642 last history !?string? search. */
1644 history_find_word (line
, ind
)
1651 words
= history_tokenize_internal (line
, ind
, &wind
);
1652 if (wind
== -1 || words
== 0)
1655 freewords (words
, 0);
1657 return ((char *)NULL
);
1660 for (i
= 0; i
< wind
; i
++)
1662 freewords (words
, wind
+ 1);