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
))
288 /* If the history is stifled, and history_length is zero,
289 and it equals history_max_entries, we don't save items. */
290 if (history_length
== 0)
293 /* If there is something in the slot, then remove it. */
295 (void) free_history_entry (the_history
[0]);
297 /* Copy the rest of the entries, moving down one slot. Copy includes
299 memmove (the_history
, the_history
+ 1, history_length
* sizeof (HIST_ENTRY
*));
301 new_length
= history_length
;
306 if (history_size
== 0)
308 if (history_stifled
&& history_max_entries
> 0)
309 history_size
= (history_max_entries
> MAX_HISTORY_INITIAL_SIZE
)
310 ? MAX_HISTORY_INITIAL_SIZE
311 : history_max_entries
+ 2;
313 history_size
= DEFAULT_HISTORY_INITIAL_SIZE
;
314 the_history
= (HIST_ENTRY
**)xmalloc (history_size
* sizeof (HIST_ENTRY
*));
319 if (history_length
== (history_size
- 1))
321 history_size
+= DEFAULT_HISTORY_GROW_SIZE
;
322 the_history
= (HIST_ENTRY
**)
323 xrealloc (the_history
, history_size
* sizeof (HIST_ENTRY
*));
325 new_length
= history_length
+ 1;
329 temp
= alloc_history_entry ((char *)string
, hist_inittime ());
331 the_history
[new_length
] = (HIST_ENTRY
*)NULL
;
332 the_history
[new_length
- 1] = temp
;
333 history_length
= new_length
;
336 /* Change the time stamp of the most recent history entry to STRING. */
338 add_history_time (const char *string
)
342 if (string
== 0 || history_length
< 1)
344 hs
= the_history
[history_length
- 1];
345 FREE (hs
->timestamp
);
346 hs
->timestamp
= savestring (string
);
349 /* Free HIST and return the data so the calling application can free it
350 if necessary and desired. */
352 free_history_entry (HIST_ENTRY
*hist
)
357 return ((histdata_t
) 0);
359 FREE (hist
->timestamp
);
366 copy_history_entry (HIST_ENTRY
*hist
)
374 ret
= alloc_history_entry (hist
->line
, (char *)NULL
);
376 ts
= hist
->timestamp
? savestring (hist
->timestamp
) : hist
->timestamp
;
379 ret
->data
= hist
->data
;
384 /* Make the history entry at WHICH have LINE and DATA. This returns
385 the old entry so you can dispose of the data. In the case of an
386 invalid WHICH, a NULL pointer is returned. */
388 replace_history_entry (int which
, const char *line
, histdata_t data
)
390 HIST_ENTRY
*temp
, *old_value
;
392 if (which
< 0 || which
>= history_length
)
393 return ((HIST_ENTRY
*)NULL
);
395 temp
= (HIST_ENTRY
*)xmalloc (sizeof (HIST_ENTRY
));
396 old_value
= the_history
[which
];
398 temp
->line
= savestring (line
);
400 temp
->timestamp
= old_value
->timestamp
? savestring (old_value
->timestamp
) : 0;
401 the_history
[which
] = temp
;
406 /* Append LINE to the history line at offset WHICH, adding a newline to the
407 end of the current line first. This can be used to construct multi-line
408 history entries while reading lines from the history file. */
410 _hs_append_history_line (int which
, const char *line
)
413 size_t newlen
, curlen
, minlen
;
416 hent
= the_history
[which
];
417 curlen
= strlen (hent
->line
);
418 minlen
= curlen
+ strlen (line
) + 2; /* min space needed */
419 if (curlen
> 256) /* XXX - for now */
421 newlen
= 512; /* now realloc in powers of 2 */
422 /* we recalcluate every time; the operations are cheap */
423 while (newlen
< minlen
)
428 /* Assume that realloc returns the same pointer and doesn't try a new
429 alloc/copy if the new size is the same as the one last passed. */
430 newline
= realloc (hent
->line
, newlen
);
433 hent
->line
= newline
;
434 hent
->line
[curlen
++] = '\n';
435 strcpy (hent
->line
+ curlen
, line
);
439 /* Replace the DATA in the specified history entries, replacing OLD with
440 NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace
441 all of the history entries where entry->data == OLD; WHICH == -2 means
442 to replace the `newest' history entry where entry->data == OLD; and
443 WHICH >= 0 means to replace that particular history entry's data, as
444 long as it matches OLD. */
446 _hs_replace_history_data (int which
, histdata_t
*old
, histdata_t
*new)
449 register int i
, last
;
451 if (which
< -2 || which
>= history_length
|| history_length
== 0 || the_history
== 0)
456 entry
= the_history
[which
];
457 if (entry
&& entry
->data
== old
)
463 for (i
= 0; i
< history_length
; i
++)
465 entry
= the_history
[i
];
468 if (entry
->data
== old
)
475 if (which
== -2 && last
>= 0)
477 entry
= the_history
[last
];
478 entry
->data
= new; /* XXX - we don't check entry->old */
482 /* Remove history element WHICH from the history. The removed
483 element is returned to you so you can free the line, data,
484 and containing structure. */
486 remove_history (int which
)
488 HIST_ENTRY
*return_value
;
492 HIST_ENTRY
**start
, **end
;
495 if (which
< 0 || which
>= history_length
|| history_length
== 0 || the_history
== 0)
496 return ((HIST_ENTRY
*)NULL
);
498 return_value
= the_history
[which
];
501 /* Copy the rest of the entries, moving down one slot. Copy includes
503 nentries
= history_length
- which
;
504 start
= the_history
+ which
;
506 memmove (start
, end
, nentries
* sizeof (HIST_ENTRY
*));
508 for (i
= which
; i
< history_length
; i
++)
509 the_history
[i
] = the_history
[i
+ 1];
514 return (return_value
);
518 remove_history_range (int first
, int last
)
520 HIST_ENTRY
**return_value
;
523 HIST_ENTRY
**start
, **end
;
525 if (the_history
== 0 || history_length
== 0)
526 return ((HIST_ENTRY
**)NULL
);
527 if (first
< 0 || first
>= history_length
|| last
< 0 || last
>= history_length
)
528 return ((HIST_ENTRY
**)NULL
);
530 return (HIST_ENTRY
**)NULL
;
532 nentries
= last
- first
+ 1;
533 return_value
= (HIST_ENTRY
**)malloc ((nentries
+ 1) * sizeof (HIST_ENTRY
*));
534 if (return_value
== 0)
537 /* Return all the deleted entries in a list */
538 for (i
= first
; i
<= last
; i
++)
539 return_value
[i
- first
] = the_history
[i
];
540 return_value
[i
- first
] = (HIST_ENTRY
*)NULL
;
542 /* Copy the rest of the entries, moving down NENTRIES slots. Copy includes
544 start
= the_history
+ first
;
545 end
= the_history
+ last
+ 1;
546 memmove (start
, end
, (history_length
- last
) * sizeof (HIST_ENTRY
*));
548 history_length
-= nentries
;
550 return (return_value
);
553 /* Stifle the history list, remembering only MAX number of lines. */
555 stifle_history (int max
)
562 if (history_length
> max
)
564 /* This loses because we cannot free the data. */
565 for (i
= 0, j
= history_length
- max
; i
< j
; i
++)
566 free_history_entry (the_history
[i
]);
569 for (j
= 0, i
= history_length
- max
; j
< max
; i
++, j
++)
570 the_history
[j
] = the_history
[i
];
571 the_history
[j
] = (HIST_ENTRY
*)NULL
;
576 max_input_history
= history_max_entries
= max
;
579 /* Stop stifling the history. This returns the previous maximum
580 number of history entries. The value is positive if the history
581 was stifled, negative if it wasn't. */
583 unstifle_history (void)
588 return (history_max_entries
);
591 return (-history_max_entries
);
595 history_is_stifled (void)
597 return (history_stifled
);
605 /* This loses because we cannot free the data. */
606 for (i
= 0; i
< history_length
; i
++)
608 free_history_entry (the_history
[i
]);
609 the_history
[i
] = (HIST_ENTRY
*)NULL
;
612 history_offset
= history_length
= 0;
613 history_base
= 1; /* reset history base to default */