bug_fix: R,L,C instantiations, tc1, tc2, numbers followed by `:'
Ternary function was not recognized in R, C, or L lines if no voltage or current node was part of the expression, because then B-Source is not used. In these cases now inp_fix_ternary_operator_str() is called explicitly. tc1, tc2 were sometimes recognized falsely, if part of a token e.g. tc1end. R, C, and L models are never commented out, because their names may be token no. 4 or 5 in an R, C, or L line, and will not be recognized if 5. INPevaluate() will now correctly evaluate a number if followed by ':' (number may be part of the ternary function).
This commit is contained in:
parent
232270cbc4
commit
8b780fa42b
|
|
@ -85,6 +85,7 @@ static void inp_bsource_compat(struct line *deck);
|
|||
static bool chk_for_line_continuation( char *line );
|
||||
static void comment_out_unused_subckt_models( struct line *start_card , int no_of_lines);
|
||||
static void inp_fix_macro_param_func_paren_io( struct line *begin_card );
|
||||
static char* inp_fix_ternary_operator_str( char *line, bool all);
|
||||
static void inp_fix_ternary_operator( struct line *start_card );
|
||||
static void inp_fix_gnd_name( struct line *deck );
|
||||
static void inp_chk_for_multi_in_vcvs( struct line *deck, int *line_number );
|
||||
|
|
@ -1319,6 +1320,20 @@ get_model_name( char *line, int num_terminals )
|
|||
return model_name;
|
||||
}
|
||||
|
||||
static char*
|
||||
get_model_type( char *line )
|
||||
{
|
||||
char *model_type, *beg_ptr = line;
|
||||
if ( !( ciprefix( ".model", line )))
|
||||
return NULL;
|
||||
while ( !isspace( *beg_ptr ) && *beg_ptr != '\0' ) beg_ptr++; /* eat .model */
|
||||
while ( isspace( *beg_ptr ) && *beg_ptr != '\0' ) beg_ptr++;
|
||||
while ( !isspace( *beg_ptr ) && *beg_ptr != '\0' ) beg_ptr++; /* eat model name */
|
||||
while ( isspace( *beg_ptr ) && *beg_ptr != '\0' ) beg_ptr++;
|
||||
model_type = gettok(&beg_ptr);
|
||||
return model_type;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_adevice_model_name( char *line )
|
||||
{
|
||||
|
|
@ -1564,10 +1579,19 @@ comment_out_unused_subckt_models( struct line *start_card , int no_of_lines)
|
|||
}
|
||||
if ( remove_subckt ) *line = '*';
|
||||
else if ( has_models && (ciprefix( ".model", line ) || ciprefix( ".cmodel", line )) ) {
|
||||
char *model_type = get_model_type( line );
|
||||
model_name = get_subckt_model_name( line );
|
||||
found_model = FALSE;
|
||||
for ( i = 0; i < num_used_model_names; i++ )
|
||||
if ( strcmp( used_model_names[i], model_name ) == 0 || model_bin_match( used_model_names[i], model_name ) ) found_model = TRUE;
|
||||
/* keep R, L, C models because in addition to no. of terminals the value may be given,
|
||||
as in RE1 1 2 800 newres dtemp=5, so model name may be token no. 4 or 5,
|
||||
and, if 5, will not be detected by get_subckt_model_name()*/
|
||||
if (cieq(model_type,"c") || cieq(model_type,"l") || cieq(model_type,"r"))
|
||||
found_model = TRUE;
|
||||
else {
|
||||
found_model = FALSE;
|
||||
for ( i = 0; i < num_used_model_names; i++ )
|
||||
if ( strcmp( used_model_names[i], model_name ) == 0 || model_bin_match( used_model_names[i], model_name ) ) found_model = TRUE;
|
||||
}
|
||||
if (model_type) tfree(model_type);
|
||||
#if ADMS >= 3
|
||||
/* ngspice strategy to detect unused models fails with dynamic models - reason: # of terms unknown during parsing */
|
||||
#else
|
||||
|
|
@ -1584,9 +1608,10 @@ comment_out_unused_subckt_models( struct line *start_card , int no_of_lines)
|
|||
|
||||
|
||||
|
||||
/* replace ternary operator ? : by fcn ternary_fcn() in .param, .func, and .meas lines */
|
||||
/* replace ternary operator ? : by fcn ternary_fcn() in .param, .func, and .meas lines,
|
||||
if all is FALSE, for all lines if all is TRUE */
|
||||
static char*
|
||||
inp_fix_ternary_operator_str( char *line )
|
||||
inp_fix_ternary_operator_str( char *line, bool all )
|
||||
{
|
||||
char *conditional, *if_str, *else_str, *question, *colon, keep, *str_ptr, *str_ptr2, *new_str;
|
||||
char *paren_ptr = NULL, *end_str = NULL, *beg_str = NULL;
|
||||
|
|
@ -1595,12 +1620,12 @@ inp_fix_ternary_operator_str( char *line )
|
|||
if ( !strstr( line, "?" ) && !strstr( line, ":" ) ) return line;
|
||||
|
||||
str_ptr = line;
|
||||
if ( ciprefix( ".param", line ) || ciprefix( ".func", line ) || ciprefix( ".meas", line ) ) {
|
||||
if ( all || ciprefix( ".param", line ) || ciprefix( ".func", line ) || ciprefix( ".meas", line ) ) {
|
||||
|
||||
str_ptr = line;
|
||||
if ( ciprefix( ".param", line ) || ciprefix( ".meas", line ) ) str_ptr = strstr( line, "=" );
|
||||
else str_ptr = strstr( line, ")" );
|
||||
if (str_ptr == NULL) {
|
||||
if ((str_ptr == NULL) && all==FALSE) {
|
||||
fprintf(stderr,"ERROR: mal formed .param, .func or .meas line: %s\n", line);
|
||||
controlled_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -1679,7 +1704,7 @@ inp_fix_ternary_operator_str( char *line )
|
|||
str_ptr2++;
|
||||
keep = *str_ptr2;
|
||||
*str_ptr2 = '\0';
|
||||
if_str = inp_fix_ternary_operator_str(strdup(str_ptr));
|
||||
if_str = inp_fix_ternary_operator_str(strdup(str_ptr), all);
|
||||
*str_ptr2 = keep;
|
||||
|
||||
// get else
|
||||
|
|
@ -1705,9 +1730,9 @@ inp_fix_ternary_operator_str( char *line )
|
|||
}
|
||||
keep = *str_ptr2;
|
||||
*str_ptr2 = '\0';
|
||||
else_str = inp_fix_ternary_operator_str(strdup(str_ptr));
|
||||
else_str = inp_fix_ternary_operator_str(strdup(str_ptr), all);
|
||||
if ( keep != '}' ) {
|
||||
end_str = inp_fix_ternary_operator_str(strdup(str_ptr2+1));
|
||||
end_str = inp_fix_ternary_operator_str(strdup(str_ptr2+1), all);
|
||||
} else {
|
||||
*str_ptr2 = keep;
|
||||
end_str = strdup(str_ptr2);
|
||||
|
|
@ -1716,11 +1741,11 @@ inp_fix_ternary_operator_str( char *line )
|
|||
} else {
|
||||
if ((str_ptr2 = strstr(str_ptr, "}")) != NULL) {
|
||||
*str_ptr2 = '\0';
|
||||
else_str = inp_fix_ternary_operator_str(strdup(str_ptr));
|
||||
else_str = inp_fix_ternary_operator_str(strdup(str_ptr), all);
|
||||
*str_ptr2 = '}';
|
||||
end_str = strdup(str_ptr2);
|
||||
} else {
|
||||
else_str = inp_fix_ternary_operator_str(strdup(str_ptr));
|
||||
else_str = inp_fix_ternary_operator_str(strdup(str_ptr), all);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1771,7 +1796,7 @@ inp_fix_ternary_operator( struct line *start_card )
|
|||
if ( *line == 'B' || *line == 'b' ) continue;
|
||||
if ( *line == '*' ) continue;
|
||||
if ( strstr( line, "?" ) && strstr( line, ":" ) ) {
|
||||
card->li_line = inp_fix_ternary_operator_str( line );
|
||||
card->li_line = inp_fix_ternary_operator_str( line, FALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4346,7 +4371,14 @@ static void inp_compat(struct line *deck)
|
|||
*/
|
||||
else if ( *curr_line == 'r' ) {
|
||||
if ((!strstr(curr_line, "v(")) && (!strstr(curr_line, "i(")))
|
||||
continue;
|
||||
/* no handling in B-Source, so we have to prepare ternary fcn
|
||||
for numparam */
|
||||
if ( strstr( curr_line, "?" ) && strstr( curr_line, ":" ) ) {
|
||||
card->li_line = inp_fix_ternary_operator_str( curr_line, TRUE );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
cut_line = curr_line;
|
||||
/* make BRxxx pos neg I = V(pos, neg)/{equation}*/
|
||||
title_tok = gettok(&cut_line);
|
||||
|
|
@ -4361,13 +4393,21 @@ static void inp_compat(struct line *deck)
|
|||
equation = gettok_char(&str_ptr, '}', TRUE);
|
||||
str_ptr = strstr(cut_line, "tc1");
|
||||
if (str_ptr) {
|
||||
tc1_ptr = strstr(str_ptr, "=");
|
||||
tc1 = atof(tc1_ptr+1);
|
||||
/* We need to have 'tc1=something */
|
||||
if (str_ptr[3] && (isspace(str_ptr[3]) || (str_ptr[3] == '='))) {
|
||||
tc1_ptr = strstr(str_ptr, "=");
|
||||
if (tc1_ptr)
|
||||
tc1 = atof(tc1_ptr+1);
|
||||
}
|
||||
}
|
||||
str_ptr = strstr(cut_line, "tc2");
|
||||
if (str_ptr) {
|
||||
tc2_ptr = strstr(str_ptr, "=");
|
||||
tc2 = atof(tc2_ptr+1);
|
||||
/* We need to have 'tc2=something */
|
||||
if (str_ptr[3] && (isspace(str_ptr[3]) || (str_ptr[3] == '='))) {
|
||||
tc2_ptr = strstr(str_ptr, "=");
|
||||
if (tc2_ptr)
|
||||
tc2 = atof(tc2_ptr+1);
|
||||
}
|
||||
}
|
||||
if ((tc1_ptr == NULL) && (tc2_ptr == NULL)) {
|
||||
xlen = strlen(title_tok) + strlen(node1) + strlen(node2) +
|
||||
|
|
@ -4416,7 +4456,14 @@ static void inp_compat(struct line *deck)
|
|||
*/
|
||||
else if ( *curr_line == 'c' ) {
|
||||
if ((!strstr(curr_line, "v(")) && (!strstr(curr_line, "i(")))
|
||||
continue;
|
||||
/* no handling in B-Source, so we have to prepare ternary fcn
|
||||
for numparam */
|
||||
if ( strstr( curr_line, "?" ) && strstr( curr_line, ":" ) ) {
|
||||
card->li_line = inp_fix_ternary_operator_str( curr_line, TRUE );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
cut_line = curr_line;
|
||||
/* title and nodes */
|
||||
title_tok = gettok(&cut_line);
|
||||
|
|
@ -4431,13 +4478,21 @@ static void inp_compat(struct line *deck)
|
|||
equation = gettok_char(&str_ptr, '}', TRUE);
|
||||
str_ptr = strstr(cut_line, "tc1");
|
||||
if (str_ptr) {
|
||||
tc1_ptr = strstr(str_ptr, "=");
|
||||
tc1 = atof(tc1_ptr+1);
|
||||
/* We need to have 'tc1=something */
|
||||
if (str_ptr[3] && (isspace(str_ptr[3]) || (str_ptr[3] == '='))) {
|
||||
tc1_ptr = strstr(str_ptr, "=");
|
||||
if (tc1_ptr)
|
||||
tc1 = atof(tc1_ptr+1);
|
||||
}
|
||||
}
|
||||
str_ptr = strstr(cut_line, "tc2");
|
||||
if (str_ptr) {
|
||||
tc2_ptr = strstr(str_ptr, "=");
|
||||
tc2 = atof(tc2_ptr+1);
|
||||
/* We need to have 'tc2=something */
|
||||
if (str_ptr[3] && (isspace(str_ptr[3]) || (str_ptr[3] == '='))) {
|
||||
tc2_ptr = strstr(str_ptr, "=");
|
||||
if (tc2_ptr)
|
||||
tc2 = atof(tc2_ptr+1);
|
||||
}
|
||||
}
|
||||
// Exxx n-aux 0 n1 n2 1
|
||||
xlen = 2*strlen(title_tok) + strlen(node1) + strlen(node2)
|
||||
|
|
@ -4507,7 +4562,14 @@ static void inp_compat(struct line *deck)
|
|||
*/
|
||||
else if ( *curr_line == 'l' ) {
|
||||
if ((!strstr(curr_line, "v(")) && (!strstr(curr_line, "i(")))
|
||||
continue;
|
||||
/* no handling in B-Source, so we have to prepare ternary fcn
|
||||
for numparam */
|
||||
if ( strstr( curr_line, "?" ) && strstr( curr_line, ":" ) ) {
|
||||
card->li_line = inp_fix_ternary_operator_str( curr_line, TRUE );
|
||||
continue;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
cut_line = curr_line;
|
||||
/* title and nodes */
|
||||
title_tok = gettok(&cut_line);
|
||||
|
|
@ -4522,13 +4584,21 @@ static void inp_compat(struct line *deck)
|
|||
equation = gettok_char(&str_ptr, '}', TRUE);
|
||||
str_ptr = strstr(cut_line, "tc1");
|
||||
if (str_ptr) {
|
||||
tc1_ptr = strstr(str_ptr, "=");
|
||||
tc1 = atof(tc1_ptr+1);
|
||||
/* We need to have 'tc1=something */
|
||||
if (str_ptr[3] && (isspace(str_ptr[3]) || (str_ptr[3] == '='))) {
|
||||
tc1_ptr = strstr(str_ptr, "=");
|
||||
if (tc1_ptr)
|
||||
tc1 = atof(tc1_ptr+1);
|
||||
}
|
||||
}
|
||||
str_ptr = strstr(cut_line, "tc2");
|
||||
if (str_ptr) {
|
||||
tc2_ptr = strstr(str_ptr, "=");
|
||||
tc2 = atof(tc2_ptr+1);
|
||||
/* We need to have 'tc2=something */
|
||||
if (str_ptr[3] && (isspace(str_ptr[3]) || (str_ptr[3] == '='))) {
|
||||
tc2_ptr = strstr(str_ptr, "=");
|
||||
if (tc2_ptr)
|
||||
tc2 = atof(tc2_ptr+1);
|
||||
}
|
||||
}
|
||||
// Fxxx n-aux 0 Bxxx 1
|
||||
xlen = 3*strlen(title_tok)
|
||||
|
|
|
|||
|
|
@ -77,10 +77,16 @@ double INPevaluate(char **line, int *error, int gobble)
|
|||
return ((double) mantis * sign);
|
||||
}
|
||||
if (*here == ':') {
|
||||
/* hack for subcircuit node numbering */
|
||||
*error = 1;
|
||||
*line = tmpline;
|
||||
return 0.0;
|
||||
/* ':' is no longer used for subcircuit node numbering
|
||||
but is part of ternary function a?b:c
|
||||
FIXME : subcircuit models still use ':' for model numbering
|
||||
Will this hurt somewhere? */
|
||||
if (gobble) {
|
||||
FREE(token);
|
||||
} else {
|
||||
*line = here;
|
||||
}
|
||||
return ((double) mantis * sign);
|
||||
}
|
||||
/* after decimal point! */
|
||||
if (*here == '.') {
|
||||
|
|
|
|||
Loading…
Reference in New Issue