/* MW. This function should not use cp_lastone, see cp_parse in cpshar.c * Many things are deleted here and memory leak closed */ wordlist * cp_doalias(wordlist *wlist) { wordlist *comm; /* The alias process is going to modify the "last" line typed, so * save a copy of what it really is and restore it after aliasing * is done. We have to do tricky things do get around the problems * with ; ... */ comm = wlist; while (comm) { int ntries; wordlist *end, *nextc; nextc = wl_find(cp_csep, comm); if (nextc == comm) { /* skip leading `;' */ comm = comm->wl_next; continue; } /* Temporarily hide the rest of the command... */ end = comm->wl_prev; wl_chop(comm); wl_chop(nextc); for (ntries = 21; ntries; ntries--) { wordlist *nwl = asubst(comm); if (nwl == NULL) break; if (eq(nwl->wl_word, comm->wl_word)) { /* Just once through... */ wl_free(comm); comm = nwl; break; } else { wl_free(comm); comm = nwl; } } if (!ntries) { fprintf(cp_err, "Error: alias loop.\n"); wlist->wl_word = NULL; return (wlist); } wl_append(end, comm); wl_append(comm, nextc); if (!end) wlist = comm; comm = nextc; } return (wlist); }
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; }
/* * called from both kernel as from wl_*() * precondition: perimeter lock is not acquired. */ static void wl_remove(struct pci_dev *pdev) { struct wl_info *wl; struct ieee80211_hw *hw; int status; hw = pci_get_drvdata(pdev); wl = HW_TO_WL(hw); if (!wl) { pr_err("wl: wl_remove: pci_get_drvdata failed\n"); return; } WL_LOCK(wl); status = wlc_chipmatch(pdev->vendor, pdev->device); WL_UNLOCK(wl); if (!status) { wiphy_err(wl->wiphy, "wl: wl_remove: wlc_chipmatch failed\n"); return; } if (wl->wlc) { wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); ieee80211_unregister_hw(hw); WL_LOCK(wl); wl_down(wl); WL_UNLOCK(wl); } pci_disable_device(pdev); wl_free(wl); pci_set_drvdata(pdev, NULL); ieee80211_free_hw(hw); }
bool cp_istrue(wordlist *wl) { struct dvec *v; struct pnode *names; bool rv; /* First do all the csh-type stuff here... */ wl = wl_copy(wl); wl = cp_variablesubst(wl); wl = cp_bquote(wl); cp_striplist(wl); names = ft_getpnames(wl, TRUE); wl_free(wl); v = ft_evaluate(names); rv = !vec_iszero(v); /* va: garbage collection for v, if pnode names is no simple value */ if (names->pn_value == NULL && v != NULL) vec_free(v); free_pnode(names); /* free also v, if pnode names is simple value */ return rv; }
bool cp_oddcomm(char *s, wordlist *wl) { FILE *fp; if ((fp = inp_pathopen(s, "r")) != NULL) { char buf[BSIZE_SP]; wordlist *setarg; (void) fclose(fp); (void) sprintf(buf, "argc = %d argv = ( ", wl_length(wl)); while (wl) { (void) strcat(buf, wl->wl_word); (void) strcat(buf, " "); wl = wl->wl_next; } (void) strcat(buf, ")"); setarg = cp_lexer(buf); com_set(setarg); wl_free(setarg); inp_source(s); cp_remvar("argc"); cp_remvar("argv"); return (TRUE); } if (wl && eq(wl->wl_word, "=")) { wordlist *ww = wl_cons(copy(s), wl); com_let(ww); wl_delete_slice(ww, ww->wl_next); return (TRUE); } return (FALSE); }
/* Return NULL if no alias was found. We can get away with just * calling cp_histsubst now because the line will have gone onto the * history list by now and cp_histsubst will look in the right place. */ static wordlist * asubst(wordlist *wlist) { struct alias *al; wordlist *wl; char *word; word = wlist->wl_word; if (*word == '\\') { while ((word[0] = word[1]) != '\0') word++; return (NULL); } for (al = cp_aliases; al; al = al->al_next) if (eq(word, al->al_name)) break; if (!al) return (NULL); wl = cp_histsubst(wl_copy(al->al_text)); if (cp_didhsubst) { /* Make sure that we have an up-to-date last history entry. */ wl_free(cp_lastone->hi_wlist); cp_lastone->hi_wlist = wl_copy(wl); } else { /* If it had no history args, then append the rest of the wl */ wl_append(wl, wl_copy(wlist->wl_next)); } return (wl); }
/* va: TODO: free control structure(s) before overwriting (memory leakage) */ int cp_evloop(char *string) { wordlist *wlist, *ww, *freewl; struct control *x; char *i; int nn; #define newblock \ do { \ cend[stackp]->co_children = TMALLOC(struct control, 1); \ ZERO(cend[stackp]->co_children, struct control); \ cend[stackp]->co_children->co_parent = cend[stackp]; \ cend[stackp] = cend[stackp]->co_children; \ cend[stackp]->co_type = CO_UNFILLED; \ } while(0) for (;;) { freewl = wlist = getcommand(string); if (wlist == NULL) { /* End of file or end of user input. */ if (cend[stackp] && cend[stackp]->co_parent && !string) { cp_resetcontrol(); continue; } else { return (0); } } if ((wlist->wl_word == NULL) || (*wlist->wl_word == '\0')) { /* User just typed return. */ wl_free(wlist); /* va, avoid memory leak */ if (string) { return (1); } else { cp_event--; continue; } } /* Just a check... */ for (ww = wlist; ww; ww = ww->wl_next) if (!ww->wl_word) { fprintf(cp_err, "cp_evloop: Internal Error: NULL word pointer\n"); continue; } /* Add this to the control structure list. If cend->co_type is * CO_UNFILLED, the last line was the beginning of a block, * and this is the unfilled first statement. */ /* va: TODO: free old structure and its content, before overwriting */ if (cend[stackp] && (cend[stackp]->co_type != CO_UNFILLED)) { cend[stackp]->co_next = TMALLOC(struct control, 1); ZERO(cend[stackp]->co_next, struct control); cend[stackp]->co_next->co_prev = cend[stackp]; cend[stackp]->co_next->co_parent = cend[stackp]->co_parent; cend[stackp] = cend[stackp]->co_next; } else if (!cend[stackp]) {
void DBfree(struct plot *plot) { struct dvec *v, *nextv; struct plot *pl, *nextpl; for (pl = plot; pl; pl = nextpl) { nextpl = pl->pl_next; tfree( pl->pl_title ); tfree( pl->pl_date ); tfree( pl->pl_name ); tfree( pl->pl_typename ); for (v = pl->pl_dvecs; v; v = nextv) { nextv = v->v_next; vec_free( v ); } wl_free( pl->pl_commands ); /* XXX Environment variables (pl->pl_env) will leak. */ } }
void ft_dotsaves(void) { wordlist *iline, *wl = NULL; char *s, *fr; if (!ft_curckt) /* Shouldn't happen. */ return; for (iline = ft_curckt->ci_commands; iline; iline = iline->wl_next) if (ciprefix(".save", iline->wl_word)) { s = iline->wl_word; /* skip .save */ fr = gettok(&s); tfree(fr); wl = wl_append(wl, gettoks(s)); } com_save(wl); wl_free(wl); }
bool cp_istrue(wordlist *wl) { int i; struct dvec *v; struct pnode *pn; /* fprintf(stderr, "isTRUE: "); wl_print(wl, stderr); fprintf(stderr, "\n"); */ /* First do all the csh-type stuff here... */ wl = wl_copy(wl); wl = cp_variablesubst(wl); wl = cp_bquote(wl); cp_striplist(wl); pn = ft_getpnames(wl, TRUE); wl_free(wl); v = ft_evaluate(pn); /* It makes no sense to say while (all), but what the heck... */ while (v) { if (isreal(v)) { for (i = 0; i < v->v_length; i++) if (v->v_realdata[i] != 0.0) { free_pnode(pn); return (TRUE); } } else { for (i = 0; i < v->v_length; i++) if ((realpart(&v->v_compdata[i]) != 0.0) || (imagpart(&v->v_compdata[i]) != 0.0)) { free_pnode(pn); return (TRUE); } } v = v->v_link2; } free_pnode(pn); return (FALSE); }
bool cp_istrue(wordlist *wl) { int i; struct dvec *v; struct pnode *names; /* First do all the csh-type stuff here... */ wl = wl_copy(wl); wl = cp_variablesubst(wl); wl = cp_bquote(wl); cp_striplist(wl); names = ft_getpnames(wl, TRUE); wl_free(wl); v = ft_evaluate(names); for (; v; v = v->v_link2) if (isreal(v)) { for (i = 0; i < v->v_length; i++) if (v->v_realdata[i] != 0.0) { free_pnode(names); return (TRUE); } } else { for (i = 0; i < v->v_length; i++) if ((realpart(v->v_compdata[i]) != 0.0) || (imagpart(v->v_compdata[i]) != 0.0)) { free_pnode(names); return (TRUE); } } free_pnode(names); return (FALSE); }
//void //inp_nutsource(FILE *fp, bool comfile, char *filename) void inp_nutsource(FILE *fp, int comfile, char *filename) { struct line *deck, *dd, *ld; struct line *realdeck, *options = NULL; char *tt = NULL, name[BSIZE_SP], *s, *t; //bool commands = FALSE; int commands = FALSE; wordlist *wl = NULL, *end = NULL; wordlist *controls = NULL; FILE *lastin, *lastout, *lasterr; deck = inp_readall(fp, NULL, comfile, FALSE); /* still to check if . or filename instead of NULL */ if (!deck) return; realdeck = inp_deckcopy(deck); if (!comfile) { /* Save the title before INPgetTitle gets it. */ tt = copy(deck->li_line); if (!deck->li_next) fprintf(cp_err, "Warning: no lines in deck...\n"); } (void) fclose(fp); /* Now save the IO context and start a new control set... After * we are done with the source we'll put the old file descriptors * back. I guess we could use a FILE stack, but since this routine * is recursive anyway... */ lastin = cp_curin; lastout = cp_curout; lasterr = cp_curerr; cp_curin = cp_in; cp_curout = cp_out; cp_curerr = cp_err; cp_pushcontrol(); /* We should now go through the deck and execute front-end * commands and remove them. Front-end commands are enclosed by * the lines .control and .endc, unless comfile * is TRUE, in which case every line must be a front-end command. * There are too many problems with matching the first word on * the line. */ ld = deck; if (comfile) { /* This is easy. */ for (dd = deck; dd; dd = ld) { ld = dd->li_next; if ((dd->li_line[0] == '*') && (dd->li_line[1] != '#')) continue; if (!ciprefix(".control", dd->li_line) && !ciprefix(".endc", dd->li_line)) { if (dd->li_line[0] == '*') (void) cp_evloop(dd->li_line + 2); else (void) cp_evloop(dd->li_line); } tfree(dd->li_line); tfree(dd); } } else { for (dd = deck->li_next; dd; dd = ld->li_next) { if ((dd->li_line[0] == '*') && (dd->li_line[1] != '#')) { ld = dd; continue; } (void) strncpy(name, dd->li_line, BSIZE_SP); for (s = name; *s && isspace(*s); s++) ; for (t = s; *t && !isspace(*t); t++) ; *t = '\0'; if (ciprefix(".control", dd->li_line)) { ld->li_next = dd->li_next; tfree(dd->li_line); tfree(dd); if (commands) fprintf(cp_err, "Warning: redundant .control line\n"); else commands = TRUE; } else if (ciprefix(".endc", dd->li_line)) { ld->li_next = dd->li_next; tfree(dd->li_line); tfree(dd); if (commands) commands = FALSE; else fprintf(cp_err, "Warning: misplaced .endc line\n"); } else if (commands || prefix("*#", dd->li_line)) { controls = wl_cons(NULL, controls); wl = controls; if (prefix("*#", dd->li_line)) wl->wl_word = copy(dd->li_line + 2); else wl->wl_word = dd->li_line; ld->li_next = dd->li_next; tfree(dd); } else if (!*dd->li_line) { /* So blank lines in com files don't get * considered as circuits. */ ld->li_next = dd->li_next; tfree(dd->li_line); tfree(dd); } else { inp_casefix(s); inp_casefix(dd->li_line); if (eq(s, ".width") || ciprefix(".four", s) || eq(s, ".plot") || eq(s, ".print") || eq(s, ".save")) { wl_append_word(&wl, &end, copy(dd->li_line)); ld->li_next = dd->li_next; tfree(dd->li_line); tfree(dd); } else { ld = dd; } } } if (deck->li_next) { /* There is something left after the controls. */ fprintf(cp_out, "\nCircuit: %s\n\n", tt); fprintf(stderr, "\nCircuit: %s\n\n", tt); /* Now expand subcircuit macros. Note that we have to * fix the case before we do this but after we * deal with the commands. */ if (!cp_getvar("nosubckt", CP_BOOL, NULL)) deck->li_next = inp_subcktexpand(deck->li_next); deck->li_actual = realdeck; nutinp_dodeck(deck, tt, wl, FALSE, options, filename); } /* Now that the deck is loaded, do the commands... */ controls = wl_reverse(controls); for (wl = controls; wl; wl = wl->wl_next) (void) cp_evloop(wl->wl_word); wl_free(controls); } /* Now reset everything. Pop the control stack, and fix up the IO * as it was before the source. */ cp_popcontrol(); cp_curin = lastin; cp_curout = lastout; cp_curerr = lasterr; tfree(tt); }
/* Clears ckt and removes current circuit from database */ void com_remcirc(wordlist *wl) { struct variable *v, *next; struct line *dd; /*in: the spice deck */ struct circ *p, *prev = NULL; #ifdef SHARED_MODULE TRANan *job; #endif NG_IGNORE(wl); if (ft_curckt == NULL) { fprintf(cp_err, "Error: there is no circuit loaded.\n"); return; } #ifdef SHARED_MODULE /* This may happen only with shared ngspice during transient analysis, if simulation is stopped with 'bg_halt' and then circuit shall be removed prematurely. */ job = (TRANan *) ft_curckt->ci_ckt->CKTcurJob; if (job && (job->JOBtype == 4) && (job->TRANplot)) SPfrontEnd->OUTendPlot (job->TRANplot); #endif /* delete numparam data structure dicoS */ nupa_del_dicoS(); dbfree(ft_curckt->ci_dbs); ft_curckt->ci_dbs = NULL; dbs = NULL; /* The next lines stem from com_rset */ INPkillMods(); if_cktfree(ft_curckt->ci_ckt, ft_curckt->ci_symtab); for (v = ft_curckt->ci_vars; v; v = next) { next = v->va_next; tfree(v->va_name); tfree(v); } ft_curckt->ci_vars = NULL; /* delete the deck, parameter list, and options list in ft_curckt */ dd = ft_curckt->ci_deck; line_free(dd, TRUE); dd = ft_curckt->ci_param; line_free(dd, TRUE); dd = ft_curckt->ci_options; line_free(dd, TRUE); wl_free(ft_curckt->ci_commands); tfree(ft_curckt->FTEstats); ft_sim->deleteTask (ft_curckt->ci_ckt, ft_curckt->ci_defTask); if (ft_curckt->ci_name) tfree(ft_curckt->ci_name); if (ft_curckt->ci_filename) tfree(ft_curckt->ci_filename); /* delete the actual circuit entry from ft_circuits */ for (p = ft_circuits; p; p = p->ci_next) { if (ft_curckt == p) { if (prev == NULL) { ft_circuits = p->ci_next; tfree(p); p = NULL; break; } else { prev->ci_next = p->ci_next; tfree(p); p = NULL; break; } } prev = p; } /* make first entry in ft_circuits the actual circuit (or NULL) */ ft_curckt = ft_circuits; if (ft_curckt) { modtab = ft_curckt->ci_modtab; dbs = ft_curckt->ci_dbs; } }
void com_removecirc(wordlist *wl) { struct variable *v, *next; struct circ *ct; struct circ *caux = NULL; struct plot *p; struct plot *paux; int auxCir = 1, i, auxPlot; char* namecircuit; NG_IGNORE(wl); if (!ft_curckt) { fprintf(cp_err, "Error: there is no circuit loaded.\n"); return; } ct = ft_curckt; if_cktfree(ct->ci_ckt, ct->ci_symtab); for (v = ct->ci_vars; v; v = next) { next = v->va_next; tfree(v); } /* PN FTESTATS*/ tfree(ct->FTEstats); ct->ci_vars = NULL; caux = ft_circuits; namecircuit = copy(ft_curckt->ci_name); /* The circuit being removed is the first loaded and you have more circuits */ if (ft_curckt == ft_circuits && ft_circuits->ci_next) ft_circuits = ft_circuits->ci_next; /* The circuit being removed id the first loaded and there are no more circuits */ else if (ft_circuits->ci_next == NULL) ft_circuits = NULL; else { /* Run over the circuit list to find how many of them are * in front of the one to be removed */ for (; ft_curckt != caux && caux; caux = caux->ci_next) auxCir++; caux = ft_circuits; /* Remove the circuit and move pointer to the next one */ for (i = 1; i < auxCir-1; i++) caux = caux->ci_next; caux->ci_next = caux->ci_next->ci_next; /* ft_curckt = ft_circuits; */ } /* If the plot is the first one and there are no other plots */ if (!plot_list->pl_next && strcmp(plot_list->pl_title, namecircuit) == 0) plot_list = NULL; else if (plot_list && plot_list->pl_next) { p = plot_list; while (p) { auxPlot = 1; /* If the plot is in the first position */ if (plot_list->pl_next && strcmp(plot_list->pl_title, namecircuit) == 0) plot_list = plot_list->pl_next; /* otherwise we run over the list of plots */ else { for (; strcmp(p->pl_title, namecircuit) != 0 && p->pl_next; p = p->pl_next) auxPlot++; if (strcmp(p->pl_title, namecircuit) == 0) { paux = plot_list; for (i = 1; i < auxPlot-1; i++) paux = paux->pl_next; paux->pl_next = paux->pl_next->pl_next; } } p = p->pl_next; } } /* if (ft_curckt) { ft_curckt->ci_devices = cp_kwswitch(CT_DEVNAMES, ft_circuits->ci_devices); ft_curckt->ci_nodes = cp_kwswitch(CT_NODENAMES, ft_circuits->ci_nodes); } */ if (ft_circuits && caux->ci_next) { struct wordlist *wlist; wlist = wl_cons(tprintf("%d", auxCir), NULL); com_scirc(wlist); wl_free(wlist); } else if (ft_circuits) { struct wordlist *wlist; wlist = wl_cons(tprintf("%d", auxCir - 1), NULL); com_scirc(wlist); wl_free(wlist); } else ft_curckt = NULL; }
/* Note that we only do io redirection when we get to here - we also * postpone some other things until now. */ static void docommand(wordlist *wlist) { wordlist *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; while (wlist) { char *s; int i; struct comm *command; wordlist *nextc, *ee; nextc = wl_find(cp_csep, wlist); if (nextc == wlist) { /* skip leading `;' */ wlist = wlist->wl_next; continue; } /* Temporarily hide the rest of the command... */ ee = wlist->wl_prev; wl_chop(nextc); wl_chop(wlist); /* 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)) == NULL) { 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++) if (strcasecmp(cp_coms[i].co_comname, s) == 0) break; command = &cp_coms[i]; /* Now give the user-supplied command routine a try... */ if (!command->co_func && cp_oddcomm(s, wlist->wl_next)) goto out; /* If it's not there, try it as a unix command. */ if (!command->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 hasn't been implemented */ } else if (!command->co_func) { fprintf(cp_err, "%s: command is not implemented\n", s); goto out; /* If it's there but spiceonly, and this is nutmeg, error. */ } else if (ft_nutmeg && command->co_spiceonly) { fprintf(cp_err, "%s: command available only in spice\n", s); goto out; } /* The command was a valid spice/nutmeg command. */ { int nargs = wl_length(wlist->wl_next); 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); } } out: wl_append(ee, wlist); wl_append(wlist, nextc); if (!ee) rwlist = wlist; wlist = nextc; } wl_free(rwlist); /* Do periodic sorts of things... */ cp_periodic(); cp_ioreset(); }
/* Note that we only do io redirection when we get to here - we also * postpone some other things until now. */ static void docommand(wordlist *wlist) { char *r, *s, *t; 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 (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) { for(wl=wlist; wl->wl_next; wl=wl->wl_next) ; wl->wl_next = nextc; nextc->wl_prev = wl; wlist = nextc->wl_next; } } while (nextc && wlist); wl_free(rwlist); /* Do periodic sorts of things... */ cp_periodic(); cp_ioreset(); return; }
/** * attach to the WL device. * * Attach to the WL device identified by vendor and device parameters. * regs is a host accessible memory address pointing to WL device registers. * * wl_attach is not defined as static because in the case where no bus * is defined, wl_attach will never be called, and thus, gcc will issue * a warning that this function is defined but not used if we declare * it as static. * * * is called in wl_pci_probe() context, therefore no locking required. */ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs, uint bustype, void *btparam, uint irq) { struct wl_info *wl = NULL; int unit, err; unsigned long base_addr; struct ieee80211_hw *hw; u8 perm[ETH_ALEN]; unit = wl_found; err = 0; if (unit < 0) { return NULL; } /* allocate private info */ hw = pci_get_drvdata(btparam); /* btparam == pdev */ if (hw != NULL) wl = hw->priv; if (WARN_ON(hw == NULL) || WARN_ON(wl == NULL)) return NULL; wl->wiphy = hw->wiphy; atomic_set(&wl->callbacks, 0); /* setup the bottom half handler */ tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl); base_addr = regs; if (bustype == PCI_BUS) { wl->piomode = false; } else if (bustype == RPC_BUS) { /* Do nothing */ } else { bustype = PCI_BUS; BCMMSG(wl->wiphy, "force to PCI\n"); } wl->bcm_bustype = bustype; wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ); if (wl->regsva == NULL) { wiphy_err(wl->wiphy, "wl%d: ioremap() failed\n", unit); goto fail; } spin_lock_init(&wl->lock); spin_lock_init(&wl->isr_lock); /* prepare ucode */ if (wl_request_fw(wl, (struct pci_dev *)btparam) < 0) { wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); wl_release_fw(wl); wl_remove((struct pci_dev *)btparam); return NULL; } /* common load-time initialization */ wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode, wl->regsva, wl->bcm_bustype, btparam, &err); wl_release_fw(wl); if (!wl->wlc) { wiphy_err(wl->wiphy, "%s: wlc_attach() failed with code %d\n", KBUILD_MODNAME, err); goto fail; } wl->pub = wlc_pub(wl->wlc); wl->pub->ieee_hw = hw; if (wlc_iovar_setint(wl->wlc, "mpc", 0)) { wiphy_err(wl->wiphy, "wl%d: Error setting MPC variable to 0\n", unit); } /* register our interrupt handler */ if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) { wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); goto fail; } wl->irq = irq; /* register module */ wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog, NULL); if (ieee_hw_init(hw)) { wiphy_err(wl->wiphy, "wl%d: %s: ieee_hw_init failed!\n", unit, __func__); goto fail; } memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN); if (WARN_ON(!is_valid_ether_addr(perm))) goto fail; SET_IEEE80211_PERM_ADDR(hw, perm); err = ieee80211_register_hw(hw); if (err) { wiphy_err(wl->wiphy, "%s: ieee80211_register_hw failed, status" "%d\n", __func__, err); } if (wl->pub->srom_ccode[0]) err = wl_set_hint(wl, wl->pub->srom_ccode); else err = wl_set_hint(wl, "US"); if (err) { wiphy_err(wl->wiphy, "%s: regulatory_hint failed, status %d\n", __func__, err); } wl_found++; return wl; fail: wl_free(wl); return NULL; }
void ft_cpinit(void) { bool found = FALSE, t = TRUE; char buf[BSIZE_SP], **x, *s, *r, *copys; struct comm *c; int i; FILE *fp; static char *predefs[] = { "yes", "1", "TRUE", "1", "no", "0", "FALSE", "0", "pi", "3.14159265358979323846", "e", "2.71828182845904523536", "c", "2.997925e8", "i", "0,1", "kelvin", "-273.15", "echarge", "1.60219e-19", "boltz", "1.38062e-23", "planck", "6.62620e-34" }; static char *udfs[] = { "max(x,y)", "(x gt y) * x + (x le y) * y", "min(x,y)", "(x lt y) * x + (x ge y) * y", "vdb(x)", "db(v(x))", "vdb(x,y)", "db(v(x) - v(y))", "vi(x)", "im(v(x))", "vi(x,y)", "im(v(x) - v(y))", "vm(x)", "mag(v(x))", "vm(x,y)", "mag(v(x) - v(y))", "vg(x)", "group_delay(v(x))", //A.Rroldan 10/06/05 group delay new function "gd(x)", "group_delay(v(x))", //A.Rroldan 10/06/05 group delay new function "vp(x)", "ph(v(x))", "vp(x,y)", "ph(v(x) - v(y))", "vr(x)", "re(v(x))", "vr(x,y)", "re(v(x) - v(y))" }; /* if TIOCSTI is defined (not available in MS Windows: Make escape the break character. So the user can type ahead... fcn defined in complete.c. */ cp_ccon(TRUE); /* Initialize io, cp_chars[], variable "history" in init.c. */ cp_init(); /* If command completion is available (global variable cp_nocc set in main.c by command line option -q) */ if (!cp_nocc) { /* Add commands... */ for (c = cp_coms; c->co_func; c++) { if (c->co_spiceonly && ft_nutmeg) continue; cp_addcomm(c->co_comname, c->co_cctypes[0], c->co_cctypes[1], c->co_cctypes[2], c->co_cctypes[3]); cp_addkword(CT_COMMANDS, c->co_comname); } /* And keywords... These are the ones that are constant... */ if (!ft_nutmeg) { cp_addkword(CT_LISTINGARGS, "deck"); cp_addkword(CT_LISTINGARGS, "logical"); cp_addkword(CT_LISTINGARGS, "physical"); cp_addkword(CT_LISTINGARGS, "expand"); cp_addkword(CT_STOPARGS, "when"); cp_addkword(CT_STOPARGS, "after"); } cp_addkword(CT_PLOT, "new"); cp_addkword(CT_PLOTKEYWORDS, "xlimit"); cp_addkword(CT_PLOTKEYWORDS, "ylimit"); cp_addkword(CT_PLOTKEYWORDS, "vs"); cp_addkword(CT_PLOTKEYWORDS, "xindices"); cp_addkword(CT_PLOTKEYWORDS, "xcompress"); cp_addkword(CT_PLOTKEYWORDS, "xdelta"); cp_addkword(CT_PLOTKEYWORDS, "ydelta"); cp_addkword(CT_PLOTKEYWORDS, "lingrid"); cp_addkword(CT_PLOTKEYWORDS, "loglog"); cp_addkword(CT_PLOTKEYWORDS, "linear"); cp_addkword(CT_PLOTKEYWORDS, "xlog"); cp_addkword(CT_PLOTKEYWORDS, "ylog"); cp_addkword(CT_PLOTKEYWORDS, "polar"); cp_addkword(CT_PLOTKEYWORDS, "smith"); cp_addkword(CT_PLOTKEYWORDS, "smithgrid"); cp_addkword(CT_PLOTKEYWORDS, "nointerp"); cp_addkword(CT_PLOTKEYWORDS, "title"); cp_addkword(CT_PLOTKEYWORDS, "xlabel"); cp_addkword(CT_PLOTKEYWORDS, "ylabel"); cp_addkword(CT_PLOTKEYWORDS, "linplot"); cp_addkword(CT_PLOTKEYWORDS, "combplot"); cp_addkword(CT_PLOTKEYWORDS, "pointplot"); cp_addkword(CT_RUSEARGS, "time"); cp_addkword(CT_RUSEARGS, "space"); cp_addkword(CT_RUSEARGS, "faults"); cp_addkword(CT_RUSEARGS, "elapsed"); cp_addkword(CT_RUSEARGS, "totiter"); cp_addkword(CT_RUSEARGS, "traniter"); cp_addkword(CT_RUSEARGS, "tranpoints"); cp_addkword(CT_RUSEARGS, "accept"); cp_addkword(CT_RUSEARGS, "rejected"); cp_addkword(CT_RUSEARGS, "time"); cp_addkword(CT_RUSEARGS, "trantime"); cp_addkword(CT_RUSEARGS, "lutime"); cp_addkword(CT_RUSEARGS, "solvetime"); cp_addkword(CT_RUSEARGS, "transolvetime"); cp_addkword(CT_RUSEARGS, "loadtime"); cp_addkword(CT_RUSEARGS, "all"); cp_addkword(CT_VECTOR, "all"); for (x = ft_setkwords; *x; x++) cp_addkword(CT_VARIABLES, *x); for (i = 0; ; i++) { if ((s = ft_typenames(i)) == NULL) break; cp_addkword(CT_TYPENAMES, s); } } cp_vset("program", CP_STRING, cp_program); /* Make the prompt use only the last component of the path... */ if (DIR_TERM) { for (s = cp_program; s && *s; s++) ; s--; while ((s > cp_program) && (*s != DIR_TERM)) s--; if (*s == DIR_TERM) s++; (void) strcpy(buf, s); for (s = buf; *s && (*s != '.'); s++) ; *s = '\0'; (void) strcat(buf, " ! -> "); } else { (void) sprintf(buf, "%s ! -> ", cp_program); } cp_vset("prompt", CP_STRING, buf); cp_vset("noglob", CP_BOOL, &t); cp_vset("brief", CP_BOOL, &t); /* Make vectors from values in predefs[] for the current plot. Define functions from entries in udfs[] (like user defined functions). */ { wordlist wl1, wl2, wl3; wl1.wl_next = &wl2; wl1.wl_prev = NULL; wl2.wl_next = NULL; wl2.wl_prev = &wl1; wl1.wl_word = "if"; wl2.wl_word = "1"; cp_setalias("begin", &wl1); wl1.wl_next = NULL; wl1.wl_word = "end"; cp_setalias("endif", &wl1); cp_setalias("endwhile", &wl1); cp_setalias("endforeach", &wl1); cp_setalias("endrepeat", &wl1); cp_setalias("enddowhile", &wl1); wl1.wl_word = "help"; cp_setalias("?", &wl1); wl1.wl_next = &wl2; wl2.wl_next = &wl3; wl2.wl_prev = &wl1; wl3.wl_prev = &wl2; wl3.wl_next = NULL; wl2.wl_word = "="; for (i = 0; (size_t) i < NUMELEMS(predefs); i += 2) { wl1.wl_word = predefs[i]; wl3.wl_word = predefs[i + 1]; com_let(&wl1); } wl2.wl_next = NULL; for (i = 0; (size_t) i < NUMELEMS(udfs); i += 2) { wl1.wl_word = udfs[i]; wl2.wl_word = udfs[i + 1]; com_define(&wl1); } } /* Reset this for the front end. */ cp_hash = '*'; /* NGSPICEDATADIR has been set to path "$dprefix/share/ngspice" in configure.ac, Spice_Lib_Dir has been set to NGSPICEDATADIR in conf.c, may be overridden by environmental variable SPICE_LIB_DIR in ivars(). Lib_Path has been set to Spice_Lib_Dir adding /scripts in ivars() */ if (Lib_Path && *Lib_Path) { /* set variable 'sourcepath' */ if (Inp_Path && *Inp_Path) (void) sprintf(buf, "sourcepath = ( %s %s %s )", DIR_CWD, Lib_Path, Inp_Path); else (void) sprintf(buf, "sourcepath = ( %s %s )", DIR_CWD, Lib_Path); { wordlist *wl; wl = cp_doglob(cp_lexer(buf)); cp_striplist(wl); com_set(wl); wl_free(wl); } /* Now source the standard startup file spinit or tclspinit. */ /* jump over leading spaces */ for (copys = s = cp_tildexpand(Lib_Path); copys && *copys; ) { while (isspace(*s)) s++; /* copy s into buf until space is seen, r is the actual position */ for (r = buf; *s && !isspace(*s); r++, s++) *r = *s; tfree(copys); /* add a path separator to buf at actual position */ (void) strcpy(r, DIR_PATHSEP); #ifdef TCL_MODULE /* add "tclspinit" to buf after actual position */ (void) strcat(r, "tclspinit"); #else /* add "spinit" to buf after actual position */ (void) strcat(r, "spinit"); #endif if ((fp = fopen(buf, "r")) != NULL) { cp_interactive = FALSE; inp_spsource(fp, TRUE, buf, FALSE); cp_interactive = TRUE; found = TRUE; break; #if defined(HAS_WINGUI) || defined(__MINGW32__) || defined(_MSC_VER) /* search in local directory where ngspice.exe resides */ #if defined TCL_MODULE } else if ((fp = fopen("./tclspinit", "r")) != NULL) { #else } else if ((fp = fopen("./spinit", "r")) != NULL) { #endif cp_interactive = FALSE; inp_spsource(fp, TRUE, buf, FALSE); cp_interactive = TRUE; found = TRUE; break; #endif } else if (ft_controldb) { fprintf(cp_err, "Note: can't open \"%s\".\n", buf); } } if (!found) fprintf(cp_err, "Note: can't find init file.\n"); } tcap_init(); }
/* 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, *wltmp; char *i, *wlword; 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; /*bl->co_numtimes: total repeat count bl->co_numtimes = -1: repeat forever bl->co_timestodo: remaining repeats*/ while ((bl->co_timestodo > 0) || (bl->co_timestodo == -1)) { if (!bl->co_children) cp_periodic(); /*CDHW*/ if (bl->co_timestodo != -1) bl->co_timestodo--; /* loop through all stements inside rpeat ... end */ for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); switch (*i) { case NORMAL: break; case BROKEN: /* Break. */ /* before leaving repeat loop set remaining timestodo to 0 */ bl->co_timestodo = 0; if (nn < 2) { return (NORMAL_STR); } else { *num = nn - 1; return (BROKEN_STR); } case CONTINUED: /* Continue. */ if (nn < 2) { cn = NULL; break; } else { /* before leaving repeat loop set remaining timestodo to 0 */ bl->co_timestodo = 0; *num = nn - 1; return (CONTINUED_STR); } default: cn = findlabel(i, bl->co_children); if (!cn) { /* no label found inside repeat loop: before leaving loop set remaining timestodo to 0 */ bl->co_timestodo = 0; 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 tfree(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: wltmp = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(bl->co_text)))); for (wl = wltmp; wl; wl = wl->wl_next) { cp_vset(bl->co_foreachvar, CP_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) { wl_free(wltmp); return (NORMAL_STR); } else { *num = nn - 1; wl_free(wltmp); return (BROKEN_STR); } case CONTINUED: /* Continue. */ if (nn < 2) { cn = NULL; break; } else { *num = nn - 1; wl_free(wltmp); return (CONTINUED_STR); } default: cn = findlabel(i, bl->co_children); if (!cn) { wl_free(wltmp); return (i); } } } } wl_free(wltmp); break; case CO_BREAK: if (bl->co_numtimes > 0) { *num = bl->co_numtimes; return (BROKEN_STR); } else { fprintf(cp_err, "Warning: break %d a no-op\n", bl->co_numtimes); return (NORMAL_STR); } case CO_CONTINUE: if (bl->co_numtimes > 0) { *num = bl->co_numtimes; return (CONTINUED_STR); } else { fprintf(cp_err, "Warning: continue %d a no-op\n", bl->co_numtimes); return (NORMAL_STR); } case CO_GOTO: wl = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(bl->co_text)))); wlword = wl->wl_word; wl->wl_word = NULL; wl_free(wl); return (wlword); case CO_LABEL: /* Do nothing. */ cp_periodic(); /*CDHW needed to avoid lock-ups when loop contains only a label CDHW*/ break; case CO_STATEMENT: docommand(wl_copy(bl->co_text)); break; case CO_UNFILLED: /* There was probably an error here... */ fprintf(cp_err, "Warning: ignoring previous error\n"); break; default: fprintf(cp_err, "doblock: Internal Error: bad block type %d\n", bl->co_type); return (NORMAL_STR); } return (NORMAL_STR); }
void com_meas(wordlist *wl) { /* wl: in, input line of meas command */ char *line_in, *outvar; wordlist *wl_count, *wl_let; char *vec_found, *token, *equal_ptr; wordlist *wl_index; struct dvec *d; int err = 0; int fail; double result = 0; if (!wl) { com_display(NULL); return; } wl_count = wl; /* check each wl entry, if it contain '=' and if the following token is a single valued vector. If yes, replace this vector by its value. Vectors may stem from other meas commands, or be generated elsewhere within the .control .endc script. All other right hand side vectors are treated in com_measure2.c. */ wl_index = wl; while (wl_index) { token = wl_index->wl_word; /* find the vector vec_found, next token after each '=' sign. May be in the next wl_word */ if (token[strlen(token) - 1] == '=') { wl_index = wl_index->wl_next; vec_found = wl_index->wl_word; /* token may be already a value, maybe 'LAST', which we have to keep, or maybe a vector */ if (!cieq(vec_found, "LAST")) { INPevaluate(&vec_found, &err, 1); /* if not a valid number */ if (err) { /* check if vec_found is a valid vector */ d = vec_get(vec_found); /* Only if we have a single valued vector, replacing of the rigt hand side does make sense */ if (d && (d->v_length == 1) && (d->v_numdims == 1)) { /* get its value */ wl_index->wl_word = tprintf("%e", d->v_realdata[0]); tfree(vec_found); } } } } /* may be inside the same wl_word */ else if ((equal_ptr = strstr(token, "=")) != NULL) { vec_found = equal_ptr + 1; if (!cieq(vec_found, "LAST")) { INPevaluate(&vec_found, &err, 1); if (err) { d = vec_get(vec_found); /* Only if we have a single valued vector, replacing of the rigt hand side does make sense */ if (d && (d->v_length == 1) && (d->v_numdims == 1)) { int lhs_len = (int)(equal_ptr - token); wl_index->wl_word = tprintf("%.*s=%e", lhs_len, token, d->v_realdata[0]); tfree(token); } } } } else { ; // nothing } wl_index = wl_index->wl_next; } line_in = wl_flatten(wl); /* get output var name */ wl_count = wl_count->wl_next; if (!wl_count) { fprintf(stdout, " meas %s failed!\n" " unspecified output var name\n\n", line_in); return; } outvar = wl_count->wl_word; fail = get_measure2(wl, &result, NULL, FALSE); if (fail) { fprintf(stdout, " meas %s failed!\n\n", line_in); return; } wl_let = wl_cons(tprintf("%s = %e", outvar, result), NULL); com_let(wl_let); wl_free(wl_let); tfree(line_in); }
//bool //do_measure( // char *what, /*in: analysis type*/ // bool chk_only /*in: TRUE if checking for "autostop", FALSE otherwise*/ //) int do_measure( char *what, /*in: analysis type*/ int chk_only /*in: TRUE if checking for "autostop", FALSE otherwise*/ ) { struct line *meas_card, *meas_results = NULL, *end = NULL, *newcard; char *line, *an_name, *an_type, *resname, *meastype, *str_ptr, out_line[1000]; int ok = 0; int fail; int num_failed = 0; double result = 0; // bool first_time = TRUE; // bool measures_passed; int first_time = TRUE; int measures_passed; wordlist *measure_word_list; int precision = measure_get_precision(); #ifdef HAS_PROGREP if (!chk_only) SetAnalyse("meas", 0); #endif an_name = strdup(what); /* analysis type, e.g. "tran" */ strtolower(an_name); measure_word_list = NULL; measures_passed = TRUE; /* don't allow .meas if batchmode is set by -b and -r rawfile given */ if (ft_batchmode && rflag) { fprintf(cp_err, "\nNo .measure possible in batch mode (-b) with -r rawfile set!\n"); fprintf(cp_err, "Remove rawfile and use .print or .plot or\n"); fprintf(cp_err, "select interactive mode (optionally with .control section) instead.\n\n"); return (measures_passed); } /* don't allow autostop if no .meas commands are given in the input file */ if ((cp_getvar("autostop", CP_BOOL, NULL)) && (ft_curckt->ci_meas == NULL)) { fprintf(cp_err, "\nWarning: No .meas commands found!\n"); fprintf(cp_err, " Option autostop is not available, ignored!\n\n"); cp_remvar("autostop"); return (FALSE); } /* Evaluating the linked list of .meas cards, assembled from the input deck by fcn inp_spsource() in inp.c:575. A typical .meas card will contain: parameter value nameof card .meas(ure) analysis type tran only tran available currently result name myout defined by user measurement type trig|delay|param|expr|avg|mean|max|min|rms|integ(ral)|when The measurement type determines how to continue the .meas card. param|expr are skipped in first pass through .meas cards and are treated in second pass, all others are treated in fcn get_measure2() (com_measure2.c). */ /* first pass through .meas cards: evaluate everything except param|expr */ for (meas_card = ft_curckt->ci_meas; meas_card != NULL; meas_card = meas_card->li_next) { line = meas_card->li_line; txfree(gettok(&line)); /* discard .meas */ an_type = gettok(&line); resname = gettok(&line); meastype = gettok(&line); if (chkAnalysisType(an_type) != TRUE) { if (!chk_only) { fprintf(cp_err, "Error: unrecognized analysis type '%s' for the following .meas statement on line %d:\n", an_type, meas_card->li_linenum); fprintf(cp_err, " %s\n", meas_card->li_line); } txfree(an_type); txfree(resname); txfree(meastype); continue; } /* print header before evaluating first .meas line */ else if (first_time) { first_time = FALSE; if (!chk_only && strcmp(an_type, "tran") == 0) { fprintf(stdout, "\n Measurements for Transient Analysis\n\n"); } } /* skip param|expr measurement types for now -- will be done after other measurements */ if (strncmp(meastype, "param", 5) == 0 || strncmp(meastype, "expr", 4) == 0) continue; /* skip .meas line, if analysis type from line and name of analysis performed differ */ if (strcmp(an_name, an_type) != 0) { txfree(an_type); txfree(resname); txfree(meastype); continue; } /* New way of processing measure statements using common code in fcn get_measure2() (com_measure2.c)*/ out_line[0] = '\0'; measure_word_list = measure_parse_line(meas_card->li_line); if (measure_word_list) { fail = get_measure2(measure_word_list, &result, out_line, chk_only); if (fail) { measures_passed = FALSE; if (!chk_only) fprintf(stderr, " %s failed!\n\n", meas_card->li_line); num_failed++; if (chk_only) { /* added for speed - cleanup last parse and break */ txfree(an_type); txfree(resname); txfree(meastype); wl_free(measure_word_list); break; } } else { if (!chk_only) nupa_add_param(resname, result); } wl_free(measure_word_list); } else { measures_passed = FALSE; num_failed++; } if (!chk_only) { newcard = alloc(struct line); newcard->li_line = strdup(out_line); newcard->li_next = NULL; if (meas_results == NULL) { meas_results = end = newcard; } else { end->li_next = newcard; end = newcard; } } txfree(an_type); txfree(resname); txfree(meastype); } /* end of for loop (first pass through .meas lines) */
wordlist * cp_lexer(char *string) { int c, d; int i, j; wordlist *wlist = NULL, *cw = NULL; char buf[NEW_BSIZE_SP], linebuf[NEW_BSIZE_SP]; int paren; if (!cp_inp_cur || cp_inp_cur != cp_in) cp_inp_cur = cp_in; /* prompt for string if none is passed */ if (!string && cp_interactive) { cp_ccon(TRUE); prompt(); } nloop: wlist = cw = NULL; i = 0; j = 0; paren = 0; bzero(linebuf, NEW_BSIZE_SP); bzero(buf, NEW_BSIZE_SP); for (;;) { c = cp_readchar(&string, cp_inp_cur); gotchar: if (string && (c == ESCAPE)) continue; if ((c != EOF) && (c != ESCAPE)) linebuf[j++] = (char) c; if (c != EOF) numeofs = 0; if (i == NEW_BSIZE_SP - 1) { fprintf(cp_err, "Warning: word too long.\n"); c = ' '; } if (j == NEW_BSIZE_SP - 1) { fprintf(cp_err, "Warning: line too long.\n"); if (cp_bqflag) c = EOF; else c = '\n'; } if (c != EOF) /* Don't need to do this really. */ c = strip(c); if ((c == '\\' && DIR_TERM != '\\') || (c == '\026') /* ^V */ ) { c = quote(cp_readchar(&string, cp_inp_cur)); linebuf[j++] = (char) strip(c); } if ((c == '\n') && cp_bqflag) c = ' '; if ((c == EOF) && cp_bqflag) c = '\n'; if ((c == cp_hash) && !cp_interactive && (j == 1)) { wl_free(wlist); wlist = cw = NULL; if (string) return NULL; while (((c = cp_readchar(&string, cp_inp_cur)) != '\n') && (c != EOF)) ; goto nloop; } if ((c == '(') || (c == '[')) /* MW. Nedded by parse() */ paren++; else if ((c == ')') || (c == ']')) paren--; switch (c) { case ' ': case '\t': if (i > 0) newword; break; case '\n': if (i) { buf[i] = '\0'; newword; } if (!cw) append(NULL); goto done; case '\'': while (((c = cp_readchar(&string, cp_inp_cur)) != '\'') && (i < NEW_BSIZE_SP - 1)) { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; buf[i++] = (char) quote(c); linebuf[j++] = (char) c; } linebuf[j++] = '\''; break; case '"': case '`': d = c; buf[i++] = (char) d; while (((c = cp_readchar(&string, cp_inp_cur)) != d) && (i < NEW_BSIZE_SP - 2)) { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; if (c == '\\') { linebuf[j++] = (char) c; c = cp_readchar(&string, cp_inp_cur); buf[i++] = (char) quote(c); linebuf[j++] = (char) c; } else { buf[i++] = (char) c; linebuf[j++] = (char) c; } } buf[i++] = (char) d; linebuf[j++] = (char) d; break; case '\004': case EOF: if (cp_interactive && !cp_nocc && !string) { if (j == 0) { if (cp_ignoreeof && (numeofs++ < 23)) { fputs("Use \"quit\" to quit.\n", stdout); } else { fputs("quit\n", stdout); // return ; // cp_doquit(); } append(NULL); goto done; } // cp_ccom doesn't mess wlist, read only access to wlist->wl_word cp_ccom(wlist, buf, FALSE); wl_free(wlist); (void) fputc('\r', cp_out); prompt(); for (j = 0; linebuf[j]; j++) #ifdef TIOCSTI (void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); #else fputc(linebuf[j], cp_out); /* But you can't edit */ #endif wlist = cw = NULL; goto nloop; } /* EOF during a source */ if (cp_interactive) { fputs("quit\n", stdout); cp_doquit(); append(NULL); goto done; } wl_free(wlist); return NULL; case ESCAPE: if (cp_interactive && !cp_nocc) { fputs("\b\b \b\b\r", cp_out); prompt(); for (j = 0; linebuf[j]; j++) #ifdef TIOCSTI (void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); #else fputc(linebuf[j], cp_out); /* But you can't edit */ #endif // cp_ccom doesn't mess wlist, read only access to wlist->wl_word cp_ccom(wlist, buf, TRUE); wl_free(wlist); wlist = cw = NULL; goto nloop; } goto ldefault; case ',': if ((paren < 1) && (i > 0)) { newword; break; } goto ldefault; case ';': /* CDHW semicolon inside parentheses is part of expression */ if (paren > 0) { buf[i++] = (char) c; break; } goto ldefault; case '&': /* va: $&name is one word */ if ((i >= 1) && (buf[i-1] == '$') && (c == '&')) { buf[i++] = (char) c; break; } goto ldefault; case '<': case '>': /* va: <=, >= are unbreakable words */ if (string) if ((i == 0) && (*string == '=')) { buf[i++] = (char) c; break; } goto ldefault; default: /* We have to remember the special case $< * here */ ldefault: if ((cp_chars[c] & CPC_BRL) && (i > 0)) if ((c != '<') || (buf[i-1] != '$')) newword; buf[i++] = (char) c; if (cp_chars[c] & CPC_BRR) if ((c != '<') || (i < 2) || (buf[i-2] != '$')) newword; } } done: if (wlist->wl_word) pwlist_echo(wlist, "Command>"); return wlist; }
/* Evaluate a variable. */ wordlist * vareval(char *string) { struct variable *v; wordlist *wl; char buf[BSIZE_SP], *s; char *oldstring = copy(string); char *range = NULL; int i, up, low; cp_wstrip(string); if ((s = strchr(string, '[')) != NULL) { *s = '\0'; range = s + 1; } switch (*string) { case '$': wl = wl_cons(tprintf("%d", getpid()), NULL); tfree(oldstring); return (wl); case '<': (void) fflush(cp_out); if (!fgets(buf, BSIZE_SP, cp_in)) { clearerr(cp_in); (void) strcpy(buf, "EOF"); } for (s = buf; *s && (*s != '\n'); s++) ; *s = '\0'; wl = cp_lexer(buf); /* This is a hack. */ if (!wl->wl_word) wl->wl_word = copy(""); tfree(oldstring); return (wl); case '?': string++; for (v = variables; v; v = v->va_next) if (eq(v->va_name, string)) break; if (!v) v = cp_enqvar(string); wl = wl_cons(copy(v ? "1" : "0"), NULL); tfree(oldstring); return (wl); case '#': string++; for (v = variables; v; v = v->va_next) if (eq(v->va_name, string)) break; if (!v) v = cp_enqvar(string); if (!v) { fprintf(cp_err, "Error: %s: no such variable.\n", string); tfree(oldstring); return (NULL); } if (v->va_type == CP_LIST) for (v = v->va_vlist, i = 0; v; v = v->va_next) i++; else i = (v->va_type != CP_BOOL); wl = wl_cons(tprintf("%d", i), NULL); tfree(oldstring); return (wl); case '\0': wl = wl_cons(copy("$"), NULL); tfree(oldstring); return (wl); } /* The notation var[stuff] has two meanings... If this is a real * variable, then the [] denotes range, but if this is a strange * (e.g, device parameter) variable, it could be anything... */ for (v = variables; v; v = v->va_next) if (eq(v->va_name, string)) break; if (!v && isdigit_c(*string)) { for (v = variables; v; v = v->va_next) if (eq(v->va_name, "argv")) break; range = string; } if (!v) { range = NULL; string = oldstring; v = cp_enqvar(string); } if (!v && (s = getenv(string)) != NULL) { wl = wl_cons(copy(s), NULL); tfree(oldstring); return (wl); } if (!v) { fprintf(cp_err, "Error: %s: no such variable.\n", string); tfree(oldstring); return (NULL); } wl = cp_varwl(v); /* Now parse and deal with 'range' ... */ if (range) { /* rather crude fix when range itself is a $expression */ wordlist *r = NULL; if (*range == '$') { char *t = ++range; if (*t == '&') t++; while (isalnum_c(*t)) t++; *t = '\0'; r = vareval(range); if (!r || r->wl_next) { fprintf(cp_err, "Error: %s: illegal index.\n", string); tfree(oldstring); wl_free(r); return NULL; } range = r->wl_word; } for (low = 0; isdigit_c(*range); range++) low = low * 10 + *range - '0'; if ((*range == '-') && isdigit_c(range[1])) for (up = 0, range++; isdigit_c(*range); range++) up = up * 10 + *range - '0'; else if (*range == '-') up = wl_length(wl); else up = low; up--, low--; wl = wl_range(wl, low, up); wl_free(r); } tfree(oldstring); return (wl); }