Annotation of embedaddon/readline/history.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>