@ -232,7 +232,6 @@ message(dico_t *dico, const char *fmt, ...)
dico - > oldline ) ;
dico - > oldline ) ;
}
}
}
}
va_start ( ap , fmt ) ;
va_start ( ap , fmt ) ;
vfprintf ( stderr , fmt , ap ) ;
vfprintf ( stderr , fmt , ap ) ;
va_end ( ap ) ;
va_end ( ap ) ;
@ -275,7 +274,6 @@ dico_free_entry(entry_t *entry)
{
{
if ( entry - > symbol )
if ( entry - > symbol )
txfree ( entry - > symbol ) ;
txfree ( entry - > symbol ) ;
txfree ( entry ) ;
txfree ( entry ) ;
}
}
@ -339,7 +337,7 @@ dicostack_pop(dico_t *dico)
fprintf ( stderr , " Error: DS could not add string %s \n " , inst_name ) ;
fprintf ( stderr , " Error: DS could not add string %s \n " , inst_name ) ;
controlled_exit ( - 1 ) ;
controlled_exit ( - 1 ) ;
}
}
nupa_add_inst_param ( ds_get_buf ( & param_name ) , entry - > vl ) ;
nupa_copy_inst_entry ( ds_get_buf ( & param_name ) , entry ) ;
dico_free_entry ( entry ) ;
dico_free_entry ( entry ) ;
}
}
nghash_free ( htable_p , NULL , NULL ) ;
nghash_free ( htable_p , NULL , NULL ) ;
@ -440,6 +438,8 @@ del_attrib(void *entry_p)
entry_t * entry = ( entry_t * ) entry_p ;
entry_t * entry = ( entry_t * ) entry_p ;
if ( entry ) {
if ( entry ) {
tfree ( entry - > symbol ) ;
tfree ( entry - > symbol ) ;
if ( entry - > sbbase )
tfree ( entry - > sbbase ) ;
tfree ( entry ) ;
tfree ( entry ) ;
}
}
}
}
@ -1085,6 +1085,79 @@ formula(dico_t *dico, const char *s, const char *s_end, bool *perror)
}
}
/* Check for a string expression, return end pointer or NULL.
* A string expression is a sequence of quoted strings and string
* variables , optionally enclosed by ' { } ' with no interventing space .
* If successful return pointer to next char , otherwise NULL .
* Evaluated string is returned in * qstr_p ( may be NULL ) .
*/
static char * string_expr ( dico_t * dico , DSTRINGPTR qstr_p ,
const char * t , const char * t_end )
{
const char * tie ;
bool ok = FALSE ;
while ( isblank ( * t ) & & t < t_end )
+ + t ;
if ( qstr_p )
ds_clear ( qstr_p ) ;
for ( ; t < t_end ; ) {
if ( * t = = ' " ' ) {
/* String constant. */
tie = + + t ;
while ( * t ! = ' " ' & & t < t_end )
+ + t ;
if ( qstr_p )
pscat ( qstr_p , tie , t ) ;
if ( * t = = ' " ' )
+ + t ;
ok = TRUE ;
continue ;
}
if ( * t = = ' { ' ) {
/* Isolate and check wrapped identifier. */
tie = + + t ;
while ( t < t_end ) {
if ( * t = = ' } ' )
break ;
+ + t ;
}
} else {
/* Last option: naked string-valued param. */
tie = t ;
t = fetchid ( t , t_end ) ;
if ( t = = tie )
return NULL ;
}
/* Now pointers tie, t should bracket an identifier. */
{
DS_CREATE ( lcl_str , 200 ) ;
entry_t * entry ;
/* Formula is a single identifier. */
pscopy ( & lcl_str , tie , t ) ;
entry = entrynb ( dico , ds_get_buf ( & lcl_str ) ) ;
ds_free ( & lcl_str ) ;
if ( entry & & ( entry - > tp = = NUPA_STRING ) ) {
if ( qstr_p )
pscat ( qstr_p , entry - > sbbase , NULL ) ;
ok = TRUE ;
} else {
return NULL ;
}
}
if ( * t = = ' } ' )
+ + t ;
}
return ok ? ( char * ) t : NULL ;
}
/* stupid, produce a string representation of a given double
/* stupid, produce a string representation of a given double
* to be spliced back into the circuit deck
* to be spliced back into the circuit deck
* we want * exactly * 25 chars , we have
* we want * exactly * 25 chars , we have
@ -1113,7 +1186,8 @@ evaluate_expr(dico_t *dico, DSTRINGPTR qstr_p, const char *t, const char * const
double u ;
double u ;
ds_clear ( qstr_p ) ;
ds_clear ( qstr_p ) ;
if ( string_expr ( dico , qstr_p , t , t_end ) )
return 0 ;
u = formula ( dico , t , t_end , & err ) ;
u = formula ( dico , t , t_end , & err ) ;
if ( err )
if ( err )
return err ;
return err ;
@ -1247,38 +1321,31 @@ getword(const char *s, DSTRINGPTR tstr_p)
static char *
static char *
getexpress ( nupa_type * type , DSTRINGPTR tstr_p , const char * s )
getexpress ( dico_t * dico , nupa_type * type , DSTRINGPTR tstr_p , const char * s )
/* returns expression-like string until next separator
/* returns expression-like string until next separator
Input i = position before expr , output i = just after expr , on separator .
Input i = position before expr , output i = just after expr , on separator .
returns tpe = = ' R ' if ( numeric , ' S ' if ( string only
returns tpe = = ' R ' if ( numeric , ' S ' if ( string only
*/
*/
{
{
const char * const s_end = s + strlen ( s ) ;
const char * s_end = s + strlen ( s ) ;
const char * p ;
const char * p ;
nupa_type tpe ;
nupa_type tpe ;
while ( ( s < s_end - 1 ) & & ( ( unsigned char ) ( * s ) < = ' ' ) )
while ( ( s < s_end - 1 ) & & ( ( unsigned char ) ( * s ) < = ' ' ) )
s + + ; /*white space ? */
s + + ; /*white space ? */
if ( * s = = ' " ' ) { /* string constant */
s + + ;
p = s ;
while ( ( p < s_end - 1 ) & & ( * p ! = ' " ' ) )
p + + ;
do
p + + ;
while ( ( p < s_end ) & & ( ( unsigned char ) ( * p ) < = ' ' ) ) ;
/* Check for injected semicolon separator in assignment list. */
p = strchr ( s , ' ; ' ) ;
if ( p )
s_end = p ;
p = string_expr ( dico , NULL , s , s_end ) ;
if ( p ) {
tpe = NUPA_STRING ;
tpe = NUPA_STRING ;
} else {
} else {
if ( * s = = ' { ' )
if ( * s = = ' { ' )
s + + ;
s + + ;
p = s ;
p = s ;
for ( ; p < s_end ; p + + ) {
for ( ; p < s_end ; p + + ) {
@ -1304,7 +1371,6 @@ getexpress(nupa_type *type, DSTRINGPTR tstr_p, const char *s)
}
}
}
}
}
}
tpe = NUPA_REAL ;
tpe = NUPA_REAL ;
}
}
@ -1313,9 +1379,6 @@ getexpress(nupa_type *type, DSTRINGPTR tstr_p, const char *s)
if ( * p = = ' } ' )
if ( * p = = ' } ' )
p + + ;
p + + ;
if ( tpe = = NUPA_STRING )
p + + ; /* beyond quote */
if ( type )
if ( type )
* type = tpe ;
* type = tpe ;
@ -1334,7 +1397,8 @@ nupa_assignment(dico_t *dico, const char *s, char mode)
/* s has the format: ident = expression; ident= expression ... */
/* s has the format: ident = expression; ident= expression ... */
const char * const s_end = s + strlen ( s ) ;
const char * const s_end = s + strlen ( s ) ;
const char * p = s ;
const char * p = s ;
const char * tmp ;
char * sval = NULL ;
bool error = 0 ;
bool error = 0 ;
nupa_type dtype ;
nupa_type dtype ;
int wval = 0 ;
int wval = 0 ;
@ -1369,23 +1433,26 @@ nupa_assignment(dico_t *dico, const char *s, char mode)
break ;
break ;
}
}
p = getexpress ( & dtype , & ustr , p + 1 ) + 1 ;
p = getexpress ( dico , & dtype , & ustr , p + 1 ) + 1 ;
tmp = ds_get_buf ( & ustr ) ;
if ( dtype = = NUPA_REAL ) {
if ( dtype = = NUPA_REAL ) {
const char * tmp = ds_get_buf ( & ustr ) ;
rval = formula ( dico , tmp , tmp + strlen ( tmp ) , & error ) ;
rval = formula ( dico , tmp , tmp + strlen ( tmp ) , & error ) ;
if ( error ) {
if ( error ) {
message ( dico ,
message ( dico ,
" Formula() error. \n "
" Formula() error. \n "
" %s \n " , s ) ;
" | %s| : |%s|=|%s| \n " , s , ds_get_buf ( & tstr ) , ds_get_buf ( & ustr ) ) ;
break ;
break ;
}
}
} else if ( dtype = = NUPA_STRING ) {
} else if ( dtype = = NUPA_STRING ) {
wval = ( int ) ( p - s ) ;
DS_CREATE ( sstr , 200 ) ;
string_expr ( dico , & sstr , tmp , tmp + strlen ( tmp ) ) ;
sval = copy ( ds_get_buf ( & sstr ) ) ;
ds_free ( & sstr ) ;
}
}
error = nupa_define ( dico , ds_get_buf ( & tstr ) , mode /* was ' ' */ ,
error = nupa_define ( dico , ds_get_buf ( & tstr ) , mode /* was ' ' */ ,
dtype , rval , wval , NULL ) ;
dtype , rval , wval , sval ) ;
if ( error )
if ( error )
break ;
break ;
@ -1445,9 +1512,10 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
/***** first, analyze the subckt definition line */
/***** first, analyze the subckt definition line */
n = 0 ; /* number of parameters if any */
n = 0 ; /* number of parameters if any */
scopys ( & tstr , s ) ;
scopys ( & tstr , s ) ;
/* Get the subcircuit name in subname. */
const char * j2 = strstr ( ds_get_buf ( & tstr ) , " subckt " ) ;
const char * j2 = strstr ( ds_get_buf ( & tstr ) , " subckt " ) ;
if ( j2 ) {
if ( j2 ) {
j2 = skip_ws ( j2 + 6 ) ; /* skip subckt and whitespace */
j2 = skip_ws ( j2 + 6 ) ; /* skip subckt and whitespace */
@ -1456,6 +1524,8 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
err = message ( dico , " ! a subckt line! \n " ) ;
err = message ( dico , " ! a subckt line! \n " ) ;
}
}
/* Scan the .subckt line for assignments, copying templates to idlist. */
const char * i2 = strstr ( ds_get_buf ( & tstr ) , " params: " ) ;
const char * i2 = strstr ( ds_get_buf ( & tstr ) , " params: " ) ;
if ( i2 ) {
if ( i2 ) {
@ -1510,7 +1580,7 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
char * const t_p = ds_get_buf ( & tstr ) ;
char * const t_p = ds_get_buf ( & tstr ) ;
char * jp = NULL ;
char * jp = NULL ;
/* search for the last occurence of `subname' in the given line */
/* Search for the last occurence of `subname' in the call line. */
for ( ; ; ) {
for ( ; ; ) {
char * next_p = search_isolated_identifier ( jp ? jp + 1 : t_p ,
char * next_p = search_isolated_identifier ( jp ? jp + 1 : t_p ,
ds_get_buf ( & subname ) ) ;
ds_get_buf ( & subname ) ) ;
@ -1528,7 +1598,6 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
/* jp is pointing to the 1st position of arglist now */
/* jp is pointing to the 1st position of arglist now */
while ( * jp ) {
while ( * jp ) {
/* try to fetch valid arguments */
/* try to fetch valid arguments */
char * kp = jp ;
char * kp = jp ;
ds_clear ( & ustr ) ;
ds_clear ( & ustr ) ;
@ -1538,13 +1607,16 @@ nupa_subcktcall(dico_t *dico, const char *s, const char *x,
jp = skip_non_ws ( kp ) ;
jp = skip_non_ws ( kp ) ;
pscopy ( & ustr , kp , jp ) ;
pscopy ( & ustr , kp , jp ) ;
} else if ( * kp = = ' { ' ) {
} else if ( * kp = = ' { ' ) {
jp = getexpress ( NULL , & ustr , jp ) ;
jp = getexpress ( dico , NULL , & ustr , jp ) ;
} else {
} else {
jp + + ;
jp + + ;
if ( ( unsigned char ) ( * kp ) > ' ' )
if ( ( unsigned char ) ( * kp ) > ' ' )
message ( dico , " Subckt call, symbol %c not understood \n " , * kp ) ;
message ( dico , " Subckt call, symbol %c not understood \n " , * kp ) ;
}
}
/* Substitute the parameter for one of the '$' characters
* in idlist .
*/
char * const u_p = ds_get_buf ( & ustr ) ;
char * const u_p = ds_get_buf ( & ustr ) ;
if ( * u_p ) {
if ( * u_p ) {
char * const idlist_p = ds_get_buf ( & idlist ) ;
char * const idlist_p = ds_get_buf ( & idlist ) ;