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

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

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