1 /* histexpand.c -- history expansion. */
3 /* Copyright (C) 1989-2015 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 typedef int _hist_search_func_t
PARAMS((const char *, int));
60 static char error_pointer
;
62 static char *subst_lhs
;
63 static char *subst_rhs
;
64 static int subst_lhs_len
;
65 static int subst_rhs_len
;
67 /* Characters that delimit history event specifications and separate event
68 specifications from word designators. Static for now */
69 static char *history_event_delimiter_chars
= HISTORY_EVENT_DELIMITERS
;
71 static char *get_history_word_specifier
PARAMS((char *, char *, int *));
72 static int history_tokenize_word
PARAMS((const char *, int));
73 static char **history_tokenize_internal
PARAMS((const char *, int, int *));
74 static char *history_substring
PARAMS((const char *, int, int));
75 static void freewords
PARAMS((char **, int));
76 static char *history_find_word
PARAMS((char *, int));
78 static char *quote_breaks
PARAMS((char *));
80 /* Variables exported by this file. */
81 /* The character that represents the start of a history expansion
82 request. This is usually `!'. */
83 char history_expansion_char
= '!';
85 /* The character that invokes word substitution if found at the start of
86 a line. This is usually `^'. */
87 char history_subst_char
= '^';
89 /* During tokenization, if this character is seen as the first character
90 of a word, then it, and all subsequent characters upto a newline are
91 ignored. For a Bourne shell, this should be '#'. Bash special cases
92 the interactive comment character to not be a comment delimiter. */
93 char history_comment_char
= '\0';
95 /* The list of characters which inhibit the expansion of text if found
96 immediately following history_expansion_char. */
97 char *history_no_expand_chars
= " \t\n\r=";
99 /* If set to a non-zero value, single quotes inhibit history expansion.
101 int history_quotes_inhibit_expansion
= 0;
103 /* Used to split words by history_tokenize_internal. */
104 char *history_word_delimiters
= HISTORY_WORD_DELIMITERS
;
106 /* If set, this points to a function that is called to verify that a
107 particular history expansion should be performed. */
108 rl_linebuf_func_t
*history_inhibit_expansion_function
;
110 /* **************************************************************** */
112 /* History Expansion */
114 /* **************************************************************** */
116 /* Hairy history expansion on text, not tokens. This is of general
117 use, and thus belongs in this library. */
119 /* The last string searched for by a !?string? search. */
120 static char *search_string
;
121 /* The last string matched by a !?string? search. */
122 static char *search_match
;
124 /* Return the event specified at TEXT + OFFSET modifying OFFSET to
125 point to after the event specifier. Just a pointer to the history
126 line is returned; NULL is returned in the event of a bad specifier.
127 You pass STRING with *INDEX equal to the history_expansion_char that
128 begins this specification.
129 DELIMITING_QUOTE is a character that is allowed to end the string
130 specification for what to search for in addition to the normal
131 characters `:', ` ', `\t', `\n', and sometimes `?'.
132 So you might call this function like:
133 line = get_history_event ("!echo:p", &index, 0); */
135 get_history_event (string
, caller_index
, delimiting_quote
)
138 int delimiting_quote
;
143 int which
, sign
, local_index
, substring_okay
;
144 _hist_search_func_t
*search_func
;
147 /* The event can be specified in a number of ways.
149 !! the previous command
151 !-n current command-line minus N
152 !str the most recent command starting with STR
154 the most recent command containing STR
156 All values N are determined via HISTORY_BASE. */
160 if (string
[i
] != history_expansion_char
)
161 return ((char *)NULL
);
163 /* Move on to the specification. */
169 #define RETURN_ENTRY(e, w) \
170 return ((e = history_get (w)) ? e->line : (char *)NULL)
172 /* Handle !! case. */
173 if (string
[i
] == history_expansion_char
)
176 which
= history_base
+ (history_length
- 1);
178 RETURN_ENTRY (entry
, which
);
181 /* Hack case of numeric line specification. */
182 if (string
[i
] == '-')
188 if (_rl_digit_p (string
[i
]))
190 /* Get the extent of the digits and compute the value. */
191 for (which
= 0; _rl_digit_p (string
[i
]); i
++)
192 which
= (which
* 10) + _rl_digit_value (string
[i
]);
197 which
= (history_length
+ history_base
) - which
;
199 RETURN_ENTRY (entry
, which
);
202 /* This must be something to search for. If the spec begins with
203 a '?', then the string may be anywhere on the line. Otherwise,
204 the string must be found at the start of a line. */
205 if (string
[i
] == '?')
211 /* Only a closing `?' or a newline delimit a substring search string. */
212 for (local_index
= i
; c
= string
[i
]; i
++)
214 #if defined (HANDLE_MULTIBYTE)
215 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
220 memset (&ps
, 0, sizeof (mbstate_t));
221 /* These produce warnings because we're passing a const string to a
222 function that takes a non-const string. */
223 _rl_adjust_point ((char *)string
, i
, &ps
);
224 if ((v
= _rl_get_char_len ((char *)string
+ i
, &ps
)) > 1)
231 #endif /* HANDLE_MULTIBYTE */
232 if ((!substring_okay
&& (whitespace (c
) || c
== ':' ||
233 (history_event_delimiter_chars
&& member (c
, history_event_delimiter_chars
)) ||
234 (history_search_delimiter_chars
&& member (c
, history_search_delimiter_chars
)) ||
235 string
[i
] == delimiting_quote
)) ||
237 (substring_okay
&& string
[i
] == '?'))
241 which
= i
- local_index
;
242 temp
= (char *)xmalloc (1 + which
);
244 strncpy (temp
, string
+ local_index
, which
);
247 if (substring_okay
&& string
[i
] == '?')
252 #define FAIL_SEARCH() \
254 history_offset = history_length; xfree (temp) ; return (char *)NULL; \
257 /* If there is no search string, try to use the previous search string,
258 if one exists. If not, fail immediately. */
259 if (*temp
== '\0' && substring_okay
)
264 temp
= savestring (search_string
);
270 search_func
= substring_okay
? history_search
: history_search_prefix
;
273 local_index
= (*search_func
) (temp
, -1);
278 if (local_index
== 0 || substring_okay
)
280 entry
= current_history ();
283 history_offset
= history_length
;
285 /* If this was a substring search, then remember the
286 string that we matched for word substitution. */
289 FREE (search_string
);
290 search_string
= temp
;
293 search_match
= history_find_word (entry
->line
, local_index
);
298 return (entry
->line
);
310 /* Function for extracting single-quoted strings. Used for inhibiting
311 history expansion within single quotes. */
313 /* Extract the contents of STRING as if it is enclosed in single quotes.
314 SINDEX, when passed in, is the offset of the character immediately
315 following the opening single quote; on exit, SINDEX is left pointing
316 to the closing single quote. FLAGS currently used to allow backslash
317 to escape a single quote (e.g., for bash $'...'). */
319 hist_string_extract_single_quoted (string
, sindex
, flags
)
325 for (i
= *sindex
; string
[i
] && string
[i
] != '\''; i
++)
327 if ((flags
& 1) && string
[i
] == '\\' && string
[i
+1])
338 register char *p
, *r
;
342 for (p
= s
; p
&& *p
; p
++, len
++)
346 else if (whitespace (*p
) || *p
== '\n')
350 r
= ret
= (char *)xmalloc (len
);
352 for (p
= s
; p
&& *p
; )
362 else if (whitespace (*p
) || *p
== '\n')
377 hist_error(s
, start
, current
, errtype
)
379 int start
, current
, errtype
;
385 ll
= current
- start
;
389 case EVENT_NOT_FOUND
:
390 emsg
= "event not found";
394 emsg
= "bad word specifier";
398 emsg
= "substitution failed";
402 emsg
= "unrecognized history modifier";
406 emsg
= "no previous substitution";
410 emsg
= "unknown expansion error";
415 temp
= (char *)xmalloc (ll
+ elen
+ 3);
416 strncpy (temp
, s
+ start
, ll
);
419 strcpy (temp
+ ll
+ 2, emsg
);
423 /* Get a history substitution string from STR starting at *IPTR
424 and return it. The length is returned in LENPTR.
426 A backslash can quote the delimiter. If the string is the
427 empty string, the previous pattern is used. If there is
428 no previous pattern for the lhs, the last history search
431 If IS_RHS is 1, we ignore empty strings and set the pattern
432 to "" anyway. subst_lhs is not changed if the lhs is empty;
433 subst_rhs is allowed to be set to the empty string. */
436 get_subst_pattern (str
, iptr
, delimiter
, is_rhs
, lenptr
)
438 int *iptr
, delimiter
, is_rhs
, *lenptr
;
440 register int si
, i
, j
, k
;
442 #if defined (HANDLE_MULTIBYTE)
449 #if defined (HANDLE_MULTIBYTE)
450 memset (&ps
, 0, sizeof (mbstate_t));
451 _rl_adjust_point (str
, i
, &ps
);
454 for (si
= i
; str
[si
] && str
[si
] != delimiter
; si
++)
455 #if defined (HANDLE_MULTIBYTE)
456 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
459 if ((v
= _rl_get_char_len (str
+ si
, &ps
)) > 1)
461 else if (str
[si
] == '\\' && str
[si
+ 1] == delimiter
)
465 #endif /* HANDLE_MULTIBYTE */
466 if (str
[si
] == '\\' && str
[si
+ 1] == delimiter
)
469 if (si
> i
|| is_rhs
)
471 s
= (char *)xmalloc (si
- i
+ 1);
472 for (j
= 0, k
= i
; k
< si
; j
++, k
++)
474 /* Remove a backslash quoting the search string delimiter. */
475 if (str
[k
] == '\\' && str
[k
+ 1] == delimiter
)
493 postproc_subst_rhs ()
498 new = (char *)xmalloc (new_size
= subst_rhs_len
+ subst_lhs_len
);
499 for (i
= j
= 0; i
< subst_rhs_len
; i
++)
501 if (subst_rhs
[i
] == '&')
503 if (j
+ subst_lhs_len
>= new_size
)
504 new = (char *)xrealloc (new, (new_size
= new_size
* 2 + subst_lhs_len
));
505 strcpy (new + j
, subst_lhs
);
510 /* a single backslash protects the `&' from lhs interpolation */
511 if (subst_rhs
[i
] == '\\' && subst_rhs
[i
+ 1] == '&')
514 new = (char *)xrealloc (new, new_size
*= 2);
515 new[j
++] = subst_rhs
[i
];
524 /* Expand the bulk of a history specifier starting at STRING[START].
525 Returns 0 if everything is OK, -1 if an error occurred, and 1
526 if the `p' modifier was supplied and the caller should just print
527 the returned string. Returns the new index into string in
528 *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
530 history_expand_internal (string
, start
, qc
, end_index_ptr
, ret_string
, current_line
)
532 int start
, qc
, *end_index_ptr
;
534 char *current_line
; /* for !# */
536 int i
, n
, starting_index
;
537 int substitute_globally
, subst_bywords
, want_quotes
, print_only
;
538 char *event
, *temp
, *result
, *tstr
, *t
, c
, *word_spec
;
540 #if defined (HANDLE_MULTIBYTE)
543 memset (&ps
, 0, sizeof (mbstate_t));
546 result
= (char *)xmalloc (result_len
= 128);
550 /* If it is followed by something that starts a word specifier,
551 then !! is implied as the event specifier. */
553 if (member (string
[i
+ 1], ":$*%^"))
558 fake_s
[0] = fake_s
[1] = history_expansion_char
;
560 event
= get_history_event (fake_s
, &fake_i
, 0);
562 else if (string
[i
+ 1] == '#')
565 event
= current_line
;
568 event
= get_history_event (string
, &i
, qc
);
572 *ret_string
= hist_error (string
, start
, i
, EVENT_NOT_FOUND
);
577 /* If a word specifier is found, then do what that requires. */
579 word_spec
= get_history_word_specifier (string
, event
, &i
);
581 /* There is no such thing as a `malformed word specifier'. However,
582 it is possible for a specifier that has no match. In that case,
584 if (word_spec
== (char *)&error_pointer
)
586 *ret_string
= hist_error (string
, starting_index
, i
, BAD_WORD_SPEC
);
591 /* If no word specifier, than the thing of interest was the event. */
592 temp
= word_spec
? savestring (word_spec
) : savestring (event
);
595 /* Perhaps there are other modifiers involved. Do what they say. */
596 want_quotes
= substitute_globally
= subst_bywords
= print_only
= 0;
599 while (string
[i
] == ':')
603 if (c
== 'g' || c
== 'a')
605 substitute_globally
= 1;
619 *ret_string
= hist_error (string
, i
+1, i
+2, BAD_MODIFIER
);
632 /* :p means make this the last executed line. So we
633 return an error state after adding this line to the
639 /* :t discards all but the last part of the pathname. */
641 tstr
= strrchr (temp
, '/');
645 t
= savestring (tstr
);
651 /* :h discards the last part of a pathname. */
653 tstr
= strrchr (temp
, '/');
658 /* :r discards the suffix. */
660 tstr
= strrchr (temp
, '.');
665 /* :e discards everything but the suffix. */
667 tstr
= strrchr (temp
, '.');
670 t
= savestring (tstr
);
676 /* :s/this/that substitutes `that' for the first
677 occurrence of `this'. :gs/this/that substitutes `that'
678 for each occurrence of `this'. :& repeats the last
679 substitution. :g& repeats the last substitution
686 int delimiter
, failed
, si
, l_temp
, ws
, we
;
690 if (i
+ 2 < (int)strlen (string
))
692 #if defined (HANDLE_MULTIBYTE)
693 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
695 _rl_adjust_point (string
, i
+ 2, &ps
);
696 if (_rl_get_char_len (string
+ i
+ 2, &ps
) > 1)
699 delimiter
= string
[i
+ 2];
702 #endif /* HANDLE_MULTIBYTE */
703 delimiter
= string
[i
+ 2];
706 break; /* no search delimiter */
710 t
= get_subst_pattern (string
, &i
, delimiter
, 0, &subst_lhs_len
);
711 /* An empty substitution lhs with no previous substitution
712 uses the last search string as the lhs. */
720 if (search_string
&& *search_string
)
722 subst_lhs
= savestring (search_string
);
723 subst_lhs_len
= strlen (subst_lhs
);
727 subst_lhs
= (char *) NULL
;
733 subst_rhs
= get_subst_pattern (string
, &i
, delimiter
, 1, &subst_rhs_len
);
735 /* If `&' appears in the rhs, it's supposed to be replaced
737 if (member ('&', subst_rhs
))
738 postproc_subst_rhs ();
743 /* If there is no lhs, the substitution can't succeed. */
744 if (subst_lhs_len
== 0)
746 *ret_string
= hist_error (string
, starting_index
, i
, NO_PREV_SUBST
);
752 l_temp
= strlen (temp
);
753 /* Ignore impossible cases. */
754 if (subst_lhs_len
> l_temp
)
756 *ret_string
= hist_error (string
, starting_index
, i
, SUBST_FAILED
);
762 /* Find the first occurrence of THIS in TEMP. */
763 /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
766 1. substitute_globally == subst_bywords == 0
767 2. substitute_globally == 1 && subst_bywords == 0
768 3. substitute_globally == 0 && subst_bywords == 1
770 In the first case, we substitute for the first occurrence only.
771 In the second case, we substitute for every occurrence.
772 In the third case, we tokenize into words and substitute the
773 first occurrence of each word. */
776 for (failed
= 1; (si
+ subst_lhs_len
) <= l_temp
; si
++)
778 /* First skip whitespace and find word boundaries if
779 we're past the end of the word boundary we found
781 if (subst_bywords
&& si
> we
)
783 for (; temp
[si
] && whitespace (temp
[si
]); si
++)
786 we
= history_tokenize_word (temp
, si
);
789 if (STREQN (temp
+si
, subst_lhs
, subst_lhs_len
))
791 int len
= subst_rhs_len
- subst_lhs_len
+ l_temp
;
792 new_event
= (char *)xmalloc (1 + len
);
793 strncpy (new_event
, temp
, si
);
794 strncpy (new_event
+ si
, subst_rhs
, subst_rhs_len
);
795 strncpy (new_event
+ si
+ subst_rhs_len
,
796 temp
+ si
+ subst_lhs_len
,
797 l_temp
- (si
+ subst_lhs_len
));
798 new_event
[len
] = '\0';
804 if (substitute_globally
)
806 /* Reported to fix a bug that causes it to skip every
807 other match when matching a single character. Was
808 si += subst_rhs_len previously. */
809 si
+= subst_rhs_len
- 1;
810 l_temp
= strlen (temp
);
811 substitute_globally
++;
814 else if (subst_bywords
)
817 l_temp
= strlen (temp
);
825 if (substitute_globally
> 1)
827 substitute_globally
= 0;
828 continue; /* don't want to increment i */
832 continue; /* don't want to increment i */
834 *ret_string
= hist_error (string
, starting_index
, i
, SUBST_FAILED
);
842 /* Done with modifiers. */
843 /* Believe it or not, we have to back the pointer up by one. */
850 if (want_quotes
== 'q')
851 x
= sh_single_quote (temp
);
852 else if (want_quotes
== 'x')
853 x
= quote_breaks (temp
);
855 x
= savestring (temp
);
863 result
= (char *)xrealloc (result
, n
+ 2);
864 strcpy (result
, temp
);
868 *ret_string
= result
;
872 /* Expand the string STRING, placing the result into OUTPUT, a pointer
873 to a string. Returns:
875 -1) If there was an error in expansion.
876 0) If no expansions took place (or, if the only change in
877 the text was the de-slashifying of the history expansion
879 1) If expansions did take place
880 2) If the `p' modifier was given and the caller should print the result
882 If an error occurred in expansion, then OUTPUT contains a descriptive
885 #define ADD_STRING(s) \
888 int sl = strlen (s); \
890 if (j >= result_len) \
892 while (j >= result_len) \
894 result = (char *)xrealloc (result, result_len); \
896 strcpy (result + j - sl, s); \
900 #define ADD_CHAR(c) \
903 if (j >= result_len - 1) \
904 result = (char *)xrealloc (result, result_len += 64); \
911 history_expand (hstring
, output
)
916 int i
, r
, l
, passc
, cc
, modified
, eindex
, only_printing
, dquote
, squote
, flag
;
919 /* The output string, and its length. */
923 #if defined (HANDLE_MULTIBYTE)
928 /* Used when adding the string. */
934 /* Setting the history expansion character to 0 inhibits all
935 history expansion. */
936 if (history_expansion_char
== 0)
938 *output
= savestring (hstring
);
942 /* Prepare the buffer for printing error messages. */
943 result
= (char *)xmalloc (result_len
= 256);
946 only_printing
= modified
= 0;
947 l
= strlen (hstring
);
949 /* Grovel the string. Only backslash and single quotes can quote the
950 history escape character. We also handle arg specifiers. */
952 /* Before we grovel forever, see if the history_expansion_char appears
953 anywhere within the text. */
955 /* The quick substitution character is a history expansion all right. That
956 is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
957 that is the substitution that we do. */
958 if (hstring
[0] == history_subst_char
)
960 string
= (char *)xmalloc (l
+ 5);
962 string
[0] = string
[1] = history_expansion_char
;
965 strcpy (string
+ 4, hstring
);
970 #if defined (HANDLE_MULTIBYTE)
971 memset (&ps
, 0, sizeof (mbstate_t));
975 /* If not quick substitution, still maybe have to do expansion. */
977 /* `!' followed by one of the characters in history_no_expand_chars
978 is NOT an expansion. */
979 for (i
= dquote
= squote
= 0; string
[i
]; i
++)
981 #if defined (HANDLE_MULTIBYTE)
982 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
985 v
= _rl_get_char_len (string
+ i
, &ps
);
992 #endif /* HANDLE_MULTIBYTE */
995 /* The history_comment_char, if set, appearing at the beginning
996 of a word signifies that the rest of the line should not have
997 history expansion performed on it.
998 Skip the rest of the line and break out of the loop. */
999 if (history_comment_char
&& string
[i
] == history_comment_char
&&
1001 (i
== 0 || member (string
[i
- 1], history_word_delimiters
)))
1007 else if (string
[i
] == history_expansion_char
)
1009 if (cc
== 0 || member (cc
, history_no_expand_chars
))
1011 /* DQUOTE won't be set unless history_quotes_inhibit_expansion
1012 is set. The idea here is to treat double-quoted strings the
1013 same as the word outside double quotes; in effect making the
1014 double quote part of history_no_expand_chars when DQUOTE is
1016 else if (dquote
&& cc
== '"')
1018 /* If the calling application has set
1019 history_inhibit_expansion_function to a function that checks
1020 for special cases that should not be history expanded,
1021 call the function and skip the expansion if it returns a
1023 else if (history_inhibit_expansion_function
&&
1024 (*history_inhibit_expansion_function
) (string
, i
))
1029 /* Shell-like quoting: allow backslashes to quote double quotes
1030 inside a double-quoted string. */
1031 else if (dquote
&& string
[i
] == '\\' && cc
== '"')
1033 /* More shell-like quoting: if we're paying attention to single
1034 quotes and letting them quote the history expansion character,
1035 then we need to pay attention to double quotes, because single
1036 quotes are not special inside double-quoted strings. */
1037 else if (history_quotes_inhibit_expansion
&& string
[i
] == '"')
1039 dquote
= 1 - dquote
;
1041 else if (dquote
== 0 && history_quotes_inhibit_expansion
&& string
[i
] == '\'')
1043 /* If this is bash, single quotes inhibit history expansion. */
1044 flag
= (i
> 0 && string
[i
- 1] == '$');
1046 hist_string_extract_single_quoted (string
, &i
, flag
);
1048 else if (history_quotes_inhibit_expansion
&& string
[i
] == '\\')
1050 /* If this is bash, allow backslashes to quote single
1051 quotes and the history expansion character. */
1052 if (cc
== '\'' || cc
== history_expansion_char
)
1058 if (string
[i
] != history_expansion_char
)
1061 *output
= savestring (string
);
1066 /* Extract and perform the substitution. */
1067 for (passc
= dquote
= squote
= i
= j
= 0; i
< l
; i
++)
1069 int qc
, tchar
= string
[i
];
1078 #if defined (HANDLE_MULTIBYTE)
1079 if (MB_CUR_MAX
> 1 && rl_byte_oriented
== 0)
1084 memset (mb
, 0, sizeof (mb
));
1085 for (k
= 0; k
< MB_LEN_MAX
; k
++)
1088 memset (&ps
, 0, sizeof (mbstate_t));
1089 if (_rl_get_char_len (mb
, &ps
) == -2)
1094 if (strlen (mb
) > 1)
1100 #endif /* HANDLE_MULTIBYTE */
1102 if (tchar
== history_expansion_char
)
1104 else if (tchar
== history_comment_char
)
1110 ADD_CHAR (string
[i
]);
1119 dquote
= 1 - dquote
;
1125 /* If history_quotes_inhibit_expansion is set, single quotes
1126 inhibit history expansion, otherwise they are treated like
1133 else if (dquote
== 0 && history_quotes_inhibit_expansion
)
1137 flag
= (i
> 0 && string
[i
- 1] == '$');
1139 hist_string_extract_single_quoted (string
, &i
, flag
);
1141 slen
= i
- quote
+ 2;
1142 temp
= (char *)xmalloc (slen
);
1143 strncpy (temp
, string
+ quote
, slen
);
1144 temp
[slen
- 1] = '\0';
1148 else if (dquote
== 0 && squote
== 0 && history_quotes_inhibit_expansion
== 0)
1151 ADD_CHAR (string
[i
]);
1154 ADD_CHAR (string
[i
]);
1158 case -2: /* history_comment_char */
1159 if ((dquote
== 0 || history_quotes_inhibit_expansion
== 0) &&
1160 (i
== 0 || member (string
[i
- 1], history_word_delimiters
)))
1162 temp
= (char *)xmalloc (l
- i
+ 1);
1163 strcpy (temp
, string
+ i
);
1169 ADD_CHAR (string
[i
]);
1172 case -3: /* history_expansion_char */
1175 /* If the history_expansion_char is followed by one of the
1176 characters in history_no_expand_chars, then it is not a
1177 candidate for expansion of any kind. */
1178 if (cc
== 0 || member (cc
, history_no_expand_chars
) ||
1179 (dquote
&& cc
== '"') ||
1180 (history_inhibit_expansion_function
&& (*history_inhibit_expansion_function
) (string
, i
)))
1182 ADD_CHAR (string
[i
]);
1186 #if defined (NO_BANG_HASH_MODIFIERS)
1187 /* There is something that is listed as a `word specifier' in csh
1188 documentation which means `the expanded text to this point'.
1189 That is not a word specifier, it is an event specifier. If we
1190 don't want to allow modifiers with `!#', just stick the current
1191 output line in again. */
1196 temp
= (char *)xmalloc (1 + strlen (result
));
1197 strcpy (temp
, result
);
1205 qc
= squote
? '\'' : (dquote
? '"' : 0);
1206 r
= history_expand_internal (string
, i
, qc
, &eindex
, &temp
, result
);
1211 if (string
!= hstring
)
1224 only_printing
+= r
== 1;
1232 if (string
!= hstring
)
1238 add_history (result
);
1243 return (modified
!= 0);
1246 /* Return a consed string which is the word specified in SPEC, and found
1247 in FROM. NULL is returned if there is no spec. The address of
1248 ERROR_POINTER is returned if the word specified cannot be found.
1249 CALLER_INDEX is the offset in SPEC to start looking; it is updated
1250 to point to just after the last character parsed. */
1252 get_history_word_specifier (spec
, from
, caller_index
)
1256 register int i
= *caller_index
;
1258 int expecting_word_spec
= 0;
1261 /* The range of words to return doesn't exist yet. */
1263 result
= (char *)NULL
;
1265 /* If we found a colon, then this *must* be a word specification. If
1266 it isn't, then it is an error. */
1270 expecting_word_spec
++;
1273 /* Handle special cases first. */
1275 /* `%' is the word last searched for. */
1278 *caller_index
= i
+ 1;
1279 return (search_match
? savestring (search_match
) : savestring (""));
1282 /* `*' matches all of the arguments, but not the command. */
1285 *caller_index
= i
+ 1;
1286 result
= history_arg_extract (1, '$', from
);
1287 return (result
? result
: savestring (""));
1290 /* `$' is last arg. */
1293 *caller_index
= i
+ 1;
1294 return (history_arg_extract ('$', '$', from
));
1297 /* Try to get FIRST and LAST figured out. */
1301 else if (spec
[i
] == '^')
1306 else if (_rl_digit_p (spec
[i
]) && expecting_word_spec
)
1308 for (first
= 0; _rl_digit_p (spec
[i
]); i
++)
1309 first
= (first
* 10) + _rl_digit_value (spec
[i
]);
1312 return ((char *)NULL
); /* no valid `first' for word specifier */
1314 if (spec
[i
] == '^' || spec
[i
] == '*')
1316 last
= (spec
[i
] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
1319 else if (spec
[i
] != '-')
1325 if (_rl_digit_p (spec
[i
]))
1327 for (last
= 0; _rl_digit_p (spec
[i
]); i
++)
1328 last
= (last
* 10) + _rl_digit_value (spec
[i
]);
1330 else if (spec
[i
] == '$')
1336 else if (!spec
[i
] || spec
[i
] == ':')
1337 /* check against `:' because there could be a modifier separator */
1340 /* csh seems to allow anything to terminate the word spec here,
1341 leaving it as an abbreviation. */
1343 last
= -1; /* x- abbreviates x-$ omitting word `$' */
1348 if (last
>= first
|| last
== '$' || last
< 0)
1349 result
= history_arg_extract (first
, last
, from
);
1351 return (result
? result
: (char *)&error_pointer
);
1354 /* Extract the args specified, starting at FIRST, and ending at LAST.
1355 The args are taken from STRING. If either FIRST or LAST is < 0,
1356 then make that arg count from the right (subtract from the number of
1357 tokens, so that FIRST = -1 means the next to last token on the line).
1358 If LAST is `$' the last arg from STRING is used. */
1360 history_arg_extract (first
, last
, string
)
1364 register int i
, len
;
1369 /* XXX - think about making history_tokenize return a struct array,
1370 each struct in array being a string and a length to avoid the
1371 calls to strlen below. */
1372 if ((list
= history_tokenize (string
)) == NULL
)
1373 return ((char *)NULL
);
1375 for (len
= 0; list
[len
]; len
++)
1379 last
= len
+ last
- 1;
1382 first
= len
+ first
- 1;
1392 if (first
>= len
|| last
> len
|| first
< 0 || last
< 0 || first
> last
)
1393 result
= ((char *)NULL
);
1396 for (size
= 0, i
= first
; i
< last
; i
++)
1397 size
+= strlen (list
[i
]) + 1;
1398 result
= (char *)xmalloc (size
+ 1);
1401 for (i
= first
, offset
= 0; i
< last
; i
++)
1403 strcpy (result
+ offset
, list
[i
]);
1404 offset
+= strlen (list
[i
]);
1407 result
[offset
++] = ' ';
1413 for (i
= 0; i
< len
; i
++)
1421 history_tokenize_word (string
, ind
)
1426 int delimiter
, nestdelim
, delimopen
;
1429 delimiter
= nestdelim
= 0;
1431 if (member (string
[i
], "()\n"))
1437 if (ISDIGIT (string
[i
]))
1440 while (string
[j
] && ISDIGIT (string
[j
]))
1444 if (string
[j
] == '<' || string
[j
] == '>')
1445 i
= j
; /* digit sequence is a file descriptor */
1449 goto get_word
; /* digit sequence is part of a word */
1453 if (member (string
[i
], "<>;&|$"))
1455 int peek
= string
[i
+ 1];
1457 if (peek
== string
[i
] && peek
!= '$')
1459 if (peek
== '<' && string
[i
+ 2] == '-')
1461 else if (peek
== '<' && string
[i
+ 2] == '<')
1466 else if (peek
== '&' && (string
[i
] == '>' || string
[i
] == '<'))
1469 while (string
[j
] && ISDIGIT (string
[j
])) /* file descriptor */
1471 if (string
[j
] =='-') /* <&[digits]-, >&[digits]- */
1475 else if ((peek
== '>' && string
[i
] == '&') || (peek
== '|' && string
[i
] == '>'))
1480 /* XXX - separated out for later -- bash-4.2 */
1481 else if ((peek
== '(' && (string
[i
] == '>' || string
[i
] == '<')) || /* ) */
1482 (peek
== '(' && string
[i
] == '$')) /*)*/
1491 else if (peek
== '\'' && string
[i
] == '$')
1498 if (string
[i
] != '$')
1505 /* same code also used for $(...)/<(...)/>(...) above */
1506 if (member (string
[i
], "!@?+*"))
1508 int peek
= string
[i
+ 1];
1510 if (peek
== '(') /*)*/
1512 /* Shell extended globbing patterns */
1515 delimiter
= ')'; /* XXX - not perfect */
1521 /* Get word from string + i; */
1523 if (delimiter
== 0 && member (string
[i
], HISTORY_QUOTE_CHARACTERS
))
1524 delimiter
= string
[i
++];
1526 for (; string
[i
]; i
++)
1528 if (string
[i
] == '\\' && string
[i
+ 1] == '\n')
1534 if (string
[i
] == '\\' && delimiter
!= '\'' &&
1535 (delimiter
!= '"' || member (string
[i
], slashify_in_quotes
)))
1541 /* delimiter must be set and set to something other than a quote if
1542 nestdelim is set, so these tests are safe. */
1543 if (nestdelim
&& string
[i
] == delimopen
)
1548 if (nestdelim
&& string
[i
] == delimiter
)
1556 if (delimiter
&& string
[i
] == delimiter
)
1562 if (delimiter
== 0 && (member (string
[i
], history_word_delimiters
)))
1565 if (delimiter
== 0 && member (string
[i
], HISTORY_QUOTE_CHARACTERS
))
1566 delimiter
= string
[i
];
1573 history_substring (string
, start
, end
)
1578 register char *result
;
1581 result
= (char *)xmalloc (len
+ 1);
1582 strncpy (result
, string
+ start
, len
);
1587 /* Parse STRING into tokens and return an array of strings. If WIND is
1588 not -1 and INDP is not null, we also want the word surrounding index
1589 WIND. The position in the returned array of strings is returned in
1592 history_tokenize_internal (string
, wind
, 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
] && whitespace (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 (string
)
1650 return (history_tokenize_internal (string
, -1, (int *)NULL
));
1653 /* Free members of WORDS from START to an empty string */
1655 freewords (words
, start
)
1661 for (i
= start
; words
[i
]; i
++)
1665 /* Find and return the word which contains the character at index IND
1666 in the history line LINE. Used to save the word matched by the
1667 last history !?string? search. */
1669 history_find_word (line
, ind
)
1676 words
= history_tokenize_internal (line
, ind
, &wind
);
1677 if (wind
== -1 || words
== 0)
1680 freewords (words
, 0);
1682 return ((char *)NULL
);
1685 for (i
= 0; i
< wind
; i
++)
1687 freewords (words
, wind
+ 1);