]> git.ipfire.org Git - thirdparty/bash.git/blob - lib/readline/history.c
ee52e8297eed27d732044e865e0958aff4fca25b
[thirdparty/bash.git] / lib / readline / history.c
1 /* history.c -- standalone history library */
2
3 /* Copyright (C) 1989-2023 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 /* The goal is to make the implementation transparent, so that you
23 don't have to know what data types are used, just what functions
24 you can call. I think I have done that. */
25 #define READLINE_LIBRARY
26
27 #if defined (HAVE_CONFIG_H)
28 # include <config.h>
29 #endif
30
31 #include <stdio.h>
32
33 #if defined (HAVE_STDLIB_H)
34 # include <stdlib.h>
35 #else
36 # include "ansi_stdlib.h"
37 #endif /* HAVE_STDLIB_H */
38
39 #if defined (HAVE_UNISTD_H)
40 # ifdef _MINIX
41 # include <sys/types.h>
42 # endif
43 # include <unistd.h>
44 #endif
45 #include "posixtime.h"
46
47 #include <errno.h>
48
49 #include "history.h"
50 #include "histlib.h"
51
52 #include "xmalloc.h"
53
54 #if !defined (errno)
55 extern int errno;
56 #endif
57
58 /* How big to make the_history when we first allocate it. */
59 #define DEFAULT_HISTORY_INITIAL_SIZE 502
60
61 #define MAX_HISTORY_INITIAL_SIZE 8192
62
63 /* The number of slots to increase the_history by. */
64 #define DEFAULT_HISTORY_GROW_SIZE 50
65
66 static char *hist_inittime (void);
67
68 /* **************************************************************** */
69 /* */
70 /* History Functions */
71 /* */
72 /* **************************************************************** */
73
74 /* An array of HIST_ENTRY. This is where we store the history. */
75 static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
76
77 /* Non-zero means that we have enforced a limit on the amount of
78 history that we save. */
79 static int history_stifled;
80
81 /* The current number of slots allocated to the input_history. */
82 static int history_size;
83
84 /* If HISTORY_STIFLED is non-zero, then this is the maximum number of
85 entries to remember. */
86 int history_max_entries;
87 int max_input_history; /* backwards compatibility */
88
89 /* The current location of the interactive history pointer. Just makes
90 life easier for outside callers. */
91 int history_offset;
92
93 /* The number of strings currently stored in the history list. */
94 int history_length;
95
96 /* The logical `base' of the history array. It defaults to 1. */
97 int history_base = 1;
98
99 /* Return the current HISTORY_STATE of the history. */
100 HISTORY_STATE *
101 history_get_history_state (void)
102 {
103 HISTORY_STATE *state;
104
105 state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
106 state->entries = the_history;
107 state->offset = history_offset;
108 state->length = history_length;
109 state->size = history_size;
110 state->flags = 0;
111 if (history_stifled)
112 state->flags |= HS_STIFLED;
113
114 return (state);
115 }
116
117 /* Set the state of the current history array to STATE. */
118 void
119 history_set_history_state (HISTORY_STATE *state)
120 {
121 the_history = state->entries;
122 history_offset = state->offset;
123 history_length = state->length;
124 history_size = state->size;
125 if (state->flags & HS_STIFLED)
126 history_stifled = 1;
127 }
128
129 /* Begin a session in which the history functions might be used. This
130 initializes interactive variables. */
131 void
132 using_history (void)
133 {
134 history_offset = history_length;
135 }
136
137 /* Return the number of bytes that the primary history entries are using.
138 This just adds up the lengths of the_history->lines and the associated
139 timestamps. */
140 int
141 history_total_bytes (void)
142 {
143 register int i, result;
144
145 for (i = result = 0; the_history && the_history[i]; i++)
146 result += HISTENT_BYTES (the_history[i]);
147
148 return (result);
149 }
150
151 /* Returns the magic number which says what history element we are
152 looking at now. In this implementation, it returns history_offset. */
153 int
154 where_history (void)
155 {
156 return (history_offset);
157 }
158
159 /* Make the current history item be the one at POS, an absolute index.
160 Returns zero if POS is out of range, else non-zero. */
161 int
162 history_set_pos (int pos)
163 {
164 if (pos > history_length || pos < 0 || !the_history)
165 return (0);
166 history_offset = pos;
167 return (1);
168 }
169
170 /* Are we currently at the end of the history list? */
171 int
172 _hs_at_end_of_history (void)
173 {
174 return (the_history == 0 || history_offset == history_length);
175 }
176
177 /* Return the current history array. The caller has to be careful, since this
178 is the actual array of data, and could be bashed or made corrupt easily.
179 The array is terminated with a NULL pointer. */
180 HIST_ENTRY **
181 history_list (void)
182 {
183 return (the_history);
184 }
185
186 /* Return the history entry at the current position, as determined by
187 history_offset. If there is no entry there, return a NULL pointer. */
188 HIST_ENTRY *
189 current_history (void)
190 {
191 return ((history_offset == history_length) || the_history == 0)
192 ? (HIST_ENTRY *)NULL
193 : the_history[history_offset];
194 }
195
196 /* Back up history_offset to the previous history entry, and return
197 a pointer to that entry. If there is no previous entry then return
198 a NULL pointer. */
199 HIST_ENTRY *
200 previous_history (void)
201 {
202 return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
203 }
204
205 /* Move history_offset forward to the next history entry, and return
206 a pointer to that entry. If there is no next entry then return a
207 NULL pointer. */
208 HIST_ENTRY *
209 next_history (void)
210 {
211 return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
212 }
213
214 /* Return the history entry which is logically at OFFSET in the history array.
215 OFFSET is relative to history_base. */
216 HIST_ENTRY *
217 history_get (int offset)
218 {
219 int local_index;
220
221 local_index = offset - history_base;
222 return (local_index >= history_length || local_index < 0 || the_history == 0)
223 ? (HIST_ENTRY *)NULL
224 : the_history[local_index];
225 }
226
227 HIST_ENTRY *
228 alloc_history_entry (char *string, char *ts)
229 {
230 HIST_ENTRY *temp;
231
232 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
233
234 temp->line = string ? savestring (string) : string;
235 temp->data = (char *)NULL;
236 temp->timestamp = ts;
237
238 return temp;
239 }
240
241 time_t
242 history_get_time (HIST_ENTRY *hist)
243 {
244 char *ts;
245 time_t t;
246
247 if (hist == 0 || hist->timestamp == 0)
248 return 0;
249 ts = hist->timestamp;
250 if (ts[0] != history_comment_char)
251 return 0;
252 errno = 0;
253 t = (time_t) strtol (ts + 1, (char **)NULL, 10); /* XXX - should use strtol() here */
254 if (errno == ERANGE)
255 return (time_t)0;
256 return t;
257 }
258
259 static char *
260 hist_inittime (void)
261 {
262 time_t t;
263 char ts[64], *ret;
264
265 t = getnow ();
266 #if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
267 snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
268 #else
269 sprintf (ts, "X%lu", (unsigned long) t);
270 #endif
271 ret = savestring (ts);
272 ret[0] = history_comment_char;
273
274 return ret;
275 }
276
277 /* Place STRING at the end of the history list. The data field
278 is set to NULL. */
279 void
280 add_history (const char *string)
281 {
282 HIST_ENTRY *temp;
283 int new_length;
284
285 if (history_stifled && (history_length == history_max_entries))
286 {
287 /* If the history is stifled, and history_length is zero,
288 and it equals history_max_entries, we don't save items. */
289 if (history_length == 0)
290 return;
291
292 /* If there is something in the slot, then remove it. */
293 if (the_history[0])
294 (void) free_history_entry (the_history[0]);
295
296 /* Copy the rest of the entries, moving down one slot. Copy includes
297 trailing NULL. */
298 memmove (the_history, the_history + 1, history_length * sizeof (HIST_ENTRY *));
299
300 new_length = history_length;
301 history_base++;
302 }
303 else
304 {
305 if (history_size == 0)
306 {
307 if (history_stifled && history_max_entries > 0)
308 history_size = (history_max_entries > MAX_HISTORY_INITIAL_SIZE)
309 ? MAX_HISTORY_INITIAL_SIZE
310 : history_max_entries + 2;
311 else
312 history_size = DEFAULT_HISTORY_INITIAL_SIZE;
313 the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
314 new_length = 1;
315 }
316 else
317 {
318 if (history_length == (history_size - 1))
319 {
320 history_size += DEFAULT_HISTORY_GROW_SIZE;
321 the_history = (HIST_ENTRY **)
322 xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
323 }
324 new_length = history_length + 1;
325 }
326 }
327
328 temp = alloc_history_entry ((char *)string, hist_inittime ());
329
330 the_history[new_length] = (HIST_ENTRY *)NULL;
331 the_history[new_length - 1] = temp;
332 history_length = new_length;
333 }
334
335 /* Change the time stamp of the most recent history entry to STRING. */
336 void
337 add_history_time (const char *string)
338 {
339 HIST_ENTRY *hs;
340
341 if (string == 0 || history_length < 1)
342 return;
343 hs = the_history[history_length - 1];
344 FREE (hs->timestamp);
345 hs->timestamp = savestring (string);
346 }
347
348 /* Free HIST and return the data so the calling application can free it
349 if necessary and desired. */
350 histdata_t
351 free_history_entry (HIST_ENTRY *hist)
352 {
353 histdata_t x;
354
355 if (hist == 0)
356 return ((histdata_t) 0);
357 FREE (hist->line);
358 FREE (hist->timestamp);
359 x = hist->data;
360 xfree (hist);
361 return (x);
362 }
363
364 HIST_ENTRY *
365 copy_history_entry (HIST_ENTRY *hist)
366 {
367 HIST_ENTRY *ret;
368 char *ts;
369
370 if (hist == 0)
371 return hist;
372
373 ret = alloc_history_entry (hist->line, (char *)NULL);
374
375 ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp;
376 ret->timestamp = ts;
377
378 ret->data = hist->data;
379
380 return ret;
381 }
382
383 /* Make the history entry at WHICH have LINE and DATA. This returns
384 the old entry so you can dispose of the data. In the case of an
385 invalid WHICH, a NULL pointer is returned. */
386 HIST_ENTRY *
387 replace_history_entry (int which, const char *line, histdata_t data)
388 {
389 HIST_ENTRY *temp, *old_value;
390
391 if (which < 0 || which >= history_length)
392 return ((HIST_ENTRY *)NULL);
393
394 temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
395 old_value = the_history[which];
396
397 temp->line = savestring (line);
398 temp->data = data;
399 temp->timestamp = old_value->timestamp ? savestring (old_value->timestamp) : 0;
400 the_history[which] = temp;
401
402 return (old_value);
403 }
404
405 /* Append LINE to the history line at offset WHICH, adding a newline to the
406 end of the current line first. This can be used to construct multi-line
407 history entries while reading lines from the history file. */
408 void
409 _hs_append_history_line (int which, const char *line)
410 {
411 HIST_ENTRY *hent;
412 size_t newlen, curlen, minlen;
413 char *newline;
414
415 hent = the_history[which];
416 curlen = strlen (hent->line);
417 minlen = curlen + strlen (line) + 2; /* min space needed */
418 if (curlen > 256) /* XXX - for now */
419 {
420 newlen = 512; /* now realloc in powers of 2 */
421 /* we recalcluate every time; the operations are cheap */
422 while (newlen < minlen)
423 newlen <<= 1;
424 }
425 else
426 newlen = minlen;
427 /* Assume that realloc returns the same pointer and doesn't try a new
428 alloc/copy if the new size is the same as the one last passed. */
429 newline = realloc (hent->line, newlen);
430 if (newline)
431 {
432 hent->line = newline;
433 hent->line[curlen++] = '\n';
434 strcpy (hent->line + curlen, line);
435 }
436 }
437
438 /* Replace the DATA in the specified history entries, replacing OLD with
439 NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace
440 all of the history entries where entry->data == OLD; WHICH == -2 means
441 to replace the `newest' history entry where entry->data == OLD; and
442 WHICH >= 0 means to replace that particular history entry's data, as
443 long as it matches OLD. */
444 void
445 _hs_replace_history_data (int which, histdata_t *old, histdata_t *new)
446 {
447 HIST_ENTRY *entry;
448 register int i, last;
449
450 if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
451 return;
452
453 if (which >= 0)
454 {
455 entry = the_history[which];
456 if (entry && entry->data == old)
457 entry->data = new;
458 return;
459 }
460
461 last = -1;
462 for (i = history_length - 1; i >= 0; i--)
463 {
464 entry = the_history[i];
465 if (entry == 0)
466 continue;
467 if (entry->data == old)
468 {
469 last = i;
470 if (which == -1)
471 entry->data = new;
472 }
473 }
474 if (which == -2 && last >= 0)
475 {
476 entry = the_history[last];
477 entry->data = new; /* XXX - we don't check entry->old */
478 }
479 }
480
481 int
482 _hs_search_history_data (histdata_t *needle)
483 {
484 register int i;
485 HIST_ENTRY *entry;
486
487 if (history_length == 0 || the_history == 0)
488 return -1;
489
490 for (i = history_length - 1; i >= 0; i--)
491 {
492 entry = the_history[i];
493 if (entry == 0)
494 continue;
495 if (entry->data == needle)
496 return i;
497 }
498 return -1;
499 }
500
501 /* Remove history element WHICH from the history. The removed
502 element is returned to you so you can free the line, data,
503 and containing structure. */
504 HIST_ENTRY *
505 remove_history (int which)
506 {
507 HIST_ENTRY *return_value;
508 register int i;
509 #if 1
510 int nentries;
511 HIST_ENTRY **start, **end;
512 #endif
513
514 if (which < 0 || which >= history_length || history_length == 0 || the_history == 0)
515 return ((HIST_ENTRY *)NULL);
516
517 return_value = the_history[which];
518
519 #if 1
520 /* Copy the rest of the entries, moving down one slot. Copy includes
521 trailing NULL. */
522 nentries = history_length - which;
523 start = the_history + which;
524 end = start + 1;
525 memmove (start, end, nentries * sizeof (HIST_ENTRY *));
526 #else
527 for (i = which; i < history_length; i++)
528 the_history[i] = the_history[i + 1];
529 #endif
530
531 history_length--;
532
533 return (return_value);
534 }
535
536 HIST_ENTRY **
537 remove_history_range (int first, int last)
538 {
539 HIST_ENTRY **return_value;
540 register int i;
541 int nentries;
542 HIST_ENTRY **start, **end;
543
544 if (the_history == 0 || history_length == 0)
545 return ((HIST_ENTRY **)NULL);
546 if (first < 0 || first >= history_length || last < 0 || last >= history_length)
547 return ((HIST_ENTRY **)NULL);
548 if (first > last)
549 return (HIST_ENTRY **)NULL;
550
551 nentries = last - first + 1;
552 return_value = (HIST_ENTRY **)malloc ((nentries + 1) * sizeof (HIST_ENTRY *));
553 if (return_value == 0)
554 return return_value;
555
556 /* Return all the deleted entries in a list */
557 for (i = first ; i <= last; i++)
558 return_value[i - first] = the_history[i];
559 return_value[i - first] = (HIST_ENTRY *)NULL;
560
561 /* Copy the rest of the entries, moving down NENTRIES slots. Copy includes
562 trailing NULL. */
563 start = the_history + first;
564 end = the_history + last + 1;
565 memmove (start, end, (history_length - last) * sizeof (HIST_ENTRY *));
566
567 history_length -= nentries;
568
569 return (return_value);
570 }
571
572 /* Stifle the history list, remembering only MAX number of lines. */
573 void
574 stifle_history (int max)
575 {
576 register int i, j;
577
578 if (max < 0)
579 max = 0;
580
581 if (history_length > max)
582 {
583 /* This loses because we cannot free the data. */
584 for (i = 0, j = history_length - max; i < j; i++)
585 free_history_entry (the_history[i]);
586
587 history_base = i;
588 for (j = 0, i = history_length - max; j < max; i++, j++)
589 the_history[j] = the_history[i];
590 the_history[j] = (HIST_ENTRY *)NULL;
591 history_length = j;
592 }
593
594 history_stifled = 1;
595 max_input_history = history_max_entries = max;
596 }
597
598 /* Stop stifling the history. This returns the previous maximum
599 number of history entries. The value is positive if the history
600 was stifled, negative if it wasn't. */
601 int
602 unstifle_history (void)
603 {
604 if (history_stifled)
605 {
606 history_stifled = 0;
607 return (history_max_entries);
608 }
609 else
610 return (-history_max_entries);
611 }
612
613 int
614 history_is_stifled (void)
615 {
616 return (history_stifled);
617 }
618
619 void
620 clear_history (void)
621 {
622 register int i;
623
624 /* This loses because we cannot free the data. */
625 for (i = 0; i < history_length; i++)
626 {
627 free_history_entry (the_history[i]);
628 the_history[i] = (HIST_ENTRY *)NULL;
629 }
630
631 history_offset = history_length = 0;
632 history_base = 1; /* reset history base to default */
633 }