📄 inp.c
字号:
/**********Copyright 1990 Regents of the University of California. All rights reserved.Author: 1985 Wayne A. Christopher$Id: inp.c,v 1.14 2005/06/09 01:38:47 sjborley Exp $**********//* * SJB 22 May 2001 * Fixed memory leaks accociated with freeing memory used by lines in the input deck * in inp_spsource(). New line_free() routine added to help with this. *//* * Stuff for dealing with spice input decks and command scripts, and * the listing routines. */#include "ngspice.h"#include "cpdefs.h"#include "inpdefs.h"#include "ftedefs.h"#include "dvec.h"#include "fteinp.h"#include "inp.h"#include "circuits.h"#include "completion.h"#include "variable.h"#include "breakp2.h"#ifdef XSPICE/* gtri - add - 12/12/90 - wbk - include new stuff */#include "ipctiein.h"#include "enh.h"/* gtri - end - 12/12/90 */#endif#define line_free(line,flag) { line_free_x(line,flag); line = NULL; }/* static declarations */static char * upper(register char *string);static bool doedit(char *filename);static void line_free_x(struct line * deck, bool recurse);/* Do a listing. Use is listing [expanded] [logical] [physical] [deck] */voidcom_listing(wordlist *wl){ int type = LS_LOGICAL; bool expand = FALSE; char *s; if (ft_curckt) { /* if there is a current circuit . . . . */ while (wl) { s = wl->wl_word; switch (*s) { case 'l': case 'L': type = LS_LOGICAL; break; case 'p': case 'P': type = LS_PHYSICAL; break; case 'd': case 'D': type = LS_DECK; break; case 'e': case 'E': expand = TRUE; break; default: fprintf(cp_err, "Error: bad listing type %s\n", s); return; /* SJB - don't go on after an error */ } wl = wl->wl_next; } if (type != LS_DECK) fprintf(cp_out, "\t%s\n\n", ft_curckt->ci_name); inp_list(cp_out, expand ? ft_curckt->ci_deck : ft_curckt->ci_origdeck, ft_curckt->ci_options, type); } else fprintf(cp_err, "Error: no circuit loaded.\n"); return;}static char *upper(char *string){ static char buf[BSIZE_SP]; if (string) { strncpy(buf, string, BSIZE_SP - 1); buf[BSIZE_SP - 1] = 0; inp_casefix(buf); } else { strcpy(buf, "<null>"); } return buf;}/* Provide an input listing on the specified file of the given card * deck. The listing should be of either LS_PHYSICAL or LS_LOGICAL or * LS_DECK lines as specified by the type parameter. */voidinp_list(FILE *file, struct line *deck, struct line *extras, int type){ struct line *here; struct line *there; bool renumber; bool useout = (file == cp_out); int i = 1;/* gtri - wbk - 03/07/91 - Don't use 'more' type output if ipc enabled */#ifdef XSPICE if(g_ipc.enabled) { useout = FALSE; }#endif/* gtri - end - 03/07/91 */ if (useout) out_init(); cp_getvar("renumber", VT_BOOL, (char *) &renumber); if (type == LS_LOGICAL) {top1: for (here = deck; here; here = here->li_next) { if (renumber) here->li_linenum = i; i++; if (ciprefix(".end", here->li_line) && !isalpha(here->li_line[4])) continue; if (*here->li_line != '*') { if (useout) { sprintf(out_pbuf, "%6d : %s\n", here->li_linenum, upper(here->li_line)); out_send(out_pbuf); } else fprintf(file, "%6d : %s\n", here->li_linenum, upper(here->li_line)); if (here->li_error) { if (useout) { out_printf("%s\n", here->li_error); } else fprintf(file, "%s\n", here->li_error); } } } if (extras) { deck = extras; extras = NULL; goto top1; } if (useout) { sprintf(out_pbuf, "%6d : .end\n", i); out_send(out_pbuf); } else fprintf(file, "%6d : .end\n", i); } else if ((type == LS_PHYSICAL) || (type == LS_DECK)) {top2: for (here = deck; here; here = here->li_next) { if ((here->li_actual == NULL) || (here == deck)) { if (renumber) here->li_linenum = i; i++; if (ciprefix(".end", here->li_line) && !isalpha(here->li_line[4])) continue; if (type == LS_PHYSICAL) { if (useout) { sprintf(out_pbuf, "%6d : %s\n", here->li_linenum, upper(here->li_line)); out_send(out_pbuf); } else fprintf(file, "%6d : %s\n", here->li_linenum, upper(here->li_line)); } else { if (useout) out_printf("%s\n", upper(here->li_line)); else fprintf(file, "%s\n", upper(here->li_line)); } if (here->li_error && (type == LS_PHYSICAL)) { if (useout) out_printf("%s\n", here->li_error); else fprintf(file, "%s\n", here->li_error); } } else { for (there = here->li_actual; there; there = there->li_next) { there->li_linenum = i++; if (ciprefix(".end", here->li_line) && isalpha(here->li_line[4])) continue; if (type == LS_PHYSICAL) { if (useout) { sprintf(out_pbuf, "%6d : %s\n", there->li_linenum, upper(there->li_line)); out_send(out_pbuf); } else fprintf(file, "%6d : %s\n", there->li_linenum, upper(there->li_line)); } else { if (useout) out_printf("%s\n", upper(there->li_line)); else fprintf(file, "%s\n", upper(there->li_line)); } if (there->li_error && (type == LS_PHYSICAL)) { if (useout) out_printf("%s\n", there->li_error); else fprintf(file, "%s\n", there->li_error); } } here->li_linenum = i; } } if (extras) { deck = extras; extras = NULL; goto top2; } if (type == LS_PHYSICAL) { if (useout) { sprintf(out_pbuf, "%6d : .end\n", i); out_send(out_pbuf); } else fprintf(file, "%6d : .end\n", i); } else { if (useout) out_printf(".end\n"); else fprintf(file, ".end\n"); } } else fprintf(cp_err, "inp_list: Internal Error: bad type %d\n", type); return;}/* * Free memory used by a line. * If recure is TRUE then recursivly free all lines linked via the li_next field. * If recurse is FALSE free only this line. * All lines linked via the li_actual field are always recursivly freed. * SJB - 22nd May 2001 */static voidline_free_x(struct line * deck, bool recurse) { if(!deck) return; tfree(deck->li_line); tfree(deck->li_error); if(recurse) line_free(deck->li_next,TRUE); line_free(deck->li_actual,TRUE); tfree(deck);}/* The routine to source a spice input deck. We read the deck in, take * out the front-end commands, and create a CKT structure. Also we * filter out the following cards: .save, .width, .four, .print, and * .plot, to perform after the run is over. * Then, we run dodeck, which parses up the deck. */voidinp_spsource(FILE *fp, bool comfile, char *filename) /* arguments: * *fp = pointer to the input file * comfile = whether it is a command file. Values are TRUE/FALSE * *filename = */{ struct line *deck, *dd, *ld; struct line *realdeck, *options = NULL; char *tt = NULL, name[BSIZE_SP], *s, *t; bool nosubckts, commands = FALSE; wordlist *wl = NULL, *end = NULL, *wl_first = NULL; wordlist *controls = NULL; FILE *lastin, *lastout, *lasterr; /* read in the deck from a file */ inp_readall(fp, &deck); /* if nothing came back from inp_readall, just close fp and return to caller */ if (!deck) { /* MW. We must close fp always when returning */ fclose(fp); return; } if (!comfile) options = inp_getopts(deck); 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 input\n"); } 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 cards .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] == '*') cp_evloop(dd->li_line + 2); else cp_evloop(dd->li_line); } line_free(dd,FALSE); /* SJB - free this line's memory */ } } /* end if(comfile) */ else { /* must be regular deck . . . . */ for (dd = deck->li_next; dd; dd = ld->li_next) { /* loop through deck and handle control cards */ /* Ignore comment lines, but not lines begining with '*#' */ s = dd->li_line; while(isspace(*s)) s++; if ( (*s == '*') && ( (s != dd->li_line) || (s[1] != '#'))) { ld = dd; continue; } 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; line_free(dd,FALSE); /* SJB - free this line's memory */ if (commands) fprintf(cp_err, "Warning: redundant .control card\n"); else commands = TRUE; } else if (ciprefix(".endc", dd->li_line)) { ld->li_next = dd->li_next; line_free(dd,FALSE); /* SJB - free this line's memory */ if (commands) commands = FALSE; else fprintf(cp_err, "Warning: misplaced .endc card\n"); } else if (commands || prefix("*#", dd->li_line)) { wl = alloc(struct wordlist); if (controls) { wl->wl_next = controls; controls->wl_prev = wl; controls = wl; } else controls = wl; if (prefix("*#", dd->li_line)) wl->wl_word = copy(dd->li_line + 2); else { wl->wl_word = dd->li_line; dd->li_line = 0; /* SJB - prevent line_free() freeing the string (now pointed at by wl->wl_word) */ }#ifdef NUMPARAMS /* Look for set or unset numparams. If either are found then we evaluate these lines immediately so they take effect before netlist parsing */ s = wl->wl_word; while(isspace(*s)) s++; /* step past any white space */ if(ciprefix("set", s)) { s+=3; } else if(ciprefix("unset", s)) { s+=5; } if(s!=dd->li_line) { /* one of the above must have matched */ while(isspace(*s)) s++; /* step past white space */ if(ciprefix("numparams", s)) { cp_evloop(wl->wl_word); } }#endif /* NUMPARAMS */ ld->li_next = dd->li_next; line_free(dd,FALSE); /* SJB - free this line's memory */ } else if (!*dd->li_line) { /* So blank lines in com files don't get considered as * circuits. */ ld->li_next = dd->li_next; line_free(dd,FALSE); /* SJB - free this line's memory */ } 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")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -