Used Win32 function PathIsRelativeA() to identify an absolute path instead of checking the string since the system function may handle more cases (network shares, etc.). Also reviewed formatting that was done on inpcom.c by a code beautifier in an earlier commit. Nearly all of it was an improvement, but a few cases were reverted back to closer to the original form. One particular instance was comments where a list of steps was given one per line.

This commit is contained in:
Jim Monte 2019-12-09 23:01:28 -05:00 committed by Holger Vogt
parent 70600258bb
commit 2f3b9d0f2d
1 changed files with 231 additions and 197 deletions

View File

@ -9,6 +9,13 @@ Author: 1985 Wayne A. Christopher
Central function is inp_readall() Central function is inp_readall()
*/ */
/* Note: Must include shlwapi.h before ngspice header defining BOOL due
* to conflict */
#ifdef _WIN32
#include <shlwapi.h> /* for definition of PathIsRelativeA() */
#pragma comment(lib, "Shlwapi.lib")
#endif
#include "ngspice/ngspice.h" #include "ngspice/ngspice.h"
#include "ngspice/compatmode.h" #include "ngspice/compatmode.h"
@ -47,8 +54,8 @@ Author: 1985 Wayne A. Christopher
/*#define TRACE*/ /*#define TRACE*/
/* globals -- wanted to avoid complicating inp_readall interface */ /* globals -- wanted to avoid complicating inp_readall interface */
#define N_LIBRARIES 1000 #define N_LIBRARIES 1000
#define N_PARAMS 1000 #define N_PARAMS 1000
#define N_SUBCKT_W_PARAMS 4000 #define N_SUBCKT_W_PARAMS 4000
#define NPARAMS 10000 #define NPARAMS 10000
@ -69,7 +76,8 @@ struct names {
int num_names; int num_names;
}; };
struct function_env { struct function_env
{
struct function_env *up; struct function_env *up;
struct function { struct function {
@ -79,10 +87,11 @@ struct function_env {
char *params[N_PARAMS]; char *params[N_PARAMS];
int num_parameters; int num_parameters;
const char *accept; const char *accept;
} * functions; } *functions;
}; };
struct func_temper { struct func_temper
{
char *funcname; char *funcname;
int subckt_depth; int subckt_depth;
int subckt_count; int subckt_count;
@ -307,7 +316,7 @@ static struct library *read_a_lib(char *y, char *dir_name)
return NULL; return NULL;
} }
#if defined(__MINGW32__) || defined(_MSC_VER) #if defined(_WIN32)
yy = _fullpath(NULL, y_resolved, 0); yy = _fullpath(NULL, y_resolved, 0);
#else #else
yy = realpath(y_resolved, NULL); yy = realpath(y_resolved, NULL);
@ -342,8 +351,8 @@ static struct library *read_a_lib(char *y, char *dir_name)
fclose(newfp); fclose(newfp);
} }
tfree(yy); txfree(yy);
tfree(y_resolved); txfree(y_resolved);
return lib; return lib;
} }
@ -556,13 +565,21 @@ static COMPATMODE_T ngspice_compat_mode(void)
store contents in string new_title store contents in string new_title
process .lib lines process .lib lines
read file and library name, open file using fcn inp_pathopen() read file and library name, open file using fcn inp_pathopen()
read file contents and put into struct libraries[].deck, one entry per .lib read file contents and put into struct libraries[].deck, one entry per .lib line
line process .inc lines read file and library name, open file using fcn process .inc lines
inp_pathopen() read file contents and add lines to cc make line entry lower read file and library name, open file using fcn inp_pathopen()
case allow for shell end of line continuation (\\) add '+' to beginning of read file contents and add lines to cc
next line add line entry to list cc add '.global gnd' add libraries find make line entry lower case
library section add lines add .end card strip end-of-line comments make allow for shell end of line continuation (\\)
continuation lines a single line add '+' to beginning of next line
add line entry to list cc
add '.global gnd'
add libraries
find library section
add lines
add .end card
strip end-of-line comments
make continuation lines a single line
*** end of processing for command files *** *** end of processing for command files ***
start preparation of input deck for numparam start preparation of input deck for numparam
... ...
@ -716,16 +733,16 @@ struct card *inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile,
for (t = cc->nextcard; t; t = t->nextcard) { for (t = cc->nextcard; t; t = t->nextcard) {
if (*(t->line) == '*') if (*(t->line) == '*')
continue; continue;
fprintf(fd, "%6d %6d %s\n", t->linenum_orig, t->linenum, fprintf(fd, "%6d %6d %s\n",
t->line); t->linenum_orig, t->linenum, t->line);
} }
fprintf(fd, fprintf(fd,
"\n****************** complete deck " "\n****************** complete deck "
"***************\n\n"); "***************\n\n");
/* now completely */ /* now completely */
for (t = cc; t; t = t->nextcard) for (t = cc; t; t = t->nextcard)
fprintf(fd, "%6d %6d %s\n", t->linenum_orig, t->linenum, fprintf(fd, "%6d %6d %s\n",
t->line); t->linenum_orig, t->linenum, t->line);
fclose(fd); fclose(fd);
fprintf(stdout, fprintf(stdout,
@ -763,8 +780,8 @@ struct inp_read_t inp_read(
int line_count = 0; int line_count = 0;
#endif #endif
char *new_title = NULL; char *new_title = NULL;
int line_number = int line_number = 1;
1; /* sjb - renamed to avoid confusion with struct card */ /* sjb - renamed to avoid confusion with struct card */
int line_number_orig = 1; int line_number_orig = 1;
int cirlinecount = 0; /* length of circarray */ int cirlinecount = 0; /* length of circarray */
static int is_control = 0; /* We are reading from a .control section */ static int is_control = 0; /* We are reading from a .control section */
@ -828,8 +845,9 @@ struct inp_read_t inp_read(
#else #else
buffer = readline(fp); buffer = readline(fp);
if (!buffer) if (!buffer) {
break; break;
}
#endif #endif
} }
@ -839,8 +857,9 @@ struct inp_read_t inp_read(
printf("in inp_read, just read %s", buffer); printf("in inp_read, just read %s", buffer);
#endif #endif
if (!buffer) if (!buffer) {
continue; continue;
}
/* OK -- now we have loaded the next line into 'buffer'. Process it. /* OK -- now we have loaded the next line into 'buffer'. Process it.
*/ */
@ -983,10 +1002,9 @@ struct inp_read_t inp_read(
end->linenum = line_number++; end->linenum = line_number++;
end->linenum_orig = line_number_inc++; end->linenum_orig = line_number_inc++;
} }
end->linenum = end->linenum = line_number++; /* SJB - renumber last line */
line_number++; /* SJB - renumber the last line */ end->linenum_orig = line_number_inc++;
end->linenum_orig = /* SJB - renumber the last line */
line_number_inc++; /* SJB - renumber the last line */
} }
/* Fix the buffer up a bit. */ /* Fix the buffer up a bit. */
@ -1122,10 +1140,10 @@ struct inp_read_t inp_read(
} }
*s = '\0'; /* Zap the newline. */ *s = '\0'; /* Zap the newline. */
if ((s - 1) >= buffer && if ((s - 1) >= buffer && s[- 1] == '\r') {
*(s - 1) == /* Zap the carriage return under windows */
'\r') /* Zop the carriage return under windows */ s[- 1] = '\0';
*(s - 1) = '\0'; }
} }
/* find the true .end command out of .endc, .ends, .endl, .end /* find the true .end command out of .endc, .ends, .endl, .end
@ -1214,17 +1232,18 @@ struct inp_read_t inp_read(
} }
static bool is_absolute_pathname(const char *p)
/* Returns true if path is an absolute path and false if it is a
* relative path. No check is done for the existance of the path. */
inline static bool is_absolute_pathname(const char *path)
{ {
#if defined(__MINGW32__) || defined(_MSC_VER) #ifdef _WIN32
/* /... or \... or D:\... or D:/... */ return !PathIsRelativeA(path);
return p[0] == DIR_TERM || p[0] == DIR_TERM_LINUX ||
(isalpha_c(p[0]) && p[1] == ':' &&
(p[2] == DIR_TERM_LINUX || p[2] == DIR_TERM));
#else #else
return p[0] == DIR_TERM; return path[0] == DIR_TERM;
#endif #endif
} } /* end of funciton is_absolute_pathname */
#if 0 #if 0
@ -1232,7 +1251,7 @@ static bool is_absolute_pathname(const char *p)
static bool static bool
is_plain_filename(const char *p) is_plain_filename(const char *p)
{ {
#if defined(__MINGW32__) || defined(_MSC_VER) #if defined(_WIN32)
return return
!strchr(p, DIR_TERM) && !strchr(p, DIR_TERM) &&
!strchr(p, DIR_TERM_LINUX); !strchr(p, DIR_TERM_LINUX);
@ -1270,7 +1289,7 @@ static char *inp_pathresolve(const char *name)
struct variable *v; struct variable *v;
struct stat st; struct stat st;
#if defined(__MINGW32__) || defined(_MSC_VER) #if defined(_WIN32)
/* If variable 'mingwpath' is set: convert mingw /d/... to d:/... */ /* If variable 'mingwpath' is set: convert mingw /d/... to d:/... */
if (cp_getvar("mingwpath", CP_BOOL, NULL, 0) && if (cp_getvar("mingwpath", CP_BOOL, NULL, 0) &&
@ -1299,8 +1318,8 @@ static char *inp_pathresolve(const char *name)
switch (v->va_type) { switch (v->va_type) {
case CP_STRING: case CP_STRING:
cp_wstrip(v->va_string); cp_wstrip(v->va_string);
(void) sprintf( (void) sprintf(buf, "%s%s%s",
buf, "%s%s%s", v->va_string, DIR_PATHSEP, name); v->va_string, DIR_PATHSEP, name);
break; break;
case CP_NUM: case CP_NUM:
(void) sprintf(buf, "%d%s%s", v->va_num, DIR_PATHSEP, name); (void) sprintf(buf, "%d%s%s", v->va_num, DIR_PATHSEP, name);
@ -1729,9 +1748,11 @@ static bool chk_for_line_continuation(char *line)
// //
// change .macro --> .subckt // change .macro --> .subckt
// .eom --> .ends // .eom --> .ends
// .subckt name 1 2 3 params: w=9u l=180n --> .subckt name 1 2 3 w=9u // .subckt name 1 2 3 params: w=9u l=180n -->
// l=180n .subckt name (1 2 3) --> .subckt name 1 2 3 x1 (1 2 3) --> x1 // .subckt name 1 2 3 w=9u l=180n
// 1 2 3 .param func1(x,y) = {x*y} --> .func func1(x,y) {x*y} // .subckt name (1 2 3) --> .subckt name 1 2 3
// x1 (1 2 3) --> x1 1 2 3
// .param func1(x,y) = {x*y} --> .func func1(x,y) {x*y}
static void inp_fix_macro_param_func_paren_io(struct card *card) static void inp_fix_macro_param_func_paren_io(struct card *card)
{ {
@ -1758,8 +1779,8 @@ static void inp_fix_macro_param_func_paren_io(struct card *card)
if (ciprefix(".subckt", card->line) || ciprefix("x", card->line)) { if (ciprefix(".subckt", card->line) || ciprefix("x", card->line)) {
/* remove () */ /* remove () */
str_ptr = skip_non_ws( str_ptr = skip_non_ws(card->line);
card->line); // skip over .subckt, instance name // skip over .subckt, instance name
str_ptr = skip_ws(str_ptr); str_ptr = skip_ws(str_ptr);
if (ciprefix(".subckt", card->line)) { if (ciprefix(".subckt", card->line)) {
str_ptr = skip_non_ws(str_ptr); // skip over subckt name str_ptr = skip_non_ws(str_ptr); // skip over subckt name
@ -1774,9 +1795,9 @@ static void inp_fix_macro_param_func_paren_io(struct card *card)
} }
str_ptr++; str_ptr++;
} }
card->line = inp_remove_ws(
card->line); /* remove the extra white spaces just /* Remove the extra white spaces just introduced */
introduced */ card->line = inp_remove_ws(card->line);
} }
} }
@ -1915,66 +1936,69 @@ static int is_a_modelname(const char *s)
/* not beeing a valid number */ /* not beeing a valid number */
testval = strtod(s, &st); testval = strtod(s, &st);
/* conversion failed, so no number */ /* conversion failed, so no number */
if (eq(s, st)) if (eq(s, st)) {
return TRUE; return TRUE;
}
/* test if we have a true number */ /* test if we have a true number */
else if (*st == '\0' || isspace(*st)) if (*st == '\0' || isspace(*st)) {
return FALSE; return FALSE;
else { }
/* look for the scale factor (alphabetic) and skip it.
* INPevaluate will not do it because is does not swallow
* the scale factor from the string.
*/
switch (*st) {
case 't':
case 'T':
case 'g':
case 'G':
case 'k':
case 'K':
case 'u':
case 'U':
case 'n':
case 'N':
case 'p':
case 'P':
case 'f':
case 'F':
st = st + 1;
break;
case 'm':
case 'M':
if (((st[1] == 'E') || (st[1] == 'e')) &&
((st[2] == 'G') || (st[2] == 'g'))) {
st = st + 3; /* Meg */
}
else if (((st[1] == 'I') || (st[1] == 'i')) &&
((st[2] == 'L') || (st[2] == 'l'))) {
st = st + 3; /* Mil */
}
else {
st = st + 1; /* m, milli */
}
break;
default:
break;
}
/* test if we have a true scale factor */
if (*st == '\0' || isspace(*st))
return FALSE;
/* test if people use Ohms, F, H for RLC, like pF or uOhms */ /* look for the scale factor (alphabetic) and skip it.
if (ciprefix("ohms", st)) * INPevaluate will not do it because is does not swallow
st = st + 4; * the scale factor from the string.
else if (ciprefix("farad", st)) */
st = st + 5; switch (*st) {
else if (ciprefix("henry", st)) case 't':
st = st + 5; case 'T':
else if ((*st == 'f') || (*st == 'h')) case 'g':
case 'G':
case 'k':
case 'K':
case 'u':
case 'U':
case 'n':
case 'N':
case 'p':
case 'P':
case 'f':
case 'F':
st = st + 1; st = st + 1;
break;
case 'm':
case 'M':
if (((st[1] == 'E') || (st[1] == 'e')) &&
((st[2] == 'G') || (st[2] == 'g'))) {
st = st + 3; /* Meg */
}
else if (((st[1] == 'I') || (st[1] == 'i')) &&
((st[2] == 'L') || (st[2] == 'l'))) {
st = st + 3; /* Mil */
}
else {
st = st + 1; /* m, milli */
}
break;
default:
break;
}
/* test if we have a true scale factor */
if (*st == '\0' || isspace(*st))
return FALSE;
if (*st == '\0' || isspace(*st)) /* test if people use Ohms, F, H for RLC, like pF or uOhms */
return FALSE; if (ciprefix("ohms", st))
st = st + 4;
else if (ciprefix("farad", st))
st = st + 5;
else if (ciprefix("henry", st))
st = st + 5;
else if ((*st == 'f') || (*st == 'h'))
st = st + 1;
if (*st == '\0' || isspace(*st)) {
return FALSE;
} }
/* token starts with non alphanum character */ /* token starts with non alphanum character */
@ -2213,7 +2237,7 @@ static void comment_out_unused_subckt_models(struct card *start_card)
} }
if (remove_subckt) if (remove_subckt)
*line = '*'; *line = '*'; /* make line a comment */
#if 0 #if 0
else if (has_models && else if (has_models &&
(ciprefix(".model", line) || ciprefix(".cmodel", line))) { (ciprefix(".model", line) || ciprefix(".cmodel", line))) {
@ -2306,7 +2330,7 @@ static char *inp_spawn_brace(char *s)
/*-------------------------------------------------------------------------* /*-------------------------------------------------------------------------*
removes " " quotes, returns lower case letters, removes " " quotes, returns lower case letters,
replaces non-printable characterss with '_', however if replaces non-printable characters with '_', however if
non-printable character is the only character in a line, non-printable character is the only character in a line,
replace it by '*' replace it by '*'
*-------------------------------------------------------------------------*/ *-------------------------------------------------------------------------*/
@ -2378,8 +2402,7 @@ static void inp_stripcomments_deck(struct card *c, bool cf)
* Comments on a continuation line (i.e. line begining with '+') are allowed * Comments on a continuation line (i.e. line begining with '+') are allowed
* and are removed before lines are stitched. * and are removed before lines are stitched.
* Lines that contain only an end-of-line comment with or without leading * Lines that contain only an end-of-line comment with or without leading
white * white space are also allowed.
* space are also allowed.
If there is only white space before the end-of-line comment the If there is only white space before the end-of-line comment the
the whole line is converted to a normal comment line (i.e. one that the whole line is converted to a normal comment line (i.e. one that
@ -4759,11 +4782,11 @@ static void inp_compat(struct card *card)
} }
// Exxx n1 n2 int1 0 1 // Exxx n1 n2 int1 0 1
ckt_array[0] = tprintf("%s %s %s %s_int1 0 1", title_tok, ckt_array[0] = tprintf("%s %s %s %s_int1 0 1",
node1, node2, title_tok); title_tok, node1, node2, title_tok);
// BExxx int1 0 V = {equation} // BExxx int1 0 V = {equation}
ckt_array[1] = tprintf("b%s %s_int1 0 v = %s", title_tok, ckt_array[1] = tprintf("b%s %s_int1 0 v = %s",
title_tok, str_ptr); title_tok, title_tok, str_ptr);
// comment out current variable e line // comment out current variable e line
*(card->line) = '*'; *(card->line) = '*';
@ -4820,8 +4843,8 @@ static void inp_compat(struct card *card)
} }
else else
m_token = copy("1"); m_token = copy("1");
ckt_array[0] = tprintf("%s %s %s %s_int1 0 %s", title_tok, ckt_array[0] = tprintf("%s %s %s %s_int1 0 %s",
node1, node2, title_tok, m_token); title_tok, node1, node2, title_tok, m_token);
// skip "table" // skip "table"
cut_line = skip_ws(cut_line); cut_line = skip_ws(cut_line);
if (!ciprefix("table", cut_line)) { if (!ciprefix("table", cut_line)) {
@ -4834,9 +4857,8 @@ static void inp_compat(struct card *card)
if (*cut_line == '=') if (*cut_line == '=')
*cut_line++ = ' '; *cut_line++ = ' ';
// get the expression // get the expression
str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE); str_ptr = gettok_char(&cut_line, '{', FALSE, FALSE);
expression = gettok_char( expression = gettok_char(&cut_line, '}', TRUE, TRUE);
&cut_line, '}', TRUE, TRUE); /* expression */
if (!expression || !str_ptr) { if (!expression || !str_ptr) {
fprintf(stderr, "Error: bad syntax in line %d\n %s\n", fprintf(stderr, "Error: bad syntax in line %d\n %s\n",
card->linenum_orig, card->line); card->linenum_orig, card->line);
@ -4936,11 +4958,11 @@ static void inp_compat(struct card *card)
// Gxxx n1 n2 int1 0 1 // Gxxx n1 n2 int1 0 1
// or // or
// Gxxx n1 n2 int1 0 m='expr' // Gxxx n1 n2 int1 0 m='expr'
ckt_array[0] = tprintf("%s %s %s %s_int1 0 %s", title_tok, ckt_array[0] = tprintf("%s %s %s %s_int1 0 %s",
node1, node2, title_tok, m_token); title_tok, node1, node2, title_tok, m_token);
// BGxxx int1 0 V = {equation} // BGxxx int1 0 V = {equation}
ckt_array[1] = tprintf("b%s %s_int1 0 v = %s", title_tok, ckt_array[1] = tprintf("b%s %s_int1 0 v = %s",
title_tok, str_ptr); title_tok, title_tok, str_ptr);
// comment out current variable g line // comment out current variable g line
*(card->line) = '*'; *(card->line) = '*';
@ -4980,14 +5002,14 @@ static void inp_compat(struct card *card)
vbFxxx int1 0 0 vbFxxx int1 0 0
*/ */
// Fxxx n1 n2 VBFxxx -1 // Fxxx n1 n2 VBFxxx -1
ckt_array[0] = tprintf("%s %s %s vb%s -1", title_tok, node1, ckt_array[0] = tprintf("%s %s %s vb%s -1",
node2, title_tok); title_tok, node1, node2, title_tok);
// BFxxx BFxxx_int1 0 I = I(vnam)*{equation} // BFxxx BFxxx_int1 0 I = I(vnam)*{equation}
ckt_array[1] = tprintf("b%s %s_int1 0 i = i(%s) * (%s)", ckt_array[1] = tprintf("b%s %s_int1 0 i = i(%s) * (%s)",
title_tok, title_tok, vnamstr, equastr); title_tok, title_tok, vnamstr, equastr);
// VBFxxx int1 0 0 // VBFxxx int1 0 0
ckt_array[2] = ckt_array[2] = tprintf("vb%s %s_int1 0 dc 0",
tprintf("vb%s %s_int1 0 dc 0", title_tok, title_tok); title_tok, title_tok);
// comment out current variable f line // comment out current variable f line
*(card->line) = '*'; *(card->line) = '*';
// insert new three lines immediately after current line // insert new three lines immediately after current line
@ -5026,8 +5048,8 @@ static void inp_compat(struct card *card)
vbHxxx int1 0 0 vbHxxx int1 0 0
*/ */
// Hxxx n1 n2 VBHxxx -1 // Hxxx n1 n2 VBHxxx -1
ckt_array[0] = tprintf("%s %s %s vb%s -1", title_tok, node1, ckt_array[0] = tprintf("%s %s %s vb%s -1",
node2, title_tok); title_tok, node1, node2, title_tok);
// BHxxx BHxxx_int1 0 I = I(vnam)*{equation} // BHxxx BHxxx_int1 0 I = I(vnam)*{equation}
ckt_array[1] = tprintf("b%s %s_int1 0 i = i(%s) * (%s)", ckt_array[1] = tprintf("b%s %s_int1 0 i = i(%s) * (%s)",
title_tok, title_tok, vnamstr, equastr); title_tok, title_tok, vnamstr, equastr);
@ -5323,8 +5345,8 @@ static void inp_compat(struct card *card)
} }
} }
// Fxxx n-aux 0 Bxxx 1 // Fxxx n-aux 0 Bxxx 1
ckt_array[0] = tprintf( ckt_array[0] = tprintf("f%s %s_int2 0 b%s -1",
"f%s %s_int2 0 b%s -1", title_tok, title_tok, title_tok); title_tok, title_tok, title_tok);
// Lxxx n-aux 0 1 // Lxxx n-aux 0 1
ckt_array[1] = tprintf("l%s %s_int2 0 1", title_tok, title_tok); ckt_array[1] = tprintf("l%s %s_int2 0 1", title_tok, title_tok);
// Bxxx n1 n2 V = v(n-aux) * equation // Bxxx n1 n2 V = v(n-aux) * equation
@ -5378,13 +5400,13 @@ static void inp_compat(struct card *card)
* + <TD=td> <FROM=val> <TO=val> * + <TD=td> <FROM=val> <TO=val>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST> * + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
* *
* .MEASURE {DC|AC|TRAN} result FIND out_variable WHEN * .MEASURE {DC|AC|TRAN} result FIND out_variable
out_variable2=val * + WHEN out_variable2=val
* + <TD=td> <FROM=val> <TO=val> * + <TD=td> <FROM=val> <TO=val>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST> * + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
* *
* .MEASURE {DC|AC|TRAN} result FIND out_variable WHEN * .MEASURE {DC|AC|TRAN} result FIND out_variable
out_variable2=out_variable3 * + WHEN out_variable2=out_variable3
* + <TD=td> * + <TD=td>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST> * + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
* *
@ -5392,7 +5414,7 @@ static void inp_compat(struct card *card)
* + <FROM=val> <TO=val> * + <FROM=val> <TO=val>
* *
* .MEASURE {DC|AC|TRAN} result {AVG|MIN|MAX|MIN_AT|MAX_AT|PP|RMS} * .MEASURE {DC|AC|TRAN} result {AVG|MIN|MAX|MIN_AT|MAX_AT|PP|RMS}
out_variable * + out_variable
* + <TD=td> <FROM=val> <TO=val> * + <TD=td> <FROM=val> <TO=val>
* *
* .MEASURE {DC|AC|TRAN} result INTEG<RAL> out_variable * .MEASURE {DC|AC|TRAN} result INTEG<RAL> out_variable
@ -5400,22 +5422,20 @@ static void inp_compat(struct card *card)
* *
* .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable AT=val * .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable AT=val
* *
* .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable WHEN * .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable
out_variable2=val * + WHEN out_variable2=val
* + <TD=td> * + <TD=td>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST> * + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
* *
* .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable WHEN * .MEASURE {DC|AC|TRAN} result DERIV<ATIVE> out_variable
out_variable2=out_variable3 * + WHEN out_variable2=out_variable3
* + <TD=td> * + <TD=td>
* + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST> * + <CROSS=# | CROSS=LAST> <RISE=#|RISE=LAST> <FALL=#|FALL=LAST>
The user may set any out_variable to par(' expr '). The user may set any out_variable to par(' expr ').
We have to replace this by v(pa_xx) and generate a B source line. We have to replace this by v(pa_xx) and generate a B source line.
* * ------------------------------------------------------------ */
-----------------------------------------------------------------
*/
if (ciprefix(".meas", curr_line)) { if (ciprefix(".meas", curr_line)) {
if (strstr(curr_line, "par(") == NULL) if (strstr(curr_line, "par(") == NULL)
continue; continue;
@ -5436,15 +5456,16 @@ static void inp_compat(struct card *card)
// find expression // find expression
beg_ptr = end_ptr = str_ptr + 5; beg_ptr = end_ptr = str_ptr + 5;
while ((*end_ptr != ' ') && (*end_ptr != '=') && while ((*end_ptr != ' ') && (*end_ptr != '=') &&
(*end_ptr != '\0')) (*end_ptr != '\0')) {
end_ptr++; end_ptr++;
}
exp_ptr = copy_substring(beg_ptr, end_ptr - 2); exp_ptr = copy_substring(beg_ptr, end_ptr - 2);
cut_line = str_ptr; cut_line = str_ptr;
// generate node // generate node
out_ptr = tprintf("pa_%02d", (int) pai); out_ptr = tprintf("pa_%02d", (int) pai);
// Bout_ptr out_ptr 0 V = v(expr_ptr) // Bout_ptr out_ptr 0 V = v(expr_ptr)
ckt_array[pai] = tprintf( ckt_array[pai] = tprintf("b%s %s 0 v = %s",
"b%s %s 0 v = %s", out_ptr, out_ptr, exp_ptr); out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL; ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr) // length of the replacement V(out_ptr)
del_ptr = copy_ptr = tprintf("v(%s)", out_ptr); del_ptr = copy_ptr = tprintf("v(%s)", out_ptr);
@ -5472,8 +5493,8 @@ static void inp_compat(struct card *card)
// generate node // generate node
out_ptr = tprintf("pa_%02d", (int) pai); out_ptr = tprintf("pa_%02d", (int) pai);
// Bout_ptr out_ptr 0 V = v(expr_ptr) // Bout_ptr out_ptr 0 V = v(expr_ptr)
ckt_array[pai] = tprintf( ckt_array[pai] = tprintf("b%s %s 0 v = %s",
"b%s %s 0 v = %s", out_ptr, out_ptr, exp_ptr); out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL; ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr) // length of the replacement V(out_ptr)
del_ptr = copy_ptr = tprintf("v(%s)", out_ptr); del_ptr = copy_ptr = tprintf("v(%s)", out_ptr);
@ -5539,8 +5560,8 @@ static void inp_compat(struct card *card)
// generate node // generate node
out_ptr = tprintf("pa_%02d", (int) pai); out_ptr = tprintf("pa_%02d", (int) pai);
// Bout_ptr out_ptr 0 V = v(expr_ptr) // Bout_ptr out_ptr 0 V = v(expr_ptr)
ckt_array[pai] = tprintf( ckt_array[pai] = tprintf("b%s %s 0 v = %s",
"b%s %s 0 v = %s", out_ptr, out_ptr, exp_ptr); out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL; ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr) // length of the replacement V(out_ptr)
del_ptr = copy_ptr = tprintf("%s", out_ptr); del_ptr = copy_ptr = tprintf("%s", out_ptr);
@ -5558,7 +5579,7 @@ static void inp_compat(struct card *card)
tfree(out_ptr); tfree(out_ptr);
} }
// or we have '={par({ ... })}' // or we have '={par({ ... })}'
else if (ciprefix("={par({", (str_ptr - 2))) { else if (ciprefix("={par({", str_ptr - 2)) {
// find myoutput // find myoutput
beg_ptr = end_ptr = str_ptr - 2; beg_ptr = end_ptr = str_ptr - 2;
@ -5572,8 +5593,8 @@ static void inp_compat(struct card *card)
end_ptr++; end_ptr++;
exp_ptr = copy_substring(beg_ptr, end_ptr - 3); exp_ptr = copy_substring(beg_ptr, end_ptr - 3);
// Bout_ptr out_ptr 0 V = v(expr_ptr) // Bout_ptr out_ptr 0 V = v(expr_ptr)
ckt_array[pai] = tprintf( ckt_array[pai] = tprintf("b%s %s 0 v = %s",
"b%s %s 0 v = %s", out_ptr, out_ptr, exp_ptr); out_ptr, out_ptr, exp_ptr);
ckt_array[++pai] = NULL; ckt_array[++pai] = NULL;
// length of the replacement V(out_ptr) // length of the replacement V(out_ptr)
del_ptr = copy_ptr = tprintf("%s", out_ptr); del_ptr = copy_ptr = tprintf("%s", out_ptr);
@ -5807,15 +5828,17 @@ static bool inp_temper_compat(struct card *card)
* and other keywords like TEMPER. --> Only parameter replacement in numparam * and other keywords like TEMPER. --> Only parameter replacement in numparam
*/ */
static char *inp_modify_exp(char *expr) static char *inp_modify_exp(/* NOT CONST */ char *expr)
{ {
char *s; char *s;
wordlist *wl = NULL, *wlist = NULL; wordlist *wl = NULL, *wlist = NULL;
/* scan the expression and remove all '{' and '}' */ /* Scan the expression and replace all '{' and '}' with ' ' */
for (s = expr; *s; s++) for (s = expr; *s; s++) {
if ((*s == '{') || (*s == '}')) if ((*s == '{') || (*s == '}')) {
*s = ' '; *s = ' ';
}
}
/* scan the expression */ /* scan the expression */
s = expr; s = expr;
@ -5860,8 +5883,9 @@ static char *inp_modify_exp(char *expr)
else if ((c == '>') || (c == '<') || (c == '!') || (c == '=')) { else if ((c == '>') || (c == '<') || (c == '!') || (c == '=')) {
/* >=, <=, !=, ==, <>, ... */ /* >=, <=, !=, ==, <>, ... */
char *beg = s++; char *beg = s++;
if ((*s == '=') || (*s == '<') || (*s == '>')) if ((*s == '=') || (*s == '<') || (*s == '>')) {
s++; s++;
}
wl->wl_word = copy_substring(beg, s); wl->wl_word = copy_substring(beg, s);
} }
else if ((c == '|') || (c == '&')) { else if ((c == '|') || (c == '&')) {
@ -5876,8 +5900,9 @@ static char *inp_modify_exp(char *expr)
int i = 0; int i = 0;
if (((c == 'v') || (c == 'i')) && (s[1] == '(')) { if (((c == 'v') || (c == 'i')) && (s[1] == '(')) {
while (*s != ')') while (*s != ')') {
buf[i++] = *s++; buf[i++] = *s++;
}
buf[i++] = *s++; buf[i++] = *s++;
buf[i] = '\0'; buf[i] = '\0';
wl->wl_word = copy(buf); wl->wl_word = copy(buf);
@ -5927,8 +5952,9 @@ static char *inp_modify_exp(char *expr)
double dvalue = INPevaluate(&s, &error1, 0); double dvalue = INPevaluate(&s, &error1, 0);
wl->wl_word = tprintf("%18.10e", dvalue); wl->wl_word = tprintf("%18.10e", dvalue);
/* skip the `unit', FIXME INPevaluate() should do this */ /* skip the `unit', FIXME INPevaluate() should do this */
while (isalpha_c(*s)) while (isalpha_c(*s)) {
s++; s++;
}
} }
else { /* strange char */ else { /* strange char */
printf("Preparing expression for numparam\nWhat is this?\n%s\n", printf("Preparing expression for numparam\nWhat is this?\n%s\n",
@ -6257,9 +6283,11 @@ static void inp_fix_temper_in_param(struct card *deck)
sub_count[j] = 0; sub_count[j] = 0;
/* first pass: determine all .param with temper inside and replace by /* first pass: determine all .param with temper inside and replace by
.func .param xxx1 = 'temper + 25' will become .func xxx1() 'temper + * .func
25' * .param xxx1 = 'temper + 25'
*/ * will become
* .func xxx1() 'temper + 25'
*/
card = deck; card = deck;
for (; card; card = card->nextcard) { for (; card; card = card->nextcard) {
@ -6858,7 +6886,8 @@ static void inp_vdmos_model(struct card *deck)
/* storage for devices which get voltage source added */ /* storage for devices which get voltage source added */
struct replace_currm { struct replace_currm
{
struct card *s_start; struct card *s_start;
struct card *cline; struct card *cline;
char *rtoken; char *rtoken;
@ -6989,8 +7018,9 @@ static void inp_meas_current(struct card *deck)
} }
/* return if we did not find any i( */ /* return if we did not find any i( */
if (rep == NULL) if (rep == NULL) {
return; return;
}
/* scan through all the devices, search for xyz, modify node 1 by adding /* scan through all the devices, search for xyz, modify node 1 by adding
_vmeas, add a line with zero voltage v_xyz, having original node 1 and _vmeas, add a line with zero voltage v_xyz, having original node 1 and
@ -7069,8 +7099,8 @@ static void inp_meas_current(struct card *deck)
/* Add _vmeas only once to first device node. /* Add _vmeas only once to first device node.
Continue if we already have modified device "tok" */ Continue if we already have modified device "tok" */
if (!strstr(node1, "_vmeas")) { if (!strstr(node1, "_vmeas")) {
new_line = tprintf( new_line = tprintf("%s %s_vmeas_%d %s",
"%s %s_vmeas_%d %s", tok, node1, sn, curr_line); tok, node1, sn, curr_line);
tfree(card->line); tfree(card->line);
card->line = new_line; card->line = new_line;
} }
@ -7079,8 +7109,8 @@ static void inp_meas_current(struct card *deck)
/* We have already added a line v_xyz to the deck */ /* We have already added a line v_xyz to the deck */
if (!ciprefix(new_tok, card->nextcard->line)) { if (!ciprefix(new_tok, card->nextcard->line)) {
/* add new line */ /* add new line */
new_line = tprintf( new_line = tprintf("%s %s %s_vmeas_%d 0",
"%s %s %s_vmeas_%d 0", new_tok, node1, node1, sn); new_tok, node1, node1, sn);
/* insert new_line after card->line */ /* insert new_line after card->line */
insert_new_line(card, new_line, card->linenum + 1, 0); insert_new_line(card, new_line, card->linenum + 1, 0);
} }
@ -7102,12 +7132,13 @@ static void inp_meas_current(struct card *deck)
} }
/* replace the E source TABLE function by a B source pwl /* replace the E source TABLE function by a B source pwl
(used by ST OpAmps and comparators). * (used by ST OpAmps and comparators).
E_RO_3 VB_3 VB_4 VALUE={ TABLE( V(VCCP,VCCN), 2 , 35 , 3.3 , 15 , 5 , 10 * E_RO_3 VB_3 VB_4 VALUE={ TABLE( V(VCCP,VCCN), 2 , 35 , 3.3 , 15 , 5 , 10
)*I(VreadIo)} will become BE_RO_3_1 TABLE_NEW_1 0 v = pwl( V(VCCP,VCCN), 2 * )*I(VreadIo)}
, 35 , 3.3 , 15 , 5 , 10 ) E_RO_3 VB_3 VB_4 VALUE={ * will become
V(TABLE_NEW_1)*I(VreadIo)} * BE_RO_3_1 TABLE_NEW_1 0 v = pwl( V(VCCP,VCCN), 2 , 35 , 3.3 , 15 , 5 , 10
*/ * ) E_RO_3 VB_3 VB_4 VALUE={ V(TABLE_NEW_1)*I(VreadIo)}
*/
static void replace_table(struct card *startcard) static void replace_table(struct card *startcard)
{ {
struct card *card; struct card *card;
@ -7124,8 +7155,8 @@ static void replace_table(struct card *startcard)
/* get the table function */ /* get the table function */
char *tabfun = gettok_char(&ftablebeg, ')', TRUE, TRUE); char *tabfun = gettok_char(&ftablebeg, ')', TRUE, TRUE);
/* the new e line */ /* the new e line */
char *neweline = tprintf( char *neweline = tprintf("%s v(table_new_%d)%s",
"%s v(table_new_%d)%s", begline, numb, ftablebeg); begline, numb, ftablebeg);
char *newbline = char *newbline =
tprintf("btable_new_%d table_new_%d 0 v=pwl%s", tprintf("btable_new_%d table_new_%d 0 v=pwl%s",
numb, numb, tabfun + 5); numb, numb, tabfun + 5);
@ -7182,8 +7213,8 @@ static struct card *find_model(struct card *startcard,
controlled_exit(1); controlled_exit(1);
} }
/* we have got it */ /* we have got it */
char *newmodcard = tprintf(".model %s %s %s%s", newmname, char *newmodcard = tprintf(".model %s %s %s%s",
newmtype, origmodline, endstr); newmname, newmtype, origmodline, endstr);
char *tmpstr = strstr(newmodcard, ")("); char *tmpstr = strstr(newmodcard, ")(");
if (tmpstr) { if (tmpstr) {
tmpstr[0] = ' '; tmpstr[0] = ' ';
@ -7206,7 +7237,7 @@ static struct card *find_model(struct card *startcard,
} }
/* do the .model replacement required by ako (a kind of) /* do the .model replacement required by ako (a kind of)
* PSPICE does not support ested .subckt definitions, so * PSPICE does not support nested .subckt definitions, so
* a simple structure is needed: search for ako:modelname, * a simple structure is needed: search for ako:modelname,
* then for modelname in the subcircuit or in the top level. * then for modelname in the subcircuit or in the top level.
* .model qorig npn (BF=48 IS=2e-7) * .model qorig npn (BF=48 IS=2e-7)
@ -7360,8 +7391,8 @@ static bool del_models(struct vsmodels *vsmodel)
* add .functions limit, pwr, pwrs, stp, if, int * add .functions limit, pwr, pwrs, stp, if, int
* replace * replace
S1 D S DG GND SWN S1 D S DG GND SWN
.MODEL SWN VSWITCH(VON = { 0.55 } VOFF = { 0.49 } RON = { 1 / (2 * M*(W / .MODEL SWN VSWITCH(VON = { 0.55 } VOFF = { 0.49 }
LE)*(KPN / 2) * 10) } ROFF = { 1G }) RON = { 1 / (2 * M*(W / LE)*(KPN / 2) * 10) } ROFF = { 1G })
* by * by
as1 %vd(DG GND) % gd(D S) aswn as1 %vd(DG GND) % gd(D S) aswn
.model aswn aswitch(cntl_off={0.49} cntl_on={0.55} r_off={1G} .model aswn aswitch(cntl_off={0.49} cntl_on={0.55} r_off={1G}
@ -7468,8 +7499,8 @@ static struct card *pspice_compat(struct card *oldcard)
tctok[-1] = '\0'; tctok[-1] = '\0';
char *newstring; char *newstring;
if (tc1 && tc2) if (tc1 && tc2)
newstring = newstring = tprintf("%s tc1=%s tc2=%s",
tprintf("%s tc1=%s tc2=%s", cut_line, tc1, tc2); cut_line, tc1, tc2);
else if (tc1) else if (tc1)
newstring = tprintf("%s tc1=%s", cut_line, tc1); newstring = tprintf("%s tc1=%s", cut_line, tc1);
else { else {
@ -7616,8 +7647,9 @@ static struct card *pspice_compat(struct card *oldcard)
while (*cut_line && !isspace(*cut_line)) while (*cut_line && !isspace(*cut_line))
if (!isdigit(*cut_line++)) if (!isdigit(*cut_line++))
is_node4 = FALSE; // already model name is_node4 = FALSE; // already model name
if (is_node4) if (is_node4) {
cut_line = nexttok(cut_line); // model name cut_line = nexttok(cut_line); // model name
}
} }
if (cut_line && *cut_line && if (cut_line && *cut_line &&
atof(cut_line) > 0.0) { // size of area is a real number atof(cut_line) > 0.0) { // size of area is a real number
@ -7667,12 +7699,12 @@ static struct card *pspice_compat(struct card *oldcard)
/* replace /* replace
* S1 D S DG GND SWN * S1 D S DG GND SWN
* .MODEL SWN VSWITCH ( VON = {0.55} VOFF = {0.49} * .MODEL SWN VSWITCH ( VON = {0.55} VOFF = {0.49}
RON={1/(2*M*(W/LE)*(KPN/2)*10)} ROFF={1G} ) * RON={1/(2*M*(W/LE)*(KPN/2)*10)} ROFF={1G} )
* by * by
* a1 %v(DG) %gd(D S) swa * a1 %v(DG) %gd(D S) swa
* .MODEL SWA aswitch(cntl_off=0.49 cntl_on=0.55 r_off=1G * .MODEL SWA aswitch(cntl_off=0.49 cntl_on=0.55 r_off=1G
r_on={1/(2*M*(W/LE)*(KPN/2)*10)} log=TRUE) * r_on={1/(2*M*(W/LE)*(KPN/2)*10)} log=TRUE)
*
* simple hierachy, as nested subcircuits are not allowed in PSPICE */ * simple hierachy, as nested subcircuits are not allowed in PSPICE */
/* first scan: find the vswitch models, transform them and put them into a /* first scan: find the vswitch models, transform them and put them into a
@ -7827,9 +7859,11 @@ static void pspice_compat_a(struct card *oldcard)
* Replace * Replace
* D1 A K SDMOD * D1 A K SDMOD
* .MODEL SDMOD D (Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10 Revepsilon=0.2 * .MODEL SDMOD D (Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10 Revepsilon=0.2
* Epsilon=0.2 Ilimit=7 Revilimit=7) by ad1 a k asdmod .model asdmod * Epsilon=0.2 Ilimit=7 Revilimit=7)
* sidiode(Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10 Revepsilon=0.2 * by
* Epsilon=0.2 Ilimit=7 Revilimit=7) * ad1 a k asdmod
* .model asdmod sidiode(Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10
* Revepsilon=0.2 Epsilon=0.2 Ilimit=7 Revilimit=7)
*/ */
struct card *ltspice_compat(struct card *oldcard) struct card *ltspice_compat(struct card *oldcard)
{ {
@ -7856,13 +7890,13 @@ struct card *ltspice_compat(struct card *oldcard)
/* replace /* replace
* D1 A K SDMOD * D1 A K SDMOD
* .MODEL SDMOD D (Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10 * .MODEL SDMOD D (Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10
Revepsilon=0.2 Epsilon=0.2 Ilimit=7 Revilimit=7) * Revepsilon=0.2 Epsilon=0.2 Ilimit=7 Revilimit=7)
* by * by
* a1 a k SDMOD * a1 a k SDMOD
* .model SDMOD sidiode(Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10 * .model SDMOD sidiode(Roff=1000 Ron=0.7 Rrev=0.2 Vfwd=1 Vrev=10
Revepsilon=0.2 Epsilon=0.2 Ilimit=7 Revilimit=7) * Revepsilon=0.2 Epsilon=0.2 Ilimit=7 Revilimit=7)
* Do this if one of the parameters, which are uncommon to standard diode * Do this if one of the parameters, which are uncommon to standard diode
model, has been found. * model, has been found.
* simple hierachy, as nested subcircuits are not allowed in PSPICE */ * simple hierachy, as nested subcircuits are not allowed in PSPICE */
@ -7961,14 +7995,14 @@ struct card *ltspice_compat(struct card *oldcard)
if ((nesting > 0) && if ((nesting > 0) &&
find_a_model(modelsfound, stoks[3], subcktline->line)) { find_a_model(modelsfound, stoks[3], subcktline->line)) {
tfree(card->line); tfree(card->line);
card->line = tprintf("a%s %s %s a%s", stoks[0], stoks[1], card->line = tprintf("a%s %s %s a%s",
stoks[2], stoks[3]); stoks[0], stoks[1], stoks[2], stoks[3]);
} }
/* if model is not within same subcircuit, search at top level */ /* if model is not within same subcircuit, search at top level */
else if (find_a_model(modelsfound, stoks[3], "top")) { else if (find_a_model(modelsfound, stoks[3], "top")) {
tfree(card->line); tfree(card->line);
card->line = tprintf("a%s %s %s a%s", stoks[0], stoks[1], card->line = tprintf("a%s %s %s a%s",
stoks[2], stoks[3]); stoks[0], stoks[1], stoks[2], stoks[3]);
} }
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
tfree(stoks[i]); tfree(stoks[i]);