fc133036493d826d436c732b06ced22551202b29
[deliverable/binutils-gdb.git] / readline / histexpand.c
1 /* histexpand.c -- history expansion. */
2
3 /* Copyright (C) 1989-2012 Free Software Foundation, Inc.
4
5 This file contains the GNU History Library (History), a set of
6 routines for managing the text of previously typed lines.
7
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.
12
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.
17
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/>.
20 */
21
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)
37 # ifndef _MINIX
38 # include <sys/types.h>
39 # endif
40 # include <unistd.h>
41 #endif
42
43 #include "rlmbutil.h"
44
45 #include "history.h"
46 #include "histlib.h"
47
48 #include "rlshell.h"
49 #include "xmalloc.h"
50
51 #define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
52 #define HISTORY_QUOTE_CHARACTERS "\"'`"
53 #define HISTORY_EVENT_DELIMITERS "^$*%-"
54
55 #define slashify_in_quotes "\\`\"$"
56
57 typedef int _hist_search_func_t PARAMS((const char *, int));
58
59 static char error_pointer;
60
61 static char *subst_lhs;
62 static char *subst_rhs;
63 static int subst_lhs_len;
64 static int subst_rhs_len;
65
66 /* Characters that delimit history event specifications and separate event
67 specifications from word designators. Static for now */
68 static char *history_event_delimiter_chars = HISTORY_EVENT_DELIMITERS;
69
70 static char *get_history_word_specifier PARAMS((char *, char *, int *));
71 static int history_tokenize_word PARAMS((const char *, int));
72 static char **history_tokenize_internal PARAMS((const char *, int, int *));
73 static char *history_substring PARAMS((const char *, int, int));
74 static void freewords PARAMS((char **, int));
75 static char *history_find_word PARAMS((char *, int));
76
77 static char *quote_breaks PARAMS((char *));
78
79 /* Variables exported by this file. */
80 /* The character that represents the start of a history expansion
81 request. This is usually `!'. */
82 char history_expansion_char = '!';
83
84 /* The character that invokes word substitution if found at the start of
85 a line. This is usually `^'. */
86 char history_subst_char = '^';
87
88 /* During tokenization, if this character is seen as the first character
89 of a word, then it, and all subsequent characters upto a newline are
90 ignored. For a Bourne shell, this should be '#'. Bash special cases
91 the interactive comment character to not be a comment delimiter. */
92 char history_comment_char = '\0';
93
94 /* The list of characters which inhibit the expansion of text if found
95 immediately following history_expansion_char. */
96 char *history_no_expand_chars = " \t\n\r=";
97
98 /* If set to a non-zero value, single quotes inhibit history expansion.
99 The default is 0. */
100 int history_quotes_inhibit_expansion = 0;
101
102 /* Used to split words by history_tokenize_internal. */
103 char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
104
105 /* If set, this points to a function that is called to verify that a
106 particular history expansion should be performed. */
107 rl_linebuf_func_t *history_inhibit_expansion_function;
108
109 /* **************************************************************** */
110 /* */
111 /* History Expansion */
112 /* */
113 /* **************************************************************** */
114
115 /* Hairy history expansion on text, not tokens. This is of general
116 use, and thus belongs in this library. */
117
118 /* The last string searched for by a !?string? search. */
119 static char *search_string;
120 /* The last string matched by a !?string? search. */
121 static char *search_match;
122
123 /* Return the event specified at TEXT + OFFSET modifying OFFSET to
124 point to after the event specifier. Just a pointer to the history
125 line is returned; NULL is returned in the event of a bad specifier.
126 You pass STRING with *INDEX equal to the history_expansion_char that
127 begins this specification.
128 DELIMITING_QUOTE is a character that is allowed to end the string
129 specification for what to search for in addition to the normal
130 characters `:', ` ', `\t', `\n', and sometimes `?'.
131 So you might call this function like:
132 line = get_history_event ("!echo:p", &index, 0); */
133 char *
134 get_history_event (string, caller_index, delimiting_quote)
135 const char *string;
136 int *caller_index;
137 int delimiting_quote;
138 {
139 register int i;
140 register char c;
141 HIST_ENTRY *entry;
142 int which, sign, local_index, substring_okay;
143 _hist_search_func_t *search_func;
144 char *temp;
145
146 /* The event can be specified in a number of ways.
147
148 !! the previous command
149 !n command line N
150 !-n current command-line minus N
151 !str the most recent command starting with STR
152 !?str[?]
153 the most recent command containing STR
154
155 All values N are determined via HISTORY_BASE. */
156
157 i = *caller_index;
158
159 if (string[i] != history_expansion_char)
160 return ((char *)NULL);
161
162 /* Move on to the specification. */
163 i++;
164
165 sign = 1;
166 substring_okay = 0;
167
168 #define RETURN_ENTRY(e, w) \
169 return ((e = history_get (w)) ? e->line : (char *)NULL)
170
171 /* Handle !! case. */
172 if (string[i] == history_expansion_char)
173 {
174 i++;
175 which = history_base + (history_length - 1);
176 *caller_index = i;
177 RETURN_ENTRY (entry, which);
178 }
179
180 /* Hack case of numeric line specification. */
181 if (string[i] == '-')
182 {
183 sign = -1;
184 i++;
185 }
186
187 if (_rl_digit_p (string[i]))
188 {
189 /* Get the extent of the digits and compute the value. */
190 for (which = 0; _rl_digit_p (string[i]); i++)
191 which = (which * 10) + _rl_digit_value (string[i]);
192
193 *caller_index = i;
194
195 if (sign < 0)
196 which = (history_length + history_base) - which;
197
198 RETURN_ENTRY (entry, which);
199 }
200
201 /* This must be something to search for. If the spec begins with
202 a '?', then the string may be anywhere on the line. Otherwise,
203 the string must be found at the start of a line. */
204 if (string[i] == '?')
205 {
206 substring_okay++;
207 i++;
208 }
209
210 /* Only a closing `?' or a newline delimit a substring search string. */
211 for (local_index = i; c = string[i]; i++)
212 {
213 #if defined (HANDLE_MULTIBYTE)
214 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
215 {
216 int v;
217 mbstate_t ps;
218
219 memset (&ps, 0, sizeof (mbstate_t));
220 /* These produce warnings because we're passing a const string to a
221 function that takes a non-const string. */
222 _rl_adjust_point ((char *)string, i, &ps);
223 if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1)
224 {
225 i += v - 1;
226 continue;
227 }
228 }
229
230 #endif /* HANDLE_MULTIBYTE */
231 if ((!substring_okay && (whitespace (c) || c == ':' ||
232 (history_event_delimiter_chars && member (c, history_event_delimiter_chars)) ||
233 (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
234 string[i] == delimiting_quote)) ||
235 string[i] == '\n' ||
236 (substring_okay && string[i] == '?'))
237 break;
238 }
239
240 which = i - local_index;
241 temp = (char *)xmalloc (1 + which);
242 if (which)
243 strncpy (temp, string + local_index, which);
244 temp[which] = '\0';
245
246 if (substring_okay && string[i] == '?')
247 i++;
248
249 *caller_index = i;
250
251 #define FAIL_SEARCH() \
252 do { \
253 history_offset = history_length; xfree (temp) ; return (char *)NULL; \
254 } while (0)
255
256 /* If there is no search string, try to use the previous search string,
257 if one exists. If not, fail immediately. */
258 if (*temp == '\0' && substring_okay)
259 {
260 if (search_string)
261 {
262 xfree (temp);
263 temp = savestring (search_string);
264 }
265 else
266 FAIL_SEARCH ();
267 }
268
269 search_func = substring_okay ? history_search : history_search_prefix;
270 while (1)
271 {
272 local_index = (*search_func) (temp, -1);
273
274 if (local_index < 0)
275 FAIL_SEARCH ();
276
277 if (local_index == 0 || substring_okay)
278 {
279 entry = current_history ();
280 if (entry == 0)
281 FAIL_SEARCH ();
282 history_offset = history_length;
283
284 /* If this was a substring search, then remember the
285 string that we matched for word substitution. */
286 if (substring_okay)
287 {
288 FREE (search_string);
289 search_string = temp;
290
291 FREE (search_match);
292 search_match = history_find_word (entry->line, local_index);
293 }
294 else
295 xfree (temp);
296
297 return (entry->line);
298 }
299
300 if (history_offset)
301 history_offset--;
302 else
303 FAIL_SEARCH ();
304 }
305 #undef FAIL_SEARCH
306 #undef RETURN_ENTRY
307 }
308
309 /* Function for extracting single-quoted strings. Used for inhibiting
310 history expansion within single quotes. */
311
312 /* Extract the contents of STRING as if it is enclosed in single quotes.
313 SINDEX, when passed in, is the offset of the character immediately
314 following the opening single quote; on exit, SINDEX is left pointing
315 to the closing single quote. FLAGS currently used to allow backslash
316 to escape a single quote (e.g., for bash $'...'). */
317 static void
318 hist_string_extract_single_quoted (string, sindex, flags)
319 char *string;
320 int *sindex, flags;
321 {
322 register int i;
323
324 for (i = *sindex; string[i] && string[i] != '\''; i++)
325 {
326 if ((flags & 1) && string[i] == '\\' && string[i+1])
327 i++;
328 }
329
330 *sindex = i;
331 }
332
333 static char *
334 quote_breaks (s)
335 char *s;
336 {
337 register char *p, *r;
338 char *ret;
339 int len = 3;
340
341 for (p = s; p && *p; p++, len++)
342 {
343 if (*p == '\'')
344 len += 3;
345 else if (whitespace (*p) || *p == '\n')
346 len += 2;
347 }
348
349 r = ret = (char *)xmalloc (len);
350 *r++ = '\'';
351 for (p = s; p && *p; )
352 {
353 if (*p == '\'')
354 {
355 *r++ = '\'';
356 *r++ = '\\';
357 *r++ = '\'';
358 *r++ = '\'';
359 p++;
360 }
361 else if (whitespace (*p) || *p == '\n')
362 {
363 *r++ = '\'';
364 *r++ = *p++;
365 *r++ = '\'';
366 }
367 else
368 *r++ = *p++;
369 }
370 *r++ = '\'';
371 *r = '\0';
372 return ret;
373 }
374
375 static char *
376 hist_error(s, start, current, errtype)
377 char *s;
378 int start, current, errtype;
379 {
380 char *temp;
381 const char *emsg;
382 int ll, elen;
383
384 ll = current - start;
385
386 switch (errtype)
387 {
388 case EVENT_NOT_FOUND:
389 emsg = "event not found";
390 elen = 15;
391 break;
392 case BAD_WORD_SPEC:
393 emsg = "bad word specifier";
394 elen = 18;
395 break;
396 case SUBST_FAILED:
397 emsg = "substitution failed";
398 elen = 19;
399 break;
400 case BAD_MODIFIER:
401 emsg = "unrecognized history modifier";
402 elen = 29;
403 break;
404 case NO_PREV_SUBST:
405 emsg = "no previous substitution";
406 elen = 24;
407 break;
408 default:
409 emsg = "unknown expansion error";
410 elen = 23;
411 break;
412 }
413
414 temp = (char *)xmalloc (ll + elen + 3);
415 strncpy (temp, s + start, ll);
416 temp[ll] = ':';
417 temp[ll + 1] = ' ';
418 strcpy (temp + ll + 2, emsg);
419 return (temp);
420 }
421
422 /* Get a history substitution string from STR starting at *IPTR
423 and return it. The length is returned in LENPTR.
424
425 A backslash can quote the delimiter. If the string is the
426 empty string, the previous pattern is used. If there is
427 no previous pattern for the lhs, the last history search
428 string is used.
429
430 If IS_RHS is 1, we ignore empty strings and set the pattern
431 to "" anyway. subst_lhs is not changed if the lhs is empty;
432 subst_rhs is allowed to be set to the empty string. */
433
434 static char *
435 get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
436 char *str;
437 int *iptr, delimiter, is_rhs, *lenptr;
438 {
439 register int si, i, j, k;
440 char *s;
441 #if defined (HANDLE_MULTIBYTE)
442 mbstate_t ps;
443 #endif
444
445 s = (char *)NULL;
446 i = *iptr;
447
448 #if defined (HANDLE_MULTIBYTE)
449 memset (&ps, 0, sizeof (mbstate_t));
450 _rl_adjust_point (str, i, &ps);
451 #endif
452
453 for (si = i; str[si] && str[si] != delimiter; si++)
454 #if defined (HANDLE_MULTIBYTE)
455 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
456 {
457 int v;
458 if ((v = _rl_get_char_len (str + si, &ps)) > 1)
459 si += v - 1;
460 else if (str[si] == '\\' && str[si + 1] == delimiter)
461 si++;
462 }
463 else
464 #endif /* HANDLE_MULTIBYTE */
465 if (str[si] == '\\' && str[si + 1] == delimiter)
466 si++;
467
468 if (si > i || is_rhs)
469 {
470 s = (char *)xmalloc (si - i + 1);
471 for (j = 0, k = i; k < si; j++, k++)
472 {
473 /* Remove a backslash quoting the search string delimiter. */
474 if (str[k] == '\\' && str[k + 1] == delimiter)
475 k++;
476 s[j] = str[k];
477 }
478 s[j] = '\0';
479 if (lenptr)
480 *lenptr = j;
481 }
482
483 i = si;
484 if (str[i])
485 i++;
486 *iptr = i;
487
488 return s;
489 }
490
491 static void
492 postproc_subst_rhs ()
493 {
494 char *new;
495 int i, j, new_size;
496
497 new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len);
498 for (i = j = 0; i < subst_rhs_len; i++)
499 {
500 if (subst_rhs[i] == '&')
501 {
502 if (j + subst_lhs_len >= new_size)
503 new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
504 strcpy (new + j, subst_lhs);
505 j += subst_lhs_len;
506 }
507 else
508 {
509 /* a single backslash protects the `&' from lhs interpolation */
510 if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
511 i++;
512 if (j >= new_size)
513 new = (char *)xrealloc (new, new_size *= 2);
514 new[j++] = subst_rhs[i];
515 }
516 }
517 new[j] = '\0';
518 xfree (subst_rhs);
519 subst_rhs = new;
520 subst_rhs_len = j;
521 }
522
523 /* Expand the bulk of a history specifier starting at STRING[START].
524 Returns 0 if everything is OK, -1 if an error occurred, and 1
525 if the `p' modifier was supplied and the caller should just print
526 the returned string. Returns the new index into string in
527 *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
528 static int
529 history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line)
530 char *string;
531 int start, qc, *end_index_ptr;
532 char **ret_string;
533 char *current_line; /* for !# */
534 {
535 int i, n, starting_index;
536 int substitute_globally, subst_bywords, want_quotes, print_only;
537 char *event, *temp, *result, *tstr, *t, c, *word_spec;
538 int result_len;
539 #if defined (HANDLE_MULTIBYTE)
540 mbstate_t ps;
541
542 memset (&ps, 0, sizeof (mbstate_t));
543 #endif
544
545 result = (char *)xmalloc (result_len = 128);
546
547 i = start;
548
549 /* If it is followed by something that starts a word specifier,
550 then !! is implied as the event specifier. */
551
552 if (member (string[i + 1], ":$*%^"))
553 {
554 char fake_s[3];
555 int fake_i = 0;
556 i++;
557 fake_s[0] = fake_s[1] = history_expansion_char;
558 fake_s[2] = '\0';
559 event = get_history_event (fake_s, &fake_i, 0);
560 }
561 else if (string[i + 1] == '#')
562 {
563 i += 2;
564 event = current_line;
565 }
566 else
567 event = get_history_event (string, &i, qc);
568
569 if (event == 0)
570 {
571 *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
572 xfree (result);
573 return (-1);
574 }
575
576 /* If a word specifier is found, then do what that requires. */
577 starting_index = i;
578 word_spec = get_history_word_specifier (string, event, &i);
579
580 /* There is no such thing as a `malformed word specifier'. However,
581 it is possible for a specifier that has no match. In that case,
582 we complain. */
583 if (word_spec == (char *)&error_pointer)
584 {
585 *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
586 xfree (result);
587 return (-1);
588 }
589
590 /* If no word specifier, than the thing of interest was the event. */
591 temp = word_spec ? savestring (word_spec) : savestring (event);
592 FREE (word_spec);
593
594 /* Perhaps there are other modifiers involved. Do what they say. */
595 want_quotes = substitute_globally = subst_bywords = print_only = 0;
596 starting_index = i;
597
598 while (string[i] == ':')
599 {
600 c = string[i + 1];
601
602 if (c == 'g' || c == 'a')
603 {
604 substitute_globally = 1;
605 i++;
606 c = string[i + 1];
607 }
608 else if (c == 'G')
609 {
610 subst_bywords = 1;
611 i++;
612 c = string[i + 1];
613 }
614
615 switch (c)
616 {
617 default:
618 *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
619 xfree (result);
620 xfree (temp);
621 return -1;
622
623 case 'q':
624 want_quotes = 'q';
625 break;
626
627 case 'x':
628 want_quotes = 'x';
629 break;
630
631 /* :p means make this the last executed line. So we
632 return an error state after adding this line to the
633 history. */
634 case 'p':
635 print_only++;
636 break;
637
638 /* :t discards all but the last part of the pathname. */
639 case 't':
640 tstr = strrchr (temp, '/');
641 if (tstr)
642 {
643 tstr++;
644 t = savestring (tstr);
645 xfree (temp);
646 temp = t;
647 }
648 break;
649
650 /* :h discards the last part of a pathname. */
651 case 'h':
652 tstr = strrchr (temp, '/');
653 if (tstr)
654 *tstr = '\0';
655 break;
656
657 /* :r discards the suffix. */
658 case 'r':
659 tstr = strrchr (temp, '.');
660 if (tstr)
661 *tstr = '\0';
662 break;
663
664 /* :e discards everything but the suffix. */
665 case 'e':
666 tstr = strrchr (temp, '.');
667 if (tstr)
668 {
669 t = savestring (tstr);
670 xfree (temp);
671 temp = t;
672 }
673 break;
674
675 /* :s/this/that substitutes `that' for the first
676 occurrence of `this'. :gs/this/that substitutes `that'
677 for each occurrence of `this'. :& repeats the last
678 substitution. :g& repeats the last substitution
679 globally. */
680
681 case '&':
682 case 's':
683 {
684 char *new_event;
685 int delimiter, failed, si, l_temp, ws, we;
686
687 if (c == 's')
688 {
689 if (i + 2 < (int)strlen (string))
690 {
691 #if defined (HANDLE_MULTIBYTE)
692 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
693 {
694 _rl_adjust_point (string, i + 2, &ps);
695 if (_rl_get_char_len (string + i + 2, &ps) > 1)
696 delimiter = 0;
697 else
698 delimiter = string[i + 2];
699 }
700 else
701 #endif /* HANDLE_MULTIBYTE */
702 delimiter = string[i + 2];
703 }
704 else
705 break; /* no search delimiter */
706
707 i += 3;
708
709 t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
710 /* An empty substitution lhs with no previous substitution
711 uses the last search string as the lhs. */
712 if (t)
713 {
714 FREE (subst_lhs);
715 subst_lhs = t;
716 }
717 else if (!subst_lhs)
718 {
719 if (search_string && *search_string)
720 {
721 subst_lhs = savestring (search_string);
722 subst_lhs_len = strlen (subst_lhs);
723 }
724 else
725 {
726 subst_lhs = (char *) NULL;
727 subst_lhs_len = 0;
728 }
729 }
730
731 FREE (subst_rhs);
732 subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
733
734 /* If `&' appears in the rhs, it's supposed to be replaced
735 with the lhs. */
736 if (member ('&', subst_rhs))
737 postproc_subst_rhs ();
738 }
739 else
740 i += 2;
741
742 /* If there is no lhs, the substitution can't succeed. */
743 if (subst_lhs_len == 0)
744 {
745 *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
746 xfree (result);
747 xfree (temp);
748 return -1;
749 }
750
751 l_temp = strlen (temp);
752 /* Ignore impossible cases. */
753 if (subst_lhs_len > l_temp)
754 {
755 *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
756 xfree (result);
757 xfree (temp);
758 return (-1);
759 }
760
761 /* Find the first occurrence of THIS in TEMP. */
762 /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
763 cases to consider:
764
765 1. substitute_globally == subst_bywords == 0
766 2. substitute_globally == 1 && subst_bywords == 0
767 3. substitute_globally == 0 && subst_bywords == 1
768
769 In the first case, we substitute for the first occurrence only.
770 In the second case, we substitute for every occurrence.
771 In the third case, we tokenize into words and substitute the
772 first occurrence of each word. */
773
774 si = we = 0;
775 for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
776 {
777 /* First skip whitespace and find word boundaries if
778 we're past the end of the word boundary we found
779 the last time. */
780 if (subst_bywords && si > we)
781 {
782 for (; temp[si] && whitespace (temp[si]); si++)
783 ;
784 ws = si;
785 we = history_tokenize_word (temp, si);
786 }
787
788 if (STREQN (temp+si, subst_lhs, subst_lhs_len))
789 {
790 int len = subst_rhs_len - subst_lhs_len + l_temp;
791 new_event = (char *)xmalloc (1 + len);
792 strncpy (new_event, temp, si);
793 strncpy (new_event + si, subst_rhs, subst_rhs_len);
794 strncpy (new_event + si + subst_rhs_len,
795 temp + si + subst_lhs_len,
796 l_temp - (si + subst_lhs_len));
797 new_event[len] = '\0';
798 xfree (temp);
799 temp = new_event;
800
801 failed = 0;
802
803 if (substitute_globally)
804 {
805 /* Reported to fix a bug that causes it to skip every
806 other match when matching a single character. Was
807 si += subst_rhs_len previously. */
808 si += subst_rhs_len - 1;
809 l_temp = strlen (temp);
810 substitute_globally++;
811 continue;
812 }
813 else if (subst_bywords)
814 {
815 si = we;
816 l_temp = strlen (temp);
817 continue;
818 }
819 else
820 break;
821 }
822 }
823
824 if (substitute_globally > 1)
825 {
826 substitute_globally = 0;
827 continue; /* don't want to increment i */
828 }
829
830 if (failed == 0)
831 continue; /* don't want to increment i */
832
833 *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
834 xfree (result);
835 xfree (temp);
836 return (-1);
837 }
838 }
839 i += 2;
840 }
841 /* Done with modifiers. */
842 /* Believe it or not, we have to back the pointer up by one. */
843 --i;
844
845 if (want_quotes)
846 {
847 char *x;
848
849 if (want_quotes == 'q')
850 x = sh_single_quote (temp);
851 else if (want_quotes == 'x')
852 x = quote_breaks (temp);
853 else
854 x = savestring (temp);
855
856 xfree (temp);
857 temp = x;
858 }
859
860 n = strlen (temp);
861 if (n >= result_len)
862 result = (char *)xrealloc (result, n + 2);
863 strcpy (result, temp);
864 xfree (temp);
865
866 *end_index_ptr = i;
867 *ret_string = result;
868 return (print_only);
869 }
870
871 /* Expand the string STRING, placing the result into OUTPUT, a pointer
872 to a string. Returns:
873
874 -1) If there was an error in expansion.
875 0) If no expansions took place (or, if the only change in
876 the text was the de-slashifying of the history expansion
877 character)
878 1) If expansions did take place
879 2) If the `p' modifier was given and the caller should print the result
880
881 If an error occurred in expansion, then OUTPUT contains a descriptive
882 error message. */
883
884 #define ADD_STRING(s) \
885 do \
886 { \
887 int sl = strlen (s); \
888 j += sl; \
889 if (j >= result_len) \
890 { \
891 while (j >= result_len) \
892 result_len += 128; \
893 result = (char *)xrealloc (result, result_len); \
894 } \
895 strcpy (result + j - sl, s); \
896 } \
897 while (0)
898
899 #define ADD_CHAR(c) \
900 do \
901 { \
902 if (j >= result_len - 1) \
903 result = (char *)xrealloc (result, result_len += 64); \
904 result[j++] = c; \
905 result[j] = '\0'; \
906 } \
907 while (0)
908
909 int
910 history_expand (hstring, output)
911 char *hstring;
912 char **output;
913 {
914 register int j;
915 int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag;
916 char *string;
917
918 /* The output string, and its length. */
919 int result_len;
920 char *result;
921
922 #if defined (HANDLE_MULTIBYTE)
923 char mb[MB_LEN_MAX];
924 mbstate_t ps;
925 #endif
926
927 /* Used when adding the string. */
928 char *temp;
929
930 if (output == 0)
931 return 0;
932
933 /* Setting the history expansion character to 0 inhibits all
934 history expansion. */
935 if (history_expansion_char == 0)
936 {
937 *output = savestring (hstring);
938 return (0);
939 }
940
941 /* Prepare the buffer for printing error messages. */
942 result = (char *)xmalloc (result_len = 256);
943 result[0] = '\0';
944
945 only_printing = modified = 0;
946 l = strlen (hstring);
947
948 /* Grovel the string. Only backslash and single quotes can quote the
949 history escape character. We also handle arg specifiers. */
950
951 /* Before we grovel forever, see if the history_expansion_char appears
952 anywhere within the text. */
953
954 /* The quick substitution character is a history expansion all right. That
955 is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
956 that is the substitution that we do. */
957 if (hstring[0] == history_subst_char)
958 {
959 string = (char *)xmalloc (l + 5);
960
961 string[0] = string[1] = history_expansion_char;
962 string[2] = ':';
963 string[3] = 's';
964 strcpy (string + 4, hstring);
965 l += 4;
966 }
967 else
968 {
969 #if defined (HANDLE_MULTIBYTE)
970 memset (&ps, 0, sizeof (mbstate_t));
971 #endif
972
973 string = hstring;
974 /* If not quick substitution, still maybe have to do expansion. */
975
976 /* `!' followed by one of the characters in history_no_expand_chars
977 is NOT an expansion. */
978 for (i = dquote = squote = 0; string[i]; i++)
979 {
980 #if defined (HANDLE_MULTIBYTE)
981 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
982 {
983 int v;
984 v = _rl_get_char_len (string + i, &ps);
985 if (v > 1)
986 {
987 i += v - 1;
988 continue;
989 }
990 }
991 #endif /* HANDLE_MULTIBYTE */
992
993 cc = string[i + 1];
994 /* The history_comment_char, if set, appearing at the beginning
995 of a word signifies that the rest of the line should not have
996 history expansion performed on it.
997 Skip the rest of the line and break out of the loop. */
998 if (history_comment_char && string[i] == history_comment_char &&
999 dquote == 0 &&
1000 (i == 0 || member (string[i - 1], history_word_delimiters)))
1001 {
1002 while (string[i])
1003 i++;
1004 break;
1005 }
1006 else if (string[i] == history_expansion_char)
1007 {
1008 if (cc == 0 || member (cc, history_no_expand_chars))
1009 continue;
1010 /* DQUOTE won't be set unless history_quotes_inhibit_expansion
1011 is set. The idea here is to treat double-quoted strings the
1012 same as the word outside double quotes; in effect making the
1013 double quote part of history_no_expand_chars when DQUOTE is
1014 set. */
1015 else if (dquote && cc == '"')
1016 continue;
1017 /* If the calling application has set
1018 history_inhibit_expansion_function to a function that checks
1019 for special cases that should not be history expanded,
1020 call the function and skip the expansion if it returns a
1021 non-zero value. */
1022 else if (history_inhibit_expansion_function &&
1023 (*history_inhibit_expansion_function) (string, i))
1024 continue;
1025 else
1026 break;
1027 }
1028 /* Shell-like quoting: allow backslashes to quote double quotes
1029 inside a double-quoted string. */
1030 else if (dquote && string[i] == '\\' && cc == '"')
1031 i++;
1032 /* More shell-like quoting: if we're paying attention to single
1033 quotes and letting them quote the history expansion character,
1034 then we need to pay attention to double quotes, because single
1035 quotes are not special inside double-quoted strings. */
1036 else if (history_quotes_inhibit_expansion && string[i] == '"')
1037 {
1038 dquote = 1 - dquote;
1039 }
1040 else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')
1041 {
1042 /* If this is bash, single quotes inhibit history expansion. */
1043 flag = (i > 0 && string[i - 1] == '$');
1044 i++;
1045 hist_string_extract_single_quoted (string, &i, flag);
1046 }
1047 else if (history_quotes_inhibit_expansion && string[i] == '\\')
1048 {
1049 /* If this is bash, allow backslashes to quote single
1050 quotes and the history expansion character. */
1051 if (cc == '\'' || cc == history_expansion_char)
1052 i++;
1053 }
1054
1055 }
1056
1057 if (string[i] != history_expansion_char)
1058 {
1059 xfree (result);
1060 *output = savestring (string);
1061 return (0);
1062 }
1063 }
1064
1065 /* Extract and perform the substitution. */
1066 for (passc = dquote = squote = i = j = 0; i < l; i++)
1067 {
1068 int qc, tchar = string[i];
1069
1070 if (passc)
1071 {
1072 passc = 0;
1073 ADD_CHAR (tchar);
1074 continue;
1075 }
1076
1077 #if defined (HANDLE_MULTIBYTE)
1078 if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
1079 {
1080 int k, c;
1081
1082 c = tchar;
1083 memset (mb, 0, sizeof (mb));
1084 for (k = 0; k < MB_LEN_MAX; k++)
1085 {
1086 mb[k] = (char)c;
1087 memset (&ps, 0, sizeof (mbstate_t));
1088 if (_rl_get_char_len (mb, &ps) == -2)
1089 c = string[++i];
1090 else
1091 break;
1092 }
1093 if (strlen (mb) > 1)
1094 {
1095 ADD_STRING (mb);
1096 continue;
1097 }
1098 }
1099 #endif /* HANDLE_MULTIBYTE */
1100
1101 if (tchar == history_expansion_char)
1102 tchar = -3;
1103 else if (tchar == history_comment_char)
1104 tchar = -2;
1105
1106 switch (tchar)
1107 {
1108 default:
1109 ADD_CHAR (string[i]);
1110 break;
1111
1112 case '\\':
1113 passc++;
1114 ADD_CHAR (tchar);
1115 break;
1116
1117 case '"':
1118 dquote = 1 - dquote;
1119 ADD_CHAR (tchar);
1120 break;
1121
1122 case '\'':
1123 {
1124 /* If history_quotes_inhibit_expansion is set, single quotes
1125 inhibit history expansion, otherwise they are treated like
1126 double quotes. */
1127 if (squote)
1128 {
1129 squote = 0;
1130 ADD_CHAR (tchar);
1131 }
1132 else if (dquote == 0 && history_quotes_inhibit_expansion)
1133 {
1134 int quote, slen;
1135
1136 flag = (i > 0 && string[i - 1] == '$');
1137 quote = i++;
1138 hist_string_extract_single_quoted (string, &i, flag);
1139
1140 slen = i - quote + 2;
1141 temp = (char *)xmalloc (slen);
1142 strncpy (temp, string + quote, slen);
1143 temp[slen - 1] = '\0';
1144 ADD_STRING (temp);
1145 xfree (temp);
1146 }
1147 else if (dquote == 0 && squote == 0 && history_quotes_inhibit_expansion == 0)
1148 {
1149 squote = 1;
1150 ADD_CHAR (string[i]);
1151 }
1152 else
1153 ADD_CHAR (string[i]);
1154 break;
1155 }
1156
1157 case -2: /* history_comment_char */
1158 if ((dquote == 0 || history_quotes_inhibit_expansion == 0) &&
1159 (i == 0 || member (string[i - 1], history_word_delimiters)))
1160 {
1161 temp = (char *)xmalloc (l - i + 1);
1162 strcpy (temp, string + i);
1163 ADD_STRING (temp);
1164 xfree (temp);
1165 i = l;
1166 }
1167 else
1168 ADD_CHAR (string[i]);
1169 break;
1170
1171 case -3: /* history_expansion_char */
1172 cc = string[i + 1];
1173
1174 /* If the history_expansion_char is followed by one of the
1175 characters in history_no_expand_chars, then it is not a
1176 candidate for expansion of any kind. */
1177 if (cc == 0 || member (cc, history_no_expand_chars) ||
1178 (dquote && cc == '"') ||
1179 (history_inhibit_expansion_function && (*history_inhibit_expansion_function) (string, i)))
1180 {
1181 ADD_CHAR (string[i]);
1182 break;
1183 }
1184
1185 #if defined (NO_BANG_HASH_MODIFIERS)
1186 /* There is something that is listed as a `word specifier' in csh
1187 documentation which means `the expanded text to this point'.
1188 That is not a word specifier, it is an event specifier. If we
1189 don't want to allow modifiers with `!#', just stick the current
1190 output line in again. */
1191 if (cc == '#')
1192 {
1193 if (result)
1194 {
1195 temp = (char *)xmalloc (1 + strlen (result));
1196 strcpy (temp, result);
1197 ADD_STRING (temp);
1198 xfree (temp);
1199 }
1200 i++;
1201 break;
1202 }
1203 #endif
1204 qc = squote ? '\'' : (dquote ? '"' : 0);
1205 r = history_expand_internal (string, i, qc, &eindex, &temp, result);
1206 if (r < 0)
1207 {
1208 *output = temp;
1209 xfree (result);
1210 if (string != hstring)
1211 xfree (string);
1212 return -1;
1213 }
1214 else
1215 {
1216 if (temp)
1217 {
1218 modified++;
1219 if (*temp)
1220 ADD_STRING (temp);
1221 xfree (temp);
1222 }
1223 only_printing = r == 1;
1224 i = eindex;
1225 }
1226 break;
1227 }
1228 }
1229
1230 *output = result;
1231 if (string != hstring)
1232 xfree (string);
1233
1234 if (only_printing)
1235 {
1236 #if 0
1237 add_history (result);
1238 #endif
1239 return (2);
1240 }
1241
1242 return (modified != 0);
1243 }
1244
1245 /* Return a consed string which is the word specified in SPEC, and found
1246 in FROM. NULL is returned if there is no spec. The address of
1247 ERROR_POINTER is returned if the word specified cannot be found.
1248 CALLER_INDEX is the offset in SPEC to start looking; it is updated
1249 to point to just after the last character parsed. */
1250 static char *
1251 get_history_word_specifier (spec, from, caller_index)
1252 char *spec, *from;
1253 int *caller_index;
1254 {
1255 register int i = *caller_index;
1256 int first, last;
1257 int expecting_word_spec = 0;
1258 char *result;
1259
1260 /* The range of words to return doesn't exist yet. */
1261 first = last = 0;
1262 result = (char *)NULL;
1263
1264 /* If we found a colon, then this *must* be a word specification. If
1265 it isn't, then it is an error. */
1266 if (spec[i] == ':')
1267 {
1268 i++;
1269 expecting_word_spec++;
1270 }
1271
1272 /* Handle special cases first. */
1273
1274 /* `%' is the word last searched for. */
1275 if (spec[i] == '%')
1276 {
1277 *caller_index = i + 1;
1278 return (search_match ? savestring (search_match) : savestring (""));
1279 }
1280
1281 /* `*' matches all of the arguments, but not the command. */
1282 if (spec[i] == '*')
1283 {
1284 *caller_index = i + 1;
1285 result = history_arg_extract (1, '$', from);
1286 return (result ? result : savestring (""));
1287 }
1288
1289 /* `$' is last arg. */
1290 if (spec[i] == '$')
1291 {
1292 *caller_index = i + 1;
1293 return (history_arg_extract ('$', '$', from));
1294 }
1295
1296 /* Try to get FIRST and LAST figured out. */
1297
1298 if (spec[i] == '-')
1299 first = 0;
1300 else if (spec[i] == '^')
1301 {
1302 first = 1;
1303 i++;
1304 }
1305 else if (_rl_digit_p (spec[i]) && expecting_word_spec)
1306 {
1307 for (first = 0; _rl_digit_p (spec[i]); i++)
1308 first = (first * 10) + _rl_digit_value (spec[i]);
1309 }
1310 else
1311 return ((char *)NULL); /* no valid `first' for word specifier */
1312
1313 if (spec[i] == '^' || spec[i] == '*')
1314 {
1315 last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
1316 i++;
1317 }
1318 else if (spec[i] != '-')
1319 last = first;
1320 else
1321 {
1322 i++;
1323
1324 if (_rl_digit_p (spec[i]))
1325 {
1326 for (last = 0; _rl_digit_p (spec[i]); i++)
1327 last = (last * 10) + _rl_digit_value (spec[i]);
1328 }
1329 else if (spec[i] == '$')
1330 {
1331 i++;
1332 last = '$';
1333 }
1334 #if 0
1335 else if (!spec[i] || spec[i] == ':')
1336 /* check against `:' because there could be a modifier separator */
1337 #else
1338 else
1339 /* csh seems to allow anything to terminate the word spec here,
1340 leaving it as an abbreviation. */
1341 #endif
1342 last = -1; /* x- abbreviates x-$ omitting word `$' */
1343 }
1344
1345 *caller_index = i;
1346
1347 if (last >= first || last == '$' || last < 0)
1348 result = history_arg_extract (first, last, from);
1349
1350 return (result ? result : (char *)&error_pointer);
1351 }
1352
1353 /* Extract the args specified, starting at FIRST, and ending at LAST.
1354 The args are taken from STRING. If either FIRST or LAST is < 0,
1355 then make that arg count from the right (subtract from the number of
1356 tokens, so that FIRST = -1 means the next to last token on the line).
1357 If LAST is `$' the last arg from STRING is used. */
1358 char *
1359 history_arg_extract (first, last, string)
1360 int first, last;
1361 const char *string;
1362 {
1363 register int i, len;
1364 char *result;
1365 int size, offset;
1366 char **list;
1367
1368 /* XXX - think about making history_tokenize return a struct array,
1369 each struct in array being a string and a length to avoid the
1370 calls to strlen below. */
1371 if ((list = history_tokenize (string)) == NULL)
1372 return ((char *)NULL);
1373
1374 for (len = 0; list[len]; len++)
1375 ;
1376
1377 if (last < 0)
1378 last = len + last - 1;
1379
1380 if (first < 0)
1381 first = len + first - 1;
1382
1383 if (last == '$')
1384 last = len - 1;
1385
1386 if (first == '$')
1387 first = len - 1;
1388
1389 last++;
1390
1391 if (first >= len || last > len || first < 0 || last < 0 || first > last)
1392 result = ((char *)NULL);
1393 else
1394 {
1395 for (size = 0, i = first; i < last; i++)
1396 size += strlen (list[i]) + 1;
1397 result = (char *)xmalloc (size + 1);
1398 result[0] = '\0';
1399
1400 for (i = first, offset = 0; i < last; i++)
1401 {
1402 strcpy (result + offset, list[i]);
1403 offset += strlen (list[i]);
1404 if (i + 1 < last)
1405 {
1406 result[offset++] = ' ';
1407 result[offset] = 0;
1408 }
1409 }
1410 }
1411
1412 for (i = 0; i < len; i++)
1413 xfree (list[i]);
1414 xfree (list);
1415
1416 return (result);
1417 }
1418
1419 static int
1420 history_tokenize_word (string, ind)
1421 const char *string;
1422 int ind;
1423 {
1424 register int i;
1425 int delimiter, nestdelim, delimopen;
1426
1427 i = ind;
1428 delimiter = nestdelim = 0;
1429
1430 if (member (string[i], "()\n"))
1431 {
1432 i++;
1433 return i;
1434 }
1435
1436 if (member (string[i], "<>;&|$"))
1437 {
1438 int peek = string[i + 1];
1439
1440 if (peek == string[i] && peek != '$')
1441 {
1442 if (peek == '<' && string[i + 2] == '-')
1443 i++;
1444 else if (peek == '<' && string[i + 2] == '<')
1445 i++;
1446 i += 2;
1447 return i;
1448 }
1449 else if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
1450 (peek == '>' && string[i] == '&'))
1451 {
1452 i += 2;
1453 return i;
1454 }
1455 /* XXX - separated out for later -- bash-4.2 */
1456 else if ((peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
1457 (peek == '(' && string[i] == '$')) /*)*/
1458 {
1459 i += 2;
1460 delimopen = '(';
1461 delimiter = ')';
1462 nestdelim = 1;
1463 goto get_word;
1464 }
1465 #if 0
1466 else if (peek == '\'' && string[i] == '$')
1467 {
1468 i += 2; /* XXX */
1469 return i;
1470 }
1471 #endif
1472
1473 if (string[i] != '$')
1474 {
1475 i++;
1476 return i;
1477 }
1478 }
1479
1480 /* same code also used for $(...)/<(...)/>(...) above */
1481 if (member (string[i], "!@?+*"))
1482 {
1483 int peek = string[i + 1];
1484
1485 if (peek == '(') /*)*/
1486 {
1487 /* Shell extended globbing patterns */
1488 i += 2;
1489 delimopen = '(';
1490 delimiter = ')'; /* XXX - not perfect */
1491 nestdelim = 1;
1492 }
1493 }
1494
1495 get_word:
1496 /* Get word from string + i; */
1497
1498 if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS))
1499 delimiter = string[i++];
1500
1501 for (; string[i]; i++)
1502 {
1503 if (string[i] == '\\' && string[i + 1] == '\n')
1504 {
1505 i++;
1506 continue;
1507 }
1508
1509 if (string[i] == '\\' && delimiter != '\'' &&
1510 (delimiter != '"' || member (string[i], slashify_in_quotes)))
1511 {
1512 i++;
1513 continue;
1514 }
1515
1516 /* delimiter must be set and set to something other than a quote if
1517 nestdelim is set, so these tests are safe. */
1518 if (nestdelim && string[i] == delimopen)
1519 {
1520 nestdelim++;
1521 continue;
1522 }
1523 if (nestdelim && string[i] == delimiter)
1524 {
1525 nestdelim--;
1526 if (nestdelim == 0)
1527 delimiter = 0;
1528 continue;
1529 }
1530
1531 if (delimiter && string[i] == delimiter)
1532 {
1533 delimiter = 0;
1534 continue;
1535 }
1536
1537 if (delimiter == 0 && (member (string[i], history_word_delimiters)))
1538 break;
1539
1540 if (delimiter == 0 && member (string[i], HISTORY_QUOTE_CHARACTERS))
1541 delimiter = string[i];
1542 }
1543
1544 return i;
1545 }
1546
1547 static char *
1548 history_substring (string, start, end)
1549 const char *string;
1550 int start, end;
1551 {
1552 register int len;
1553 register char *result;
1554
1555 len = end - start;
1556 result = (char *)xmalloc (len + 1);
1557 strncpy (result, string + start, len);
1558 result[len] = '\0';
1559 return result;
1560 }
1561
1562 /* Parse STRING into tokens and return an array of strings. If WIND is
1563 not -1 and INDP is not null, we also want the word surrounding index
1564 WIND. The position in the returned array of strings is returned in
1565 *INDP. */
1566 static char **
1567 history_tokenize_internal (string, wind, indp)
1568 const char *string;
1569 int wind, *indp;
1570 {
1571 char **result;
1572 register int i, start, result_index, size;
1573
1574 /* If we're searching for a string that's not part of a word (e.g., " "),
1575 make sure we set *INDP to a reasonable value. */
1576 if (indp && wind != -1)
1577 *indp = -1;
1578
1579 /* Get a token, and stuff it into RESULT. The tokens are split
1580 exactly where the shell would split them. */
1581 for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
1582 {
1583 /* Skip leading whitespace. */
1584 for (; string[i] && whitespace (string[i]); i++)
1585 ;
1586 if (string[i] == 0 || string[i] == history_comment_char)
1587 return (result);
1588
1589 start = i;
1590
1591 i = history_tokenize_word (string, start);
1592
1593 /* If we have a non-whitespace delimiter character (which would not be
1594 skipped by the loop above), use it and any adjacent delimiters to
1595 make a separate field. Any adjacent white space will be skipped the
1596 next time through the loop. */
1597 if (i == start && history_word_delimiters)
1598 {
1599 i++;
1600 while (string[i] && member (string[i], history_word_delimiters))
1601 i++;
1602 }
1603
1604 /* If we are looking for the word in which the character at a
1605 particular index falls, remember it. */
1606 if (indp && wind != -1 && wind >= start && wind < i)
1607 *indp = result_index;
1608
1609 if (result_index + 2 >= size)
1610 result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
1611
1612 result[result_index++] = history_substring (string, start, i);
1613 result[result_index] = (char *)NULL;
1614 }
1615
1616 return (result);
1617 }
1618
1619 /* Return an array of tokens, much as the shell might. The tokens are
1620 parsed out of STRING. */
1621 char **
1622 history_tokenize (string)
1623 const char *string;
1624 {
1625 return (history_tokenize_internal (string, -1, (int *)NULL));
1626 }
1627
1628 /* Free members of WORDS from START to an empty string */
1629 static void
1630 freewords (words, start)
1631 char **words;
1632 int start;
1633 {
1634 register int i;
1635
1636 for (i = start; words[i]; i++)
1637 xfree (words[i]);
1638 }
1639
1640 /* Find and return the word which contains the character at index IND
1641 in the history line LINE. Used to save the word matched by the
1642 last history !?string? search. */
1643 static char *
1644 history_find_word (line, ind)
1645 char *line;
1646 int ind;
1647 {
1648 char **words, *s;
1649 int i, wind;
1650
1651 words = history_tokenize_internal (line, ind, &wind);
1652 if (wind == -1 || words == 0)
1653 {
1654 if (words)
1655 freewords (words, 0);
1656 FREE (words);
1657 return ((char *)NULL);
1658 }
1659 s = words[wind];
1660 for (i = 0; i < wind; i++)
1661 xfree (words[i]);
1662 freewords (words, wind + 1);
1663 xfree (words);
1664 return s;
1665 }
This page took 0.062342 seconds and 3 git commands to generate.