⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 com_history.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group$Id: com_history.c,v 1.8 2005/05/21 13:25:28 sjborley Exp $**********//* Do history substitutions.  */#include <ngspice.h>#include <cpdefs.h>#include "com_history.h"#ifdef HAVE_GNUREADLINE/* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */#include <readline/readline.h>#include <readline/history.h>#endif /* HAVE_GNUREADLINE */#ifdef HAVE_BSDEDITLINE/* SJB added edit line support 2005-05-05 */#include <editline/readline.h>#endif /* HAVE_BSDEDITLINE *//* static declarations */static wordlist * dohsubst(char *string);static wordlist * dohmod(char **string, wordlist *wl);static wordlist * hpattern(char *buf);static wordlist * hprefix(char *buf);static wordlist * getevent(int num);#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)static void freehist(int num);#endifstatic char * dohs(char *pat, char *str);struct histent *cp_lastone = NULL;int cp_maxhistlength = 10000;        /* Chris Inbody */char cp_hat = '^';char cp_bang = '!';bool cp_didhsubst;static struct histent *histlist = NULL;static int histlength = 0;/* First check for a ^ at the beginning of the line, and then search * each word for !. Following this can be any of string, number, * ?string, -number ; then there may be a word specifier, the same as * csh, and then the : modifiers. For the :s modifier, the syntax is * :sXoooXnnnX, where X is any character, and ooo and nnn are strings * not containing X. */wordlist *cp_histsubst(wordlist *wlist){    wordlist *nwl, *w, *n;    char buf[BSIZE_SP], *s, *b;    /* Replace ^old^new with !:s^old^new. */    cp_didhsubst = FALSE;    if (*wlist->wl_word == cp_hat) {        (void) sprintf(buf, "%c%c:s%s", cp_bang, cp_bang,             wlist->wl_word);        tfree(wlist->wl_word);        wlist->wl_word = copy(buf);    }    for (w = wlist; w; w = w->wl_next) {        b = w->wl_word;        for (s = b; *s; s++)            if (*s == cp_bang) {                cp_didhsubst = TRUE;                n = dohsubst(s + 1);                if (!n) {                    wlist->wl_word = NULL;                    return (wlist);                }                if (b < s) {                    (void) sprintf(buf, "%.*s%s", (int)(s-b), b,                         n->wl_word);                    tfree(n->wl_word);                    n->wl_word = copy(buf);                }                nwl = wl_splice(w, n);                if (wlist == w)                    wlist = n;                w = nwl;                break;            }    }    return (wlist);}/* Do a history substitution on one word. Figure out which event is * being referenced, then do word selections and modifications, and * then stick anything left over on the end of the last word. */static wordlist *dohsubst(char *string){    wordlist *wl, *nwl;    char buf[BSIZE_SP], *s, *r = NULL, *t;    if (*string == cp_bang) {        if (cp_lastone) {            wl = cp_lastone->hi_wlist;            string++;        } else {            fprintf(cp_err, "0: event not found.\n");            return (NULL);        }    } else {        switch(*string) {            case '-':            wl = getevent(cp_event - scannum(++string));            if (!wl)                return (NULL);            while (isdigit(*string))                string++;            break;            case '?':            (void) strcpy(buf, string + 1);            if ((s =strchr(buf, '?')))                *s = '\0';            wl = hpattern(buf);            if (!wl)                return (NULL);            if (s == NULL) /* No modifiers on this one. */                return (wl_copy(wl));            break;            case '\0':  /* Maybe this should be cp_event. */            wl = alloc(struct wordlist);            wl->wl_word = copy("!");            wl->wl_next = NULL;            wl->wl_prev = NULL;            cp_didhsubst = FALSE;            return (wl);            default:            if (isdigit(*string)) {                wl = getevent(scannum(string));                if (!wl)                    return (NULL);                while (isdigit(*string))                    string++;            } else {                (void) strcpy(buf, string);                for (s = ":^$*-%"; *s; s++) {                    t =strchr(buf, *s);                    if (t && ((t < r) || !r)) {                        r = t;                        string += r - buf;                    }                }                if (r)                    *r = '\0';                else                     while (*string)                        string++;                if ((buf[0] == '\0') && cp_lastone)                    wl = cp_lastone->hi_wlist;                else                    wl = hprefix(buf);                if (!wl)                    return (NULL);            }        }    }    if (wl == NULL) {   /* Shouldn't happen. */        fprintf(cp_err, "Event not found.\n");        return (NULL);    }    nwl = dohmod(&string, wl_copy(wl));    if (!nwl)        return (NULL);    if (*string) {        for (wl = nwl; wl->wl_next; wl = wl->wl_next)            ;        (void) sprintf(buf, "%s%s", wl->wl_word, string);        tfree(wl->wl_word);        wl->wl_word = copy(buf);    }    return (nwl);}static wordlist *dohmod(char **string, wordlist *wl){    wordlist *w;    char *s;    char *r = NULL, *t;    int numwords, eventlo, eventhi, i;    bool globalsubst;anothermod:    numwords = wl_length(wl);    globalsubst = FALSE;    eventlo = 0;    eventhi = numwords - 1;    /* Now we know what wordlist we want. Take care of modifiers now. */    r = NULL;    for (s = ":^$*-%"; *s; s++) {        t =strchr(*string, *s);        if (t && ((t < r) || (r == NULL)))            r = t;    }    if (!r)     /* No more modifiers. */        return (wl);    *string = r;    if (**string == ':')        (*string)++;    switch(**string) {        case '$':   /* Last word. */            eventhi = eventlo = numwords - 1;            break;        case '*':   /* Words 1 through $ */            if (numwords == 1)                return (NULL);            eventlo = 1;            eventhi = numwords - 1;            break;        case '-':   /* Words 0 through ... */            eventlo = 0;            if (*(*string + 1))                eventhi = scannum(*string + 1);            else                eventhi = numwords - 1;            if (eventhi > numwords - 1)                eventhi = numwords - 1;            break;        case 'p':   /* Print the command and don't execute it.                  * This doesn't work quite like csh.                 */            wl_print(wl, cp_out);            (void) putc('\n', cp_out);            return (NULL);        case 's':   /* Do a substitution. */            for (w = wl; w; w = w->wl_next) {                s = dohs(*string + 1, w->wl_word);                if (s) {                    tfree(w->wl_word);                    w->wl_word = s;                    if (globalsubst == FALSE) {                        while (**string)                            (*string)++;                        break;                    }                }            }            /* In case globalsubst is TRUE... */            while (**string)                (*string)++;            break;        default:            if (!isdigit(**string)) {                fprintf(cp_err, "Error: %s: bad modifier.\n",                    *string);                return (NULL);            }            i = scannum(*string);            if (i > eventhi) {                fprintf(cp_err, "Error: bad event number %d\n",                        i);                return (NULL);            }            eventhi = eventlo = i;            while (isdigit(**string))                (*string)++;            if (**string == '*')                eventhi = numwords - 1;            if (**string == '-') {                if (!isdigit(*(*string + 1)))                    eventhi = numwords - 1;                else {                    eventhi = scannum(++*string);                    while (isdigit(**string))                        (*string)++;                }	    }    }    /* Now change the word list accordingly and make another pass     * if there is more of the substitute left.     */        wl = wl_range(wl, eventlo, eventhi);    numwords = wl_length(wl);    if (**string && *++*string)        goto anothermod;    return (wl);}/* Look for an event with a pattern in it... */static wordlist *hpattern(char *buf){    struct histent *hi;    wordlist *wl;    if (*buf == '\0') {        fprintf(cp_err, "Bad pattern specification.\n");        return (NULL);    }    for (hi = cp_lastone; hi; hi = hi->hi_prev)        for (wl = hi->hi_wlist; wl; wl = wl->wl_next)            if (substring(buf, wl->wl_word))                return (hi->hi_wlist);    fprintf(cp_err, "%s: event not found.\n", buf);    return (NULL);}static wordlist *hprefix(char *buf){    struct histent *hi;    if (*buf == '\0') {        fprintf(cp_err, "Bad pattern specification.\n");        return (NULL);    }    for (hi = cp_lastone; hi; hi = hi->hi_prev)        if (hi->hi_wlist && prefix(buf, hi->hi_wlist->wl_word))            return (hi->hi_wlist);    fprintf(cp_err, "%s: event not found.\n", buf);    return (NULL);}/* Add a wordlist to the history list. (Done after the first parse.) Note * that if event numbers are given in a random order that's how they'll * show up in the history list. */voidcp_addhistent(int event, wordlist *wlist){	/* MW. This test is not needed if everything works right 	if (cp_lastone && !cp_lastone->hi_wlist)        fprintf(cp_err, "Internal error: bad history list\n"); */            if (cp_lastone == NULL) {/* MW. the begging - initialize histlength*/	histlength = 1;		         cp_lastone = histlist = alloc(struct histent);        cp_lastone->hi_prev = NULL;    } else {        cp_lastone->hi_next = alloc(struct histent);        cp_lastone->hi_next->hi_prev = cp_lastone;        cp_lastone = cp_lastone->hi_next;    }    cp_lastone->hi_next = NULL;    cp_lastone->hi_event = event;    cp_lastone->hi_wlist = wl_copy(wlist);#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)    freehist(histlength - cp_maxhistlength);    histlength++;#endif    return;}/* Get a copy of the wordlist associated with an event. Error if out  * of range.  */static wordlist *getevent(int num){    struct histent *hi;    for (hi = histlist; hi; hi = hi->hi_next)        if (hi->hi_event == num)            break;    if (hi == NULL) {        fprintf(cp_err, "%d: event not found.\n", num);        return (NULL);    }    return (wl_copy(hi->hi_wlist));}/* Print out history between eventhi and eventlo.  * This doesn't remember quoting, so 'hodedo' prints as hodedo. */voidcp_hprint(int eventhi, int eventlo, bool rev){    struct histent *hi;    if (rev) {        for (hi = histlist; hi->hi_next; hi = hi->hi_next)            ;        for (; hi; hi = hi->hi_prev)            if ((hi->hi_event <= eventhi) &&                     (hi->hi_event >= eventlo) &&                    hi->hi_wlist) {                fprintf(cp_out, "%d\t", hi->hi_event);                wl_print(hi->hi_wlist, cp_out);                (void) putc('\n', cp_out);            }    } else {        for (hi = histlist; hi; hi = hi->hi_next)            if ((hi->hi_event <= eventhi) &&                     (hi->hi_event >= eventlo) &&                    hi->hi_wlist) {                fprintf(cp_out, "%d\t", hi->hi_event);                wl_print(hi->hi_wlist, cp_out);                (void) putc('\n', cp_out);            }    }    return;}#if !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE)/* This just gets rid of the first num entries on the history list, and * decrements histlength. */static voidfreehist(int num){    struct histent *hi;    if (num < 1)        return;    histlength -= num;    hi = histlist;    while (num-- && histlist->hi_next)        histlist = histlist->hi_next;    if (histlist->hi_prev) {        histlist->hi_prev->hi_next = NULL;        histlist->hi_prev = NULL;    } else        {        fprintf(cp_err, "Internal error: history list mangled\n");        exit(0);                                   /* Chris Inbody */        }    while (hi->hi_next) {        wl_free(hi->hi_wlist);        hi = hi->hi_next;        tfree(hi->hi_prev);    }    wl_free(hi->hi_wlist);    tfree(hi);    return;}#endif /* !defined(HAVE_GNUREADLINE) && !defined(HAVE_BSDEDITLINE) *//* Do a :s substitution. */static char *dohs(char *pat, char *str){    char schar, *s, *p, buf[BSIZE_SP];    int i = 0, plen;    bool ok = FALSE;    pat = copy(pat);    /* Don't want to mangle anything. */    schar = *pat++;    s =strchr(pat, schar);    if (s == NULL) {        fprintf(cp_err, "Bad substitute.\n");        return (NULL);    }    *s++ = '\0';    p =strchr(s, schar);    if (p)        *p = '\0';    plen = strlen(pat) - 1;    for (i = 0; *str; str++) {        if ((*str == *pat) && prefix(pat, str) && (ok == FALSE)) {            for (p = s; *p; p++)                buf[i++] = *p;            str += plen;            ok = TRUE;        } else            buf[i++] = *str;    }    buf[i] = '\0';    if (ok)        return (copy(buf));    else        return (NULL);}/* The "history" command. history [-r] [number] */voidcom_history(wordlist *wl){    bool rev = FALSE;    if (wl && eq(wl->wl_word, "-r")) {        wl = wl->wl_next;        rev = TRUE;    }#if defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE)    /* Added GNU Readline Support -- Andrew Veliath <veliaa@rpi.edu> */    {       HIST_ENTRY *he;       int i, N;       N = (wl == NULL) ? history_length : atoi(wl->wl_word);       if (N < 0) N = 0;       if (N > history_length) N = history_length;       if (rev)           for (i = history_length; i > 0 && N; --i, --N) {               he = history_get(i);               if (!he) return;               fprintf(cp_out, "%d\t%s\n", i, he->line);           }       else           for (i = history_length - N + 1; i <= history_length; ++i) {               he = history_get(i);               if (!he) return;               fprintf(cp_out, "%d\t%s\n", i, he->line);           }    }#else    if (wl == NULL)        cp_hprint(cp_event - 1, cp_event - histlength, rev);    else        cp_hprint(cp_event - 1, cp_event - 1 - atoi(wl->wl_word), rev);#endif /* defined(HAVE_GNUREADLINE) || defined(HAVE_BSDEDITLINE) */    return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -