1 /* histexpand.c -- history expansion. */
3 /* Copyright (C) 1989-2018 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>
52 #define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
53 #define HISTORY_QUOTE_CHARACTERS "\"'`"
54 #define HISTORY_EVENT_DELIMITERS "^$*%-"
56 #define slashify_in_quotes "\\`\"$"
58 #define fielddelim(c) (whitespace(c) || (c) == '\n')
60 typedef int _hist_search_func_t
PARAMS((const char *, int));
62 static char error_pointer
;
64 static char *subst_lhs
;
65 static char *subst_rhs
;
66 static int subst_lhs_len
;
67 static int subst_rhs_len
;
69 /* Characters that delimit history event specifications and separate event
70 specifications from word designators. Static for now */
71 static char *history_event_delimiter_chars
= HISTORY_EVENT_DELIMITERS
;
73 static char *get_history_word_specifier
PARAMS((char *, char *, int *));
74 static int history_tokenize_word
PARAMS((const char *, int));
75 static char **history_tokenize_internal
PARAMS((const char *, int, int *));
76 static char *history_substring
PARAMS((const char *, int, int));
77 static void freewords
PARAMS((char **, int));
78 static char *history_find_word
PARAMS((char *, int));
80 static char *quote_breaks
PARAMS((char *));
82 /* Variables exported by this file. */
83 /* The character that represents the start of a history expansion
84 request. This is usually `!'. */
85 char history_expansion_char
= '!';
87 /* The character that invokes word substitution if found at the start of
88 a line. This is usually `^'. */
89 char history_subst_char
= '^';
91 /* During tokenization, if this character is seen as the first character
92 of a word, then it, and all subsequent characters upto a newline are
93 ignored. For a Bourne shell, this should be '#'. Bash special cases
94 the interactive comment character to not be a comment delimiter. */
95 char history_comment_char
= '\0';
97 /* The list of characters which inhibit the expansion of text if found
98 immediately following history_expansion_char. */
99 char *history_no_expand_chars
= " \t\n\r=";
101 /* If set to a non-zero value, single quotes inhibit history expansion.
103 int history_quotes_inhibit_expansion
= 0;
105 /* Used to split words by history_tokenize_internal. */
106 char *history_word_delimiters
= HISTORY_WORD_DELIMITERS
;
108 /* If set, this points to a function that is called to verify that a
109 particular history expansion should be performed. */
110 rl_linebuf_func_t
*history_inhibit_expansion_function
;
112 int history_quoting_state
= 0;
114 /* **************************************************************** */
116 /* History Expansion */
118 /* **************************************************************** */
120 /* Hairy history expansion on text, not tokens. This is of general
121 use, and thus belongs in this library. */
123 /* The last string searched for by a !?string? search. */
124 static char *search_string
;
125 /* The last string matched by a !?string? search. */
126 static char *search_match
;
128 /* Return the event specified at TEXT + OFFSET modifying OFFSET to
129 point to after the event specifier. Just a pointer to the history
130 line is returned; NULL is returned in the event of a bad specifier.
131 You pass STRING with *INDEX equal to the history_expansion_char that
132 begins this specification.
133 DELIMITING_QUOTE is a character that is allowed to end the string
134 specification for what to search for in addition to the normal
135 characters `:', ` ', `\t', `\n', and sometimes `?'.
136 So you might call this function like:
137 line = get_history_event ("!echo:p", &index, 0); */
139 get_history_event (const char *string
, int *caller_index
, int delimiting_quote
)
144 int which
, sign
, local_index
, substring_okay
;
145 _hist_search_func_t
*search_func
;
148 /* The event can be specified in a number of ways.
150 !! the previous command
152 !-n current command-line minus N
153 !str the most recent command starting with STR
155 the most recent command containing STR
157 All values N are determined via HISTORY_BASE. */
161 if (string
[i
] != history_expansion_char
)
162 return ((char *)NULL
);
164 /* Move on to the specification. */
170 #define RETURN_ENTRY(e, w) \
171 return ((e = history_get (w)) ? e->line : (char *)NULL)
173 /* Handle !! case. */
174 if (string
[i
] == history_expansion_char
)
177 which
= history_base
+ (history_length
- 1);
179 RETURN_ENTRY (entry
, which
);
182 /* Hack case of numeric line specification. */
183 if (string
[i
] == '-')
189 if (_rl_digit_p (string
[i
]))
191 /* Get the extent of the digits and compute the value. */
192 for (which
= 0; _rl_digit_p (string
[i
]); i
++)
193 which
= (which
* 10) + _rl_digit_value (string
[i
]);
198 which
= (history_length
+ history_base
) - which
;
200 RETURN_ENTRY (entry
, which
);
203 /* This must be something to search for. If the spec begins with
204 a '?', then the string may be anywhere on the line. Otherwise,
205 the string must be found at the start of a line. */
206 if (string
[i
] == '?')
212 /* Only a closing `?' or a newline delimit a substring search string. */
213 for (local_index
= i
; c
= string
[i
]; i
++)
215 #if defined (HANDLE_MULTIBYTE)
216 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
221 memset (&ps
, 0, sizeof (mbstate_t));
222 /* These produce warnings because we're passing a const string to a
223 function that takes a non-const string. */
224 _rl_adjust_point ((char *)string
, i
, &ps
);
225 if ((v
= _rl_get_char_len ((char *)string
+ i
, &ps
)) > 1)
232 #endif /* HANDLE_MULTIBYTE */
233 if ((!substring_okay
&& (whitespace (c
) || c
== ':' ||
234 (history_event_delimiter_chars
&& member (c
, history_event_delimiter_chars
)) ||
235 (history_search_delimiter_chars
&& member (c
, history_search_delimiter_chars
)) ||
236 string
[i
] == delimiting_quote
)) ||
238 (substring_okay
&& string
[i
] == '?'))
242 which
= i
- local_index
;
243 temp
= (char *)xmalloc (1 + which
);
245 strncpy (temp
, string
+ local_index
, which
);
248 if (substring_okay
&& string
[i
] == '?')
253 #define FAIL_SEARCH() \
255 history_offset = history_length; xfree (temp) ; return (char *)NULL; \
258 /* If there is no search string, try to use the previous search string,
259 if one exists. If not, fail immediately. */
260 if (*temp
== '\0' && substring_okay
)
265 temp
= savestring (search_string
);
271 search_func
= substring_okay
? history_search
: history_search_prefix
;
274 local_index
= (*search_func
) (temp
, -1);
279 if (local_index
== 0 || substring_okay
)
281 entry
= current_history ();
284 history_offset
= history_length
;
286 /* If this was a substring search, then remember the
287 string that we matched for word substitution. */
290 FREE (search_string
);
291 search_string
= temp
;
294 search_match
= history_find_word (entry
->line
, local_index
);
299 return (entry
->line
);
311 /* Function for extracting single-quoted strings. Used for inhibiting
312 history expansion within single quotes. */
314 /* Extract the contents of STRING as if it is enclosed in single quotes.
315 SINDEX, when passed in, is the offset of the character immediately
316 following the opening single quote; on exit, SINDEX is left pointing
317 to the closing single quote. FLAGS currently used to allow backslash
318 to escape a single quote (e.g., for bash $'...'). */
320 hist_string_extract_single_quoted (char *string
, int *sindex
, int flags
)
324 for (i
= *sindex
; string
[i
] && string
[i
] != '\''; i
++)
326 if ((flags
& 1) && string
[i
] == '\\' && string
[i
+1])
334 quote_breaks (char *s
)
336 register char *p
, *r
;
340 for (p
= s
; p
&& *p
; p
++, len
++)
344 else if (whitespace (*p
) || *p
== '\n')
348 r
= ret
= (char *)xmalloc (len
);
350 for (p
= s
; p
&& *p
; )
360 else if (whitespace (*p
) || *p
== '\n')
375 hist_error(char *s
, int start
, int current
, int errtype
)
381 ll
= current
- start
;
385 case EVENT_NOT_FOUND
:
386 emsg
= "event not found";
390 emsg
= "bad word specifier";
394 emsg
= "substitution failed";
398 emsg
= "unrecognized history modifier";
402 emsg
= "no previous substitution";
406 emsg
= "unknown expansion error";
411 temp
= (char *)xmalloc (ll
+ elen
+ 3);
412 strncpy (temp
, s
+ start
, ll
);
415 strcpy (temp
+ ll
+ 2, emsg
);
419 /* Get a history substitution string from STR starting at *IPTR
420 and return it. The length is returned in LENPTR.
422 A backslash can quote the delimiter. If the string is the
423 empty string, the previous pattern is used. If there is
424 no previous pattern for the lhs, the last history search
427 If IS_RHS is 1, we ignore empty strings and set the pattern
428 to "" anyway. subst_lhs is not changed if the lhs is empty;
429 subst_rhs is allowed to be set to the empty string. */
432 get_subst_pattern (char *str
, int *iptr
, int delimiter
, int is_rhs
, int *lenptr
)
434 register int si
, i
, j
, k
;
436 #if defined (HANDLE_MULTIBYTE)
443 #if defined (HANDLE_MULTIBYTE)
444 memset (&ps
, 0, sizeof (mbstate_t));
445 _rl_adjust_point (str
, i
, &ps
);
448 for (si
= i
; str
[si
] && str
[si
] != delimiter
; si
++)
449 #if defined (HANDLE_MULTIBYTE)
450 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
453 if ((v
= _rl_get_char_len (str
+ si
, &ps
)) > 1)
455 else if (str
[si
] == '\\' && str
[si
+ 1] == delimiter
)
459 #endif /* HANDLE_MULTIBYTE */
460 if (str
[si
] == '\\' && str
[si
+ 1] == delimiter
)
463 if (si
> i
|| is_rhs
)
465 s
= (char *)xmalloc (si
- i
+ 1);
466 for (j
= 0, k
= i
; k
< si
; j
++, k
++)
468 /* Remove a backslash quoting the search string delimiter. */
469 if (str
[k
] == '\\' && str
[k
+ 1] == delimiter
)
487 postproc_subst_rhs (void)
492 new = (char *)xmalloc (new_size
= subst_rhs_len
+ subst_lhs_len
);
493 for (i
= j
= 0; i
< subst_rhs_len
; i
++)
495 if (subst_rhs
[i
] == '&')
497 if (j
+ subst_lhs_len
>= new_size
)
498 new = (char *)xrealloc (new, (new_size
= new_size
* 2 + subst_lhs_len
));
499 strcpy (new + j
, subst_lhs
);
504 /* a single backslash protects the `&' from lhs interpolation */
505 if (subst_rhs
[i
] == '\\' && subst_rhs
[i
+ 1] == '&')
508 new = (char *)xrealloc (new, new_size
*= 2);
509 new[j
++] = subst_rhs
[i
];
518 /* Expand the bulk of a history specifier starting at STRING[START].
519 Returns 0 if everything is OK, -1 if an error occurred, and 1
520 if the `p' modifier was supplied and the caller should just print
521 the returned string. Returns the new index into string in
522 *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
523 /* need current line for !# */
525 history_expand_internal (char *string
, int start
, int qc
, int *end_index_ptr
, char **ret_string
, char *current_line
)
527 int i
, n
, starting_index
;
528 int substitute_globally
, subst_bywords
, want_quotes
, print_only
;
529 char *event
, *temp
, *result
, *tstr
, *t
, c
, *word_spec
;
531 #if defined (HANDLE_MULTIBYTE)
534 memset (&ps
, 0, sizeof (mbstate_t));
537 result
= (char *)xmalloc (result_len
= 128);
541 /* If it is followed by something that starts a word specifier,
542 then !! is implied as the event specifier. */
544 if (member (string
[i
+ 1], ":$*%^"))
549 fake_s
[0] = fake_s
[1] = history_expansion_char
;
551 event
= get_history_event (fake_s
, &fake_i
, 0);
553 else if (string
[i
+ 1] == '#')
556 event
= current_line
;
559 event
= get_history_event (string
, &i
, qc
);
563 *ret_string
= hist_error (string
, start
, i
, EVENT_NOT_FOUND
);
568 /* If a word specifier is found, then do what that requires. */
570 word_spec
= get_history_word_specifier (string
, event
, &i
);
572 /* There is no such thing as a `malformed word specifier'. However,
573 it is possible for a specifier that has no match. In that case,
575 if (word_spec
== (char *)&error_pointer
)
577 *ret_string
= hist_error (string
, starting_index
, i
, BAD_WORD_SPEC
);
582 /* If no word specifier, than the thing of interest was the event. */
583 temp
= word_spec
? savestring (word_spec
) : savestring (event
);
586 /* Perhaps there are other modifiers involved. Do what they say. */
587 want_quotes
= substitute_globally
= subst_bywords
= print_only
= 0;
590 while (string
[i
] == ':')
594 if (c
== 'g' || c
== 'a')
596 substitute_globally
= 1;
610 *ret_string
= hist_error (string
, i
+1, i
+2, BAD_MODIFIER
);
623 /* :p means make this the last executed line. So we
624 return an error state after adding this line to the
630 /* :t discards all but the last part of the pathname. */
632 tstr
= strrchr (temp
, '/');
636 t
= savestring (tstr
);
642 /* :h discards the last part of a pathname. */
644 tstr
= strrchr (temp
, '/');
649 /* :r discards the suffix. */
651 tstr
= strrchr (temp
, '.');
656 /* :e discards everything but the suffix. */
658 tstr
= strrchr (temp
, '.');
661 t
= savestring (tstr
);
667 /* :s/this/that substitutes `that' for the first
668 occurrence of `this'. :gs/this/that substitutes `that'
669 for each occurrence of `this'. :& repeats the last
670 substitution. :g& repeats the last substitution
677 int delimiter
, failed
, si
, l_temp
, ws
, we
;
681 if (i
+ 2 < (int)strlen (string
))
683 #if defined (HANDLE_MULTIBYTE)
684 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
686 _rl_adjust_point (string
, i
+ 2, &ps
);
687 if (_rl_get_char_len (string
+ i
+ 2, &ps
) > 1)
690 delimiter
= string
[i
+ 2];
693 #endif /* HANDLE_MULTIBYTE */
694 delimiter
= string
[i
+ 2];
697 break; /* no search delimiter */
701 t
= get_subst_pattern (string
, &i
, delimiter
, 0, &subst_lhs_len
);
702 /* An empty substitution lhs with no previous substitution
703 uses the last search string as the lhs. */
711 if (search_string
&& *search_string
)
713 subst_lhs
= savestring (search_string
);
714 subst_lhs_len
= strlen (subst_lhs
);
718 subst_lhs
= (char *) NULL
;
724 subst_rhs
= get_subst_pattern (string
, &i
, delimiter
, 1, &subst_rhs_len
);
726 /* If `&' appears in the rhs, it's supposed to be replaced
728 if (member ('&', subst_rhs
))
729 postproc_subst_rhs ();
734 /* If there is no lhs, the substitution can't succeed. */
735 if (subst_lhs_len
== 0)
737 *ret_string
= hist_error (string
, starting_index
, i
, NO_PREV_SUBST
);
743 l_temp
= strlen (temp
);
744 /* Ignore impossible cases. */
745 if (subst_lhs_len
> l_temp
)
747 *ret_string
= hist_error (string
, starting_index
, i
, SUBST_FAILED
);
753 /* Find the first occurrence of THIS in TEMP. */
754 /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
757 1. substitute_globally == subst_bywords == 0
758 2. substitute_globally == 1 && subst_bywords == 0
759 3. substitute_globally == 0 && subst_bywords == 1
761 In the first case, we substitute for the first occurrence only.
762 In the second case, we substitute for every occurrence.
763 In the third case, we tokenize into words and substitute the
764 first occurrence of each word. */
767 for (failed
= 1; (si
+ subst_lhs_len
) <= l_temp
; si
++)
769 /* First skip whitespace and find word boundaries if
770 we're past the end of the word boundary we found
772 if (subst_bywords
&& si
> we
)
774 for (; temp
[si
] && fielddelim (temp
[si
]); si
++)
777 we
= history_tokenize_word (temp
, si
);
780 if (STREQN (temp
+si
, subst_lhs
, subst_lhs_len
))
782 int len
= subst_rhs_len
- subst_lhs_len
+ l_temp
;
783 new_event
= (char *)xmalloc (1 + len
);
784 strncpy (new_event
, temp
, si
);
785 strncpy (new_event
+ si
, subst_rhs
, subst_rhs_len
);
786 strncpy (new_event
+ si
+ subst_rhs_len
,
787 temp
+ si
+ subst_lhs_len
,
788 l_temp
- (si
+ subst_lhs_len
));
789 new_event
[len
] = '\0';
795 if (substitute_globally
)
797 /* Reported to fix a bug that causes it to skip every
798 other match when matching a single character. Was
799 si += subst_rhs_len previously. */
800 si
+= subst_rhs_len
- 1;
801 l_temp
= strlen (temp
);
802 substitute_globally
++;
805 else if (subst_bywords
)
808 l_temp
= strlen (temp
);
816 if (substitute_globally
> 1)
818 substitute_globally
= 0;
819 continue; /* don't want to increment i */
823 continue; /* don't want to increment i */
825 *ret_string
= hist_error (string
, starting_index
, i
, SUBST_FAILED
);
833 /* Done with modifiers. */
834 /* Believe it or not, we have to back the pointer up by one. */
841 if (want_quotes
== 'q')
842 x
= sh_single_quote (temp
);
843 else if (want_quotes
== 'x')
844 x
= quote_breaks (temp
);
846 x
= savestring (temp
);
854 result
= (char *)xrealloc (result
, n
+ 2);
855 strcpy (result
, temp
);
859 *ret_string
= result
;
863 /* Expand the string STRING, placing the result into OUTPUT, a pointer
864 to a string. Returns:
866 -1) If there was an error in expansion.
867 0) If no expansions took place (or, if the only change in
868 the text was the de-slashifying of the history expansion
870 1) If expansions did take place
871 2) If the `p' modifier was given and the caller should print the result
873 If an error occurred in expansion, then OUTPUT contains a descriptive
876 #define ADD_STRING(s) \
879 int sl = strlen (s); \
881 if (j >= result_len) \
883 while (j >= result_len) \
885 result = (char *)xrealloc (result, result_len); \
887 strcpy (result + j - sl, s); \
891 #define ADD_CHAR(c) \
894 if (j >= result_len - 1) \
895 result = (char *)xrealloc (result, result_len += 64); \
902 history_expand (char *hstring
, char **output
)
905 int i
, r
, l
, passc
, cc
, modified
, eindex
, only_printing
, dquote
, squote
, flag
;
908 /* The output string, and its length. */
912 #if defined (HANDLE_MULTIBYTE)
917 /* Used when adding the string. */
923 /* Setting the history expansion character to 0 inhibits all
924 history expansion. */
925 if (history_expansion_char
== 0)
927 *output
= savestring (hstring
);
931 /* Prepare the buffer for printing error messages. */
932 result
= (char *)xmalloc (result_len
= 256);
935 only_printing
= modified
= 0;
936 l
= strlen (hstring
);
938 /* Grovel the string. Only backslash and single quotes can quote the
939 history escape character. We also handle arg specifiers. */
941 /* Before we grovel forever, see if the history_expansion_char appears
942 anywhere within the text. */
944 /* The quick substitution character is a history expansion all right. That
945 is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
946 that is the substitution that we do. */
947 if (hstring
[0] == history_subst_char
)
949 string
= (char *)xmalloc (l
+ 5);
951 string
[0] = string
[1] = history_expansion_char
;
954 strcpy (string
+ 4, hstring
);
959 #if defined (HANDLE_MULTIBYTE)
960 memset (&ps
, 0, sizeof (mbstate_t));
964 /* If not quick substitution, still maybe have to do expansion. */
966 /* `!' followed by one of the characters in history_no_expand_chars
967 is NOT an expansion. */
968 dquote
= history_quoting_state
== '"';
969 squote
= history_quoting_state
== '\'';
971 /* If the calling application tells us we are already reading a
972 single-quoted string, consume the rest of the string right now
975 if (squote
&& history_quotes_inhibit_expansion
)
977 hist_string_extract_single_quoted (string
, &i
, 0);
983 for ( ; string
[i
]; i
++)
985 #if defined (HANDLE_MULTIBYTE)
986 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
989 v
= _rl_get_char_len (string
+ i
, &ps
);
996 #endif /* HANDLE_MULTIBYTE */
999 /* The history_comment_char, if set, appearing at the beginning
1000 of a word signifies that the rest of the line should not have
1001 history expansion performed on it.
1002 Skip the rest of the line and break out of the loop. */
1003 if (history_comment_char
&& string
[i
] == history_comment_char
&&
1005 (i
== 0 || member (string
[i
- 1], history_word_delimiters
)))
1011 else if (string
[i
] == history_expansion_char
)
1013 if (cc
== 0 || member (cc
, history_no_expand_chars
))
1015 /* DQUOTE won't be set unless history_quotes_inhibit_expansion
1016 is set. The idea here is to treat double-quoted strings the
1017 same as the word outside double quotes; in effect making the
1018 double quote part of history_no_expand_chars when DQUOTE is
1020 else if (dquote
&& cc
== '"')
1022 /* If the calling application has set
1023 history_inhibit_expansion_function to a function that checks
1024 for special cases that should not be history expanded,
1025 call the function and skip the expansion if it returns a
1027 else if (history_inhibit_expansion_function
&&
1028 (*history_inhibit_expansion_function
) (string
, i
))
1033 /* Shell-like quoting: allow backslashes to quote double quotes
1034 inside a double-quoted string. */
1035 else if (dquote
&& string
[i
] == '\\' && cc
== '"')
1037 /* More shell-like quoting: if we're paying attention to single
1038 quotes and letting them quote the history expansion character,
1039 then we need to pay attention to double quotes, because single
1040 quotes are not special inside double-quoted strings. */
1041 else if (history_quotes_inhibit_expansion
&& string
[i
] == '"')
1043 dquote
= 1 - dquote
;
1045 else if (dquote
== 0 && history_quotes_inhibit_expansion
&& string
[i
] == '\'')
1047 /* If this is bash, single quotes inhibit history expansion. */
1048 flag
= (i
> 0 && string
[i
- 1] == '$');
1050 hist_string_extract_single_quoted (string
, &i
, flag
);
1052 else if (history_quotes_inhibit_expansion
&& string
[i
] == '\\')
1054 /* If this is bash, allow backslashes to quote single
1055 quotes and the history expansion character. */
1056 if (cc
== '\'' || cc
== history_expansion_char
)
1062 if (string
[i
] != history_expansion_char
)
1065 *output
= savestring (string
);
1070 /* Extract and perform the substitution. */
1071 dquote
= history_quoting_state
== '"';
1072 squote
= history_quoting_state
== '\'';
1074 /* If the calling application tells us we are already reading a
1075 single-quoted string, consume the rest of the string right now
1078 if (squote
&& history_quotes_inhibit_expansion
)
1082 hist_string_extract_single_quoted (string
, &i
, 0);
1084 for (c
= 0; c
< i
; c
++)
1085 ADD_CHAR (string
[c
]);
1088 ADD_CHAR (string
[i
]);
1093 for (passc
= 0; i
< l
; i
++)
1095 int qc
, tchar
= string
[i
];
1104 #if defined (HANDLE_MULTIBYTE)
1105 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1110 memset (mb
, 0, sizeof (mb
));
1111 for (k
= 0; k
< MB_LEN_MAX
; k
++)
1114 memset (&ps
, 0, sizeof (mbstate_t));
1115 if (_rl_get_char_len (mb
, &ps
) == -2)
1120 if (strlen (mb
) > 1)
1126 #endif /* HANDLE_MULTIBYTE */
1128 if (tchar
== history_expansion_char
)
1130 else if (tchar
== history_comment_char
)
1136 ADD_CHAR (string
[i
]);
1145 dquote
= 1 - dquote
;
1151 /* If history_quotes_inhibit_expansion is set, single quotes
1152 inhibit history expansion, otherwise they are treated like
1159 else if (dquote
== 0 && history_quotes_inhibit_expansion
)
1163 flag
= (i
> 0 && string
[i
- 1] == '$');
1165 hist_string_extract_single_quoted (string
, &i
, flag
);
1167 slen
= i
- quote
+ 2;
1168 temp
= (char *)xmalloc (slen
);
1169 strncpy (temp
, string
+ quote
, slen
);
1170 temp
[slen
- 1] = '\0';
1174 else if (dquote
== 0 && squote
== 0 && history_quotes_inhibit_expansion
== 0)
1177 ADD_CHAR (string
[i
]);
1180 ADD_CHAR (string
[i
]);
1184 case -2: /* history_comment_char */
1185 if ((dquote
== 0 || history_quotes_inhibit_expansion
== 0) &&
1186 (i
== 0 || member (string
[i
- 1], history_word_delimiters
)))
1188 temp
= (char *)xmalloc (l
- i
+ 1);
1189 strcpy (temp
, string
+ i
);
1195 ADD_CHAR (string
[i
]);
1198 case -3: /* history_expansion_char */
1201 /* If the history_expansion_char is followed by one of the
1202 characters in history_no_expand_chars, then it is not a
1203 candidate for expansion of any kind. */
1204 if (cc
== 0 || member (cc
, history_no_expand_chars
) ||
1205 (dquote
&& cc
== '"') ||
1206 (history_inhibit_expansion_function
&& (*history_inhibit_expansion_function
) (string
, i
)))
1208 ADD_CHAR (string
[i
]);
1212 #if defined (NO_BANG_HASH_MODIFIERS)
1213 /* There is something that is listed as a `word specifier' in csh
1214 documentation which means `the expanded text to this point'.
1215 That is not a word specifier, it is an event specifier. If we
1216 don't want to allow modifiers with `!#', just stick the current
1217 output line in again. */
1222 temp
= (char *)xmalloc (1 + strlen (result
));
1223 strcpy (temp
, result
);
1231 qc
= squote
? '\'' : (dquote
? '"' : 0);
1232 r
= history_expand_internal (string
, i
, qc
, &eindex
, &temp
, result
);
1237 if (string
!= hstring
)
1250 only_printing
+= r
== 1;
1258 if (string
!= hstring
)
1264 add_history (result
);
1269 return (modified
!= 0);
1272 /* Return a consed string which is the word specified in SPEC, and found
1273 in FROM. NULL is returned if there is no spec. The address of
1274 ERROR_POINTER is returned if the word specified cannot be found.
1275 CALLER_INDEX is the offset in SPEC to start looking; it is updated
1276 to point to just after the last character parsed. */
1278 get_history_word_specifier (char *spec
, char *from
, int *caller_index
)
1280 register int i
= *caller_index
;
1282 int expecting_word_spec
= 0;
1285 /* The range of words to return doesn't exist yet. */
1287 result
= (char *)NULL
;
1289 /* If we found a colon, then this *must* be a word specification. If
1290 it isn't, then it is an error. */
1294 expecting_word_spec
++;
1297 /* Handle special cases first. */
1299 /* `%' is the word last searched for. */
1302 *caller_index
= i
+ 1;
1303 return (search_match
? savestring (search_match
) : savestring (""));
1306 /* `*' matches all of the arguments, but not the command. */
1309 *caller_index
= i
+ 1;
1310 result
= history_arg_extract (1, '$', from
);
1311 return (result
? result
: savestring (""));
1314 /* `$' is last arg. */
1317 *caller_index
= i
+ 1;
1318 return (history_arg_extract ('$', '$', from
));
1321 /* Try to get FIRST and LAST figured out. */
1325 else if (spec
[i
] == '^')
1330 else if (_rl_digit_p (spec
[i
]) && expecting_word_spec
)
1332 for (first
= 0; _rl_digit_p (spec
[i
]); i
++)
1333 first
= (first
* 10) + _rl_digit_value (spec
[i
]);
1336 return ((char *)NULL
); /* no valid `first' for word specifier */
1338 if (spec
[i
] == '^' || spec
[i
] == '*')
1340 last
= (spec
[i
] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
1343 else if (spec
[i
] != '-')
1349 if (_rl_digit_p (spec
[i
]))
1351 for (last
= 0; _rl_digit_p (spec
[i
]); i
++)
1352 last
= (last
* 10) + _rl_digit_value (spec
[i
]);
1354 else if (spec
[i
] == '$')
1360 else if (!spec
[i
] || spec
[i
] == ':')
1361 /* check against `:' because there could be a modifier separator */
1364 /* csh seems to allow anything to terminate the word spec here,
1365 leaving it as an abbreviation. */
1367 last
= -1; /* x- abbreviates x-$ omitting word `$' */
1372 if (last
>= first
|| last
== '$' || last
< 0)
1373 result
= history_arg_extract (first
, last
, from
);
1375 return (result
? result
: (char *)&error_pointer
);
1378 /* Extract the args specified, starting at FIRST, and ending at LAST.
1379 The args are taken from STRING. If either FIRST or LAST is < 0,
1380 then make that arg count from the right (subtract from the number of
1381 tokens, so that FIRST = -1 means the next to last token on the line).
1382 If LAST is `$' the last arg from STRING is used. */
1384 history_arg_extract (int first
, int last
, const char *string
)
1386 register int i
, len
;
1391 /* XXX - think about making history_tokenize return a struct array,
1392 each struct in array being a string and a length to avoid the
1393 calls to strlen below. */
1394 if ((list
= history_tokenize (string
)) == NULL
)
1395 return ((char *)NULL
);
1397 for (len
= 0; list
[len
]; len
++)
1401 last
= len
+ last
- 1;
1404 first
= len
+ first
- 1;
1414 if (first
>= len
|| last
> len
|| first
< 0 || last
< 0 || first
> last
)
1415 result
= ((char *)NULL
);
1418 for (size
= 0, i
= first
; i
< last
; i
++)
1419 size
+= strlen (list
[i
]) + 1;
1420 result
= (char *)xmalloc (size
+ 1);
1423 for (i
= first
, offset
= 0; i
< last
; i
++)
1425 strcpy (result
+ offset
, list
[i
]);
1426 offset
+= strlen (list
[i
]);
1429 result
[offset
++] = ' ';
1435 for (i
= 0; i
< len
; i
++)
1443 history_tokenize_word (const char *string
, int ind
)
1446 int delimiter
, nestdelim
, delimopen
;
1449 delimiter
= nestdelim
= 0;
1451 if (member (string
[i
], "()\n")) /* XXX - included \n, but why? been here forever */
1457 if (ISDIGIT (string
[i
]))
1460 while (string
[j
] && ISDIGIT (string
[j
]))
1464 if (string
[j
] == '<' || string
[j
] == '>')
1465 i
= j
; /* digit sequence is a file descriptor */
1469 goto get_word
; /* digit sequence is part of a word */
1473 if (member (string
[i
], "<>;&|"))
1475 int peek
= string
[i
+ 1];
1477 if (peek
== string
[i
])
1479 if (peek
== '<' && string
[i
+ 2] == '-')
1481 else if (peek
== '<' && string
[i
+ 2] == '<')
1486 else if (peek
== '&' && (string
[i
] == '>' || string
[i
] == '<'))
1489 while (string
[j
] && ISDIGIT (string
[j
])) /* file descriptor */
1491 if (string
[j
] =='-') /* <&[digits]-, >&[digits]- */
1495 else if ((peek
== '>' && string
[i
] == '&') || (peek
== '|' && string
[i
] == '>'))
1500 /* XXX - process substitution -- separated out for later -- bash-4.2 */
1501 else if (peek
== '(' && (string
[i
] == '>' || string
[i
] == '<')) /*)*/
1515 /* Get word from string + i; */
1517 if (delimiter
== 0 && member (string
[i
], HISTORY_QUOTE_CHARACTERS
))
1518 delimiter
= string
[i
++];
1520 for (; string
[i
]; i
++)
1522 if (string
[i
] == '\\' && string
[i
+ 1] == '\n')
1528 if (string
[i
] == '\\' && delimiter
!= '\'' &&
1529 (delimiter
!= '"' || member (string
[i
], slashify_in_quotes
)))
1535 /* delimiter must be set and set to something other than a quote if
1536 nestdelim is set, so these tests are safe. */
1537 if (nestdelim
&& string
[i
] == delimopen
)
1542 if (nestdelim
&& string
[i
] == delimiter
)
1550 if (delimiter
&& string
[i
] == delimiter
)
1556 /* Command and process substitution; shell extended globbing patterns */
1557 if (nestdelim
== 0 && delimiter
== 0 && member (string
[i
], "<>$!@?+*") && string
[i
+1] == '(') /*)*/
1566 if (delimiter
== 0 && (member (string
[i
], history_word_delimiters
)))
1569 if (delimiter
== 0 && member (string
[i
], HISTORY_QUOTE_CHARACTERS
))
1570 delimiter
= string
[i
];
1577 history_substring (const char *string
, int start
, int end
)
1580 register char *result
;
1583 result
= (char *)xmalloc (len
+ 1);
1584 strncpy (result
, string
+ start
, len
);
1589 /* Parse STRING into tokens and return an array of strings. If WIND is
1590 not -1 and INDP is not null, we also want the word surrounding index
1591 WIND. The position in the returned array of strings is returned in
1594 history_tokenize_internal (const char *string
, int wind
, int *indp
)
1597 register int i
, start
, result_index
, size
;
1599 /* If we're searching for a string that's not part of a word (e.g., " "),
1600 make sure we set *INDP to a reasonable value. */
1601 if (indp
&& wind
!= -1)
1604 /* Get a token, and stuff it into RESULT. The tokens are split
1605 exactly where the shell would split them. */
1606 for (i
= result_index
= size
= 0, result
= (char **)NULL
; string
[i
]; )
1608 /* Skip leading whitespace. */
1609 for (; string
[i
] && fielddelim (string
[i
]); i
++)
1611 if (string
[i
] == 0 || string
[i
] == history_comment_char
)
1616 i
= history_tokenize_word (string
, start
);
1618 /* If we have a non-whitespace delimiter character (which would not be
1619 skipped by the loop above), use it and any adjacent delimiters to
1620 make a separate field. Any adjacent white space will be skipped the
1621 next time through the loop. */
1622 if (i
== start
&& history_word_delimiters
)
1625 while (string
[i
] && member (string
[i
], history_word_delimiters
))
1629 /* If we are looking for the word in which the character at a
1630 particular index falls, remember it. */
1631 if (indp
&& wind
!= -1 && wind
>= start
&& wind
< i
)
1632 *indp
= result_index
;
1634 if (result_index
+ 2 >= size
)
1635 result
= (char **)xrealloc (result
, ((size
+= 10) * sizeof (char *)));
1637 result
[result_index
++] = history_substring (string
, start
, i
);
1638 result
[result_index
] = (char *)NULL
;
1644 /* Return an array of tokens, much as the shell might. The tokens are
1645 parsed out of STRING. */
1647 history_tokenize (const char *string
)
1649 return (history_tokenize_internal (string
, -1, (int *)NULL
));
1652 /* Free members of WORDS from START to an empty string */
1654 freewords (char **words
, int start
)
1658 for (i
= start
; words
[i
]; i
++)
1662 /* Find and return the word which contains the character at index IND
1663 in the history line LINE. Used to save the word matched by the
1664 last history !?string? search. */
1666 history_find_word (char *line
, int ind
)
1671 words
= history_tokenize_internal (line
, ind
, &wind
);
1672 if (wind
== -1 || words
== 0)
1675 freewords (words
, 0);
1677 return ((char *)NULL
);
1680 for (i
= 0; i
< wind
; i
++)
1682 freewords (words
, wind
+ 1);