Hello,

  I attach a short .c example to demonstrate the actual problem,
    and I correct my message.
  It is the sum history_base + history_length which causes me grief.
  The behaviour of where_history() is unexpected to me, but I'm not
    sure whether its usage in ngspice is correct.

Regards,
  Robert

// adapted example from
//   (compile "wget -O - https://cnswww.cns.cwru.edu/php/chet/readline/history.html#SEC18 | html2text | perl -ne 'print if(/^  #include/../^  }/)' > ex-0.c")
//
//  (diff "ex-0.c" "ex-1.c" "-u0 -b -w")
//
// two compilation incantations, one for -lreadline, one for -ledit
//   (compile "gcc -o ex-1.e -Wall -DEDITLINE ex-1.c -ledit")
//   (compile "gcc -o ex-1.r -Wall -DREADLINE ex-1.c -lreadline")
//
// I expect history_base + history_length being the user visible position
//   the thing one might use to print a "prompt"
// This works for -lreadline, but doesn't for -ledit
// It is not obvious for me, whether where_history() should do something
//   similiar. It doesn't in different ways for both libraries
// In ngspice, there is a history_set_pos(history_length) before invoking
//   readline(). then where_history() does the job, but only for -lreadline
//
// call ex-1.l and ex-1.r, enter some lines, and compare the printed values
//   especially for history_base + history_length which does not increment beyond 1
//   for libedit
// enter "list" for additional curiosity
// further experiment entering "bla", "bla", "save",
// then restart and enter "read", "bla"
//  ==> history_length will jump as expected, but only after the next line

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#ifdef READLINE
#include <readline/history.h>
#endif
#ifdef EDITLINE
#include <editline/history.h>
#endif

int
main (argc, argv)
     int argc;
     char **argv;
{
    char line[1024], *t;
    int len, done = 0;

    line[0] = 0;

    using_history ();

    // stifle_history(5);

    while (!done)
    {
        // history_set_pos(history_length);
        printf ("history wh=%d / hb+hl=%d / hb=%d hl=%d > ",
                where_history(), history_base + history_length,
                history_base, history_length);
        fflush (stdout);
        t = fgets (line, sizeof (line) - 1, stdin);
        if (t && *t)
        {
            len = strlen (t);
            if (t[len - 1] == '\n')
                t[len - 1] = '\0';
        }

        if (!t)
            strcpy (line, "quit");

        if (line[0])
        {
            char *expansion;
            int result;

            result = history_expand (line, &expansion);
            if (result)
                fprintf (stderr, "%s\n", expansion);

            if (result < 0 || result == 2)
            {
                free (expansion);
                continue;
            }
            add_history (expansion);
            strncpy (line, expansion, sizeof (line) - 1);
            free (expansion);
        }

        if (strcmp (line, "quit") == 0)
            done = 1;
        else if (strcmp (line, "save") == 0)
            write_history ("history_file");
        else if (strcmp (line, "read") == 0)
            read_history ("history_file");
        else if (strcmp (line, "list") == 0)
        {
            register HIST_ENTRY **the_list = NULL;
            register int i;

#ifdef READLINE
            HISTORY_STATE *xx = history_get_history_state ();

            // offset+length seems to be the actual user visible history position

            the_list = history_list ();
            fprintf(stderr, "history_list() = %p, history_get_history_state()->entries = %p, ->offset=%d ->length=%d, ->size=%d\n",
                    the_list, xx->entries, xx->offset, xx->length, xx->size);
#endif
            fprintf (stderr, "  wh=%d / hb=%d hl=%d\n",
                     where_history(), history_base, history_length);
            if (the_list)
                for (i = 0; the_list[i]; i++)
                    printf ("%d: %s\n", i + history_base, the_list[i]->line);
        }
        else if (strncmp (line, "delete", 6) == 0)
        {
            int which;
            if ((sscanf (line + 6, "%d", &which)) == 1)
            {
                HIST_ENTRY *entry = remove_history (which);
                if (!entry)
                    fprintf (stderr, "No such entry %d\n", which);
                else
                {
                    free ((char *) entry->line);
                    free (entry);
                }
            }
            else
            {
                fprintf (stderr, "non-numeric arg given to `delete'\n");
            }
        }
    }

    exit(0);
}

Reply via email to