blob: 4899b9d3a0e706e21df4e4cec1bdfef135b6977c [file] [log] [blame]
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001/* histexpand.c -- history expansion. */
2
Chet Rameyac50fba2014-02-26 09:36:43 -05003/* Copyright (C) 1989-2012 Free Software Foundation, Inc.
Jari Aaltoccc6cda1996-12-23 17:02:34 +00004
Jari Aalto31859422009-01-12 13:36:28 +00005 This file contains the GNU History Library (History), a set of
Jari Aaltoccc6cda1996-12-23 17:02:34 +00006 routines for managing the text of previously typed lines.
7
Jari Aalto31859422009-01-12 13:36:28 +00008 History is free software: you can redistribute it and/or modify
Jari Aaltoccc6cda1996-12-23 17:02:34 +00009 it under the terms of the GNU General Public License as published by
Jari Aalto31859422009-01-12 13:36:28 +000010 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000012
Jari Aalto31859422009-01-12 13:36:28 +000013 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.
Jari Aaltoccc6cda1996-12-23 17:02:34 +000017
Jari Aalto31859422009-01-12 13:36:28 +000018 You should have received a copy of the GNU General Public License
19 along with History. If not, see <http://www.gnu.org/licenses/>.
20*/
Jari Aaltoccc6cda1996-12-23 17:02:34 +000021
22#define READLINE_LIBRARY
23
24#if defined (HAVE_CONFIG_H)
25# include <config.h>
26#endif
27
28#include <stdio.h>
29
30#if defined (HAVE_STDLIB_H)
31# include <stdlib.h>
32#else
33# include "ansi_stdlib.h"
34#endif /* HAVE_STDLIB_H */
35
36#if defined (HAVE_UNISTD_H)
Jari Aaltocce855b1998-04-17 19:52:44 +000037# ifndef _MINIX
38# include <sys/types.h>
39# endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +000040# include <unistd.h>
41#endif
42
Jari Aalto7117c2d2002-07-17 14:10:11 +000043#include "rlmbutil.h"
Jari Aaltoccc6cda1996-12-23 17:02:34 +000044
45#include "history.h"
46#include "histlib.h"
47
Jari Aaltobb706242000-03-17 21:46:59 +000048#include "rlshell.h"
49#include "xmalloc.h"
50
Jari Aaltocce855b1998-04-17 19:52:44 +000051#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
52#define HISTORY_QUOTE_CHARACTERS "\"'`"
53
Jari Aaltob80f6442004-07-27 13:29:18 +000054#define slashify_in_quotes "\\`\"$"
55
Jari Aaltof73dda02001-11-13 17:56:06 +000056typedef int _hist_search_func_t PARAMS((const char *, int));
Jari Aalto28ef6c32001-04-06 19:14:31 +000057
Jari Aaltoccc6cda1996-12-23 17:02:34 +000058static char error_pointer;
59
60static char *subst_lhs;
61static char *subst_rhs;
62static int subst_lhs_len;
63static int subst_rhs_len;
64
Jari Aaltof73dda02001-11-13 17:56:06 +000065static char *get_history_word_specifier PARAMS((char *, char *, int *));
Jari Aaltob80f6442004-07-27 13:29:18 +000066static int history_tokenize_word PARAMS((const char *, int));
Jari Aalto31859422009-01-12 13:36:28 +000067static char **history_tokenize_internal PARAMS((const char *, int, int *));
Jari Aaltob80f6442004-07-27 13:29:18 +000068static char *history_substring PARAMS((const char *, int, int));
Jari Aalto31859422009-01-12 13:36:28 +000069static void freewords PARAMS((char **, int));
70static char *history_find_word PARAMS((char *, int));
Jari Aaltoccc6cda1996-12-23 17:02:34 +000071
Jari Aaltof73dda02001-11-13 17:56:06 +000072static char *quote_breaks PARAMS((char *));
Jari Aaltoccc6cda1996-12-23 17:02:34 +000073
74/* Variables exported by this file. */
75/* The character that represents the start of a history expansion
76 request. This is usually `!'. */
77char history_expansion_char = '!';
78
79/* The character that invokes word substitution if found at the start of
80 a line. This is usually `^'. */
81char history_subst_char = '^';
82
83/* During tokenization, if this character is seen as the first character
84 of a word, then it, and all subsequent characters upto a newline are
85 ignored. For a Bourne shell, this should be '#'. Bash special cases
86 the interactive comment character to not be a comment delimiter. */
87char history_comment_char = '\0';
88
89/* The list of characters which inhibit the expansion of text if found
90 immediately following history_expansion_char. */
91char *history_no_expand_chars = " \t\n\r=";
92
93/* If set to a non-zero value, single quotes inhibit history expansion.
94 The default is 0. */
95int history_quotes_inhibit_expansion = 0;
96
Jari Aalto28ef6c32001-04-06 19:14:31 +000097/* Used to split words by history_tokenize_internal. */
98char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
99
Jari Aaltod166f041997-06-05 14:59:13 +0000100/* If set, this points to a function that is called to verify that a
101 particular history expansion should be performed. */
Jari Aalto28ef6c32001-04-06 19:14:31 +0000102rl_linebuf_func_t *history_inhibit_expansion_function;
Jari Aaltod166f041997-06-05 14:59:13 +0000103
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000104/* **************************************************************** */
105/* */
106/* History Expansion */
107/* */
108/* **************************************************************** */
109
110/* Hairy history expansion on text, not tokens. This is of general
111 use, and thus belongs in this library. */
112
113/* The last string searched for by a !?string? search. */
114static char *search_string;
115
116/* The last string matched by a !?string? search. */
117static char *search_match;
118
119/* Return the event specified at TEXT + OFFSET modifying OFFSET to
120 point to after the event specifier. Just a pointer to the history
121 line is returned; NULL is returned in the event of a bad specifier.
122 You pass STRING with *INDEX equal to the history_expansion_char that
123 begins this specification.
124 DELIMITING_QUOTE is a character that is allowed to end the string
125 specification for what to search for in addition to the normal
126 characters `:', ` ', `\t', `\n', and sometimes `?'.
127 So you might call this function like:
128 line = get_history_event ("!echo:p", &index, 0); */
129char *
130get_history_event (string, caller_index, delimiting_quote)
Jari Aalto28ef6c32001-04-06 19:14:31 +0000131 const char *string;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000132 int *caller_index;
133 int delimiting_quote;
134{
135 register int i;
136 register char c;
137 HIST_ENTRY *entry;
138 int which, sign, local_index, substring_okay;
Jari Aalto28ef6c32001-04-06 19:14:31 +0000139 _hist_search_func_t *search_func;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000140 char *temp;
141
142 /* The event can be specified in a number of ways.
143
144 !! the previous command
145 !n command line N
146 !-n current command-line minus N
147 !str the most recent command starting with STR
148 !?str[?]
149 the most recent command containing STR
150
151 All values N are determined via HISTORY_BASE. */
152
153 i = *caller_index;
154
155 if (string[i] != history_expansion_char)
156 return ((char *)NULL);
157
158 /* Move on to the specification. */
159 i++;
160
161 sign = 1;
162 substring_okay = 0;
163
164#define RETURN_ENTRY(e, w) \
165 return ((e = history_get (w)) ? e->line : (char *)NULL)
166
167 /* Handle !! case. */
168 if (string[i] == history_expansion_char)
169 {
170 i++;
171 which = history_base + (history_length - 1);
172 *caller_index = i;
173 RETURN_ENTRY (entry, which);
174 }
175
176 /* Hack case of numeric line specification. */
177 if (string[i] == '-')
178 {
179 sign = -1;
180 i++;
181 }
182
183 if (_rl_digit_p (string[i]))
184 {
185 /* Get the extent of the digits and compute the value. */
186 for (which = 0; _rl_digit_p (string[i]); i++)
187 which = (which * 10) + _rl_digit_value (string[i]);
188
189 *caller_index = i;
190
191 if (sign < 0)
192 which = (history_length + history_base) - which;
193
194 RETURN_ENTRY (entry, which);
195 }
196
197 /* This must be something to search for. If the spec begins with
198 a '?', then the string may be anywhere on the line. Otherwise,
199 the string must be found at the start of a line. */
200 if (string[i] == '?')
201 {
202 substring_okay++;
203 i++;
204 }
205
206 /* Only a closing `?' or a newline delimit a substring search string. */
207 for (local_index = i; c = string[i]; i++)
Jari Aalto95732b42005-12-07 14:08:12 +0000208 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000209#if defined (HANDLE_MULTIBYTE)
Jari Aalto95732b42005-12-07 14:08:12 +0000210 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
211 {
212 int v;
213 mbstate_t ps;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000214
Jari Aalto95732b42005-12-07 14:08:12 +0000215 memset (&ps, 0, sizeof (mbstate_t));
216 /* These produce warnings because we're passing a const string to a
217 function that takes a non-const string. */
218 _rl_adjust_point ((char *)string, i, &ps);
219 if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1)
220 {
221 i += v - 1;
222 continue;
223 }
224 }
225
Jari Aalto7117c2d2002-07-17 14:10:11 +0000226#endif /* HANDLE_MULTIBYTE */
227 if ((!substring_okay && (whitespace (c) || c == ':' ||
228 (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
229 string[i] == delimiting_quote)) ||
230 string[i] == '\n' ||
231 (substring_okay && string[i] == '?'))
232 break;
Jari Aalto95732b42005-12-07 14:08:12 +0000233 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000234
235 which = i - local_index;
Jari Aaltof73dda02001-11-13 17:56:06 +0000236 temp = (char *)xmalloc (1 + which);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000237 if (which)
238 strncpy (temp, string + local_index, which);
239 temp[which] = '\0';
240
241 if (substring_okay && string[i] == '?')
242 i++;
243
244 *caller_index = i;
245
246#define FAIL_SEARCH() \
247 do { \
Chet Ramey495aee42011-11-22 19:11:26 -0500248 history_offset = history_length; xfree (temp) ; return (char *)NULL; \
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000249 } while (0)
250
251 /* If there is no search string, try to use the previous search string,
252 if one exists. If not, fail immediately. */
253 if (*temp == '\0' && substring_okay)
254 {
255 if (search_string)
256 {
Chet Ramey495aee42011-11-22 19:11:26 -0500257 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000258 temp = savestring (search_string);
259 }
260 else
261 FAIL_SEARCH ();
262 }
263
264 search_func = substring_okay ? history_search : history_search_prefix;
265 while (1)
266 {
267 local_index = (*search_func) (temp, -1);
268
269 if (local_index < 0)
270 FAIL_SEARCH ();
271
272 if (local_index == 0 || substring_okay)
273 {
274 entry = current_history ();
Chet Rameyac50fba2014-02-26 09:36:43 -0500275 if (entry == 0)
276 FAIL_SEARCH ();
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000277 history_offset = history_length;
278
279 /* If this was a substring search, then remember the
280 string that we matched for word substitution. */
281 if (substring_okay)
282 {
283 FREE (search_string);
284 search_string = temp;
285
286 FREE (search_match);
287 search_match = history_find_word (entry->line, local_index);
288 }
289 else
Chet Ramey495aee42011-11-22 19:11:26 -0500290 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000291
292 return (entry->line);
293 }
294
295 if (history_offset)
296 history_offset--;
297 else
298 FAIL_SEARCH ();
299 }
300#undef FAIL_SEARCH
301#undef RETURN_ENTRY
302}
303
304/* Function for extracting single-quoted strings. Used for inhibiting
305 history expansion within single quotes. */
306
307/* Extract the contents of STRING as if it is enclosed in single quotes.
308 SINDEX, when passed in, is the offset of the character immediately
309 following the opening single quote; on exit, SINDEX is left pointing
Chet Ramey00018032011-11-21 20:51:19 -0500310 to the closing single quote. FLAGS currently used to allow backslash
311 to escape a single quote (e.g., for bash $'...'). */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000312static void
Chet Ramey00018032011-11-21 20:51:19 -0500313hist_string_extract_single_quoted (string, sindex, flags)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000314 char *string;
Chet Ramey00018032011-11-21 20:51:19 -0500315 int *sindex, flags;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000316{
317 register int i;
318
319 for (i = *sindex; string[i] && string[i] != '\''; i++)
Chet Ramey00018032011-11-21 20:51:19 -0500320 {
321 if ((flags & 1) && string[i] == '\\' && string[i+1])
322 i++;
323 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000324
325 *sindex = i;
326}
327
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000328static char *
329quote_breaks (s)
330 char *s;
331{
332 register char *p, *r;
333 char *ret;
334 int len = 3;
335
336 for (p = s; p && *p; p++, len++)
337 {
338 if (*p == '\'')
339 len += 3;
340 else if (whitespace (*p) || *p == '\n')
341 len += 2;
342 }
343
Jari Aaltof73dda02001-11-13 17:56:06 +0000344 r = ret = (char *)xmalloc (len);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000345 *r++ = '\'';
346 for (p = s; p && *p; )
347 {
348 if (*p == '\'')
349 {
350 *r++ = '\'';
351 *r++ = '\\';
352 *r++ = '\'';
353 *r++ = '\'';
354 p++;
355 }
356 else if (whitespace (*p) || *p == '\n')
357 {
358 *r++ = '\'';
359 *r++ = *p++;
360 *r++ = '\'';
361 }
362 else
363 *r++ = *p++;
364 }
365 *r++ = '\'';
366 *r = '\0';
367 return ret;
368}
369
370static char *
371hist_error(s, start, current, errtype)
372 char *s;
373 int start, current, errtype;
374{
Jari Aalto28ef6c32001-04-06 19:14:31 +0000375 char *temp;
376 const char *emsg;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000377 int ll, elen;
378
379 ll = current - start;
380
381 switch (errtype)
382 {
383 case EVENT_NOT_FOUND:
384 emsg = "event not found";
385 elen = 15;
386 break;
387 case BAD_WORD_SPEC:
388 emsg = "bad word specifier";
389 elen = 18;
390 break;
391 case SUBST_FAILED:
392 emsg = "substitution failed";
393 elen = 19;
394 break;
395 case BAD_MODIFIER:
396 emsg = "unrecognized history modifier";
397 elen = 29;
398 break;
Jari Aaltob72432f1999-02-19 17:11:39 +0000399 case NO_PREV_SUBST:
400 emsg = "no previous substitution";
401 elen = 24;
402 break;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000403 default:
404 emsg = "unknown expansion error";
405 elen = 23;
406 break;
407 }
408
Jari Aaltof73dda02001-11-13 17:56:06 +0000409 temp = (char *)xmalloc (ll + elen + 3);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000410 strncpy (temp, s + start, ll);
411 temp[ll] = ':';
412 temp[ll + 1] = ' ';
413 strcpy (temp + ll + 2, emsg);
414 return (temp);
415}
416
417/* Get a history substitution string from STR starting at *IPTR
418 and return it. The length is returned in LENPTR.
419
420 A backslash can quote the delimiter. If the string is the
421 empty string, the previous pattern is used. If there is
422 no previous pattern for the lhs, the last history search
423 string is used.
424
425 If IS_RHS is 1, we ignore empty strings and set the pattern
426 to "" anyway. subst_lhs is not changed if the lhs is empty;
427 subst_rhs is allowed to be set to the empty string. */
428
429static char *
430get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
431 char *str;
432 int *iptr, delimiter, is_rhs, *lenptr;
433{
434 register int si, i, j, k;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000435 char *s;
436#if defined (HANDLE_MULTIBYTE)
437 mbstate_t ps;
438#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000439
Jari Aalto7117c2d2002-07-17 14:10:11 +0000440 s = (char *)NULL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000441 i = *iptr;
442
Jari Aalto7117c2d2002-07-17 14:10:11 +0000443#if defined (HANDLE_MULTIBYTE)
444 memset (&ps, 0, sizeof (mbstate_t));
445 _rl_adjust_point (str, i, &ps);
446#endif
447
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000448 for (si = i; str[si] && str[si] != delimiter; si++)
Jari Aalto7117c2d2002-07-17 14:10:11 +0000449#if defined (HANDLE_MULTIBYTE)
450 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
451 {
452 int v;
453 if ((v = _rl_get_char_len (str + si, &ps)) > 1)
454 si += v - 1;
455 else if (str[si] == '\\' && str[si + 1] == delimiter)
456 si++;
457 }
458 else
459#endif /* HANDLE_MULTIBYTE */
460 if (str[si] == '\\' && str[si + 1] == delimiter)
461 si++;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000462
463 if (si > i || is_rhs)
464 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000465 s = (char *)xmalloc (si - i + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000466 for (j = 0, k = i; k < si; j++, k++)
467 {
468 /* Remove a backslash quoting the search string delimiter. */
469 if (str[k] == '\\' && str[k + 1] == delimiter)
470 k++;
471 s[j] = str[k];
472 }
473 s[j] = '\0';
474 if (lenptr)
475 *lenptr = j;
476 }
477
478 i = si;
479 if (str[i])
480 i++;
481 *iptr = i;
482
483 return s;
484}
485
486static void
487postproc_subst_rhs ()
488{
489 char *new;
490 int i, j, new_size;
491
Jari Aaltof73dda02001-11-13 17:56:06 +0000492 new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000493 for (i = j = 0; i < subst_rhs_len; i++)
494 {
495 if (subst_rhs[i] == '&')
496 {
497 if (j + subst_lhs_len >= new_size)
Jari Aaltof73dda02001-11-13 17:56:06 +0000498 new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000499 strcpy (new + j, subst_lhs);
500 j += subst_lhs_len;
501 }
502 else
503 {
504 /* a single backslash protects the `&' from lhs interpolation */
505 if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
506 i++;
507 if (j >= new_size)
Jari Aaltof73dda02001-11-13 17:56:06 +0000508 new = (char *)xrealloc (new, new_size *= 2);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000509 new[j++] = subst_rhs[i];
510 }
511 }
512 new[j] = '\0';
Chet Ramey495aee42011-11-22 19:11:26 -0500513 xfree (subst_rhs);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000514 subst_rhs = new;
515 subst_rhs_len = j;
516}
517
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. */
523static int
Chet Rameyac50fba2014-02-26 09:36:43 -0500524history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000525 char *string;
Chet Rameyac50fba2014-02-26 09:36:43 -0500526 int start, qc, *end_index_ptr;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000527 char **ret_string;
528 char *current_line; /* for !# */
529{
530 int i, n, starting_index;
Jari Aaltob80f6442004-07-27 13:29:18 +0000531 int substitute_globally, subst_bywords, want_quotes, print_only;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000532 char *event, *temp, *result, *tstr, *t, c, *word_spec;
533 int result_len;
Jari Aalto7117c2d2002-07-17 14:10:11 +0000534#if defined (HANDLE_MULTIBYTE)
535 mbstate_t ps;
536
537 memset (&ps, 0, sizeof (mbstate_t));
538#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000539
Jari Aaltof73dda02001-11-13 17:56:06 +0000540 result = (char *)xmalloc (result_len = 128);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000541
542 i = start;
543
544 /* If it is followed by something that starts a word specifier,
545 then !! is implied as the event specifier. */
546
547 if (member (string[i + 1], ":$*%^"))
548 {
549 char fake_s[3];
550 int fake_i = 0;
551 i++;
552 fake_s[0] = fake_s[1] = history_expansion_char;
553 fake_s[2] = '\0';
554 event = get_history_event (fake_s, &fake_i, 0);
555 }
556 else if (string[i + 1] == '#')
557 {
558 i += 2;
559 event = current_line;
560 }
561 else
Chet Rameyac50fba2014-02-26 09:36:43 -0500562 event = get_history_event (string, &i, qc);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000563
564 if (event == 0)
565 {
566 *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
Chet Ramey495aee42011-11-22 19:11:26 -0500567 xfree (result);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000568 return (-1);
569 }
570
571 /* If a word specifier is found, then do what that requires. */
572 starting_index = i;
573 word_spec = get_history_word_specifier (string, event, &i);
574
575 /* There is no such thing as a `malformed word specifier'. However,
576 it is possible for a specifier that has no match. In that case,
577 we complain. */
578 if (word_spec == (char *)&error_pointer)
579 {
580 *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
Chet Ramey495aee42011-11-22 19:11:26 -0500581 xfree (result);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000582 return (-1);
583 }
584
585 /* If no word specifier, than the thing of interest was the event. */
586 temp = word_spec ? savestring (word_spec) : savestring (event);
587 FREE (word_spec);
588
589 /* Perhaps there are other modifiers involved. Do what they say. */
Jari Aaltob80f6442004-07-27 13:29:18 +0000590 want_quotes = substitute_globally = subst_bywords = print_only = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000591 starting_index = i;
592
593 while (string[i] == ':')
594 {
595 c = string[i + 1];
596
Jari Aaltob80f6442004-07-27 13:29:18 +0000597 if (c == 'g' || c == 'a')
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000598 {
599 substitute_globally = 1;
600 i++;
601 c = string[i + 1];
602 }
Jari Aaltob80f6442004-07-27 13:29:18 +0000603 else if (c == 'G')
604 {
605 subst_bywords = 1;
606 i++;
607 c = string[i + 1];
608 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000609
610 switch (c)
611 {
612 default:
613 *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
Chet Ramey495aee42011-11-22 19:11:26 -0500614 xfree (result);
615 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000616 return -1;
617
618 case 'q':
619 want_quotes = 'q';
620 break;
621
622 case 'x':
623 want_quotes = 'x';
624 break;
625
626 /* :p means make this the last executed line. So we
627 return an error state after adding this line to the
628 history. */
629 case 'p':
630 print_only++;
631 break;
632
633 /* :t discards all but the last part of the pathname. */
634 case 't':
635 tstr = strrchr (temp, '/');
636 if (tstr)
637 {
638 tstr++;
639 t = savestring (tstr);
Chet Ramey495aee42011-11-22 19:11:26 -0500640 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000641 temp = t;
642 }
643 break;
644
645 /* :h discards the last part of a pathname. */
646 case 'h':
647 tstr = strrchr (temp, '/');
648 if (tstr)
649 *tstr = '\0';
650 break;
651
652 /* :r discards the suffix. */
653 case 'r':
654 tstr = strrchr (temp, '.');
655 if (tstr)
656 *tstr = '\0';
657 break;
658
659 /* :e discards everything but the suffix. */
660 case 'e':
661 tstr = strrchr (temp, '.');
662 if (tstr)
663 {
664 t = savestring (tstr);
Chet Ramey495aee42011-11-22 19:11:26 -0500665 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000666 temp = t;
667 }
668 break;
669
670 /* :s/this/that substitutes `that' for the first
671 occurrence of `this'. :gs/this/that substitutes `that'
672 for each occurrence of `this'. :& repeats the last
673 substitution. :g& repeats the last substitution
674 globally. */
675
676 case '&':
677 case 's':
678 {
Jari Aalto28ef6c32001-04-06 19:14:31 +0000679 char *new_event;
Jari Aaltob80f6442004-07-27 13:29:18 +0000680 int delimiter, failed, si, l_temp, ws, we;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000681
682 if (c == 's')
683 {
684 if (i + 2 < (int)strlen (string))
Jari Aalto7117c2d2002-07-17 14:10:11 +0000685 {
686#if defined (HANDLE_MULTIBYTE)
687 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
688 {
689 _rl_adjust_point (string, i + 2, &ps);
690 if (_rl_get_char_len (string + i + 2, &ps) > 1)
691 delimiter = 0;
692 else
693 delimiter = string[i + 2];
694 }
695 else
696#endif /* HANDLE_MULTIBYTE */
697 delimiter = string[i + 2];
698 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000699 else
700 break; /* no search delimiter */
701
702 i += 3;
703
704 t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
705 /* An empty substitution lhs with no previous substitution
706 uses the last search string as the lhs. */
707 if (t)
708 {
709 FREE (subst_lhs);
710 subst_lhs = t;
711 }
712 else if (!subst_lhs)
713 {
714 if (search_string && *search_string)
715 {
716 subst_lhs = savestring (search_string);
717 subst_lhs_len = strlen (subst_lhs);
718 }
719 else
720 {
721 subst_lhs = (char *) NULL;
722 subst_lhs_len = 0;
723 }
724 }
725
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000726 FREE (subst_rhs);
727 subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
728
729 /* If `&' appears in the rhs, it's supposed to be replaced
730 with the lhs. */
731 if (member ('&', subst_rhs))
732 postproc_subst_rhs ();
733 }
734 else
735 i += 2;
736
Jari Aaltob72432f1999-02-19 17:11:39 +0000737 /* If there is no lhs, the substitution can't succeed. */
738 if (subst_lhs_len == 0)
739 {
740 *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
Chet Ramey495aee42011-11-22 19:11:26 -0500741 xfree (result);
742 xfree (temp);
Jari Aaltob72432f1999-02-19 17:11:39 +0000743 return -1;
744 }
745
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000746 l_temp = strlen (temp);
747 /* Ignore impossible cases. */
748 if (subst_lhs_len > l_temp)
749 {
750 *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
Chet Ramey495aee42011-11-22 19:11:26 -0500751 xfree (result);
752 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000753 return (-1);
754 }
755
756 /* Find the first occurrence of THIS in TEMP. */
Jari Aaltob80f6442004-07-27 13:29:18 +0000757 /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
758 cases to consider:
759
760 1. substitute_globally == subst_bywords == 0
761 2. substitute_globally == 1 && subst_bywords == 0
762 3. substitute_globally == 0 && subst_bywords == 1
763
764 In the first case, we substitute for the first occurrence only.
765 In the second case, we substitute for every occurrence.
766 In the third case, we tokenize into words and substitute the
767 first occurrence of each word. */
768
769 si = we = 0;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000770 for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
Jari Aaltob80f6442004-07-27 13:29:18 +0000771 {
772 /* First skip whitespace and find word boundaries if
773 we're past the end of the word boundary we found
774 the last time. */
775 if (subst_bywords && si > we)
776 {
777 for (; temp[si] && whitespace (temp[si]); si++)
778 ;
779 ws = si;
780 we = history_tokenize_word (temp, si);
781 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000782
Jari Aaltob80f6442004-07-27 13:29:18 +0000783 if (STREQN (temp+si, subst_lhs, subst_lhs_len))
784 {
785 int len = subst_rhs_len - subst_lhs_len + l_temp;
786 new_event = (char *)xmalloc (1 + len);
787 strncpy (new_event, temp, si);
788 strncpy (new_event + si, subst_rhs, subst_rhs_len);
789 strncpy (new_event + si + subst_rhs_len,
790 temp + si + subst_lhs_len,
791 l_temp - (si + subst_lhs_len));
792 new_event[len] = '\0';
Chet Ramey495aee42011-11-22 19:11:26 -0500793 xfree (temp);
Jari Aaltob80f6442004-07-27 13:29:18 +0000794 temp = new_event;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000795
Jari Aaltob80f6442004-07-27 13:29:18 +0000796 failed = 0;
797
798 if (substitute_globally)
799 {
800 /* Reported to fix a bug that causes it to skip every
801 other match when matching a single character. Was
802 si += subst_rhs_len previously. */
803 si += subst_rhs_len - 1;
804 l_temp = strlen (temp);
805 substitute_globally++;
806 continue;
807 }
808 else if (subst_bywords)
809 {
810 si = we;
811 l_temp = strlen (temp);
812 continue;
813 }
814 else
815 break;
816 }
817 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000818
819 if (substitute_globally > 1)
820 {
821 substitute_globally = 0;
822 continue; /* don't want to increment i */
823 }
824
825 if (failed == 0)
826 continue; /* don't want to increment i */
827
828 *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
Chet Ramey495aee42011-11-22 19:11:26 -0500829 xfree (result);
830 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000831 return (-1);
832 }
833 }
834 i += 2;
835 }
Chet Rameyac50fba2014-02-26 09:36:43 -0500836 /* Done with modifiers. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000837 /* Believe it or not, we have to back the pointer up by one. */
838 --i;
839
840 if (want_quotes)
841 {
842 char *x;
843
844 if (want_quotes == 'q')
Jari Aalto28ef6c32001-04-06 19:14:31 +0000845 x = sh_single_quote (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000846 else if (want_quotes == 'x')
847 x = quote_breaks (temp);
848 else
849 x = savestring (temp);
850
Chet Ramey495aee42011-11-22 19:11:26 -0500851 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000852 temp = x;
853 }
854
855 n = strlen (temp);
856 if (n >= result_len)
Jari Aaltof73dda02001-11-13 17:56:06 +0000857 result = (char *)xrealloc (result, n + 2);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000858 strcpy (result, temp);
Chet Ramey495aee42011-11-22 19:11:26 -0500859 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000860
861 *end_index_ptr = i;
862 *ret_string = result;
863 return (print_only);
864}
865
866/* Expand the string STRING, placing the result into OUTPUT, a pointer
867 to a string. Returns:
868
869 -1) If there was an error in expansion.
870 0) If no expansions took place (or, if the only change in
871 the text was the de-slashifying of the history expansion
872 character)
873 1) If expansions did take place
874 2) If the `p' modifier was given and the caller should print the result
875
876 If an error ocurred in expansion, then OUTPUT contains a descriptive
877 error message. */
878
879#define ADD_STRING(s) \
880 do \
881 { \
882 int sl = strlen (s); \
883 j += sl; \
884 if (j >= result_len) \
885 { \
886 while (j >= result_len) \
887 result_len += 128; \
Jari Aaltof73dda02001-11-13 17:56:06 +0000888 result = (char *)xrealloc (result, result_len); \
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000889 } \
890 strcpy (result + j - sl, s); \
891 } \
892 while (0)
893
894#define ADD_CHAR(c) \
895 do \
896 { \
897 if (j >= result_len - 1) \
Jari Aaltof73dda02001-11-13 17:56:06 +0000898 result = (char *)xrealloc (result, result_len += 64); \
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000899 result[j++] = c; \
900 result[j] = '\0'; \
901 } \
902 while (0)
903
904int
905history_expand (hstring, output)
906 char *hstring;
907 char **output;
908{
909 register int j;
Chet Rameyac50fba2014-02-26 09:36:43 -0500910 int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000911 char *string;
912
913 /* The output string, and its length. */
914 int result_len;
915 char *result;
916
Jari Aalto7117c2d2002-07-17 14:10:11 +0000917#if defined (HANDLE_MULTIBYTE)
918 char mb[MB_LEN_MAX];
919 mbstate_t ps;
920#endif
921
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000922 /* Used when adding the string. */
923 char *temp;
924
Jari Aalto28ef6c32001-04-06 19:14:31 +0000925 if (output == 0)
926 return 0;
927
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000928 /* Setting the history expansion character to 0 inhibits all
929 history expansion. */
930 if (history_expansion_char == 0)
931 {
932 *output = savestring (hstring);
933 return (0);
934 }
935
936 /* Prepare the buffer for printing error messages. */
Jari Aaltof73dda02001-11-13 17:56:06 +0000937 result = (char *)xmalloc (result_len = 256);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000938 result[0] = '\0';
939
940 only_printing = modified = 0;
941 l = strlen (hstring);
942
Jari Aaltocce855b1998-04-17 19:52:44 +0000943 /* Grovel the string. Only backslash and single quotes can quote the
944 history escape character. We also handle arg specifiers. */
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000945
946 /* Before we grovel forever, see if the history_expansion_char appears
947 anywhere within the text. */
948
949 /* The quick substitution character is a history expansion all right. That
950 is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
951 that is the substitution that we do. */
952 if (hstring[0] == history_subst_char)
953 {
Jari Aaltof73dda02001-11-13 17:56:06 +0000954 string = (char *)xmalloc (l + 5);
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000955
956 string[0] = string[1] = history_expansion_char;
957 string[2] = ':';
958 string[3] = 's';
959 strcpy (string + 4, hstring);
960 l += 4;
961 }
962 else
963 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000964#if defined (HANDLE_MULTIBYTE)
965 memset (&ps, 0, sizeof (mbstate_t));
966#endif
967
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000968 string = hstring;
969 /* If not quick substitution, still maybe have to do expansion. */
970
971 /* `!' followed by one of the characters in history_no_expand_chars
972 is NOT an expansion. */
Chet Rameyac50fba2014-02-26 09:36:43 -0500973 for (i = dquote = squote = 0; string[i]; i++)
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000974 {
Jari Aalto7117c2d2002-07-17 14:10:11 +0000975#if defined (HANDLE_MULTIBYTE)
976 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
977 {
978 int v;
979 v = _rl_get_char_len (string + i, &ps);
980 if (v > 1)
981 {
982 i += v - 1;
983 continue;
984 }
985 }
986#endif /* HANDLE_MULTIBYTE */
987
Jari Aaltoccc6cda1996-12-23 17:02:34 +0000988 cc = string[i + 1];
Jari Aalto7117c2d2002-07-17 14:10:11 +0000989 /* The history_comment_char, if set, appearing at the beginning
Jari Aaltocce855b1998-04-17 19:52:44 +0000990 of a word signifies that the rest of the line should not have
991 history expansion performed on it.
992 Skip the rest of the line and break out of the loop. */
993 if (history_comment_char && string[i] == history_comment_char &&
Jari Aalto28ef6c32001-04-06 19:14:31 +0000994 (i == 0 || member (string[i - 1], history_word_delimiters)))
Jari Aaltocce855b1998-04-17 19:52:44 +0000995 {
996 while (string[i])
997 i++;
998 break;
999 }
1000 else if (string[i] == history_expansion_char)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001001 {
Jari Aalto17345e52009-02-19 22:21:29 +00001002 if (cc == 0 || member (cc, history_no_expand_chars))
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001003 continue;
Chet Rameyac50fba2014-02-26 09:36:43 -05001004 /* DQUOTE won't be set unless history_quotes_inhibit_expansion
1005 is set. The idea here is to treat double-quoted strings the
1006 same as the word outside double quotes; in effect making the
1007 double quote part of history_no_expand_chars when DQUOTE is
1008 set. */
1009 else if (dquote && cc == '"')
1010 continue;
Jari Aaltod166f041997-06-05 14:59:13 +00001011 /* If the calling application has set
1012 history_inhibit_expansion_function to a function that checks
1013 for special cases that should not be history expanded,
1014 call the function and skip the expansion if it returns a
1015 non-zero value. */
1016 else if (history_inhibit_expansion_function &&
1017 (*history_inhibit_expansion_function) (string, i))
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001018 continue;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001019 else
1020 break;
1021 }
Jari Aaltob80f6442004-07-27 13:29:18 +00001022 /* Shell-like quoting: allow backslashes to quote double quotes
1023 inside a double-quoted string. */
1024 else if (dquote && string[i] == '\\' && cc == '"')
1025 i++;
1026 /* More shell-like quoting: if we're paying attention to single
1027 quotes and letting them quote the history expansion character,
1028 then we need to pay attention to double quotes, because single
1029 quotes are not special inside double-quoted strings. */
1030 else if (history_quotes_inhibit_expansion && string[i] == '"')
1031 {
1032 dquote = 1 - dquote;
1033 }
1034 else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001035 {
1036 /* If this is bash, single quotes inhibit history expansion. */
Chet Ramey00018032011-11-21 20:51:19 -05001037 flag = (i > 0 && string[i - 1] == '$');
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001038 i++;
Chet Ramey00018032011-11-21 20:51:19 -05001039 hist_string_extract_single_quoted (string, &i, flag);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001040 }
1041 else if (history_quotes_inhibit_expansion && string[i] == '\\')
1042 {
1043 /* If this is bash, allow backslashes to quote single
1044 quotes and the history expansion character. */
1045 if (cc == '\'' || cc == history_expansion_char)
1046 i++;
1047 }
Jari Aaltob80f6442004-07-27 13:29:18 +00001048
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001049 }
1050
1051 if (string[i] != history_expansion_char)
1052 {
Chet Ramey495aee42011-11-22 19:11:26 -05001053 xfree (result);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001054 *output = savestring (string);
1055 return (0);
1056 }
1057 }
1058
1059 /* Extract and perform the substitution. */
Chet Rameyac50fba2014-02-26 09:36:43 -05001060 for (passc = dquote = squote = i = j = 0; i < l; i++)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001061 {
Chet Rameyac50fba2014-02-26 09:36:43 -05001062 int qc, tchar = string[i];
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001063
1064 if (passc)
1065 {
1066 passc = 0;
1067 ADD_CHAR (tchar);
1068 continue;
1069 }
1070
Jari Aalto7117c2d2002-07-17 14:10:11 +00001071#if defined (HANDLE_MULTIBYTE)
1072 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1073 {
1074 int k, c;
1075
1076 c = tchar;
1077 memset (mb, 0, sizeof (mb));
1078 for (k = 0; k < MB_LEN_MAX; k++)
1079 {
1080 mb[k] = (char)c;
1081 memset (&ps, 0, sizeof (mbstate_t));
1082 if (_rl_get_char_len (mb, &ps) == -2)
1083 c = string[++i];
1084 else
1085 break;
1086 }
1087 if (strlen (mb) > 1)
1088 {
1089 ADD_STRING (mb);
Chet Ramey00018032011-11-21 20:51:19 -05001090 continue;
Jari Aalto7117c2d2002-07-17 14:10:11 +00001091 }
1092 }
1093#endif /* HANDLE_MULTIBYTE */
1094
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001095 if (tchar == history_expansion_char)
1096 tchar = -3;
Jari Aaltocce855b1998-04-17 19:52:44 +00001097 else if (tchar == history_comment_char)
1098 tchar = -2;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001099
1100 switch (tchar)
1101 {
1102 default:
1103 ADD_CHAR (string[i]);
1104 break;
1105
1106 case '\\':
1107 passc++;
1108 ADD_CHAR (tchar);
1109 break;
1110
Jari Aaltob80f6442004-07-27 13:29:18 +00001111 case '"':
1112 dquote = 1 - dquote;
1113 ADD_CHAR (tchar);
1114 break;
1115
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001116 case '\'':
1117 {
1118 /* If history_quotes_inhibit_expansion is set, single quotes
Chet Rameyac50fba2014-02-26 09:36:43 -05001119 inhibit history expansion, otherwise they are treated like
1120 double quotes. */
1121 if (squote)
1122 {
1123 squote = 0;
1124 ADD_CHAR (tchar);
1125 }
1126 else if (dquote == 0 && history_quotes_inhibit_expansion)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001127 {
1128 int quote, slen;
1129
Chet Ramey00018032011-11-21 20:51:19 -05001130 flag = (i > 0 && string[i - 1] == '$');
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001131 quote = i++;
Chet Ramey00018032011-11-21 20:51:19 -05001132 hist_string_extract_single_quoted (string, &i, flag);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001133
1134 slen = i - quote + 2;
Jari Aaltof73dda02001-11-13 17:56:06 +00001135 temp = (char *)xmalloc (slen);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001136 strncpy (temp, string + quote, slen);
1137 temp[slen - 1] = '\0';
1138 ADD_STRING (temp);
Chet Ramey495aee42011-11-22 19:11:26 -05001139 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001140 }
Chet Rameyac50fba2014-02-26 09:36:43 -05001141 else if (dquote == 0 && squote == 0 && history_quotes_inhibit_expansion == 0)
1142 {
1143 squote = 1;
1144 ADD_CHAR (string[i]);
1145 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001146 else
1147 ADD_CHAR (string[i]);
1148 break;
1149 }
1150
Jari Aaltocce855b1998-04-17 19:52:44 +00001151 case -2: /* history_comment_char */
Jari Aalto28ef6c32001-04-06 19:14:31 +00001152 if (i == 0 || member (string[i - 1], history_word_delimiters))
Jari Aaltocce855b1998-04-17 19:52:44 +00001153 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001154 temp = (char *)xmalloc (l - i + 1);
Jari Aaltocce855b1998-04-17 19:52:44 +00001155 strcpy (temp, string + i);
1156 ADD_STRING (temp);
Chet Ramey495aee42011-11-22 19:11:26 -05001157 xfree (temp);
Jari Aaltocce855b1998-04-17 19:52:44 +00001158 i = l;
1159 }
1160 else
1161 ADD_CHAR (string[i]);
1162 break;
1163
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001164 case -3: /* history_expansion_char */
1165 cc = string[i + 1];
1166
1167 /* If the history_expansion_char is followed by one of the
1168 characters in history_no_expand_chars, then it is not a
1169 candidate for expansion of any kind. */
Jari Aalto17345e52009-02-19 22:21:29 +00001170 if (cc == 0 || member (cc, history_no_expand_chars) ||
Chet Rameyac50fba2014-02-26 09:36:43 -05001171 (dquote && cc == '"') ||
Jari Aalto17345e52009-02-19 22:21:29 +00001172 (history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i)))
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001173 {
1174 ADD_CHAR (string[i]);
1175 break;
1176 }
1177
1178#if defined (NO_BANG_HASH_MODIFIERS)
1179 /* There is something that is listed as a `word specifier' in csh
1180 documentation which means `the expanded text to this point'.
1181 That is not a word specifier, it is an event specifier. If we
1182 don't want to allow modifiers with `!#', just stick the current
1183 output line in again. */
1184 if (cc == '#')
1185 {
1186 if (result)
1187 {
Jari Aaltof73dda02001-11-13 17:56:06 +00001188 temp = (char *)xmalloc (1 + strlen (result));
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001189 strcpy (temp, result);
1190 ADD_STRING (temp);
Chet Ramey495aee42011-11-22 19:11:26 -05001191 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001192 }
1193 i++;
1194 break;
1195 }
1196#endif
Chet Rameyac50fba2014-02-26 09:36:43 -05001197 qc = squote ? '\'' : (dquote ? '"' : 0);
1198 r = history_expand_internal (string, i, qc, &eindex, &temp, result);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001199 if (r < 0)
1200 {
1201 *output = temp;
Chet Ramey495aee42011-11-22 19:11:26 -05001202 xfree (result);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001203 if (string != hstring)
Chet Ramey495aee42011-11-22 19:11:26 -05001204 xfree (string);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001205 return -1;
1206 }
1207 else
1208 {
1209 if (temp)
1210 {
1211 modified++;
1212 if (*temp)
1213 ADD_STRING (temp);
Chet Ramey495aee42011-11-22 19:11:26 -05001214 xfree (temp);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001215 }
1216 only_printing = r == 1;
1217 i = eindex;
1218 }
1219 break;
1220 }
1221 }
1222
1223 *output = result;
1224 if (string != hstring)
Chet Ramey495aee42011-11-22 19:11:26 -05001225 xfree (string);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001226
1227 if (only_printing)
1228 {
Jari Aaltob80f6442004-07-27 13:29:18 +00001229#if 0
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001230 add_history (result);
Jari Aaltob80f6442004-07-27 13:29:18 +00001231#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001232 return (2);
1233 }
1234
1235 return (modified != 0);
1236}
1237
1238/* Return a consed string which is the word specified in SPEC, and found
1239 in FROM. NULL is returned if there is no spec. The address of
1240 ERROR_POINTER is returned if the word specified cannot be found.
1241 CALLER_INDEX is the offset in SPEC to start looking; it is updated
1242 to point to just after the last character parsed. */
1243static char *
1244get_history_word_specifier (spec, from, caller_index)
1245 char *spec, *from;
1246 int *caller_index;
1247{
1248 register int i = *caller_index;
1249 int first, last;
1250 int expecting_word_spec = 0;
1251 char *result;
1252
1253 /* The range of words to return doesn't exist yet. */
1254 first = last = 0;
1255 result = (char *)NULL;
1256
1257 /* If we found a colon, then this *must* be a word specification. If
1258 it isn't, then it is an error. */
1259 if (spec[i] == ':')
1260 {
1261 i++;
1262 expecting_word_spec++;
1263 }
1264
1265 /* Handle special cases first. */
1266
1267 /* `%' is the word last searched for. */
1268 if (spec[i] == '%')
1269 {
1270 *caller_index = i + 1;
1271 return (search_match ? savestring (search_match) : savestring (""));
1272 }
1273
1274 /* `*' matches all of the arguments, but not the command. */
1275 if (spec[i] == '*')
1276 {
1277 *caller_index = i + 1;
1278 result = history_arg_extract (1, '$', from);
1279 return (result ? result : savestring (""));
1280 }
1281
1282 /* `$' is last arg. */
1283 if (spec[i] == '$')
1284 {
1285 *caller_index = i + 1;
1286 return (history_arg_extract ('$', '$', from));
1287 }
1288
1289 /* Try to get FIRST and LAST figured out. */
1290
1291 if (spec[i] == '-')
1292 first = 0;
1293 else if (spec[i] == '^')
Jari Aaltob80f6442004-07-27 13:29:18 +00001294 {
1295 first = 1;
1296 i++;
1297 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001298 else if (_rl_digit_p (spec[i]) && expecting_word_spec)
1299 {
1300 for (first = 0; _rl_digit_p (spec[i]); i++)
1301 first = (first * 10) + _rl_digit_value (spec[i]);
1302 }
1303 else
1304 return ((char *)NULL); /* no valid `first' for word specifier */
1305
1306 if (spec[i] == '^' || spec[i] == '*')
1307 {
1308 last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
1309 i++;
1310 }
1311 else if (spec[i] != '-')
1312 last = first;
1313 else
1314 {
1315 i++;
1316
1317 if (_rl_digit_p (spec[i]))
1318 {
1319 for (last = 0; _rl_digit_p (spec[i]); i++)
1320 last = (last * 10) + _rl_digit_value (spec[i]);
1321 }
1322 else if (spec[i] == '$')
1323 {
1324 i++;
1325 last = '$';
1326 }
Jari Aaltof73dda02001-11-13 17:56:06 +00001327#if 0
1328 else if (!spec[i] || spec[i] == ':')
1329 /* check against `:' because there could be a modifier separator */
1330#else
1331 else
1332 /* csh seems to allow anything to terminate the word spec here,
1333 leaving it as an abbreviation. */
1334#endif
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001335 last = -1; /* x- abbreviates x-$ omitting word `$' */
1336 }
1337
1338 *caller_index = i;
1339
1340 if (last >= first || last == '$' || last < 0)
1341 result = history_arg_extract (first, last, from);
1342
1343 return (result ? result : (char *)&error_pointer);
1344}
1345
1346/* Extract the args specified, starting at FIRST, and ending at LAST.
1347 The args are taken from STRING. If either FIRST or LAST is < 0,
1348 then make that arg count from the right (subtract from the number of
1349 tokens, so that FIRST = -1 means the next to last token on the line).
1350 If LAST is `$' the last arg from STRING is used. */
1351char *
1352history_arg_extract (first, last, string)
1353 int first, last;
Jari Aalto28ef6c32001-04-06 19:14:31 +00001354 const char *string;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001355{
1356 register int i, len;
1357 char *result;
1358 int size, offset;
1359 char **list;
1360
1361 /* XXX - think about making history_tokenize return a struct array,
1362 each struct in array being a string and a length to avoid the
1363 calls to strlen below. */
1364 if ((list = history_tokenize (string)) == NULL)
1365 return ((char *)NULL);
1366
1367 for (len = 0; list[len]; len++)
1368 ;
1369
1370 if (last < 0)
1371 last = len + last - 1;
1372
1373 if (first < 0)
1374 first = len + first - 1;
1375
1376 if (last == '$')
1377 last = len - 1;
1378
1379 if (first == '$')
1380 first = len - 1;
1381
1382 last++;
1383
1384 if (first >= len || last > len || first < 0 || last < 0 || first > last)
1385 result = ((char *)NULL);
1386 else
1387 {
1388 for (size = 0, i = first; i < last; i++)
1389 size += strlen (list[i]) + 1;
Jari Aaltof73dda02001-11-13 17:56:06 +00001390 result = (char *)xmalloc (size + 1);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001391 result[0] = '\0';
1392
1393 for (i = first, offset = 0; i < last; i++)
1394 {
1395 strcpy (result + offset, list[i]);
1396 offset += strlen (list[i]);
1397 if (i + 1 < last)
1398 {
1399 result[offset++] = ' ';
1400 result[offset] = 0;
1401 }
1402 }
1403 }
1404
1405 for (i = 0; i < len; i++)
Chet Ramey495aee42011-11-22 19:11:26 -05001406 xfree (list[i]);
1407 xfree (list);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001408
1409 return (result);
1410}
1411
Jari Aaltob80f6442004-07-27 13:29:18 +00001412static int
1413history_tokenize_word (string, ind)
1414 const char *string;
1415 int ind;
1416{
1417 register int i;
Chet Ramey495aee42011-11-22 19:11:26 -05001418 int delimiter, nestdelim, delimopen;
Jari Aaltob80f6442004-07-27 13:29:18 +00001419
1420 i = ind;
Chet Ramey495aee42011-11-22 19:11:26 -05001421 delimiter = nestdelim = 0;
Jari Aaltob80f6442004-07-27 13:29:18 +00001422
1423 if (member (string[i], "()\n"))
1424 {
1425 i++;
1426 return i;
1427 }
1428
1429 if (member (string[i], "<>;&|$"))
1430 {
1431 int peek = string[i + 1];
1432
1433 if (peek == string[i] && peek != '$')
1434 {
1435 if (peek == '<' && string[i + 2] == '-')
1436 i++;
Jari Aalto06285672006-10-10 14:15:34 +00001437 else if (peek == '<' && string[i + 2] == '<')
1438 i++;
Jari Aaltob80f6442004-07-27 13:29:18 +00001439 i += 2;
1440 return i;
1441 }
Chet Ramey00018032011-11-21 20:51:19 -05001442 else if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
Chet Ramey495aee42011-11-22 19:11:26 -05001443 (peek == '>' && string[i] == '&'))
Jari Aaltob80f6442004-07-27 13:29:18 +00001444 {
Chet Ramey00018032011-11-21 20:51:19 -05001445 i += 2;
1446 return i;
Jari Aaltob80f6442004-07-27 13:29:18 +00001447 }
Chet Ramey495aee42011-11-22 19:11:26 -05001448 /* XXX - separated out for later -- bash-4.2 */
1449 else if ((peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
1450 (peek == '(' && string[i] == '$')) /*)*/
1451 {
1452 i += 2;
1453 delimopen = '(';
1454 delimiter = ')';
1455 nestdelim = 1;
1456 goto get_word;
1457 }
Chet Ramey00018032011-11-21 20:51:19 -05001458#if 0
1459 else if (peek == '\'' && string[i] == '$')
1460 {
1461 i += 2; /* XXX */
1462 return i;
1463 }
1464#endif
Jari Aaltob80f6442004-07-27 13:29:18 +00001465
1466 if (string[i] != '$')
1467 {
1468 i++;
1469 return i;
1470 }
1471 }
1472
Chet Ramey495aee42011-11-22 19:11:26 -05001473 /* same code also used for $(...)/<(...)/>(...) above */
1474 if (member (string[i], "!@?+*"))
1475 {
1476 int peek = string[i + 1];
1477
1478 if (peek == '(') /*)*/
1479 {
1480 /* Shell extended globbing patterns */
1481 i += 2;
1482 delimopen = '(';
1483 delimiter = ')'; /* XXX - not perfect */
1484 nestdelim = 1;
1485 }
1486 }
1487
1488get_word:
Jari Aaltob80f6442004-07-27 13:29:18 +00001489 /* Get word from string + i; */
1490
Chet Ramey495aee42011-11-22 19:11:26 -05001491 if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS))
Jari Aaltob80f6442004-07-27 13:29:18 +00001492 delimiter = string[i++];
1493
1494 for (; string[i]; i++)
1495 {
1496 if (string[i] == '\\' && string[i + 1] == '\n')
1497 {
1498 i++;
1499 continue;
1500 }
1501
1502 if (string[i] == '\\' && delimiter != '\'' &&
1503 (delimiter != '"' || member (string[i], slashify_in_quotes)))
1504 {
1505 i++;
1506 continue;
1507 }
1508
Chet Ramey495aee42011-11-22 19:11:26 -05001509 /* delimiter must be set and set to something other than a quote if
1510 nestdelim is set, so these tests are safe. */
1511 if (nestdelim && string[i] == delimopen)
1512 {
1513 nestdelim++;
1514 continue;
1515 }
1516 if (nestdelim && string[i] == delimiter)
1517 {
1518 nestdelim--;
1519 if (nestdelim == 0)
1520 delimiter = 0;
1521 continue;
1522 }
1523
Jari Aaltob80f6442004-07-27 13:29:18 +00001524 if (delimiter && string[i] == delimiter)
1525 {
1526 delimiter = 0;
1527 continue;
1528 }
1529
Chet Ramey495aee42011-11-22 19:11:26 -05001530 if (delimiter == 0 && (member (string[i], history_word_delimiters)))
Jari Aaltob80f6442004-07-27 13:29:18 +00001531 break;
1532
Chet Ramey495aee42011-11-22 19:11:26 -05001533 if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS))
Jari Aaltob80f6442004-07-27 13:29:18 +00001534 delimiter = string[i];
1535 }
1536
1537 return i;
1538}
1539
1540static char *
1541history_substring (string, start, end)
1542 const char *string;
1543 int start, end;
1544{
1545 register int len;
1546 register char *result;
1547
1548 len = end - start;
1549 result = (char *)xmalloc (len + 1);
1550 strncpy (result, string + start, len);
1551 result[len] = '\0';
1552 return result;
1553}
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001554
1555/* Parse STRING into tokens and return an array of strings. If WIND is
1556 not -1 and INDP is not null, we also want the word surrounding index
1557 WIND. The position in the returned array of strings is returned in
1558 *INDP. */
1559static char **
1560history_tokenize_internal (string, wind, indp)
Jari Aalto28ef6c32001-04-06 19:14:31 +00001561 const char *string;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001562 int wind, *indp;
1563{
1564 char **result;
1565 register int i, start, result_index, size;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001566
Jari Aalto28ef6c32001-04-06 19:14:31 +00001567 /* If we're searching for a string that's not part of a word (e.g., " "),
1568 make sure we set *INDP to a reasonable value. */
1569 if (indp && wind != -1)
1570 *indp = -1;
1571
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001572 /* Get a token, and stuff it into RESULT. The tokens are split
1573 exactly where the shell would split them. */
1574 for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
1575 {
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001576 /* Skip leading whitespace. */
1577 for (; string[i] && whitespace (string[i]); i++)
1578 ;
1579 if (string[i] == 0 || string[i] == history_comment_char)
1580 return (result);
1581
1582 start = i;
Jari Aaltob80f6442004-07-27 13:29:18 +00001583
1584 i = history_tokenize_word (string, start);
1585
1586 /* If we have a non-whitespace delimiter character (which would not be
1587 skipped by the loop above), use it and any adjacent delimiters to
1588 make a separate field. Any adjacent white space will be skipped the
1589 next time through the loop. */
1590 if (i == start && history_word_delimiters)
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001591 {
1592 i++;
Jari Aaltob80f6442004-07-27 13:29:18 +00001593 while (string[i] && member (string[i], history_word_delimiters))
1594 i++;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001595 }
1596
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001597 /* If we are looking for the word in which the character at a
1598 particular index falls, remember it. */
1599 if (indp && wind != -1 && wind >= start && wind < i)
1600 *indp = result_index;
1601
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001602 if (result_index + 2 >= size)
1603 result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
Jari Aaltob80f6442004-07-27 13:29:18 +00001604
1605 result[result_index++] = history_substring (string, start, i);
1606 result[result_index] = (char *)NULL;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001607 }
1608
1609 return (result);
1610}
1611
1612/* Return an array of tokens, much as the shell might. The tokens are
1613 parsed out of STRING. */
1614char **
1615history_tokenize (string)
Jari Aalto28ef6c32001-04-06 19:14:31 +00001616 const char *string;
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001617{
1618 return (history_tokenize_internal (string, -1, (int *)NULL));
1619}
1620
Jari Aalto31859422009-01-12 13:36:28 +00001621/* Free members of WORDS from START to an empty string */
1622static void
1623freewords (words, start)
1624 char **words;
1625 int start;
1626{
1627 register int i;
1628
1629 for (i = start; words[i]; i++)
Chet Ramey495aee42011-11-22 19:11:26 -05001630 xfree (words[i]);
Jari Aalto31859422009-01-12 13:36:28 +00001631}
1632
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001633/* Find and return the word which contains the character at index IND
1634 in the history line LINE. Used to save the word matched by the
1635 last history !?string? search. */
1636static char *
1637history_find_word (line, ind)
1638 char *line;
1639 int ind;
1640{
1641 char **words, *s;
1642 int i, wind;
1643
1644 words = history_tokenize_internal (line, ind, &wind);
Jari Aalto28ef6c32001-04-06 19:14:31 +00001645 if (wind == -1 || words == 0)
Jari Aalto31859422009-01-12 13:36:28 +00001646 {
1647 if (words)
1648 freewords (words, 0);
1649 FREE (words);
1650 return ((char *)NULL);
1651 }
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001652 s = words[wind];
1653 for (i = 0; i < wind; i++)
Chet Ramey495aee42011-11-22 19:11:26 -05001654 xfree (words[i]);
Jari Aalto31859422009-01-12 13:36:28 +00001655 freewords (words, wind + 1);
Chet Ramey495aee42011-11-22 19:11:26 -05001656 xfree (words);
Jari Aaltoccc6cda1996-12-23 17:02:34 +00001657 return s;
1658}