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

📄 define.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group**********//* * User-defined functions. The user defines the function with *  define func(arg1, arg2, arg3) <expression involving args...> * Then when he types "func(1, 2, 3)", the commas are interpreted as * binary operations of the lowest priority by the parser, and ft_substdef() * below is given a chance to fill things in and return what the parse tree * would have been had the entire thing been typed. * Note that we have to take some care to distinguish between functions * with the same name and different arities. */#include "spice.h"#include "util.h"#include "misc.h"#include "cpdefs.h"#include "ftedefs.h"#include "ftedata.h"#include "fteparse.h"#include "suffix.h"static struct pnode *ntharg();static struct pnode *trcopy();static void prdefs();static void prtree();static void prtree1();static void savetree();static struct udfunc *udfuncs = NULL;/* Set up a function definition. */voidcom_define(wlist)    wordlist *wlist;{    int arity = 0, i;    char buf[BSIZE_SP], tbuf[BSIZE_SP], *s, *t, *b;    wordlist *wl;    struct pnode *pn;    struct udfunc *udf;    /* If there's nothing then print all the definitions. */    if (wlist == NULL) {        prdefs((char *) NULL);        return;    }    /* Accumulate the function head in the buffer, w/out spaces. A     * useful thing here would be to check to make sure that there     * are no formal parameters here called "list". But you have     * to try really hard to break this here.     */    buf[0] = '\0';    for (wl = wlist; wl && (index(wl->wl_word, /* ( */ ')') == NULL);                wl = wl->wl_next)        (void) strcat(buf, wl->wl_word);    if (wl) {        for (t = buf; *t; t++);        for (s = wl->wl_word; *s && (*s != /* ( */ ')'); s++, t++)            *t = *s;        *t++ = /* ( */ ')';        *t = '\0';        if (*++s)            wl->wl_word = copy(s);        else            wl = wl->wl_next;    }    /* If that's all, then print the definition. */    if (wl == NULL) {        prdefs(buf);        return;    }    /* Now check to see if this is a valid name for a function (i.e,     * there isn't a predefined function of the same name).     */    (void) strcpy(tbuf, buf);    for (b = tbuf; *b; b++)        if (isspace(*b) || (*b == '(' /* ) */)) {            *b = '\0';            break;        }    for (i = 0; ft_funcs[i].fu_name; i++)        if (eq(ft_funcs[i].fu_name, tbuf)) {            fprintf(cp_err, "Error: %s is a predefined function.\n",                    tbuf);            return;        }    /* Parse the rest of it. We can't know if there are the right     * number of undefined variables in the expression.     */    if (!(pn = ft_getpnames(wl, false)))        return;    /* This is a pain -- when things are garbage-collected, any     * vectors that may have been mentioned here will be thrown     * away. So go down the tree and save any vectors that aren't     * formal parameters.     */    savetree(pn);        /* Format the name properly and add to the list. */    b = copy(buf);    for (s = b; *s; s++) {        if (*s == '(') { /*)*/            *s = '\0';            if (s[1] != /*(*/ ')')                arity++;    /* It will have been 0. */        } else if (*s == /*(*/ ')') {            *s = '\0';        } else if (*s == ',') {            *s = '\0';            arity++;        }    }    for (udf = udfuncs; udf; udf = udf->ud_next)        if (prefix(b, udf->ud_name) && (arity == udf->ud_arity))            break;    if (udf == NULL) {        udf = alloc(struct udfunc);        if (udfuncs == NULL) {            udfuncs = udf;            udf->ud_next = NULL;	} else {            udf->ud_next = udfuncs;            udfuncs = udf;        }    }    udf->ud_text = pn;    udf->ud_name = b;    udf->ud_arity = arity;    cp_addkword(CT_UDFUNCS, b);    return;}/* Kludge. */static voidsavetree(pn)    struct pnode *pn;{    struct dvec *d;    if (pn->pn_value) {        /* We specifically don't add this to the plot list         * so it won't get gc'ed.         */        d = pn->pn_value;        if ((d->v_length != 0) || eq(d->v_name, "list")) {            pn->pn_value = alloc(struct dvec);	    ZERO(pn->pn_value, struct dvec);            pn->pn_value->v_name = copy(d->v_name);            pn->pn_value->v_length = d->v_length;            pn->pn_value->v_type = d->v_type;            pn->pn_value->v_flags = d->v_flags;            pn->pn_value->v_plot = d->v_plot;            if (isreal(d)) {                pn->pn_value->v_realdata = (double *)                     tmalloc(sizeof (double) * d->v_length);                bcopy((char *) d->v_realdata,                    (char *) pn->pn_value->v_realdata,                    sizeof (double) * d->v_length);            } else {                pn->pn_value->v_compdata = (complex *)                     tmalloc(sizeof (complex) * d->v_length);                bcopy((char *) d->v_compdata,                    (char *) pn->pn_value->v_compdata,                    sizeof (complex) * d->v_length);            }        }    } else if (pn->pn_op) {        savetree(pn->pn_left);        if (pn->pn_op->op_arity == 2)            savetree(pn->pn_right);    } else if (pn->pn_func) {        savetree(pn->pn_left);    }    return;}/* A bunch of junk to print out nodes. */static voidprdefs(name)    char *name;{    struct udfunc *udf;    char *s;    if (name) {        s = index(name, '(' /* ) */);        if (s)            *s = '\0';    }    if (name && *name) {    /* You never know what people will do */        for (udf = udfuncs; udf; udf = udf->ud_next)            if (eq(name, udf->ud_name))                prtree(udf);    } else        for (udf = udfuncs; udf; udf = udf->ud_next)            prtree(udf);    return;}/* Print out one definition. */static voidprtree(ud)    struct udfunc *ud;{    char *s, buf[BSIZE_SP];    /* Print the head. */    buf[0] = '\0';    (void) strcat(buf, ud->ud_name);     for (s = ud->ud_name; *s; s++);    (void) strcat(buf, " (");    s++;    while (*s) {        (void) strcat(buf, s);        while (*s)            s++;        if (s[1])            (void) strcat(buf, ", ");        s++;    }    (void) strcat(buf, ") = ");    fputs(buf, cp_out);    prtree1(ud->ud_text, cp_out);    (void) putc('\n', cp_out);    return;}static voidprtree1(pn, fp)    struct pnode *pn;    FILE *fp;{    if (pn->pn_value) {        fputs(pn->pn_value->v_name, fp);    } else if (pn->pn_func) {        fprintf(fp, "%s (", pn->pn_func->fu_name);        prtree1(pn->pn_left, fp);        fputs(")", fp);    } else if (pn->pn_op && (pn->pn_op->op_arity == 2)) {        fputs("(", fp);        prtree1(pn->pn_left, fp);        fprintf(fp, ")%s(", pn->pn_op->op_name);        prtree1(pn->pn_right, fp);        fputs(")", fp);    } else if (pn->pn_op && (pn->pn_op->op_arity == 1)) {        fprintf(fp, "%s(", pn->pn_op->op_name);        prtree1(pn->pn_left, fp);        fputs(")", fp);    } else        fputs("<something strange>", fp);    return;}struct pnode *ft_substdef(name, args)    char *name;    struct pnode *args;{    struct udfunc *udf;    struct pnode *tp;    char *s;    int arity = 0, rarity;    bool found = false;    if (args)        arity = 1;    for (tp = args; tp && tp->pn_op && (tp->pn_op->op_num == COMMA); tp =            tp->pn_right)        arity++;    for (udf = udfuncs; udf; udf = udf->ud_next)        if (eq(name, udf->ud_name)) {            if (arity == udf->ud_arity)                break;            else {                found = true;                rarity = udf->ud_arity;            }        }    if (udf == NULL) {        if (found)            fprintf(cp_err,        "Warning: the user-defined function %s has %d args\n",                name, rarity);        return (NULL);    }    for (s = udf->ud_name; *s; s++)        ;    s++;    /* Now we have to traverse the tree and copy it over,     * substituting args.     */    return (trcopy(udf->ud_text, s, args));}/* Copy the tree and replace formal args with the right stuff. The way * we know that something might be a formal arg is when it is a dvec * with length 0 and a name that isn't "list". I hope nobody calls their * formal parameters "list". */static struct pnode *trcopy(tree, args, nn)    struct pnode *tree;    char *args;    struct pnode *nn;{    struct pnode *pn;    struct dvec *d;    char *s;    int i;    if (tree->pn_value) {        d = tree->pn_value;        if ((d->v_length == 0) && strcmp(d->v_name, "list")) {            /* Yep, it's a formal parameter. Substitute for it.             * IMPORTANT: we never free parse trees, so we             * needn't worry that they aren't trees here.             */            s = args;            i = 1;            while (*s) {                if (eq(s, d->v_name))                    break;                else                    i++;                while (*s++);   /* Get past the last '\0'. */            }            if (*s)                return (ntharg(i, nn));            else                return (tree);        } else            return (tree);    } else if (tree->pn_func) {        struct func *func;        func = alloc(struct func);        func->fu_name = copy(tree->pn_func->fu_name);        func->fu_func = tree->pn_func->fu_func;        pn = alloc(struct pnode);        pn->pn_value = NULL;        pn->pn_func = func;        pn->pn_op = NULL;        pn->pn_left = trcopy(tree->pn_left, args, nn);        pn->pn_right = NULL;        pn->pn_next = NULL;    } else if (tree->pn_op) {        struct op *op;        op = alloc(struct op);        op->op_num = tree->pn_op->op_num;        op->op_arity = tree->pn_op->op_arity;        op->op_func = tree->pn_op->op_func;        op->op_name = copy(tree->pn_op->op_name);        pn = alloc(struct pnode);        pn->pn_value = NULL;        pn->pn_func = NULL;        pn->pn_op = op;        pn->pn_left = trcopy(tree->pn_left, args, nn);        if (op->op_arity == 2)            pn->pn_right = trcopy(tree->pn_right, args, nn);	else            pn->pn_right = NULL;        pn->pn_next = NULL;    } else {        fprintf(cp_err, "trcopy: Internal Error: bad parse node\n");        return (NULL);    }    return (pn);}/* Find the n'th arg in the arglist, returning NULL if there isn't one.  * Since comma has such a low priority and associates to the right, * we can just follow the right branch of the tree num times. * Note that we start at 1 when numbering the args. */static struct pnode *ntharg(num, args)    struct pnode *args;{    struct pnode *ptry;    ptry = args;    if (num > 1) {        while (--num > 0) {            if (ptry && ptry->pn_op &&                    (ptry->pn_op->op_num != COMMA))                if (num == 1)                    break;                else                    return (NULL);            ptry = ptry->pn_right;        }    }    if (ptry && ptry->pn_op && (ptry->pn_op->op_num == COMMA))        ptry = ptry->pn_left;    return (ptry);}voidcom_undefine(wlist)    wordlist *wlist;{    struct udfunc *udf, *ludf = NULL;    if (!wlist)        return;    if (*wlist->wl_word == '*') {        udfuncs = NULL;     /* Be sloppy. */        return;    }    while (wlist) {        for (udf = udfuncs; udf; udf = udf->ud_next) {            if (eq(wlist->wl_word, udf->ud_name)) {                if (ludf)                    ludf->ud_next = udf->ud_next;                else                    udfuncs = udf->ud_next;                cp_remkword(CT_UDFUNCS, wlist->wl_word);            } else                ludf = udf;        }        wlist = wlist->wl_next;    }    return;}#ifndef LINT/* Watch out, this is not at all portable.  It's only here so I can * call it from dbx with an int value (all you can give with "call")... */voidft_pnode(pn)    struct pn *pn;{    prtree1(pn, cp_err);}#endif

⌨️ 快捷键说明

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