1 /* history.c -- standalone history library */
3 /* Copyright (C) 1989-2021 Free Software Foundation, Inc.
5 This file contains the GNU History Library (History), a set of
6 routines for managing the text of previously typed lines.
8 History is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 History is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with History. If not, see <http://www.gnu.org/licenses/>.
22 /* 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
27 #if defined (HAVE_CONFIG_H)
33 #if defined (HAVE_STDLIB_H)
36 # include "ansi_stdlib.h"
37 #endif /* HAVE_STDLIB_H */
39 #if defined (HAVE_UNISTD_H)
41 # include <sys/types.h>
57 /* How big to make the_history when we first allocate it. */
58 #define DEFAULT_HISTORY_INITIAL_SIZE 502
60 #define MAX_HISTORY_INITIAL_SIZE 8192
62 /* The number of slots to increase the_history by. */
63 #define DEFAULT_HISTORY_GROW_SIZE 50
65 static char *hist_inittime (void);
67 /* **************************************************************** */
69 /* History Functions */
71 /* **************************************************************** */
73 /* An array of HIST_ENTRY. This is where we store the history. */
74 static HIST_ENTRY
**the_history
= (HIST_ENTRY
**)NULL
;
76 /* Non-zero means that we have enforced a limit on the amount of
77 history that we save. */
78 static int history_stifled
;
80 /* The current number of slots allocated to the input_history. */
81 static int history_size
;
83 /* If HISTORY_STIFLED is non-zero, then this is the maximum number of
84 entries to remember. */
85 int history_max_entries
;
86 int max_input_history
; /* backwards compatibility */
88 /* The current location of the interactive history pointer. Just makes
89 life easier for outside callers. */
92 /* The number of strings currently stored in the history list. */
95 /* The logical `base' of the history array. It defaults to 1. */
98 /* Return the current HISTORY_STATE of the history. */
100 history_get_history_state (void)
102 HISTORY_STATE
*state
;
104 state
= (HISTORY_STATE
*)xmalloc (sizeof (HISTORY_STATE
));
105 state
->entries
= the_history
;
106 state
->offset
= history_offset
;
107 state
->length
= history_length
;
108 state
->size
= history_size
;
111 state
->flags
|= HS_STIFLED
;
116 /* Set the state of the current history array to STATE. */
118 history_set_history_state (HISTORY_STATE
*state
)
120 the_history
= state
->entries
;
121 history_offset
= state
->offset
;
122 history_length
= state
->length
;
123 history_size
= state
->size
;
124 if (state
->flags
& HS_STIFLED
)
128 /* Begin a session in which the history functions might be used. This
129 initializes interactive variables. */
133 history_offset
= history_length
;
136 /* Return the number of bytes that the primary history entries are using.
137 This just adds up the lengths of the_history->lines and the associated
140 history_total_bytes (void)
142 register int i
, result
;
144 for (i
= result
= 0; the_history
&& the_history
[i
]; i
++)
145 result
+= HISTENT_BYTES (the_history
[i
]);
150 /* Returns the magic number which says what history element we are
151 looking at now. In this implementation, it returns history_offset. */
155 return (history_offset
);
158 /* Make the current history item be the one at POS, an absolute index.
159 Returns zero if POS is out of range, else non-zero. */
161 history_set_pos (int pos
)
163 if (pos
> history_length
|| pos
< 0 || !the_history
)
165 history_offset
= pos
;
169 /* Are we currently at the end of the history list? */
171 _hs_at_end_of_history (void)
173 return (the_history
== 0 || history_offset
== history_length
);
176 /* Return the current history array. The caller has to be careful, since this
177 is the actual array of data, and could be bashed or made corrupt easily.
178 The array is terminated with a NULL pointer. */
182 return (the_history
);
185 /* Return the history entry at the current position, as determined by
186 history_offset. If there is no entry there, return a NULL pointer. */
188 current_history (void)
190 return ((history_offset
== history_length
) || the_history
== 0)
192 : the_history
[history_offset
];
195 /* Back up history_offset to the previous history entry, and return
196 a pointer to that entry. If there is no previous entry then return
199 previous_history (void)
201 return history_offset
? the_history
[--history_offset
] : (HIST_ENTRY
*)NULL
;
204 /* Move history_offset forward to the next history entry, and return
205 a pointer to that entry. If there is no next entry then return a
210 return (history_offset
== history_length
) ? (HIST_ENTRY
*)NULL
: the_history
[++history_offset
];
213 /* Return the history entry which is logically at OFFSET in the history array.
214 OFFSET is relative to history_base. */
216 history_get (int offset
)
220 local_index
= offset
- history_base
;
221 return (local_index
>= history_length
|| local_index
< 0 || the_history
== 0)
223 : the_history
[local_index
];
227 alloc_history_entry (char *string
, char *ts
)
231 temp
= (HIST_ENTRY
*)xmalloc (sizeof (HIST_ENTRY
));
233 temp
->line
= string
? savestring (string
) : string
;
234 temp
->data
= (char *)NULL
;
235 temp
->timestamp
= ts
;
241 history_get_time (HIST_ENTRY
*hist
)
246 if (hist
== 0 || hist
->timestamp
== 0)
248 ts
= hist
->timestamp
;
249 if (ts
[0] != history_comment_char
)
252 t
= (time_t) strtol (ts
+ 1, (char **)NULL
, 10); /* XXX - should use strtol() here */
264 t
= (time_t) time ((time_t *)0);
265 #if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
266 snprintf (ts
, sizeof (ts
) - 1, "X%lu", (unsigned long) t
);
268 sprintf (ts
, "X%lu", (unsigned long) t
);
270 ret
= savestring (ts
);
271 ret
[0] = history_comment_char
;
276 /* Place STRING at the end of the history list. The data field
279 add_history (const char *string
)
284 if (history_stifled
&& (history_length
== history_max_entries
))
286 /* If the history is stifled, and history_length is zero,
287 and it equals history_max_entries, we don't save items. */
288 if (history_length
== 0)
291 /* If there is something in the slot, then remove it. */
293 (void) free_history_entry (the_history
[0]);
295 /* Copy the rest of the entries, moving down one slot. Copy includes
297 memmove (the_history
, the_history
+ 1, history_length
* sizeof (HIST_ENTRY
*));
299 new_length
= history_length
;
304 if (history_size
== 0)
306 if (history_stifled
&& history_max_entries
> 0)
307 history_size
= (history_max_entries
> MAX_HISTORY_INITIAL_SIZE
)
308 ? MAX_HISTORY_INITIAL_SIZE
309 : history_max_entries
+ 2;
311 history_size
= DEFAULT_HISTORY_INITIAL_SIZE
;
312 the_history
= (HIST_ENTRY
**)xmalloc (history_size
* sizeof (HIST_ENTRY
*));
317 if (history_length
== (history_size
- 1))
319 history_size
+= DEFAULT_HISTORY_GROW_SIZE
;
320 the_history
= (HIST_ENTRY
**)
321 xrealloc (the_history
, history_size
* sizeof (HIST_ENTRY
*));
323 new_length
= history_length
+ 1;
327 temp
= alloc_history_entry ((char *)string
, hist_inittime ());
329 the_history
[new_length
] = (HIST_ENTRY
*)NULL
;
330 the_history
[new_length
- 1] = temp
;
331 history_length
= new_length
;
334 /* Change the time stamp of the most recent history entry to STRING. */
336 add_history_time (const char *string
)
340 if (string
== 0 || history_length
< 1)
342 hs
= the_history
[history_length
- 1];
343 FREE (hs
->timestamp
);
344 hs
->timestamp
= savestring (string
);
347 /* Free HIST and return the data so the calling application can free it
348 if necessary and desired. */
350 free_history_entry (HIST_ENTRY
*hist
)
355 return ((histdata_t
) 0);
357 FREE (hist
->timestamp
);
364 copy_history_entry (HIST_ENTRY
*hist
)
372 ret
= alloc_history_entry (hist
->line
, (char *)NULL
);
374 ts
= hist
->timestamp
? savestring (hist
->timestamp
) : hist
->timestamp
;
377 ret
->data
= hist
->data
;
382 /* Make the history entry at WHICH have LINE and DATA. This returns
383 the old entry so you can dispose of the data. In the case of an
384 invalid WHICH, a NULL pointer is returned. */
386 replace_history_entry (int which
, const char *line
, histdata_t data
)
388 HIST_ENTRY
*temp
, *old_value
;
390 if (which
< 0 || which
>= history_length
)
391 return ((HIST_ENTRY
*)NULL
);
393 temp
= (HIST_ENTRY
*)xmalloc (sizeof (HIST_ENTRY
));
394 old_value
= the_history
[which
];
396 temp
->line
= savestring (line
);
398 temp
->timestamp
= old_value
->timestamp
? savestring (old_value
->timestamp
) : 0;
399 the_history
[which
] = temp
;
404 /* Append LINE to the history line at offset WHICH, adding a newline to the
405 end of the current line first. This can be used to construct multi-line
406 history entries while reading lines from the history file. */
408 _hs_append_history_line (int which
, const char *line
)
411 size_t newlen
, curlen
, minlen
;
414 hent
= the_history
[which
];
415 curlen
= strlen (hent
->line
);
416 minlen
= curlen
+ strlen (line
) + 2; /* min space needed */
417 if (curlen
> 256) /* XXX - for now */
419 newlen
= 512; /* now realloc in powers of 2 */
420 /* we recalcluate every time; the operations are cheap */
421 while (newlen
< minlen
)
426 /* Assume that realloc returns the same pointer and doesn't try a new
427 alloc/copy if the new size is the same as the one last passed. */
428 newline
= realloc (hent
->line
, newlen
);
431 hent
->line
= newline
;
432 hent
->line
[curlen
++] = '\n';
433 strcpy (hent
->line
+ curlen
, line
);
437 /* Replace the DATA in the specified history entries, replacing OLD with
438 NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace
439 all of the history entries where entry->data == OLD; WHICH == -2 means
440 to replace the `newest' history entry where entry->data == OLD; and
441 WHICH >= 0 means to replace that particular history entry's data, as
442 long as it matches OLD. */
444 _hs_replace_history_data (int which
, histdata_t
*old
, histdata_t
*new)
447 register int i
, last
;
449 if (which
< -2 || which
>= history_length
|| history_length
== 0 || the_history
== 0)
454 entry
= the_history
[which
];
455 if (entry
&& entry
->data
== old
)
461 for (i
= 0; i
< history_length
; i
++)
463 entry
= the_history
[i
];
466 if (entry
->data
== old
)
473 if (which
== -2 && last
>= 0)
475 entry
= the_history
[last
];
476 entry
->data
= new; /* XXX - we don't check entry->old */
480 /* Remove history element WHICH from the history. The removed
481 element is returned to you so you can free the line, data,
482 and containing structure. */
484 remove_history (int which
)
486 HIST_ENTRY
*return_value
;
490 HIST_ENTRY
**start
, **end
;
493 if (which
< 0 || which
>= history_length
|| history_length
== 0 || the_history
== 0)
494 return ((HIST_ENTRY
*)NULL
);
496 return_value
= the_history
[which
];
499 /* Copy the rest of the entries, moving down one slot. Copy includes
501 nentries
= history_length
- which
;
502 start
= the_history
+ which
;
504 memmove (start
, end
, nentries
* sizeof (HIST_ENTRY
*));
506 for (i
= which
; i
< history_length
; i
++)
507 the_history
[i
] = the_history
[i
+ 1];
512 return (return_value
);
516 remove_history_range (int first
, int last
)
518 HIST_ENTRY
**return_value
;
521 HIST_ENTRY
**start
, **end
;
523 if (the_history
== 0 || history_length
== 0)
524 return ((HIST_ENTRY
**)NULL
);
525 if (first
< 0 || first
>= history_length
|| last
< 0 || last
>= history_length
)
526 return ((HIST_ENTRY
**)NULL
);
528 return (HIST_ENTRY
**)NULL
;
530 nentries
= last
- first
+ 1;
531 return_value
= (HIST_ENTRY
**)malloc ((nentries
+ 1) * sizeof (HIST_ENTRY
*));
532 if (return_value
== 0)
535 /* Return all the deleted entries in a list */
536 for (i
= first
; i
<= last
; i
++)
537 return_value
[i
- first
] = the_history
[i
];
538 return_value
[i
- first
] = (HIST_ENTRY
*)NULL
;
540 /* Copy the rest of the entries, moving down NENTRIES slots. Copy includes
542 start
= the_history
+ first
;
543 end
= the_history
+ last
+ 1;
544 memmove (start
, end
, (history_length
- last
) * sizeof (HIST_ENTRY
*));
546 history_length
-= nentries
;
548 return (return_value
);
551 /* Stifle the history list, remembering only MAX number of lines. */
553 stifle_history (int max
)
560 if (history_length
> max
)
562 /* This loses because we cannot free the data. */
563 for (i
= 0, j
= history_length
- max
; i
< j
; i
++)
564 free_history_entry (the_history
[i
]);
567 for (j
= 0, i
= history_length
- max
; j
< max
; i
++, j
++)
568 the_history
[j
] = the_history
[i
];
569 the_history
[j
] = (HIST_ENTRY
*)NULL
;
574 max_input_history
= history_max_entries
= max
;
577 /* Stop stifling the history. This returns the previous maximum
578 number of history entries. The value is positive if the history
579 was stifled, negative if it wasn't. */
581 unstifle_history (void)
586 return (history_max_entries
);
589 return (-history_max_entries
);
593 history_is_stifled (void)
595 return (history_stifled
);
603 /* This loses because we cannot free the data. */
604 for (i
= 0; i
< history_length
; i
++)
606 free_history_entry (the_history
[i
]);
607 the_history
[i
] = (HIST_ENTRY
*)NULL
;
610 history_offset
= history_length
= 0;
611 history_base
= 1; /* reset history base to default */