From 112261297df08237b859732822be5bbd0ba774ba Mon Sep 17 00:00:00 2001 From: dwarning Date: Thu, 25 Mar 2010 22:44:37 +0000 Subject: [PATCH] Bill Swartz patch --- ChangeLog | 6 + doc/version.texi | 4 +- src/frontend/numparam/general.h | 33 +-- src/frontend/numparam/mystring.c | 325 ---------------------------- src/frontend/numparam/numparam.h | 16 +- src/frontend/numparam/readme.txt | 2 +- src/frontend/numparam/spicenum.c | 154 ++++++++++---- src/frontend/numparam/xpressn.c | 189 +++++++++-------- src/include/Makefile.am | 1 + src/include/hash.h | 33 ++- src/misc/Makefile.am | 1 + src/misc/dstring.c | 352 +++++++++++++++++++++++++++++++ src/misc/hash.c | 16 +- src/misc/string.c | 67 +++--- src/spicelib/analysis/cktop.c | 4 +- visualc/vngspice.sln | 94 ++++----- 16 files changed, 700 insertions(+), 597 deletions(-) create mode 100644 src/misc/dstring.c diff --git a/ChangeLog b/ChangeLog index 0f7c6684a..8ae7672ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-03-25 Dietmar Warning + * Bill Swartz patch: + * numparam/*.c, *.h, *.txt, misc/hash.c, string.c: local and global hash lists for subckts + * misc/dstring.c, include/dstring.h, Makefile.am: dynamic string feature + * analysis/cktop.c: remove the CR in some printf's + 2010-03-20 Holger Vogt * variable.c:450 prevent ngspice from crashing after command 'unset zzz', when zzz is not defined diff --git a/doc/version.texi b/doc/version.texi index 46e87106b..a3c4e9898 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -1,4 +1,4 @@ @set UPDATED 25 November 2008 @set UPDATED-MONTH November 2008 -@set EDITION 18 -@set VERSION 18 +@set EDITION 20 +@set VERSION 20 diff --git a/src/frontend/numparam/general.h b/src/frontend/numparam/general.h index 7819cb957..556f67536 100644 --- a/src/frontend/numparam/general.h +++ b/src/frontend/numparam/general.h @@ -5,43 +5,12 @@ #include the function code is in 'mystring.c' . */ +#include "dstring.h" #define Use(x) x=0;x=x #define Uses(s) s=s #define Usep(x) x=x -/* ----------------------------------------------------------------- - * This structure is modified from Tcl. We do this to avoid a - * conflict and later add a conditional compile to just use the Tcl - * code if desired. ------------------------------------------------------------------ */ -#define SPICE_DSTRING_STATIC_SIZE 200 -typedef struct spice_dstring { - char *string ; /* Points to beginning of string: either - * staticSpace below or a malloced array. */ - int length ; /* Number of non-NULL characters in the - * string. */ - int spaceAvl ; /* Total number of bytes available for the - * string and its terminating NULL char. */ - char staticSpace[SPICE_DSTRING_STATIC_SIZE] ; - /* Space to use in common case where string - * is small. */ -} SPICE_DSTRING, *SPICE_DSTRINGPTR ; - -/* ----------------------------------------------------------------- - * spice_dstring_xxxx routines. Used to manipulate dynamic strings. ------------------------------------------------------------------ */ -extern void spice_dstring_init(SPICE_DSTRINGPTR dsPtr) ; -extern char *spice_dstring_append(SPICE_DSTRINGPTR dsPtr,char *string,int length) ; -extern char *spice_dstring_print(SPICE_DSTRINGPTR dsPtr,char *format, ... ) ; -extern char *spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) ; -extern char *_spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) ; -extern void spice_dstring_free(SPICE_DSTRINGPTR dsPtr) ; -#define spice_dstring_reinit(x_xz) spice_dstring_setlength(x_xz,0) ; -#define spice_dstring_value(x_xz) ((x_xz)->string) -#define spice_dstring_space(x_xz) ((x_xz)->spaceAvl) -#define spice_dstring_length(x_xz) ((x_xz)->length) - typedef enum {Esc=27} _nEsc; typedef enum {Tab=9} _nTab; typedef enum {Bs=8} _nBs; diff --git a/src/frontend/numparam/mystring.c b/src/frontend/numparam/mystring.c index 9cd3d13bc..9c0779381 100644 --- a/src/frontend/numparam/mystring.c +++ b/src/frontend/numparam/mystring.c @@ -1119,328 +1119,3 @@ intp (double x) /* integral part */ } #endif - -/* ----------------------------------------------------------------- - * Dynamic string utilities. - * ----------------------------------------------------------------- */ - -/* - *---------------------------------------------------------------------- - * - * spice_dstring_init -- - * - * Initializes a dynamic string, discarding any previous contents - * of the string (spice_dstring_free should have been called already - * if the dynamic string was previously in use). - * - * Results: - * None. - * - * Side effects: - * The dynamic string is initialized to be empty. - * - *---------------------------------------------------------------------- - */ - -void spice_dstring_init(SPICE_DSTRINGPTR dsPtr) -{ - dsPtr->string = dsPtr->staticSpace ; - dsPtr->length = 0 ; - dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE ; - dsPtr->staticSpace[0] = EOS; -} /* end spice_dstring_init() */ - -/* - *---------------------------------------------------------------------- - * - * spice_dstring_append -- - * - * Append more characters to the current value of a dynamic string. - * - * Results: - * The return value is a pointer to the dynamic string's new value. - * - * Side effects: - * Length bytes from string (or all of string if length is less - * than zero) are added to the current value of the string. Memory - * gets reallocated if needed to accomodate the string's new size. - * - * Notes: char *string; String to append. If length is -1 then - * this must be null-terminated. - * INT length; Number of characters from string to append. - * If < 0, then append all of string, up to null at end. - * - *---------------------------------------------------------------------- - */ -char *spice_dstring_append(SPICE_DSTRINGPTR dsPtr,char *string,int length) -{ - int newSize ; /* needed size */ - char *newString ; /* newly allocated string buffer */ - char *dst ; /* destination */ - char *end ; /* end of string */ - - if( length < 0){ - length = strlen(string) ; - } - newSize = length + dsPtr->length ; - - /* ----------------------------------------------------------------- - * Allocate a larger buffer for the string if the current one isn't - * large enough. Allocate extra space in the new buffer so that there - * will be room to grow before we have to allocate again. - ----------------------------------------------------------------- */ - if (newSize >= dsPtr->spaceAvl) { - dsPtr->spaceAvl = 2 * newSize ; - newString = new( dsPtr->spaceAvl * sizeof(char) ) ; - memcpy((void *) newString, (void *) dsPtr->string, (size_t) dsPtr->length) ; - if (dsPtr->string != dsPtr->staticSpace) { - dispose(dsPtr->string) ; - } - dsPtr->string = newString; - } - - /* ----------------------------------------------------------------- - * Copy the new string into the buffer at the end of the old - * one. - ----------------------------------------------------------------- */ - for( dst = dsPtr->string + dsPtr->length, end = string+length; - string < end; string++, dst++) { - *dst = *string ; - } - *dst = EOS ; - dsPtr->length += length ; - - return(dsPtr->string) ; - -} /* end spice_dstring_append() */ - - -static int spice_format_length( va_list args, char *fmt ) -{ - int i ; /* integer */ - int len ; /* length of format */ - int size_format ; /* width of field */ - int found_special ; /* look for special characters */ - char *s ; /* string */ - char c ; /* character */ - - /* ----------------------------------------------------------------- - * First find length of buffer. - ----------------------------------------------------------------- */ - len = 0 ; - while(fmt && *fmt){ - if( *fmt == '%' ){ - fmt++ ; - if( *fmt == '%' ){ - len++ ; - } else { - /* ----------------------------------------------------------------- - * We have a real formatting character, loop until we get a special - * character. - ----------------------------------------------------------------- */ - if( *fmt == '.' || *fmt == '-' ){ - fmt++ ; /* skip over these characters */ - } - size_format = atoi(fmt) ; - if( size_format > 0 ){ - len += size_format ; - } - found_special = FALSE ; - for( ; fmt && *fmt ; fmt++ ){ - switch( *fmt ){ - case 's': - s = va_arg(args, char *) ; - if( s ){ - len += strlen(s) ; - } - found_special = TRUE ; - break ; - case 'i': - case 'd': - case 'o': - case 'x': - case 'X': - case 'u': - i = va_arg(args, int) ; - len += 10 ; - found_special = TRUE ; - break ; - case 'c': - c = va_arg(args, int) ; - len++ ; - found_special = TRUE ; - break ; - case 'f': - case 'e': - case 'F': - case 'g': - case 'G': - c = va_arg(args, double) ; - len += 35 ; - found_special = TRUE ; - break ; - default: - ; - } /* end switch() */ - - if( found_special ){ - break ; - } - } - } - } else { - len++ ; - } - fmt++ ; - } /* end while() */ - va_end(args) ; - - return(len) ; - -} /* end Ymessage_format_length() */ - - -char *spice_dstring_print( SPICE_DSTRINGPTR dsPtr,char *format, ... ) -{ - va_list args ; - int format_len ; /* length of format */ - int length ; /* new length */ - int orig_length ; /* original length of buffer */ - char *buffer ; /* proper length of buffer */ - - /* ----------------------------------------------------------------- - * First get the length of the buffer needed. - ----------------------------------------------------------------- */ - va_start( args, format ) ; - format_len = spice_format_length(args,format) ; - - /* ----------------------------------------------------------------- - * Next allocate the proper buffer size. - ----------------------------------------------------------------- */ - orig_length = dsPtr->length ; - length = orig_length + format_len + 1 ; - buffer = spice_dstring_setlength( dsPtr, length) ; - - /* ----------------------------------------------------------------- - * Convert the format. - ----------------------------------------------------------------- */ - va_start( args, format ) ; - if( format ){ - vsprintf( buffer + orig_length, format, args ) ; - dsPtr->length = strlen( buffer ) ; - } else { - buffer = NULL ; - } - va_end(args) ; - return( buffer ) ; - -} /* end spice_dstring_print() */ - -/* - *---------------------------------------------------------------------- - * - * _spice_dstring_setlength -- - * - * Change the length of a dynamic string. This can cause the - * string to either grow or shrink, depending on the value of - * length. - * - * Results: - * Returns the current string buffer. - * - * Side effects: - * The length of dsPtr is changed to length but a null byte is not - * stored at that position in the string. Use spice_dstring_setlength - * for that function. If length is larger - * than the space allocated for dsPtr, then a panic occurs. - * - *---------------------------------------------------------------------- - */ - -char *_spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) -{ - char *newString ; - - if (length < 0) { - length = 0 ; - } - if (length >= dsPtr->spaceAvl) { - - dsPtr->spaceAvl = length+1; - newString = new( dsPtr->spaceAvl * sizeof(char) ) ; - /* ----------------------------------------------------------------- - * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string - * to a larger buffer, since there may be embedded NULLs in the - * string in some cases. - ----------------------------------------------------------------- */ - memcpy((void *) newString, (void *) dsPtr->string, (size_t) dsPtr->length) ; - if( dsPtr->string != dsPtr->staticSpace ) { - dispose(dsPtr->string) ; - } - dsPtr->string = newString ; - } - dsPtr->length = length ; - return(dsPtr->string) ; - -} /* end _spice_dstring_setlength() */ - - -/* - *---------------------------------------------------------------------- - * - * spice_dstring_setlength -- - * - * Change the length of a dynamic string. This can cause the - * string to either grow or shrink, depending on the value of - * length. - * - * Results: - * Returns the current string buffer. - * - * Side effects: - * The length of dsPtr is changed to length and a null byte is - * stored at that position in the string. If length is larger - * than the space allocated for dsPtr, then a panic occurs. - * - *---------------------------------------------------------------------- - */ - -char *spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) -{ - char *str_p ; /* newly create string */ - - str_p = _spice_dstring_setlength( dsPtr,length) ; - str_p[length] = EOS ; - return( str_p ) ; - -} /* end spice_dstring_setlength() */ - -/* - *---------------------------------------------------------------------- - * - * spice_dstring_free -- - * - * Frees up any memory allocated for the dynamic string and - * reinitializes the string to an empty state. - * - * Results: - * None. - * - * Side effects: - * The previous contents of the dynamic string are lost, and - * the new value is an empty string. - * - *---------------------------------------------------------------------- - */ - -void spice_dstring_free(SPICE_DSTRINGPTR dsPtr) -{ - if (dsPtr->string != dsPtr->staticSpace) { - dispose(dsPtr->string) ; - } - dsPtr->string = dsPtr->staticSpace ; - dsPtr->length = 0 ; - dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE; - dsPtr->staticSpace[0] = EOS ; - -} /* end spice_dstring_free() */ diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h index e5480662f..5cf04451a 100644 --- a/src/frontend/numparam/numparam.h +++ b/src/frontend/numparam/numparam.h @@ -60,15 +60,14 @@ typedef struct _ttdico { int srcline; int oldline; int errcount; - int num_symbols ; /* number of symbols in entry array */ - entry **symbol_array ; /* symbol entries in array format for stack ops */ - NGHASHPTR symbol_table ; /* hash table of symbols for quick lookup */ - int nbd; /* number of data entries */ + int symbol_stack_alloc ; /* stack allocation */ + int stack_depth ; /* current depth of the symbol stack */ + NGHASHPTR global_symbols ; /* hash table of globally defined symbols for quick lookup */ + NGHASHPTR *local_symbols ; /* stack of locally defined symbols */ + NGHASHPTR inst_symbols ; /* instance qualified symbols - after a pop */ + char **inst_name ; /* name of subcircuit */ fumas fms[101]; int nfms; /* number of functions & macros */ - int stack[20]; - char *inst_name[20]; - int tos; /* top of stack index for symbol mark/release mechanics */ auxtable nodetab; // char * refptr[Maxline]; /* pointers to source code lines */ char **dynrefptr; @@ -79,6 +78,7 @@ typedef struct _ttdico { void initdico(tdico * dico); int donedico(tdico * dico); +void dico_free_entry( entry *entry_p ) ; unsigned char defsubckt( tdico *dico, char * s, int w, char categ); int findsubckt( tdico *dico, char * s, SPICE_DSTRINGPTR subname); unsigned char nupa_substitute( tdico *dico, char * s, char * r, unsigned char err); @@ -87,4 +87,4 @@ unsigned char nupa_subcktcall( tdico *dico, char * s, char * x, unsigned char er void nupa_subcktexit( tdico *dico); tdico * nupa_fetchinstance(void); char getidtype( tdico *d, char * s); -entry *attrib( tdico *dico, char * t, char op ); +entry *attrib( tdico *d, NGHASHPTR htable, char * t, char op ); diff --git a/src/frontend/numparam/readme.txt b/src/frontend/numparam/readme.txt index 24ce2be43..84bfb93dc 100644 --- a/src/frontend/numparam/readme.txt +++ b/src/frontend/numparam/readme.txt @@ -295,7 +295,7 @@ In the syntax description, symbols and any .param assignments are considered local: they mask any global identical names, until the .ends line is encountered. You cannot reassign to a global number inside a .subckt, a local copy is - created instead. Scope nesting works up to a level of 10. For example, + created instead. Scope nesting now works up to any level. For example, if the main circuit calls A which has a formal parameter xx, A calls B which has a param. xx, and B calls C which also has a formal param. xx, there will be three versions of 'xx' in the symbol table but only the most diff --git a/src/frontend/numparam/spicenum.c b/src/frontend/numparam/spicenum.c index e3b30646d..e05a2174d 100644 --- a/src/frontend/numparam/spicenum.c +++ b/src/frontend/numparam/spicenum.c @@ -32,7 +32,6 @@ Todo: extern void txfree (void *ptr); char *nupa_inst_name; -static tdico *inst_dicoS ; /* number of parameter substitutions, available only after the substitution */ extern long dynsubst; /* spicenum.c:144 */ @@ -166,7 +165,7 @@ findsubname (tdico * dico, SPICE_DSTRINGPTR dstr_p) SPICE_DSTRING name ; /* extract a name */ char *s ; /* current dstring */ int h, j, k, nest, ls; - unsigned char found; + int found ; h = 0; ls = spice_dstring_length (dstr_p) ; @@ -310,7 +309,7 @@ transform (tdico * dico, SPICE_DSTRINGPTR dstr_p, unsigned char nostripping, * 'B' netlist (or .model ?) line that had Braces killed */ { - int i, k, a, n; + int k, a, n; char *s ; /* dstring value of dstr_p */ char *t ; /* dstring value of tstr */ char category; @@ -367,7 +366,7 @@ transform (tdico * dico, SPICE_DSTRINGPTR dstr_p, unsigned char nostripping, } else if (upcase (s[0]) == 'X') { /* strip actual parameters */ - i = findsubname (dico, dstr_p) ; /* i= index following last identifier in s */ + findsubname (dico, dstr_p) ;/* i= index following last identifier in s */ category = 'X'; } else if (s[0] == '+') /* continuation line */ @@ -454,9 +453,7 @@ nupa_init (char *srcfile) incontrolS = 0; placeholder = 0; dicoS = (tdico *)new(sizeof(tdico)); - inst_dicoS = (tdico *)new(sizeof(tdico)); initdico (dicoS); - initdico (inst_dicoS); dicoS->dynrefptr = (char**)tmalloc((dynmaxline + 1)*sizeof(char*)); dicoS->dyncategory = (char*)tmalloc((dynmaxline + 1)*sizeof(char)); @@ -545,21 +542,19 @@ nupa_scan (char *s, int linenum, int is_subckt) } /* ----------------------------------------------------------------- - * Dump the contents of the symbol table. + * Dump the contents of a symbol table. * ----------------------------------------------------------------- */ -void -nupa_list_params (FILE * cp_out) +static void +dump_symbol_table( tdico *dico_p, NGHASHPTR htable_p, FILE * cp_out) { char *name; /* current symbol */ entry *entry_p ; /* current entry */ - tdico *dico_p ; /* local copy for speed */ NGHASHITER iter ; /* hash iterator - thread safe */ - dico_p = dicoS ; - fprintf (cp_out, "\n\n"); - for (entry_p = nghash_enumerateRE(dico_p->symbol_table,NGHASH_FIRST(&iter)) ; + NGHASH_FIRST(&iter) ; + for (entry_p = nghash_enumerateRE( htable_p,&iter) ; entry_p ; - entry_p = nghash_enumerateRE(dico_p->symbol_table,&iter)) + entry_p = nghash_enumerateRE( htable_p,&iter)) { if (entry_p->tp == 'R') { @@ -570,17 +565,58 @@ nupa_list_params (FILE * cp_out) spice_dstring_free( & dico_p->lookup_buf ) ; } } +} /* end dump_symbol_table() */ + + +/* ----------------------------------------------------------------- + * Dump the contents of the symbol table. + * ----------------------------------------------------------------- */ +void +nupa_list_params (FILE * cp_out) +{ + int depth ; /* nested subcircit depth */ + tdico *dico_p ; /* local copy for speed */ + NGHASHPTR htable_p ; /* current hash table */ + + dico_p = dicoS ; + fprintf (cp_out, "\n\n"); + + /* ----------------------------------------------------------------- + * Print out the locally defined symbols from highest to lowest priority. + * If there are no parameters, the hash table will not be allocated as + * we use lazy allocation to save memory. + * ----------------------------------------------------------------- */ + for( depth = dico_p->stack_depth ; depth > 0 ; depth-- ){ + htable_p = dico_p->local_symbols[depth] ; + if( htable_p ){ + fprintf (cp_out, " local symbol definitions for:%s\n", dico_p->inst_name[depth]) ; + dump_symbol_table( dico_p, htable_p, cp_out ) ; + } + } + + /* ----------------------------------------------------------------- + * Finally dump the global symbols. + * ----------------------------------------------------------------- */ + fprintf (cp_out, " global symbol definitions:\n") ; + dump_symbol_table( dico_p, dico_p->global_symbols, cp_out ) ; } /* ----------------------------------------------------------------- - * Lookup a parameter value in the symbol table. + * Lookup a parameter value in the symbol tables. This involves + * multiple lookups in various hash tables in order to get the scope + * correct. Each subcircuit instance will have its own local hash + * table if it has parameters. We can return whenever we get a hit. + * Otherwise, we have to exhaust all of the tables including the global + * table. * ----------------------------------------------------------------- */ double nupa_get_param (char *param_name, int *found) { + int depth ; /* nested subcircit depth */ char *up_name; /* current parameter upper case */ entry *entry_p ; /* current entry */ tdico *dico_p ; /* local copy for speed */ + NGHASHPTR htable_p ; /* current hash table */ double result = 0; /* parameter value */ dico_p = dicoS ; @@ -589,11 +625,27 @@ nupa_get_param (char *param_name, int *found) up_name = spice_dstring_value( & dico_p->lookup_buf ) ; *found = 0; - entry_p = nghash_find( dico_p->symbol_table, up_name ) ; - if( entry_p ){ - result = entry_p->vl ; - *found = 1; + for( depth = dico_p->stack_depth ; depth > 0 ; depth-- ){ + htable_p = dico_p->local_symbols[depth] ; + if( htable_p ){ + entry_p = nghash_find( htable_p, up_name ) ; + if( entry_p ){ + result = entry_p->vl ; + *found = 1; + break ; + } + } } + + if(!(*found)){ + /* No luck. Try the global table. */ + entry_p = nghash_find( dico_p->global_symbols, up_name ) ; + if( entry_p ){ + result = entry_p->vl ; + *found = 1; + } + } + spice_dstring_free( & dico_p->lookup_buf ) ; return result; } @@ -604,6 +656,7 @@ nupa_add_param (char *param_name, double value) char *up_name; /* current parameter upper case */ entry *entry_p ; /* current entry */ tdico *dico_p ; /* local copy for speed */ + NGHASHPTR htable_p ; /* hash table of interest */ dico_p = dicoS ; /* ----------------------------------------------------------------- @@ -614,7 +667,18 @@ nupa_add_param (char *param_name, double value) scopy_up( & dico_p->lookup_buf, param_name ) ; up_name = spice_dstring_value( & dico_p->lookup_buf ) ; - entry_p = attrib (dicoS, up_name, 'N'); + if( dico_p->stack_depth > 0 ){ + /* can't be lazy anymore */ + if(!(dico_p->local_symbols[dico_p->stack_depth])){ + dico_p->local_symbols[dico_p->stack_depth] = nghash_init( NGHASH_MIN_SIZE ) ; + } + htable_p = dico_p->local_symbols[dico_p->stack_depth] ; + } else { + /* global symbol */ + htable_p = dico_p->global_symbols ; + } + + entry_p = attrib ( dico_p, htable_p, up_name, 'N'); if( entry_p ){ entry_p->vl = value; entry_p->tp = 'R'; @@ -631,12 +695,16 @@ nupa_add_inst_param (char *param_name, double value) entry *entry_p ; /* current entry */ tdico *dico_p ; /* local copy for speed */ - dico_p = inst_dicoS ; + dico_p = dicoS ; spice_dstring_reinit( & dico_p->lookup_buf ) ; scopy_up( & dico_p->lookup_buf, param_name ) ; up_name = spice_dstring_value( & dico_p->lookup_buf ) ; - entry_p = attrib (dicoS, up_name, 'N'); + if(!(dico_p->inst_symbols)){ + dico_p->inst_symbols = nghash_init( NGHASH_MIN_SIZE ) ; + } + + entry_p = attrib ( dico_p, dico_p->inst_symbols, up_name, 'N'); if( entry_p ){ entry_p->vl = value; entry_p->tp = 'R'; @@ -646,18 +714,35 @@ nupa_add_inst_param (char *param_name, double value) spice_dstring_free( & dico_p->lookup_buf ) ; } +/* ----------------------------------------------------------------- + * This function copies any definitions in the inst_symbols hash + * table which are qualified symbols and makes them available at + * the global level. Afterwards, the inst_symbols table is freed. + * ----------------------------------------------------------------- */ void nupa_copy_inst_dico () { - tdico *idico_p ; /* local copy for speed */ entry *entry_p ; /* current entry */ + tdico *dico_p ; /* local copy for speed */ NGHASHITER iter ; /* hash iterator - thread safe */ - idico_p = inst_dicoS ; - for (entry_p = nghash_enumerateRE(idico_p->symbol_table,NGHASH_FIRST(&iter)) ; - entry_p ; - entry_p = nghash_enumerateRE(idico_p->symbol_table,&iter)) - nupa_add_param ( entry_p->symbol, entry_p->vl) ; + dico_p = dicoS ; + if( dico_p->inst_symbols ){ + /* We we perform this operation we should be in global scope */ + if( dico_p->stack_depth > 0 ){ + fprintf( stderr, "stack depth should be zero.\n" ) ; + } + NGHASH_FIRST(&iter) ; + for (entry_p = nghash_enumerateRE(dico_p->inst_symbols,&iter ) ; + entry_p ; + entry_p = nghash_enumerateRE(dico_p->inst_symbols,&iter)){ + nupa_add_param ( entry_p->symbol, entry_p->vl) ; + dico_free_entry( entry_p ) ; + } + + nghash_free( dico_p->inst_symbols, NULL, NULL ) ; + dico_p->inst_symbols = NULL ; + } } char * @@ -840,18 +925,9 @@ nupa_fetchinstance (void) } #endif /* USING_NUPATEST */ -static void dump_symbols( tdico *dico_p ) +void dump_symbols( tdico *dico_p ) { - char *name_p ; /* current symbol */ - entry *entry_p ; /* current entry */ - void *key ; /* return key */ - NGHASHITER iter ; /* hash iterator - thread safe */ fprintf (stderr, "Symbol table\n"); - for (entry_p = nghash_enumeratekRE(dico_p->symbol_table,&key,NGHASH_FIRST(&iter)) ; - entry_p ; - entry_p = nghash_enumeratekRE(dico_p->symbol_table,&key,&iter)) { - name_p = (char *) key ; - fprintf (stderr, " ---> %s = %g\n", name_p, entry_p->vl) ; - } + nupa_list_params ( stderr ) ; } diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 64d60188b..cf0b740f4 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -177,21 +177,26 @@ debugwarn (tdico * d, char *s) void initdico (tdico * dico) { + int asize ; /* default allocation size */ COMPATMODE_T compat_mode; - dico->nbd = 0; spice_dstring_init( &(dico->option) ) ; spice_dstring_init( &(dico->srcfile) ) ; dico->srcline = -1; dico->errcount = 0; - dico->symbol_table = nghash_init( NGHASH_MIN_SIZE ) ; - nghash_unique( dico->symbol_table, FALSE ) ; + dico->global_symbols = nghash_init( NGHASH_MIN_SIZE ) ; + nghash_unique( dico->global_symbols, TRUE ) ; /* no rewrite of global symbols */ spice_dstring_init( &(dico->lookup_buf) ) ; - dico->tos = 0; - dico->stack[dico->tos] = 0; /* global data beneath */ + dico->stack_depth = 0 ; /* top of the stack */ + asize = dico->symbol_stack_alloc = 10 ;/* expected stack depth - no longer limited */ + asize++ ; /* account for zero */ + dico->local_symbols = tmalloc( asize * sizeof(NGHASHPTR) ) ; + dico->inst_name = tmalloc( asize * sizeof(char *) ) ; + dico->inst_symbols = NULL ; /* instance qualified are lazily allocated */ + initkeys (); compat_mode = ngspice_compat_mode() ; @@ -202,7 +207,7 @@ initdico (tdico * dico) dico->hspice_compatibility = 0 ; } -static void dico_free_entry( entry *entry_p ) +void dico_free_entry( entry *entry_p ) { if( entry_p->symbol ){ txfree(entry_p->symbol ) ; @@ -210,32 +215,6 @@ static void dico_free_entry( entry *entry_p ) txfree(entry_p) ; } /* end dico_free_entry() */ -static -entry **dico_rebuild_symbol_array( tdico * dico, int *num_entries_ret ) -{ - int i ; /* counter */ - int size ; /* number of entries in symbol table */ - entry *entry_p ; /* current entry */ - NGHASHITER iter ; /* hash iterator - thread safe */ - - size = *num_entries_ret = nghash_get_size( dico->symbol_table ) ; - if( dico->num_symbols == size ){ - /* no work to do up to date */ - return( dico->symbol_array ) ; - } - if( size <= 0 ){ - size = 1 ; - } - dico->symbol_array = trealloc( dico->symbol_array, (size+1) * sizeof(entry *) ) ; - i = 0 ; - for (entry_p = nghash_enumerateRE(dico->symbol_table,NGHASH_FIRST(&iter)) ; - entry_p ; - entry_p = nghash_enumerateRE(dico->symbol_table,&iter)){ - dico->symbol_array[i++] = entry_p ; - } - dico->num_symbols = *num_entries_ret ; - return dico->symbol_array ; -} /* local semantics for parameters inside a subckt */ /* arguments as wll as .param expressions */ @@ -251,52 +230,61 @@ static void dicostack (tdico * dico, char op) /* push or pop operation for nested subcircuit locals */ { - char *param_p, *inst_name; - int i, current_stack_size, old_stack_size; - int num_entries ; /* number of entries */ - entry **entry_array ; /* entry array */ + int asize ; /* allocation size */ + char *inst_name ; /* name of subcircuit instance */ + char *param_p ; /* qualified inst parameter name */ entry *entry_p ; /* current entry */ - SPICE_DSTRING param_name ; + NGHASHPTR htable_p ; /* current hash table */ + NGHASHITER iter ; /* hash iterator - thread safe */ if (op == Push) { - if (dico->tos < (20 - 1)) - dico->tos++; - else - message (dico, " Subckt Stack overflow"); - - dico->stack[dico->tos] = dico->nbd; - dico->inst_name[dico->tos] = nupa_inst_name; + dico->stack_depth++; + if ( dico->stack_depth > dico->symbol_stack_alloc ){ + /* Just double the stack alloc */ + dico->symbol_stack_alloc *= 2 ; + asize = dico->symbol_stack_alloc + 1 ; /* account for zero */ + dico->local_symbols = trealloc( dico->local_symbols, asize * sizeof(NGHASHPTR) ) ; + dico->inst_name = trealloc( dico->inst_name, asize * sizeof(char *) ) ; + } + /* lazy allocation - don't allocate space if we can help it */ + dico->local_symbols[dico->stack_depth] = NULL ; + dico->inst_name[dico->stack_depth] = nupa_inst_name ; } else if (op == Pop) { - if (dico->tos > 0) + if (dico->stack_depth > 0) { - /* keep instance parameters around */ - current_stack_size = dico->nbd; - old_stack_size = dico->stack[dico->tos]; - inst_name = dico->inst_name[dico->tos]; - spice_dstring_init(¶m_name) ; - entry_array = dico_rebuild_symbol_array( dico, &num_entries ) ; + /* ----------------------------------------------------------------- + * Keep instance parameters around by transferring current local + * scope variables to an instance qualified hash table. + * ----------------------------------------------------------------- */ + inst_name = dico->inst_name[dico->stack_depth] ; + htable_p = dico->local_symbols[dico->stack_depth] ; + if( htable_p ){ + SPICE_DSTRING param_name ; /* build a qualified name */ + spice_dstring_init(¶m_name) ; - for (i = old_stack_size + 1; i <= current_stack_size; i++) - { - spice_dstring_reinit(¶m_name) ; - if( i < num_entries ){ - entry_p = entry_array[i] ; - param_p = spice_dstring_print( ¶m_name, "%s.%s", - inst_name, - entry_p->symbol ) ; + NGHASH_FIRST(&iter) ; + for (entry_p = nghash_enumerateRE( htable_p,&iter ) ; + entry_p ; + entry_p = nghash_enumerateRE( htable_p,&iter)) + { + spice_dstring_reinit(¶m_name) ; + param_p = spice_dstring_print( ¶m_name, "%s.%s", + inst_name, + entry_p->symbol ) ; nupa_add_inst_param (param_p, entry_p->vl); -/* nghash_deleteItem( dico->symbol_table, entry_p->symbol, entry_p ) ; - dico_free_entry( entry_p ) ; */ + dico_free_entry( entry_p ) ; } + nghash_free( htable_p, NULL, NULL ) ; + spice_dstring_free(¶m_name) ; } tfree (inst_name); - spice_dstring_free(¶m_name) ; - dico->nbd = dico->stack[dico->tos]; /* simply kill all local items */ - dico->tos--; + dico->inst_name[dico->stack_depth] = NULL ; + dico->local_symbols[dico->stack_depth] = NULL ; + dico->stack_depth--; } else { @@ -308,21 +296,37 @@ dicostack (tdico * dico, char op) int donedico (tdico * dico) { - int sze = dico->nbd; + int sze = nghash_get_size( dico->global_symbols ) ; return sze; } -/* FIXME : WPS this should be a hash table */ +/* ----------------------------------------------------------------- + * Now entryb works on the given hash table hierarchy. First + * look thru the stack of local symbols and then look at the global + * symbols in that order. + * ----------------------------------------------------------------- */ static entry * -entrynb (tdico * d, char *s) -/* symbol lookup from end to start, for stacked local symbols .*/ -/* bug: sometimes we need access to same-name symbol, at lower level? */ +entrynb ( tdico *d, char *s) { + int depth ; /* stack depth */ entry *entry_p ; /* search hash table */ + NGHASHPTR htable_p ; /* hash table */ - entry_p = nghash_find( d->symbol_table, s ) ; - return( entry_p ) ; -} + /* look at the current scope and then backup the stack */ + for( depth = d->stack_depth ; depth > 0 ; depth-- ){ + htable_p = d->local_symbols[depth] ; + if( htable_p ){ + entry_p = nghash_find( htable_p, s ) ; + if( entry_p ){ + return( entry_p ) ; + } + } + } + /* No local symbols - try the global table */ + entry_p = nghash_find( d->global_symbols, s ) ; + return( entry_p ) ; + +} /* end entrynb() */ char getidtype (tdico * d, char *s) @@ -331,11 +335,11 @@ getidtype (tdico * d, char *s) entry *entry_p ; /* hash table entry */ char itp = '?'; /* assume unknown */ - entry_p = entrynb (d, s) ; - if( entry_p ){ - itp = entry_p->tp ; - } - return (itp) ; + entry_p = entrynb( d, s ) ; + if( entry_p ) + itp = entry_p->tp ; + + return (itp) ; } static double @@ -379,30 +383,27 @@ fetchnumentry (tdico * dico, char *t, unsigned char *perr) /******* writing dictionary entries *********/ entry * -attrib (tdico * dico, char *t, char op) +attrib (tdico *dico_p, NGHASHPTR htable_p, char *t, char op) { /* seek or attribute dico entry number for string t. Option op='N' : force a new entry, if tos>level and old is valid. */ - int i; entry *entry_p ; /* symbol table entry */ - entry_p = nghash_find( dico->symbol_table, t ) ; + entry_p = nghash_find( htable_p, t ) ; if ( entry_p && (op == 'N') - && ( entry_p->level < dico->tos) && ( entry_p->tp != '?')) + && ( entry_p->level < dico_p->stack_depth) && ( entry_p->tp != '?')) { entry_p = NULL ; } if (!(entry_p)) { - dico->nbd++; - i = dico->nbd; entry_p = tmalloc( sizeof(entry) ) ; entry_p->symbol = strdup( t ) ; entry_p->tp = '?'; /* signal Unknown */ - entry_p->level = dico->tos ; - nghash_insert( dico->symbol_table, t, entry_p ) ; + entry_p->level = dico_p->stack_depth ; + nghash_insert( htable_p, t, entry_p ) ; } return entry_p ; } @@ -429,9 +430,21 @@ define (tdico * dico, unsigned char err, warn; entry *entry_p ; /* spice table entry */ SPICE_DSTRING vartemp ; /* vairable temp */ + NGHASHPTR htable_p ; /* hash table */ spice_dstring_init(&vartemp) ; - entry_p = attrib (dico, t, op); + + if( dico->stack_depth > 0 ){ + /* can't be lazy anymore */ + if(!(dico->local_symbols[dico->stack_depth])){ + dico->local_symbols[dico->stack_depth] = nghash_init( NGHASH_MIN_SIZE ) ; + } + htable_p = dico->local_symbols[dico->stack_depth] ; + } else { + /* global symbol */ + htable_p = dico->global_symbols ; + } + entry_p = attrib (dico, htable_p, t, op); err = 0; if (!(entry_p)) err = message (dico, " Symbol table overflow"); @@ -453,9 +466,9 @@ define (tdico * dico, entry_p->sbbase = base ; /* if ( (c !='?') && (i<= dico->stack[dico->tos]) ) { */ if (c == '?') - entry_p->level = dico->tos; /* promote! */ + entry_p->level = dico->stack_depth ; /* promote! */ - if ( entry_p->level < dico->tos) + if ( entry_p->level < dico->stack_depth) { /* warn about re-write to a global scope! */ scopys(&vartemp, t) ; diff --git a/src/include/Makefile.am b/src/include/Makefile.am index c16b8b0f6..3405c33e2 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -28,6 +28,7 @@ noinst_HEADERS = \ dllitf.h \ domndefs.h \ dopdefs.h \ + dstring.h \ dvec.h \ elctdefs.h \ enh.h \ diff --git a/src/include/hash.h b/src/include/hash.h index 22c3c4cab..95dce559b 100644 --- a/src/include/hash.h +++ b/src/include/hash.h @@ -39,11 +39,11 @@ typedef struct nghashbox { NGTABLEPTR searchPtr ; /* used for find again mechanism */ void *compare_func ; /* the comparison function */ void *hash_func ; /* the hash function */ + double growth_factor ; /* how much to grow table by */ int size ; /* the size of the table */ int max_density ; /* maximum number of entries before growth */ int num_entries ; /* current number of entries in table */ int need_resize ; /* amount before we need a resize */ - float growth_factor ; /* how much to grow table by */ long access ; /* used for statistics */ long collision ; /* collision times */ unsigned int power_of_two : 8 ; /* build table as a power of two */ @@ -51,29 +51,40 @@ typedef struct nghashbox { unsigned int unique : 16 ; /* true if only one unique item in col. list */ } NGHASHBOX, *NGHASHPTR ; +/* ----------------------------------------------------------------- + * This enumerated type is used to control the base hash function types + * as well as hash table attributes such as uniqueness and power of 2. + * The negative definitions for the function are used so we catch a + * segfault immediately if the hash table is used incorrectly. Notice + * that the default function string is zero. Because there definitions + * can be cast into functions, they are defined as longs so it will work + * on all architecture types include 64bits. + * ----------------------------------------------------------------- */ typedef enum { - NGHASH_NONUNIQUE = 0, - NGHASH_UNIQUE = 1L, - NGHASH_POWER_OF_TWO = (1L<<1) + NGHASH_FUNC_NUM = -2L, + NGHASH_FUNC_PTR = -1L, + NGHASH_FUNC_STR = 0L, + NGHASH_UNIQUE = 1L, + NGHASH_POWER_OF_TWO = (1L<<1), + NGHASH_UNIQUE_TWO = NGHASH_UNIQUE | NGHASH_POWER_OF_TWO } NGHASHFLAGS_T ; typedef unsigned int (*nghash_func)(NGHASHPTR,void *) ; -/* the default hashing functions */ -typedef enum { - NGHASH_FUNC_STR = 0, - NGHASH_FUNC_PTR = -1, - NGHASH_FUNC_NUM = -2 -} NGHASH_FUNC_T ; typedef struct nghash_iter_rec { struct ngtable_rec *position ; } NGHASHITER, *NGHASHITERPTR ; + /* ----------------------------------------------------------------- * macro definition for enumeration. Strange looking but compiler * will optimize. x_yz->position = 0 and x_yz will be returned. ------------------------------------------------------------------ */ #define NGHASH_FIRST(x_yz) ( ((x_yz)->position = NULL) ? (x_yz) : (x_yz) ) +No longer use this trick and now explicitly write out both lines because +some compilers complain about unintentional assignment. Unfortunately, +we want to intentionally assign it. The compiler is warning unnecessarily. +----------------------------------------------------------------- */ +#define NGHASH_FIRST(x_yz) ( (x_yz)->position = NULL ) ; #define NGHASH_ITER_EQUAL(x_yz,y_yz) ( (x_yz)->position == (y_yz)->position ) #define NGHASH_DEF_HASH_STR NGHASH_FUNC_STR diff --git a/src/misc/Makefile.am b/src/misc/Makefile.am index 5f068d7ee..46217ff85 100644 --- a/src/misc/Makefile.am +++ b/src/misc/Makefile.am @@ -10,6 +10,7 @@ libmisc_la_SOURCES = \ alloc.c \ alloc.h \ dup2.c \ + dstring.c \ dup2.h \ hash.c \ ivars.c \ diff --git a/src/misc/dstring.c b/src/misc/dstring.c new file mode 100644 index 000000000..de31937cd --- /dev/null +++ b/src/misc/dstring.c @@ -0,0 +1,352 @@ +/* ----------------------------------------------------------------- +FILE: dstring.c +DESCRIPTION:This file contains the routines for manipulating dynamic strings. +CONTENTS: +DATE: Wed Mar 24 18:38:28 CDT 2010 +REVISIONS: $Log$ +REVISIONS: Revision 1.1 2010-03-25 22:44:38 dwarning +REVISIONS: Bill Swartz patch +REVISIONS: +----------------------------------------------------------------- */ +#include "ngspice.h" +#include +#include "dstring.h" + +/* definitions local to this file only */ + +/* ********************** TYPE DEFINITIONS ************************* */ + +/* ********************** STATIC DEFINITIONS ************************* */ +/* + *---------------------------------------------------------------------- + * + * spice_dstring_init -- + * + * Initializes a dynamic string, discarding any previous contents + * of the string (spice_dstring_free should have been called already + * if the dynamic string was previously in use). + * + * Results: + * None. + * + * Side effects: + * The dynamic string is initialized to be empty. + * + *---------------------------------------------------------------------- + */ + +void spice_dstring_init(SPICE_DSTRINGPTR dsPtr) +{ + dsPtr->string = dsPtr->staticSpace ; + dsPtr->length = 0 ; + dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE ; + dsPtr->staticSpace[0] = EOS; +} /* end spice_dstring_init() */ + +/* + *---------------------------------------------------------------------- + * + * spice_dstring_append -- + * + * Append more characters to the current value of a dynamic string. + * + * Results: + * The return value is a pointer to the dynamic string's new value. + * + * Side effects: + * Length bytes from string (or all of string if length is less + * than zero) are added to the current value of the string. Memory + * gets reallocated if needed to accomodate the string's new size. + * + * Notes: char *string; String to append. If length is -1 then + * this must be null-terminated. + * INT length; Number of characters from string to append. + * If < 0, then append all of string, up to null at end. + * + *---------------------------------------------------------------------- + */ +char *spice_dstring_append(SPICE_DSTRINGPTR dsPtr,char *string,int length) +{ + int newSize ; /* needed size */ + char *newString ; /* newly allocated string buffer */ + char *dst ; /* destination */ + char *end ; /* end of string */ + + if( length < 0){ + length = strlen(string) ; + } + newSize = length + dsPtr->length ; + + /* ----------------------------------------------------------------- + * Allocate a larger buffer for the string if the current one isn't + * large enough. Allocate extra space in the new buffer so that there + * will be room to grow before we have to allocate again. + ----------------------------------------------------------------- */ + if (newSize >= dsPtr->spaceAvl) { + dsPtr->spaceAvl = 2 * newSize ; + newString = tmalloc( dsPtr->spaceAvl * sizeof(char) ) ; + memcpy((void *) newString, (void *) dsPtr->string, (size_t) dsPtr->length) ; + if (dsPtr->string != dsPtr->staticSpace) { + txfree(dsPtr->string) ; + } + dsPtr->string = newString; + } + + /* ----------------------------------------------------------------- + * Copy the new string into the buffer at the end of the old + * one. + ----------------------------------------------------------------- */ + for( dst = dsPtr->string + dsPtr->length, end = string+length; + string < end; string++, dst++) { + *dst = *string ; + } + *dst = EOS ; + dsPtr->length += length ; + + return(dsPtr->string) ; + +} /* end spice_dstring_append() */ + +/* ----------------------------------------------------------------- + * Function: add character c to dynamic string dstr_p. + * ----------------------------------------------------------------- */ +char *spice_dstring_append_char( SPICE_DSTRINGPTR dstr_p, char c) +{ + char tmp_str[2] ; /* temporary string for append */ + char *val_p ; /* return value */ + + tmp_str[0] = c ; + tmp_str[1] = EOS ; + val_p = spice_dstring_append( dstr_p, tmp_str, -1 ) ; + return(val_p) ; +} /* end spice_dstring_append_char() */ + +static int spice_format_length( va_list args, char *fmt ) +{ + int i ; /* integer */ + int len ; /* length of format */ + int size_format ; /* width of field */ + int found_special ; /* look for special characters */ + char *s ; /* string */ + char c ; /* character */ + + /* ----------------------------------------------------------------- + * First find length of buffer. + ----------------------------------------------------------------- */ + len = 0 ; + while(fmt && *fmt){ + if( *fmt == '%' ){ + fmt++ ; + if( *fmt == '%' ){ + len++ ; + } else { + /* ----------------------------------------------------------------- + * We have a real formatting character, loop until we get a special + * character. + ----------------------------------------------------------------- */ + if( *fmt == '.' || *fmt == '-' ){ + fmt++ ; /* skip over these characters */ + } + size_format = atoi(fmt) ; + if( size_format > 0 ){ + len += size_format ; + } + found_special = FALSE ; + for( ; fmt && *fmt ; fmt++ ){ + switch( *fmt ){ + case 's': + s = va_arg(args, char *) ; + if( s ){ + len += strlen(s) ; + } + found_special = TRUE ; + break ; + case 'i': + case 'd': + case 'o': + case 'x': + case 'X': + case 'u': + i = va_arg(args, int) ; + len += 10 ; + found_special = TRUE ; + break ; + case 'c': + c = va_arg(args, int) ; + len++ ; + found_special = TRUE ; + break ; + case 'f': + case 'e': + case 'F': + case 'g': + case 'G': + c = va_arg(args, double) ; + len += 35 ; + found_special = TRUE ; + break ; + default: + ; + } /* end switch() */ + + if( found_special ){ + break ; + } + } + } + } else { + len++ ; + } + fmt++ ; + } /* end while() */ + va_end(args) ; + + return(len) ; + +} /* end Ymessage_format_length() */ + + +char *spice_dstring_print( SPICE_DSTRINGPTR dsPtr,char *format, ... ) +{ + va_list args ; + int format_len ; /* length of format */ + int length ; /* new length */ + int orig_length ; /* original length of buffer */ + char *buffer ; /* proper length of buffer */ + + /* ----------------------------------------------------------------- + * First get the length of the buffer needed. + ----------------------------------------------------------------- */ + va_start( args, format ) ; + format_len = spice_format_length(args,format) ; + + /* ----------------------------------------------------------------- + * Next allocate the proper buffer size. + ----------------------------------------------------------------- */ + orig_length = dsPtr->length ; + length = orig_length + format_len + 1 ; + buffer = spice_dstring_setlength( dsPtr, length) ; + + /* ----------------------------------------------------------------- + * Convert the format. + ----------------------------------------------------------------- */ + va_start( args, format ) ; + if( format ){ + vsprintf( buffer + orig_length, format, args ) ; + dsPtr->length = strlen( buffer ) ; + } else { + buffer = NULL ; + } + va_end(args) ; + return( buffer ) ; + +} /* end spice_dstring_print() */ + +/* + *---------------------------------------------------------------------- + * + * _spice_dstring_setlength -- + * + * Change the length of a dynamic string. This can cause the + * string to either grow or shrink, depending on the value of + * length. + * + * Results: + * Returns the current string buffer. + * + * Side effects: + * The length of dsPtr is changed to length but a null byte is not + * stored at that position in the string. Use spice_dstring_setlength + * for that function. If length is larger + * than the space allocated for dsPtr, then a panic occurs. + * + *---------------------------------------------------------------------- + */ + +char *_spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) +{ + char *newString ; + + if (length < 0) { + length = 0 ; + } + if (length >= dsPtr->spaceAvl) { + + dsPtr->spaceAvl = length+1; + newString = tmalloc( dsPtr->spaceAvl * sizeof(char) ) ; + /* ----------------------------------------------------------------- + * SPECIAL NOTE: must use memcpy, not strcpy, to copy the string + * to a larger buffer, since there may be embedded NULLs in the + * string in some cases. + ----------------------------------------------------------------- */ + memcpy((void *) newString, (void *) dsPtr->string, (size_t) dsPtr->length) ; + if( dsPtr->string != dsPtr->staticSpace ) { + txfree(dsPtr->string) ; + } + dsPtr->string = newString ; + } + dsPtr->length = length ; + return(dsPtr->string) ; + +} /* end _spice_dstring_setlength() */ + + +/* + *---------------------------------------------------------------------- + * + * spice_dstring_setlength -- + * + * Change the length of a dynamic string. This can cause the + * string to either grow or shrink, depending on the value of + * length. + * + * Results: + * Returns the current string buffer. + * + * Side effects: + * The length of dsPtr is changed to length and a null byte is + * stored at that position in the string. If length is larger + * than the space allocated for dsPtr, then a panic occurs. + * + *---------------------------------------------------------------------- + */ + +char *spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length) +{ + char *str_p ; /* newly create string */ + + str_p = _spice_dstring_setlength( dsPtr,length) ; + str_p[length] = EOS ; + return( str_p ) ; + +} /* end spice_dstring_setlength() */ + +/* + *---------------------------------------------------------------------- + * + * spice_dstring_free -- + * + * Frees up any memory allocated for the dynamic string and + * reinitializes the string to an empty state. + * + * Results: + * None. + * + * Side effects: + * The previous contents of the dynamic string are lost, and + * the new value is an empty string. + * + *---------------------------------------------------------------------- + */ + +void spice_dstring_free(SPICE_DSTRINGPTR dsPtr) +{ + if (dsPtr->string != dsPtr->staticSpace) { + txfree(dsPtr->string) ; + } + dsPtr->string = dsPtr->staticSpace ; + dsPtr->length = 0 ; + dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE; + dsPtr->staticSpace[0] = EOS ; + +} /* end spice_dstring_free() */ diff --git a/src/misc/hash.c b/src/misc/hash.c index 3eadd50bf..9b6205fa9 100644 --- a/src/misc/hash.c +++ b/src/misc/hash.c @@ -138,7 +138,7 @@ NGHASHPTR nghash_init_pointer(int num_entries) return( nghash_init_with_parms( NGHASH_DEF_CMP_PTR, NGHASH_DEF_HASH_PTR, num_entries, NGHASH_DEF_MAX_DENSITY, NGHASH_DEF_GROW_FACTOR, - NGHASH_UNIQUE|NGHASH_POWER_OF_TWO) ) ; + NGHASH_UNIQUE_TWO) ) ; } /* end nghash_init_pointer() */ NGHASHPTR nghash_init_integer(int num_entries) @@ -146,7 +146,7 @@ NGHASHPTR nghash_init_integer(int num_entries) return( nghash_init_with_parms( NGHASH_DEF_CMP_NUM, NGHASH_DEF_HASH_NUM, num_entries, NGHASH_DEF_MAX_DENSITY, NGHASH_DEF_GROW_FACTOR, - NGHASH_UNIQUE|NGHASH_POWER_OF_TWO) ) ; + NGHASH_UNIQUE_TWO) ) ; } /* end nghash_init_integer() */ int nghash_table_get(NGHASHPTR hashtable) @@ -166,20 +166,10 @@ int nghash_max_density(NGHASHPTR hashtable,int max_density) void nghash_empty(NGHASHPTR hashtable, void (*delete_data) (void *), void (*delete_key) (void *)) { - long old_size ; /* old size of hash table */ - long new_size ; /* new size of hash table */ NGTABLEPTR *table, hptr , zapptr ; nghash_reset_stat(hashtable); - old_size = MAX( NGHASH_MIN_SIZE, hashtable->num_entries ) ; - if( hashtable->power_of_two ){ - new_size = nghash_table_size2( old_size ) ; - } else { - /* prime size */ - new_size = nghash_table_size( old_size ) ; - } - table = hashtable->hash_table ; if( table ){ for( hptr = hashtable->thread ; hptr ; ){ @@ -316,10 +306,8 @@ void * _nghash_find_again(NGHASHPTR hashtable, void * user_key,BOOL *status) int ret_code ; /* comparison return code */ NGTABLEPTR curPtr ; /* current hashtable entry */ COMPARE_FUNC compare_func ; /* user defined comparison function */ - NGTABLEPTR *table ; /* hash table array */ /* initialization */ - table = hashtable->hash_table ; DS(hashtable->access++;) ; if( hashtable->searchPtr ){ diff --git a/src/misc/string.c b/src/misc/string.c index 739711ba2..afe4268e0 100644 --- a/src/misc/string.c +++ b/src/misc/string.c @@ -8,6 +8,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. #include "ngspice.h" #include "stringutil.h" +#include "dstring.h" int prefix(register char *p, register char *s) @@ -195,16 +196,17 @@ register char *p, register char *s) char * gettok(char **s) { - char buf[BSIZE_SP]; - int i = 0; char c; int paren; + char *token ; /* return token */ + SPICE_DSTRING buf ; /* allow any length string */ paren = 0; while (isspace(**s)) (*s)++; if (!**s) return (NULL); + spice_dstring_init(&buf) ; while ((c = **s) && !isspace(c)) { if (c == '('/*)*/) paren += 1; @@ -212,12 +214,13 @@ gettok(char **s) paren -= 1; else if (c == ',' && paren < 1) break; - buf[i++] = *(*s)++; + spice_dstring_append_char( &buf, *(*s)++ ) ; } - buf[i] = '\0'; while (isspace(**s) || **s == ',') (*s)++; - return (copy(buf)); + token = copy( spice_dstring_value(&buf) ) ; + spice_dstring_free(&buf) ; + return ( token ) ; } /*-------------------------------------------------------------------------* @@ -230,9 +233,9 @@ gettok(char **s) char * gettok_noparens(char **s) { - char buf[BSIZE_SP]; - int i = 0; char c; + char *token ; /* return token */ + SPICE_DSTRING buf ; /* allow any length string */ while ( isspace(**s) ) (*s)++; /* iterate over whitespace */ @@ -240,29 +243,31 @@ gettok_noparens(char **s) if (!**s) return (NULL); /* return NULL if we come to end of line */ + spice_dstring_init(&buf) ; while ((c = **s) && !isspace(c) && ( **s != '(' ) && ( **s != ')' ) && ( **s != ',') ) { - buf[i++] = *(*s)++; + spice_dstring_append_char( &buf, *(*s)++ ) ; } - buf[i] = '\0'; /* Now iterate up to next non-whitespace char */ while ( isspace(**s) ) (*s)++; - return (copy(buf)); + token = copy( spice_dstring_value(&buf) ) ; + spice_dstring_free(&buf) ; + return ( token ) ; } char * gettok_instance(char **s) { - char buf[BSIZE_SP]; - int i = 0; char c; + char *token ; /* return token */ + SPICE_DSTRING buf ; /* allow any length string */ while ( isspace(**s) ) (*s)++; /* iterate over whitespace */ @@ -270,20 +275,22 @@ gettok_instance(char **s) if (!**s) return (NULL); /* return NULL if we come to end of line */ + spice_dstring_init(&buf) ; while ((c = **s) && !isspace(c) && ( **s != '(' ) && ( **s != ')' ) ) { - buf[i++] = *(*s)++; + spice_dstring_append_char( &buf, *(*s)++ ) ; } - buf[i] = '\0'; /* Now iterate up to next non-whitespace char */ while ( isspace(**s) ) (*s)++; - return (copy(buf)); + token = copy( spice_dstring_value(&buf) ) ; + spice_dstring_free(&buf) ; + return ( token ) ; } /*-------------------------------------------------------------------------* @@ -295,9 +302,9 @@ gettok_instance(char **s) char * gettok_node(char **s) { - char buf[BSIZE_SP]; - int i = 0; char c; + char *token ; /* return token */ + SPICE_DSTRING buf ; /* allow any length string */ while (isspace(**s) || ( **s == '(' ) || @@ -309,15 +316,15 @@ gettok_node(char **s) if (!**s) return (NULL); /* return NULL if we come to end of line */ + spice_dstring_init(&buf) ; while ((c = **s) && !isspace(c) && ( **s != '(' ) && ( **s != ')' ) && ( **s != ',') ) { /* collect chars until whitespace or ( , ) */ - buf[i++] = *(*s)++; + spice_dstring_append_char( &buf, *(*s)++ ) ; } - buf[i] = '\0'; /* Now iterate up to next non-whitespace char */ while (isspace(**s) || @@ -327,7 +334,9 @@ gettok_node(char **s) ) (*s)++; /* iterate over whitespace and ( , ) */ - return (copy(buf)); + token = copy( spice_dstring_value(&buf) ) ; + spice_dstring_free(&buf) ; + return ( token ) ; } /*-------------------------------------------------------------------------* @@ -383,26 +392,29 @@ get_r_paren(char **s) char * stripWhiteSpacesInsideParens(char *str) { - char buf[BSIZE_SP]; - int i = 0, j = 0; + char *token ; /* return token */ + SPICE_DSTRING buf ; /* allow any length string */ + int i = 0 ; /* index into string */ while ( (str[i] == ' ') || (str[i] == '\t') ) i++; + spice_dstring_init(&buf) ; for(i=i; str[i]!='\0'; i++) { if ( str[i] != '(' ) { - buf[j++] = str[i]; + spice_dstring_append_char( &buf, str[i] ) ; } else { - buf[j++] = str[i]; + spice_dstring_append_char( &buf, str[i] ) ; while ( (str[i++] != ')') ) { - if ( str[i] != ' ' ) buf[j++] = str[i]; + if ( str[i] != ' ' ) spice_dstring_append_char( &buf, str[i] ) ; } i--; } } - buf[j] = '\0'; - return copy(buf); + token = copy( spice_dstring_value(&buf) ) ; + spice_dstring_free(&buf) ; + return ( token ) ; } @@ -477,4 +489,3 @@ get_comma_separated_values( char *values[], char *str ) { values[count++] = strdup(str); return count; } - diff --git a/src/spicelib/analysis/cktop.c b/src/spicelib/analysis/cktop.c index 2862914bf..a3215dd22 100644 --- a/src/spicelib/analysis/cktop.c +++ b/src/spicelib/analysis/cktop.c @@ -419,7 +419,7 @@ gillespie_src (CKTcircuit * ckt, long int firstmode, /* First, try a straight solution with all sources at zero */ - fprintf (stderr, "\rSupplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); + fprintf (stderr, "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter); /* If this doesn't work, try gmin stepping as well for the first solution */ @@ -490,7 +490,7 @@ gillespie_src (CKTcircuit * ckt, long int firstmode, if (converged == 0) do { fprintf (stderr, - "\rSupplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); + "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100); iters = ckt->CKTstat->STATnumIter; diff --git a/visualc/vngspice.sln b/visualc/vngspice.sln index ae8bcc66a..c47acb3c9 100644 --- a/visualc/vngspice.sln +++ b/visualc/vngspice.sln @@ -1,47 +1,47 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vngspice", "vngspice.vcproj", "{83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - console_debug|Win32 = console_debug|Win32 - console_debug|x64 = console_debug|x64 - console_release|Win32 = console_release|Win32 - console_release|x64 = console_release|x64 - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - release64|Win32 = release64|Win32 - release64|x64 = release64|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|Win32.ActiveCfg = console_debug|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|Win32.Build.0 = console_debug|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|x64.ActiveCfg = console_debug|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|x64.Build.0 = console_debug|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|Win32.ActiveCfg = console_release|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|Win32.Build.0 = console_release|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|x64.ActiveCfg = console_release|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|x64.Build.0 = console_release|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|Win32.ActiveCfg = Debug|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|Win32.Build.0 = Debug|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|x64.ActiveCfg = Debug|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|x64.Build.0 = Debug|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.ActiveCfg = Debug|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.Build.0 = Debug|Win32 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|x64.ActiveCfg = Release|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|x64.Build.0 = Release|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.ActiveCfg = release64|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.Build.0 = release64|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|x64.ActiveCfg = release64|x64 - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|x64.Build.0 = release64|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - AMDCaProjectFile = D:\Spice_general\ng-spice-rework\visualc\CodeAnalyst\vngspice.caw - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vngspice", "vngspice.vcproj", "{83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + console_debug|Win32 = console_debug|Win32 + console_debug|x64 = console_debug|x64 + console_release|Win32 = console_release|Win32 + console_release|x64 = console_release|x64 + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + release64|Win32 = release64|Win32 + release64|x64 = release64|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|Win32.ActiveCfg = console_debug|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|Win32.Build.0 = console_debug|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|x64.ActiveCfg = console_debug|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_debug|x64.Build.0 = console_debug|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|Win32.ActiveCfg = console_release|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|Win32.Build.0 = console_release|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|x64.ActiveCfg = console_release|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.console_release|x64.Build.0 = console_release|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|Win32.ActiveCfg = Debug|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|Win32.Build.0 = Debug|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|x64.ActiveCfg = Debug|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Debug|x64.Build.0 = Debug|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.ActiveCfg = Release|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|Win32.Build.0 = Release|Win32 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|x64.ActiveCfg = Release|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.Release|x64.Build.0 = Release|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.ActiveCfg = release64|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|Win32.Build.0 = release64|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|x64.ActiveCfg = release64|x64 + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A}.release64|x64.Build.0 = release64|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + AMDCaProjectFile = D:\Spice_general\ng-spice-rework\visualc\CodeAnalyst\vngspice.caw + EndGlobalSection +EndGlobal