1 /* history.c -- standalone history library */
3 /* Copyright (C) 1989-2015 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
PARAMS((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 ()
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 (state
)
119 HISTORY_STATE
*state
;
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
)
129 /* Begin a session in which the history functions might be used. This
130 initializes interactive variables. */
134 history_offset
= history_length
;
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
141 history_total_bytes ()
143 register int i
, result
;
145 for (i
= result
= 0; the_history
&& the_history
[i
]; i
++)
146 result
+= HISTENT_BYTES (the_history
[i
]);
151 /* Returns the magic number which says what history element we are
152 looking at now. In this implementation, it returns history_offset. */
156 return (history_offset
);
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. */
162 history_set_pos (pos
)
165 if (pos
> history_length
|| pos
< 0 || !the_history
)
167 history_offset
= pos
;
171 /* Return the current history array. The caller has to be careful, since this
172 is the actual array of data, and could be bashed or made corrupt easily.
173 The array is terminated with a NULL pointer. */
177 return (the_history
);
180 /* Return the history entry at the current position, as determined by
181 history_offset. If there is no entry there, return a NULL pointer. */
185 return ((history_offset
== history_length
) || the_history
== 0)
187 : the_history
[history_offset
];
190 /* Back up history_offset to the previous history entry, and return
191 a pointer to that entry. If there is no previous entry then return
196 return history_offset
? the_history
[--history_offset
] : (HIST_ENTRY
*)NULL
;
199 /* Move history_offset forward to the next history entry, and return
200 a pointer to that entry. If there is no next entry then return a
205 return (history_offset
== history_length
) ? (HIST_ENTRY
*)NULL
: the_history
[++history_offset
];
208 /* Return the history entry which is logically at OFFSET in the history array.
209 OFFSET is relative to history_base. */
216 local_index
= offset
- history_base
;
217 return (local_index
>= history_length
|| local_index
< 0 || the_history
== 0)
219 : the_history
[local_index
];
223 alloc_history_entry (string
, ts
)
229 temp
= (HIST_ENTRY
*)xmalloc (sizeof (HIST_ENTRY
));
231 temp
->line
= string
? savestring (string
) : string
;
232 temp
->data
= (char *)NULL
;
233 temp
->timestamp
= ts
;
239 history_get_time (hist
)
245 if (hist
== 0 || hist
->timestamp
== 0)
247 ts
= hist
->timestamp
;
248 if (ts
[0] != history_comment_char
)
251 t
= (time_t) strtol (ts
+ 1, (char **)NULL
, 10); /* XXX - should use strtol() here */
263 t
= (time_t) time ((time_t *)0);
264 #if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
265 snprintf (ts
, sizeof (ts
) - 1, "X%lu", (unsigned long) t
);
267 sprintf (ts
, "X%lu", (unsigned long) t
);
269 ret
= savestring (ts
);
270 ret
[0] = history_comment_char
;
275 /* Place STRING at the end of the history list. The data field
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 (string
)
343 if (string
== 0 || history_length
< 1)
345 hs
= the_history
[history_length
- 1];
346 FREE (hs
->timestamp
);
347 hs
->timestamp
= savestring (string
);
350 /* Free HIST and return the data so the calling application can free it
351 if necessary and desired. */
353 free_history_entry (hist
)
359 return ((histdata_t
) 0);
361 FREE (hist
->timestamp
);
368 copy_history_entry (hist
)
377 ret
= alloc_history_entry (hist
->line
, (char *)NULL
);
379 ts
= hist
->timestamp
? savestring (hist
->timestamp
) : hist
->timestamp
;
382 ret
->data
= hist
->data
;
387 /* Make the history entry at WHICH have LINE and DATA. This returns
388 the old entry so you can dispose of the data. In the case of an
389 invalid WHICH, a NULL pointer is returned. */
391 replace_history_entry (which
, line
, data
)
396 HIST_ENTRY
*temp
, *old_value
;
398 if (which
< 0 || which
>= history_length
)
399 return ((HIST_ENTRY
*)NULL
);
401 temp
= (HIST_ENTRY
*)xmalloc (sizeof (HIST_ENTRY
));
402 old_value
= the_history
[which
];
404 temp
->line
= savestring (line
);
406 temp
->timestamp
= savestring (old_value
->timestamp
);
407 the_history
[which
] = temp
;
412 /* Append LINE to the history line at offset WHICH, adding a newline to the
413 end of the current line first. This can be used to construct multi-line
414 history entries while reading lines from the history file. */
416 _hs_append_history_line (which
, line
)
421 size_t newlen
, curlen
;
424 hent
= the_history
[which
];
425 curlen
= strlen (hent
->line
);
426 newlen
= curlen
+ strlen (line
) + 2;
427 newline
= realloc (hent
->line
, newlen
);
430 hent
->line
= newline
;
431 hent
->line
[curlen
++] = '\n';
432 strcpy (hent
->line
+ curlen
, line
);
436 /* Replace the DATA in the specified history entries, replacing OLD with
437 NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace
438 all of the history entries where entry->data == OLD; WHICH == -2 means
439 to replace the `newest' history entry where entry->data == OLD; and
440 WHICH >= 0 means to replace that particular history entry's data, as
441 long as it matches OLD. */
443 _hs_replace_history_data (which
, old
, new)
445 histdata_t
*old
, *new;
448 register int i
, last
;
450 if (which
< -2 || which
>= history_length
|| history_length
== 0 || the_history
== 0)
455 entry
= the_history
[which
];
456 if (entry
&& entry
->data
== old
)
462 for (i
= 0; i
< history_length
; i
++)
464 entry
= the_history
[i
];
467 if (entry
->data
== old
)
474 if (which
== -2 && last
>= 0)
476 entry
= the_history
[last
];
477 entry
->data
= new; /* XXX - we don't check entry->old */
481 /* Remove history element WHICH from the history. The removed
482 element is returned to you so you can free the line, data,
483 and containing structure. */
485 remove_history (which
)
488 HIST_ENTRY
*return_value
;
491 if (which
< 0 || which
>= history_length
|| history_length
== 0 || the_history
== 0)
492 return ((HIST_ENTRY
*)NULL
);
494 return_value
= the_history
[which
];
496 for (i
= which
; i
< history_length
; i
++)
497 the_history
[i
] = the_history
[i
+ 1];
501 return (return_value
);
504 /* Stifle the history list, remembering only MAX number of lines. */
514 if (history_length
> max
)
516 /* This loses because we cannot free the data. */
517 for (i
= 0, j
= history_length
- max
; i
< j
; i
++)
518 free_history_entry (the_history
[i
]);
521 for (j
= 0, i
= history_length
- max
; j
< max
; i
++, j
++)
522 the_history
[j
] = the_history
[i
];
523 the_history
[j
] = (HIST_ENTRY
*)NULL
;
528 max_input_history
= history_max_entries
= max
;
531 /* Stop stifling the history. This returns the previous maximum
532 number of history entries. The value is positive if the history
533 was stifled, negative if it wasn't. */
540 return (history_max_entries
);
543 return (-history_max_entries
);
547 history_is_stifled ()
549 return (history_stifled
);
557 /* This loses because we cannot free the data. */
558 for (i
= 0; i
< history_length
; i
++)
560 free_history_entry (the_history
[i
]);
561 the_history
[i
] = (HIST_ENTRY
*)NULL
;
564 history_offset
= history_length
= 0;