1 /* misc.c -- miscellaneous bindable readline functions. */
2 
3 /* Copyright (C) 1987-2019 Free Software Foundation, Inc.
4 
5    This file is part of the GNU Readline Library (Readline), a library
6    for reading lines of text with interactive input and history editing.
7 
8    Readline 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    Readline 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 Readline.  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 #if defined (HAVE_UNISTD_H)
29 #  include <unistd.h>
30 #endif /* HAVE_UNISTD_H */
31 
32 #if defined (HAVE_STDLIB_H)
33 #  include <stdlib.h>
34 #else
35 #  include "ansi_stdlib.h"
36 #endif /* HAVE_STDLIB_H */
37 
38 #if defined (HAVE_LOCALE_H)
39 #  include <locale.h>
40 #endif
41 
42 #include <stdio.h>
43 
44 /* System-specific feature definitions and include files. */
45 #include "rldefs.h"
46 #include "rlmbutil.h"
47 
48 /* Some standard library routines. */
49 #include "readline.h"
50 #include "history.h"
51 
52 #include "rlprivate.h"
53 #include "rlshell.h"
54 #include "xmalloc.h"
55 
56 static int rl_digit_loop PARAMS((void));
57 static void _rl_history_set_point PARAMS((void));
58 
59 /* Forward declarations used in this file */
60 void _rl_free_history_entry PARAMS((HIST_ENTRY *));
61 
62 /* If non-zero, rl_get_previous_history and rl_get_next_history attempt
63    to preserve the value of rl_point from line to line. */
64 int _rl_history_preserve_point = 0;
65 
66 _rl_arg_cxt _rl_argcxt;
67 
68 /* Saved target point for when _rl_history_preserve_point is set.  Special
69    value of -1 means that point is at the end of the line. */
70 int _rl_history_saved_point = -1;
71 
72 /* **************************************************************** */
73 /*								    */
74 /*			Numeric Arguments			    */
75 /*								    */
76 /* **************************************************************** */
77 
78 int
_rl_arg_overflow(void)79 _rl_arg_overflow (void)
80 {
81   if (rl_numeric_arg > 1000000)
82     {
83       _rl_argcxt = 0;
84       rl_explicit_arg = rl_numeric_arg = 0;
85       rl_ding ();
86       rl_restore_prompt ();
87       rl_clear_message ();
88       RL_UNSETSTATE(RL_STATE_NUMERICARG);
89       return 1;
90     }
91   return 0;
92 }
93 
94 void
_rl_arg_init(void)95 _rl_arg_init (void)
96 {
97   rl_save_prompt ();
98   _rl_argcxt = 0;
99   RL_SETSTATE(RL_STATE_NUMERICARG);
100 }
101 
102 int
_rl_arg_getchar(void)103 _rl_arg_getchar (void)
104 {
105   int c;
106 
107   rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
108   RL_SETSTATE(RL_STATE_MOREINPUT);
109   c = rl_read_key ();
110   RL_UNSETSTATE(RL_STATE_MOREINPUT);
111 
112   return c;
113 }
114 
115 /* Process C as part of the current numeric argument.  Return -1 if the
116    argument should be aborted, 0 if we should not read any more chars, and
117    1 if we should continue to read chars. */
118 int
_rl_arg_dispatch(_rl_arg_cxt cxt,int c)119 _rl_arg_dispatch (_rl_arg_cxt cxt, int c)
120 {
121   int key, r;
122 
123   key = c;
124 
125   /* If we see a key bound to `universal-argument' after seeing digits,
126       it ends the argument but is otherwise ignored. */
127   if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
128     {
129       if ((cxt & NUM_SAWDIGITS) == 0)
130 	{
131 	  rl_numeric_arg *= 4;
132 	  return 1;
133 	}
134       else if (RL_ISSTATE (RL_STATE_CALLBACK))
135         {
136           _rl_argcxt |= NUM_READONE;
137           return 0;	/* XXX */
138         }
139       else
140 	{
141 	  key = _rl_bracketed_read_key ();
142 	  rl_restore_prompt ();
143 	  rl_clear_message ();
144 	  RL_UNSETSTATE(RL_STATE_NUMERICARG);
145 	  if (key < 0)
146 	    return -1;
147 	  return (_rl_dispatch (key, _rl_keymap));
148 	}
149     }
150 
151   c = UNMETA (c);
152 
153   if (_rl_digit_p (c))
154     {
155       r = _rl_digit_value (c);
156       rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) +  r : r;
157       rl_explicit_arg = 1;
158       _rl_argcxt |= NUM_SAWDIGITS;
159     }
160   else if (c == '-' && rl_explicit_arg == 0)
161     {
162       rl_numeric_arg = 1;
163       _rl_argcxt |= NUM_SAWMINUS;
164       rl_arg_sign = -1;
165     }
166   else
167     {
168       /* Make M-- command equivalent to M--1 command. */
169       if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0)
170 	rl_explicit_arg = 1;
171       rl_restore_prompt ();
172       rl_clear_message ();
173       RL_UNSETSTATE(RL_STATE_NUMERICARG);
174 
175       r = _rl_dispatch (key, _rl_keymap);
176       if (RL_ISSTATE (RL_STATE_CALLBACK))
177 	{
178 	  /* At worst, this will cause an extra redisplay.  Otherwise,
179 	     we have to wait until the next character comes in. */
180 	  if (rl_done == 0)
181 	    (*rl_redisplay_function) ();
182 	  r = 0;
183 	}
184       return r;
185     }
186 
187   return 1;
188 }
189 
190 /* Handle C-u style numeric args, as well as M--, and M-digits. */
191 static int
rl_digit_loop(void)192 rl_digit_loop (void)
193 {
194   int c, r;
195 
196   while (1)
197     {
198       if (_rl_arg_overflow ())
199 	return 1;
200 
201       c = _rl_arg_getchar ();
202 
203       if (c < 0)
204 	{
205 	  _rl_abort_internal ();
206 	  return -1;
207 	}
208 
209       r = _rl_arg_dispatch (_rl_argcxt, c);
210       if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
211         break;
212     }
213 
214   return r;
215 }
216 
217 /* Create a default argument. */
218 void
_rl_reset_argument(void)219 _rl_reset_argument (void)
220 {
221   rl_numeric_arg = rl_arg_sign = 1;
222   rl_explicit_arg = 0;
223   _rl_argcxt = 0;
224 }
225 
226 /* Start a numeric argument with initial value KEY */
227 int
rl_digit_argument(int ignore,int key)228 rl_digit_argument (int ignore, int key)
229 {
230   _rl_arg_init ();
231   if (RL_ISSTATE (RL_STATE_CALLBACK))
232     {
233       _rl_arg_dispatch (_rl_argcxt, key);
234       rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
235       return 0;
236     }
237   else
238     {
239       rl_execute_next (key);
240       return (rl_digit_loop ());
241     }
242 }
243 
244 /* C-u, universal argument.  Multiply the current argument by 4.
245    Read a key.  If the key has nothing to do with arguments, then
246    dispatch on it.  If the key is the abort character then abort. */
247 int
rl_universal_argument(int count,int key)248 rl_universal_argument (int count, int key)
249 {
250   _rl_arg_init ();
251   rl_numeric_arg *= 4;
252 
253   return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
254 }
255 
256 int
_rl_arg_callback(_rl_arg_cxt cxt)257 _rl_arg_callback (_rl_arg_cxt cxt)
258 {
259   int c, r;
260 
261   c = _rl_arg_getchar ();
262   if (c < 0)
263     return (1);		/* EOF */
264 
265   if (_rl_argcxt & NUM_READONE)
266     {
267       _rl_argcxt &= ~NUM_READONE;
268       rl_restore_prompt ();
269       rl_clear_message ();
270       RL_UNSETSTATE(RL_STATE_NUMERICARG);
271       rl_execute_next (c);
272       return 0;
273     }
274 
275   r = _rl_arg_dispatch (cxt, c);
276   if (r > 0)
277     rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
278   return (r != 1);
279 }
280 
281 /* What to do when you abort reading an argument. */
282 int
rl_discard_argument(void)283 rl_discard_argument (void)
284 {
285   rl_ding ();
286   rl_clear_message ();
287   _rl_reset_argument ();
288 
289   return 0;
290 }
291 
292 /* **************************************************************** */
293 /*								    */
294 /*			History Utilities			    */
295 /*								    */
296 /* **************************************************************** */
297 
298 /* We already have a history library, and that is what we use to control
299    the history features of readline.  This is our local interface to
300    the history mechanism. */
301 
302 /* While we are editing the history, this is the saved
303    version of the original line. */
304 HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
305 
306 /* Set the history pointer back to the last entry in the history. */
307 void
_rl_start_using_history(void)308 _rl_start_using_history (void)
309 {
310   using_history ();
311   if (_rl_saved_line_for_history)
312     _rl_free_history_entry (_rl_saved_line_for_history);
313 
314   _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
315 }
316 
317 /* Free the contents (and containing structure) of a HIST_ENTRY. */
318 void
_rl_free_history_entry(HIST_ENTRY * entry)319 _rl_free_history_entry (HIST_ENTRY *entry)
320 {
321   if (entry == 0)
322     return;
323 
324   FREE (entry->line);
325   FREE (entry->timestamp);
326 
327   xfree (entry);
328 }
329 
330 /* Perhaps put back the current line if it has changed. */
331 int
rl_maybe_replace_line(void)332 rl_maybe_replace_line (void)
333 {
334   HIST_ENTRY *temp;
335 
336   temp = current_history ();
337   /* If the current line has changed, save the changes. */
338   if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
339     {
340       temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
341       xfree (temp->line);
342       FREE (temp->timestamp);
343       xfree (temp);
344     }
345   return 0;
346 }
347 
348 /* Restore the _rl_saved_line_for_history if there is one. */
349 int
rl_maybe_unsave_line(void)350 rl_maybe_unsave_line (void)
351 {
352   if (_rl_saved_line_for_history)
353     {
354       /* Can't call with `1' because rl_undo_list might point to an undo
355 	 list from a history entry, as in rl_replace_from_history() below. */
356       rl_replace_line (_rl_saved_line_for_history->line, 0);
357       rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
358       _rl_free_history_entry (_rl_saved_line_for_history);
359       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
360       rl_point = rl_end;	/* rl_replace_line sets rl_end */
361     }
362   else
363     rl_ding ();
364   return 0;
365 }
366 
367 /* Save the current line in _rl_saved_line_for_history. */
368 int
rl_maybe_save_line(void)369 rl_maybe_save_line (void)
370 {
371   if (_rl_saved_line_for_history == 0)
372     {
373       _rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
374       _rl_saved_line_for_history->line = savestring (rl_line_buffer);
375       _rl_saved_line_for_history->timestamp = (char *)NULL;
376       _rl_saved_line_for_history->data = (char *)rl_undo_list;
377     }
378 
379   return 0;
380 }
381 
382 int
_rl_free_saved_history_line(void)383 _rl_free_saved_history_line (void)
384 {
385   if (_rl_saved_line_for_history)
386     {
387       _rl_free_history_entry (_rl_saved_line_for_history);
388       _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
389     }
390   return 0;
391 }
392 
393 static void
_rl_history_set_point(void)394 _rl_history_set_point (void)
395 {
396   rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
397 		? _rl_history_saved_point
398 		: rl_end;
399   if (rl_point > rl_end)
400     rl_point = rl_end;
401 
402 #if defined (VI_MODE)
403   if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
404     rl_point = 0;
405 #endif /* VI_MODE */
406 
407   if (rl_editing_mode == emacs_mode)
408     rl_mark = (rl_point == rl_end ? 0 : rl_end);
409 }
410 
411 void
rl_replace_from_history(HIST_ENTRY * entry,int flags)412 rl_replace_from_history (HIST_ENTRY *entry, int flags)
413 {
414   /* Can't call with `1' because rl_undo_list might point to an undo list
415      from a history entry, just like we're setting up here. */
416   rl_replace_line (entry->line, 0);
417   rl_undo_list = (UNDO_LIST *)entry->data;
418   rl_point = rl_end;
419   rl_mark = 0;
420 
421 #if defined (VI_MODE)
422   if (rl_editing_mode == vi_mode)
423     {
424       rl_point = 0;
425       rl_mark = rl_end;
426     }
427 #endif
428 }
429 
430 /* Process and free undo lists attached to each history entry prior to the
431    current entry, inclusive, reverting each line to its saved state.  This
432    is destructive, and state about the current line is lost.  This is not
433    intended to be called while actively editing, and the current line is
434    not assumed to have been added to the history list. */
435 void
_rl_revert_previous_lines(void)436 _rl_revert_previous_lines (void)
437 {
438   int hpos;
439   HIST_ENTRY *entry;
440   UNDO_LIST *ul, *saved_undo_list;
441   char *lbuf;
442 
443   lbuf = savestring (rl_line_buffer);
444   saved_undo_list = rl_undo_list;
445   hpos = where_history ();
446 
447   entry = (hpos == history_length) ? previous_history () : current_history ();
448   while (entry)
449     {
450       if (ul = (UNDO_LIST *)entry->data)
451 	{
452 	  if (ul == saved_undo_list)
453 	    saved_undo_list = 0;
454 	  /* Set up rl_line_buffer and other variables from history entry */
455 	  rl_replace_from_history (entry, 0);	/* entry->line is now current */
456 	  entry->data = 0;			/* entry->data is now current undo list */
457 	  /* Undo all changes to this history entry */
458 	  while (rl_undo_list)
459 	    rl_do_undo ();
460 	  /* And copy the reverted line back to the history entry, preserving
461 	     the timestamp. */
462 	  FREE (entry->line);
463 	  entry->line = savestring (rl_line_buffer);
464 	}
465       entry = previous_history ();
466     }
467 
468   /* Restore history state */
469   rl_undo_list = saved_undo_list;	/* may have been set to null */
470   history_set_pos (hpos);
471 
472   /* reset the line buffer */
473   rl_replace_line (lbuf, 0);
474   _rl_set_the_line ();
475 
476   /* and clean up */
477   xfree (lbuf);
478 }
479 
480 /* Revert all lines in the history by making sure we are at the end of the
481    history before calling _rl_revert_previous_lines() */
482 void
_rl_revert_all_lines(void)483 _rl_revert_all_lines (void)
484 {
485   int pos;
486 
487   pos = where_history ();
488   using_history ();
489   _rl_revert_previous_lines ();
490   history_set_pos (pos);
491 }
492 
493 /* Free the history list, including private readline data and take care
494    of pointer aliases to history data.  Resets rl_undo_list if it points
495    to an UNDO_LIST * saved as some history entry's data member.  This
496    should not be called while editing is active. */
497 void
rl_clear_history(void)498 rl_clear_history (void)
499 {
500   HIST_ENTRY **hlist, *hent;
501   register int i;
502   UNDO_LIST *ul, *saved_undo_list;
503 
504   saved_undo_list = rl_undo_list;
505   hlist = history_list ();		/* direct pointer, not copy */
506 
507   for (i = 0; i < history_length; i++)
508     {
509       hent = hlist[i];
510       if (ul = (UNDO_LIST *)hent->data)
511 	{
512 	  if (ul == saved_undo_list)
513 	    saved_undo_list = 0;
514 	  _rl_free_undo_list (ul);
515 	  hent->data = 0;
516 	}
517       _rl_free_history_entry (hent);
518     }
519 
520   history_offset = history_length = 0;
521   rl_undo_list = saved_undo_list;	/* should be NULL */
522 }
523 
524 /* **************************************************************** */
525 /*								    */
526 /*			History Commands			    */
527 /*								    */
528 /* **************************************************************** */
529 
530 /* Meta-< goes to the start of the history. */
531 int
rl_beginning_of_history(int count,int key)532 rl_beginning_of_history (int count, int key)
533 {
534   return (rl_get_previous_history (1 + where_history (), key));
535 }
536 
537 /* Meta-> goes to the end of the history.  (The current line). */
538 int
rl_end_of_history(int count,int key)539 rl_end_of_history (int count, int key)
540 {
541   rl_maybe_replace_line ();
542   using_history ();
543   rl_maybe_unsave_line ();
544   return 0;
545 }
546 
547 /* Move down to the next history line. */
548 int
rl_get_next_history(int count,int key)549 rl_get_next_history (int count, int key)
550 {
551   HIST_ENTRY *temp;
552 
553   if (count < 0)
554     return (rl_get_previous_history (-count, key));
555 
556   if (count == 0)
557     return 0;
558 
559   rl_maybe_replace_line ();
560 
561   /* either not saved by rl_newline or at end of line, so set appropriately. */
562   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
563     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
564 
565   temp = (HIST_ENTRY *)NULL;
566   while (count)
567     {
568       temp = next_history ();
569       if (!temp)
570 	break;
571       --count;
572     }
573 
574   if (temp == 0)
575     rl_maybe_unsave_line ();
576   else
577     {
578       rl_replace_from_history (temp, 0);
579       _rl_history_set_point ();
580     }
581   return 0;
582 }
583 
584 /* Get the previous item out of our interactive history, making it the current
585    line.  If there is no previous history, just ding. */
586 int
rl_get_previous_history(int count,int key)587 rl_get_previous_history (int count, int key)
588 {
589   HIST_ENTRY *old_temp, *temp;
590   int had_saved_line;
591 
592   if (count < 0)
593     return (rl_get_next_history (-count, key));
594 
595   if (count == 0 || history_list () == 0)
596     return 0;
597 
598   /* either not saved by rl_newline or at end of line, so set appropriately. */
599   if (_rl_history_saved_point == -1 && (rl_point || rl_end))
600     _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
601 
602   /* If we don't have a line saved, then save this one. */
603   had_saved_line = _rl_saved_line_for_history != 0;
604   rl_maybe_save_line ();
605 
606   /* If the current line has changed, save the changes. */
607   rl_maybe_replace_line ();
608 
609   temp = old_temp = (HIST_ENTRY *)NULL;
610   while (count)
611     {
612       temp = previous_history ();
613       if (temp == 0)
614 	break;
615 
616       old_temp = temp;
617       --count;
618     }
619 
620   /* If there was a large argument, and we moved back to the start of the
621      history, that is not an error.  So use the last value found. */
622   if (!temp && old_temp)
623     temp = old_temp;
624 
625   if (temp == 0)
626     {
627       if (had_saved_line == 0)
628         _rl_free_saved_history_line ();
629       rl_ding ();
630     }
631   else
632     {
633       rl_replace_from_history (temp, 0);
634       _rl_history_set_point ();
635     }
636 
637   return 0;
638 }
639 
640 /* The equivalent of the Korn shell C-o operate-and-get-next-history-line
641    editing command. */
642 
643 /* This could stand to be global to the readline library */
644 static rl_hook_func_t *_rl_saved_internal_startup_hook = 0;
645 static int saved_history_logical_offset = -1;
646 
647 #define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
648 
649 static int
set_saved_history()650 set_saved_history ()
651 {
652   int absolute_offset, count;
653 
654   if (saved_history_logical_offset >= 0)
655     {
656       absolute_offset = saved_history_logical_offset - history_base;
657       count = where_history () - absolute_offset;
658       rl_get_previous_history (count, 0);
659     }
660   saved_history_logical_offset = -1;
661   _rl_internal_startup_hook = _rl_saved_internal_startup_hook;
662 
663   return (0);
664 }
665 
666 int
rl_operate_and_get_next(count,c)667 rl_operate_and_get_next (count, c)
668      int count, c;
669 {
670   /* Accept the current line. */
671   rl_newline (1, c);
672 
673   saved_history_logical_offset = rl_explicit_arg ? count : where_history () + history_base + 1;
674 
675 
676   _rl_saved_internal_startup_hook = _rl_internal_startup_hook;
677   _rl_internal_startup_hook = set_saved_history;
678 
679   return 0;
680 }
681 
682 /* **************************************************************** */
683 /*								    */
684 /*			    Editing Modes			    */
685 /*								    */
686 /* **************************************************************** */
687 /* How to toggle back and forth between editing modes. */
688 int
rl_vi_editing_mode(int count,int key)689 rl_vi_editing_mode (int count, int key)
690 {
691 #if defined (VI_MODE)
692   _rl_set_insert_mode (RL_IM_INSERT, 1);	/* vi mode ignores insert mode */
693   rl_editing_mode = vi_mode;
694   rl_vi_insert_mode (1, key);
695 #endif /* VI_MODE */
696 
697   return 0;
698 }
699 
700 int
rl_emacs_editing_mode(int count,int key)701 rl_emacs_editing_mode (int count, int key)
702 {
703   rl_editing_mode = emacs_mode;
704   _rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
705   _rl_keymap = emacs_standard_keymap;
706 
707   if (_rl_show_mode_in_prompt)
708     _rl_reset_prompt ();
709 
710   return 0;
711 }
712 
713 /* Function for the rest of the library to use to set insert/overwrite mode. */
714 void
_rl_set_insert_mode(int im,int force)715 _rl_set_insert_mode (int im, int force)
716 {
717 #ifdef CURSOR_MODE
718   _rl_set_cursor (im, force);
719 #endif
720 
721   rl_insert_mode = im;
722 }
723 
724 /* Toggle overwrite mode.  A positive explicit argument selects overwrite
725    mode.  A negative or zero explicit argument selects insert mode. */
726 int
rl_overwrite_mode(int count,int key)727 rl_overwrite_mode (int count, int key)
728 {
729   if (rl_explicit_arg == 0)
730     _rl_set_insert_mode (rl_insert_mode ^ 1, 0);
731   else if (count > 0)
732     _rl_set_insert_mode (RL_IM_OVERWRITE, 0);
733   else
734     _rl_set_insert_mode (RL_IM_INSERT, 0);
735 
736   return 0;
737 }
738