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

📄 control.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group**********//* The front-end command loop.  */#include <ngspice.h>#include <cpdefs.h>#include "control.h"#include "com_cdump.h"#include "variable.h"#include "fteext.h"/* Return values from doblock().  I am assuming that nobody will use * these characters in a string.  */#define NORMAL      '\001'#define BROKEN      '\002'#define CONTINUED   '\003'#define NORMAL_STR  "\001"#define BROKEN_STR  "\002"#define CONTINUED_STR   "\003"/* Are we waiting for a command? This lets signal handling be * more clever. */bool cp_cwait = FALSE;      char *cp_csep = ";";bool cp_dounixcom = FALSE;/* We have to keep the control structures in a stack, so that when we * do a 'source', we can push a fresh set onto the top...  Actually * there have to be two stacks -- one for the pointer to the list of * control structs, and one for the 'current command' pointer...  */struct control *control[CONTROLSTACKSIZE];struct control *cend[CONTROLSTACKSIZE];int stackp = 0;/* If there is an argument, give this to cshpar to use instead of * stdin. In a few places, we call cp_evloop again if it returns 1 and * exit (or close a file) if it returns 0... Because of the way * sources are done, we can't allow the control structures to get * blown away every time we return -- probably every time we type * source at the keyboard and every time a source returns to keyboard * input is ok though -- use ft_controlreset.  */  /* Notes by CDHW: * This routine leaked like a sieve because each getcommand() created a * wordlist that was never freed because it might have been added into * the control structure. I've tackled this by making sure that everything * put into the cend[stackp] is a copy. This means that wlist can be * destroyed safely */static char *noredirect[] = { "stop", NULL } ;  /* Only one?? */static struct control *findlabel(char *s, struct control *ct){    while (ct) {        if ((ct->co_type == CO_LABEL) && eq(s, ct->co_text->wl_word))            break;        ct = ct->co_next;    }    return (ct);}/* This is also in cshpar.c ... */static voidpwlist(wordlist *wlist, char *name){    wordlist *wl;    if (!cp_debug)        return;    fprintf(cp_err, "%s : [ ", name);    for (wl = wlist; wl; wl = wl->wl_next)        fprintf(cp_err, "%s ", wl->wl_word);    fprintf(cp_err, "]\n");    return;}/* CDHW defined functions */static voidpwlist_echo(wlist, name)   /*CDHW used to perform function of set echo */    wordlist *wlist;    char *name;{    wordlist *wl;    if ((!cp_echo)||cp_debug) /* cpdebug prints the same info */        return;    fprintf(cp_err, "%s ", name);    for (wl = wlist; wl; wl = wl->wl_next)        fprintf(cp_err, "%s ", wl->wl_word);    fprintf(cp_err, "\n");    return;}/*CDHW Remove control structure and free the memory its hogging CDHW*/void ctl_free(struct control *ctrl) {   if (!ctrl) return;   wl_free(ctrl->co_cond); ctrl->co_cond = NULL;   tfree(ctrl->co_foreachvar); ctrl->co_foreachvar = NULL;   wl_free(ctrl->co_text); ctrl->co_text = NULL;   ctl_free(ctrl->co_children); ctrl->co_children = NULL;   ctl_free(ctrl->co_elseblock); ctrl->co_elseblock = NULL;   ctl_free(ctrl->co_next); ctrl->co_next = NULL;   tfree(ctrl); ctrl = NULL;}/* Note that we only do io redirection when we get to here - we also * postpone some other things until now.  */static voiddocommand(wordlist *wlist){    char *r, *s, *t;    char *lcom;    int nargs;    int i;    struct comm *command;    wordlist *wl, *nextc, *ee, *rwlist;    if (cp_debug) {        printf("docommand ");        wl_print(wlist, stdout);        putc('\n', stdout);    }    /* Do all the things that used to be done by cshpar when the line     * was read...  */    wlist = cp_variablesubst(wlist);    pwlist(wlist, "After variable substitution");    wlist = cp_bquote(wlist);    pwlist(wlist, "After backquote substitution");    wlist = cp_doglob(wlist);    pwlist(wlist, "After globbing");        pwlist_echo(wlist, "Becomes >");    if (!wlist || !wlist->wl_word) /*CDHW need to free wlist in second case? CDHW*/        return;    /* Now loop through all of the commands given. */    rwlist = wlist;    do {        for (nextc = wlist; nextc; nextc = nextc->wl_next)            if (eq(nextc->wl_word, cp_csep))                break;        /* Temporarily hide the rest of the command... */        if (nextc && nextc->wl_prev)            nextc->wl_prev->wl_next = NULL;        ee = wlist->wl_prev;        if (ee)            wlist->wl_prev = NULL;        if (nextc == wlist) {            /* There was no text... */            goto out;        }        /* And do the redirection. */        cp_ioreset();        for (i = 0; noredirect[i]; i++)            if (eq(wlist->wl_word, noredirect[i]))                break;        if (!noredirect[i]) {            if (!(wlist = cp_redirect(wlist))) {                cp_ioreset();                return;            }        }        /* Get rid of all the 8th bits now... */        cp_striplist(wlist);        s = wlist->wl_word;        /* Look for the command in the command list. */        for (i = 0; cp_coms[i].co_comname; i++) {            /* strcmp(cp_coms[i].co_comname, s) ... */            for (t = cp_coms[i].co_comname, r = s; *t && *r;		 t++, r++)                if (*t != *r)                    break;            if (!*t && !*r)                break;         }                /* Now give the user-supplied command routine a try... */        if (!cp_coms[i].co_func && cp_oddcomm(s, wlist->wl_next))            goto out;        /* If it's not there, try it as a unix command. */        if (!cp_coms[i].co_comname) {            if (cp_dounixcom && cp_unixcom(wlist))                goto out;            fprintf(cp_err,"%s: no such command available in %s\n",		    s, cp_program);            goto out;	    /* If it's there but spiceonly, and this is nutmeg, error. */        } else if (!cp_coms[i].co_func && ft_nutmeg && 		   (cp_coms[i].co_spiceonly)) {            fprintf(cp_err,"%s: command available only in spice\n",                    s);            goto out;        }        /* The command was a valid spice/nutmeg command. */        command = &cp_coms[i];        nargs = 0;        for (wl = wlist->wl_next; wl; wl = wl->wl_next)            nargs++;        if (command->co_stringargs) {            lcom = wl_flatten(wlist->wl_next); /*CDHW lcom will need freeing CDHW*/            (*command->co_func) ((void *)(lcom));        } else {            if (nargs < command->co_minargs) {		if (command->co_argfn) {		    (*command->co_argfn) (wlist->wl_next, command);		} else {		    fprintf(cp_err, "%s: too few args.\n", s);		}            } else if (nargs > command->co_maxargs) {                fprintf(cp_err, "%s: too many args.\n", s);            } else {                (*command->co_func) (wlist->wl_next);            }        }        /* Now fix the pointers and advance wlist. */    out:        wlist->wl_prev = ee;        if (nextc) {            if (nextc->wl_prev)                nextc->wl_prev->wl_next = nextc;            wlist = nextc->wl_next;        }    } while (nextc && wlist);    wl_free(rwlist);    /* Do periodic sorts of things... */    cp_periodic();    cp_ioreset();    return;}/* Execute a block.  There can be a number of return values from this routine. *  NORMAL indicates a normal termination *  BROKEN indicates a break -- if the caller is a breakable loop, *      terminate it, otherwise pass the break upwards *  CONTINUED indicates a continue -- if the caller is a continuable loop, *      continue, else pass the continue upwards *  Any other return code is considered a pointer to a string which is *      a label somewhere -- if this label is present in the block, *      goto it, otherwise pass it up. Note that this prevents jumping *      into a loop, which is good. * * Note that here is where we expand variables, ``, and globs for * controls. * * The 'num' argument is used by break n and continue n.  */static char *doblock(struct control *bl, int *num){    struct control *ch, *cn = NULL;    wordlist *wl;    char *i;    int nn;     nn = *num + 1 ; /*CDHW this is a guess... CDHW*/        switch (bl->co_type) {    case CO_WHILE:        if (!bl->co_children) {          fprintf(cp_err, "Warning: Executing empty 'while' block.\n");          fprintf(cp_err, "         (Use a label statement as a no-op to suppress this warning.)\n");        }        while (bl->co_cond && cp_istrue(bl->co_cond)) {            if (!bl->co_children) cp_periodic();  /*CDHW*/            for (ch = bl->co_children; ch; ch = cn) {                cn = ch->co_next;                i = doblock(ch, &nn);                switch (*i) {		case NORMAL:                    break;		case BROKEN:    /* Break. */                    if (nn < 2)                        return (NORMAL_STR);                    else {                        *num = nn - 1;                        return (BROKEN_STR);                    }		case CONTINUED: /* Continue. */                    if (nn < 2) {                        cn = NULL;                        break;                    } else {                        *num = nn - 1;                        return (CONTINUED_STR);                    }		default:                    cn = findlabel(i, bl->co_children);                    if (!cn)                        return (i);                }            }        }        break;    case CO_DOWHILE:        do {            for (ch = bl->co_children; ch; ch = cn) {                cn = ch->co_next;                i = doblock(ch, &nn);                switch (*i) {		case NORMAL:                    break;		case BROKEN:    /* Break. */                    if (nn < 2)                        return (NORMAL_STR);                    else {                        *num = nn - 1;                        return (BROKEN_STR);                    }		case CONTINUED: /* Continue. */                    if (nn < 2) {                        cn = NULL;                        break;                    } else {                        *num = nn - 1;                        return (CONTINUED_STR);                    }		default:                    cn = findlabel(i, bl->co_children);                    if (!cn)                        return (i);                }            }        } while (bl->co_cond && cp_istrue(bl->co_cond));        break;    case CO_REPEAT:        if (!bl->co_children) {          fprintf(cp_err, "Warning: Executing empty 'repeat' block.\n");          fprintf(cp_err, "         (Use a label statement as a no-op to suppress this warning.)\n");        }	if (!bl->co_timestodo) bl->co_timestodo = bl->co_numtimes;        /*...CDHW*/        while ((bl->co_timestodo > 0) ||	       (bl->co_timestodo == -1)) {            if (bl->co_numtimes != -1)                bl->co_numtimes--;                        if (!bl->co_children) cp_periodic();  /*CDHW*/            if (bl->co_timestodo != -1) bl->co_timestodo--;            for (ch = bl->co_children; ch; ch = cn) {                cn = ch->co_next;                i = doblock(ch, &nn);                switch (*i) {		case NORMAL:                    break;		case BROKEN:    /* Break. */                    if (nn < 2)                        return (NORMAL_STR);                    else {                        *num = nn - 1;                        return (BROKEN_STR);                    }		case CONTINUED: /* Continue. */                    if (nn < 2) {                        cn = NULL;                        break;                    } else {                        *num = nn - 1;                        return (CONTINUED_STR);                    }		default:                    cn = findlabel(i, bl->co_children);                    if (!cn)                        return (i);                }            }        }        break;    case CO_IF:        if (bl->co_cond && cp_istrue(bl->co_cond)) {            for (ch = bl->co_children; ch; ch = cn) {                cn = ch->co_next;                i = doblock(ch, &nn);                if (*i > 2) {                    cn = findlabel(i,				   bl->co_children);                    if (!cn)                        return (i);                } else if (*i != NORMAL) {                    *num = nn;                    return (i);                }            }        } else {            for (ch = bl->co_elseblock; ch; ch = cn) {                cn = ch->co_next;                i = doblock(ch, &nn);                if (*i > 2) {                    cn = findlabel(i,				   bl->co_elseblock);                    if (!cn)                        return (i);                } else if (*i != NORMAL) {                    *num = nn;                    return (i);                }            }        }        break;    case CO_FOREACH:        for (wl = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(bl->co_text))));	     wl;	     wl = wl->wl_next) {            cp_vset(bl->co_foreachvar, VT_STRING, wl->wl_word);            for (ch = bl->co_children; ch; ch = cn) {                cn = ch->co_next;                i = doblock(ch, &nn);                switch (*i) {		case NORMAL:                    break;		case BROKEN:    /* Break. */                    if (nn < 2)                        return (NORMAL_STR);

⌨️ 快捷键说明

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