|
|
|
@ -51,13 +51,13 @@ Author: 1985 Wayne A. Christopher |
|
|
|
|
|
|
|
static char *upper(register char *string); |
|
|
|
static bool doedit(char *filename); |
|
|
|
static struct line *com_options = NULL; |
|
|
|
static void cktislinear(CKTcircuit *ckt, struct line *deck); |
|
|
|
static void dotifeval(struct line *deck); |
|
|
|
static struct card *com_options = NULL; |
|
|
|
static void cktislinear(CKTcircuit *ckt, struct card *deck); |
|
|
|
static void dotifeval(struct card *deck); |
|
|
|
|
|
|
|
static wordlist *inp_savecurrents(struct line *deck, struct line *options, wordlist *wl, wordlist *controls); |
|
|
|
static wordlist *inp_savecurrents(struct card *deck, struct card *options, wordlist *wl, wordlist *controls); |
|
|
|
|
|
|
|
void line_free_x(struct line *deck, bool recurse); |
|
|
|
void line_free_x(struct card *deck, bool recurse); |
|
|
|
void create_circbyline(char *line); |
|
|
|
|
|
|
|
extern bool ft_batchmode; |
|
|
|
@ -74,7 +74,7 @@ struct pt_temper { |
|
|
|
struct pt_temper *next; |
|
|
|
}; |
|
|
|
|
|
|
|
static int inp_parse_temper(struct line *deck, |
|
|
|
static int inp_parse_temper(struct card *deck, |
|
|
|
struct pt_temper **motdlist_p, |
|
|
|
struct pt_temper **devtlist_p); |
|
|
|
static void inp_parse_temper_trees(struct circ *ckt); |
|
|
|
@ -179,10 +179,10 @@ upper(char *string) |
|
|
|
* deck. The listing should be of either LS_PHYSICAL or LS_LOGICAL or |
|
|
|
* LS_DECK lines as specified by the type parameter. */ |
|
|
|
void |
|
|
|
inp_list(FILE *file, struct line *deck, struct line *extras, int type) |
|
|
|
inp_list(FILE *file, struct card *deck, struct card *extras, int type) |
|
|
|
{ |
|
|
|
struct line *here; |
|
|
|
struct line *there; |
|
|
|
struct card *here; |
|
|
|
struct card *there; |
|
|
|
bool renumber; |
|
|
|
bool useout = (file == cp_out); |
|
|
|
int i = 1; |
|
|
|
@ -203,15 +203,15 @@ inp_list(FILE *file, struct line *deck, struct line *extras, int type) |
|
|
|
|
|
|
|
if (type == LS_LOGICAL) { |
|
|
|
top1: |
|
|
|
for (here = deck; here; here = here->li_next) { |
|
|
|
for (here = deck; here; here = here->nextcard) { |
|
|
|
if (renumber) |
|
|
|
here->li_linenum = i; |
|
|
|
if (ciprefix(".end", here->li_line) && !isalpha_c(here->li_line[4])) |
|
|
|
here->linenum = i; |
|
|
|
if (ciprefix(".end", here->line) && !isalpha_c(here->line[4])) |
|
|
|
continue; |
|
|
|
if (*here->li_line != '*') { |
|
|
|
Xprintf(file, "%6d : %s\n", here->li_linenum, upper(here->li_line)); |
|
|
|
if (here->li_error) |
|
|
|
Xprintf(file, "%s\n", here->li_error); |
|
|
|
if (*here->line != '*') { |
|
|
|
Xprintf(file, "%6d : %s\n", here->linenum, upper(here->line)); |
|
|
|
if (here->error) |
|
|
|
Xprintf(file, "%s\n", here->error); |
|
|
|
} |
|
|
|
i++; |
|
|
|
} |
|
|
|
@ -227,33 +227,33 @@ inp_list(FILE *file, struct line *deck, struct line *extras, int type) |
|
|
|
} else if ((type == LS_PHYSICAL) || (type == LS_DECK)) { |
|
|
|
|
|
|
|
top2: |
|
|
|
for (here = deck; here; here = here->li_next) { |
|
|
|
if ((here->li_actual == NULL) || (here == deck)) { |
|
|
|
for (here = deck; here; here = here->nextcard) { |
|
|
|
if ((here->actualLine == NULL) || (here == deck)) { |
|
|
|
if (renumber) |
|
|
|
here->li_linenum = i; |
|
|
|
if (ciprefix(".end", here->li_line) && !isalpha_c(here->li_line[4])) |
|
|
|
here->linenum = i; |
|
|
|
if (ciprefix(".end", here->line) && !isalpha_c(here->line[4])) |
|
|
|
continue; |
|
|
|
if (type == LS_PHYSICAL) |
|
|
|
Xprintf(file, "%6d : %s\n", |
|
|
|
here->li_linenum, upper(here->li_line)); |
|
|
|
here->linenum, upper(here->line)); |
|
|
|
else |
|
|
|
Xprintf(file, "%s\n", upper(here->li_line)); |
|
|
|
if (here->li_error && (type == LS_PHYSICAL)) |
|
|
|
Xprintf(file, "%s\n", here->li_error); |
|
|
|
Xprintf(file, "%s\n", upper(here->line)); |
|
|
|
if (here->error && (type == LS_PHYSICAL)) |
|
|
|
Xprintf(file, "%s\n", here->error); |
|
|
|
} else { |
|
|
|
for (there = here->li_actual; there; there = there->li_next) { |
|
|
|
there->li_linenum = i++; |
|
|
|
if (ciprefix(".end", here->li_line) && isalpha_c(here->li_line[4])) |
|
|
|
for (there = here->actualLine; there; there = there->nextcard) { |
|
|
|
there->linenum = i++; |
|
|
|
if (ciprefix(".end", here->line) && isalpha_c(here->line[4])) |
|
|
|
continue; |
|
|
|
if (type == LS_PHYSICAL) |
|
|
|
Xprintf(file, "%6d : %s\n", |
|
|
|
there->li_linenum, upper(there->li_line)); |
|
|
|
there->linenum, upper(there->line)); |
|
|
|
else |
|
|
|
Xprintf(file, "%s\n", upper(there->li_line)); |
|
|
|
if (there->li_error && (type == LS_PHYSICAL)) |
|
|
|
Xprintf(file, "%s\n", there->li_error); |
|
|
|
Xprintf(file, "%s\n", upper(there->line)); |
|
|
|
if (there->error && (type == LS_PHYSICAL)) |
|
|
|
Xprintf(file, "%s\n", there->error); |
|
|
|
} |
|
|
|
here->li_linenum = i; |
|
|
|
here->linenum = i; |
|
|
|
} |
|
|
|
i++; |
|
|
|
} |
|
|
|
@ -274,19 +274,19 @@ inp_list(FILE *file, struct line *deck, struct line *extras, int type) |
|
|
|
|
|
|
|
/* |
|
|
|
* Free memory used by a line. |
|
|
|
* If recurse is TRUE then recursively free all lines linked via the ->li_next field. |
|
|
|
* If recurse is TRUE then recursively free all lines linked via the ->nextcard field. |
|
|
|
* If recurse is FALSE free only this line. |
|
|
|
* All lines linked via the ->li_actual field are always recursivly freed. |
|
|
|
* All lines linked via the ->actualLine field are always recursivly freed. |
|
|
|
* SJB - 22nd May 2001 |
|
|
|
*/ |
|
|
|
void |
|
|
|
line_free_x(struct line *deck, bool recurse) |
|
|
|
line_free_x(struct card *deck, bool recurse) |
|
|
|
{ |
|
|
|
while (deck) { |
|
|
|
struct line *next_deck = deck->li_next; |
|
|
|
line_free_x(deck->li_actual, TRUE); |
|
|
|
tfree(deck->li_line); |
|
|
|
tfree(deck->li_error); |
|
|
|
struct card *next_deck = deck->nextcard; |
|
|
|
line_free_x(deck->actualLine, TRUE); |
|
|
|
tfree(deck->line); |
|
|
|
tfree(deck->error); |
|
|
|
tfree(deck); |
|
|
|
if (!recurse) |
|
|
|
return; |
|
|
|
@ -296,31 +296,31 @@ line_free_x(struct line *deck, bool recurse) |
|
|
|
|
|
|
|
|
|
|
|
/* concatenate two lists, destructively altering the first one */ |
|
|
|
struct line * |
|
|
|
line_nconc(struct line *head, struct line *rest) |
|
|
|
struct card * |
|
|
|
line_nconc(struct card *head, struct card *rest) |
|
|
|
{ |
|
|
|
struct line *p = head; |
|
|
|
struct card *p = head; |
|
|
|
if (!rest) |
|
|
|
return head; |
|
|
|
if (!head) |
|
|
|
return rest; |
|
|
|
while (p->li_next) |
|
|
|
p = p->li_next; |
|
|
|
p->li_next = rest; |
|
|
|
while (p->nextcard) |
|
|
|
p = p->nextcard; |
|
|
|
p->nextcard = rest; |
|
|
|
return head; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* reverse the linked list struct line */ |
|
|
|
struct line * |
|
|
|
line_reverse(struct line *head) |
|
|
|
/* reverse the linked list struct card */ |
|
|
|
struct card * |
|
|
|
line_reverse(struct card *head) |
|
|
|
{ |
|
|
|
struct line *prev = NULL; |
|
|
|
struct line *next; |
|
|
|
struct card *prev = NULL; |
|
|
|
struct card *next; |
|
|
|
|
|
|
|
while (head) { |
|
|
|
next = head->li_next; |
|
|
|
head->li_next = prev; |
|
|
|
next = head->nextcard; |
|
|
|
head->nextcard = prev; |
|
|
|
prev = head; |
|
|
|
head = next; |
|
|
|
} |
|
|
|
@ -343,8 +343,8 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
* intfile = whether input is from internal array. Values are TRUE/FALSE |
|
|
|
*/ |
|
|
|
{ |
|
|
|
struct line *deck, *dd, *ld, *prev_param = NULL, *prev_card = NULL; |
|
|
|
struct line *realdeck = NULL, *options = NULL, *curr_meas = NULL; |
|
|
|
struct card *deck, *dd, *ld, *prev_param = NULL, *prev_card = NULL; |
|
|
|
struct card *realdeck = NULL, *options = NULL, *curr_meas = NULL; |
|
|
|
char *tt = NULL, name[BSIZE_SP], *s, *t, *temperature = NULL; |
|
|
|
double testemp = 0.0; |
|
|
|
bool commands = FALSE; |
|
|
|
@ -377,7 +377,7 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
} |
|
|
|
|
|
|
|
/* files starting with *ng_script are user supplied command files */ |
|
|
|
if (ciprefix("*ng_script", deck->li_line)) |
|
|
|
if (ciprefix("*ng_script", deck->line)) |
|
|
|
comfile = TRUE; |
|
|
|
|
|
|
|
if (!comfile) { |
|
|
|
@ -389,8 +389,8 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
realdeck = inp_deckcopy(deck); |
|
|
|
|
|
|
|
/* Save the title before INPgetTitle gets it. */ |
|
|
|
tt = copy(deck->li_line); |
|
|
|
if (!deck->li_next) |
|
|
|
tt = copy(deck->line); |
|
|
|
if (!deck->nextcard) |
|
|
|
fprintf(cp_err, "Warning: no lines in input\n"); |
|
|
|
} |
|
|
|
if (!intfile) |
|
|
|
@ -419,17 +419,17 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
/* Process each command, except 'option' which is assembled |
|
|
|
in a list and ingnored here */ |
|
|
|
for (dd = deck; dd; dd = ld) { |
|
|
|
ld = dd->li_next; |
|
|
|
if ((dd->li_line[0] == '*') && (dd->li_line[1] != '#')) |
|
|
|
ld = dd->nextcard; |
|
|
|
if ((dd->line[0] == '*') && (dd->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); |
|
|
|
if (!ciprefix(".control", dd->line) && !ciprefix(".endc", dd->line)) { |
|
|
|
if (dd->line[0] == '*') |
|
|
|
cp_evloop(dd->line + 2); |
|
|
|
/* option line stored but not processed */ |
|
|
|
else if (ciprefix("option", dd->li_line)) |
|
|
|
com_options = inp_getoptsc(dd->li_line, com_options); |
|
|
|
else if (ciprefix("option", dd->line)) |
|
|
|
com_options = inp_getoptsc(dd->line, com_options); |
|
|
|
else |
|
|
|
cp_evloop(dd->li_line); |
|
|
|
cp_evloop(dd->line); |
|
|
|
} |
|
|
|
} |
|
|
|
/* free the control deck */ |
|
|
|
@ -442,22 +442,22 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
|
|
|
|
else { /* must be regular deck . . . . */ |
|
|
|
/* loop through deck and handle control cards */ |
|
|
|
for (dd = deck->li_next; dd; dd = ld->li_next) { |
|
|
|
for (dd = deck->nextcard; dd; dd = ld->nextcard) { |
|
|
|
/* get temp from deck */ |
|
|
|
if (ciprefix(".temp", dd->li_line)) { |
|
|
|
s = skip_ws(dd->li_line + 5); |
|
|
|
if (ciprefix(".temp", dd->line)) { |
|
|
|
s = skip_ws(dd->line + 5); |
|
|
|
if (temperature) |
|
|
|
txfree(temperature); |
|
|
|
temperature = strdup(s); |
|
|
|
} |
|
|
|
/* Ignore comment lines, but not lines begining with '*#', |
|
|
|
but remove them, if they are in a .control ... .endc section */ |
|
|
|
s = skip_ws(dd->li_line); |
|
|
|
if ((*s == '*') && ((s != dd->li_line) || (s[1] != '#'))) { |
|
|
|
s = skip_ws(dd->line); |
|
|
|
if ((*s == '*') && ((s != dd->line) || (s[1] != '#'))) { |
|
|
|
if (commands) { |
|
|
|
/* Remove comment lines in control sections, so they don't |
|
|
|
* get considered as circuits. */ |
|
|
|
ld->li_next = dd->li_next; |
|
|
|
ld->nextcard = dd->nextcard; |
|
|
|
line_free(dd, FALSE); |
|
|
|
continue; |
|
|
|
} |
|
|
|
@ -466,55 +466,55 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
} |
|
|
|
|
|
|
|
/* Put the first token from line into s */ |
|
|
|
strncpy(name, dd->li_line, BSIZE_SP); |
|
|
|
strncpy(name, dd->line, BSIZE_SP); |
|
|
|
s = skip_ws(name); |
|
|
|
t = skip_non_ws(s); |
|
|
|
*t = '\0'; |
|
|
|
|
|
|
|
if (ciprefix(".control", dd->li_line)) { |
|
|
|
ld->li_next = dd->li_next; |
|
|
|
if (ciprefix(".control", dd->line)) { |
|
|
|
ld->nextcard = dd->nextcard; |
|
|
|
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; |
|
|
|
} else if (ciprefix(".endc", dd->line)) { |
|
|
|
ld->nextcard = dd->nextcard; |
|
|
|
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)) { |
|
|
|
} else if (commands || prefix("*#", dd->line)) { |
|
|
|
/* assemble all commands starting with pre_ after stripping pre_, |
|
|
|
to be executed before circuit parsing */ |
|
|
|
if (ciprefix("pre_", dd->li_line)) { |
|
|
|
s = copy(dd->li_line + 4); |
|
|
|
if (ciprefix("pre_", dd->line)) { |
|
|
|
s = copy(dd->line + 4); |
|
|
|
pre_controls = wl_cons(s, pre_controls); |
|
|
|
} |
|
|
|
/* assemble all other commands to be executed after circuit parsing */ |
|
|
|
else { |
|
|
|
/* special control lines outside of .control section*/ |
|
|
|
if (prefix("*#", dd->li_line)) { |
|
|
|
s = copy(dd->li_line + 2); |
|
|
|
if (prefix("*#", dd->line)) { |
|
|
|
s = copy(dd->line + 2); |
|
|
|
/* all commands from within .control section */ |
|
|
|
} else { |
|
|
|
s = dd->li_line; |
|
|
|
dd->li_line = NULL; /* SJB - prevent line_free() freeing the string (now pointed at by wl->wl_word) */ |
|
|
|
s = dd->line; |
|
|
|
dd->line = NULL; /* SJB - prevent line_free() freeing the string (now pointed at by wl->wl_word) */ |
|
|
|
} |
|
|
|
controls = wl_cons(s, controls); |
|
|
|
} |
|
|
|
ld->li_next = dd->li_next; |
|
|
|
ld->nextcard = dd->nextcard; |
|
|
|
line_free(dd, FALSE); |
|
|
|
} else if (!*dd->li_line) { |
|
|
|
} else if (!*dd->line) { |
|
|
|
/* So blank lines in com files don't get considered as circuits. */ |
|
|
|
ld->li_next = dd->li_next; |
|
|
|
ld->nextcard = dd->nextcard; |
|
|
|
line_free(dd, FALSE); |
|
|
|
} else { |
|
|
|
/* lines .width, .four, .plot, .print, .save added to wl_first, removed from deck */ |
|
|
|
/* lines .op, .meas, .tf added to wl_first */ |
|
|
|
inp_casefix(s); /* s: first token from line */ |
|
|
|
inp_casefix(dd->li_line); |
|
|
|
inp_casefix(dd->line); |
|
|
|
if (eq(s, ".width") || |
|
|
|
ciprefix(".four", s) || |
|
|
|
eq(s, ".plot") || |
|
|
|
@ -524,10 +524,10 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
ciprefix(".meas", s) || |
|
|
|
eq(s, ".tf")) |
|
|
|
{ |
|
|
|
wl_append_word(&wl_first, &end, copy(dd->li_line)); |
|
|
|
wl_append_word(&wl_first, &end, copy(dd->line)); |
|
|
|
|
|
|
|
if (!eq(s, ".op") && !eq(s, ".tf") && !ciprefix(".meas", s)) { |
|
|
|
ld->li_next = dd->li_next; |
|
|
|
ld->nextcard = dd->nextcard; |
|
|
|
line_free(dd, FALSE); |
|
|
|
} else { |
|
|
|
ld = dd; |
|
|
|
@ -536,7 +536,7 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
ld = dd; |
|
|
|
} |
|
|
|
} |
|
|
|
} /* end for (dd = deck->li_next . . . . */ |
|
|
|
} /* end for (dd = deck->nextcard . . . . */ |
|
|
|
|
|
|
|
/* Now that the deck is loaded, do the pre commands, if there are any, |
|
|
|
before the circuit structure is set up */ |
|
|
|
@ -560,16 +560,16 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
|
|
|
|
/* We are done handling the control stuff. Now process remainder of deck. |
|
|
|
Go on if there is something left after the controls.*/ |
|
|
|
if (deck->li_next) { |
|
|
|
if (deck->nextcard) { |
|
|
|
fprintf(cp_out, "\nCircuit: %s\n\n", tt); |
|
|
|
#ifdef HAS_PROGREP |
|
|
|
SetAnalyse("Prepare Deck", 0); |
|
|
|
#endif |
|
|
|
/* Now expand subcircuit macros and substitute numparams.*/ |
|
|
|
if (!cp_getvar("nosubckt", CP_BOOL, NULL)) |
|
|
|
if ((deck->li_next = inp_subcktexpand(deck->li_next)) == NULL) { |
|
|
|
if ((deck->nextcard = inp_subcktexpand(deck->nextcard)) == NULL) { |
|
|
|
line_free(realdeck, TRUE); |
|
|
|
line_free(deck->li_actual, TRUE); |
|
|
|
line_free(deck->actualLine, TRUE); |
|
|
|
tfree(tt); |
|
|
|
return; |
|
|
|
} |
|
|
|
@ -577,41 +577,41 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
/* Now handle translation of spice2c6 POLYs. */ |
|
|
|
#ifdef XSPICE |
|
|
|
/* Translate all SPICE 2G6 polynomial type sources */ |
|
|
|
deck->li_next = ENHtranslate_poly(deck->li_next); |
|
|
|
deck->nextcard = ENHtranslate_poly(deck->nextcard); |
|
|
|
#endif |
|
|
|
|
|
|
|
line_free(deck->li_actual, FALSE); |
|
|
|
deck->li_actual = realdeck; |
|
|
|
line_free(deck->actualLine, FALSE); |
|
|
|
deck->actualLine = realdeck; |
|
|
|
|
|
|
|
/* print out the expanded deck into debug-out2.txt */ |
|
|
|
if (ft_ngdebug) { |
|
|
|
/*debug: print into file*/ |
|
|
|
FILE *fdo = fopen("debug-out2.txt", "w"); |
|
|
|
struct line *t = NULL; |
|
|
|
struct card *t = NULL; |
|
|
|
fprintf(fdo, "**************** uncommented deck **************\n\n"); |
|
|
|
/* always print first line */ |
|
|
|
fprintf(fdo, "%6d %6d %s\n", deck->li_linenum_orig, deck->li_linenum, deck->li_line); |
|
|
|
fprintf(fdo, "%6d %6d %s\n", deck->linenum_orig, deck->linenum, deck->line); |
|
|
|
/* here without out-commented lines */ |
|
|
|
for (t = deck->li_next; t; t = t->li_next) { |
|
|
|
if (*(t->li_line) == '*') |
|
|
|
for (t = deck->nextcard; t; t = t->nextcard) { |
|
|
|
if (*(t->line) == '*') |
|
|
|
continue; |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->li_linenum_orig, t->li_linenum, t->li_line); |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->linenum_orig, t->linenum, t->line); |
|
|
|
} |
|
|
|
fprintf(fdo, "\n****************** complete deck ***************\n\n"); |
|
|
|
/* now completely */ |
|
|
|
for (t = deck; t; t = t->li_next) |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->li_linenum_orig, t->li_linenum, t->li_line); |
|
|
|
for (t = deck; t; t = t->nextcard) |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->linenum_orig, t->linenum, t->line); |
|
|
|
fclose(fdo); |
|
|
|
} |
|
|
|
for (dd = deck; dd; dd = dd->li_next) { |
|
|
|
for (dd = deck; dd; dd = dd->nextcard) { |
|
|
|
/* get csparams and create vectors, being |
|
|
|
available in .control section, in plot 'const' */ |
|
|
|
if (ciprefix(".csparam", dd->li_line)) { |
|
|
|
if (ciprefix(".csparam", dd->line)) { |
|
|
|
wordlist *wlist = NULL; |
|
|
|
char *cstoken[3]; |
|
|
|
int i; |
|
|
|
dd->li_line[0] = '*'; |
|
|
|
s = skip_ws(dd->li_line + 8); |
|
|
|
dd->line[0] = '*'; |
|
|
|
s = skip_ws(dd->line + 8); |
|
|
|
cstoken[0] = gettok_char(&s, '=', FALSE, FALSE); |
|
|
|
cstoken[1] = gettok_char(&s, '=', TRUE, FALSE); |
|
|
|
cstoken[2] = gettok(&s); |
|
|
|
@ -654,7 +654,7 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
tt = NULL; |
|
|
|
options = NULL; |
|
|
|
|
|
|
|
} /* if (deck->li_next) */ |
|
|
|
} /* if (deck->nextcard) */ |
|
|
|
|
|
|
|
/* look for and set temperature; also store param and .meas statements in circuit struct */ |
|
|
|
if (ft_curckt) { |
|
|
|
@ -664,33 +664,33 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
ft_curckt->FTEstats->FTESTATnetLoadTime = endTime - startTime; |
|
|
|
} |
|
|
|
|
|
|
|
for (dd = deck; dd; dd = dd->li_next) { |
|
|
|
for (dd = deck; dd; dd = dd->nextcard) { |
|
|
|
/* all parameter lines should be sequentially ordered and placed at |
|
|
|
beginning of deck */ |
|
|
|
if (ciprefix(".para", dd->li_line)) { |
|
|
|
if (ciprefix(".para", dd->line)) { |
|
|
|
ft_curckt->ci_param = dd; |
|
|
|
/* find end of .param statements */ |
|
|
|
while (ciprefix(".para", dd->li_line)) { |
|
|
|
while (ciprefix(".para", dd->line)) { |
|
|
|
prev_param = dd; |
|
|
|
dd = dd->li_next; |
|
|
|
dd = dd->nextcard; |
|
|
|
if (dd == NULL) |
|
|
|
break; // no line after .param line |
|
|
|
} |
|
|
|
prev_card->li_next = dd; |
|
|
|
prev_param->li_next = NULL; |
|
|
|
prev_card->nextcard = dd; |
|
|
|
prev_param->nextcard = NULL; |
|
|
|
if (dd == NULL) { |
|
|
|
fprintf(cp_err, "Warning: Missing .end card!\n"); |
|
|
|
break; // no line after .param line |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (ciprefix(".meas", dd->li_line)) { |
|
|
|
if (ciprefix(".meas", dd->line)) { |
|
|
|
if (cp_getvar("autostop", CP_BOOL, NULL)) { |
|
|
|
if (strstr(dd->li_line, " max ") || |
|
|
|
strstr(dd->li_line, " min ") || |
|
|
|
strstr(dd->li_line, " avg ") || |
|
|
|
strstr(dd->li_line, " rms ") || |
|
|
|
strstr(dd->li_line, " integ ")) |
|
|
|
if (strstr(dd->line, " max ") || |
|
|
|
strstr(dd->line, " min ") || |
|
|
|
strstr(dd->line, " avg ") || |
|
|
|
strstr(dd->line, " rms ") || |
|
|
|
strstr(dd->line, " integ ")) |
|
|
|
{ |
|
|
|
printf("Warning: .OPTION AUTOSTOP will not be effective because one of 'max|min|avg|rms|integ' is used in .meas\n"); |
|
|
|
printf(" AUTOSTOP being disabled...\n"); |
|
|
|
@ -701,11 +701,11 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
if (curr_meas == NULL) { |
|
|
|
curr_meas = ft_curckt->ci_meas = dd; |
|
|
|
} else { |
|
|
|
curr_meas->li_next = dd; |
|
|
|
curr_meas->nextcard = dd; |
|
|
|
curr_meas = dd; |
|
|
|
} |
|
|
|
prev_card->li_next = dd->li_next; |
|
|
|
curr_meas->li_next = NULL; |
|
|
|
prev_card->nextcard = dd->nextcard; |
|
|
|
curr_meas->nextcard = NULL; |
|
|
|
dd = prev_card; |
|
|
|
} |
|
|
|
prev_card = dd; |
|
|
|
@ -729,20 +729,20 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
if (ft_ngdebug) { |
|
|
|
/*debug: print into file*/ |
|
|
|
FILE *fdo = fopen("debug-out3.txt", "w"); |
|
|
|
struct line *t = NULL; |
|
|
|
struct card *t = NULL; |
|
|
|
fprintf(fdo, "**************** uncommented deck **************\n\n"); |
|
|
|
/* always print first line */ |
|
|
|
fprintf(fdo, "%6d %6d %s\n", deck->li_linenum_orig, deck->li_linenum, deck->li_line); |
|
|
|
fprintf(fdo, "%6d %6d %s\n", deck->linenum_orig, deck->linenum, deck->line); |
|
|
|
/* here without out-commented lines */ |
|
|
|
for (t = deck->li_next; t; t = t->li_next) { |
|
|
|
if (*(t->li_line) == '*') |
|
|
|
for (t = deck->nextcard; t; t = t->nextcard) { |
|
|
|
if (*(t->line) == '*') |
|
|
|
continue; |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->li_linenum_orig, t->li_linenum, t->li_line); |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->linenum_orig, t->linenum, t->line); |
|
|
|
} |
|
|
|
fprintf(fdo, "\n****************** complete deck ***************\n\n"); |
|
|
|
/* now completely */ |
|
|
|
for (t = deck; t; t = t->li_next) |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->li_linenum_orig, t->li_linenum, t->li_line); |
|
|
|
for (t = deck; t; t = t->nextcard) |
|
|
|
fprintf(fdo, "%6d %6d %s\n", t->linenum_orig, t->linenum, t->line); |
|
|
|
fclose(fdo); |
|
|
|
} |
|
|
|
|
|
|
|
@ -789,17 +789,17 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) |
|
|
|
*-----------------------------------------------------------------*/ |
|
|
|
void |
|
|
|
inp_dodeck( |
|
|
|
struct line *deck, /*in: the spice deck */ |
|
|
|
struct card *deck, /*in: the spice deck */ |
|
|
|
char *tt, /*in: the title of the deck */ |
|
|
|
wordlist *end, /*in: all lines with .width, .plot, .print, .save, .op, .meas, .tf */ |
|
|
|
bool reuse, /*in: TRUE if called from runcoms2.c com_rset, |
|
|
|
FALSE if called from inp_spsource() */ |
|
|
|
struct line *options, /*in: all .option lines from deck */ |
|
|
|
struct card *options, /*in: all .option lines from deck */ |
|
|
|
char *filename /*in: input file of deck */ |
|
|
|
) |
|
|
|
{ |
|
|
|
struct circ *ct; |
|
|
|
struct line *dd; |
|
|
|
struct card *dd; |
|
|
|
CKTcircuit *ckt; |
|
|
|
char *s; |
|
|
|
INPtables *tab = NULL; |
|
|
|
@ -814,10 +814,10 @@ inp_dodeck( |
|
|
|
|
|
|
|
/* First throw away any old error messages there might be and fix |
|
|
|
the case of the lines. */ |
|
|
|
for (dd = deck; dd; dd = dd->li_next) |
|
|
|
if (dd->li_error) { |
|
|
|
tfree(dd->li_error); |
|
|
|
dd->li_error = NULL; |
|
|
|
for (dd = deck; dd; dd = dd->nextcard) |
|
|
|
if (dd->error) { |
|
|
|
tfree(dd->error); |
|
|
|
dd->error = NULL; |
|
|
|
} |
|
|
|
|
|
|
|
if (reuse) { |
|
|
|
@ -841,9 +841,9 @@ inp_dodeck( |
|
|
|
is needed because we need the scale info BEFORE building the circuit |
|
|
|
and seems there is no other way to do this. */ |
|
|
|
if (!noparse) { |
|
|
|
struct line *opt_beg = options; |
|
|
|
for (; options; options = options->li_next) { |
|
|
|
s = skip_non_ws(options->li_line); |
|
|
|
struct card *opt_beg = options; |
|
|
|
for (; options; options = options->nextcard) { |
|
|
|
s = skip_non_ws(options->line); |
|
|
|
|
|
|
|
ii = cp_interactive; |
|
|
|
cp_interactive = FALSE; |
|
|
|
@ -916,42 +916,42 @@ inp_dodeck( |
|
|
|
ft_curckt->FTEstats->FTESTATdeckNumLines = 0; |
|
|
|
/*---------------------------------------------------- |
|
|
|
Now run through the deck and look to see if there are |
|
|
|
errors on any line (message contained in ->li_error). |
|
|
|
errors on any line (message contained in ->error). |
|
|
|
|
|
|
|
Error messages have been generated either by writing |
|
|
|
directly to ->li_error from a struct line or to |
|
|
|
directly to ->error from a struct card or to |
|
|
|
->error from a struct card , or by using one of the |
|
|
|
macros as defined in inpmacs.h. Functions INPerror(), |
|
|
|
INPerrCat(), and SPerror() are invoked. |
|
|
|
*---------------------------------------------------*/ |
|
|
|
for (dd = deck; dd; dd = dd->li_next) { |
|
|
|
for (dd = deck; dd; dd = dd->nextcard) { |
|
|
|
|
|
|
|
ft_curckt->FTEstats->FTESTATdeckNumLines += 1; |
|
|
|
|
|
|
|
#ifdef TRACE |
|
|
|
/* SDB debug statement */ |
|
|
|
printf("In inp_dodeck, looking for errors and examining line %s . . . \n", dd->li_line); |
|
|
|
printf("In inp_dodeck, looking for errors and examining line %s . . . \n", dd->line); |
|
|
|
#endif |
|
|
|
|
|
|
|
if (dd->li_error) { |
|
|
|
if (dd->error) { |
|
|
|
char *p, *q; |
|
|
|
#ifdef XSPICE |
|
|
|
/* add setting of ipc syntax error flag */ |
|
|
|
g_ipc.syntax_error = IPC_TRUE; |
|
|
|
#endif |
|
|
|
p = dd->li_error; |
|
|
|
p = dd->error; |
|
|
|
do { |
|
|
|
q = strchr(p, '\n'); |
|
|
|
if (q) |
|
|
|
*q = '\0'; |
|
|
|
|
|
|
|
if (p == dd->li_error) { |
|
|
|
if (strstr(dd->li_line, ".model")) |
|
|
|
if (p == dd->error) { |
|
|
|
if (strstr(dd->line, ".model")) |
|
|
|
out_printf("Warning: Model issue on line %d :\n %.*s ...\n%s\n", |
|
|
|
dd->li_linenum_orig, 72, dd->li_line, dd->li_error); |
|
|
|
dd->linenum_orig, 72, dd->line, dd->error); |
|
|
|
else { |
|
|
|
out_printf("Error on line %d :\n %s\n%s\n", |
|
|
|
dd->li_linenum_orig, dd->li_line, dd->li_error); |
|
|
|
dd->linenum_orig, dd->line, dd->error); |
|
|
|
have_err = TRUE; |
|
|
|
} |
|
|
|
if (ft_stricterror) |
|
|
|
@ -964,9 +964,9 @@ inp_dodeck( |
|
|
|
*q++ = '\n'; |
|
|
|
p = q; |
|
|
|
} while (p && *p); |
|
|
|
} /* end if (dd->li_error) */ |
|
|
|
} /* end if (dd->error) */ |
|
|
|
|
|
|
|
} /* for (dd = deck; dd; dd = dd->li_next) */ |
|
|
|
} /* for (dd = deck; dd; dd = dd->nextcard) */ |
|
|
|
|
|
|
|
/* Stop here and exit if error occurred in batch mode */ |
|
|
|
if (have_err && ft_batchmode) { |
|
|
|
@ -980,12 +980,12 @@ inp_dodeck( |
|
|
|
out_printf("\nProcessed Netlist\n"); |
|
|
|
out_printf("=================\n"); |
|
|
|
print_listing = 1; |
|
|
|
for (dd = deck; dd; dd = dd->li_next) { |
|
|
|
if (ciprefix(".prot", dd->li_line)) |
|
|
|
for (dd = deck; dd; dd = dd->nextcard) { |
|
|
|
if (ciprefix(".prot", dd->line)) |
|
|
|
print_listing = 0; |
|
|
|
if (print_listing == 1) |
|
|
|
out_printf("%s\n", dd->li_line); |
|
|
|
if (ciprefix(".unprot", dd->li_line)) |
|
|
|
out_printf("%s\n", dd->line); |
|
|
|
if (ciprefix(".unprot", dd->line)) |
|
|
|
print_listing = 1; |
|
|
|
} |
|
|
|
out_printf("\n"); |
|
|
|
@ -1006,8 +1006,8 @@ inp_dodeck( |
|
|
|
ct->ci_name = tt; |
|
|
|
ct->ci_deck = deck; |
|
|
|
ct->ci_options = options; |
|
|
|
if (deck->li_actual) |
|
|
|
ct->ci_origdeck = deck->li_actual; |
|
|
|
if (deck->actualLine) |
|
|
|
ct->ci_origdeck = deck->actualLine; |
|
|
|
else |
|
|
|
ct->ci_origdeck = ct->ci_deck; |
|
|
|
ct->ci_ckt = ckt; /* attach the input ckt to the list of circuits */ |
|
|
|
@ -1021,8 +1021,8 @@ inp_dodeck( |
|
|
|
|
|
|
|
if (!noparse) { |
|
|
|
/* |
|
|
|
* for (; options; options = options->li_next) { |
|
|
|
* s = skip_non_ws(options->li_line); |
|
|
|
* for (; options; options = options->nextcard) { |
|
|
|
* s = skip_non_ws(options->line); |
|
|
|
* ii = cp_interactive; |
|
|
|
* cp_interactive = FALSE; |
|
|
|
* wl = cp_lexer(s); |
|
|
|
@ -1264,14 +1264,14 @@ inp_source(char *file) |
|
|
|
ckt->CKTisLinear is set to 1. Return immediately if a first |
|
|
|
non-linear element is found. */ |
|
|
|
static void |
|
|
|
cktislinear(CKTcircuit *ckt, struct line *deck) |
|
|
|
cktislinear(CKTcircuit *ckt, struct card *deck) |
|
|
|
{ |
|
|
|
struct line *dd; |
|
|
|
struct card *dd; |
|
|
|
char firstchar; |
|
|
|
|
|
|
|
if (deck->li_next) |
|
|
|
for (dd = deck->li_next; dd; dd = dd->li_next) { |
|
|
|
firstchar = *dd->li_line; |
|
|
|
if (deck->nextcard) |
|
|
|
for (dd = deck->nextcard; dd; dd = dd->nextcard) { |
|
|
|
firstchar = *dd->line; |
|
|
|
switch (firstchar) { |
|
|
|
case 'r': |
|
|
|
case 'l': |
|
|
|
@ -1342,17 +1342,17 @@ com_circbyline(wordlist *wl) |
|
|
|
numparam has evaluated .if('boolean expression') to |
|
|
|
.if ( 1.000000000e+000 ) or .elseif ( 0.000000000e+000 ) */ |
|
|
|
static void |
|
|
|
dotifeval(struct line *deck) |
|
|
|
dotifeval(struct card *deck) |
|
|
|
{ |
|
|
|
int iftrue = 0, elseiftrue = 0, elsetrue = 0, iffound = 0, elseiffound = 0, elsefound = 0; |
|
|
|
struct line *dd; |
|
|
|
struct card *dd; |
|
|
|
char *dottoken; |
|
|
|
char *s, *t; |
|
|
|
|
|
|
|
/* skip the first line (title line) */ |
|
|
|
for (dd = deck->li_next; dd; dd = dd->li_next) { |
|
|
|
for (dd = deck->nextcard; dd; dd = dd->nextcard) { |
|
|
|
|
|
|
|
s = t = dd->li_line; |
|
|
|
s = t = dd->line; |
|
|
|
|
|
|
|
if (*s == '*') |
|
|
|
continue; |
|
|
|
@ -1364,7 +1364,7 @@ dotifeval(struct line *deck) |
|
|
|
elseiffound = 0; |
|
|
|
iffound = 1; |
|
|
|
*s = '*'; |
|
|
|
s = dd->li_line + 3; |
|
|
|
s = dd->line + 3; |
|
|
|
iftrue = atoi(s); |
|
|
|
} |
|
|
|
else if (cieq(dottoken, ".elseif")) { |
|
|
|
@ -1373,7 +1373,7 @@ dotifeval(struct line *deck) |
|
|
|
iffound = 0; |
|
|
|
*s = '*'; |
|
|
|
if (!iftrue) { |
|
|
|
s = dd->li_line + 7; |
|
|
|
s = dd->line + 7; |
|
|
|
elseiftrue = atoi(s); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1435,7 +1435,7 @@ dotifeval(struct line *deck) |
|
|
|
*/ |
|
|
|
|
|
|
|
static int |
|
|
|
inp_parse_temper(struct line *card, struct pt_temper **modtlist_p, struct pt_temper **devtlist_p) |
|
|
|
inp_parse_temper(struct card *card, struct pt_temper **modtlist_p, struct pt_temper **devtlist_p) |
|
|
|
{ |
|
|
|
int error = 0; |
|
|
|
|
|
|
|
@ -1443,10 +1443,10 @@ inp_parse_temper(struct line *card, struct pt_temper **modtlist_p, struct pt_tem |
|
|
|
struct pt_temper *devtlist = NULL; |
|
|
|
|
|
|
|
/* skip title line */ |
|
|
|
card = card->li_next; |
|
|
|
for (; card; card = card->li_next) { |
|
|
|
card = card->nextcard; |
|
|
|
for (; card; card = card->nextcard) { |
|
|
|
|
|
|
|
char *curr_line = card->li_line; |
|
|
|
char *curr_line = card->line; |
|
|
|
|
|
|
|
/* exclude some elements */ |
|
|
|
if (strchr("*vbiegfh", curr_line[0])) |
|
|
|
@ -1600,13 +1600,13 @@ inp_evaluate_temper(struct circ *circ) |
|
|
|
*/ |
|
|
|
|
|
|
|
static wordlist * |
|
|
|
inp_savecurrents(struct line *deck, struct line *options, wordlist *wl, wordlist *controls) |
|
|
|
inp_savecurrents(struct card *deck, struct card *options, wordlist *wl, wordlist *controls) |
|
|
|
{ |
|
|
|
wordlist *p; |
|
|
|
|
|
|
|
/* check if option 'savecurrents' is set */ |
|
|
|
for (; options; options = options->li_next) |
|
|
|
if (strstr(options->li_line, "savecurrents")) |
|
|
|
for (; options; options = options->nextcard) |
|
|
|
if (strstr(options->line, "savecurrents")) |
|
|
|
break; |
|
|
|
|
|
|
|
if (!options) |
|
|
|
@ -1633,8 +1633,8 @@ inp_savecurrents(struct line *deck, struct line *options, wordlist *wl, wordlist |
|
|
|
* We currently serve bipolars, resistors, MOS1, capacitors, inductors, |
|
|
|
* controlled current sources. Others may follow. |
|
|
|
*/ |
|
|
|
for (deck = deck->li_next; deck; deck = deck->li_next) { |
|
|
|
char *newline, *devname, *devline = deck->li_line; |
|
|
|
for (deck = deck->nextcard; deck; deck = deck->nextcard) { |
|
|
|
char *newline, *devname, *devline = deck->line; |
|
|
|
|
|
|
|
switch (devline[0]) { |
|
|
|
case 'm': |
|
|
|
|