diff --git a/compile_linux.sh b/compile_linux.sh index ffa32a27b..5634c5f36 100644 --- a/compile_linux.sh +++ b/compile_linux.sh @@ -19,10 +19,10 @@ # Add (optionally) --enable-relpath to avoid absolute paths when searching for code models. # It might be necessary to uncomment and run ./autogen.sh . -if test "$1" = "64"; then - if [ ! -d "release64" ]; then - mkdir release64 - if [ $? -ne 0 ]; then echo "mkdir release64 failed"; exit 1 ; fi +if test "$1" = "32"; then + if [ ! -d "release32" ]; then + mkdir release32 + if [ $? -ne 0 ]; then echo "mkdir release32 failed"; exit 1 ; fi fi else if [ ! -d "release" ]; then @@ -42,20 +42,20 @@ if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi #if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi echo -if test "$1" = "64"; then - cd release64 - if [ $? -ne 0 ]; then echo "cd release64 failed"; exit 1 ; fi - echo "configuring for 64 bit" - echo -# You may add --enable-adms to the following command for adding adms generated devices - ../configure --with-x --enable-xspice --enable-cider --with-readline=yes --enable-openmp --disable-debug CFLAGS="-m64 -O2" LDFLAGS="-m64 -s" -else - cd release - if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi +if test "$1" = "32"; then + cd release32 + if [ $? -ne 0 ]; then echo "cd release32 failed"; exit 1 ; fi echo "configuring for 32 bit" echo # You may add --enable-adms to the following command for adding adms generated devices ../configure --with-x --enable-xspice --enable-cider --with-readline=yes --enable-openmp --disable-debug CFLAGS="-m32 -O2" LDFLAGS="-m32 -s" +else + cd release + if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi + echo "configuring for 64 bit" + echo +# You may add --enable-adms to the following command for adding adms generated devices + ../configure --with-x --enable-xspice --enable-cider --with-readline=yes --enable-openmp --disable-debug CFLAGS="-m64 -O2" LDFLAGS="-m64 -s" fi if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi diff --git a/compile_min.sh b/compile_min.sh index f215de448..fdf26a6e2 100755 --- a/compile_min.sh +++ b/compile_min.sh @@ -9,7 +9,7 @@ # (allows to generate either 32 or 64 bit executables by setting flag -m32 or -m64) # set path to compiler in msys/xx/etc/fstab (e.g. c:/MinGW64 /mingw) # start compiling with -# './compile_min.sh' or './compile_min.sh 64' +# './compile_min.sh 32' or './compile_min.sh' # As an (more recent) alternative install MSYS2 and the tools cited above. # Options: @@ -25,10 +25,10 @@ # Add (optionally) --enable-relpath to avoid absolute paths when searching for code models. # It might be necessary to uncomment and run ./autogen.sh . -if test "$1" = "64"; then - if [ ! -d "release64" ]; then - mkdir release64 - if [ $? -ne 0 ]; then echo "mkdir release64 failed"; exit 1 ; fi +if test "$1" = "32"; then + if [ ! -d "release32" ]; then + mkdir release32 + if [ $? -ne 0 ]; then echo "mkdir release32 failed"; exit 1 ; fi fi else if [ ! -d "release" ]; then @@ -48,20 +48,20 @@ fi #if [ $? -ne 0 ]; then echo "./autogen.sh failed"; exit 1 ; fi echo -if test "$1" = "64"; then - cd release64 - if [ $? -ne 0 ]; then echo "cd release64 failed"; exit 1 ; fi - echo "configuring for 64 bit" - echo -# You may add --enable-adms to the following command for adding adms generated devices - ../configure --with-wingui --enable-xspice --enable-cider --enable-openmp --disable-debug prefix="C:/Spice64" CFLAGS="-m64 -O2" LDFLAGS="-m64 -s" -else - cd release - if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi +if test "$1" = "32"; then + cd release32 + if [ $? -ne 0 ]; then echo "cd release32 failed"; exit 1 ; fi echo "configuring for 32 bit" echo # You may add --enable-adms to the following command for adding adms generated devices ../configure --with-wingui --enable-xspice --enable-cider --enable-openmp --disable-debug prefix="C:/Spice" CFLAGS="-m32 -O2" LDFLAGS="-m32 -s" +else + cd release + if [ $? -ne 0 ]; then echo "cd release failed"; exit 1 ; fi + echo "configuring for 64 bit" + echo +# You may add --enable-adms to the following command for adding adms generated devices + ../configure --with-wingui --enable-xspice --enable-cider --enable-openmp --disable-debug prefix="C:/Spice64" CFLAGS="-m64 -O2" LDFLAGS="-m64 -s" fi if [ $? -ne 0 ]; then echo "../configure failed"; exit 1 ; fi diff --git a/configure.ac b/configure.ac index d73fe1b39..c969c1603 100644 --- a/configure.ac +++ b/configure.ac @@ -220,7 +220,7 @@ if test "x$ext_CFLAGS" != xyes; then else AC_DEFINE([NGDEBUG], [1], [Compile with debug info]) if test "x$GCC" = xyes; then - CFLAGS="-g -O1" + CFLAGS="-g -O0" else CFLAGS="-g" fi diff --git a/examples/p-to-n-examples/logic.cir b/examples/p-to-n-examples/logic.cir new file mode 100644 index 000000000..7a68b2bdf --- /dev/null +++ b/examples/p-to-n-examples/logic.cir @@ -0,0 +1,15 @@ +logic test, PSPICE +* requires 'set ngbehavior=psa' + +v8 8 0 1 Pulse (0 1 0.45 1m 1m 5 10) +v9 9 0 0 + +B1 1 0 V=~(~v(9)&v(8)) + 0.5 + +.control +tran 1m 1 +plot v(1) v(8) v(9) +listing +.endc + +.end diff --git a/examples/xspice/pll/pll-xspice-fstep.cir b/examples/xspice/pll/pll-xspice-fstep.cir index 4f86fe9d9..d66a96061 100644 --- a/examples/xspice/pll/pll-xspice-fstep.cir +++ b/examples/xspice/pll/pll-xspice-fstep.cir @@ -17,7 +17,7 @@ vdd dd 0 dc 'vcc' * 10 MHz reference frequency * PULSE(V1 V2 TD TR TF PW PER) -vref ref 0 dc 0 pulse(0 'vcc' 10n 1n 1n '1/fref/2' '1/fref') +vref ref 0 dc 0 pulse(0 'vcc' 10n 2n 2n '1/fref/2' '1/fref') abridgeref [ref] [d_ref] adc_vbuf .model adc_vbuf adc_bridge(in_low = 0.5 in_high = 0.5) @@ -66,7 +66,10 @@ abridge-w1 [d_divout d_ref d_Un d_D] [s1 s2 u1 d1] dac1 ; change to d_u or d_Un .control save cont s1 s2 u1 d1 -iplot cont +let isbmode = $?batchmode +if isbmode = 0 + iplot cont +endif * calculate breakpoint for switching frequency let t1_3 = simtime/3 set ti1_3 ="$&t1_3" @@ -80,7 +83,7 @@ let pw2 = per2/2 let per3=1/f3 let pw3 = per3/2 *simulate -tran 0.1n $&simtime 0 0.5n uic +tran 10n $&simtime 0 1n uic *change frequency after stopping * first pair of [] without spaces, second pair with spaces alter @vref[pulse] = [ 0 3.3 10n 1n 1n $&pw2 $&per2 ] @@ -89,8 +92,11 @@ resume alter @vref[pulse] = [ 0 3.3 10n 1n 1n $&pw3 $&per3 ] resume rusage -plot cont s1 s2+1.2 u1+2.4 d1+3.6 xlimit 15u 16u -*plot cont +if isbmode = 0 + plot cont s1 s2+1.2 u1+2.4 d1+3.6 xlimit 15u 16u +else + write pll.raw all +endif .endc *model = bsim3v3 diff --git a/examples/xspice/table/table-generator-b4-2d.sp b/examples/xspice/table/table-generator-b4-2d.sp index 6b4c42a6b..4b0ccd371 100644 --- a/examples/xspice/table/table-generator-b4-2d.sp +++ b/examples/xspice/table/table-generator-b4-2d.sp @@ -12,6 +12,13 @@ * These tables will contain pure dc data. For transient simulation you may * need to add some capacitors to the device model for a 'real world' simulation. +* In case the script is called with existing DC* plots, must free up everyting +* or the plot created will not be DC1, which will cause the later destroy +* in the loop to remove the wrong one, and a new data sets will be added +* at each loop iteration. Also the control variables like loopy will be hidden +* in another plot. +destroy all + *NMOS *.csparam vdstart=-0.1 *.csparam vdstop=1.8 @@ -88,6 +95,9 @@ while lcy < ycount * end let xvec = i(vss) echo $&xvec >> $outfile + +* Free the plot data that was just created. Then the name dc1 will be used +* again. destroy dc1 let loopy = loopy + vgstep let lcy = lcy + 1 diff --git a/src/frontend/com_measure2.c b/src/frontend/com_measure2.c index 5346cf7c9..6c91fedcc 100644 --- a/src/frontend/com_measure2.c +++ b/src/frontend/com_measure2.c @@ -1151,7 +1151,7 @@ measure_parse_stdParams( ) { int pCnt; - char *p, *pName, *pValue; + char *p, *pName = NULL, *pValue; double engVal1; pCnt = 0; @@ -1169,7 +1169,7 @@ measure_parse_stdParams( wl = wl->wl_next; continue; } else { - sprintf(errbuf, "bad syntax of ??\n"); + sprintf(errbuf, "bad syntax. equal sign missing ?\n"); return 0; } } @@ -1179,7 +1179,8 @@ measure_parse_stdParams( } else { if (ft_numparse(&pValue, FALSE, &engVal1) < 0) { - sprintf(errbuf, "bad syntax of ??\n"); + sprintf(errbuf, "bad syntax, cannot evaluate right hand side " + "of %s=%s\n", pName, pValue); return 0; } } @@ -1216,7 +1217,10 @@ measure_parse_stdParams( } if (pCnt == 0) { - sprintf(errbuf, "bad syntax of ??\n"); + if (pName) + sprintf(errbuf, "bad syntax of %s\n", pName); + else + sprintf(errbuf, "bad syntax of\n"); return 0; } @@ -1477,6 +1481,7 @@ get_measure2( ) { wordlist *words, *wlTarg, *wlWhen; +///XXX TODO -- errbuf can be overrun -- convert to dstring char errbuf[100]; char *mAnalysis = NULL; // analysis type char *mName = NULL; // name given to the measured output diff --git a/src/frontend/com_sysinfo.c b/src/frontend/com_sysinfo.c index 8d1f817c0..570b8fe59 100644 --- a/src/frontend/com_sysinfo.c +++ b/src/frontend/com_sysinfo.c @@ -492,7 +492,7 @@ static int registry_value_to_ds(const char *sz_subkey, size_t n_byte_reserve = (size_t) n_byte_data + 1; if (ds_reserve(p_ds, n_byte_reserve) != 0) { (void) fprintf(cp_err, - "Unable to reserve a buffer of %u bytes for data.\n", + "Unable to reserve a buffer of %zu bytes for data.\n", n_byte_reserve); xrc = -1; goto EXITPOINT; @@ -924,7 +924,8 @@ static void get_physical_processor_count(void) /* Allocate buffer to get the info */ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX * const buf = - (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *) malloc(n_byte_buf); + (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *) TMALLOC( + char, n_byte_buf); if (buf == (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *) NULL) { fprintf(cp_err, "Unable to allocate a buffer of %lu bytes " diff --git a/src/frontend/display.c b/src/frontend/display.c index faf14f1ec..0faa71b27 100644 --- a/src/frontend/display.c +++ b/src/frontend/display.c @@ -119,7 +119,7 @@ DISPDEVICE device[] = { (disp_fn_Track_t *) nodev, (disp_fn_MakeMenu_t *) nodev, (disp_fn_MakeDialog_t *) nodev, (disp_fn_Input_t *) nodev, gen_DatatoScreen, }, - { "printf", 0, 0, 24, 80, 0, 0, + { "PrinterOnly", 0, 0, 24, 80, 0, 0, (disp_fn_Init_t *) nodev, (disp_fn_NewViewport_t *) nodev, (disp_fn_Close_t *) nop, (disp_fn_Clear_t *) nodev, (disp_fn_DrawLine_t *) nodev, (disp_fn_Arc_t *) nodev, (disp_fn_Text_t *) nodev, diff --git a/src/frontend/dvec.c b/src/frontend/dvec.c index 5bc7b5df6..e574e35d0 100644 --- a/src/frontend/dvec.c +++ b/src/frontend/dvec.c @@ -2,7 +2,8 @@ #include "ngspice/dvec.h" -struct dvec *dvec_alloc(/* NOT const -- assigned to char */ char *name, +struct dvec *dvec_alloc( + /* not const -- given to non-const struct */ char *name, int type, short flags, int length, void *storage) { struct dvec * const rv = TMALLOC(struct dvec, 1); diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 74ab6bceb..35d77c475 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -86,7 +86,7 @@ struct function_env char *body; char *params[N_PARAMS]; int num_parameters; - const char *accept; + char *accept; } *functions; }; @@ -7518,7 +7518,7 @@ static struct card *pspice_compat(struct card *oldcard) } } - /* replace & with && and | with || and *# with * # */ + /* replace & with && , | with || , *# with * # , and ~ with ! */ for (card = newcard; card; card = card->nextcard) { char *t; char *cut_line = card->line; @@ -7581,6 +7581,18 @@ static struct card *pspice_compat(struct card *oldcard) t = strstr(tt, "|"); } } + /* We may have '~' in path names or A devices */ + char *firsttok = nexttok(card->line); /* skip over whitespaces */ + if (ciprefix(".inc", firsttok) || ciprefix(".lib", firsttok) || + ciprefix("A", firsttok)) + continue; + + if ((t = strstr(card->line, "~")) != NULL) { + while (t) { + *t = '!'; + t = strstr(t, "~"); + } + } } /* replace T_ABS by temp, T_REL_GLOBAL by dtemp, and T_MEASURED by TNOM diff --git a/src/frontend/measure.c b/src/frontend/measure.c index 603b2d0af..05727a6cb 100644 --- a/src/frontend/measure.c +++ b/src/frontend/measure.c @@ -67,6 +67,12 @@ com_meas(wordlist *wl) May be in the next wl_word */ if (token[strlen(token) - 1] == '=') { wl_index = wl_index->wl_next; + if (wl_index == NULL) { + line_in = wl_flatten(wl); + fprintf(stderr, "\nError: meas failed due to missing token in \n meas %s \n\n", line_in); + tfree(line_in); + return; + } vec_found = wl_index->wl_word; /* token may be already a value, maybe 'LAST', which we have to keep, or maybe a vector */ if (!cieq(vec_found, "LAST")) { diff --git a/src/frontend/misccoms.c b/src/frontend/misccoms.c index 6d306f964..40f35ede9 100644 --- a/src/frontend/misccoms.c +++ b/src/frontend/misccoms.c @@ -38,6 +38,7 @@ extern void rem_controls(void); extern IFsimulator SIMinfo; extern void spice_destroy_devices(void); /* FIXME need a better place */ +extern void pl_rempar(void); /* plotit.c */ static void byemesg(void); static int confirm_quit(void); @@ -56,6 +57,7 @@ com_quit(wordlist *wl) gr_clean(); cp_ccon(FALSE); + /* Make sure the guy really wants to quit. */ if (!ft_nutmeg) if (!noask && !confirm_quit()) @@ -90,6 +92,9 @@ com_quit(wordlist *wl) cp_destroy_keywords(); destroy_ivars(); #else + /* remove plotting parameters */ + pl_rempar(); + while (ft_curckt) com_remcirc(NULL); #endif diff --git a/src/frontend/parse-bison.y b/src/frontend/parse-bison.y index bc3b55af9..e765b0aa1 100644 --- a/src/frontend/parse-bison.y +++ b/src/frontend/parse-bison.y @@ -123,7 +123,7 @@ one_exp: exp: TOK_NUM { $$ = PP_mknnode($1); } - | TOK_STR { $$ = PP_mksnode($1); txfree($1); } + | TOK_STR { $$ = PP_mksnode($1); txfree((void *) $1); } | exp ',' exp { $$ = PP_mkbnode(PT_OP_COMMA, $1, $3); } | exp '+' exp { $$ = PP_mkbnode(PT_OP_PLUS, $1, $3); } @@ -139,7 +139,7 @@ exp: | '~' exp { $$ = PP_mkunode(PT_OP_NOT, $2); } | TOK_STR '(' exp ')' { $$ = PP_mkfnode($1, $3); - txfree($1); + txfree((void *) $1); if(!$$) YYABORT; } diff --git a/src/frontend/plotting/plotit.c b/src/frontend/plotting/plotit.c index ba3c1039d..db54545eb 100644 --- a/src/frontend/plotting/plotit.c +++ b/src/frontend/plotting/plotit.c @@ -18,11 +18,36 @@ #include "graf.h" static bool sameflag; - +/* All these things are static so that "samep" will work. + They are outside of plotit() to allow deleting */ +static double *xcompress = NULL, *xindices = NULL; +static double *xlim = NULL, *ylim = NULL; +static double *xdelta = NULL, *ydelta = NULL; +static char *xlabel = NULL, *ylabel = NULL, *title = NULL; #ifdef TCL_MODULE #include "ngspice/tclspice.h" #endif +/* remove the malloced parameters upon ngspice quit */ +void pl_rempar(void) +{ + txfree(xcompress); + txfree(xindices); + txfree(xlim); + txfree(ylim); + txfree(xdelta); + txfree(ydelta); + txfree(xlabel); + txfree(ylabel); +} + +static struct dvec *vec_self(struct dvec *v); +static struct dvec *vec_scale(struct dvec *v); +static void find_axis_limits(double *lim, bool oneval, bool f_real, + struct dvec *vecs, + struct dvec *(*p_get_axis_dvec)(struct dvec *dvec), + double *lims); + static struct dvec *vec_self(struct dvec *v); static struct dvec *vec_scale(struct dvec *v); @@ -258,11 +283,6 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) return FALSE; } - /* All these things are static so that "samep" will work. */ - static double *xcompress = NULL, *xindices = NULL; - static double *xlim = NULL, *ylim = NULL; - static double *xdelta = NULL, *ydelta = NULL; - static char *xlabel = NULL, *ylabel = NULL, *title = NULL; static bool nointerp = FALSE; static GRIDTYPE gtype = GRID_LIN; static PLOTTYPE ptype = PLOT_LIN; @@ -317,7 +337,11 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) /* Build the plot command. This construction had been done with wordlists * and reversing, and flattening, but it is clearer as well as much more * efficient to use a dstring. */ - rc_ds |= ds_cat_printf(&ds_cline, "plot %s", wl_flatten(wwl->wl_next)); + { + char * const flatstr = wl_flatten(wwl->wl_next); + rc_ds |= ds_cat_printf(&ds_cline, "plot %s", flatstr); + txfree(flatstr); + } wl_free(wwl); /* Add title, xlabel or ylabel, if available, with quotes ''. */ @@ -343,6 +367,7 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) sameflag = getflag(wl, "samep"); if (!sameflag || !xlim) { + txfree(xlim); xlim = getlims(wl, "xl", 2); if (!xlim) { xlim = getlims(wl, "xlimit", 2); @@ -354,6 +379,7 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) } if (!sameflag || !ylim) { + txfree(ylim); ylim = getlims(wl, "yl", 2); if (!ylim) { ylim = getlims(wl, "ylimit", 2); @@ -365,6 +391,7 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) } if (!sameflag || !xcompress) { + txfree(xcompress); xcompress = getlims(wl, "xcompress", 1); if (!xcompress) { xcompress = getlims(wl, "xcomp", 1); @@ -376,6 +403,7 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) } if (!sameflag || !xindices) { + txfree(xindices); xindices = getlims(wl, "xindices", 2); if (!xindices) { xindices = getlims(wl, "xind", 2); @@ -387,6 +415,7 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) } if (!sameflag || !xdelta) { + txfree(xdelta); xdelta = getlims(wl, "xdelta", 1); if (!xdelta) { xdelta = getlims(wl, "xdel", 1); @@ -397,6 +426,7 @@ bool plotit(wordlist *wl, const char *hcopy, const char *devname) } if (!sameflag || !ydelta) { + txfree(ydelta); ydelta = getlims(wl, "ydelta", 1); if (!ydelta) { ydelta = getlims(wl, "ydel", 1); diff --git a/src/frontend/postsc.c b/src/frontend/postsc.c index a3145b027..857f71e68 100644 --- a/src/frontend/postsc.c +++ b/src/frontend/postsc.c @@ -173,7 +173,7 @@ int PS_NewViewport(GRAPH *graph) /* devdep initially contains name of output file */ if ((plotfile = fopen((char*)graph->devdep, "w")) == NULL) { perror((char *) graph->devdep); - free(graph->devdep); + txfree(graph->devdep); graph->devdep = NULL; graph->n_byte_devdep = 0; return 1; diff --git a/src/frontend/streams.c b/src/frontend/streams.c index e49a91a9b..6a84970b8 100644 --- a/src/frontend/streams.c +++ b/src/frontend/streams.c @@ -4,15 +4,15 @@ #include #include +#include "ngspice/bool.h" +#include "ngspice/cpextern.h" #include "ngspice/ngspice.h" #include "ngspice/wordlist.h" -#include "ngspice/bool.h" -#include "variable.h" -#include "terminal.h" #include "quote.h" -#include "ngspice/cpextern.h" #include "streams.h" +#include "terminal.h" +#include "variable.h" bool cp_debug = FALSE; diff --git a/src/include/ngspice/alloc.h b/src/include/ngspice/alloc.h new file mode 100644 index 000000000..ade5f7c56 --- /dev/null +++ b/src/include/ngspice/alloc.h @@ -0,0 +1,29 @@ +/************* + * Header file for alloc.c + * 1999 E. Rouat + ************/ + +#ifndef ngspice_ALLOC_H +#define ngspice_ALLOC_H + +#include + +void *tmalloc(size_t num); +void *tcalloc(size_t num, size_t size); +void *trealloc(void *ptr, size_t num); +void txfree(void *ptr); + +#ifdef HAVE_LIBGC +#include + +#define tmalloc_raw GC_malloc +#define tcalloc_raw GC_calloc +#define trealloc_raw GC_realloc + +#else +void *tmalloc_raw(size_t num); +void *tcalloc_raw(size_t num, size_t size); +void *trealloc_raw(void *ptr, size_t num); +#endif + +#endif /* include guard */ diff --git a/src/include/ngspice/cm.h b/src/include/ngspice/cm.h index 1f3854e3a..3f15a52b1 100644 --- a/src/include/ngspice/cm.h +++ b/src/include/ngspice/cm.h @@ -44,6 +44,7 @@ NON-STANDARD FEATURES #include "ngspice/cmconstants.h" #include "ngspice/cmproto.h" #include "ngspice/mifcmdat.h" +#include "ngspice/mifproto.h" #include diff --git a/src/include/ngspice/cmproto.h b/src/include/ngspice/cmproto.h index d29d91c0d..9138abe25 100644 --- a/src/include/ngspice/cmproto.h +++ b/src/include/ngspice/cmproto.h @@ -45,8 +45,8 @@ NON-STANDARD FEATURES /* The actual functions reside in ../ICM/CMutil.c */ /* 12/17/90 */ - #include + #include "ngspice/cmtypes.h" #include "ngspice/cktdefs.h" @@ -78,21 +78,11 @@ int cm_analog_set_temp_bkpt(double time); int cm_analog_set_perm_bkpt(double time); void cm_analog_not_converged(void); void cm_analog_auto_partial(void); - void cm_event_alloc(int tag, int bytes); void *cm_event_get_ptr(int tag, int timepoint); int cm_event_queue(double time); - char *cm_message_get_errmsg(void); -int cm_message_send(char *msg); - -#ifdef __GNUC__ -int cm_message_printf(const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2))); -#else -int cm_message_printf(const char *fmt, ...); -#endif - - +int cm_message_send(const char *msg); double cm_netlist_get_c(void); double cm_netlist_get_l(void); @@ -111,9 +101,29 @@ FILE *cm_stream_err(void); void *malloc_pj(size_t s); void *calloc_pj(size_t s1, size_t s2); -void *realloc_pj(const void *ptr, size_t s); -void free_pj(const void *ptr); +void *realloc_pj(void *ptr, size_t s); +void free_pj(void *ptr); +void *tmalloc(size_t s); +void *trealloc(void *ptr, size_t s); +void txfree(void *ptr); +const char *ngspice_version(void); +void *tmalloc_raw(size_t s); +void *tcalloc_raw(size_t n, size_t s); +void *trealloc_raw(void *ptr, size_t s); +char *tstrdup(const char *str_in); +char *tstrdup_raw(const char *str_in); FILE *fopen_with_path(const char *path, const char *mode); +#ifdef __GNUC__ +int cm_message_printf(const char *fmt, ...) + __attribute__ ((format (__printf__, 1, 2))); +#else +int cm_message_printf(const char *fmt, ...); +#endif + +#ifndef CM_IGNORE +#define CM_IGNORE(x) (x) +#endif + #endif diff --git a/src/include/ngspice/dllitf.h b/src/include/ngspice/dllitf.h index 8bdbc2354..84cdc7267 100644 --- a/src/include/ngspice/dllitf.h +++ b/src/include/ngspice/dllitf.h @@ -16,7 +16,8 @@ struct coreInfo_t { /* MIF stuff */ void ((*dllitf_MIF_INP2A)(CKTcircuit *, INPtables *, struct card *)); - char * ((*dllitf_MIFgetMod)(CKTcircuit *, char *, INPmodel **, INPtables *)); + char * ((*dllitf_MIFgetMod)(CKTcircuit *, const char *, INPmodel **, + INPtables *)); IFvalue * ((*dllitf_MIFgetValue)(CKTcircuit *, char **, int, INPtables *, char **)); int ((*dllitf_MIFsetup)(SMPmatrix *, GENmodel *, CKTcircuit *, int *)); int ((*dllitf_MIFunsetup)(GENmodel *, CKTcircuit *)); @@ -32,7 +33,7 @@ struct coreInfo_t { char * ((*dllitf_MIFgettok)(char **)); char * ((*dllitf_MIFget_token)(char **, Mif_Token_Type_t *)); Mif_Cntl_Src_Type_t ((*dllitf_MIFget_cntl_src_type)(Mif_Port_Type_t, Mif_Port_Type_t)); - char * ((*dllitf_MIFcopy)(char *)); + char * ((*dllitf_MIFcopy)(const char *)); /* CM stuff */ void ((*dllitf_cm_climit_fcn)(double, double, double, double, double, double, double, double, int, double *, double *, double *, @@ -55,7 +56,7 @@ struct coreInfo_t { void * ((*dllitf_cm_event_get_ptr)(int, int)); int ((*dllitf_cm_event_queue)(double)); char * ((*dllitf_cm_message_get_errmsg)(void)); - int ((*dllitf_cm_message_send)(char *)); + int ((*dllitf_cm_message_send)(const char *)); double ((*dllitf_cm_netlist_get_c)(void)); double ((*dllitf_cm_netlist_get_l)(void)); Complex_t ((*dllitf_cm_complex_set)(double, double)); @@ -71,11 +72,32 @@ struct coreInfo_t { /*Other stuff*/ void * ((*dllitf_malloc_pj)(size_t)); void * ((*dllitf_calloc_pj)(size_t, size_t)); - void * ((*dllitf_realloc_pj)(const void *, size_t)); - void ((*dllitf_free_pj)(const void *)); + void * ((*dllitf_realloc_pj)(void *, size_t)); + void ((*dllitf_free_pj)(void *)); void * ((*dllitf_tmalloc)(size_t)); - void * ((*dllitf_trealloc)(const void *, size_t)); - void ((*dllitf_txfree)(const void *)); + void * ((*dllitf_trealloc)(void *, size_t)); + void ((*dllitf_txfree)(void *)); + + /*** VERSION 2 ADDITIONS ***/ + const char *(*dllitf_ngspice_version)(void); + /* version string of ngspice using the cm */ + void *(*dllitf_tmalloc_raw)(size_t size); + /* mutex-protected malloc() that will not + * cause program termination on failure */ + void *(*dllitf_tcalloc_raw)(size_t num, size_t size); + /* mutex-protected calloc() that will not + * cause program termination on failure */ + void *(*dllitf_trealloc_raw)(void *p, size_t size); + /* mutex-protected realloc() that will not + * cause program termination on failure */ + char *(*dllitf_tstrdup)(const char *sz); + /* mutex-protected strdup() that WILL + * cause program termination on failure */ + char *(*dllitf_tstrdup_raw)(const char *sz); + /* mutex-protected strdup() that will not + * cause program termination on failure */ }; -#endif +extern const struct coreInfo_t coreInfo; + +#endif /* include guard */ diff --git a/src/include/ngspice/dstring.h b/src/include/ngspice/dstring.h index 25ad51773..b18072c87 100644 --- a/src/include/ngspice/dstring.h +++ b/src/include/ngspice/dstring.h @@ -9,6 +9,8 @@ #include #include +#include "ngspice/memory.h" + /* Error codes */ #define DS_E_OK 0 #define DS_E_INVALID (-1) @@ -192,7 +194,7 @@ inline char *ds_free_move(DSTRING *p_ds, unsigned int opt) if (opt & DS_FREE_MOVE_OPT_FORCE_ALLOC) { /* Allocate to minimum size */ size_t n_byte_alloc = p_ds->length + 1; - char * const p_ret = (char *) malloc(n_byte_alloc); + char * const p_ret = (char *) tmalloc_raw(n_byte_alloc); if (p_ret == (char *) NULL) { return (char *) NULL; } @@ -204,7 +206,7 @@ inline char *ds_free_move(DSTRING *p_ds, unsigned int opt) if (opt & DS_FREE_MOVE_OPT_COMPACT) { /* Allocate to minimum size */ size_t n_byte_alloc = p_ds->length + 1; - char * const p_ret = (char *) realloc(p_buf_active, n_byte_alloc); + char * const p_ret = (char *) trealloc_raw(p_buf_active, n_byte_alloc); if (p_ret == (char *) NULL) { /* Realloc to smaller size somehow failed! */ return (char *) NULL; diff --git a/src/include/ngspice/dvec.h b/src/include/ngspice/dvec.h index 3833295b7..beaf5b1b2 100644 --- a/src/include/ngspice/dvec.h +++ b/src/include/ngspice/dvec.h @@ -75,7 +75,8 @@ struct dveclist { bool f_own_vector; }; -struct dvec *dvec_alloc(/* NOT CONST -- assigned to const */ char *name, +struct dvec *dvec_alloc( + /* not const -- given to non-const struct */ char *name, int type, short flags, int length, void *storage); void dvec_realloc(struct dvec *v, int length, void *storage); void dvec_extend(struct dvec *v, int length); diff --git a/src/include/ngspice/inpdefs.h b/src/include/ngspice/inpdefs.h index e8d9c864f..9dcab19e6 100644 --- a/src/include/ngspice/inpdefs.h +++ b/src/include/ngspice/inpdefs.h @@ -68,7 +68,7 @@ struct nscope { /* A linked list of netlist line entries, associated for a specific reason */ struct card_assoc { - const char *name; + char *name; struct card *line; struct card_assoc *next; }; diff --git a/src/include/ngspice/memory.h b/src/include/ngspice/memory.h index d1c7fe7ca..e1e55b67d 100644 --- a/src/include/ngspice/memory.h +++ b/src/include/ngspice/memory.h @@ -3,33 +3,23 @@ #include -#define TMALLOC(t, n) (t*) tmalloc(sizeof(t) * (size_t)(n)) -#define TREALLOC(t, p, n) (t*) trealloc(p, sizeof(t) * (size_t)(n)) +#include "ngspice/alloc.h" + +/* "Type" allocations */ +#define TMALLOC(t, n) (t *) tmalloc(sizeof(t) * (size_t)(n)) +#define TREALLOC(t, p, n) (t *) trealloc(p, sizeof(t) * (size_t)(n)) -#ifndef HAVE_LIBGC - -extern void *tmalloc(size_t num); -extern void *trealloc(const void *str, size_t num); -extern void txfree(const void *ptr); - -#define tfree(x) (txfree(x), (x) = 0) - -#else - -#include - -#define tmalloc(m) GC_malloc(m) -#define trealloc(m, n) GC_realloc((m), (n)) +#ifdef HAVE_LIBGC #define tfree(m) -#define txfree(m) - +#else +#define tfree(x) (txfree(x), (x) = 0) #endif /* HAVE_LIBGC */ #include "ngspice/stringutil.h" -#define FREE(x) do { if(x) { txfree(x); (x) = NULL; } } while(0) +#define FREE(x) do { if (x) { txfree(x); (x) = NULL; } } while(0) #define ZERO(PTR, TYPE) memset(PTR, 0, sizeof(TYPE)) @@ -59,4 +49,4 @@ extern void txfree(const void *ptr); #endif /* CIDER */ -#endif +#endif /* include guard */ diff --git a/src/include/ngspice/mifproto.h b/src/include/ngspice/mifproto.h index 192044193..edf125988 100644 --- a/src/include/ngspice/mifproto.h +++ b/src/include/ngspice/mifproto.h @@ -59,7 +59,7 @@ extern void MIF_INP2A( extern char * MIFgetMod( CKTcircuit *ckt, - char *name, + const char *name, INPmodel **model, INPtables *tab ); @@ -152,7 +152,11 @@ extern Mif_Cntl_Src_Type_t MIFget_cntl_src_type( Mif_Port_Type_t out_port_type ); -extern char *MIFcopy(char *); +extern char *MIFcopy(const char *); +#ifndef CM_IGNORE +#define CM_IGNORE(x) (x) +#endif + #endif diff --git a/src/include/ngspice/ngspice.h b/src/include/ngspice/ngspice.h index 3e1c1c1f4..d09705891 100644 --- a/src/include/ngspice/ngspice.h +++ b/src/include/ngspice/ngspice.h @@ -172,7 +172,7 @@ extern double x_acosh(double); extern double x_atanh(double); #define hypot _hypot #endif -#define strdup _strdup +/////#define strdup _strdup #define unlink _unlink #define fileno _fileno #define getcwd _getcwd diff --git a/src/include/ngspice/stringutil.h b/src/include/ngspice/stringutil.h index f02c2a6b1..b9d008c36 100644 --- a/src/include/ngspice/stringutil.h +++ b/src/include/ngspice/stringutil.h @@ -9,7 +9,6 @@ #include #include -#include "ngspice/config.h" #include "ngspice/bool.h" diff --git a/src/main.c b/src/main.c index 47326fc99..8ecc75b0f 100644 --- a/src/main.c +++ b/src/main.c @@ -722,6 +722,7 @@ append_to_stream(FILE *dest, FILE *source) SJB 25th April 2005 */ static bool read_initialisation_file(const char *dir, const char *name) { + char *full_name = (char *) NULL; const char *path; bool result = FALSE; @@ -735,7 +736,7 @@ static bool read_initialisation_file(const char *dir, const char *name) path = name; } else { - path = tprintf("%s" DIR_PATHSEP "%s", dir, name); + path = full_name = tprintf("%s" DIR_PATHSEP "%s", dir, name); if (!path) { return FALSE; /* memory allocation error */ } @@ -763,8 +764,8 @@ static bool read_initialisation_file(const char *dir, const char *name) #endif } - if (path != name) { /* Allocated by tprintf() */ - txfree(path); + if (full_name != (char *) NULL) { /* Allocated by tprintf() */ + txfree(full_name); } return result; @@ -776,7 +777,7 @@ static bool read_initialisation_file(const char *dir, const char *name) static void print_news(void) { if (News_File && *News_File) { - const char * const fname = cp_tildexpand(News_File); /*DG Memory leak */ + char * const fname = cp_tildexpand(News_File); /*DG Memory leak */ FILE * const fp = fopen(fname, "r"); txfree(fname); if (fp) { diff --git a/src/misc/alloc.c b/src/misc/alloc.c index d870999e2..f425d8afc 100644 --- a/src/misc/alloc.c +++ b/src/misc/alloc.c @@ -1,16 +1,28 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. **********/ - /* for thread handling */ -#if defined __MINGW32__ || defined _MSC_VER +#ifdef _WIN32 #include #endif +#include + /* * Memory alloction functions */ +#include "ngspice/alloc.h" #include "ngspice/ngspice.h" +#include "ngspice/cpextern.h" + +#if defined HAS_WINGUI || defined SHARED_MODULE +#define EXIT(rc) controlled_exit(rc) +#else +#define EXIT(rc) exit(rc) +#endif + +static void overflow_error(size_t num, size_t size); +static inline int product_overflow(size_t a, size_t b, size_t *p_n); #ifdef SHARED_MODULE @@ -35,119 +47,269 @@ extern mutexType allocMutex; #endif -#ifndef HAVE_LIBGC +#ifdef HAVE_LIBGC +#include + +void *tmalloc(size_t num) +{ + if (GC_malloc(num) == NULL) { + EXIT(EXIT_FAILURE); + } +} /* end of function tmalloc */ + + +void *tcalloc(size_t num, size_t count) +{ + if (GC_calloc(num, count) == NULL) { + EXIT(EXIT_FAILURE); + } +} /* end of function tmalloc */ + + + +void *trealloc(size_t num, size_t count) +{ + if (GC_calloc(num, count) == NULL) { + EXIT(EXIT_FAILURE); + } +} /* end of function tmalloc */ + + +/* Free is noop for GC */ +void txfree(p) +{ + NG_IGNORE(p); + return; +} /* end of function txfree */ + + + +#else /*saj For Tcl module locking*/ #ifdef TCL_MODULE #include #endif /* Malloc num bytes and initialize to zero. Fatal error if the space can't - * be tmalloc'd. Return NULL for a request for 0 bytes. + * be tmalloc'd. Return NULL for a request for 0 bytes. */ - -/* New implementation of tmalloc, it uses calloc and does not call memset() */ - -void * -tmalloc(size_t num) +void *tmalloc(size_t num) { - void *s; -/*saj*/ -#ifdef TCL_MODULE - Tcl_Mutex *alloc; - alloc = Tcl_GetAllocMutex(); -#endif - if (!num) - return NULL; -/*saj*/ -#ifdef TCL_MODULE - Tcl_MutexLock(alloc); -#elif defined SHARED_MODULE - mutex_lock(&allocMutex); -#endif - s = calloc(num,1); -/*saj*/ -#ifdef TCL_MODULE - Tcl_MutexUnlock(alloc); -#elif defined SHARED_MODULE - mutex_unlock(&allocMutex); -#endif - if (!s){ - fprintf(stderr,"malloc: Internal Error: can't allocate %ld bytes. \n",(long)num); -#if defined HAS_WINGUI || defined SHARED_MODULE - controlled_exit(EXIT_FAILURE); -#else - exit(EXIT_FAILURE); -#endif + if (num == 0) { + return NULL; } - return(s); -} + void * const p = tmalloc_raw(num); + if (p == NULL) { + (void) fprintf(cp_err, "malloc: Internal Error: can't allocate " + "%zd bytes. \n", num); + EXIT(EXIT_FAILURE); + } + return memset(p, 0, num); +} /* end of function tmalloc */ -void * -trealloc(const void *ptr, size_t num) + +/* A "raw" malloc with mutex protection. */ +void *tmalloc_raw(size_t num) { - void *s; -/*saj*/ -#ifdef TCL_MODULE - Tcl_Mutex *alloc; - alloc = Tcl_GetAllocMutex(); -#endif - if (!num) { - if (ptr) - free((void*) ptr); - return NULL; - } + if (num == 0) { /* 0-byte request */ + return NULL; + } - if (!ptr) - s = tmalloc(num); - else { /*saj*/ #ifdef TCL_MODULE + Tcl_Mutex *alloc; + alloc = Tcl_GetAllocMutex(); Tcl_MutexLock(alloc); #elif defined SHARED_MODULE - mutex_lock(&allocMutex); + mutex_lock(&allocMutex); #endif - s = realloc((void*) ptr, num); + void * const p = malloc(num); /*saj*/ #ifdef TCL_MODULE - Tcl_MutexUnlock(alloc); + Tcl_MutexUnlock(alloc); #elif defined SHARED_MODULE - mutex_unlock(&allocMutex); + mutex_unlock(&allocMutex); #endif - } - if (!s) { - fprintf(stderr,"realloc: Internal Error: can't allocate %ld bytes.\n", (long)num); -#if defined HAS_WINGUI || defined SHARED_MODULE - controlled_exit(EXIT_FAILURE); -#else - exit(EXIT_FAILURE); -#endif - } - return(s); -} + return p; +} /* end of function tmalloc_raw */ -void -txfree(const void *ptr) + +/* calloc with mutex protection */ +void *tcalloc(size_t num, size_t size) { + size_t n; + if (product_overflow(num, size, &n)) { + overflow_error(num, size); + /* Fatal. No return */ + } + + return tmalloc(n); +} /* end of function tcalloc */ + + + +/* A "raw" calloc with mutex protection built from tmalloc_raw(). */ +void *tcalloc_raw(size_t num, size_t size) +{ + size_t n; + if (product_overflow(num, size, &n)) { + return NULL; + } + void * const p = tmalloc_raw(n); + return memset(p, 0, n); +} /* end of function tmalloc_raw */ + + + +/* Realloc with mutex protection and exit if failure */ +void *trealloc(void *ptr, size_t num) +{ + void *p_new = trealloc_raw(ptr, num); + + if (num != 0 && p_new == NULL) { + (void) fprintf(stderr, "realloc: Internal Error: " + "can't allocate %zd bytes.\n", + num); + EXIT(EXIT_FAILURE); + } + + return p_new; +} /* end of function trealloc */ + + + +/* A "raw" realloc with mutex protection */ +void *trealloc_raw(void *ptr, size_t num) { /*saj*/ + if (num == 0) { /* Acts like free() */ + if (ptr != NULL) { + txfree((void*) ptr); + } + return NULL; + } + + if (ptr == NULL) { /* Acts like malloc() */ + return tmalloc_raw(num); + } + #ifdef TCL_MODULE - Tcl_Mutex *alloc; - alloc = Tcl_GetAllocMutex(); - Tcl_MutexLock(alloc); + Tcl_Mutex *alloc; + alloc = Tcl_GetAllocMutex(); + Tcl_MutexLock(alloc); +#elif defined SHARED_MODULE + mutex_lock(&allocMutex); #endif -#ifdef SHARED_MODULE - mutex_lock(&allocMutex); -#endif - if (ptr) - free((void*) ptr); + void * const p_new = realloc(ptr, num); /*saj*/ #ifdef TCL_MODULE - Tcl_MutexUnlock(alloc); + Tcl_MutexUnlock(alloc); #elif defined SHARED_MODULE - mutex_unlock(&allocMutex); + mutex_unlock(&allocMutex); #endif -} + return p_new; +} /* end of function trealloc_raw */ + + + +/* Free with mutex protection */ +void txfree(void *ptr) +{ + if (ptr == NULL) { + return; + } + +/*saj*/ +#ifdef TCL_MODULE + Tcl_Mutex *alloc; + alloc = Tcl_GetAllocMutex(); + Tcl_MutexLock(alloc); #endif +#ifdef SHARED_MODULE + mutex_lock(&allocMutex); +#endif + free(ptr); +/*saj*/ +#ifdef TCL_MODULE + Tcl_MutexUnlock(alloc); +#elif defined SHARED_MODULE + mutex_unlock(&allocMutex); +#endif +} /* end of function txfree */ + + + + +/* This function returns the product of a and b if it does not overflow. + * + * Return codes + * 0: No overflow + * 1: overflow + */ +static inline int product_overflow(size_t a, size_t b, size_t *p_n) +{ + /* Some overflow conditions: + * a == SIZE_MAX and b > 1 + * a > 1 and b == SIZE_MAX + * a * b < a + * a * b < b + */ + if (a == SIZE_MAX && b > 1 || a > 1 && b == SIZE_MAX) { + return +1; + } + + const size_t n = a * b; + if (n < a || n < b) { + return +1; + } + + *p_n = n; + return 0; +} /* end of function product_overflow */ + + + +/* Print error related to allocating a product that cannot fit in a + * size_t and exit. This function does not return. */ +static void overflow_error(size_t num, size_t size) +{ + (void) fprintf(cp_err, "Cannot allocate %zu X %zu bytes: " + "Product exceeds largest size_t = %zu.\n", + num, size, SIZE_MAX); + EXIT(EXIT_FAILURE); +} /* end of function overflow_error */ + + +/* strdup must also be serialized since it performs an allocation. Note that + * Microsoft has not had a single-threaded CRT since VS 2005 (Windows XP), + * so, their _strdup can be safely used if desired. */ +/* Declared in cmproto.h */ +char *tstrdup(const char *str_in) +{ + const size_t n_byte_alloc = strlen(str_in); + 1; + char * const str_out = (char *) tmalloc(n_byte_alloc); + /* Program execution would end in tmalloc() if the allocation fails */ + return memcpy(str_out, str_in, n_byte_alloc); +} /* end of function tstrdup */ + + + +/* Declared in cmproto.h */ +char *tstrdup_raw(const char *str_in) +{ + const size_t n_byte_alloc = strlen(str_in); + 1; + char * const str_out = (char *) tmalloc_raw(n_byte_alloc); + if (str_out == (char *) NULL) { + return (char *) NULL; + } + + return memcpy(str_out, str_in, n_byte_alloc); +} /* end of function tstrdup_raw */ + + + +#endif /* #ifndef HAVE_LIBGC */ + diff --git a/src/misc/alloc.h b/src/misc/alloc.h deleted file mode 100644 index b310e3cba..000000000 --- a/src/misc/alloc.h +++ /dev/null @@ -1,15 +0,0 @@ -/************* - * Header file for alloc.c - * 1999 E. Rouat - ************/ - -#ifndef ngspice_ALLOC_H -#define ngspice_ALLOC_H - -#ifndef HAVE_LIBGC -void * tmalloc(size_t num); -void * trealloc(const void *ptr, size_t num); -void txfree(const void *ptr); -#endif - -#endif diff --git a/src/misc/dstring.c b/src/misc/dstring.c index ccee090e6..7e4323bba 100644 --- a/src/misc/dstring.c +++ b/src/misc/dstring.c @@ -4,13 +4,13 @@ DESCRIPTION:This file contains the routines for manipulating dynamic strings. ----------------------------------------------------------------- */ #include #include -#include #include #include #include #include #include "ngspice/dstring.h" +#include "ngspice/alloc.h" static int ds_reserve_internal(DSTRING *p_ds, @@ -86,7 +86,7 @@ int ds_init(DSTRING *p_ds, char *p_buf, size_t length_string, void ds_free(DSTRING *p_ds) { if (p_ds->p_buf != p_ds->p_stack_buf) { - free((void *) p_ds->p_buf); + txfree((void *) p_ds->p_buf); } } /* end of function ds_free */ @@ -212,7 +212,8 @@ static int ds_reserve_internal(DSTRING *p_ds, n_byte_alloc_min = n_byte_alloc_opt; } for ( ; ; ) { - if ((p_buf_new = (char *) malloc(n_byte_alloc)) != (char *) NULL) { + if ((p_buf_new = (char *) tmalloc_raw( + n_byte_alloc)) != (char *) NULL) { break; /* Allocated OK */ } @@ -230,7 +231,7 @@ static int ds_reserve_internal(DSTRING *p_ds, /* If there already was a dynamic allocation, free it */ if (p_ds->p_buf != p_ds->p_stack_buf) { - free((void *) p_ds->p_buf); + txfree((void *) p_ds->p_buf); } /* Assign new active buffer and its size */ @@ -334,7 +335,7 @@ int ds_compact(DSTRING *p_ds) * free the allocation. */ if (p_ds->n_byte_stack_buf >= n_byte_alloc_min) { (void) memcpy(p_ds->p_stack_buf, p_ds->p_buf, n_byte_alloc_min); - free((void *) p_ds->p_buf); + txfree((void *) p_ds->p_buf); p_ds->p_buf = p_ds->p_stack_buf; p_ds->n_byte_alloc = p_ds->n_byte_stack_buf; return DS_E_OK; @@ -347,7 +348,7 @@ int ds_compact(DSTRING *p_ds) /* Else realloc the heap buffer */ { - void *p = realloc(p_ds->p_buf, n_byte_alloc_min); + void * const p = trealloc_raw(p_ds->p_buf, n_byte_alloc_min); if (p == NULL) { return DS_E_NO_MEMORY; } diff --git a/src/spicelib/devices/dev.c b/src/spicelib/devices/dev.c index 1298eb016..c8076d6dd 100644 --- a/src/spicelib/devices/dev.c +++ b/src/spicelib/devices/dev.c @@ -42,20 +42,22 @@ #include /* for strcpy, strcat*/ #if (!defined HAS_WINGUI) && (!defined __MINGW32__) && (!defined _MSC_VER) #include /* to load libraries*/ -typedef void * funptr_t; +typedef void * funptr_t; +#define FREE_DLERR_MSG(msg) #else /* ifdef HAS_WINGUI */ #undef BOOLEAN #include typedef FARPROC funptr_t; -void *dlopen (const char *, int); -funptr_t dlsym (void *, const char *); -int dlclose (void *); -char *dlerror (void); +void *dlopen(const char *, int); +funptr_t dlsym(void *, const char *); +char *dlerror(void); +#define FREE_DLERR_MSG(msg) free_dlerr_msg(msg) +static void free_dlerr_msg(char *msg); #define RTLD_LAZY 1 /* lazy function call binding */ #define RTLD_NOW 2 /* immediate function call binding */ #define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other dlopen'ed objs */ -static char errstr[128]; #endif /* ifndef HAS_WINGUI */ + #include "ngspice/dllitf.h" /* the coreInfo Structure*/ #include "ngspice/evtudn.h" /*Use defined nodes */ @@ -400,115 +402,198 @@ int add_udn(int n,Evt_Udn_Info_t **udns){ return 0; } -extern struct coreInfo_t coreInfo; -int load_opus(char *name){ - void *lib; - const char *msg; - int *num=NULL; - struct coreInfo_t **core; - SPICEdev **devs; - Evt_Udn_Info_t **udns; - funptr_t fetch; +int load_opus(const char *name) +{ + void *lib; + char *msg; + int num; + SPICEdev **devs; + Evt_Udn_Info_t **udns; + funptr_t fetch; + + lib = dlopen(name, RTLD_NOW); + if (!lib) { + msg = dlerror(); + printf("Error opening code model \"%s\": %s\n", name, msg); + FREE_DLERR_MSG(msg); + return 1; + } + + + /* Get code models defined by the library */ + if ((fetch = dlsym(lib, "CMdevNum2")) != (funptr_t) NULL) { + /* Version 2 code models present */ + num = *(*(int * (*)(void)) fetch)(); + fetch = dlsym(lib, "CMdevs2"); + if (fetch != (funptr_t) NULL) { + devs = (*(SPICEdev ** (*)(void)) fetch)(); + } + else { + msg = dlerror(); + printf("Error getting the list of version 2 devices: %s\n", + msg); + FREE_DLERR_MSG(msg); + return 1; + } + } + else { /* no version 2, so try version 1 */ + if ((fetch = dlsym(lib, "CMdevNum")) != (funptr_t) NULL) { + num = *(*(int * (*)(void)) fetch)(); + fetch = dlsym(lib, "CMdevs"); + if (fetch != (funptr_t) NULL) { + devs = (*(SPICEdev ** (*)(void)) fetch)(); + } + else { + msg = dlerror(); + printf("Error getting the list of version 1 devices: %s\n", + msg); + FREE_DLERR_MSG(msg); + return 1; + } + } /* end of case that got version 1 */ + else { /* no version 2 or version 1 */ + msg = dlerror(); + printf("Error finding the number of devices: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; + } + } /* end of case of no version 2 */ + + add_device(num, devs, 1); - lib = dlopen(name,RTLD_NOW); - if(!lib){ - msg = dlerror(); - printf("%s\n", msg); - return 1; - } - - fetch = dlsym(lib,"CMdevNum"); - if(fetch){ - num = ((int * (*)(void)) fetch) (); #ifdef TRACE - printf("Got %u devices.\n",*num); + printf("Got %u devices.\n", num); #endif - }else{ - msg = dlerror(); - printf("%s\n", msg); - return 1; - } - fetch = dlsym(lib,"CMdevs"); - if(fetch){ - devs = ((SPICEdev ** (*)(void)) fetch) (); - }else{ - msg = dlerror(); - printf("%s\n", msg); - return 1; - } - fetch = dlsym(lib,"CMgetCoreItfPtr"); - if(fetch){ - core = ((struct coreInfo_t ** (*)(void)) fetch) (); - *core = &coreInfo; - }else{ - msg = dlerror(); - printf("%s\n", msg); - return 1; - } - add_device(*num,devs,1); + /* Get user-defined ndes defined by the library */ + if ((fetch = dlsym(lib, "CMudnNum2")) != (funptr_t) NULL) { + /* Version 2 user-defined types present */ + num = *(*(int * (*)(void)) fetch)(); + fetch = dlsym(lib, "CMudns2"); + if (fetch != (funptr_t) NULL) { + udns = (*(Evt_Udn_Info_t ** (*)(void)) fetch)(); + } + else { + msg = dlerror(); + printf("Error getting the list of version 2 " + "user-defined types: %s\n", + msg); + FREE_DLERR_MSG(msg); + return 1; + } + } + else { /* no version 2, so try version 1 */ + if ((fetch = dlsym(lib, "CMudnNum")) != (funptr_t) NULL) { + num = *(*(int * (*)(void)) fetch)(); + fetch = dlsym(lib, "CMudns"); + if (fetch != (funptr_t) NULL) { + udns = (*(Evt_Udn_Info_t ** (*)(void)) fetch)(); + } + else { + msg = dlerror(); + printf("Error getting the list of version 1 " + "user-defined types: %s\n", + msg); + FREE_DLERR_MSG(msg); + return 1; + } + } /* end of case that got version 1 */ + else { /* no version 2 or version 1 */ + msg = dlerror(); + printf("Error finding the number of " + "user-defined types: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; + } + } /* end of case of no version 2 */ - fetch = dlsym(lib,"CMudnNum"); - if(fetch){ - num = ((int * (*)(void)) fetch) (); + add_udn(num, udns); #ifdef TRACE - printf("Got %u udns.\n",*num); + printf("Got %u udns.\n", num); #endif - }else{ - msg = dlerror(); - printf("%s\n", msg); - return 1; - } - fetch = dlsym(lib,"CMudns"); - if(fetch){ - udns = ((Evt_Udn_Info_t ** (*)(void)) fetch) (); - }else{ - msg = dlerror(); - printf("%s\n", msg); - return 1; - } - add_udn(*num,udns); + /* Give the code model access to facilities provided by ngspice. Note + * that older versions of code models will not access the functions + * added by newer versions of ngspice since it is unaware of them and + * newer versions of code models will not use newer (undefined) + * functions from ngspice because any of its models that use them + * will not be recognized and used by ngspice. */ + if ((fetch = dlsym(lib,"CMgetCoreItfPtr")) != (funptr_t) NULL) { + const struct coreInfo_t ** const core = + (*(const struct coreInfo_t ** const (*)(void)) fetch)(); + *core = &coreInfo; + } + else { + msg = dlerror(); + printf("Error getting interface pointer: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; + } + + + return 0; +} /* end of function load_opus */ + - return 0; -} #if defined(__MINGW32__) || defined(HAS_WINGUI) || defined(_MSC_VER) -void *dlopen(const char *name,int type) +/* For reporting error message if formatting fails */ +static const char errstr_fmt[] = + "Unable to find message in dlerr(). System code = %lu"; +static char errstr[sizeof errstr_fmt - 3 + 3 * sizeof(unsigned long)]; + +/* Emulations of POSIX dlopen(), dlsym(), and dlerror(). */ +void *dlopen(const char *name, int type) { - NG_IGNORE(type); - return LoadLibrary(name); + NG_IGNORE(type); + return LoadLibrary(name); } funptr_t dlsym(void *hDll, const char *funcname) { - return GetProcAddress(hDll, funcname); + return GetProcAddress(hDll, funcname); } char *dlerror(void) { - LPVOID lpMsgBuf; + LPVOID lpMsgBuf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); - strcpy(errstr,lpMsgBuf); - LocalFree(lpMsgBuf); - return errstr; -} -#endif + DWORD rc = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + if (rc == 0) { /* FormatMessage failed */ + (void) sprintf(errstr, errstr_fmt, (unsigned long) GetLastError()); + return errstr; + } + + return lpMsgBuf; /* Return the formatted message */ +} /* end of function dlerror */ + + + +/* Free message related to dynamic loading */ +static void free_dlerr_msg(char *msg) +{ + if (msg != errstr) { /* msg is an allocation */ + LocalFree(msg); + } +} /* end of function free_dlerr_msg */ + + + +#endif /* Windows emulation of dlopen, dlsym, and dlerr */ #endif /*-------------------- end of XSPICE additions ----------------------*/ diff --git a/src/spicelib/devices/dev.h b/src/spicelib/devices/dev.h index c366aee67..3356d04b7 100644 --- a/src/spicelib/devices/dev.h +++ b/src/spicelib/devices/dev.h @@ -8,7 +8,7 @@ int num_devices(void); IFdevice **devices_ptr(void); SPICEdev **devices(void); #ifdef XSPICE -int load_opus(char *); +int load_opus(const char *); int DEVflag(int type); #endif #ifdef DEVLIB diff --git a/src/spicelib/parser/inpptree-parser.y b/src/spicelib/parser/inpptree-parser.y index 0c6bccadf..95f16d13c 100644 --- a/src/spicelib/parser/inpptree-parser.y +++ b/src/spicelib/parser/inpptree-parser.y @@ -84,7 +84,7 @@ expression: exp exp: TOK_NUM { $$ = PT_mknnode($1); } - | TOK_STR { $$ = PT_mksnode($1, ckt); txfree($1); } + | TOK_STR { $$ = PT_mksnode($1, ckt); txfree((void *) $1); } | exp '+' exp { $$ = PT_mkbnode("+", $1, $3); } | exp '-' exp { $$ = PT_mkbnode("-", $1, $3); } @@ -100,7 +100,7 @@ exp: | TOK_STR '(' nonempty_arglist ')' { $$ = PT_mkfnode($1, $3); if (!$$) YYERROR; - txfree($1); } + txfree((void *) $1); } | TOK_pnode diff --git a/src/winmain.c b/src/winmain.c index 1de964375..d22bde1a3 100644 --- a/src/winmain.c +++ b/src/winmain.c @@ -1080,8 +1080,8 @@ static struct History_info *init_history(void) } { - /* Initialize history buffer with a greeting */ - static const char cmd_welcome[] = "# Welcome to ngspice!"; + /* Initialize history buffer with empty input line */ + static const char cmd_welcome[] = ""; (void) history_add(&p_hi, sizeof cmd_welcome - 1, cmd_welcome); } diff --git a/src/xspice/cm/cm.c b/src/xspice/cm/cm.c index 462047915..92d302642 100644 --- a/src/xspice/cm/cm.c +++ b/src/xspice/cm/cm.c @@ -105,7 +105,8 @@ void cm_analog_alloc( } /* Compute number of doubles needed and allocate space in ckt->CKTstates[i] */ - doubles_needed = bytes / (int) sizeof(double) + 1; + doubles_needed = + (bytes + (int) sizeof(double) - 1) / (int) sizeof(double); /* Allocate space in instance struct for this state descriptor */ if(here->num_state == 0) { @@ -133,7 +134,8 @@ void cm_analog_alloc( else ckt->CKTstates[i] = TREALLOC(double, ckt->CKTstates[i], ckt->CKTnumStates); } -} +} /* end of function cm_analog_alloc */ + /* @@ -657,8 +659,7 @@ the instance name. */ -int cm_message_send( - char *msg) /* The message to output. */ +int cm_message_send(const char *msg) /* The message to output. */ { MIFinstance *here; diff --git a/src/xspice/cm/cmexport.c b/src/xspice/cm/cmexport.c index fa8e9199c..fb4703933 100644 --- a/src/xspice/cm/cmexport.c +++ b/src/xspice/cm/cmexport.c @@ -1,12 +1,9 @@ #include "ngspice/ngspice.h" #include "ngspice/mif.h" #include "ngspice/cm.h" +#include "ngspice/cpextern.h" #include "ngspice/dllitf.h" - -/*how annoying!, needed for structure below*/ -static void *tcalloc(size_t a, size_t b) { - return tmalloc(a*b); /* FIXME, tcalloc must zero !?!? */ -} +#include "ngspice/alloc.h" #ifdef HAVE_LIBGC static void no_free(const void *p) { @@ -14,11 +11,31 @@ static void no_free(const void *p) { } #endif -static FILE * no_file(void) { - return NULL; +/* Returns the version string for ngspice */ +static const char *get_ngspice_version(void) +{ + const char *buf = VERSION; + return buf; +} /* end of function get_ngspice_version */ + + +/* Returns stdout, stdin, and stderr */ +static FILE *get_stdout(void) +{ + return cp_out; +} +static FILE *get_stdin(void) +{ + return cp_in; +} +static FILE *get_stderr(void) +{ + return cp_err; } -struct coreInfo_t coreInfo = + + +const struct coreInfo_t coreInfo = { MIF_INP2A, MIFgetMod, @@ -65,24 +82,21 @@ struct coreInfo_t coreInfo = cm_complex_divide, cm_get_path, cm_get_circuit, - no_file, - no_file, - no_file, -#ifndef HAVE_LIBGC - tmalloc, - tcalloc, - trealloc, - txfree, - tmalloc, - trealloc, - txfree -#else - GC_malloc, - tcalloc, - GC_realloc, - no_free, - GC_malloc, - GC_realloc, - no_free -#endif + &get_stdout, + &get_stdin, + &get_stderr, + &tmalloc, + &tcalloc, + &trealloc, + &txfree, + &tmalloc, + &trealloc, + &txfree, + /* Version 2 additions */ + &get_ngspice_version, + &tmalloc_raw, + &tcalloc_raw, + &trealloc_raw, + &tstrdup, + &tstrdup_raw }; diff --git a/src/xspice/cmpp/Makefile.am b/src/xspice/cmpp/Makefile.am index c5fce8cc3..c858a3348 100644 --- a/src/xspice/cmpp/Makefile.am +++ b/src/xspice/cmpp/Makefile.am @@ -11,7 +11,7 @@ bin_PROGRAMS = cmpp AM_CPPFLAGS = -I. -I$(srcdir) AM_YFLAGS = -d -cmpp_SOURCES = main.c cmpp.h \ +cmpp_SOURCES = main.c cmpp.h file_buffer.c file_buffer.h\ pp_ifs.c pp_lst.c pp_mod.c read_ifs.c writ_ifs.c util.c \ ifs_lex.l ifs_yacc.y ifs_yacc_y.h \ mod_lex.l mod_yacc.y mod_yacc_y.h @@ -42,7 +42,7 @@ if CROSS_COMPILING BUILT_SOURCES += build/cmpp$(BUILD_EXEEXT) CLEANFILES = build/cmpp$(BUILD_EXEEXT) -BUILD_CMPP_FILES = main.c \ +BUILD_CMPP_FILES = main.c file_buffer.c \ pp_ifs.c pp_lst.c pp_mod.c read_ifs.c writ_ifs.c util.c \ ifs_lex.c ifs_yacc.c \ mod_lex.c mod_yacc.c diff --git a/src/xspice/cmpp/cmpp.h b/src/xspice/cmpp/cmpp.h index 0467f274e..27e713ab7 100644 --- a/src/xspice/cmpp/cmpp.h +++ b/src/xspice/cmpp/cmpp.h @@ -38,6 +38,7 @@ NON-STANDARD FEATURES ============================================================================*/ +#include #include #include @@ -49,20 +50,25 @@ NON-STANDARD FEATURES #ifdef _MSC_VER #include #include + +/* If CRT debugging is being used so that crtdbg.h is included, strdup will + * be defined to a debug version. In this case, strdup should not be + * redefined to the standard version. */ +#ifndef strdup #define strdup _strdup +#endif + #define unlink _unlink #define isatty _isatty #define fileno _fileno -#endif +#endif /* _MSC_VER */ /* *********************************************************************** */ #define GET_IFS_TABLE 0 /* Read the entire ifs table */ #define GET_IFS_NAME 1 /* Get the C function name out of the table only */ -#define MAX_PATH_LEN 1024 /* Maximum pathname length */ #define MAX_NAME_LEN 1024 /* Maximum SPICE name length */ -#define MAX_FN_LEN 31 /* Maximum filename length */ /* ******************************************************************** */ @@ -262,7 +268,9 @@ void preprocess_ifs_file(void); void preprocess_lst_files(void); -void preprocess_mod_file(char *filename); +void preprocess_mod_file(const char *filename); + +int output_paths_from_lst_file(const char *filename); void init_error (char *program_name); @@ -272,6 +280,7 @@ void print_error(const char *fmt, ...) __attribute__ ((format (__printf__, 1, 2) #else void print_error(const char *fmt, ...); #endif +void vprint_error(const char *fmt, va_list p); void str_to_lower(char *s); @@ -281,8 +290,9 @@ int read_ifs_file(const char *filename, int mode, Ifs_Table_t *ifs_table); int write_ifs_c_file(const char *filename, Ifs_Table_t *ifs_table); -FILE *fopen_cmpp(const char **path_p, const char *mode); +char *gen_filename(const char *filename, const char *mode); +void rem_ifs_table(Ifs_Table_t *ifs_table); /* * type safe variants of the functions for char arguments diff --git a/src/xspice/cmpp/file_buffer.c b/src/xspice/cmpp/file_buffer.c new file mode 100644 index 000000000..27a9d10ff --- /dev/null +++ b/src/xspice/cmpp/file_buffer.c @@ -0,0 +1,698 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "file_buffer.h" +#include "cmpp.h" + +/* Default buffer size */ +#define N_BYTE_FILEBUF_INIT_DFLT 16384 + + +static int fb_fill(FILEBUF *p_fb); +static int fbget_quoted_unescaped_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj); +static size_t fb_make_space_at_end(FILEBUF *p_fb); +static int fbget_quoted_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj); +static int fbget_quoted_escaped_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj); +static int fbget_unquoted_string(FILEBUF *p_fb, + unsigned int n_type_wanted, FBTYPE *p_type_wanted, + FBTYPE *p_type_found, FBOBJ *p_fbobj); +static int fb_return_obj(FILEBUF *p_fb, + unsigned int n_type_wanted, FBTYPE *p_type_wanted, + FBTYPE *p_type_found, FBOBJ *p_fbobj); +static int fb_return_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj); +static int fb_skip_to_eol(FILEBUF *p_fb); +static int fb_skip_whitespace(FILEBUF *p_fb); + + +/* This function initializes a file-buffer read access to the named file. + * + * Parameters + * filename: Name of file to be opened for reading + * n_byte_buf_init: Intial buffer size. May be 0 for default size + * + * Return values + * NULL: Error occurred. The value of errno will provide more details + * Otherwise an initialized structure + */ +FILEBUF *fbopen(const char *filename, size_t n_byte_buf_init) +{ + int xrc = 0; + FILEBUF *p_fb = (FILEBUF *) NULL; + + /* Set default buffer size if requested */ + if (n_byte_buf_init == 0) { + n_byte_buf_init = N_BYTE_FILEBUF_INIT_DFLT; + } + + /* Allocate structure to return */ + if ((p_fb = (FILEBUF *) malloc(sizeof *p_fb)) == (FILEBUF *) NULL) { + xrc = -1; + goto EXITPOINT; + } + + p_fb->is_eof = false; + p_fb->f_skip_to_eol = false; + + /* Init resources for error recovery */ + p_fb->fp = (FILE *) NULL; + p_fb->p_buf = (char *) NULL; + + /* Allocate data buffer */ + if ((p_fb->p_buf = (char *) malloc(n_byte_buf_init)) == (char *) NULL) { + xrc = -1; + goto EXITPOINT; + } + p_fb->n_byte_buf_alloc = n_byte_buf_init; + p_fb->p_data_end = p_fb->p_data_cur = p_fb->p_buf; + p_fb->p_buf_end = p_fb->p_buf + n_byte_buf_init; + + /* p_fb->p_obj_undefined since no object yet */ + + /* Open file. It is opened in binary mode because the scanning will + * handle all EOL chars, so any translations by the OS are almost + * pure overhead. Also, not converting ensures that if fread returns + * fewer than the requested number of chars, that read was to the + * end of the file (if not an error). Otherwise an additional read + * getting a size of 0 would be required. */ + if ((p_fb->fp = fopen(filename, "rb")) == (FILE *) NULL) { + xrc = -1; + goto EXITPOINT; + } + +EXITPOINT: + /* Free resources on error */ + if (xrc != 0) { + if (p_fb != (FILEBUF *) NULL) { + const int errno_save = errno; /* save errno in case fbclose() + * changes it */ + (void) fbclose(p_fb); + errno = errno_save; + p_fb = (FILEBUF *) NULL; + } + } /* end of case of error */ + + return p_fb; +} /* end of function fbopen */ + + + +/* This function frees resources used by a FILEBUF. + * + * Parameter + * p_fb: The address of the FILEBUF to free. This argument may be NULL. + * + * Return values + * 0: OK + * EOF: Error closing file. Details can be found using errno. + */ +int fbclose(FILEBUF *p_fb) +{ + if (p_fb == (FILEBUF *) NULL) { + return 0; + } + + int xrc = 0; + + { + void *p; + if ((p = p_fb->p_buf) != NULL) { + free(p); + } + } + + { + FILE *fp; + if ((fp = p_fb->fp) != (FILE *) NULL) { + xrc = fclose(fp); + } + } + + free(p_fb); + return xrc; +} /* end of function fbclose */ + + + +/* This function gets the next object converting it to the most desired + * type. + * + * Parameters + * p_fb: FILEBUF pointer initialized using fbopen() + * n_type_wanted: number of desired type conversions for data from highest + * priority to lowest. + * p_type_wanted: Desired type conversions for data from highest priority + * to lowest. + * p_type_found: Address to receive the type of the data obtained + * p_fbobj: Address of an FBOBJ structure to receive the data + * + * Return codes + * +1: EOF reached + * 0: Normal return + * -1: Error. Use errno for further details. + * + * Remarks + * Type BUF_TYPE_STRING is always implicitly added to the list of wanted + * types as the final choice, which any data will satisfy + * + * A string may be double-quoted. In this case the quotes are not supplied + * to the caller as part of the data. Double-quoting ensures that a string + * will not be converted to any other type. Within double quotes, a double + * qoute and a backslash are escaped by a backslash, and a final unescaped + * double quote is impilcitly added if EOF is reached when scanning for a + * closing quote. + * + * A "*" or a "#" not within a quoted expression begins a comment that + * extends to the end of the line. + * + * When called p_fb has data from the last get or it is the first call. + * + * Return Codes + * +1: EOF + * 0: Normal + * -1: Error + */ +int fbget(FILEBUF *p_fb, + unsigned int n_type_wanted, FBTYPE *p_type_wanted, + FBTYPE *p_type_found, FBOBJ *p_fbobj) +{ + /* Test for existing EOF */ + if (p_fb->is_eof && p_fb->p_data_cur == p_fb->p_data_end) { /* no data */ + return +1; + } + + /* Init to no object */ + p_fb->p_obj_start = (char *) NULL; + + /* Skip the comment if the initiating character was processed during + * the last call to fbget */ + if (p_fb->f_skip_to_eol) { + const int rc = fb_skip_to_eol(p_fb); + if (rc != 0) { /* EOF or error */ + return rc; + } + } + + { + const int rc = fb_skip_whitespace(p_fb); + if (rc != 0) { /* EOF or error */ + return rc; + } + } + + /* Current char exists and starts the item */ + if (*p_fb->p_data_cur == '"') { /* quoted string */ + return fbget_quoted_string(p_fb, p_type_found, p_fbobj); + } + + /* Else unquoted string */ + return fbget_unquoted_string(p_fb, n_type_wanted, p_type_wanted, + p_type_found, p_fbobj); +} /* end of function fbget */ + + + +/* Get a quoted string given at a quote. On entry p_fb->p_data_cur points + * to the quote starting the quoted string. On return it points to the first + * character after the current item or equals p_fb->p_data_end if the + * current item extens to the end of the current data string. */ +static int fbget_quoted_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj) +{ + /* Advance past the opening quote to the true start of the string */ + if (++p_fb->p_data_cur == p_fb->p_data_end) { + /* The leading quote ended the current data */ + const int rc = fb_fill(p_fb); /* Try to refill buffer */ + if (rc != 0) { /* EOF or error */ + if (rc < 0) { /* error */ + return -1; + } + /* Else EOF. This item is an empty string that ended without the + * closing quote, so add an implicit closing quote, i.e., end + * the string to form "". + * + * Since the object was started at the beginning of the buffer + * and the buffer has at leat 1 byte a NULL to create the + * string "" can be written here */ + *(p_fb->p_obj_end = p_fb->p_obj_start = p_fb->p_buf) = '\0'; + return fb_return_string(p_fb, p_type_found, p_fbobj); + } + /* Else data is now available at p_fb->p_data_cur */ + } /* end of case that at end of data from file */ + + /* Save the start of the string as the current position */ + p_fb->p_obj_start = p_fb->p_data_cur; + + /* Continue processing as an unescaped string, unless the contrary + * is found to be true */ + return fbget_quoted_unescaped_string(p_fb, p_type_found, p_fbobj); +} /* end of function fbget_quoted_string */ + + + +/* Get a quoted string with no escape. The start has already been set on + * entry. If an escape is found, processing continues as an escaped string */ +int fbget_quoted_unescaped_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj) +{ + /* Step through characters until end or escape */ + char *p_data_cur = p_fb->p_data_cur; + char *p_data_end = p_fb->p_data_end; + for ( ; ; ) { /* continue until done */ + for ( ; p_data_cur != p_data_end; ++p_data_cur) { /* current data */ + const char ch_cur = *p_data_cur; + if (ch_cur == '"') { /* Closing quote, so done */ + *(p_fb->p_obj_end = p_data_cur) = '\0'; + p_fb->p_data_cur = p_data_cur + 1; + return fb_return_string(p_fb, p_type_found, p_fbobj); + } + if (ch_cur == '\\') { /* Escape */ + /* After an escape, data must be moved to fill in the gap + * left by the escape character */ + p_fb->p_data_cur = p_data_cur; /* Reprocess the escape */ + return fbget_quoted_escaped_string(p_fb, + p_type_found, p_fbobj); + } + /* Else the character is part of the quoted string */ + } /* end of loop over current text */ + + p_fb->p_data_cur = p_data_cur; /* update current position */ + const int rc = fb_fill(p_fb); /* Try to refill buffer */ + if (rc != 0) { /* EOF or error */ + if (rc < 0) { /* error */ + return -1; + } + /* Else EOF. Ended without closing quote, so add an implicit + * closing quote, i.e., end the string. Since fb_fill() + * did not return -1, there is at least 1 byte at the end of + * the buffer where the read would have gone. */ + *(p_fb->p_obj_end = p_fb->p_data_cur) = '\0'; + return fb_return_string(p_fb, p_type_found, p_fbobj); + } + p_data_cur = p_fb->p_data_cur; /* Update after fill */ + p_data_end = p_fb->p_data_end; + } /* end of loop processing until done or escape */ +} /* end of function fbget_quoted_unescaped_string */ + + + +/* Get a quoted string with an escape. The start has already been set on + * entry */ +static int fbget_quoted_escaped_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj) +{ + /* Step through characters until end */ + char *p_data_src = p_fb->p_data_cur; /* at current char */ + char *p_data_dst = p_data_src; /* at current char */ + char *p_data_end = p_fb->p_data_end; + bool f_escape_in_progress = false; + for ( ; ; ) { /* continue until done */ + for ( ; p_data_src != p_data_end; ++p_data_src) { /* current data */ + const char ch_cur = *p_data_src; + if (f_escape_in_progress) { /* Always copy the char */ + f_escape_in_progress = false; + *p_data_dst++ = ch_cur; + } + else { /* Not an escaped character */ + if (ch_cur == '"') { /* Closing quote, so done */ + p_fb->p_data_cur = p_data_src + 1; + *(p_fb->p_obj_end = p_data_dst) = '\0'; + return fb_return_string(p_fb, p_type_found, p_fbobj); + } + if (ch_cur == '\\') { /* Escape */ + f_escape_in_progress = true; + /* Do not copy the escape or advancd p_data_dst */ + } + else { /* ordinary character */ + *p_data_dst++ = ch_cur; + } + } /* end of case of not an escaped character */ + /* Else the character is part of the quoted string */ + } /* end of loop over current text */ + + /* Indicate that there is no more unprocessed data */ + p_fb->p_data_end = p_fb->p_data_cur = p_data_dst; + + /* If no pending escape, can switch back to unescaped version and + * avoid the moves */ + if (!f_escape_in_progress) { + return fbget_quoted_unescaped_string(p_fb, p_type_found, + p_fbobj); + } + + /* Else escape must be processed, so continue with escaped version */ + const int rc = fb_fill(p_fb); /* Try to refill buffer */ + if (rc != 0) { /* EOF or error */ + if (rc < 0) { /* error */ + return -1; + } + /* Else EOF. Ended without closing quote, so add an implicit + * closing quote, i.e., end the string. Since fb_fill() + * did not return -1, there is at least 1 byte at the end of + * the buffer where the read would have gone. */ + *(p_fb->p_obj_end = p_fb->p_data_cur) = '\0'; + return fb_return_string(p_fb, p_type_found, p_fbobj); + } + p_data_dst = p_data_src = p_fb->p_data_cur; /* Update after fill */ + p_data_end = p_fb->p_data_end; + } /* end of loop processing until done or escape */ +} /* end of function fbget_quoted_escaped_string */ + + + +/* Get an unquoted string starting at the current position */ +static int fbget_unquoted_string(FILEBUF *p_fb, + unsigned int n_type_wanted, FBTYPE *p_type_wanted, + FBTYPE *p_type_found, FBOBJ *p_fbobj) +{ + /* Save the start of the string as the current position */ + p_fb->p_obj_start = p_fb->p_data_cur; + + static const signed char p_map[1 << CHAR_BIT] = { + [(unsigned char ) ' '] = (signed char) +1, + [(unsigned char ) '\t'] = (signed char) +1, + [(unsigned char ) '\n'] = (signed char) +1, + [(unsigned char ) '\r'] = (signed char) +1, + [(unsigned char ) '\v'] = (signed char) +1, + [(unsigned char ) '\f'] = (signed char) +1, + [(unsigned char ) '*'] = (signed char) -1, + [(unsigned char ) '#'] = (signed char) -1 + }; + /* Step through characters until whitespace or comment */ + char *p_data_cur = p_fb->p_data_cur; + char *p_data_end = p_fb->p_data_end; + for ( ; ; ) { /* continue until done */ + for ( ; p_data_cur != p_data_end; ++p_data_cur) { /* current data */ + const char ch_cur = *p_data_cur; + const signed char map_cur = p_map[(unsigned char) ch_cur]; + if (map_cur != 0) { /* ws or comment start, so done */ + *(p_fb->p_obj_end = p_data_cur) = '\0'; + p_fb->p_data_cur = p_data_cur + 1; /* 1st char past string */ + p_fb->f_skip_to_eol = map_cur < 0; + return fb_return_obj(p_fb, n_type_wanted, p_type_wanted, + p_type_found, p_fbobj); + } + /* Else more of the string */ + } /* end of loop over current text */ + + p_fb->p_data_cur = p_data_cur; /* update current position */ + const int rc = fb_fill(p_fb); /* Try to refill buffer */ + if (rc != 0) { /* EOF or error */ + if (rc < 0) { /* error */ + return -1; + } + /* Else EOF. Ended without closing quote, so add an implicit + * closing quote, i.e., end the string. Since fb_fill() + * did not return -1, there is at least 1 byte at the end of + * the buffer where the read would have gone. */ + *(p_fb->p_obj_end = p_fb->p_data_cur) = '\0'; + return fb_return_obj(p_fb, n_type_wanted, p_type_wanted, + p_type_found, p_fbobj); + } + p_data_cur = p_fb->p_data_cur; /* Update after fill */ + p_data_end = p_fb->p_data_end; + } /* end of loop processing until done or escape */ +} /* end of function fbget_unquoted_string */ + + + +/* This function fills the buffer. First it moves all data in the interval + * [start current object, current position) to the beginning of the buffer. + * + * If there is no space left at the end of the buffer after the move (so + * that the move did not occur and data extends to the end), the buffer is + * doubled in size. In either case, the end of the buffer is filled with + * data read from the file. */ +static int fb_fill(FILEBUF *p_fb) +{ + /* Exit if EOF already */ + if (p_fb->is_eof) { + return +1; + } + + /* Move the data in use to the front of the buffer if not already and + * enlarge the buffer if still no space. Returned value is bytes + * available at the end of the buffer at p_data_end */ + const size_t n_byte_read = fb_make_space_at_end(p_fb); + if (n_byte_read == 0) { + return -1; + } + + const size_t n_got = fread(p_fb->p_data_end, 1, n_byte_read, p_fb->fp); + if (n_got < n_byte_read) { /* EOF or error */ + if (ferror(p_fb->fp)) { + return -1; + } + /* Else mark as EOF for subsequent calls */ + p_fb->is_eof = true; + + if (n_got == 0) { /* Nothing to return for this call */ + return +1; + } + /* Else partial buffer to return */ + } + + /* Extend the end of the data by the bytes obtained */ + p_fb->p_data_end += n_got; + return 0; +} /* end of function fb_fill */ + + + +/* Make space at the end of the buffer by moving data of current object + * to the front of the buffer and enlarging if there is still no room + * + * Return value: Number of spaces that are free at the end of p_buf on + * return. If 0, more space could not be obtained. + */ +static size_t fb_make_space_at_end(FILEBUF *p_fb) +{ + const char * const p_obj_start = p_fb->p_obj_start; + const char * const p_src = p_obj_start == (char *) NULL ? + p_fb->p_data_cur : p_obj_start; + char * const p_dst = p_fb->p_buf; + + /* Shift data in use to the front of the buffer if not already */ + if (p_dst != p_src) { /* object is not at start of buffer */ + const size_t n = p_fb->p_data_end - p_src; + if (n > 0) { /* Will be 0 if skipping whitespace and comments */ + (void) memmove(p_dst, p_src, n); + } + + /* Adjust pointers after the move */ + ptrdiff_t delta = p_src - p_dst; + p_fb->p_data_cur -= delta; + p_fb->p_data_end -= delta; + + if (p_obj_start != (char *) NULL) { + p_fb->p_obj_start -= delta; + } + /* never called when p_obj_end is valid */ + } + else { /* already at front */ + if (p_fb->p_buf_end - p_fb->p_data_end == 0) { + const size_t n_alloc_orig = p_fb->n_byte_buf_alloc; + + /* For debugging, this added size can be made very small to + * force many reallocs and to have strings end at "hard" + * locations such as right before where a terminating null + * should be added to a string */ + //const size_t n_added = 1; + const size_t n_added = n_alloc_orig; + + const size_t n_byte_buf_alloc_new = n_alloc_orig + n_added; + void * const p = realloc(p_fb->p_buf, n_byte_buf_alloc_new); + if (p == NULL) { + return 0; + } + /* Else allocation OK, so update buffer and internal pointers */ + ptrdiff_t delta = (char *) p - p_fb->p_buf; + p_fb->p_buf = (char *) p; + p_fb->p_buf_end = (char *) p + n_byte_buf_alloc_new; + p_fb->n_byte_buf_alloc = n_byte_buf_alloc_new; + p_fb->p_data_cur += delta; + p_fb->p_data_end += delta; + + if (p_obj_start != (char *) NULL) { + p_fb->p_obj_start += delta; + } + /* never called when p_obj_end is valid */ + } + } + + return p_fb->p_buf_end - p_fb->p_data_end; +} /* end of function fb_make_space_at_end */ + + + +/* Skip whitespace, including comments starting at the current position */ +static int fb_skip_whitespace(FILEBUF *p_fb) +{ + static const signed char p_map[1 << CHAR_BIT] = { + [(unsigned char ) ' '] = (signed char) +1, + [(unsigned char ) '\t'] = (signed char) +1, + [(unsigned char ) '\n'] = (signed char) +1, + [(unsigned char ) '\r'] = (signed char) +1, + [(unsigned char ) '\v'] = (signed char) +1, + [(unsigned char ) '\f'] = (signed char) +1, + [(unsigned char ) '*'] = (signed char) -1, + [(unsigned char ) '#'] = (signed char) -1 + }; + /* Step through characters until not whitespace (including comments) */ + char *p_data_cur = p_fb->p_data_cur; + char *p_data_end = p_fb->p_data_end; + for ( ; ; ) { /* continue until done */ + for ( ; p_data_cur != p_data_end; ++p_data_cur) { /* current data */ + const char ch_cur = *p_data_cur; + const signed char map_cur = p_map[(unsigned char) ch_cur]; + if (map_cur == 0) { /* not in ws or at comment start, so done */ + p_fb->p_data_cur = p_data_cur; + return 0; + } + if (map_cur == -1) { /* a comment has started */ + p_fb->p_data_cur = p_data_cur + 1; /* after comment start */ + const int rc = fb_skip_to_eol(p_fb); + if (rc != 0) { /* EOF or error */ + return rc; + } + + /* Update local variables. Note that p_fb->p_data_cur is at + * the character after the comment, which is a \n or \r. + * These characters are whitespace that will be skipped, + * so incrementing past it in the ++p_data_cur of the for() + * only skips a character that will be skipped anyhow. + * (A long comment to say that + * p_data_cur = p_fb->p_data_cur - 1 is not necessary.) */ + p_data_cur = p_fb->p_data_cur; + p_data_end = p_fb->p_data_end; + } /* end of comment processing */ + /* Else whitespace, which is skipped */ + } /* end of loop over current text */ + + p_fb->p_data_cur = p_data_cur; /* update current position */ + const int rc = fb_fill(p_fb); /* Try to refill buffer */ + if (rc != 0) { /* EOF or error */ + return rc; + } + /* Else got more text to process */ + p_data_cur = p_fb->p_data_cur; /* Update after fill */ + p_data_end = p_fb->p_data_end; + } /* end of loop over text pieces */ +} /* end of function fb_skip_whitespace */ + + + +/* Skip text to EOL char, starting at the current position */ +static int fb_skip_to_eol(FILEBUF *p_fb) +{ + /* Step through characters until not whitespace (including comments) */ + char *p_data_cur = p_fb->p_data_cur; + char *p_data_end = p_fb->p_data_end; + for ( ; ; ) { /* continue until done */ + for ( ; p_data_cur != p_data_end; ++p_data_cur) { /* current data */ + const char ch_cur = *p_data_cur; + if (ch_cur == '\n' || ch_cur == '\r') { + p_fb->p_data_cur = p_data_cur; + return 0; + } + /* Else not EOL, which is skipped */ + } /* end of loop over current text */ + + p_fb->p_data_cur = p_data_cur; /* update current position */ + const int rc = fb_fill(p_fb); /* Try to refill buffer */ + if (rc != 0) { /* EOF or error */ + return rc; + } + /* Else got more text to process */ + p_data_cur = p_fb->p_data_cur; /* Update after fill */ + p_data_end = p_fb->p_data_end; + } /* end of loop over text pieces */ +} /* end of function fb_skip_to_eol */ + + + +/* Return the data found in the most preferred format possible */ +static int fb_return_obj(FILEBUF *p_fb, + unsigned int n_type_wanted, FBTYPE *p_type_wanted, + FBTYPE *p_type_found, FBOBJ *p_fbobj) +{ + const char * const p_obj_start = p_fb->p_obj_start; /* data to convert */ + const char * const p_obj_end = p_fb->p_obj_end; + + /* Must test for null string separately since strto* does not set + * errno in this case. Aside from that, it can only be returned + * as a string anyhow. */ + if (p_obj_start != p_obj_end) { /* have a string besides "" */ + unsigned int i; + for (i = 0; i < n_type_wanted; ++i) { + FBTYPE type_cur = p_type_wanted[i]; + errno = 0; + if (type_cur == BUF_TYPE_ULONG) { + char *p_end; + unsigned long val = strtoul(p_obj_start, &p_end, 10); + /* Test for processing of full string. Note that checking + * for the end of the string rather than a NULL handles the + * case of an embedded NULL which the latter test would + * not */ + if (errno == 0 && p_end == p_obj_end) { + *p_type_found = BUF_TYPE_ULONG; + p_fbobj->ulong_value = val; + return 0; + } + } + else if (type_cur == BUF_TYPE_LONG) { + char *p_end; + long val = strtol(p_obj_start, &p_end, 10); + if (errno == 0 && p_end == p_obj_end) { + *p_type_found = BUF_TYPE_LONG; + p_fbobj->long_value = val; + return 0; + } + } + else if (type_cur == BUF_TYPE_DOUBLE) { + char *p_end; + double val = strtod(p_obj_start, &p_end); + if (errno == 0 && p_end == p_obj_end) { + *p_type_found = BUF_TYPE_DOUBLE; + p_fbobj->dbl_value = val; + return 0; + } + } + else if (type_cur == BUF_TYPE_STRING) { + break; /* exit loop and use default return of string */ + } + else { /* unknown type */ + print_error("Unknown output data type %d is ignored.", + (int) type_cur); + } + } /* end of loop trying types */ + } /* end of case that string is not "" */ + + /* If no rquested type was converted OK or string requested, return as + * a string */ + return fb_return_string(p_fb, p_type_found, p_fbobj); +} /* end of function fb_return_obj */ + + + +/* Return string */ +static int fb_return_string(FILEBUF *p_fb, + FBTYPE *p_type_found, FBOBJ *p_fbobj) +{ + const char *p_data_start = + p_fbobj->str_value.sz = p_fb->p_obj_start; + p_fbobj->str_value.n_char = p_fb->p_obj_end - p_data_start; + *p_type_found = BUF_TYPE_STRING; + return 0; +} /* end of function fb_return_string */ + + + diff --git a/src/xspice/cmpp/file_buffer.h b/src/xspice/cmpp/file_buffer.h new file mode 100644 index 000000000..bee1f76fc --- /dev/null +++ b/src/xspice/cmpp/file_buffer.h @@ -0,0 +1,58 @@ +#ifndef file_buffer_h_included +#define file_buffer_h_included + +#include + + +/* Null-terminated string prefixed by length excluding null */ +typedef struct Filebuf_len_str { + size_t n_char; /* length of string excluding null termination */ + char *sz; /* Start of string */ +} FBSTRING; + +/* Union for returned value */ +typedef union Filebuf_obj { + FBSTRING str_value; + unsigned long ulong_value; + long long_value; + double dbl_value; +} FBOBJ; + +/* Structure for getting file data */ +typedef struct Filebuf { + FILE *fp; /* handle to file */ + bool is_eof; /* flag that EOF reached */ + bool f_skip_to_eol; + /* Flag that text until the next EOL character should be + * skipped before getting the next item from the buffer. + * This flag is set when a comment terminates an item, + * such as "abc# This is a comment." */ + size_t n_byte_buf_alloc; /* Allocated buffer size */ + char *p_buf; /* buffer to receive data from file */ + char *p_obj_start; /* start of object being returned */ + char *p_obj_end; /* byte past object being returned */ + char *p_data_cur; /* current position in buffer. Depending on + * circumstances, it points to either the character + * being processed or the next character to process */ + char *p_data_end; /* byte past end of data in buffer */ + char *p_buf_end; /* byte past end of allocated buffer size, equal to + * p_buf + n_byte_buf_alloc, so it is redundant, but + * convenient to have available */ +} FILEBUF; + +/* Types of data */ +typedef enum FBtype { + BUF_TYPE_STRING, /* value type string (always possible) */ + BUF_TYPE_ULONG, /* value type an unsigned int */ + BUF_TYPE_LONG, /* value type an int */ + BUF_TYPE_DOUBLE /* value type double */ +} FBTYPE; + + +FILEBUF *fbopen(const char *filename, size_t n_byte_buf_init); +int fbget(FILEBUF *p_fb, unsigned int n_type_wanted, FBTYPE *p_type_wanted, + FBTYPE *p_type_found, FBOBJ *p_fbobj); +int fbclose(FILEBUF *fbp); + + +#endif /* include guard */ diff --git a/src/xspice/cmpp/main.c b/src/xspice/cmpp/main.c index 94ad9fff5..d49f30f77 100644 --- a/src/xspice/cmpp/main.c +++ b/src/xspice/cmpp/main.c @@ -35,25 +35,37 @@ REFERENCED FILES NON-STANDARD FEATURES None. - ============================================================================*/ +#ifdef DEBUG_CMPP +#ifdef _WIN32 +#include +#endif +#endif #include #include #include + #include "cmpp.h" -#define USAGE_MSG "Usage: cmpp [-ifs] [-mod []] [-lst]" +#define USAGE_MSG \ + "Usage: cmpp [-ifs] | [-mod []] | [-lst] | [-p fn.lst]" #define TOO_FEW_ARGS "ERROR - Too few arguments" #define TOO_MANY_ARGS "ERROR - Too many arguments" #define UNRECOGNIZED_ARGS "ERROR - Unrecognized argument" +#ifdef DEBUG_CMPP +#define PRINT_CMPP_INFO(argc, argv) print_cmpp_info(argc, argv); +static void print_cmpp_info(int argc, char **argv); +#else +#define PRINT_CMPP_INFO(argc, argv) +#endif + + /* *********************************************************************** */ - - /* main @@ -61,9 +73,11 @@ Function main checks the validity of the command-line arguments supplied when the program is invoked and calls one of the three major functions as appropriate: - preprocess_ifs_file Process Interface Specification File. - preprocess_mod_file Process Model Definition File. - preprocess_lst_file Process Pathname List Files. + preprocess_ifs_file Process Interface Specification File. + preprocess_mod_file Process Model Definition File. + preprocess_lst_file Process Pathname List Files. + output_paths_from_lst_file Write paths from a list file to stdout + to facilite building the code models depending on the argument. */ @@ -72,11 +86,11 @@ int main( int argc, /* Number of command line arguments */ char *argv[]) /* Command line argument text */ { - init_error (argv[0]); - /* Process command line arguments and vector to appropriate function */ + PRINT_CMPP_INFO(argc, argv) + /* Process command line arguments and vector to appropriate function */ if(argc < 2) { print_error(TOO_FEW_ARGS); print_error(USAGE_MSG); @@ -115,6 +129,26 @@ int main( print_error(USAGE_MSG); exit(1); } + } + else if (strcmp(argv[1],"-p") == 0) { /* Output paths from a list file */ + if (argc == 3) { + const int n_item = output_paths_from_lst_file(argv[2]); + if (n_item < 0) { + print_error("Unable to print paths to stdout"); + exit(-1); + } + exit(n_item); + } + else { /* Wrong number of arguments */ + if (argc < 3) { + print_error(TOO_FEW_ARGS); + } + else { + print_error(TOO_MANY_ARGS); + } + print_error(USAGE_MSG); + exit(1); + } } else { print_error(UNRECOGNIZED_ARGS); @@ -123,5 +157,67 @@ int main( } exit(0); -} +} /* end of function main */ + + + +#ifdef DEBUG_CMPP +/* Print some debugging information for cmpp + * + * With the use of environment variables to locate files, it is helpful + * to know some information about the program when debugging. If the + * build of a code model fails due to cmpp, the macro can be enabled to + * find the information needed to separately debug cmpp */ +static void print_cmpp_info(int argc, char **argv) +{ + /* Print the program and its arguments */ + { + int i; + for (i = 0; i < argc; ++i) { + (void) fprintf(stdout, "%s ", argv[i]); + } + (void) fprintf(stdout, "\n"); + } + +#ifdef _WIN32 + /* Print the current directory */ + { + const DWORD n_char = GetCurrentDirectoryA(0, (char *) NULL); + if (n_char > 0) { + char *p_buf = (char *) malloc(n_char); + if (p_buf != (char *) NULL) { + if (GetCurrentDirectoryA(n_char, p_buf) != 0) { + (void) fprintf(stdout, "Current Directory: \"%s\".\n", + p_buf); + } + free(p_buf); + } + } + } +#endif + + /* Print the CMPP_IDIR environment variable if defined */ + { + const char * const ev = getenv("CMPP_IDIR"); + if (ev) { + (void) fprintf(stdout, "CMPP_IDIR = \"%s\"\n", ev); + } + else { + (void) fprintf(stdout, "CMPP_IDIR is not defined\n"); + } + } + + /* Print the CMPP_ODIR environment variable if defined */ + { + const char * const ev = getenv("CMPP_ODIR"); + if (ev) { + (void) fprintf(stdout, "CMPP_ODIR = \"%s\"\n", ev); + } + else { + (void) fprintf(stdout, "CMPP_ODIR is not defined\n"); + } + } +} /* end of function print_cmpp_info */ +#endif /* #ifdef DEBUG_CMPP */ + diff --git a/src/xspice/cmpp/pp_ifs.c b/src/xspice/cmpp/pp_ifs.c index b6bd99a12..830633fef 100644 --- a/src/xspice/cmpp/pp_ifs.c +++ b/src/xspice/cmpp/pp_ifs.c @@ -42,9 +42,6 @@ NON-STANDARD FEATURES -/* *********************************************************************** */ - - /* preprocess_ifs_file @@ -65,7 +62,6 @@ void preprocess_ifs_file(void) int status; /* Return status */ - /* Read the entire ifspec.ifs file and load the data into ifs_table */ status = read_ifs_file(IFSPEC_FILENAME,GET_IFS_TABLE,&ifs_table); @@ -82,8 +78,56 @@ void preprocess_ifs_file(void) if(status != 0) { exit(1); } - + rem_ifs_table(&ifs_table); } +void rem_ifs_table(Ifs_Table_t *ifs_table) +{ + /* Remove the ifs_table */ + free(ifs_table->name.c_fcn_name); + free(ifs_table->name.description); + free(ifs_table->name.model_name); + + { + Conn_Info_t * const p_conn = ifs_table->conn; + const int num_conn = ifs_table->num_conn; + int i; + for (i = 0; i < num_conn; ++i) { + Conn_Info_t *p_conn_cur = p_conn + i; + free(p_conn_cur->name); + free(p_conn_cur->description); + free(p_conn_cur->default_type); + } + } + + { + Param_Info_t * const p_param = ifs_table->param; + const int num_param = ifs_table->num_param; + int i; + for (i = 0; i < num_param; ++i) { + Param_Info_t *p_param_cur = p_param + i; + free(p_param_cur->name); + free(p_param_cur->description); + } + } + + { + Inst_Var_Info_t * const p_inst_var = ifs_table->inst_var; + const int num_inst_var = ifs_table->num_inst_var; + int i; + for(i = 0; i < num_inst_var; ++i) { + Inst_Var_Info_t *p_inst_var_cur = p_inst_var + i; + free(p_inst_var_cur->name); + free(p_inst_var_cur->description); + } + } + + free(ifs_table->conn); + free(ifs_table->param); + free(ifs_table->inst_var); +} /* end of function rem_ifs_table */ + + + diff --git a/src/xspice/cmpp/pp_lst.c b/src/xspice/cmpp/pp_lst.c index b04394920..3d321a396 100644 --- a/src/xspice/cmpp/pp_lst.c +++ b/src/xspice/cmpp/pp_lst.c @@ -47,11 +47,15 @@ NON-STANDARD FEATURES ============================================================================*/ -#include "cmpp.h" #include +#include +#include +#include #include #include +#include "cmpp.h" +#include "file_buffer.h" /* *********************************************************************** */ @@ -63,34 +67,56 @@ typedef struct { char *path_name; /* Pathname read from model path file */ char *spice_name; /* Name of model from ifspec.ifs */ char *cfunc_name; /* Name of C fcn from ifspec.ifs */ - bool spice_unique; /* True if spice name unique */ - bool cfunc_unique; /* True if C fcn name unique */ + unsigned int version; /* version of the code model */ } Model_Info_t; typedef struct { char *path_name; /* Pathname read from udn path file */ char *node_name; /* Name of node type */ - bool unique; /* True if node type name unique */ + unsigned int version; /* version of the code model */ } Node_Info_t; - -/* *********************************************************************** */ +/* Structure for uniqueness testing */ +struct Key_src { + const char *key; /* value to compare */ + const char *src; /* source of value */ +}; + + + +/************************************************************************ */ + +static int cmpr_ks(const struct Key_src *ks1, const struct Key_src *ks2); +static void free_model_info(int num_models, Model_Info_t *p_model_info); +static void free_node_info(int num_nodes, Node_Info_t *p_node_info); static int read_modpath(int *num_models, Model_Info_t **model_info); static int read_udnpath(int *num_nodes, Node_Info_t **node_info); static int read_model_names(int num_models, Model_Info_t *model_info); static int read_node_names(int num_nodes, Node_Info_t *node_info); static int check_uniqueness(int num_models, Model_Info_t *model_info, - int num_nodes, Node_Info_t *node_info); + int num_nodes, Node_Info_t *node_info); +static void report_error_spice_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2); +static void report_error_function_name (const struct Key_src *p_ks1, + const struct Key_src *p_ks2); +static void report_error_udn_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2); +static bool test_for_duplicates(unsigned int n, struct Key_src *p_ks, + void (*p_error_reporter)(const struct Key_src *p_ks1, + const struct Key_src *p_ks2)); +static inline void trim_slash(size_t *p_n, char *p); static int write_CMextrn(int num_models, Model_Info_t *model_info); static int write_CMinfo(int num_models, Model_Info_t *model_info); +static int write_CMinfo2(int num_models, Model_Info_t *model_info); static int write_UDNextrn(int num_nodes, Node_Info_t *node_info); static int write_UDNinfo(int num_nodes, Node_Info_t *node_info); +static int write_UDNinfo2(int num_nodes, Node_Info_t *node_info); static int write_objects_inc(int num_models, Model_Info_t *model_info, - int num_nodes, Node_Info_t *node_info); + int num_nodes, Node_Info_t *node_info); static int read_udn_type_name(const char *path, char **node_name); @@ -101,7 +127,7 @@ static int read_udn_type_name(const char *path, char **node_name); preprocess_lst_files Function preprocess_lst_files is the top-level driver function for -preprocessing a simulator model path list file (modpath.lst). +preprocessing a simulator model path list file (modpath.lst). This function calls read_ifs_file() requesting it to read and parse the Interface Specification file (ifspec.ifs) to extract the model name and associated C function name and place this @@ -125,20 +151,18 @@ void preprocess_lst_files(void) int num_models; /* The number of models */ int num_nodes; /* The number of user-defined nodes */ - /* Get list of models from model pathname file */ status = read_modpath(&num_models, &model_info); - if(status != 0) { + if (status != 0) { exit(1); } /* Get list of node types from udn pathname file */ status = read_udnpath(&num_nodes, &node_info); - if(status != 0) { + if (status < 0) { exit(1); } - /* Get the spice and C function names from the ifspec.ifs files */ status = read_model_names(num_models, model_info); if(status != 0) { @@ -151,15 +175,12 @@ void preprocess_lst_files(void) exit(1); } - /* Check to be sure the names are unique */ - status = check_uniqueness(num_models, model_info, - num_nodes, node_info); + status = check_uniqueness(num_models, model_info, num_nodes, node_info); if(status != 0) { exit(1); } - /* Write out the CMextrn.h file used to compile SPIinit.c */ status = write_CMextrn(num_models, model_info); if(status != 0) { @@ -171,7 +192,10 @@ void preprocess_lst_files(void) if(status != 0) { exit(1); } - + status = write_CMinfo2(num_models, model_info); + if(status != 0) { + exit(1); + } /* Write out the UDNextrn.h file used to compile SPIinit.c */ status = write_UDNextrn(num_nodes, node_info); @@ -184,7 +208,10 @@ void preprocess_lst_files(void) if(status != 0) { exit(1); } - + status = write_UDNinfo2(num_nodes, node_info); + if(status != 0) { + exit(1); + } /* Write the make_include file used to link the models and */ /* user-defined node functions with the simulator */ @@ -194,7 +221,106 @@ void preprocess_lst_files(void) exit(1); } -} + /* Free allocations */ + if (model_info != (Model_Info_t *) NULL) { + free_model_info(num_models, model_info); + } + if (node_info != (Node_Info_t *) NULL) { + free_node_info(num_nodes, node_info); + } +} /* end of function preprocess_lst_files */ + + + +/* This function parses the supplied .lst file and outputs the paths to + * stdout */ +int output_paths_from_lst_file(const char *filename) +{ + int xrc = 0; + FILEBUF *fbp = (FILEBUF *) NULL; /* for reading MODPATH_FILENAME */ + unsigned int n_path = 0; + + /* Open the file */ + if ((fbp = fbopen(filename, 0)) == (FILEBUF *) NULL) { + print_error("ERROR - Unable to open file \"%s\" to obtain " + "paths: %s", + filename, strerror(errno)); + xrc = -1; + goto EXITPOINT; + } + + bool f_have_path = false; /* do not have a path to store */ + FBTYPE fbtype; + FBOBJ fbobj; + for ( ; ; ) { /* Read items until end of file */ + /* Get the next path if not found yet */ + if (!f_have_path) { + const int rc = fbget(fbp, 0, (FBTYPE *) NULL, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + + /* Output the file that was found */ + if (fprintf(stdout, "%s\n", fbobj.str_value.sz) < 0) { + print_error("ERROR - Unable to output path name to stdout: %s", + strerror(errno)); + xrc = -1; + goto EXITPOINT; + } + ++n_path; /* 1 more path printed OK */ + + /* Try getting a version. If found, it will be discarded */ + FBTYPE type_wanted = BUF_TYPE_ULONG; + const int rc = fbget(fbp, 1, &type_wanted, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + if (fbtype == BUF_TYPE_ULONG) { /* found version number */ + f_have_path = false; + } + else { /* it was a string, so it is the next path */ + f_have_path = true; + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + } /* end of loop reading items into buffer */ + +EXITPOINT: + /* Close model pathname file and return data read */ + if (fbclose(fbp) != 0) { + print_error("ERROR - Unable to close file with path names: %s", + strerror(errno)); + xrc = -1; + } + + /* Return the path count if no errors */ + if (xrc == 0) { + xrc = (int) n_path; + } + + return xrc; +} /* end of function output_paths_from_lst_file */ + @@ -209,109 +335,169 @@ file, and puts them into an internal data structure for future processing. */ +/* Structure for retrieving data items from the file. These will be either + * names, such as directory names or unsigned integers that are version + * numbers */ +#define N_MODEL_INIT 10 static int read_modpath( - int *num_models, /* Number of model pathnames found */ - Model_Info_t **model_info /* Info about each model */ -) + int *p_num_model_info, /* Number of model pathnames found */ + Model_Info_t **pp_model_info) /* Info about each model */ { - FILE *fp; /* Model pathname file pointer */ - char path[MAX_PATH_LEN+2]; /* space to read pathnames into */ - Model_Info_t *model = NULL; /* temporary pointer to model info */ - - int n; - int i; - int j; - int len; - int line_num; - - const char *filename = MODPATH_FILENAME; - - - /* Initialize number of models to zero in case of error */ - *num_models = 0; + int xrc = 0; + FILEBUF *fbp = (FILEBUF *) NULL; /* for reading MODPATH_FILENAME */ + Model_Info_t *p_model_info = (Model_Info_t *) NULL; + unsigned int n_model_info = 0; + unsigned int n_model_info_alloc = 0; + char *filename = (char *) NULL; /* Open the model pathname file */ - fp = fopen_cmpp(&filename, "r"); - - if (fp == NULL) { - print_error("ERROR - File not found: %s", filename); - return -1; + if ((filename = gen_filename(MODPATH_FILENAME, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build mod path file name"); + xrc = -1; + goto EXITPOINT; + } + /* Open the file using the default buffer size. For debugging, a very + * small value can be used, for example by giving the size as 1, to + * force the function do actions that otherwise would be done rarely + * if at all. */ + if ((fbp = fbopen(filename, 0)) == (FILEBUF *) NULL) { + print_error("ERROR - Unable to open mod path file \"%s\": %s", + filename, strerror(errno)); + xrc = -1; + goto EXITPOINT; } - /* Read the pathnames from the file, one line at a time until EOF */ - n = 0; - line_num = 0; - while( fgets(path, sizeof(path), fp) ) { + /* Allocate initial model info array */ + if ((p_model_info = (Model_Info_t *) malloc(N_MODEL_INIT * + sizeof(Model_Info_t))) == (Model_Info_t *) NULL) { + print_error("ERROR - Unable to allocate initial model array"); + xrc = -1; + goto EXITPOINT; + } + n_model_info_alloc = N_MODEL_INIT; - line_num++; - len = (int) strlen(path); + bool f_have_path = false; /* do not have a path to store */ + FBTYPE fbtype; + FBOBJ fbobj; + for ( ; ; ) { /* Read items until end of file */ + /* Get the next path if not found yet */ + if (!f_have_path) { + const int rc = fbget(fbp, 0, (FBTYPE *) NULL, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ - /* If line was too long for buffer, exit with error */ - if(len > MAX_PATH_LEN) { - print_error("ERROR - Line %d of %s exceeds %d characters", - line_num, filename, MAX_PATH_LEN); - return -1; + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); } - /* Strip white space including newline */ - for(i = 0, j = 0; i < len; ) { - if(isspace_c(path[i])) { - i++; - } - else { - path[j] = path[i]; - i++; - j++; + /* Enlarge model array if full */ + if (n_model_info_alloc == n_model_info) { + n_model_info_alloc *= 2; + void * const p = realloc(p_model_info, + n_model_info_alloc * sizeof(Model_Info_t)); + if (p == NULL) { + print_error("ERROR - Unable to enlarge model array"); + xrc = -1; + goto EXITPOINT; } + p_model_info = (Model_Info_t *) p; } - path[j] = '\0'; - len = j; - - /* Strip trailing '/' if any */ - if(path[len - 1] == '/') - path[--len] = '\0'; - - /* If blank line, continue */ - if(len == 0) - continue; - - /* Make sure pathname is short enough to add a filename at the end */ - if(len > (MAX_PATH_LEN - (MAX_FN_LEN + 1)) ) { - print_error("ERROR - Pathname on line %d of %s exceeds %d characters", - line_num, filename, (MAX_PATH_LEN - (MAX_FN_LEN + 1))); - return -1; - } - - /* Allocate and initialize a new model info structure */ - if(n == 0) - model = (Model_Info_t *) malloc(sizeof(Model_Info_t)); - else - model = (Model_Info_t *) realloc(model, (size_t) (n + 1) * sizeof(Model_Info_t)); - model[n].path_name = NULL; - model[n].spice_name = NULL; - model[n].cfunc_name = NULL; - model[n].spice_unique = true; - model[n].cfunc_unique = true; /* Put pathname into info structure */ - model[n].path_name = (char *) malloc((size_t) (len+1)); - strcpy(model[n].path_name, path); + Model_Info_t * const p_model_info_cur = p_model_info + + n_model_info; - /* Increment count of paths read */ - n++; + if ((p_model_info_cur->path_name = (char *) malloc( + fbobj.str_value.n_char + 1)) == (char *) NULL) { + print_error("ERROR - Unable to allocate path name"); + xrc = -1; + goto EXITPOINT; + } + + strcpy(p_model_info_cur->path_name, fbobj.str_value.sz); + p_model_info_cur->spice_name = (char *) NULL; + p_model_info_cur->cfunc_name = (char *) NULL; + + /* Must set before returning due to EOF. */ + p_model_info_cur->version = 1; + ++n_model_info; + + /* Try getting a version */ + FBTYPE type_wanted = BUF_TYPE_ULONG; + const int rc = fbget(fbp, 1, &type_wanted, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + if (fbtype == BUF_TYPE_ULONG) { /* found version number */ + f_have_path = false; + p_model_info_cur->version = (unsigned int) fbobj.ulong_value; + } + else { /* it was a string, so it is the next path */ + f_have_path = true; + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + } /* end of loop reading items into buffer */ + +EXITPOINT: + /* Close model pathname file and return data read */ + if (fbclose(fbp) != 0) { + print_error("ERROR - Unable to close file with model info: %s", + strerror(errno)); + xrc = -1; } + /* Free name of file being used */ + if (filename) { + free((void *) filename); + } - /* Close model pathname file and return data read */ - fclose(fp); + /* If error, free model info */ + if (xrc != 0) { + free_model_info(n_model_info, p_model_info); + n_model_info = 0; + p_model_info = (Model_Info_t *) NULL; + } - *num_models = n; - *model_info = model; + *p_num_model_info = n_model_info; + *pp_model_info = p_model_info; - return 0; + return xrc; +} /* end of function read_modpath */ + + + +/* Remove slash at end of path name if present */ +static inline void trim_slash(size_t *p_n, char *p) +{ + size_t n = *p_n; + if (n > 1) { + char * const p_last = p + n - 1; + if (*p_last == '/') { + *p_last = '\0'; + --*p_n; + } + } +} /* end of function trim_slash */ -} /* *********************************************************************** */ @@ -326,107 +512,153 @@ processing. */ +#define N_NODE_INIT 5 + static int read_udnpath( - int *num_nodes, /* Number of node pathnames found */ - Node_Info_t **node_info /* Info about each node */ + int *p_num_node_info, /* Addr to receive # node pathnames */ + Node_Info_t **pp_node_info /* Addr to receive node info */ ) { - FILE *fp; /* Udn pathname file pointer */ - char path[MAX_PATH_LEN+2]; /* space to read pathnames into */ - Node_Info_t *node = NULL; /* temporary pointer to node info */ + int xrc = 0; + FILEBUF *fbp = (FILEBUF *) NULL; /* For reading Udn pathname */ + Node_Info_t *p_node_info = (Node_Info_t *) NULL; + /* array of node info */ + unsigned int n_node_info = 0; + unsigned int n_node_info_alloc = 0; + char *filename = (char *) NULL; - int n; - int i; - int j; - int len; - int line_num; - - const char *filename = UDNPATH_FILENAME; - - - /* Initialize number of nodes to zero in case of error */ - *num_nodes = 0; /* Open the node pathname file */ - fp = fopen_cmpp(&filename, "r"); - - /* For backward compatibility, return with WARNING only if file not found */ - if(fp == NULL) { - print_error("WARNING - File not found: %s", filename); - return 0; + if ((filename = gen_filename(UDNPATH_FILENAME, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build udn path file name"); + xrc = -1; + goto EXITPOINT; } - /* Read the pathnames from the file, one line at a time until EOF */ - n = 0; - line_num = 0; - while( fgets(path, sizeof(path), fp) ) { + /* For backward compatibility, return with WARNING only if file + * not found */ + if ((fbp = fbopen(filename, 0)) == (FILEBUF *) NULL) { + print_error("WARNING - File not found: %s", filename); + xrc = +1; + goto EXITPOINT; + } - line_num++; - len = (int) strlen(path); + /* Allocate initial node info array */ + if ((p_node_info = (Node_Info_t *) malloc(N_NODE_INIT * + sizeof(Node_Info_t))) == (Node_Info_t *) NULL) { + print_error("ERROR - Unable to allocate initial node array"); + xrc = -1; + goto EXITPOINT; + } + n_node_info_alloc = N_NODE_INIT; - /* If line was too long for buffer, exit with error */ - if(len > MAX_PATH_LEN) { - print_error("ERROR - Line %d of %s exceeds %d characters", - line_num, filename, MAX_PATH_LEN); - return -1; + bool f_have_path = false; /* do not have a path to store */ + FBTYPE fbtype; + FBOBJ fbobj; + + for ( ; ; ) { /* Read items until end of file */ + /* Get the next path if not found yet */ + if (!f_have_path) { + const int rc = fbget(fbp, 0, (FBTYPE *) NULL, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); } - /* Strip white space including newline */ - for(i = 0, j = 0; i < len; ) { - if(isspace_c(path[i])) { - i++; - } - else { - path[j] = path[i]; - i++; - j++; + + /* Enlarge node array if full */ + if (n_node_info_alloc == n_node_info) { + n_node_info_alloc *= 2; + void * const p = realloc(p_node_info, + n_node_info_alloc * sizeof(Node_Info_t)); + if (p == NULL) { + print_error("ERROR - Unable to enlarge node array"); + xrc = -1; + goto EXITPOINT; } + p_node_info = (Node_Info_t *) p; } - path[j] = '\0'; - len = j; - - /* Strip trailing '/' if any */ - if(path[len - 1] == '/') - path[--len] = '\0'; - - /* If blank line, continue */ - if(len == 0) - continue; - - /* Make sure pathname is short enough to add a filename at the end */ - if(len > (MAX_PATH_LEN - (MAX_FN_LEN + 1)) ) { - print_error("ERROR - Pathname on line %d of %s exceeds %d characters", - line_num, filename, (MAX_PATH_LEN - (MAX_FN_LEN + 1))); - return -1; - } - - /* Allocate and initialize a new node info structure */ - if(n == 0) - node = (Node_Info_t *) malloc(sizeof(Node_Info_t)); - else - node = (Node_Info_t *) realloc(node, (size_t) (n + 1) * sizeof(Node_Info_t)); - node[n].path_name = NULL; - node[n].node_name = NULL; - node[n].unique = true; /* Put pathname into info structure */ - node[n].path_name = (char *) malloc((size_t) (len+1)); - strcpy(node[n].path_name, path); + Node_Info_t * const p_node_info_cur = p_node_info + + n_node_info; - /* Increment count of paths read */ - n++; + if ((p_node_info_cur->path_name = (char *) malloc( + fbobj.str_value.n_char + 1)) == (char *) NULL) { + print_error("ERROR - Unable to allocate path name"); + xrc = -1; + goto EXITPOINT; + } + + strcpy(p_node_info_cur->path_name, fbobj.str_value.sz); + p_node_info_cur->node_name = NULL; + + /* Must set before returning due to EOF. */ + p_node_info_cur->version = 1; + ++n_node_info; + + /* Try getting a version */ + FBTYPE type_wanted = BUF_TYPE_ULONG; + const int rc = fbget(fbp, 1, &type_wanted, &fbtype, &fbobj); + if (rc != 0) { + if (rc == -1) { /* Error */ + print_error("ERROR - Unable to read item to buffer"); + xrc = -1; + goto EXITPOINT; + } + else { /* +1 -- EOF */ + break; + } + } /* end of abnormal case */ + + if (fbtype == BUF_TYPE_ULONG) { /* found version number */ + f_have_path = false; + p_node_info_cur->version = (unsigned int) fbobj.ulong_value; + } + else { /* it was a string, so it is the next path */ + f_have_path = true; + + /* Remove trailing slash if appended to path */ + trim_slash(&fbobj.str_value.n_char, fbobj.str_value.sz); + } + + } /* end of loop reading items into buffer */ + +EXITPOINT: + /* Close model pathname file and return data read */ + if (fbclose(fbp) != 0) { + print_error("ERROR - Unable to close file with node info: %s", + strerror(errno)); + xrc = -1; } + /* Free name of file being used */ + if (filename) { + free((void *) filename); + } - /* Close node pathname file and return data read */ - fclose(fp); + /* If error, free node info */ + if (xrc != 0) { + free_node_info(n_node_info, p_node_info); + n_node_info = 0; + p_node_info = (Node_Info_t *) NULL; + } - *num_nodes = n; - *node_info = node; + *p_num_node_info = n_node_info; + *pp_node_info = p_node_info; - return 0; - -} + return xrc; +} /* end of function read_udnpath */ @@ -445,44 +677,109 @@ static int read_model_names( Model_Info_t *model_info /* Info about each model */ ) { - bool all_found; /* True if all ifspec files read */ - int i; /* A temporary counter */ - char path[MAX_PATH_LEN+1]; /* full pathname to ifspec file */ - int status; /* Return status */ - Ifs_Table_t ifs_table; /* Repository for info read from ifspec file */ + bool all_found = true; /* True if all ifspec files read */ + int i; /* A temporary counter */ + char path_stack[100]; /* full pathname to ifspec file if from stack */ + char *path = path_stack; /* actual path buffer */ + int status; /* Return status */ + + /* Repository for info read from ifspec file.*/ + Ifs_Table_t ifs_table; + + /* Find the required buffer size and allocate if the default buffer + * on the stack is too small */ + { + int j; + size_t n_byte_needed = 0; + for (j = 0; j < num_models; j++) { /* max(model path lengths) */ + const size_t n = strlen(model_info[j].path_name); + if (n_byte_needed < n) { + n_byte_needed = n; + } + } + n_byte_needed += 1 + strlen(IFSPEC_FILENAME) + 1; + if (n_byte_needed > sizeof path_stack) { + if ((path = (char *) malloc(n_byte_needed)) == (char *) NULL) { + print_error("ERROR - Unable to allocate a buffer " + "for model paths"); + return -1; + } + } + } /* For each model found in model pathname file, read the interface */ /* spec file to get the SPICE and C function names into model_info */ + for(i = 0; i < num_models; i++) { + Model_Info_t *p_model_info_cur = model_info + i; - for(i = 0, all_found = true; i < num_models; i++) { + /* 0 for error recovery */ + (void) memset(&ifs_table, 0, sizeof ifs_table); - /* Form the full pathname to the interface spec file */ - strcpy(path, model_info[i].path_name); - strcat(path, "/"); - strcat(path, IFSPEC_FILENAME); + /* Form the full pathname to the interface spec file. Size has + * been checked to ensure that all strings will fit. */ + { + char *p_dst = path; + + /* Copy path name */ + const char *p_src = model_info[i].path_name; + for ( ; ; ) { + const char ch_cur = *p_src; + if (ch_cur == '\0') { + break; + } + *p_dst++ = ch_cur; + ++p_src; + } + *p_dst++ = '/'; /* add directory separator */ + strcpy(p_dst, IFSPEC_FILENAME); + } /* Read the SPICE and C function names from the interface spec file */ status = read_ifs_file(path, GET_IFS_NAME, &ifs_table); /* Transfer the names into the model_info structure */ - if(status == 0) { - model_info[i].spice_name = ifs_table.name.model_name; - model_info[i].cfunc_name = ifs_table.name.c_fcn_name; + if (status == 0) { + if ((p_model_info_cur->spice_name = strdup( + ifs_table.name.model_name)) == (char *) NULL) { + print_error("ERROR - Unable to copy code model name"); + all_found = false; + break; + } + if ((p_model_info_cur->cfunc_name = strdup( + ifs_table.name.c_fcn_name)) == (char *) NULL) { + print_error("ERROR - Unable to copy code model function name"); + all_found = false; + break; + } } else { + print_error( + "ERROR - Problems reading \"%s\" in directory \"%s\"", + IFSPEC_FILENAME, p_model_info_cur->path_name); all_found = false; - print_error("ERROR - Problems reading %s in directory %s", - IFSPEC_FILENAME, model_info[i].path_name); + break; } + + /* Remove the ifs_table */ + rem_ifs_table(&ifs_table); + } /* end of loop over models */ + + /* Free buffer if allocated */ + if (path != path_stack) { + free(path); } - if(all_found) + if (all_found) { return 0; - else + } + else { + /* Free allocations of model when failure occurred */ + rem_ifs_table(&ifs_table); return -1; + } +} /* end of function read_model_names */ -} /* *********************************************************************** */ @@ -501,21 +798,57 @@ static int read_node_names( Node_Info_t *node_info /* Info about each node */ ) { - bool all_found; /* True if all files read OK */ - int i; /* A temporary counter */ - char path[MAX_PATH_LEN+1]; /* full pathname to file */ - int status; /* Return status */ + bool all_found = true; /* True if all ifspec files read */ + int i; /* A temporary counter */ + char path_stack[100]; /* full pathname to ifspec file if from stack */ + char *path = path_stack; /* actual path buffer */ + int status; /* Return status */ char *node_name; /* Name of node type read from file */ + /* Find the required buffer size and allocate if the default buffer + * on the stack is too small */ + { + int j; + size_t n_byte_needed = 0; + for (j = 0; j < num_nodes; j++) { /* max(model path lengths) */ + const size_t n = strlen(node_info[j].path_name); + if (n_byte_needed < n) { + n_byte_needed = n; + } + } + n_byte_needed += 1 + strlen(UDNFUNC_FILENAME) + 1; + if (n_byte_needed > sizeof path_stack) { + if ((path = (char *) malloc(n_byte_needed)) == (char *) NULL) { + print_error("ERROR - Unable to allocate a buffer " + "for user types"); + return -1; + } + } + } + + /* For each node found in node pathname file, read the udnfunc.c */ /* file to get the node type names into node_info */ for(i = 0, all_found = true; i < num_nodes; i++) { + /* Form the full pathname to the user-defined type file. Size has + * been checked to ensure that all strings will fit. */ + { + char *p_dst = path; - /* Form the full pathname to the interface spec file */ - strcpy(path, node_info[i].path_name); - strcat(path, "/"); - strcat(path, UDNFUNC_FILENAME); + /* Copy path name */ + const char *p_src = node_info[i].path_name; + for ( ; ; ) { + const char ch_cur = *p_src; + if (ch_cur == '\0') { + break; + } + *p_dst++ = ch_cur; + ++p_src; + } + *p_dst++ = '/'; /* add directory separator */ + strcpy(p_dst, UDNFUNC_FILENAME); + } /* Read the udn node type name from the file */ status = read_udn_type_name(path, &node_name); @@ -535,8 +868,7 @@ static int read_node_names( return 0; else return -1; - -} +} /* end of function read_node_names */ @@ -558,14 +890,11 @@ static int check_uniqueness( Node_Info_t *node_info /* Info about each node type */ ) { - int i; /* A temporary counter */ - int j; /* A temporary counter */ - bool all_unique; /* true if names are unique */ - /* Define a list of model names used internally by XSPICE */ /* These names (except 'poly') are defined in src/sim/INP/INPdomodel.c and */ /* are case insensitive */ - static char *SPICEmodel[] = { "npn", + static const char *SPICEmodel[] = { + "npn", "pnp", "d", "njf", @@ -580,13 +909,14 @@ static int check_uniqueness( "sw", "csw", "poly" }; - static int numSPICEmodels = sizeof(SPICEmodel) / sizeof(char *); + static const int numSPICEmodels = sizeof(SPICEmodel) / sizeof(char *); /* Define a list of node type names used internally by the simulator */ /* These names are defined in src/sim/include/MIFtypes.h and are case */ /* insensitive */ - static char *UDNidentifier[] = { "v", + static const char *UDNidentifier[] = { + "v", "vd", "i", "id", @@ -596,138 +926,220 @@ static int check_uniqueness( "h", "hd", "d" }; - static int numUDNidentifiers = sizeof(UDNidentifier) / sizeof(char *); - + static const int numUDNidentifiers = sizeof(UDNidentifier) / sizeof(char *); + bool f_have_duplicate = false; /* no duplicates found yet */ /* First, normalize case of all model and node names to lower since */ /* SPICE is case insensitive in parsing decks */ - for(i = 0; i < num_models; i++) - str_to_lower(model_info[i].spice_name); - for(i = 0; i < num_nodes; i++) - str_to_lower(node_info[i].node_name); - - /* Then, loop through all model names and report errors if same as SPICE */ - /* model name or same as another model name in list */ - for(i = 0, all_unique = true; i < num_models; i++) { - - /* First check against list of SPICE internal names */ - for(j = 0; j < numSPICEmodels; j++) { - if(strcmp(model_info[i].spice_name, SPICEmodel[j]) == 0) { - all_unique = false; - print_error("ERROR - Model name '%s' is same as internal SPICE model name\n", - model_info[i].spice_name); - } + { + int i; + for(i = 0; i < num_models; i++) { + str_to_lower(model_info[i].spice_name); } - - /* Skip if already seen once */ - if(model_info[i].spice_unique == false) - continue; - - /* Then check against other names in list */ - for(j = 0; j < num_models; j++) { - - /* Skip checking against itself */ - if(i == j) - continue; - - /* Compare the names */ - if(strcmp(model_info[i].spice_name, model_info[j].spice_name) == 0) { - all_unique = false; - model_info[i].spice_unique = false; - model_info[j].spice_unique = false; - print_error("ERROR - Model name '%s' in directory: %s", - model_info[i].spice_name, - model_info[i].path_name); - print_error(" is same as"); - print_error(" model name '%s' in directory: %s\n", - model_info[j].spice_name, - model_info[j].path_name); - } - } - } - - /* Loop through all C function names and report errors if duplicates found */ - for(i = 0; i < num_models; i++) { - - /* Skip if already seen once */ - if(model_info[i].cfunc_unique == false) - continue; - - /* Check against other names in list only, not against SPICE identifiers */ - /* Let linker catch collisions with SPICE identifiers for now */ - for(j = 0; j < num_models; j++) { - - /* Skip checking against itself */ - if(i == j) - continue; - - /* Compare the names */ - if(strcmp(model_info[i].cfunc_name, model_info[j].cfunc_name) == 0) { - all_unique = false; - model_info[i].cfunc_unique = false; - model_info[j].cfunc_unique = false; - print_error("ERROR - C function name '%s' in directory: %s", - model_info[i].cfunc_name, - model_info[i].path_name); - print_error(" is same as"); - print_error(" C function name '%s' in directory: %s\n", - model_info[j].cfunc_name, - model_info[j].path_name); - } - } - - } - - /* Loop through all node type names and report errors if same as internal */ - /* name or same as another name in list */ - for(i = 0; i < num_nodes; i++) { - - /* First check against list of internal names */ - for(j = 0; j < numUDNidentifiers; j++) { - if(strcmp(node_info[i].node_name, UDNidentifier[j]) == 0) { - all_unique = false; - print_error("ERROR - Node type '%s' is same as internal node type\n", - node_info[i].node_name); - } - } - - /* Skip if already seen once */ - if(node_info[i].unique == false) - continue; - - /* Then check against other names in list */ - for(j = 0; j < num_nodes; j++) { - - /* Skip checking against itself */ - if(i == j) - continue; - - /* Compare the names */ - if(strcmp(node_info[i].node_name, node_info[j].node_name) == 0) { - all_unique = false; - node_info[i].unique = false; - node_info[j].unique = false; - print_error("ERROR - Node type '%s' in directory: %s", - node_info[i].node_name, - node_info[i].path_name); - print_error(" is same as"); - print_error(" node type '%s' in directory: %s\n", - node_info[j].node_name, - node_info[j].path_name); - } + { + int i; + for(i = 0; i < num_nodes; i++) { + str_to_lower(node_info[i].node_name); } } + /* Sizes of models and nodes */ + const unsigned int n_model = (unsigned int) numSPICEmodels + num_models; + const unsigned int n_node = (unsigned int) numUDNidentifiers + num_nodes; + const unsigned int n_ks = n_model > n_node ? n_model : n_node; + + /* Allocate structure to compare */ + struct Key_src * const p_ks = (struct Key_src *) malloc( + n_ks * sizeof *p_ks); + if (p_ks == (struct Key_src *) NULL) { + print_error("ERROR - Unable to allocate array to check uniqueness."); + return -1; + } + + /* Set up for test of SPICE name of models and test */ + if (num_models > 0) { /* Have user-defined models */ + { + int i, j; + + /* Fill up with SPICE models */ + for (i = 0; i < numSPICEmodels; ++i) { + struct Key_src *p_ks_cur = p_ks + i; + p_ks_cur->key = SPICEmodel[i]; + p_ks_cur->src = (char *) NULL; /* denotes internal SPICE */ + } + /* Add SPICE model names for code models */ + for (j = 0; j < num_models; ++i, ++j) { + struct Key_src *p_ks_cur = p_ks + i; + Model_Info_t *p_mi_cur = model_info + j; + p_ks_cur->key = p_mi_cur->spice_name; + p_ks_cur->src = p_mi_cur->path_name; + } + + /* Test for duplicates */ + f_have_duplicate |= test_for_duplicates(n_model, p_ks, + &report_error_spice_name); + } + + /* Set up for test of function names */ + { + int i; + + /* Fill up with C function names from code models */ + for (i = 0; i < num_models; ++i) { + struct Key_src *p_ks_cur = p_ks + i; + Model_Info_t *p_mi_cur = model_info + i; + p_ks_cur->key = p_mi_cur->cfunc_name; + p_ks_cur->src = p_mi_cur->path_name; + } + + /* Test for duplicates */ + f_have_duplicate |= test_for_duplicates(num_models, p_ks, + &report_error_function_name); + } + } + + /* Set up for test of node types and test */ + if (num_nodes > 0) { /* Have user-defined types */ + int i, j; + + /* Fill up with SPICE node types */ + for (i = 0; i < numUDNidentifiers; ++i) { + struct Key_src *p_ks_cur = p_ks + i; + p_ks_cur->key = UDNidentifier[i]; + p_ks_cur->src = (char *) NULL; /* denotes internal SPICE */ + } + /* Add user-defined nodes */ + for (j = 0; j < num_nodes; ++i, ++j) { + struct Key_src *p_ks_cur = p_ks + i; + Node_Info_t *p_ni_cur = node_info + j; + p_ks_cur->key = p_ni_cur->node_name; + p_ks_cur->src = p_ni_cur->path_name; + } + + /* Test for duplicates */ + f_have_duplicate |= test_for_duplicates(n_node, p_ks, + &report_error_udn_name); + } + + /* Free allocation for compares */ + free(p_ks); /* Return error status */ - if(all_unique) - return 0; - else - return -1; + return f_have_duplicate ? -1 : 0; +} /* end of function check_uniqueness */ + + + +/* Test for duplicate key values and report using the supplied function + * if found */ +static bool test_for_duplicates(unsigned int n, struct Key_src *p_ks, + void (*p_error_reporter)(const struct Key_src *p_ks1, + const struct Key_src *p_ks2)) +{ + bool f_have_duplicate = false; + + /* Sort to put duplicates together */ + qsort(p_ks, n, sizeof(struct Key_src), + (int (*)(const void *, const void *)) &cmpr_ks); + + unsigned int i; + for (i = 0; i != n; ) { + const struct Key_src * const p_ks_i = p_ks + i; + const char * const p_key_i_val = p_ks_i->key; + unsigned int j; + for (j = i + 1; j != n; ++j) { + const struct Key_src * const p_ks_j = p_ks + j; + const char * const p_key_j_val = p_ks_j->key; + if (strcmp(p_key_i_val, p_key_j_val) != 0) { + break; + } + + /* Duplicate found. Indicate a duplicate was found and report + * the error */ + f_have_duplicate = true; + (*p_error_reporter)(p_ks_i, p_ks_j); + } /* end of loop testing for duplicates */ + i = j; /* advance to next unique value or end of list */ + } /* end of loop over items to test */ + return f_have_duplicate; +} /* end of function test_for_duplicates */ + + + +/* Compare function for struct Key_src. + * + * Remarks + * the src field may be NULL to indicate internal values. These should + * be ordered before values that are not NULL for nicer error messages. + * Note that for a given key, only one src field can be NULL. */ +static int cmpr_ks(const struct Key_src *ks1, const struct Key_src *ks2) +{ + /* First order by the value of the key */ + const int rc = strcmp(ks1->key, ks2->key); + if (rc != 0) { + return rc; + } + + /* Test for NULL src fields. Only one can be NULL for the same key */ + if (ks1->src == (char *) NULL) { + return -1; + } + if (ks2->src == (char *) NULL) { + return +1; + } + + /* Both keys not NULL, so compare */ + return strcmp(ks1->src, ks2->src); +} /* end of function cmpr_ks */ + + + +static void report_error_spice_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2) +{ + const char * const p_ks1_src = p_ks1->src; + if (p_ks1_src == (char *) NULL) { /* internal SPICE name */ + print_error("ERROR: Model name \"%s\" from directory \"%s\" " + "is the name of an internal SPICE model", + p_ks1->key, p_ks2->src); + } + else { + print_error("ERROR: Model name \"%s\" in directory \"%s\" " + "is also in directory \"%s\".", + p_ks1->key, p_ks1_src, p_ks2->src); + } +} /* end of function report_error_spice_name */ + + + +static void report_error_function_name (const struct Key_src *p_ks1, + const struct Key_src *p_ks2) +{ + print_error("ERROR: C function name \"%s\" in directory \"%s\" " + "is also in directory \"%s\".", + p_ks1->key, p_ks1->src, p_ks2->src); +} /* end of function report_error_spice_name */ + + + +static void report_error_udn_name(const struct Key_src *p_ks1, + const struct Key_src *p_ks2) +{ + const char * const p_ks1_src = p_ks1->src; + if (p_ks1_src == (char *) NULL) { /* internal SPICE name */ + print_error("ERROR: Node type \"%s\" from directory \"%s\" " + "is the name of an internal SPICE node type", + p_ks1->key, p_ks2->src); + } + else { + print_error("ERROR: Node type \"%s\" in directory \"%s\" " + "is also in directory \"%s\".", + p_ks1->key, p_ks1_src, p_ks2->src); + } +} /* end of function report_error_udn_name */ -} /* *********************************************************************** */ @@ -751,12 +1163,17 @@ static int write_CMextrn( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing CMextrn.h */ - const char *filename = "cmextrn.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("cmextrn.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to cmextrn.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); + free(filename); return -1; } @@ -766,9 +1183,14 @@ static int write_CMextrn( } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + free(filename); return 0; -} +} /* end of function write_CMextrn */ /* *********************************************************************** */ @@ -792,24 +1214,81 @@ static int write_CMinfo( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing CMinfo.h */ - const char *filename = "cminfo.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("cminfo.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to cminfo.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); + free(filename); return -1; } /* Write out the data */ for(i = 0; i < num_models; i++) { - fprintf(fp, "&%s_info,\n", model_info[i].cfunc_name); + Model_Info_t *p_mi_cur = model_info + i; + if (p_mi_cur->version == 1) { + fprintf(fp, "&%s_info,\n", model_info[i].cfunc_name); + } } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_CMinfo */ + + + +static int write_CMinfo2( + int num_models, /* Number of model pathnames */ + Model_Info_t *model_info /* Info about each model */ +) +{ + int i; /* A temporary counter */ + FILE *fp; /* File pointer for writing CMinfo.h */ + + char *filename = (char *) NULL; + + /* Open the file to be written */ + if ((filename = gen_filename("cminfo2.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to cminfo2.h"); + return -1; + } + fp = fopen(filename, "w"); + if(fp == NULL) { + print_error("ERROR - Problems opening %s for write", filename); + free(filename); + return -1; + } + + /* Write out the data */ + for (i = 0; i < num_models; i++) { + Model_Info_t *p_mi_cur = model_info + i; + if (p_mi_cur->version <= 2) { + fprintf(fp, "&%s_info,\n", model_info[i].cfunc_name); + } + } + + /* Close the file and return */ + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); + return 0; +} /* end of function write_CMinfo2 */ @@ -837,10 +1316,14 @@ static int write_UDNextrn( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing UDNextrn.h */ - const char *filename = "udnextrn.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("udnextrn.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to udnextrn.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); return -1; @@ -852,9 +1335,16 @@ static int write_UDNextrn( } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_UDNextrn */ + /* *********************************************************************** */ @@ -869,9 +1359,6 @@ and user-defined nodes. This SPICE source file uses the structures mentioned in the include file to define the node types known to the simulator. */ - - - static int write_UDNinfo( int num_nodes, /* Number of node pathnames */ Node_Info_t *node_info /* Info about each node */ @@ -880,10 +1367,14 @@ static int write_UDNinfo( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing UDNinfo.h */ - const char *filename = "udninfo.h"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("udninfo.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to udninfo.h"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); return -1; @@ -891,13 +1382,65 @@ static int write_UDNinfo( /* Write out the data */ for(i = 0; i < num_nodes; i++) { - fprintf(fp, "&udn_%s_info,\n", node_info[i].node_name); + Node_Info_t *p_ni_cur = node_info + i; + if (p_ni_cur->version == 1) { + fprintf(fp, "&udn_%s_info,\n", p_ni_cur->node_name); + } } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_UDNinfo */ + + + +static int write_UDNinfo2( + int num_nodes, /* Number of node pathnames */ + Node_Info_t *node_info /* Info about each node */ +) +{ + int i; /* A temporary counter */ + FILE *fp; /* File pointer for writing UDNinfo.h */ + + char *filename = (char *) NULL; + + /* Open the file to be written */ + if ((filename = gen_filename("udninfo2.h", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to udninfo2.h"); + return -1; + } + fp = fopen(filename, "w"); + if(fp == NULL) { + print_error("ERROR - Problems opening %s for write", filename); + return -1; + } + + /* Write out the data */ + for(i = 0; i < num_nodes; i++) { + Node_Info_t *p_ni_cur = node_info + i; + if (p_ni_cur->version <= 2) { + fprintf(fp, "&udn_%s_info,\n", p_ni_cur->node_name); + } + } + + /* Close the file and return */ + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); + return 0; +} /* end of function write_UDNinfo */ + /* *********************************************************************** */ @@ -920,10 +1463,14 @@ static int write_objects_inc( int i; /* A temporary counter */ FILE *fp; /* File pointer for writing make_include */ - const char *filename = "objects.inc"; + char *filename = (char *) NULL; /* Open the file to be written */ - fp = fopen_cmpp(&filename, "w"); + if ((filename = gen_filename("objects.inc", "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to objects.inc"); + return -1; + } + fp = fopen(filename, "w"); if(fp == NULL) { print_error("ERROR - Problems opening %s for write", filename); return -1; @@ -946,9 +1493,16 @@ static int write_objects_inc( } /* Close the file and return */ - fclose(fp); + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing %s", filename); + free(filename); + return -1; + } + + free(filename); return 0; -} +} /* end of function write_objects_inc */ + /* @@ -973,11 +1527,18 @@ static int read_udn_type_name( int i; /* a counter */ static char *struct_type = "Evt_Udn_Info_t"; + char *filename = (char *) NULL; /* Open the file from which the node type name will be read */ - fp = fopen_cmpp(&path, "r"); - if(fp == NULL) + if ((filename = gen_filename(path, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build path to Evt_Udn_Info_t"); return -1; + } + fp = fopen(filename, "r"); + if(fp == NULL) { + print_error("ERROR - Problems opening %s for reading", filename); + return -1; + } /* Read the file until the definition of the Evt_Udn_Info_t struct */ /* is found, then get the name of the node type from the first */ @@ -1028,10 +1589,19 @@ static int read_udn_type_name( c = fgetc(fp); if(c == '"') { found = true; + if (i >= sizeof name) { + print_error("name too long"); + exit(1); + } name[i] = '\0'; } - else if(c != EOF) + else if(c != EOF) { + if (i > sizeof name) { + print_error("name too long"); + exit(1); + } name[i++] = (char) c; + } } while((c != EOF) && (! found)); } } while((c != EOF) && (! found)); @@ -1043,7 +1613,11 @@ static int read_udn_type_name( fclose(fp); if(found) { - *node_name = (char *) malloc(strlen(name) + 1); + if ((*node_name = (char *) malloc( + strlen(name) + 1)) == (char *) NULL) { + print_error("ERROR - Unable to allocate node name"); + return -1; + } strcpy(*node_name, name); return 0; } @@ -1053,3 +1627,58 @@ static int read_udn_type_name( } } + + +/* Free allocations in p_model_info array */ +static void free_model_info(int num_models, Model_Info_t *p_model_info) +{ + /* Return if no structure */ + if (p_model_info == (Model_Info_t *) NULL) { + return; + } + + int i; + for (i = 0; i < num_models; ++i) { + Model_Info_t *p_cur = p_model_info + i; + void *p; + if ((p = p_cur->cfunc_name) != NULL) { + free(p); + } + if ((p = p_cur->path_name) != NULL) { + free(p); + } + if ((p = p_cur->spice_name) != NULL) { + free(p); + } + } + + free(p_model_info); +} /* end of function free_model_info */ + + + +/* Free allocations in p_nod_info array */ +static void free_node_info(int num_nodes, Node_Info_t *p_node_info) +{ + /* Return if no structure */ + if (p_node_info == (Node_Info_t *) NULL) { + return; + } + + int i; + for (i = 0; i < num_nodes; ++i) { + Node_Info_t *p_cur = p_node_info + i; + void *p; + if ((p = p_cur->node_name) != NULL) { + free(p); + } + if ((p = p_cur->path_name) != NULL) { + free(p); + } + } + + free(p_node_info); +} /* end of function free_node_info */ + + + diff --git a/src/xspice/cmpp/pp_mod.c b/src/xspice/cmpp/pp_mod.c index 2351e0a22..c31bce1a8 100644 --- a/src/xspice/cmpp/pp_mod.c +++ b/src/xspice/cmpp/pp_mod.c @@ -54,6 +54,7 @@ NON-STANDARD FEATURES ============================================================================*/ +#include #include #include #include @@ -74,21 +75,33 @@ extern int mod_num_errors; extern Ifs_Table_t *mod_ifs_table; -extern const char *current_filename; +extern char *current_filename; extern char *prog_name; /*---------------------------------------------------------------------------*/ -static char *change_extension (char *filename, char *ext) +/* Allocate and build a file name from the input filename by changing its + * extension (text after the last '.') in filename to ext or append .ext if + * the filename has no extension */ +static char *change_extension(const char *filename, const char *ext) { - char *p = strrchr(filename, '.'); - size_t prefix_len = p ? (size_t) (p-filename+1) : strlen(filename); - char *new_filename = malloc(prefix_len + strlen(ext) + 1); + const char * const p = strrchr(filename, '.'); + const size_t prefix_len = p ? (size_t) (p - filename) : strlen(filename); + const size_t ext_len = strlen(ext); + char * const new_filename = malloc(prefix_len + ext_len + 2); + /* +1 for '.' +1 for '\0' */ + if (new_filename == (char *) NULL) { + return (char *) NULL; + } - strncpy(new_filename, filename, prefix_len); - strcpy(new_filename+prefix_len, ext); + { + char *p_cur = (char *) memcpy(new_filename, filename, prefix_len) + + prefix_len; + *p_cur++ = '.'; + (void) memcpy(p_cur, ext, ext_len + 1); + } return new_filename; -} +} /* end of function change_extension */ /*---------------------------------------------------------------------------*/ @@ -108,14 +121,12 @@ utilities. void preprocess_mod_file ( - char *filename) /* The file to read */ + const char *filename) /* The file to read */ { - - - Ifs_Table_t ifs_table; /* info read from ifspec.ifs file */ - int status; /* Return status */ - const char *output_filename; - + Ifs_Table_t ifs_table; /* info read from ifspec.ifs file */ + int status; /* Return status */ + char *output_filename = (char *) NULL; /* .mod file being written */ + /* * Read the entire ifspec.ifs file and load the data into ifs_table */ @@ -125,42 +136,80 @@ void preprocess_mod_file ( if (status != 0) { exit(1); } - - current_filename = filename; - mod_yyin = fopen_cmpp (¤t_filename, "r"); - if (mod_yyin == NULL) { - print_error("ERROR - Could not open input .mod file: %s", current_filename); - exit(1); - } - - output_filename = change_extension (filename, "c"); - mod_yyout = fopen_cmpp (&output_filename, "w"); + /* Open the cfunc.mod file defining the code model function */ + if ((current_filename = gen_filename(filename, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build mod file name"); + exit(1); + } + if ((mod_yyin = fopen(current_filename, "r")) == (FILE *) NULL) { + print_error("ERROR - Unable to open mod file \"%s\": %s", + current_filename, strerror(errno)); + exit(1); + } + + { + char *output_filename_base = (char *) NULL; + if ((output_filename_base = change_extension( + filename, "c")) == (char *) NULL) { + print_error("ERROR - Could not change extension of " + "\"%s\".", filename); + exit(1); + } + + if ((output_filename = gen_filename( + output_filename_base, "w")) == (char *) NULL) { + print_error("ERROR - Unable to build output file name"); + exit(1); + } + + free(output_filename_base); + } + + if ((mod_yyout = fopen(output_filename, "w")) == (FILE *) NULL) { + /* .c file could not be opened */ + print_error("ERROR - Could not open output .c file\"%s\": %s", + output_filename, strerror(errno)); + exit(1); + } - if (mod_yyout == NULL) { - print_error("ERROR - Could not open output .c file: %s", output_filename); - exit(1); - } - mod_ifs_table = &ifs_table; mod_num_errors = 0; +/* Define DEBUG_WITH_MOD_FILE to have the compiler use the cfunc.mod file for + * deugging instead of the cfunc.c file. */ +#ifdef DEBUG_WITH_MOD_FILE fprintf (mod_yyout, "#line 1 \"%s\"\n", current_filename); +#endif fprintf (mod_yyout, "#include \"ngspice/cm.h\"\n"); fprintf (mod_yyout, "extern void %s(Mif_Private_t *);\n", - ifs_table.name.c_fcn_name); + ifs_table.name.c_fcn_name); +#ifdef DEBUG_WITH_MOD_FILE fprintf (mod_yyout, "#line 1 \"%s\"\n", current_filename); +#endif mod_yylineno = 1; - if (mod_yyparse() || (mod_num_errors > 0)) { - print_error("Error parsing .mod file: \"%s\"", current_filename); - unlink (output_filename); - exit (1); - } - fclose (mod_yyout); - mod_yyrestart(NULL); -} + if (mod_yyparse() || (mod_num_errors > 0)) { + print_error("Error parsing .mod file: \"%s\"", current_filename); + unlink(output_filename); + exit(1); + } + + if (fclose(mod_yyout) != 0) { + print_error("Error closing output file \"%s\": %s", + current_filename, strerror(errno)); + unlink(output_filename); + exit(1); + } + + rem_ifs_table(&ifs_table); + mod_yyrestart(NULL); + free(output_filename); + free(current_filename); +} /* end of function preprocess_mod_file */ + + /*---------------------------------------------------------------------------*/ void diff --git a/src/xspice/cmpp/read_ifs.c b/src/xspice/cmpp/read_ifs.c index 71f709139..ce439a8a5 100644 --- a/src/xspice/cmpp/read_ifs.c +++ b/src/xspice/cmpp/read_ifs.c @@ -47,7 +47,11 @@ NON-STANDARD FEATURES ============================================================================*/ #include +#include #include +#include +#include + #include "ifs_yacc_y.h" extern char *prog_name; @@ -65,7 +69,7 @@ extern int ifs_num_errors; static int read_ifs_table(FILE *fp, int mode, Ifs_Table_t *ifs_table); -const char *current_filename; +char *current_filename; /* *********************************************************************** */ @@ -94,35 +98,42 @@ int read_ifs_file( int mode, /* Get names only or get everything? */ Ifs_Table_t *ifs_table) /* Table to put info in */ { - - FILE *fp; /* Ifs file pointer */ - - int status; /* returned status from function */ - - + FILE *fp = (FILE *) NULL; /* Ifs file pointer */ + int status = 0; /* returned status from function */ + + /* Open the ifs file for read access */ - fp = fopen_cmpp(&filename, "r"); - - if(fp == NULL) { - perror (prog_name); - print_error("ERROR - File not found: %s", filename); - return -1; + /* Open the model pathname file */ + if ((current_filename = gen_filename(filename, "r")) == (char *) NULL) { + print_error("ERROR - Unable to build full file name"); + return -1; + } + if ((fp = fopen(current_filename, "r")) == (FILE *) NULL) { + print_error("ERROR - Unable to open \"%s\": %s", + current_filename, strerror(errno)); + status = -1; + goto EXITPOINT; + } + + /* Get the stuff from the file into the ifs_table struct. Here mode + * defines the data that will be added to the structure */ + status = read_ifs_table(fp, mode, ifs_table); + + EXITPOINT: + /* Close file and return */ + if (fp != (FILE *) NULL) { + if (fclose(fp) != 0) { + print_error("ERROR - Unable to close \"%s\": %s", + current_filename, strerror(errno)); + status = -1; + } } - current_filename = filename; - - /* Get the stuff from the file into the ifs_table struct */ - - status = read_ifs_table(fp, mode, ifs_table); - - /* Close file and return */ - - fclose(fp); - - return(status); - -} + free(current_filename); + current_filename = (char *) NULL; + return status; +} /* end of function read_ifs_file */ @@ -146,10 +157,13 @@ static int read_ifs_table( int mode, /* Get names only or get everything? */ Ifs_Table_t *ifs_table) /* Table to put info in */ { - assert (ifs_table); assert (fp); + ifs_table->name.description = + ifs_table->name.c_fcn_name = + ifs_table->name.model_name = NULL; + ifs_yylineno = 1; ifs_yyin = fp; parser_just_names = (mode == GET_IFS_NAME) ? true : false; diff --git a/src/xspice/cmpp/util.c b/src/xspice/cmpp/util.c index da6a27163..7daec9194 100644 --- a/src/xspice/cmpp/util.c +++ b/src/xspice/cmpp/util.c @@ -84,16 +84,21 @@ void print_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); - - fprintf(stderr, "%s: ", prog_name); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - + vprint_error(fmt, ap); va_end(ap); } /* end of function print_error */ +void vprint_error(const char *fmt, va_list p_arg) +{ + fprintf(stderr, "%s: ", prog_name); + vfprintf(stderr, fmt, p_arg); + fprintf(stderr, "\n"); +} /* end of functoin vprint_error */ + + + /* Convert a string to all lower case */ void str_to_lower(char *s) { @@ -110,24 +115,22 @@ void str_to_lower(char *s) /* If *path_p is relative, prefix with the value of the CMPP output or * input environment variable. Open the file and return the path that * was used to open it. */ -FILE *fopen_cmpp(const char **path_p, const char *mode) +char *gen_filename(const char *filename, const char *mode) { - const char *path = *path_p; char *buf = (char *) NULL; /* If absoulte path, prefix with CMPP_ODIR/CMPP_IDIR env value */ - if (!is_absolute_pathname(path)) { /* relative path */ + if (!is_absolute_pathname(filename)) { /* relative path */ const char *e = getenv((*mode == 'w' || *mode == 'a') ? "CMPP_ODIR" : "CMPP_IDIR"); if (e) { /* have env var */ const size_t len_prefix = strlen(e); - const size_t len_path = strlen(path); - const size_t n_char = len_prefix + len_path + 1; + const size_t len_filename = strlen(filename); + const size_t n_char = len_prefix + len_filename + 1; /* Allocate buffer to build full file name */ if ((buf = (char *) malloc(n_char + 1)) == (char *) NULL) { - *path_p = (char *) NULL; - return (FILE *) NULL; + return (char *) NULL; } /* Build the full file name */ @@ -136,24 +139,21 @@ FILE *fopen_cmpp(const char **path_p, const char *mode) (void) memcpy(p_cur, e, len_prefix); p_cur += len_prefix; *p_cur++ = DIR_TERM_UNIX; - (void) memcpy(p_cur, path, len_path + 1); + (void) memcpy(p_cur, filename, len_filename + 1); } } /* end of case that env variable found */ } /* end of case that path is absolute */ - /* If did not build full file name yet, copy the original - * name of the file */ + /* If did not build full file name yet, make the original + * name of the file the full file name */ if (buf == (char *) NULL) { - if ((buf = strdup(path)) == (char *) NULL) { /* failed */ - *path_p = (char *) NULL; - return (FILE *) NULL; + if ((buf = strdup(filename)) == (char *) NULL) { /* failed */ + return (char *) NULL; } } - /* Return copy of file name and opened file */ - *path_p = buf; - return fopen(buf, mode); -} /* end of function fopen_cmpp */ + return buf; +} /* end of function gen_filename */ diff --git a/src/xspice/cmpp/writ_ifs.c b/src/xspice/cmpp/writ_ifs.c index 9e9129fa7..e1ab2d5e6 100644 --- a/src/xspice/cmpp/writ_ifs.c +++ b/src/xspice/cmpp/writ_ifs.c @@ -40,45 +40,31 @@ NON-STANDARD FEATURES #include +#include #include #include #include "cmpp.h" /* Local function prototypes */ - -static void write_comment(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_includes(FILE *fp); - -static void write_mPTable(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_pTable(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_conn_info(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_param_info(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_inst_var_info(FILE *fp, Ifs_Table_t *ifs_table); - -static void write_SPICEdev(FILE *fp, Ifs_Table_t *ifs_table); +static int write_comment(FILE *fp, Ifs_Table_t *ifs_table); +static int write_includes(FILE *fp); +static int write_mPTable(FILE *fp, Ifs_Table_t *ifs_table); +static int write_pTable(FILE *fp, Ifs_Table_t *ifs_table); +static int write_conn_info(FILE *fp, Ifs_Table_t *ifs_table); +static int write_param_info(FILE *fp, Ifs_Table_t *ifs_table); +static int write_inst_var_info(FILE *fp, Ifs_Table_t *ifs_table); +static int write_SPICEdev(FILE *fp, Ifs_Table_t *ifs_table); -static char *data_type_to_str(Data_Type_t type); - -static char *port_type_to_str(Port_Type_t port); - -static char *dir_to_str(Dir_t dir); - +static const char *data_type_to_str(Data_Type_t type); +static const char *port_type_to_str(Port_Type_t port); +static const char *dir_to_str(Dir_t dir); static char *value_to_str(Data_Type_t type, Value_t value); - -static char *no_value_to_str(void); - -static char *boolean_to_str(bool value); - +static const char *no_value_to_str(void); +static const char *boolean_to_str(bool value); static char *integer_to_str(int value); - -static char *gen_port_type_str(Port_Type_t port); +static const char *gen_port_type_str(Port_Type_t port); @@ -110,59 +96,102 @@ The output file is then closed. int write_ifs_c_file( - const char *filename, /* File to write to */ + const char *filename_in, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - FILE *fp; /* File pointer */ - int int_status; /* returned status from fclose */ + FILE *fp = (FILE *) NULL; /* File pointer */ + char *filename = (char *) NULL; + int xrc = 0; /* Open the ifspec.c file for write access */ - - fp = fopen_cmpp(&filename, "w"); - - if(fp == NULL) { - print_error("ERROR - Can't create file: %s", filename); - return -1; + if ((filename = gen_filename(filename_in, "w")) == (char *) NULL) { + print_error("ERROR - Unable to build path to \"%s\".", filename); + xrc = -1; + goto EXITPOINT; + } + fp = fopen(filename, "w"); + if(fp == NULL) { + print_error("ERROR - Problems opening \"%s\" for write", filename); + xrc = -1; + goto EXITPOINT; } - /* Write out a comment section at the top of the file */ - write_comment(fp, ifs_table); + if (write_comment(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing comment to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Put in the # includes */ - write_includes(fp); + if (write_includes(fp) != 0) { + print_error("ERROR - Problems writing includes to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write the SPICE3 required XXXmPTable structure */ - write_mPTable(fp, ifs_table); + if (write_mPTable(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing mPTable to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write the SPICE3 required XXXpTable structure */ - write_pTable(fp, ifs_table); + if (write_pTable(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing pTable to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the connector table required for the code model element parser */ - write_conn_info(fp, ifs_table); + if (write_conn_info(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing includes to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the parameter table required for the code model element parser */ - write_param_info(fp, ifs_table); + if (write_param_info(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing params to \"%s\"", filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the instance variable table required for the code model element parser */ - write_inst_var_info(fp, ifs_table); + if (write_inst_var_info(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing instaice variables to \"%s\"", + filename); + xrc = -1; + goto EXITPOINT; + } /* Write out the externally visible structure for this model */ - write_SPICEdev(fp, ifs_table); - - - /* Close the ifspec.c file and return */ - - int_status = fclose(fp); - - if (int_status == 0) { - return 0; + if (write_SPICEdev(fp, ifs_table) != 0) { + print_error("ERROR - Problems writing model structureto \"%s\"", + filename); + xrc = -1; + goto EXITPOINT; } - else { - return -1; + + +EXITPOINT: + /* Close the ifspec.c file, free allocation, and return */ + if (fp != (FILE *) NULL) { + if (fclose(fp) != 0) { + print_error("ERROR - Problems closing \"%s\": %s.", + filename, strerror(errno)); + xrc = -1; + } } -} + + if (filename != (char *) NULL) { + free(filename); + } + + return xrc; +} /* end of function write_ifs_c_file */ @@ -178,21 +207,29 @@ generated and should not be edited. */ -static void write_comment( +static int write_comment( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - fprintf(fp, "\n"); - fprintf(fp, "/*\n"); - fprintf(fp, " * Structures for model: %s\n", ifs_table->name.model_name); - fprintf(fp, " *\n"); - fprintf(fp, " * Automatically generated by cmpp preprocessor\n"); - fprintf(fp, " *\n"); - fprintf(fp, " * !!! DO NOT EDIT !!!\n"); - fprintf(fp, " *\n"); - fprintf(fp, " */\n"); - fprintf(fp, "\n"); -} + const int rc = fprintf(fp, + "\n" + "/*\n" + " * Structures for model: %s\n" + " *\n" + " * Automatically generated by cmpp preprocessor\n" + " *\n" + " * !!! DO NOT EDIT !!!\n" + " *\n" + " */\n" + "\n", + ifs_table->name.model_name); + if (rc < 0) { + print_error("Comment writing failed."); + return -1; + } + return 0; +} /* end of function write_comment */ + /* *********************************************************************** */ @@ -205,21 +242,28 @@ ifspec.c. */ -static void write_includes( +static int write_includes( FILE *fp) /* File to write to */ { - fprintf(fp, "\n"); - fprintf(fp, "#include \"ngspice/ngspice.h\"\n"); -/* fprintf(fp, "#include \"ngspice/prefix.h\"\n");*/ - fprintf(fp, "#include \n"); - fprintf(fp, "#include \"ngspice/devdefs.h\"\n"); - fprintf(fp, "#include \"ngspice/ifsim.h\"\n"); - fprintf(fp, "#include \"ngspice/mifdefs.h\"\n"); - fprintf(fp, "#include \"ngspice/mifproto.h\"\n"); - fprintf(fp, "#include \"ngspice/mifparse.h\"\n"); -/* fprintf(fp, "#include \"ngspice/suffix.h\"\n");*/ - fprintf(fp, "\n"); -} + const int rc = fprintf(fp, + "\n" + "#include \"ngspice/ngspice.h\"\n" +/* "#include \"ngspice/prefix.h\"\n"*/ + "#include \n" + "#include \"ngspice/devdefs.h\"\n" + "#include \"ngspice/ifsim.h\"\n" + "#include \"ngspice/mifdefs.h\"\n" + "#include \"ngspice/mifproto.h\"\n" + "#include \"ngspice/mifparse.h\"\n" +/* "#include \"ngspice/suffix.h\"\n"*/ + "\n"); + if (rc < 0) { + print_error("Include writing failed."); + return -1; + } + return 0; +} /* end of function write_includes */ + /* *********************************************************************** */ @@ -238,28 +282,28 @@ that can be queried using the SPICE 3C1 .save feature. */ -static void write_pTable( +static int write_pTable( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char str[80]; bool is_array; Data_Type_t type; /* Only write the pTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ + if (ifs_table->num_inst_var == 0) { + return 0; + } - if(ifs_table->num_inst_var == 0) - return; - + int rc = 0; /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static IFparm MIFpTable[] = {\n"); + rc |= fprintf(fp, + "\n" + "static IFparm MIFpTable[] = {\n"); /* Write out an entry for each instance variable in the table */ @@ -267,68 +311,71 @@ static void write_pTable( /* Use the index of the element in the instance variable info array */ /* ADDED TO the number of parameters as the SPICE3 integer tag. */ - for(i = 0; i < ifs_table->num_inst_var; i++) { + for (i = 0; i < ifs_table->num_inst_var; i++) { /* Use the SPICE3 OP macro since instance vars are output-only */ - fprintf(fp, " OP("); + rc |= fprintf(fp, " OP("); /* Put in the name of the parameter and the integer tag */ - fprintf(fp, "\"%s\", ", ifs_table->inst_var[i].name); - fprintf(fp, "%d, ", i + ifs_table->num_param); + rc |= fprintf(fp, "\"%s\", ", ifs_table->inst_var[i].name); + rc |= fprintf(fp, "%d, ", i + ifs_table->num_param); /* Format SPICE3 type according to parameter type field */ type = ifs_table->inst_var[i].type; is_array = ifs_table->inst_var[i].is_array; - strcpy(str,""); - if(is_array == true) { - strcat(str,"("); + rc |= fprintf(fp, "("); } if(type == CMPP_BOOLEAN) { - strcat(str,"IF_FLAG"); /* There is no BOOLEAN in SPICE3 */ + rc |= fprintf(fp, "IF_FLAG"); /* no BOOLEAN in SPICE3 */ } else if(type == CMPP_INTEGER) { - strcat(str,"IF_INTEGER"); + rc |= fprintf(fp, "IF_INTEGER"); } else if(type == CMPP_REAL) { - strcat(str,"IF_REAL"); + rc |= fprintf(fp, "IF_REAL"); } else if(type == CMPP_COMPLEX) { - strcat(str,"IF_COMPLEX"); + rc |= fprintf(fp, "IF_COMPLEX"); } else if(type == CMPP_STRING) { - strcat(str,"IF_STRING"); + rc |= fprintf(fp, "IF_STRING"); } else if(type == CMPP_POINTER) { - strcat(str,"IF_STRING"); + rc |= fprintf(fp, "IF_STRING"); } else { print_error("INTERNAL ERROR - write_pTable() - Impossible data type."); + xrc = -1; + rc |= fprintf(fp, "INVALID DATA TYPE"); } if(is_array == true) { - strcat(str,"|IF_VECTOR)"); + rc |= fprintf(fp, "|IF_VECTOR)"); } - fprintf(fp, "%s, ", str); /* Put in the description string and finish this line off */ - - fprintf(fp, "\"%s\"", ifs_table->inst_var[i].description); - fprintf(fp, "),\n"); - - } + rc |= fprintf(fp, ", \"%s\"),\n", ifs_table->inst_var[i].description); + } /* end of loop over instance variables */ /* Finish off the structure */ + rc |= fprintf(fp, "};\n\n"); + + /* Check outputs */ + if (rc < 0) { + print_error("pTable writing failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_pTable */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); -} /* *********************************************************************** */ @@ -345,95 +392,95 @@ model parameters are derived from the Interface Specification's PARAMETER table. */ -static void write_mPTable( +static int write_mPTable( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char str[80]; - bool is_array; - Data_Type_t type; /* Only write the mPTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_param == 0) - return; + if (ifs_table->num_param == 0) { + return 0; + } + int rc = 0; /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static IFparm MIFmPTable[] = {\n"); + rc |= fprintf(fp, + "\n" + "static IFparm MIFmPTable[] = {\n"); /* Write out an entry for each parameter in the table */ /* Use the index of the element in the parameter info array */ /* as the SPICE3 integer tag. */ - + Param_Info_t *param = ifs_table->param; for(i = 0; i < ifs_table->num_param; i++) { + Param_Info_t *param_cur = param + i; /* Use the SPICE3 IOP macro since model parameters are input/output */ - fprintf(fp, " IOP("); + rc |= fprintf(fp, " IOP("); /* Put in the name of the parameter and the integer tag */ - - fprintf(fp, "\"%s\", ", ifs_table->param[i].name); - fprintf(fp, "%d, ", i); + rc |= fprintf(fp, "\"%s\", ", param_cur->name); + rc |= fprintf(fp, "%d, ", i); /* Format SPICE3 type according to parameter type field */ - type = ifs_table->param[i].type; - is_array = ifs_table->param[i].is_array; + const bool is_array = param_cur->is_array; + const Data_Type_t type = param_cur->type; - strcpy(str,""); - - if(is_array == true) { - strcat(str,"("); + if (is_array) { + rc |= fprintf(fp, "("); } - if(type == CMPP_BOOLEAN) { - strcat(str,"IF_FLAG"); /* There is no BOOLEAN in SPICE3 */ + if (type == CMPP_BOOLEAN) { + rc |= fprintf(fp, "IF_FLAG"); /* no BOOLEAN in SPICE3 */ } - else if(type == CMPP_INTEGER) { - strcat(str,"IF_INTEGER"); + else if (type == CMPP_INTEGER) { + rc |= fprintf(fp, "IF_INTEGER"); } - else if(type == CMPP_REAL) { - strcat(str,"IF_REAL"); + else if (type == CMPP_REAL) { + rc |= fprintf(fp, "IF_REAL"); } - else if(type == CMPP_COMPLEX) { - strcat(str,"IF_COMPLEX"); + else if (type == CMPP_COMPLEX) { + rc |= fprintf(fp, "IF_COMPLEX"); } - else if(type == CMPP_STRING) { - strcat(str,"IF_STRING"); + else if (type == CMPP_STRING) { + rc |= fprintf(fp, "IF_STRING"); } else { print_error("INTERNAL ERROR - write_mPTable() - Impossible data type."); + xrc = -1; } - if(is_array == true) { - strcat(str,"|IF_VECTOR)"); + if (is_array) { + rc |= fprintf(fp, "|IF_VECTOR)"); } - fprintf(fp, "%s, ", str); /* Put in the description string and finish this line off */ - - fprintf(fp, "\"%s\"", ifs_table->param[i].description); - fprintf(fp, "),\n"); - - } + rc |= fprintf(fp, ", \"%s\"),\n", ifs_table->param[i].description); + } /* end of loop over parameters */ /* Finish off the structure */ + rc |= fprintf(fp, "};\n\n"); - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + /* Check outputs */ + if (rc < 0) { + print_error("mPTable writing failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_mPTable */ -} /* *********************************************************************** */ @@ -450,147 +497,164 @@ derived from the Interface Specification file's PORT table. -static void write_conn_info( +static int write_conn_info( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; int j; - char *str; + const char *str; + int rc = 0; /* Only write the connTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_conn == 0) /* An unlikely condition for sure ... */ - return; + if (ifs_table->num_conn == 0) { /* An unlikely condition for sure ... */ + return 0; + } /* First, we must define arrays of port types */ /* Note that there should be always at least one allowed port type */ /* so we don't have to worry about arrays with no elements */ - for(i = 0; i < ifs_table->num_conn; i++) { + const Conn_Info_t * const conn = ifs_table->conn; + const int num_conn = ifs_table->num_conn; + for (i = 0; i < num_conn; i++) { + const Conn_Info_t * const p_conn_cur = conn + i; + rc |= fprintf(fp, + "\n" + "static Mif_Port_Type_t MIFportEnum%d[] = {\n", i); - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Port_Type_t MIFportEnum%d[] = {\n", i); - - if(ifs_table->conn[i].num_allowed_types < 1) - print_error("ERROR - write_conn_info() - Number of allowed types cannot be zero"); - - for(j = 0; j < ifs_table->conn[i].num_allowed_types; j++) { - - str = port_type_to_str(ifs_table->conn[i].allowed_port_type[j]); - fprintf(fp, "\t%s,\n", str); + if (p_conn_cur->num_allowed_types < 1) { + print_error("ERROR - write_conn_info() - " + "Number of allowed types cannot be zero"); + xrc = -1; + } + const int num_allowed_types = p_conn_cur->num_allowed_types; + for (j = 0; j < num_allowed_types; j++) { + rc |= fprintf(fp, " %s,\n", + port_type_to_str(p_conn_cur->allowed_port_type[j])); } /* for number of allowed types */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + rc |= fprintf(fp, + "};\n" + "\n" + "\n" + "static char *MIFportStr%d[] = {\n", i); - - fprintf(fp, "\n"); - fprintf(fp, "static char *MIFportStr%d[] = {\n", i); - - for(j = 0; j < ifs_table->conn[i].num_allowed_types; j++) { - if(ifs_table->conn[i].allowed_port_type[j] == USER_DEFINED) - fprintf(fp, "\t\"%s\",\n", ifs_table->conn[i].allowed_type[j]); + for (j = 0; j < num_allowed_types; j++) { + if (p_conn_cur->allowed_port_type[j] == USER_DEFINED) { + rc |= fprintf(fp, " \"%s\",\n", + p_conn_cur->allowed_type[j]); + } else { - str = gen_port_type_str(ifs_table->conn[i].allowed_port_type[j]); - fprintf(fp, "\t\"%s\",\n", str); + str = gen_port_type_str(p_conn_cur->allowed_port_type[j]); + rc |= fprintf(fp, " \"%s\",\n", str); } } /* for number of allowed types */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); - + rc |= fprintf(fp, + "};\n" + "\n"); } /* for number of connections */ /* Now write the structure */ - - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Conn_Info_t MIFconnTable[] = {\n"); + rc |= fprintf(fp, + "\n" + "static Mif_Conn_Info_t MIFconnTable[] = {\n"); /* Write out an entry for each parameter in the table */ - for(i = 0; i < ifs_table->num_conn; i++) { + for (i = 0; i < num_conn; i++) { + const Conn_Info_t * const p_conn_cur = conn + i; - fprintf(fp, " {\n"); - fprintf(fp, " \"%s\",\n",ifs_table->conn[i].name); - fprintf(fp, " \"%s\",\n",ifs_table->conn[i].description); + rc |= fprintf(fp, " {\n"); + rc |= fprintf(fp, " \"%s\",\n", p_conn_cur->name); + rc |= fprintf(fp, " \"%s\",\n", p_conn_cur->description); - str = dir_to_str(ifs_table->conn[i].direction); - fprintf(fp, " %s,\n", str); + str = dir_to_str(p_conn_cur->direction); + rc |= fprintf(fp, " %s,\n", str); - str = port_type_to_str(ifs_table->conn[i].default_port_type); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", + port_type_to_str(p_conn_cur->default_port_type)); - fprintf(fp, " \"%s\",\n", - (ifs_table->conn[i].default_port_type == USER_DEFINED) - ? ifs_table->conn[i].default_type - : gen_port_type_str (ifs_table->conn[i].default_port_type)); + rc |= fprintf(fp, " \"%s\",\n", + (p_conn_cur->default_port_type == USER_DEFINED) + ? p_conn_cur->default_type + : gen_port_type_str(p_conn_cur->default_port_type)); - fprintf(fp," %d,\n",ifs_table->conn[i].num_allowed_types); - - fprintf(fp, " MIFportEnum%d,\n", i); - fprintf(fp, " MIFportStr%d,\n", i); + rc |= fprintf(fp," %d,\n", p_conn_cur->num_allowed_types); + rc |= fprintf(fp, " MIFportEnum%d,\n", i); + rc |= fprintf(fp, " MIFportStr%d,\n", i); - str = boolean_to_str(ifs_table->conn[i].is_array); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->is_array); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->conn[i].is_array == false) { + if (p_conn_cur->is_array == false) { str = boolean_to_str(false); /* has_lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } else { /* is_array == true */ - str = boolean_to_str(ifs_table->conn[i].has_lower_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->has_lower_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->conn[i].has_lower_bound == true) - str = integer_to_str(ifs_table->conn[i].lower_bound); + if (p_conn_cur->has_lower_bound == true) + str = integer_to_str(p_conn_cur->lower_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->conn[i].has_upper_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->has_upper_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->conn[i].has_upper_bound == true) - str = integer_to_str(ifs_table->conn[i].upper_bound); + if (p_conn_cur->has_upper_bound == true) + str = integer_to_str(p_conn_cur->upper_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } /* if is_array */ - str = boolean_to_str(ifs_table->conn[i].null_allowed); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_conn_cur->null_allowed); + rc |= fprintf(fp, " %s,\n", str); - fprintf(fp, " },\n"); + rc |= fprintf(fp, " },\n"); } /* for number of parameters */ /* Finish off the structure */ + rc |= fprintf(fp, + "};\n" + "\n"); + + /* Check outputs */ + if (rc < 0) { + print_error("Writing of connection information failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_conn_info */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); -} /* *********************************************************************** */ @@ -613,152 +677,162 @@ input deck. -static void write_param_info( +static int write_param_info( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char *str; + const char *str; /* Only write the paramTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_param == 0) - return; + if (ifs_table->num_param == 0) { + return 0; + } /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Param_Info_t MIFparamTable[] = {\n"); + int rc = 0; + rc |= fprintf(fp, + "\n" + "static Mif_Param_Info_t MIFparamTable[] = {\n"); /* Write out an entry for each parameter in the table */ + const Param_Info_t * const param = ifs_table->param; + const int num_param = ifs_table->num_param; + for (i = 0; i < num_param; i++) { + const Param_Info_t * const p_param_cur = param + i; - for(i = 0; i < ifs_table->num_param; i++) { + rc |= fprintf(fp, " {\n"); + rc |= fprintf(fp, " \"%s\",\n", p_param_cur->name); + rc |= fprintf(fp, " \"%s\",\n", p_param_cur->description); - fprintf(fp, " {\n"); - fprintf(fp, " \"%s\",\n",ifs_table->param[i].name); - fprintf(fp, " \"%s\",\n",ifs_table->param[i].description); + rc |= fprintf(fp, " %s,\n", + data_type_to_str(p_param_cur->type)); - str = data_type_to_str(ifs_table->param[i].type); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_default); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_default); - fprintf(fp, " %s,\n", str); - - if(ifs_table->param[i].has_default == true) - str = value_to_str(ifs_table->param[i].type, ifs_table->param[i].default_value); + if (p_param_cur->has_default == true) + str = value_to_str(p_param_cur->type, p_param_cur->default_value); else str = no_value_to_str(); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_lower_limit); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_lower_limit); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_lower_limit == true) - str = value_to_str(ifs_table->param[i].type, ifs_table->param[i].lower_limit); + if (p_param_cur->has_lower_limit == true) + str = value_to_str(p_param_cur->type, p_param_cur->lower_limit); else str = no_value_to_str(); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_upper_limit); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_upper_limit); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_upper_limit == true) - str = value_to_str(ifs_table->param[i].type, ifs_table->param[i].upper_limit); + if (p_param_cur->has_upper_limit == true) + str = value_to_str(p_param_cur->type, p_param_cur->upper_limit); else str = no_value_to_str(); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].is_array); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->is_array); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].is_array == false) { + if (!p_param_cur->is_array) { str = boolean_to_str(false); /* has_conn_ref */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* conn_ref */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } else { /* is_array == true */ - str = boolean_to_str(ifs_table->param[i].has_conn_ref); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_conn_ref); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_conn_ref == true) { + if (p_param_cur->has_conn_ref) { - str = integer_to_str(ifs_table->param[i].conn_ref); - fprintf(fp, " %s,\n", str); + str = integer_to_str(p_param_cur->conn_ref); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* lower_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = boolean_to_str(false); /* has_upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); str = integer_to_str(0); /* upper_bound */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } else { /* has_conn_ref == false */ str = integer_to_str(0); /* conn_ref */ - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_lower_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_lower_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_lower_bound == true) - str = integer_to_str(ifs_table->param[i].lower_bound); + if (p_param_cur->has_lower_bound) + str = integer_to_str(p_param_cur->lower_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - str = boolean_to_str(ifs_table->param[i].has_upper_bound); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->has_upper_bound); + rc |= fprintf(fp, " %s,\n", str); - if(ifs_table->param[i].has_upper_bound == true) - str = integer_to_str(ifs_table->param[i].upper_bound); + if (p_param_cur->has_upper_bound) + str = integer_to_str(p_param_cur->upper_bound); else str = integer_to_str(0); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); } /* if has_conn_ref */ } /* if is_array */ - str = boolean_to_str(ifs_table->param[i].null_allowed); - fprintf(fp, " %s,\n", str); + str = boolean_to_str(p_param_cur->null_allowed); + rc |= fprintf(fp, " %s,\n", str); - fprintf(fp, " },\n"); + rc |= fprintf(fp, " },\n"); } /* for number of parameters */ /* Finish off the structure */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + rc |= fprintf(fp, "};\n\n"); -} + /* Check outputs */ + if (rc < 0) { + print_error("Writing of param information failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_param_info */ @@ -780,53 +854,59 @@ written by write_inst_var_info is more extensive. -static void write_inst_var_info( +static int write_inst_var_info( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - + int xrc = 0; int i; - char *str; + const char *str; /* Only write the inst_varTable if there is something to put in it. */ /* Otherwise, we will put NULL in the SPICEdev structure in its slot */ - if(ifs_table->num_inst_var == 0) - return; + if (ifs_table->num_inst_var == 0) + return 0; /* Write the structure beginning */ - - fprintf(fp, "\n"); - fprintf(fp, "static Mif_Inst_Var_Info_t MIFinst_varTable[] = {\n"); + int rc = 0; + rc |= fprintf(fp, + "\n" + "static Mif_Inst_Var_Info_t MIFinst_varTable[] = {\n"); /* Write out an entry for each parameter in the table */ for(i = 0; i < ifs_table->num_inst_var; i++) { - fprintf(fp, " {\n"); - fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].name); - fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].description); + rc |= fprintf(fp, " {\n"); + rc |= fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].name); + rc |= fprintf(fp, " \"%s\",\n",ifs_table->inst_var[i].description); - str = data_type_to_str(ifs_table->inst_var[i].type); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", + data_type_to_str(ifs_table->inst_var[i].type)); str = boolean_to_str(ifs_table->inst_var[i].is_array); - fprintf(fp, " %s,\n", str); + rc |= fprintf(fp, " %s,\n", str); - fprintf(fp, " },\n"); + rc |= fprintf(fp, " },\n"); } /* for number of parameters */ /* Finish off the structure */ - fprintf(fp, "};\n"); - fprintf(fp, "\n"); + rc |= fprintf(fp, "};\n\n"); -} + /* Check outputs */ + if (rc < 0) { + print_error("Writing of instance variable information failed."); + xrc = -1; + } + return xrc; +} /* end of function write_inst_var_info */ @@ -845,118 +925,133 @@ pointers to all of the above data structures. -static void write_SPICEdev( +static int write_SPICEdev( FILE *fp, /* File to write to */ Ifs_Table_t *ifs_table) /* Table of Interface Specification data */ { - - /* Extern the code model function name */ - fprintf(fp, "\n"); - fprintf(fp, "extern void %s(Mif_Private_t *);\n", - ifs_table->name.c_fcn_name); + int rc = 0; /* init print rc to nonnegative (no error) */ + int xrc = 0; - /* SPICE now needs these static integers */ - fprintf(fp, "\n"); - fprintf(fp, "static int val_terms = 0;\n"); - fprintf(fp, "static int val_numNames = 0;\n"); - fprintf(fp, "static int val_numInstanceParms = %d;\n",ifs_table->num_inst_var); - fprintf(fp, "static int val_numModelParms = %d;\n",ifs_table->num_param); - fprintf(fp, "static int val_sizeofMIFinstance = sizeof(MIFinstance);\n"); - fprintf(fp, "static int val_sizeofMIFmodel = sizeof(MIFmodel);\n"); + /* Extern the code model function name */ + rc |= fprintf(fp, + "\n" + "extern void %s(Mif_Private_t *);\n", + ifs_table->name.c_fcn_name); + + /* SPICE now needs these static integers */ + rc |= fprintf(fp, + "\n" + "static int val_terms = 0;\n" + "static int val_numNames = 0;\n" + "static int val_numInstanceParms = %d;\n" + "static int val_numModelParms = %d;\n" + "static int val_sizeofMIFinstance = sizeof(MIFinstance);\n" + "static int val_sizeofMIFmodel = sizeof(MIFmodel);\n", + ifs_table->num_inst_var, ifs_table->num_param); /* Write out the structure beginning */ /* Use the c function external identifier appended with _info as the */ /* external identifier for the structure. */ - fprintf(fp, "\n"); - fprintf(fp, "SPICEdev %s_info = {\n", ifs_table->name.c_fcn_name); + rc |= fprintf(fp, + "\n" + "SPICEdev %s_info = {\n", ifs_table->name.c_fcn_name); /* Write the IFdevice structure */ - fprintf(fp, " .DEVpublic = {\n"); - fprintf(fp, " .name = \"%s\",\n", ifs_table->name.model_name); - fprintf(fp, " .description = \"%s\",\n", ifs_table->name.description); - fprintf(fp, " .terms = &val_terms,\n"); - fprintf(fp, " .numNames = &val_numNames,\n"); - fprintf(fp, " .termNames = NULL,\n"); + rc |= fprintf(fp, " .DEVpublic = {\n"); + rc |= fprintf(fp, " .name = \"%s\",\n", ifs_table->name.model_name); + rc |= fprintf(fp, " .description = \"%s\",\n", ifs_table->name.description); + rc |= fprintf(fp, + " .terms = &val_terms,\n" + " .numNames = &val_numNames,\n" + " .termNames = NULL,\n" + " .numInstanceParms = &val_numInstanceParms,\n"); - fprintf(fp, " .numInstanceParms = &val_numInstanceParms,\n"); if(ifs_table->num_inst_var > 0) - fprintf(fp, " .instanceParms = MIFpTable,\n"); + rc |= fprintf(fp, " .instanceParms = MIFpTable,\n"); else - fprintf(fp, " .instanceParms = NULL,\n"); + rc |= fprintf(fp, " .instanceParms = NULL,\n"); - fprintf(fp, " .numModelParms = &val_numModelParms,\n"); + rc |= fprintf(fp, " .numModelParms = &val_numModelParms,\n"); if(ifs_table->num_param > 0) - fprintf(fp, " .modelParms = MIFmPTable,\n"); + rc |= fprintf(fp, " .modelParms = MIFmPTable,\n"); else - fprintf(fp, " .modelParms = NULL,\n"); - fprintf(fp, " .flags = 0,\n\n"); + rc |= fprintf(fp, " .modelParms = NULL,\n"); + rc |= fprintf(fp, " .flags = 0,\n\n"); - fprintf(fp, " .cm_func = %s,\n", ifs_table->name.c_fcn_name); + rc |= fprintf(fp, " .cm_func = %s,\n", ifs_table->name.c_fcn_name); - fprintf(fp, " .num_conn = %d,\n", ifs_table->num_conn); + rc |= fprintf(fp, " .num_conn = %d,\n", ifs_table->num_conn); if(ifs_table->num_conn > 0) - fprintf(fp, " .conn = MIFconnTable,\n"); + rc |= fprintf(fp, " .conn = MIFconnTable,\n"); else - fprintf(fp, " .conn = NULL,\n"); + rc |= fprintf(fp, " .conn = NULL,\n"); - fprintf(fp, " .num_param = %d,\n", ifs_table->num_param); + rc |= fprintf(fp, " .num_param = %d,\n", ifs_table->num_param); if(ifs_table->num_param > 0) - fprintf(fp, " .param = MIFparamTable,\n"); + rc |= fprintf(fp, " .param = MIFparamTable,\n"); else - fprintf(fp, " .param = NULL,\n"); + rc |= fprintf(fp, " .param = NULL,\n"); - fprintf(fp, " .num_inst_var = %d,\n", ifs_table->num_inst_var); + rc |= fprintf(fp, " .num_inst_var = %d,\n", ifs_table->num_inst_var); if(ifs_table->num_inst_var > 0) - fprintf(fp, " .inst_var = MIFinst_varTable,\n"); + rc |= fprintf(fp, " .inst_var = MIFinst_varTable,\n"); else - fprintf(fp, " .inst_var = NULL,\n"); + rc |= fprintf(fp, " .inst_var = NULL,\n"); - fprintf(fp, " },\n\n"); + rc |= fprintf(fp, " },\n\n"); /* Write the names of the generic code model functions */ - fprintf(fp, " .DEVparam = NULL,\n"); - fprintf(fp, " .DEVmodParam = MIFmParam,\n"); - fprintf(fp, " .DEVload = MIFload,\n"); - fprintf(fp, " .DEVsetup = MIFsetup,\n"); - fprintf(fp, " .DEVunsetup = MIFunsetup,\n"); - fprintf(fp, " .DEVpzSetup = NULL,\n"); - fprintf(fp, " .DEVtemperature = NULL,\n"); - fprintf(fp, " .DEVtrunc = MIFtrunc,\n"); - fprintf(fp, " .DEVfindBranch = NULL,\n"); - fprintf(fp, " .DEVacLoad = MIFload,\n"); - fprintf(fp, " .DEVaccept = NULL,\n"); - fprintf(fp, " .DEVdestroy = MIFdestroy,\n"); - fprintf(fp, " .DEVmodDelete = MIFmDelete,\n"); - fprintf(fp, " .DEVdelete = MIFdelete,\n"); - fprintf(fp, " .DEVsetic = NULL,\n"); - fprintf(fp, " .DEVask = MIFask,\n"); - fprintf(fp, " .DEVmodAsk = MIFmAsk,\n"); - fprintf(fp, " .DEVpzLoad = NULL,\n"); - fprintf(fp, " .DEVconvTest = MIFconvTest,\n"); - fprintf(fp, " .DEVsenSetup = NULL,\n"); - fprintf(fp, " .DEVsenLoad = NULL,\n"); - fprintf(fp, " .DEVsenUpdate = NULL,\n"); - fprintf(fp, " .DEVsenAcLoad = NULL,\n"); - fprintf(fp, " .DEVsenPrint = NULL,\n"); - fprintf(fp, " .DEVsenTrunc = NULL,\n"); - fprintf(fp, " .DEVdisto = NULL,\n"); - fprintf(fp, " .DEVnoise = NULL,\n"); - fprintf(fp, " .DEVsoaCheck = NULL,\n"); - fprintf(fp, " .DEVinstSize = &val_sizeofMIFinstance,\n"); - fprintf(fp, " .DEVmodSize = &val_sizeofMIFmodel,\n"); - fprintf(fp, "\n"); - fprintf(fp, "#ifdef CIDER\n"); - fprintf(fp, " .DEVdump = NULL,\n"); - fprintf(fp, " .DEVacct = NULL,\n"); - fprintf(fp, "#endif\n"); - fprintf(fp, "};\n"); - fprintf(fp, "\n"); -} + rc |= fprintf(fp, + " .DEVparam = NULL,\n" + " .DEVmodParam = MIFmParam,\n" + " .DEVload = MIFload,\n" + " .DEVsetup = MIFsetup,\n" + " .DEVunsetup = MIFunsetup,\n" + " .DEVpzSetup = NULL,\n" + " .DEVtemperature = NULL,\n" + " .DEVtrunc = MIFtrunc,\n" + " .DEVfindBranch = NULL,\n" + " .DEVacLoad = MIFload,\n" + " .DEVaccept = NULL,\n" + " .DEVdestroy = MIFdestroy,\n" + " .DEVmodDelete = MIFmDelete,\n" + " .DEVdelete = MIFdelete,\n" + " .DEVsetic = NULL,\n" + " .DEVask = MIFask,\n" + " .DEVmodAsk = MIFmAsk,\n" + " .DEVpzLoad = NULL,\n" + " .DEVconvTest = MIFconvTest,\n" + " .DEVsenSetup = NULL,\n" + " .DEVsenLoad = NULL,\n" + " .DEVsenUpdate = NULL,\n" + " .DEVsenAcLoad = NULL,\n" + " .DEVsenPrint = NULL,\n" + " .DEVsenTrunc = NULL,\n" + " .DEVdisto = NULL,\n" + " .DEVnoise = NULL,\n" + " .DEVsoaCheck = NULL,\n" + " .DEVinstSize = &val_sizeofMIFinstance,\n" + " .DEVmodSize = &val_sizeofMIFmodel,\n" + "\n" + "#ifdef CIDER\n" + " .DEVdump = NULL,\n" + " .DEVacct = NULL,\n" + "#endif\n" + "};\n\n" + ); + /* Check outputs */ + if (rc < 0) { + print_error("Writing of SPICE device information failed."); + xrc = -1; + } + + return xrc; +} /* end of function write_SPICEdev */ @@ -973,202 +1068,111 @@ being created. #define BASE_STR_LEN 80 -static char *data_type_to_str(Data_Type_t type) +static const char *data_type_to_str(Data_Type_t type) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - - switch(type) { - + switch (type) { case CMPP_BOOLEAN: - strcpy(str,"MIF_BOOLEAN"); - break; - + return "MIF_BOOLEAN"; case CMPP_INTEGER: - strcpy(str,"MIF_INTEGER"); - break; - + return "MIF_INTEGER"; case CMPP_REAL: - strcpy(str,"MIF_REAL"); - break; - + return "MIF_REAL"; case CMPP_COMPLEX: - strcpy(str,"MIF_COMPLEX"); - break; - + return "MIF_COMPLEX"; case CMPP_STRING: - strcpy(str,"MIF_STRING"); - break; - - case CMPP_POINTER: - strcpy(str,"MIF_STRING"); - break; - + case CMPP_POINTER: + return "MIF_STRING"; default: print_error("INTERNAL ERROR - data_type_to_str() - Impossible data type."); + return "INVALID DATA TYPE"; } - - return(str); } /* *********************************************************************** */ -static char *port_type_to_str(Port_Type_t port) +static const char *port_type_to_str(Port_Type_t port) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - - switch(port) { - + switch (port) { case VOLTAGE: - strcpy(str,"MIF_VOLTAGE"); - break; - + return "MIF_VOLTAGE"; case DIFF_VOLTAGE: - strcpy(str,"MIF_DIFF_VOLTAGE"); - break; - + return "MIF_DIFF_VOLTAGE"; case CURRENT: - strcpy(str,"MIF_CURRENT"); - break; - + return "MIF_CURRENT"; case DIFF_CURRENT: - strcpy(str,"MIF_DIFF_CURRENT"); - break; - + return "MIF_DIFF_CURRENT"; case VSOURCE_CURRENT: - strcpy(str,"MIF_VSOURCE_CURRENT"); - break; - + return "MIF_VSOURCE_CURRENT"; case CONDUCTANCE: - strcpy(str,"MIF_CONDUCTANCE"); - break; - + return "MIF_CONDUCTANCE"; case DIFF_CONDUCTANCE: - strcpy(str,"MIF_DIFF_CONDUCTANCE"); - break; - + return "MIF_DIFF_CONDUCTANCE"; case RESISTANCE: - strcpy(str,"MIF_RESISTANCE"); - break; - + return "MIF_RESISTANCE"; case DIFF_RESISTANCE: - strcpy(str,"MIF_DIFF_RESISTANCE"); - break; - + return "MIF_DIFF_RESISTANCE"; case DIGITAL: - strcpy(str,"MIF_DIGITAL"); - break; - + return "MIF_DIGITAL"; case USER_DEFINED: - strcpy(str,"MIF_USER_DEFINED"); - break; - + return "MIF_USER_DEFINED"; default: print_error("INTERNAL ERROR - port_type_to_str() - Impossible port type."); + return "INVALID PORT TYPE"; } - - return(str); - } /* *********************************************************************** */ -static char *gen_port_type_str(Port_Type_t port) +static const char *gen_port_type_str(Port_Type_t port) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - - switch(port) { - + switch (port) { case VOLTAGE: - strcpy(str,"v"); - break; - + return "v"; case DIFF_VOLTAGE: - strcpy(str,"vd"); - break; - + return "vd"; case CURRENT: - strcpy(str,"i"); - break; - + return "i"; case DIFF_CURRENT: - strcpy(str,"id"); - break; - + return "id"; case VSOURCE_CURRENT: - strcpy(str,"vnam"); - break; - + return "vnam"; case CONDUCTANCE: - strcpy(str,"g"); - break; - + return "g"; case DIFF_CONDUCTANCE: - strcpy(str,"gd"); - break; - + return "gd"; case RESISTANCE: - strcpy(str,"h"); - break; - + return "h"; case DIFF_RESISTANCE: - strcpy(str,"hd"); - break; - + return "hd"; case DIGITAL: - strcpy(str,"d"); - break; - + return "d"; case USER_DEFINED: - strcpy(str,""); - break; - + return ""; default: - print_error("INTERNAL ERROR - gen_port_type_str() - Impossible port type."); + print_error("INTERNAL ERROR - gen_port_type_str() - " + "Impossible port type."); + return "INVALID PORT TYPE"; } +} /* end of function gen_port_type_str */ - return(str); - -} /* *********************************************************************** */ -static char *dir_to_str(Dir_t dir) +static const char *dir_to_str(Dir_t dir) { - static char *str = NULL; - - if(str == NULL) - str = (char *) malloc(BASE_STR_LEN+1); - switch(dir) { - case CMPP_IN: - strcpy(str,"MIF_IN"); - break; - + return "MIF_IN"; case CMPP_OUT: - strcpy(str,"MIF_OUT"); - break; - + return "MIF_OUT"; case CMPP_INOUT: - strcpy(str,"MIF_INOUT"); - break; - + return "MIF_INOUT"; default: print_error("INTERNAL ERROR - dir_to_str() - Impossible direction type."); + return "MIF_DIRECTION_INVALID"; } - - return(str); } @@ -1180,12 +1184,15 @@ static char *value_to_str(Data_Type_t type, Value_t value) static char *str = NULL; static int max_len = 0; - char *bool_str; + const char *bool_str; int str_len; if(str == NULL) { - str = (char *) malloc(2 * BASE_STR_LEN + 1); + if ((str = (char *) malloc(2 * BASE_STR_LEN + 1)) == (char *) NULL) { + (void) fprintf(stderr, "Unable to allocate string buffer.\n"); + return (char *) NULL; + } max_len = 2 * BASE_STR_LEN; } @@ -1212,35 +1219,38 @@ static char *value_to_str(Data_Type_t type, Value_t value) case CMPP_STRING: /* be careful, the string could conceivably be very long... */ str_len = (int) strlen(value.svalue); - if((str_len + BASE_STR_LEN) > max_len) { - str = (char *) realloc(str, (size_t) (max_len + str_len + 1)); + if ((str_len + BASE_STR_LEN) > max_len) { + size_t n_byte_alloc = max_len + str_len + 1; + void * const p = realloc(str, n_byte_alloc); + if (p == NULL) { + (void) fprintf(stderr, "Unable to resize string " + "buffer to size %zu.\n", + n_byte_alloc); + free(str); + return (char *) NULL; + } + str = (char *) p; max_len += str_len; - } + } /* end of resize */ + sprintf(str, "{MIF_FALSE, 0, 0.0, {0.0, 0.0}, \"%s\"}", value.svalue); break; default: print_error("INTERNAL ERROR - value_to_str() - Impossible data type."); - } + } /* end of switch */ + + return str; +} /* end of function value_to_string */ - return(str); -} /* *********************************************************************** */ -static char *boolean_to_str(bool value) +static const char *boolean_to_str(bool value) { - static char *str = NULL; - - if (str == NULL) { - str = (char *) malloc(BASE_STR_LEN+1); - } - - strcpy(str, value ? "MIF_TRUE" : "MIF_FALSE"); - - return str; + return value ? "MIF_TRUE" : "MIF_FALSE"; } @@ -1248,31 +1258,17 @@ static char *boolean_to_str(bool value) static char *integer_to_str(int value) { - static char *str = NULL; - - if(str == NULL) { - str = (char *) malloc(BASE_STR_LEN + 1); - } - + static char str[3 * sizeof(int) + 1]; sprintf(str, "%d", value); - - return(str); + return str; } /* *********************************************************************** */ -static char *no_value_to_str(void) +static const char *no_value_to_str(void) { - static char *str = NULL; - - if(str == NULL) { - str = (char *) malloc(BASE_STR_LEN + 1); - } - - sprintf(str, "{MIF_FALSE, 0, 0.0, {0.0, 0.0}, NULL}"); - - return(str); + return "{MIF_FALSE, 0, 0.0, {0.0, 0.0}, NULL}"; } diff --git a/src/xspice/evt/evtload.c b/src/xspice/evt/evtload.c index 903e5f2b4..1dc0368a7 100644 --- a/src/xspice/evt/evtload.c +++ b/src/xspice/evt/evtload.c @@ -340,6 +340,7 @@ static void EVTcreate_state( { new_state = state_data->free[inst_index]; state_data->free[inst_index] = new_state->next; + new_state->next = NULL; // reusing dirty memory: next must be reset } else { diff --git a/src/xspice/icm/GNUmakefile.in b/src/xspice/icm/GNUmakefile.in index 1958103fe..2e8e0766b 100644 --- a/src/xspice/icm/GNUmakefile.in +++ b/src/xspice/icm/GNUmakefile.in @@ -44,14 +44,30 @@ clean: #----------------------------------------------------------------------------- NGSRCDIR = $(CURDIR)/../../../../src - +COMPILE = $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(VIS_CFLAGS) dstring.o : $(NGSRCDIR)/misc/dstring.c $(NGSRCDIR)/include/ngspice/dstring.h - $(COMPILE) -I $(NGSRCDIR)/include/ngspice -o $@ -c $< + $(COMPILE) -I $(NGSRCDIR)/include -o $@ -c $< ifdef cm -modlst := $(shell cat $(srcdir)/$(cm)/modpath.lst) -udnlst := $(shell cat $(srcdir)/$(cm)/udnpath.lst) +# These will work for a simpler format of the .lst files with # comments and +# version information on the same line. +# sed removes comment lines of form [space]#[text] +# awk keeps the name of the path only, removing version number if present +# $$ and \# are escapes for Makefile +#modlst := $(shell cat $(srcdir)/$(cm)/modpath.lst | sed -e '/^[ \t]*\#/d' |\ +# awk '{ print $$1 }') +#udnlst := $(shell cat $(srcdir)/$(cm)/udnpath.lst | sed -e '/^[ \t]*\#/d' |\ +# awk '{ print $$1 }') + +ifeq ($(OS),Windows_NT) + cmpp = ../cmpp/cmpp.exe +else + cmpp = ../cmpp/cmpp +endif +modlst := $(shell $(cmpp) -p $(srcdir)/$(cm)/modpath.lst) +udnlst := $(shell $(cmpp) -p $(srcdir)/$(cm)/udnpath.lst) + cm-dirs := $(cm) $(udnlst:%=$(cm)/%) $(modlst:%=$(cm)/%) cm-dep-dirs := $(cm-dirs:%=%/.deps) diff --git a/src/xspice/icm/analog/file_source/cfunc.mod b/src/xspice/icm/analog/file_source/cfunc.mod index 6eae2f9f1..d664fcd5d 100644 --- a/src/xspice/icm/analog/file_source/cfunc.mod +++ b/src/xspice/icm/analog/file_source/cfunc.mod @@ -65,10 +65,6 @@ NON-STANDARD FEATURES #define DIR_PATHSEP "/" #endif -#if defined(_MSC_VER) -#define strdup _strdup -#endif - /*=== LOCAL VARIABLES & TYPEDEFS =======*/ struct filesource_state { @@ -149,27 +145,8 @@ NON-STANDARD FEATURES /*=== CM_FILESOURCE ROUTINE ===*/ - - -static void -cm_filesource_callback(ARGS, Mif_Callback_Reason_t reason) -{ - switch (reason) { - case MIF_CB_DESTROY: { - Local_Data_t *loc = STATIC_VAR (locdata); - if (loc->state->fp) - fclose(loc->state->fp); - free(loc->state); - free(loc->amplinterval); - free(loc->timeinterval); - free(loc->indata->datavec); - free(loc->indata); - free(loc); - break; - } - } -} +static void cm_filesource_callback(ARGS, Mif_Callback_Reason_t reason); void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. */ { @@ -189,18 +166,39 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. int count; - CALLBACK = cm_filesource_callback; - /*** allocate static storage for *loc ***/ - STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t )); - loc = STATIC_VAR (locdata); + if ((loc = (Local_Data_t *) (STATIC_VAR(locdata) = tcalloc_raw(1, + sizeof(Local_Data_t)))) == (Local_Data_t *) NULL) { + cm_message_send("Unable to allocate Local_Data_t " + "in cm_filesource()"); + return; + } /* Allocate storage for internal state */ - loc->timeinterval = (double*)calloc(2, sizeof(double)); - loc->amplinterval = (double*)calloc(2 * (size_t) size, sizeof(double)); - loc->state = (struct filesource_state*)malloc(sizeof(struct filesource_state)); - loc->indata = (struct infiledata*)malloc(sizeof(struct infiledata)); - loc->indata->datavec = (double*)malloc(sizeof(double) * stepsize * 1000); + loc->timeinterval = (double *) tcalloc_raw(2, sizeof(double)); + loc->amplinterval = (double *) tcalloc_raw(2 * (size_t) size, + sizeof(double)); + loc->state = (struct filesource_state *) tcalloc_raw(1, + sizeof(struct filesource_state)); /* calloc to null fp */ + loc->indata = (struct infiledata *) tmalloc_raw( + sizeof(struct infiledata)); + loc->indata->datavec = (double *) tmalloc_raw(sizeof(double) * + stepsize * 1000); + + /* Check allocations */ + if (loc->timeinterval == (double *) NULL || + loc->amplinterval == (double *) NULL || + loc->state == (struct filesource_state *) NULL || + loc->indata == (struct infiledata *) NULL || + loc->indata->datavec == (double *) NULL) { + cm_message_send("Unable to allocate Local_Data_t fields " + "in cm_filesource()"); + cm_filesource_callback(mif_private, MIF_CB_DESTROY); + return; + } + + CALLBACK = cm_filesource_callback; + loc->indata->vecallocated = stepsize * 1000; loc->indata->maxoccupied = 0; loc->indata->actpointer = 0; @@ -210,13 +208,21 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. loc->state->fp = fopen_with_path(PARAM(file), "r"); loc->state->atend = 0; if (!loc->state->fp) { - char *lbuffer, *p; + char *lbuffer; lbuffer = getenv("NGSPICE_INPUT_DIR"); if (lbuffer && *lbuffer) { - p = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1); - sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file)); - loc->state->fp = fopen(p, "r"); - free(p); + char *p; + if ((p = (char *) tmalloc_raw(strlen(lbuffer) + + strlen(DIR_PATHSEP) + strlen(PARAM(file)) + 1)) == + (char *) NULL) { + cm_message_send("Unable to allocate buffer " + "for building file name in cm_filesource()"); + } + else { + sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(file)); + loc->state->fp = fopen(p, "r"); + txfree(p); + } } if (!loc->state->fp) { cm_message_printf("cannot open file %s", PARAM(file)); @@ -237,18 +243,23 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. loc->state->atend = 1; break; } - cpdel = cp = strdup(line); + if ((cpdel = cp = tstrdup_raw(line)) == (char *) NULL) { + cm_message_send("Unable to duplicate string " + "cm_filesource()"); + loc->state->atend = 1; + break; + } /* read the time channel; update the time difference */ while (*cp && isspace_c(*cp)) ++cp; if (*cp == '*' || *cp == '#' || *cp == ';') { - free(cpdel); + txfree(cpdel); continue; } t = strtod(cp, &cp2); if (cp2 == cp) { - free(cpdel); + txfree(cpdel); continue; } cp = cp2; @@ -265,11 +276,13 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. If not, add another 1000*size doubles */ if (count > loc->indata->vecallocated - size) { loc->indata->vecallocated += size * 1000; - loc->indata->datavec = (double*)realloc(loc->indata->datavec, sizeof(double) * loc->indata->vecallocated); - } - if(loc->indata->datavec == NULL){ - cm_message_printf("cannot allocate enough memory"); - break; // loc->state->atend = 1; + void * const p = trealloc_raw(loc->indata->datavec, + sizeof(double) * loc->indata->vecallocated); + if (p == NULL) { + cm_message_printf("cannot allocate enough memory"); + break; // loc->state->atend = 1; + } + loc->indata->datavec = (double *) p; } loc->indata->datavec[count++] = t; @@ -287,7 +300,7 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. t += PARAM(amploffset[i]); loc->indata->datavec[count++] = t; } - free(cpdel); + txfree(cpdel); } loc->indata->maxoccupied = count; @@ -345,4 +358,48 @@ void cm_filesource(ARGS) /* structure holding parms, inputs, outputs, etc. for (i = 0; i < size; ++i) OUTPUT(out[i]) = loc->amplinterval[2 * i + 1]; } -} +} /* end of function cm_filesource */ + + + +static void cm_filesource_callback(ARGS, Mif_Callback_Reason_t reason) +{ + switch (reason) { + case MIF_CB_DESTROY: { + Local_Data_t *loc = (Local_Data_t *) STATIC_VAR(locdata); + if (loc == (Local_Data_t *) NULL) { + break; + } + + if (loc->state != (struct filesource_state *) NULL) { + if (loc->state->fp != (FILE *) NULL) { + fclose(loc->state->fp); + } + txfree(loc->state); + } + + if (loc->amplinterval != (double *) NULL) { + txfree(loc->amplinterval); + } + + if (loc->timeinterval != (double *) NULL) { + txfree(loc->timeinterval); + } + + if (loc->indata) { + if (loc->indata->datavec) { + txfree(loc->indata->datavec); + } + txfree(loc->indata); + } + + txfree(loc); + + STATIC_VAR(locdata) = NULL; + break; + } + } +} /* end of function cm_filesource_callback */ + + + diff --git a/src/xspice/icm/analog/modpath.lst b/src/xspice/icm/analog/modpath.lst index d5555b2a4..d83d03e8b 100644 --- a/src/xspice/icm/analog/modpath.lst +++ b/src/xspice/icm/analog/modpath.lst @@ -1,19 +1,20 @@ -climit -divide -d_dt -gain -hyst -ilimit -int -limit -mult -multi_input_pwl -oneshot -pwl -sine -slew -square -summer -s_xfer -triangle -file_source +#Directory Version +climit 1 +divide 1 +d_dt 1 +gain 1 +hyst 1 +ilimit 1 +int 1 +limit 1 +mult 1 +multi_input_pwl 1 +oneshot 2 +pwl 2 +sine 2 +slew 1 +square 1 +summer 1 +s_xfer 2 +triangle 1 +file_source 2 diff --git a/src/xspice/icm/analog/oneshot/cfunc.mod b/src/xspice/icm/analog/oneshot/cfunc.mod index 822071e70..60a09a0e3 100644 --- a/src/xspice/icm/analog/oneshot/cfunc.mod +++ b/src/xspice/icm/analog/oneshot/cfunc.mod @@ -155,6 +155,8 @@ NON-STANDARD FEATURES #include +static void cm_oneshot_callback(ARGS, Mif_Callback_Reason_t reason); + void cm_oneshot(ARGS) /* structure holding parms, inputs, outputs, etc. */ { @@ -251,24 +253,31 @@ void cm_oneshot(ARGS) /* structure holding parms, cm_analog_alloc(OUTPUT_OLD,sizeof(double)); /*** allocate static storage for *loc ***/ - STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t )); - loc = STATIC_VAR (locdata); + if ((loc = (Local_Data_t *) (STATIC_VAR(locdata) = tcalloc_raw(1, + sizeof(Local_Data_t)))) == (Local_Data_t *) NULL) { + cm_message_send("Unable to allocate Local_Data_t " + "in cm_oneshot()"); + cm_oneshot_callback(mif_private, MIF_CB_DESTROY); + return; + } /* Allocate storage for breakpoint domain & pulse width values */ - x = loc->control = (double *) calloc((size_t) cntl_size, sizeof(double)); - if (!x) { + if ((x = loc->control = (double *) tcalloc_raw((size_t) cntl_size, + sizeof(double))) == (double *) NULL) { cm_message_send(oneshot_allocation_error); + cm_oneshot_callback(mif_private, MIF_CB_DESTROY); return; } - y = loc->pw = (double *) calloc((size_t) pw_size, sizeof(double)); - if (!y) { + if ((y = loc->pw = (double *) tcalloc_raw((size_t) pw_size, + sizeof(double))) == (double *) NULL) { cm_message_send(oneshot_allocation_error); + cm_oneshot_callback(mif_private, MIF_CB_DESTROY); return; } + CALLBACK = cm_oneshot_callback; loc->tran_init = FALSE; - - } + } /* end of initialization */ if(ANALYSIS == MIF_DC) { @@ -339,7 +348,12 @@ void cm_oneshot(ARGS) /* structure holding parms, OUTPUT(out) = output_low; } else { - loc = STATIC_VAR (locdata); + if ((loc = (Local_Data_t *) STATIC_VAR(locdata)) == + (Local_Data_t *) NULL) { + cm_message_send("Attempt to use uninitialized Local_Data_t " + "in cm_oneshot()"); + return; + } x = loc->control; y = loc->pw; @@ -544,5 +558,28 @@ void cm_oneshot(ARGS) /* structure holding parms, ac_gain.imag= 0.0; AC_GAIN(out,clk) = ac_gain; } -} +} /* end of function cm_oneshot */ + + + +/* This function frees resources when called with reason argument + * MIF_CB_DESTROY */ +static void cm_oneshot_callback(ARGS, Mif_Callback_Reason_t reason) +{ + switch (reason) { + case MIF_CB_DESTROY: { + Local_Data_t *loc = STATIC_VAR(locdata); + if (loc == (Local_Data_t *) NULL) { + break; + } + txfree(loc->control); + txfree(loc->pw); + txfree(loc); + STATIC_VAR(locdata) = (Local_Data_t *) NULL; + break; + } + } +} /* end of function cm_oneshot_callback */ + + diff --git a/src/xspice/icm/analog/pwl/cfunc.mod b/src/xspice/icm/analog/pwl/cfunc.mod index 9a2ee5d99..251fc197f 100644 --- a/src/xspice/icm/analog/pwl/cfunc.mod +++ b/src/xspice/icm/analog/pwl/cfunc.mod @@ -229,19 +229,30 @@ cm_pwl_callback(ARGS, Mif_Callback_Reason_t reason) { switch (reason) { case MIF_CB_DESTROY: { - double *last_x_value = STATIC_VAR (last_x_value); - double *x = STATIC_VAR (x); - double *y = STATIC_VAR (y); - free(last_x_value); - free(x); - free(y); + void *p = STATIC_VAR(last_x_value); + if (p != NULL) { + txfree(p); + } + + p = STATIC_VAR(x); + if (p != NULL) { + txfree(p); + } + + p = STATIC_VAR(y); + if (p != NULL) { + txfree(p); + } + STATIC_VAR (last_x_value) = NULL; STATIC_VAR (x) = NULL; - STATIC_VAR (y) = NULL; + STATIC_VAR (y) = NULL; break; } } -} +} /* end of function cm_pwl_callback */ + + /*=== CM_PWL ROUTINE ================*/ @@ -270,10 +281,11 @@ void cm_pwl(ARGS) /* structure holding parms, Mif_Complex_t ac_gain; - CALLBACK = cm_pwl_callback; - char *allocation_error="\n***ERROR***\nPWL: Allocation calloc failed!\n"; - char *limit_error="\n***ERROR***\nPWL: Violation of 50% rule in breakpoints!\n"; + static const char * const allocation_error = "\n***ERROR***\n" + "PWL: Allocation failed!\n"; + static const char * const limit_error = "\n***ERROR***\n" + "PWL: Violation of 50% rule in breakpoints!\n"; /* Retrieve frequently used parameters... */ @@ -282,25 +294,22 @@ void cm_pwl(ARGS) /* structure holding parms, size = PARAM_SIZE(x_array); - if (INIT==1) { /* First pass...allocate storage for previous value... */ /* Allocate storage for last_x_value */ - STATIC_VAR(last_x_value) = (double *) malloc(sizeof(double)); - last_x_value = (double *) STATIC_VAR(last_x_value); - - /* Allocate storage for breakpoint domain & range values */ - STATIC_VAR(x) = (double *) calloc((size_t) size, sizeof(double)); - x = (double *) STATIC_VAR(x); - if (!x) { - cm_message_send(allocation_error); - } - - STATIC_VAR(y) = (double *) calloc((size_t) size, sizeof(double)); - y = (double *) STATIC_VAR(y); - if (!y) { - cm_message_send(allocation_error); + last_x_value = (double *) (STATIC_VAR(last_x_value) = tmalloc_raw( + sizeof(double))); + x = (double *) (STATIC_VAR(x) = tcalloc_raw((size_t) size, + sizeof(double))); + y = (double *) (STATIC_VAR(y) = tcalloc_raw((size_t) size, + sizeof(double))); + if (last_x_value == (double *) NULL || + x == (double *) NULL || y == (double *) NULL) { + cm_message_send(allocation_error); + cm_pwl_callback(mif_private, MIF_CB_DESTROY); + return; } + CALLBACK = cm_pwl_callback; /* Retrieve x and y values. */ for (i=0; i - static char *CNVgettok(char **s) - { char *buf; /* temporary storage to copy token into */ /*char *temp;*/ /* temporary storage to copy token into */ - char *ret_str; /* storage for returned string */ int i; /* allocate space big enough for the whole string */ - buf = (char *) malloc(strlen(*s) + 1); + if ((buf = (char *) tmalloc_raw(strlen(*s) + 1)) == (char *) NULL) { + cm_message_send("Unable to allocate buffer in CNVgettok()"); + return (char *) NULL; + } /* skip over any white space */ @@ -180,18 +183,17 @@ static char *CNVgettok(char **s) switch(**s) { case '\0': /* End of string found */ - if(buf) free(buf); - return(NULL); - + txfree(buf); + return (char *) NULL; default: /* Otherwise, we are dealing with a */ /* string representation of a number */ /* or a mess o' characters. */ i = 0; while( (**s != '\0') && - (! ( isspace_c(**s) || (**s == '=') || - (**s == '(') || (**s == ')') || - (**s == ',') + (! ( isspace_c(**s) || (**s == '=') || + (**s == '(') || (**s == ')') || + (**s == ',') ) ) ) { buf[i] = **s; i++; @@ -210,13 +212,20 @@ static char *CNVgettok(char **s) /* make a copy using only the space needed by the string length */ - ret_str = (char *) malloc(strlen(buf) + 1); - ret_str = strcpy(ret_str,buf); + { + char * const ret_str = (char *) tmalloc_raw(strlen(buf) + 1); + if (ret_str == (char *) NULL) { + cm_message_send("Unable to allocate return buffer " + "in CNVgettok()"); + return (char *) NULL; + } + strcpy(ret_str, buf); + txfree(buf); - if(buf) free(buf); + return ret_str; + } +} /* end of function CNVgettok */ - return(ret_str); -} /*============================================================================== @@ -267,21 +276,16 @@ is returned. The original input string is undisturbed. */ static char *CNVget_token(char **s, Cnv_Token_Type_t *type) - { - - char *ret_str; /* storage for returned string */ - + /* storage for returned string */ /* get the token from the input line */ - - ret_str = CNVgettok(s); + char * const ret_str = CNVgettok(s); /* if no next token, return */ - - if(ret_str == NULL) { + if (ret_str == (char *) NULL) { *type = CNV_NO_TOK; - return(NULL); + return (char *) NULL; } /* else, determine and return token type */ @@ -295,8 +299,7 @@ static char *CNVget_token(char **s, Cnv_Token_Type_t *type) } return(ret_str); -} - +} /* end of function CNVget_token */ @@ -695,7 +698,6 @@ NON-STANDARD FEATURES static int cm_read_source(FILE *source, Local_Data_t *loc) { - int n; /* loop index */ int i, /* indexing variable */ j, /* indexing variable */ num_tokens; /* number of tokens in a given string */ @@ -735,7 +737,7 @@ static int cm_read_source(FILE *source, Local_Data_t *loc) while ( type != CNV_NO_TOK ) { token = CNVget_token(&s, &type); if (token) - free(token); + txfree(token); j++; } num_tokens = j; @@ -749,9 +751,13 @@ static int cm_read_source(FILE *source, Local_Data_t *loc) s = base_address; /* set storage space for bits in a row and set them to 0*/ - loc->all_data[i] = (char*)malloc(sizeof(char) * (size_t) loc->width); - for (n = 0; n < loc->width; n++) - loc->all_data[i][n] = 0; + if ((loc->all_data[i] = (char *) tcalloc_raw( + (size_t) loc->width, + sizeof(char))) == (char *) NULL) { + cm_message_send("Unable to allocate buffer " + "for all_data bits in cm_d_source()"); + return -1; + } /** Retrieve each token, analyze, and **/ /** store the timepoint and bit information **/ @@ -807,7 +813,7 @@ static int cm_read_source(FILE *source, Local_Data_t *loc) } } if (token) - free(token); + txfree(token); } i++; } @@ -910,7 +916,9 @@ void cm_d_source(ARGS) *s; /* main string variable */ - char *loading_error = "\nERROR **\n D_SOURCE: source.in file was not read successfully. \n"; + const char *loading_error = + "\nERROR **\n D_SOURCE: source.in file " + "was not read successfully."; Local_Data_t *loc; /* Pointer to local static data, not to be included in the state vector (save memory!) */ @@ -928,10 +936,16 @@ void cm_d_source(ARGS) char *lbuffer, *p; lbuffer = getenv("NGSPICE_INPUT_DIR"); if (lbuffer && *lbuffer) { - p = (char*) malloc(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(PARAM(input_file)) + 1); + p = (char *) tmalloc_raw(strlen(lbuffer) + + strlen(DIR_PATHSEP) + strlen(PARAM(input_file)) + 1); + if (p == (char *) NULL) { + cm_message_send("Unable to allocate buffer " + "for building file name in cm_d_source()"); + return; + } sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, PARAM(input_file)); source = fopen(p, "r"); - free(p); + txfree(p); } if (!source) cm_message_printf("cannot open file %s", PARAM(input_file)); @@ -952,8 +966,12 @@ void cm_d_source(ARGS) } /*** allocate static storage for *loc ***/ - STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t )); - loc = STATIC_VAR (locdata); + if ((loc = (Local_Data_t *) (STATIC_VAR(locdata) = tcalloc_raw(1, + sizeof(Local_Data_t)))) == (Local_Data_t *) NULL) { + cm_message_send("Unable to allocate buffer " + "for building file name in cm_d_source()"); + return; + } /*** allocate storage for *index, *bits & *timepoint ***/ @@ -976,8 +994,22 @@ void cm_d_source(ARGS) loc->width = PORT_SIZE(out); /*** allocate storage for **all_data, & *all_timepoints ***/ - loc->all_timepoints = (double*)calloc((size_t) i, sizeof(double)); - loc->all_data = (char**)calloc((size_t) i, sizeof(char*)); + if ((loc->all_timepoints = (double *) tcalloc_raw((size_t) i, + sizeof(double))) == (double *) NULL) { + cm_message_send("Unable to allocate all_timepoints " + "in cm_d_source()"); + free_local_data(loc); + STATIC_VAR(locdata) = NULL; + return; + } + if ((loc->all_data = (char **) tcalloc_raw((size_t) i, + sizeof(char *))) == (char **) NULL) { + cm_message_send("Unable to allocate all_data " + "in cm_d_source()"); + free_local_data(loc); + STATIC_VAR(locdata) = NULL; + return; + } /* Send file pointer and the two array storage pointers */ /* to "cm_read_source()". This will return after */ @@ -993,36 +1025,50 @@ void cm_d_source(ARGS) err=1; } + /* close source file */ + if (source) { + fclose(source); + } + if (err) { /* problem occurred in load...send error msg. */ cm_message_send(loading_error); switch (err) { + case -1: + cm_message_send(" Allocation failure " + "while allocating memory for bits" ); + break; case 2: - cm_message_send(" d_source word length and number of columns in file differ.\n" ); + cm_message_send(" d_source word length and number of columns in file differ." ); break; case 3: - cm_message_send(" Time values in first column have to increase monotonically.\n"); + cm_message_send(" Time values in first column have to increase monotonically."); break; case 4: - cm_message_send(" Unknown bit value.\n"); + cm_message_send(" Unknown bit value."); break; default: break; } - } - /* close source file */ - if (source) - fclose(source); + free_local_data(loc); + STATIC_VAR(locdata) = NULL; + return; + } + CALLBACK = cm_d_source_callback; } else { /*** Retrieve previous values ***/ + if ((loc = (Local_Data_t *) STATIC_VAR (locdata)) == + (Local_Data_t *) NULL) { + cm_message_send("Attempt to use unallocated Local_Data_t " + "in cm_d_source()"); + } /** Retrieve info... **/ row_index = (int *) cm_event_get_ptr(0,0); row_index_old = (int *) cm_event_get_ptr(0,1); - loc = STATIC_VAR (locdata); /* Set old values to new... */ *row_index = *row_index_old; @@ -1147,7 +1193,59 @@ void cm_d_source(ARGS) } } } -} +} /* end of function cm_d_source */ + + + +/* This function frees resources when called with reason argument + * MIF_CB_DESTROY */ +static void cm_d_source_callback(ARGS, Mif_Callback_Reason_t reason) +{ + switch (reason) { + case MIF_CB_DESTROY: { + Local_Data_t *loc = (Local_Data_t *) STATIC_VAR(locdata); + if (loc != (Local_Data_t *) NULL) { + free_local_data(loc); + } + break; + } + } +} /* end of function cm_d_state_callback */ + + + +static void free_local_data(Local_Data_t *loc) +{ + /* Immediate return if no structure */ + if (loc == (Local_Data_t *) NULL) { + return; + } + + /* Free all_data and internal allocations */ + { + char ** const all_data = loc->all_data; + if (all_data != (char **) NULL) { + const int n = loc->width; + int i; + for (i = 0; i != n; ++i) { /* free individual allocs */ + if (all_data[i] != (char *) NULL) { + txfree(all_data[i]); + } + } + txfree(all_data); + } + } + + /* Free all_timepoints */ + { + void * const p = loc->all_timepoints; + if (p != NULL) { + txfree(p); + } + } + + txfree(loc); +} /* end of function free_local_data */ diff --git a/src/xspice/icm/digital/d_state/cfunc.mod b/src/xspice/icm/digital/d_state/cfunc.mod index 18f4ed371..8683aa29e 100644 --- a/src/xspice/icm/digital/d_state/cfunc.mod +++ b/src/xspice/icm/digital/d_state/cfunc.mod @@ -150,9 +150,8 @@ typedef char line_t[82]; /* A SPICE size line. <= 80 characters plus '\n\0' */ /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - - - +static void cm_d_state_callback(ARGS, Mif_Callback_Reason_t reason); +static void free_state_fields(State_Table_t *p_state); /*============================================================================== @@ -201,18 +200,19 @@ is returned. The original input string is undisturbed. */ static char *CNVgettok(char **s) - { char *buf; /* temporary storage to copy token into */ /*char *temp;*/ /* temporary storage to copy token into */ - char *ret_str; /* storage for returned string */ int i; /* allocate space big enough for the whole string */ - buf = (char *) malloc(strlen(*s) + 1); + if ((buf = (char *) tmalloc_raw(strlen(*s) + 1)) == (char *) NULL) { + cm_message_send("Unable to allocate buffer in CNVgettok()"); + return (char *) NULL; + } /* skip over any white space */ @@ -225,9 +225,8 @@ static char *CNVgettok(char **s) switch(**s) { case '\0': /* End of string found */ - if(buf) free(buf); - return(NULL); - + txfree(buf); + return (char *) NULL; default: /* Otherwise, we are dealing with a */ /* string representation of a number */ @@ -255,13 +254,20 @@ static char *CNVgettok(char **s) /* make a copy using only the space needed by the string length */ - ret_str = (char *) malloc(strlen(buf) + 1); - ret_str = strcpy(ret_str,buf); + { + char * const ret_str = (char *) tmalloc_raw(strlen(buf) + 1); + if (ret_str == (char *) NULL) { + cm_message_send("Unable to allocate return buffer " + "in CNVgettok()"); + return (char *) NULL; + } + strcpy(ret_str, buf); + txfree(buf); - if(buf) free(buf); + return ret_str; + } +} /* end of function CNVgettok */ - return(ret_str); -} /*============================================================================== @@ -312,21 +318,16 @@ is returned. The original input string is undisturbed. */ static char *CNVget_token(char **s, Cnv_Token_Type_t *type) - { - - char *ret_str; /* storage for returned string */ - + /* storage for returned string */ /* get the token from the input line */ - - ret_str = CNVgettok(s); + char * const ret_str = CNVgettok(s); /* if no next token, return */ - - if(ret_str == NULL) { + if (ret_str == (char *) NULL) { *type = CNV_NO_TOK; - return(NULL); + return (char *) NULL; } /* else, determine and return token type */ @@ -340,8 +341,7 @@ static char *CNVget_token(char **s, Cnv_Token_Type_t *type) } return(ret_str); -} - +} /* end of function CNVget_token */ @@ -395,8 +395,6 @@ static int cnv_get_spice_value( char *str, /* IN - The value text e.g. 1.2K */ double *p_value ) /* OUT - The numerical value */ { - - /* the following were "int4" devices - jpm */ size_t len; size_t i; @@ -482,8 +480,7 @@ double *p_value ) /* OUT - The numerical value */ scale_factor = 1.0e-3; break; } - if(islower_c(c1)) - c1 = toupper_c(c1); + c1 = toupper_c(c1); if(c1 == 'E') scale_factor = 1.0e6; else if(c1 == 'I') @@ -1807,11 +1804,26 @@ void cm_d_state(ARGS) /* assign storage for arrays to pointers in states table */ - states->state = (int *) calloc((size_t) (states->depth + 1), sizeof(int)); - states->bits = (short *) calloc((size_t) (states->num_outputs * states->depth / 4 + 1), sizeof(short)); - states->inputs = (short *) calloc((size_t) (states->num_inputs * states->depth / 8 + 1), sizeof(short)); - states->next_state = (int *) calloc((size_t) (states->depth + 1), sizeof(int)); - + states->state = (int *) tcalloc_raw( + (size_t) (states->depth + 1), sizeof(int)); + states->bits = (short *) tcalloc_raw( + (size_t) (states->num_outputs * states->depth / 4 + 1), + sizeof(short)); + states->inputs = (short *) tcalloc_raw( + (size_t) (states->num_inputs * states->depth / 8 + 1), + sizeof(short)); + states->next_state = (int *) tcalloc_raw( + (size_t) (states->depth + 1), sizeof(int)); + if (states->state == (int *) NULL || + states->bits == (short *) NULL || + states->inputs == (short *) NULL || + states->next_state == (int *) NULL) { + cm_message_send("Unable to allocate state fields " + "in cm_d_state()"); + free_state_fields(states); + return; + } + CALLBACK = cm_d_state_callback; /* Initialize *state, *bits, *inputs & *next_state to zero */ for (i=0; idepth; i++) { @@ -1872,7 +1884,7 @@ void cm_d_state(ARGS) /* declare load values */ - // for (i=0; inum_outputs; i++) { + // for (i=0; inum_outputs; i++) for (i=0; inum_inputs; i++) { LOAD(in[i]) = PARAM(input_load); } @@ -1885,6 +1897,14 @@ void cm_d_state(ARGS) else { /**** Retrieve previous values ****/ states = (State_Table_t *) cm_event_get_ptr(0,0); + /* Need only check one allocation since will either be all + * allocated or not */ + if (states->state == (int *) NULL) { + cm_message_send("Attempt to use unallocated state arrays " + "in cm_d_state()"); + return; + } + states_old = (State_Table_t *) cm_event_get_ptr(0,1); // Copy storage *states = *states_old; @@ -2089,7 +2109,49 @@ void cm_d_state(ARGS) } } } -} +} /* end of function cm_d_state */ + + + +/* This function frees resources when called with reason argument + * MIF_CB_DESTROY */ +static void cm_d_state_callback(ARGS, Mif_Callback_Reason_t reason) +{ + CM_IGNORE(mif_private); + + switch (reason) { + case MIF_CB_DESTROY: { + State_Table_t *p_state = + (State_Table_t *) cm_event_get_ptr(0, 0); + free_state_fields(p_state); + break; + } + } +} /* end of function cm_d_state_callback */ + + + +/* Free fields in State_Table_t structure */ +static void free_state_fields(State_Table_t *p_state) +{ + void *p; + if ((p = p_state->state) != NULL) { + txfree(p); + p_state->state = (int *) NULL; + } + if ((p = p_state->bits) != NULL) { + txfree(p); + p_state->bits = (short *) NULL; + } + if ((p = p_state->inputs) != NULL) { + txfree(p); + p_state->inputs = (short *) NULL; + } + if ((p = p_state->next_state) != NULL) { + txfree(p); + p_state->next_state = (int *) NULL; + } +} /* end of function free_state_fields */ diff --git a/src/xspice/icm/digital/modpath.lst b/src/xspice/icm/digital/modpath.lst index 38d193a83..73021ec18 100644 --- a/src/xspice/icm/digital/modpath.lst +++ b/src/xspice/icm/digital/modpath.lst @@ -1,28 +1,29 @@ -adc_bridge -dac_bridge -d_and -d_buffer -d_dff -d_dlatch -d_fdiv -d_genlut -d_inverter -d_jkff -d_lut -d_nand -d_nor -d_open_c -d_open_e -d_or -d_osc -d_pulldown -d_pullup -d_ram -d_source -d_srff -d_srlatch -d_state -d_tff -d_tristate -d_xnor -d_xor +#Directory Version +adc_bridge 1 +dac_bridge 1 +d_and 1 +d_buffer 1 +d_dff 1 +d_dlatch 1 +d_fdiv 1 +d_genlut 2 +d_inverter 1 +d_jkff 1 +d_lut 2 +d_nand 1 +d_nor 1 +d_open_c 1 +d_open_e 1 +d_or 1 +d_osc 2 +d_pulldown 1 +d_pullup 1 +d_ram 1 +d_source 2 +d_srff 1 +d_srlatch 1 +d_state 2 +d_tff 1 +d_tristate 1 +d_xnor 1 +d_xor 1 diff --git a/src/xspice/icm/dlmain.c b/src/xspice/icm/dlmain.c index 93afe745e..0be4c9e72 100644 --- a/src/xspice/icm/dlmain.c +++ b/src/xspice/icm/dlmain.c @@ -17,6 +17,7 @@ #include "ngspice/evtudn.h" #include "ngspice/inpdefs.h" #include "cmextrn.h" +#include "dlmain.h" #include "udnextrn.h" @@ -26,19 +27,31 @@ // Do not modify anything below this line ////////////////////////////////////////////////////////////////////////////// -SPICEdev *cmDEVices[] = { +const SPICEdev * const cmDEVices[] = { #include "cminfo.h" - NULL + NULL }; -int cmDEVicesCNT = sizeof(cmDEVices)/sizeof(SPICEdev *)-1; +const SPICEdev * const cmDEVices2[] = { +#include "cminfo2.h" + NULL +}; -Evt_Udn_Info_t *cmEVTudns[] = { +const int cmDEVicesCNT = sizeof(cmDEVices) / sizeof(SPICEdev *) - 1; +const int cmDEVicesCNT2 = sizeof(cmDEVices2) / sizeof(SPICEdev *) - 1; + +const Evt_Udn_Info_t * const cmEVTudns[] = { #include "udninfo.h" - NULL + NULL }; -int cmEVTudnCNT = sizeof(cmEVTudns)/sizeof(Evt_Udn_Info_t *)-1; +const Evt_Udn_Info_t * const cmEVTudns2[] = { +#include "udninfo2.h" + NULL +}; + +const int cmEVTudnCNT = sizeof(cmEVTudns) / sizeof(Evt_Udn_Info_t *) - 1; +const int cmEVTudnCNT2 = sizeof(cmEVTudns2) / sizeof(Evt_Udn_Info_t *) - 1; // Pointer to core info structure containing pointers to core functions. struct coreInfo_t *coreitf; @@ -62,39 +75,60 @@ struct coreInfo_t *coreitf; #endif extern CM_EXPORT void *CMdevs(void); +extern CM_EXPORT void *CMdevs2(void); extern CM_EXPORT void *CMdevNum(void); +extern CM_EXPORT void *CMdevNum2(void); extern CM_EXPORT void *CMudns(void); +extern CM_EXPORT void *CMudns2(void); extern CM_EXPORT void *CMudnNum(void); +extern CM_EXPORT void *CMudnNum2(void); extern CM_EXPORT void *CMgetCoreItfPtr(void); -extern void *tmalloc(size_t num); -extern void *trealloc(const void *str, size_t num); -extern void txfree(const void *ptr); // This one returns the device table -CM_EXPORT void *CMdevs(void) { - return (void *)cmDEVices; +CM_EXPORT void *CMdevs(void) +{ + return (void *) cmDEVices; +} +CM_EXPORT void *CMdevs2(void) +{ + return (void *) cmDEVices2; } // This one returns the device count -CM_EXPORT void *CMdevNum(void) { - return (void *)&cmDEVicesCNT; +CM_EXPORT void *CMdevNum(void) +{ + return (void *) &cmDEVicesCNT; +} +CM_EXPORT void *CMdevNum2(void) +{ + return (void *) &cmDEVicesCNT2; } // This one returns the UDN table -CM_EXPORT void *CMudns(void) { - return (void *)cmEVTudns; +CM_EXPORT void *CMudns(void) +{ + return (void *) cmEVTudns; +} +CM_EXPORT void *CMudns2(void) +{ + return (void *) cmEVTudns2; } // This one returns the UDN count -CM_EXPORT void *CMudnNum(void) { - return (void *)&cmEVTudnCNT; +CM_EXPORT void *CMudnNum(void) +{ + return (void *) &cmEVTudnCNT; +} +CM_EXPORT void *CMudnNum2(void) +{ + return (void *) &cmEVTudnCNT2; } // This one returns the pointer to the pointer to the core interface structure CM_EXPORT void *CMgetCoreItfPtr(void) { - return (void *)(&coreitf); + return (void *)(&coreitf); } @@ -103,23 +137,27 @@ CM_EXPORT void *CMgetCoreItfPtr(void) { // These functions call the real core functions of SPICE OPUS using the // pointers in coreitf structure. ////////////////////////////////////////////////////////////////////////////// +/* Declared in mifproto.h */ void MIF_INP2A( CKTcircuit *ckt, /* circuit structure to put mod/inst structs in */ INPtables *tab, /* symbol table for node names, etc. */ struct card *current /* the card we are to parse */ - ) { + ) +{ (coreitf->dllitf_MIF_INP2A)(ckt,tab,current); } +/* Declared in mifproto.h */ char * MIFgetMod( CKTcircuit *ckt, - char *name, + const char *name, INPmodel **model, INPtables *tab ) { return (coreitf->dllitf_MIFgetMod)(ckt,name,model,tab); } +/* Declared in mifproto.h */ IFvalue * MIFgetValue( CKTcircuit *ckt, char **line, @@ -131,6 +169,7 @@ IFvalue * MIFgetValue( } +/* Declared in mifproto.h */ int MIFsetup( SMPmatrix *matrix, GENmodel *inModel, @@ -140,6 +179,7 @@ int MIFsetup( return (coreitf->dllitf_MIFsetup)(matrix,inModel,ckt,state); } +/* Declared in mifproto.h */ int MIFunsetup( GENmodel *inModel, CKTcircuit *ckt @@ -147,6 +187,7 @@ int MIFunsetup( return (coreitf->dllitf_MIFunsetup)(inModel,ckt); } +/* Declared in mifproto.h */ int MIFload( GENmodel *inModel, CKTcircuit *ckt @@ -155,6 +196,7 @@ int MIFload( } +/* Declared in mifproto.h */ int MIFmParam( int param_index, IFvalue *value, @@ -163,6 +205,7 @@ int MIFmParam( return (coreitf->dllitf_MIFmParam)(param_index,value,inModel); } +/* Declared in mifproto.h */ int MIFask( CKTcircuit *ckt, GENinstance *inst, @@ -173,6 +216,7 @@ int MIFask( return (coreitf->dllitf_MIFask)(ckt,inst,param_index,value,select); } +/* Declared in mifproto.h */ int MIFmAsk( CKTcircuit *ckt, GENmodel *inModel, @@ -182,6 +226,7 @@ int MIFmAsk( return (coreitf->dllitf_MIFmAsk)(ckt,inModel,param_index,value); } +/* Declared in mifproto.h */ int MIFtrunc( GENmodel *inModel, CKTcircuit *ckt, @@ -190,6 +235,7 @@ int MIFtrunc( return (coreitf->dllitf_MIFtrunc)(inModel,ckt,timeStep); } +/* Declared in mifproto.h */ int MIFconvTest( GENmodel *inModel, CKTcircuit *ckt @@ -197,24 +243,28 @@ int MIFconvTest( return (coreitf->dllitf_MIFconvTest)(inModel,ckt); } +/* Declared in mifproto.h */ int MIFdelete( GENinstance *inst ) { return (coreitf->dllitf_MIFdelete)(inst); } +/* Declared in mifproto.h */ int MIFmDelete( GENmodel *gen_model ) { return (coreitf->dllitf_MIFmDelete)(gen_model); } +/* Declared in mifproto.h */ void MIFdestroy( void ) { (coreitf->dllitf_MIFdestroy)(); } +/* Declared in mifproto.h */ char *MIFgettok( char **s ) { @@ -222,6 +272,7 @@ char *MIFgettok( } +/* Declared in mifproto.h */ char *MIFget_token( char **s, Mif_Token_Type_t *type @@ -230,6 +281,7 @@ char *MIFget_token( } +/* Declared in mifproto.h */ Mif_Cntl_Src_Type_t MIFget_cntl_src_type( Mif_Port_Type_t in_port_type, Mif_Port_Type_t out_port_type @@ -237,11 +289,16 @@ Mif_Cntl_Src_Type_t MIFget_cntl_src_type( return (coreitf->dllitf_MIFget_cntl_src_type)(in_port_type,out_port_type); } -char *MIFcopy(char *c) { +/* Declared in mifproto.h */ +char *MIFcopy(const char *c) { return (coreitf->dllitf_MIFcopy)(c); } +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +/* Declared in cmproto.h */ void cm_climit_fcn(double in, double in_offset, double cntl_upper, double cntl_lower, double lower_delta, double upper_delta, double limit_range, @@ -256,6 +313,7 @@ void cm_climit_fcn(double in, double in_offset, double cntl_upper, +/* Declared in cmproto.h */ void cm_smooth_corner(double x_input, double x_center, double y_center, double domain, double lower_slope, double upper_slope, double *y_output, double *dy_dx) { @@ -263,6 +321,7 @@ void cm_smooth_corner(double x_input, double x_center, double y_center, upper_slope,y_output,dy_dx); } +/* Declared in cmproto.h */ void cm_smooth_discontinuity(double x_input, double x_lower, double y_lower, double x_upper, double y_upper, double *y_output, double *dy_dx) { @@ -270,143 +329,260 @@ void cm_smooth_discontinuity(double x_input, double x_lower, double y_lower, y_output,dy_dx); } +/* Declared in cmproto.h */ double cm_smooth_pwl(double x_input, double *x, double *y, int size, double input_domain, double *dout_din) { return (coreitf->dllitf_cm_smooth_pwl)(x_input,x,y,size,input_domain,dout_din); } +/* Declared in cmproto.h */ double cm_analog_ramp_factor(void) { return (coreitf->dllitf_cm_analog_ramp_factor)(); } +/* Declared in cmproto.h */ void cm_analog_alloc(int tag, int bytes) { (coreitf->dllitf_cm_analog_alloc)(tag,bytes); } +/* Declared in cmproto.h */ void *cm_analog_get_ptr(int tag, int timepoint) { return (coreitf->dllitf_cm_analog_get_ptr)(tag,timepoint); } +/* Declared in cmproto.h */ int cm_analog_integrate(double integrand, double *integral, double *partial) { return (coreitf->dllitf_cm_analog_integrate)(integrand,integral,partial); } +/* Declared in cmproto.h */ int cm_analog_converge(double *state) { return (coreitf->dllitf_cm_analog_converge)(state); } +/* Declared in cmproto.h */ int cm_analog_set_temp_bkpt(double time) { return (coreitf->dllitf_cm_analog_set_temp_bkpt)(time); } +/* Declared in cmproto.h */ int cm_analog_set_perm_bkpt(double time) { return (coreitf->dllitf_cm_analog_set_perm_bkpt)(time); } +/* Declared in cmproto.h */ void cm_analog_not_converged(void) { (coreitf->dllitf_cm_analog_not_converged)(); } +/* Declared in cmproto.h */ void cm_analog_auto_partial(void) { (coreitf->dllitf_cm_analog_auto_partial)(); } +/* Declared in cmproto.h */ void cm_event_alloc(int tag, int bytes){ (coreitf->dllitf_cm_event_alloc)(tag,bytes); } +/* Declared in cmproto.h */ void *cm_event_get_ptr(int tag, int timepoint) { return (coreitf->dllitf_cm_event_get_ptr)(tag,timepoint); } +/* Declared in cmproto.h */ int cm_event_queue(double time) { return (coreitf->dllitf_cm_event_queue)(time); } +/* Declared in cmproto.h */ char *cm_message_get_errmsg(void) { return (coreitf->dllitf_cm_message_get_errmsg)(); } -int cm_message_send(char *msg) { +/* Declared in cmproto.h */ +int cm_message_send(const char *msg) { return (coreitf->dllitf_cm_message_send)(msg); } +/* Declared in cmproto.h */ double cm_netlist_get_c(void) { return (coreitf->dllitf_cm_netlist_get_c)(); } +/* Declared in cmproto.h */ double cm_netlist_get_l(void) { return (coreitf->dllitf_cm_netlist_get_l)(); } +/* Declared in cmproto.h */ Complex_t cm_complex_set(double real, double imag) { return (coreitf->dllitf_cm_complex_set)(real,imag); } +/* Declared in cmproto.h */ Complex_t cm_complex_add(Complex_t x, Complex_t y) { return (coreitf->dllitf_cm_complex_add)(x,y); } +/* Declared in cmproto.h */ Complex_t cm_complex_subtract(Complex_t x, Complex_t y) { return (coreitf->dllitf_cm_complex_subtract)(x,y); } +/* Declared in cmproto.h */ Complex_t cm_complex_multiply(Complex_t x, Complex_t y) { return (coreitf->dllitf_cm_complex_multiply)(x,y); } +/* Declared in cmproto.h */ Complex_t cm_complex_divide(Complex_t x, Complex_t y) { return (coreitf->dllitf_cm_complex_divide)(x,y); } +/* Declared in cmproto.h */ char * cm_get_path(void) { return (coreitf->dllitf_cm_get_path)(); } +/* Declared in cmproto.h */ CKTcircuit *cm_get_circuit(void) { return (coreitf->dllitf_cm_get_circuit)(); } +/* Declared in cmproto.h */ FILE * cm_stream_out(void) { return (coreitf->dllitf_cm_stream_out)(); } +/* Declared in cmproto.h */ FILE * cm_stream_in(void) { return (coreitf->dllitf_cm_stream_in)(); } +/* Declared in cmproto.h */ FILE * cm_stream_err(void) { return (coreitf->dllitf_cm_stream_err)(); } +/* Declared in cmproto.h */ void * malloc_pj(size_t s) { return (coreitf->dllitf_malloc_pj)(s); } +/* Declared in cmproto.h */ void * calloc_pj(size_t s1, size_t s2) { return (coreitf->dllitf_calloc_pj)(s1,s2); } -void * realloc_pj(const void *ptr, size_t s) { +/* Declared in cmproto.h */ +void * realloc_pj(void *ptr, size_t s) { return (coreitf->dllitf_realloc_pj)(ptr,s); } -void free_pj(const void *ptr) { +/* Declared in cmproto.h */ +void free_pj(void *ptr) { (coreitf->dllitf_free_pj)(ptr); } +/* Declared in cmproto.h */ void * tmalloc(size_t s) { return (coreitf->dllitf_tmalloc)(s); } -void * trealloc(const void *ptr, size_t s) { +/* Declared in cmproto.h */ +void * trealloc(void *ptr, size_t s) { return (coreitf->dllitf_trealloc)(ptr,s); } -void txfree(const void *ptr) { +/* Declared in cmproto.h */ +void txfree(void *ptr) { (coreitf->dllitf_txfree)(ptr); } +/* Declared in cmproto.h */ +int +cm_message_printf(const char *fmt, ...) +{ + char buf[1024]; + char *p = buf; + int size = sizeof(buf); + int rv; + + for (;;) { + + int nchars; + va_list ap; + + va_start(ap, fmt); + nchars = vsnprintf(p, (size_t) size, fmt, ap); + va_end(ap); + + if (nchars == -1) { // compatibility to old implementations + size *= 2; + } else if (size < nchars + 1) { + size = nchars + 1; + } else { + break; + } + + if (p == buf) + p = tmalloc((size_t) size * sizeof(char)); + else + p = trealloc(p, (size_t) size * sizeof(char)); + } + + rv = cm_message_send(p); + if (p != buf) + txfree(p); + return rv; +} + + + + + +/**** V E R S I O N 2 A D D I T I O N S ***/ +/* Declared in cmproto.h */ +const char *ngspice_version(void) +{ + return (*coreitf->dllitf_ngspice_version)(); +} + +/* Wrapper functions around interface function pointers that are used to get + * access to "raw" malloc(), calloc(), and realloc() under mutex protection + * when necessary */ +/* Declared in cmproto.h */ +void *tmalloc_raw(size_t s) +{ + return (*coreitf->dllitf_tmalloc_raw)(s); +} + +/* Declared in cmproto.h */ +void *tcalloc_raw(size_t n, size_t s) +{ + return (*coreitf->dllitf_tcalloc_raw)(n, s); +} + +/* Declared in cmproto.h */ +void *trealloc_raw(void *ptr, size_t s) +{ + return (*coreitf->dllitf_trealloc_raw)(ptr, s); +} + +/* Declared in cmproto.h */ +char *tstrdup(const char *sz_in) +{ + return (*coreitf->dllitf_tstrdup)(sz_in); +} /* end of function tstrdup */ + +/* Declared in cmproto.h */ +char *tstrdup_raw(const char *sz_in) +{ + return (*coreitf->dllitf_tstrdup_raw)(sz_in); +} /* end of function tstrdup_raw */ + + /* fopen_with_path() @@ -416,13 +592,16 @@ Then searches for (and opens) an a sequence from Infile_Path/ NGSPICE_INPUT_DIR/, where the path is given by the environmental variable , where the path is the current directory + +Requires version 2 due to DSTRING, which uses raw allocations. */ #define DFLT_BUF_SIZE 256 +/* Declared in cmproto.h */ FILE *fopen_with_path(const char *path, const char *mode) { FILE *fp; - if((path[0] != '/') && (path[1] != ':')) { /* path absolue (probably) */ + if ((path[0] != '/') && (path[1] != ':')) { /* path absolue (probably) */ // const char *x = getenv("ngspice_vpath"); const char *x = cm_get_path(); if (x) { @@ -439,7 +618,7 @@ FILE *fopen_with_path(const char *path, const char *mode) /* Try opening file. If fail, try using NGSPICE_INPUT_DIR * env variable location */ if ((fp = fopen(ds_get_buf(&ds), mode)) == (FILE *) NULL) { - char *y = getenv("NGSPICE_INPUT_DIR"); + const char * const y = getenv("NGSPICE_INPUT_DIR"); if (y && *y) { /* have env var and not "" */ int rc_ds = 0; /* Build /path and try opening. If the env var @@ -489,39 +668,3 @@ FILE *fopen_with_path(const char *path, const char *mode) -int -cm_message_printf(const char *fmt, ...) -{ - char buf[1024]; - char *p = buf; - int size = sizeof(buf); - int rv; - - for (;;) { - - int nchars; - va_list ap; - - va_start(ap, fmt); - nchars = vsnprintf(p, (size_t) size, fmt, ap); - va_end(ap); - - if (nchars == -1) { // compatibility to old implementations - size *= 2; - } else if (size < nchars + 1) { - size = nchars + 1; - } else { - break; - } - - if (p == buf) - p = tmalloc((size_t) size * sizeof(char)); - else - p = trealloc(p, (size_t) size * sizeof(char)); - } - - rv = cm_message_send(p); - if (p != buf) - txfree(p); - return rv; -} diff --git a/src/xspice/icm/dlmain.h b/src/xspice/icm/dlmain.h new file mode 100644 index 000000000..c442f1a14 --- /dev/null +++ b/src/xspice/icm/dlmain.h @@ -0,0 +1,10 @@ +#ifndef dlmain_h_included +#define dlmain_h_included + +#include "ngspice/cmproto.h" +#include "ngspice/mifproto.h" +#include "ngspice/dllitf.h" + +struct coreInfo_t *coreitf; + +#endif /* dlmain.h */ diff --git a/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod b/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod index 4e4687337..437235d26 100644 --- a/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod +++ b/src/xspice/icm/spice2poly/icm_spice2poly/cfunc.mod @@ -75,7 +75,7 @@ cm_spice2poly_callback(ARGS, Mif_Callback_Reason_t reason) case MIF_CB_DESTROY: { Mif_Inst_Var_Data_t *p = STATIC_VAR_INST(acgains); if(p->element) { - free(p->element); + txfree(p->element); p->element = NULL; } break; @@ -89,15 +89,15 @@ void spice2poly (ARGS) { int num_inputs; /* Number of inputs to model */ int num_coefs; /* Number of coefficients */ - int *exp; /* List of exponents in products */ + int *exp = (int *) NULL; /* List of exponents in products */ /* One for each input */ int i; /* Counter */ int j; /* Counter */ int k; /* Counter */ - double *in; /* Values of inputs to model */ - double *coef; /* Values of coefficients */ + double *in = (double *) NULL; /* Values of inputs to model */ + double *coef = (double *) NULL; /* Values of coefficients */ double sum; /* Temporary for accumulating sum of terms */ double product; /* Temporary for accumulating product */ @@ -112,10 +112,16 @@ void spice2poly (ARGS) /* array */ if(INIT) { - CALLBACK = cm_spice2poly_callback; Mif_Inst_Var_Data_t *p = STATIC_VAR_INST(acgains); p -> size = num_inputs; - p -> element = (Mif_Value_t *) malloc((size_t) num_inputs * sizeof(Mif_Value_t)); + if ((p->element = (Mif_Value_t *) tmalloc_raw((size_t) num_inputs * + sizeof(Mif_Value_t))) == (Mif_Value_t *) NULL) { + cm_message_send("Unable to allocate element array " + "in spice2poly()"); + return; + } + CALLBACK = cm_spice2poly_callback; + for(i = 0; i < num_inputs; i++) STATIC_VAR(acgains[i]) = 0.0; } @@ -133,19 +139,34 @@ void spice2poly (ARGS) /* Get input values and coefficients to local storage for faster access */ - in = (double *) malloc((size_t) num_inputs * sizeof(double)); + if ((in = (double *) tmalloc_raw((size_t) num_inputs * + sizeof(double))) == (double *) NULL) { + cm_message_send("Unable to allocate array for inputs " + "in spice2poly()"); + goto EXITPOINT; + } for(i = 0; i < num_inputs; i++) in[i] = INPUT(in[i]); num_coefs = PARAM_SIZE(coef); - coef = (double *) malloc((size_t) num_coefs * sizeof(double)); + if ((coef = (double *) tmalloc_raw((size_t) num_coefs * + sizeof(double))) == (double *) NULL) { + cm_message_send("Unable to allocate array for coef " + "in spice2poly()"); + goto EXITPOINT; + } for(i = 0; i < num_coefs; i++) coef[i] = PARAM(coef[i]); /* Allocate the array of exponents used in computing the poly terms */ - exp = (int *) malloc((size_t) num_inputs * sizeof(int)); + if ((exp = (int *) tmalloc_raw((size_t) num_inputs * + sizeof(int))) == (int *) NULL) { + cm_message_send("Unable to allocate array for exp " + "in spice2poly()"); + goto EXITPOINT; + } /* Initialize the exponents to zeros */ for(i = 0; i < num_inputs; i++) @@ -211,12 +232,20 @@ void spice2poly (ARGS) } /* Free the allocated items and return */ - free(in); - free(coef); - free(exp); +EXITPOINT: + if (in != (double *) NULL) { + txfree(in); + } + if (coef != (double *) NULL) { + txfree(coef); + } + if (exp != (int *) NULL) { + txfree(exp); + } return; -} +} /* end of function spice2poly */ + /* Function evterm computes the value of x**n */ @@ -309,5 +338,55 @@ stmt80: PWRSEQ(1) = PWRSEQ(1) + 1; stmt100: return; + +#if 0 +/* First cut at a "normal" translation. Would suggest doing the + * translation independently and checking for differences */ + if (pdim == 1) { + ++pwrseq[0]; + return; + } + + for (k = pdim; k != 0; --k) { + if (pwrseq[k - 1] != 0) { + break; + } + } + if (k == 0) { + ++pwrseq[0]; + return; + } + + if (k != pdim) { + --pwrseq[k - 1]; + ++pwrseq[k]; + return; + } + + km1 = k - 1; + for (i = 1; i <= km1; i++) { + if (pwrseq[i - 1] != 0) { + psum = 1; + k = pdim; + for ( ; ; ) { + if (pwrseq[k - 2] >= 1) { + break; + } + psum += pwrseq[k - 1]; + pwrseq[k - 1] = 0; + --k; + } + + pwrseq[k - 1] += psum; + --pwrseq[k - 2]; + return; + } + } + pwrseq[1 - 1] = pwrseq[pdim - 1] + 1; + pwrseq[pdim - 1] = 0; + return; +#endif + + } diff --git a/src/xspice/icm/spice2poly/modpath.lst b/src/xspice/icm/spice2poly/modpath.lst index eba74545a..a3aaed46d 100644 --- a/src/xspice/icm/spice2poly/modpath.lst +++ b/src/xspice/icm/spice2poly/modpath.lst @@ -1 +1,2 @@ -icm_spice2poly +#Directory Version +icm_spice2poly 1 diff --git a/src/xspice/icm/table/mada/alloc.c b/src/xspice/icm/table/mada/alloc.c index b45d611aa..ae93af5d0 100644 --- a/src/xspice/icm/table/mada/alloc.c +++ b/src/xspice/icm/table/mada/alloc.c @@ -41,7 +41,7 @@ sf_alloc(int n /* number of elements */, /* Use calloc so that any internal allocations will be set to NULL to * facilitate error recovery */ - if ((ptr = calloc(n, size)) == NULL) { + if ((ptr = tcalloc_raw(n, size)) == NULL) { cm_message_printf("%s: cannot allocate %zd bytes : ", __FILE__, n * size); return NULL; diff --git a/src/xspice/icm/table/mada/eno.c b/src/xspice/icm/table/mada/eno.c index 36acbe338..6d07dedda 100644 --- a/src/xspice/icm/table/mada/eno.c +++ b/src/xspice/icm/table/mada/eno.c @@ -97,10 +97,10 @@ sf_eno_close (sf_eno ent) int i; const int n = ent->order; for (i = 0; i < n; i++) { - free (ent->diff[i]); + txfree (ent->diff[i]); } - free (ent->diff); - free (ent); + txfree (ent->diff); + txfree (ent); } void diff --git a/src/xspice/icm/table/mada/eno2.c b/src/xspice/icm/table/mada/eno2.c index e8a0cc867..a7241559d 100644 --- a/src/xspice/icm/table/mada/eno2.c +++ b/src/xspice/icm/table/mada/eno2.c @@ -129,10 +129,10 @@ sf_eno2_close (sf_eno2 pnt) sf_eno_close (pnt->jnt); for (i2 = 0; i2 < pnt->n2; i2++) sf_eno_close (pnt->ent[i2]); - free (pnt->f); - free (pnt->f1); - free (pnt->ent); - free (pnt); + txfree (pnt->f); + txfree (pnt->f1); + txfree (pnt->ent); + txfree (pnt); } void diff --git a/src/xspice/icm/table/mada/eno3.c b/src/xspice/icm/table/mada/eno3.c index a5cb76f64..1b541d252 100644 --- a/src/xspice/icm/table/mada/eno3.c +++ b/src/xspice/icm/table/mada/eno3.c @@ -115,7 +115,7 @@ EXITPOINT: if (xrc != 0) { if (pnt != (sf_eno3) NULL) { sf_eno3_close(pnt); - free(pnt); + txfree(pnt); pnt = (sf_eno3) NULL; } } @@ -146,14 +146,14 @@ sf_eno3_close(sf_eno3 pnt) for (i3 = 0; i3 < pnt->n3; i3++) { for (i2 = 0; i2 < pnt->n2; i2++) sf_eno_close (pnt->ent[i3][i2]); - free (pnt->ent[i3]); + txfree(pnt->ent[i3]); } - free (pnt->ent); - free (pnt->f[0]); - free (pnt->f); - free (pnt->f1[0]); - free (pnt->f1); - free (pnt); + txfree(pnt->ent); + txfree(pnt->f[0]); + txfree(pnt->f); + txfree(pnt->f1[0]); + txfree(pnt->f1); + txfree(pnt); } void diff --git a/src/xspice/icm/table/modpath.lst b/src/xspice/icm/table/modpath.lst index 53c945633..e7fa27782 100644 --- a/src/xspice/icm/table/modpath.lst +++ b/src/xspice/icm/table/modpath.lst @@ -1,2 +1,3 @@ -table2D -table3D +#Directory version +table2D 2 +table3D 2 diff --git a/src/xspice/icm/table/support/gettokens.c b/src/xspice/icm/table/support/gettokens.c index 4c936c017..519d5d227 100644 --- a/src/xspice/icm/table/support/gettokens.c +++ b/src/xspice/icm/table/support/gettokens.c @@ -20,13 +20,15 @@ char *CNVgettok(char **s) { char *buf; /* temporary storage to copy token into */ /*char *temp;*/ /* temporary storage to copy token into */ - char *ret_str; /* storage for returned string */ int i; /* allocate space big enough for the whole string */ - buf = (char *) malloc(strlen(*s) + 1); + if ((buf = (char *) tmalloc_raw(strlen(*s) + 1)) == (char *) NULL) { + cm_message_printf("cannot allocate buffer to tokenize"); + return (char *) NULL; + } /* skip over any white space */ @@ -39,8 +41,9 @@ char *CNVgettok(char **s) switch (**s) { case '\0': /* End of string found */ - if (buf) - free(buf); + if (buf) { + txfree(buf); + } return NULL; @@ -70,12 +73,15 @@ char *CNVgettok(char **s) /* make a copy using only the space needed by the string length */ - ret_str = (char *) malloc(strlen(buf) + 1); - ret_str = strcpy(ret_str,buf); - - if (buf) free(buf); - - return ret_str; + { + char * const ret_str = (char *) tmalloc_raw(strlen(buf) + 1); + if (ret_str == (char *) NULL) { + return (char *) NULL; + } + (void) strcpy(ret_str, buf); + txfree(buf); + return ret_str; + } } /* end of function CNVgettok */ diff --git a/src/xspice/icm/table/support/gettokens.h b/src/xspice/icm/table/support/gettokens.h new file mode 100644 index 000000000..fef240af4 --- /dev/null +++ b/src/xspice/icm/table/support/gettokens.h @@ -0,0 +1,10 @@ +#ifndef gettokens_h_included +#define gettokens_h_included + +/* Type definition for each possible token returned. */ +typedef enum token_type_s { CNV_NO_TOK, CNV_STRING_TOK } Cnv_Token_Type_t; + +char * CNVget_token(char **s, Cnv_Token_Type_t *type); +char *CNVgettok(char **s); +int cnv_get_spice_value(char *str, double *p_value); +#endif /* gettokens_h_included */ diff --git a/src/xspice/icm/table/support/table_util.h b/src/xspice/icm/table/support/table_util.h new file mode 100644 index 000000000..88bf059e3 --- /dev/null +++ b/src/xspice/icm/table/support/table_util.h @@ -0,0 +1,38 @@ +#include "eno2.h" +#include "eno3.h" + +typedef struct { + int ix; /* size of array in x */ + int iy; /* size of array in y */ + int iz; /* size of array in z */ + + sf_eno3 newtable; /* the table, code borrowed from madagascar project */ + + /* Input values corresponding to each index. They define the value + * in the domain at each index value */ + double *xcol; /* array of doubles in x */ + double *ycol; /* array of doubles in y */ + double *zcol; /* array of doubles in z */ + + double ***table; /* f(xi, yj, zk) */ +} Table3_Data_t; + +void free_local_data(Table3_Data_t *loc); + + +Table3_Data_t *init_local_data(const char *filename, int order); + +/* Finds difference between column values */ +static inline double get_local_diff(int n, double *col, int ind) +{ + if (ind >= n - 1) { + return col[n - 1] - col[n - 2]; + } + if (ind <= 0) { + return col[1] - col[0]; + } + return 0.5 * (col[ind + 1] - col[ind - 1]); +} /* end of function get_local_diff */ + + + diff --git a/src/xspice/icm/table/table2D/cfunc.mod b/src/xspice/icm/table/table2D/cfunc.mod index 77760dae6..e2dc56868 100644 --- a/src/xspice/icm/table/table2D/cfunc.mod +++ b/src/xspice/icm/table/table2D/cfunc.mod @@ -72,6 +72,7 @@ NON-STANDARD FEATURES #include #include +#include "support/gettokens.h" #include "mada/eno2.h" typedef struct { @@ -88,7 +89,6 @@ typedef struct { double **table; /* f(xi, yj) */ } Table2_Data_t; -typedef Table2_Data_t Local_Data_t; /*=== MACROS ===========================*/ @@ -98,19 +98,8 @@ typedef Table2_Data_t Local_Data_t; #define DIR_PATHSEP "/" #endif -#if defined(_MSC_VER) -#define strdup _strdup -#endif - /*=== LOCAL VARIABLES & TYPEDEFS =======*/ -struct filesource_state { - FILE *fp; - long pos; - unsigned char atend; -}; - - @@ -118,74 +107,12 @@ struct filesource_state { double BilinearInterpolation(double x, double y, int xind, int yind, double **td); -extern char *CNVgettok(char **s); -int cnv_get_spice_value(char *str, double *p_value); +static void cm_table2D_callback(ARGS, Mif_Callback_Reason_t reason); extern int findCrossOver(double arr[], int n, double x); - static void free_local_data(Table2_Data_t *loc); static inline double get_local_diff(int n, double *col, int ind); static Table2_Data_t *init_local_data(const char *filename, int order); - - -/*============================================================================== - -FUNCTION cnv_get_spice_value() - -AUTHORS - - ??? Bill Kuhn - -MODIFICATIONS - - 30 Sep 1991 Jeffrey P. Murray - -SUMMARY - - This function takes as input a string token from a SPICE - deck and returns a floating point equivalent value. - -INTERFACES - - FILE ROUTINE CALLED - - N/A N/A - -RETURNED VALUE - - Returns the floating point value in pointer *p_value. Also - returns an integer representing successful completion. - -GLOBAL VARIABLES - - NONE - -NON-STANDARD FEATURES - - NONE - -==============================================================================*/ - - - - -static void cm_table2D_callback(ARGS, - Mif_Callback_Reason_t reason) -{ - switch (reason) { - case MIF_CB_DESTROY: { - Table2_Data_t *loc = STATIC_VAR(locdata); - if (loc) { - free_local_data(loc); - STATIC_VAR(locdata) = loc = NULL; - } - break; - } /* end of case MIF_CB_DESTROY */ - } /* end of switch over reason being called */ -} /* end of function cm_table2D_callback */ - - - /*============================================================================== FUNCTION void cm_table2D() @@ -262,7 +189,8 @@ void cm_table2D(ARGS) /* structure holding parms, inputs, outputs, etc. */ } /* return immediately if there was an initialization error */ - if ((loc = STATIC_VAR(locdata)) == (Table2_Data_t *) NULL) { + if ((loc = (Table2_Data_t *) STATIC_VAR(locdata)) == + (Table2_Data_t *) NULL) { return; } @@ -345,11 +273,10 @@ void cm_table2D(ARGS) /* structure holding parms, inputs, outputs, etc. */ } else { Mif_Complex_t ac_gain; - ac_gain.real = PARAM(gain) * derivval[0] / xdiff; ac_gain.imag= 0.0; + ac_gain.real = PARAM(gain) * derivval[0] / xdiff; AC_GAIN(out, inx) = ac_gain; ac_gain.real = PARAM(gain) * derivval[1] / ydiff; - ac_gain.imag= 0.0; AC_GAIN(out, iny) = ac_gain; } } /* end of function cm_table2D */ @@ -357,12 +284,11 @@ void cm_table2D(ARGS) /* structure holding parms, inputs, outputs, etc. */ /* This function initializes local data */ -static Table2_Data_t *init_local_data(const char *filename, int order) +static Table2_Data_t *init_local_data(const char *filename, int interporder) { int xrc = 0; int ix = 0, /* elements in a row */ iy = 0; /* number of rows */ - double **table_data; double tmp; FILE *fp = (FILE *) NULL; /* Handle to file */ @@ -373,12 +299,11 @@ static Table2_Data_t *init_local_data(const char *filename, int order) size_t lFileRead; /* Length of file read in */ int lLineCount; /* Current line number */ size_t lTotalChar; /* Total characters read */ - int interporder; /* order of interpolation for eno */ Table2_Data_t *loc = (Table2_Data_t *) NULL; /* local data */ /* Allocate static storage for *loc */ - if ((loc = (Table2_Data_t *) calloc(1, + if ((loc = (Table2_Data_t *) tcalloc_raw(1, sizeof(Table2_Data_t))) == (Table2_Data_t *) NULL) { cm_message_printf("cannot allocate memory for lookup table."); xrc = -1; @@ -394,7 +319,7 @@ static Table2_Data_t *init_local_data(const char *filename, int order) if (!fp) { /* Standard open attempt failed */ const char * const lbuffer = getenv("NGSPICE_INPUT_DIR"); if (lbuffer && *lbuffer) { - char * const p = (char *) malloc(strlen(lbuffer) + + char * const p = (char *) tmalloc_raw(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(filename) + 1); if (p == (char *) NULL) { @@ -406,7 +331,7 @@ static Table2_Data_t *init_local_data(const char *filename, int order) (void) sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, filename); fp = fopen(p, "r"); - free(p); + txfree(p); } } @@ -431,9 +356,9 @@ static Table2_Data_t *init_local_data(const char *filename, int order) } /* create string to hold the whole file */ - cFile = calloc(lFileLen + 1, sizeof(char)); + cFile = tcalloc_raw(lFileLen + 1, sizeof(char)); /* create another string long enough for file manipulation */ - cThisLine = calloc(lFileLen + 1, sizeof(char)); + cThisLine = tcalloc_raw(lFileLen + 1, sizeof(char)); if (cFile == NULL || cThisLine == NULL) { cm_message_printf("Insufficient memory to read file %s", filename); @@ -494,7 +419,7 @@ static Table2_Data_t *init_local_data(const char *filename, int order) cnv_get_spice_value(cThisLinePtr, &tmp); loc->ix = ix = (int) tmp; /* generate row data structure (x) */ - if ((loc->xcol = (double *) calloc((size_t) ix, + if ((loc->xcol = (double *) tcalloc_raw((size_t) ix, sizeof(double))) == (double *) NULL) { cm_message_printf("Unable to allocate row structure."); xrc = -1; @@ -505,7 +430,7 @@ static Table2_Data_t *init_local_data(const char *filename, int order) cnv_get_spice_value(cThisLinePtr, &tmp); loc->iy = iy = (int) tmp; /* generate column data structure (y) */ - if ((loc->ycol = (double *) calloc((size_t) iy, + if ((loc->ycol = (double *) tcalloc_raw((size_t) iy, sizeof(double))) == (double *) NULL) { cm_message_printf("Unable to allocate colum structure."); xrc = -1; @@ -522,7 +447,7 @@ static Table2_Data_t *init_local_data(const char *filename, int order) goto EXITPOINT; } cnv_get_spice_value(token, &loc->xcol[i++]); - free(token); + txfree(token); token = CNVgettok(&cThisLinePtr); } if (i < ix) { @@ -541,7 +466,7 @@ static Table2_Data_t *init_local_data(const char *filename, int order) goto EXITPOINT; } cnv_get_spice_value(token, &loc->ycol[i++]); - free(token); + txfree(token); token = CNVgettok(&cThisLinePtr); } if (i < iy) { @@ -556,7 +481,6 @@ static Table2_Data_t *init_local_data(const char *filename, int order) } /* generate table core */ - interporder = order; /* boundary limits set to param 'order' aren't recognized, so limit them here */ if (interporder < 2) { @@ -569,40 +493,33 @@ static Table2_Data_t *init_local_data(const char *filename, int order) int n1, int n2 : data dimensions */ if ((loc->newtable = sf_eno2_init( interporder, ix, iy)) == (sf_eno2) NULL) { - cm_message_printf("eno2 initialization failure."); + cm_message_send("eno2 initialization failure."); xrc = -1; goto EXITPOINT; - } /* create table_data in memory */ /* data [n2][n1] */ - if ((loc->table = table_data = (double **) calloc((size_t) iy, + if ((loc->table = table_data = (double **) tcalloc_raw((size_t) iy, sizeof(double *))) == (double **) NULL) { - cm_message_printf("Unable to allocate data table."); - free(cFile); - free(cThisLine); - free_local_data(loc); - return (Local_Data_t *) NULL; + cm_message_send("Unable to allocate data table."); + xrc = -1; + goto EXITPOINT; } { int i; for (i = 0; i < iy; i++) { - if ((table_data[i] = (double *) calloc((size_t) ix, + if ((table_data[i] = (double *) tcalloc_raw((size_t) ix, sizeof(double))) == (double *) NULL) { cm_message_printf("Unable to allocate data table " "row %d", i + 1); - free(cFile); - free(cThisLine); - free_local_data(loc); - return (Local_Data_t *) NULL; + xrc = -1; + goto EXITPOINT; } } } - loc->table = table_data; /* give to local data structure */ - /* continue reading f(x,y) values from cFile */ lLineCount = 0; @@ -634,10 +551,8 @@ static Table2_Data_t *init_local_data(const char *filename, int order) if (lTotalChar >= lFileLen) { cm_message_printf("Not enough data in file %s", filename); - free(cFile); - free(cThisLine); - free_local_data(loc); - return (Local_Data_t *) NULL; + xrc = -1; + goto EXITPOINT; } lLineCount--; /* we count only real lines */ continue; @@ -658,7 +573,7 @@ static Table2_Data_t *init_local_data(const char *filename, int order) * structure table_data */ cnv_get_spice_value(token, &tmpval); table_data[lLineCount - 1][i++] = tmpval; - free(token); + txfree(token); token = CNVgettok(&cThisLinePtr); } if (i < ix) { @@ -676,10 +591,10 @@ static Table2_Data_t *init_local_data(const char *filename, int order) EXITPOINT: /* free the file and memory allocated */ if (cFile != (char *) NULL) { - free(cFile); + txfree(cFile); } if (cThisLine != (char *) NULL) { - free(cThisLine); + txfree(cThisLine); } if (fp != (FILE *) NULL) { (void) fclose(fp); @@ -697,7 +612,7 @@ EXITPOINT: -/* Free memory allocations in Local_Data_t structure */ +/* Free memory allocations in Table2_Data_t structure */ static void free_local_data(Table2_Data_t *loc) { if (loc == (Table2_Data_t *) NULL) { @@ -709,16 +624,24 @@ static void free_local_data(Table2_Data_t *loc) int i; int n_y = loc->iy; for (i = 0; i < n_y; i++) { - free(loc->table[i]); + txfree(loc->table[i]); } - free(loc->table); + txfree(loc->table); } - free(loc->xcol); - free(loc->ycol); - sf_eno2_close(loc->newtable); - free(loc); + if (loc->xcol != (double *) NULL) { + txfree(loc->xcol); + } + if (loc->ycol != (double *) NULL) { + txfree(loc->ycol); + } + + if (loc->newtable != (sf_eno2) NULL) { + sf_eno2_close(loc->newtable); + } + + txfree(loc); } /* end of function free_local_data */ @@ -737,3 +660,21 @@ static inline double get_local_diff(int n, double *col, int ind) +/* This function frees resources when called with reason argument + * MIF_CB_DESTROY */ +static void cm_table2D_callback(ARGS, Mif_Callback_Reason_t reason) +{ + switch (reason) { + case MIF_CB_DESTROY: { + Table2_Data_t *loc = (Table2_Data_t *) STATIC_VAR(locdata); + if (loc) { + free_local_data(loc); + STATIC_VAR(locdata) = NULL; + } + break; + } /* end of case MIF_CB_DESTROY */ + } /* end of switch over reason being called */ +} /* end of function cm_table2D_callback */ + + + diff --git a/src/xspice/icm/table/table3D/cfunc.mod b/src/xspice/icm/table/table3D/cfunc.mod index d354cc9c3..24af85de2 100644 --- a/src/xspice/icm/table/table3D/cfunc.mod +++ b/src/xspice/icm/table/table3D/cfunc.mod @@ -92,7 +92,6 @@ typedef struct { double ***table; /* f(xi, yj, zk) */ } Table3_Data_t; -typedef Table3_Data_t Local_Data_t; /*=== MACROS ===========================*/ @@ -102,10 +101,6 @@ typedef Table3_Data_t Local_Data_t; #define DIR_PATHSEP "/" #endif -#if defined(_MSC_VER) -#define strdup _strdup -#endif - /*=== LOCAL VARIABLES & TYPEDEFS =======*/ @@ -113,76 +108,15 @@ typedef Table3_Data_t Local_Data_t; /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ -extern char *CNVgettok(char **s); -extern double TrilinearInterpolation(double x, double y, double z, int xind, int yind, int zind, double ***td); -int cnv_get_spice_value(char *str, double *p_value); +extern double TrilinearInterpolation(double x, double y, double z, + int xind, int yind, int zind, double ***td); +static void cm_table3D_callback(ARGS, Mif_Callback_Reason_t reason); extern int findCrossOver(double arr[], int n, double x); - static void free_local_data(Table3_Data_t *loc); static inline double get_local_diff(int n, double *col, int ind); static Table3_Data_t *init_local_data(const char *filename, int order); - -/*============================================================================== - -FUNCTION cnv_get_spice_value() - -AUTHORS - - ??? Bill Kuhn - -MODIFICATIONS - - 30 Sep 1991 Jeffrey P. Murray - -SUMMARY - - This function takes as input a string token from a SPICE - deck and returns a floating point equivalent value. - -INTERFACES - - FILE ROUTINE CALLED - - N/A N/A - -RETURNED VALUE - - Returns the floating point value in pointer *p_value. Also - returns an integer representing successful completion. - -GLOBAL VARIABLES - - NONE - -NON-STANDARD FEATURES - - NONE - -==============================================================================*/ - - - - - -static void cm_table3D_callback(ARGS, - Mif_Callback_Reason_t reason) -{ - switch (reason) { - case MIF_CB_DESTROY: { - Table3_Data_t *loc = STATIC_VAR(locdata); - if (loc) { - free_local_data(loc); - STATIC_VAR(locdata) = loc = NULL; - } - break; - } /* end of case MIF_CB_DESTROY */ - } /* end of switch over reason being called */ -} /* end of function cm_table2D_callback */ - - - /*============================================================================== FUNCTION void cm_table3D() @@ -261,7 +195,8 @@ void cm_table3D(ARGS) /* structure holding parms, inputs, outputs, etc. */ } /* return immediately if there was an initialization error */ - if ((loc = STATIC_VAR(locdata)) == (Table3_Data_t *) NULL) { + if ((loc = (Table3_Data_t *) STATIC_VAR(locdata)) == + (Table3_Data_t *) NULL) { return; } @@ -362,15 +297,13 @@ void cm_table3D(ARGS) /* structure holding parms, inputs, outputs, etc. */ } else { Mif_Complex_t ac_gain; - ac_gain.real = PARAM(gain) * derivval[0] / xdiff; ac_gain.imag= 0.0; + ac_gain.real = PARAM(gain) * derivval[0] / xdiff; AC_GAIN(out, inx) = ac_gain; ac_gain.real = PARAM(gain) * derivval[1] / ydiff; - ac_gain.imag= 0.0; AC_GAIN(out, iny) = ac_gain; ac_gain.real = PARAM(gain) * derivval[2] / zdiff; - ac_gain.imag= 0.0; - AC_GAIN(out, iny) = ac_gain; + AC_GAIN(out, inz) = ac_gain; } } /* end of function cm_table3D */ @@ -398,7 +331,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) /* Allocate static storage for *loc */ - if ((loc = (Table3_Data_t *) calloc(1, + if ((loc = (Table3_Data_t *) tcalloc_raw(1, sizeof(Table3_Data_t))) == (Table3_Data_t *) NULL) { cm_message_printf("cannot allocate memory for lookup table."); xrc = -1; @@ -414,7 +347,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) if (!fp) { /* Standard open attempt failed */ const char * const lbuffer = getenv("NGSPICE_INPUT_DIR"); if (lbuffer && *lbuffer) { - char * const p = (char *) malloc(strlen(lbuffer) + + char * const p = (char *) tmalloc_raw(strlen(lbuffer) + strlen(DIR_PATHSEP) + strlen(filename) + 1); if (p == (char *) NULL) { @@ -426,7 +359,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) (void) sprintf(p, "%s%s%s", lbuffer, DIR_PATHSEP, filename); fp = fopen(p, "r"); - free(p); + txfree(p); } } @@ -451,9 +384,9 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) } /* create string to hold the whole file */ - cFile = calloc(lFileLen + 1, sizeof(char)); + cFile = tcalloc_raw(lFileLen + 1, sizeof(char)); /* create another string long enough for file manipulation */ - cThisLine = calloc(lFileLen + 1, sizeof(char)); + cThisLine = tcalloc_raw(lFileLen + 1, sizeof(char)); if (cFile == NULL || cThisLine == NULL) { cm_message_printf("Insufficient memory to read file %s", filename); @@ -514,7 +447,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) cnv_get_spice_value(cThisLinePtr, &tmp); loc->ix = ix = (int) tmp; /* generate row data structure (x) */ - if ((loc->xcol = (double *) calloc((size_t) ix, + if ((loc->xcol = (double *) tcalloc_raw((size_t) ix, sizeof(double))) == (double *) NULL) { cm_message_printf("Unable to allocate row structure."); xrc = -1; @@ -525,7 +458,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) cnv_get_spice_value(cThisLinePtr, &tmp); loc->iy = iy = (int) tmp; /* generate column data structure (y) */ - if ((loc->ycol = (double *) calloc((size_t) iy, + if ((loc->ycol = (double *) tcalloc_raw((size_t) iy, sizeof(double))) == (double *) NULL) { cm_message_printf("Unable to allocate colum structure."); xrc = -1; @@ -536,7 +469,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) cnv_get_spice_value(cThisLinePtr, &tmp); loc->iz = iz = (int) tmp; /* generate column data structure (z) */ - if ((loc->zcol = (double *) calloc((size_t) iz, + if ((loc->zcol = (double *) tcalloc_raw((size_t) iz, sizeof(double))) == (double *) NULL) { cm_message_printf("Unable to allocate \"z\" structure."); xrc = -1; @@ -553,7 +486,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) goto EXITPOINT; } cnv_get_spice_value(token, &loc->xcol[i++]); - free(token); + txfree(token); token = CNVgettok(&cThisLinePtr); } if (i < ix) { @@ -572,7 +505,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) goto EXITPOINT; } cnv_get_spice_value(token, &loc->ycol[i++]); - free(token); + txfree(token); token = CNVgettok(&cThisLinePtr); } if (i < iy) { @@ -591,7 +524,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) goto EXITPOINT; } cnv_get_spice_value(token, &loc->zcol[i++]); - free(token); + txfree(token); token = CNVgettok(&cThisLinePtr); } if (i < iz) { @@ -618,16 +551,16 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) int n1, int n2, int n3 : data dimensions */ if ((loc->newtable = sf_eno3_init( interporder, ix, iy, iz)) == (sf_eno3) NULL) { - cm_message_printf("eno3 initialization failure."); + cm_message_send("eno3 initialization failure."); xrc = -1; goto EXITPOINT; } /* create table_data in memory */ /* data [n3][n2][n1] */ - if ((loc->table = table_data = (double ***) calloc((size_t) iz, + if ((loc->table = table_data = (double ***) tcalloc_raw((size_t) iz, sizeof(double **))) == (double ***) NULL) { - cm_message_printf("Unable to allocate data table."); + cm_message_send("Unable to allocate data table."); xrc = -1; goto EXITPOINT; } @@ -635,7 +568,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) { int i, j; for (i = 0; i < iz; i++) { - if ((table_data[i] = (double **) calloc((size_t) iy, + if ((table_data[i] = (double **) tcalloc_raw((size_t) iy, sizeof(double *))) == (double **) NULL) { cm_message_printf("Unable to allocate data table " "z=%d", @@ -644,7 +577,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) goto EXITPOINT; } for (j = 0; j < iy; j++) { - if ((table_data[i][j] = (double *) calloc((size_t) ix, + if ((table_data[i][j] = (double *) tcalloc_raw((size_t) ix, sizeof(double))) == (double *) NULL) { cm_message_printf("Unable to allocate data table " "z=%d y=%d", @@ -709,7 +642,7 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) table_data[lTableCount][lLineCount][i++] = tmpval; - free(token); + txfree(token); token = CNVgettok(&cThisLinePtr); } if (i < ix) { @@ -730,10 +663,10 @@ static Table3_Data_t *init_local_data(const char *filename, int interporder) EXITPOINT: /* free the file and memory allocated */ if (cFile != (char *) NULL) { - free(cFile); + txfree(cFile); } if (cThisLine != (char *) NULL) { - free(cThisLine); + txfree(cThisLine); } if (fp != (FILE *) NULL) { (void) fclose(fp); @@ -760,24 +693,35 @@ static void free_local_data(Table3_Data_t *loc) /* Free data table and related values */ if (loc->table) { - int i, j; + int i; int n_y = loc->iy; int n_z = loc->iz; for (i = 0; i < n_z; i++) { + int j; for (j = 0; j < n_y; j++) { - free(loc->table[i][j]); + txfree(loc->table[i][j]); } - free(loc->table[i]); + txfree(loc->table[i]); } - free(loc->table); + txfree(loc->table); } - free(loc->xcol); - free(loc->ycol); - free(loc->zcol); - sf_eno3_close(loc->newtable); - free(loc); + if (loc->xcol != (double *) NULL) { + txfree(loc->xcol); + } + if (loc->ycol != (double *) NULL) { + txfree(loc->ycol); + } + if (loc->zcol != (double *) NULL) { + txfree(loc->zcol); + } + + if (loc->newtable != (sf_eno3) NULL) { + sf_eno3_close(loc->newtable); + } + + txfree(loc); } /* end of function free_local_data */ @@ -795,6 +739,25 @@ static inline double get_local_diff(int n, double *col, int ind) } /* end of function get_local_diff */ + +/* This function frees resources when called with reason argument + * MIF_CB_DESTROY */ +static void cm_table3D_callback(ARGS, Mif_Callback_Reason_t reason) +{ + switch (reason) { + case MIF_CB_DESTROY: { + Table3_Data_t *loc = (Table3_Data_t *) STATIC_VAR(locdata); + if (loc) { + free_local_data(loc); + STATIC_VAR(locdata) = NULL; + } + break; + } /* end of case MIF_CB_DESTROY */ + } /* end of switch over reason being called */ +} /* end of function cm_table3D_callback */ + + + /* These includes add functions from extra source code files, * still using the standard XSPICE procedure of cmpp-ing cfunc.mod * and then only compiling the resulting *.c file. diff --git a/src/xspice/icm/xtradev/modpath.lst b/src/xspice/icm/xtradev/modpath.lst index 4e30d11f6..8c8529b96 100644 --- a/src/xspice/icm/xtradev/modpath.lst +++ b/src/xspice/icm/xtradev/modpath.lst @@ -1,11 +1,12 @@ -aswitch -capacitor -cmeter -core -inductor -lcouple -lmeter -potentiometer -zener -memristor -sidiode +#Directory Version +aswitch 1 +capacitor 1 +cmeter 1 +core 1 +inductor 1 +lcouple 1 +lmeter 1 +potentiometer 1 +zener 2 +memristor 1 +sidiode 1 diff --git a/src/xspice/icm/xtradev/sidiode/cfunc.mod b/src/xspice/icm/xtradev/sidiode/cfunc.mod index 612c8dfbd..bf127b5fa 100644 --- a/src/xspice/icm/xtradev/sidiode/cfunc.mod +++ b/src/xspice/icm/xtradev/sidiode/cfunc.mod @@ -86,19 +86,7 @@ typedef struct { /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ - -static void -cm_sidiode_callback(ARGS, Mif_Callback_Reason_t reason) -{ - switch (reason) { - case MIF_CB_DESTROY: { - Local_Data_t *loc = STATIC_VAR (locdata); - free(loc); - break; - } - } -} - +static void cm_sidiode_callback(ARGS, Mif_Callback_Reason_t reason); /*============================================================================== @@ -127,11 +115,12 @@ void cm_sidiode(ARGS) /* structure holding parms, double grev, goff, gon, Va, Vb, Vc, Vd, hEpsilon, hRevepsilon; - CALLBACK = cm_sidiode_callback; - /* allocate static storage for *loc */ - STATIC_VAR(locdata) = calloc (1, sizeof(Local_Data_t)); - loc = STATIC_VAR(locdata); + if ((loc = (Local_Data_t *) (STATIC_VAR(locdata) = tcalloc_raw(1, + sizeof(Local_Data_t)))) == (Local_Data_t *) NULL) { + cm_message_send("Unable to allocate locdata in cm_sidiode()."); + } + CALLBACK = cm_sidiode_callback; goff = 1./PARAM(roff); gon = 1./PARAM(ron); @@ -177,8 +166,14 @@ void cm_sidiode(ARGS) /* structure holding parms, loc->goff = goff; loc->gon = gon; } - else - loc = STATIC_VAR(locdata); + else { + if ((loc = (Local_Data_t *) STATIC_VAR(locdata)) == + (Local_Data_t *) NULL) { + cm_message_send("Attempt to use uninitialized locdata " + "in cm_sidiode()"); + return; + } + } /* Calculate diode current Id and its derivative deriv=dId/dVin */ @@ -233,4 +228,24 @@ void cm_sidiode(ARGS) /* structure holding parms, ac_gain.imag= 0.0; AC_GAIN(ds,ds) = ac_gain; } -} +} /* end of function cm_sidiode */ + + + +/* This function frees resources when called with reason argument + * MIF_CB_DESTROY */ +static void cm_sidiode_callback(ARGS, Mif_Callback_Reason_t reason) +{ + switch (reason) { + case MIF_CB_DESTROY: { + Local_Data_t *loc = (Local_Data_t *) STATIC_VAR(locdata); + if (loc != (Local_Data_t *) NULL) { + txfree(loc); + } + break; + } + } +} /* end of function cm_sidiode_callback */ + + + diff --git a/src/xspice/icm/xtradev/zener/cfunc.mod b/src/xspice/icm/xtradev/zener/cfunc.mod index 7c25a229e..29fde78fc 100644 --- a/src/xspice/icm/xtradev/zener/cfunc.mod +++ b/src/xspice/icm/xtradev/zener/cfunc.mod @@ -69,9 +69,9 @@ NON-STANDARD FEATURES /*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ +static void cm_zener_callback(ARGS, Mif_Callback_Reason_t reason); - /*============================================================================== FUNCTION void cm_zener() @@ -174,16 +174,25 @@ void cm_zener(ARGS) /* structure holding parms, if (INIT==1) { /* First pass...allocate storage for previous value... */ /* Allocate storage for frequencies */ - STATIC_VAR(previous_voltage) = (double *) malloc(sizeof(double)); - previous_voltage = (double *) STATIC_VAR(previous_voltage); + if ((previous_voltage = (double *) (STATIC_VAR(previous_voltage) = + tmalloc_raw(sizeof(double)))) == (double *) NULL) { + cm_message_send("Unable to allocate memory for previous " + "voltage in cm_zener()"); + return; + } + CALLBACK = cm_zener_callback; /* Set previous_voltage value to zero... */ *previous_voltage = 0.0; } else { - - previous_voltage = (double *) STATIC_VAR(previous_voltage); + if ((previous_voltage = (double *) STATIC_VAR( + previous_voltage)) == (double *) NULL) { + cm_message_send("Attempt to use uninitialized previous " + "voltage in cm_zener()"); + return; + } } @@ -352,5 +361,23 @@ void cm_zener(ARGS) /* structure holding parms, ac_gain.imag= 0.0; AC_GAIN(z,z) = ac_gain; } -} +} /* end of function cm_zener */ + + + +static void cm_zener_callback(ARGS, Mif_Callback_Reason_t reason) +{ + switch (reason) { + case MIF_CB_DESTROY: { + double * const p_prev_voltage = + (double *) STATIC_VAR(previous_voltage); + if (p_prev_voltage != (double *) NULL) { + txfree(p_prev_voltage); + } + break; + } + } +} /* end of function cm_zener_callback */ + + diff --git a/src/xspice/icm/xtraevt/modpath.lst b/src/xspice/icm/xtraevt/modpath.lst index 81dbd3ec7..e6cd74acd 100644 --- a/src/xspice/icm/xtraevt/modpath.lst +++ b/src/xspice/icm/xtraevt/modpath.lst @@ -1,4 +1,5 @@ -d_to_real -real_delay -real_gain -real_to_v +#Directory Version +d_to_real 1 +real_delay 1 +real_gain 1 +real_to_v 1 diff --git a/src/xspice/icm/xtraevt/udnpath.lst b/src/xspice/icm/xtraevt/udnpath.lst index e5705e826..8febcb47f 100644 --- a/src/xspice/icm/xtraevt/udnpath.lst +++ b/src/xspice/icm/xtraevt/udnpath.lst @@ -1,2 +1,3 @@ -int -real +#Directory Version +int 1 +real 1 diff --git a/src/xspice/ipc/ipcstdio.c b/src/xspice/ipc/ipcstdio.c index 15ef467b1..229fff3ba 100644 --- a/src/xspice/ipc/ipcstdio.c +++ b/src/xspice/ipc/ipcstdio.c @@ -45,7 +45,10 @@ Ipc_Status_t ipc_transport_get_line ( NG_IGNORE(wait); printf ("GET_LINE\n"); - gets (str); + fgets (str, 512, stdin); + char *tmp = strchr(str, '\n'); + if (tmp) + *tmp = '\0'; *len = (int) strlen (str); return IPC_STATUS_OK; } diff --git a/src/xspice/mif/mifgetmod.c b/src/xspice/mif/mifgetmod.c index b38c279dd..1ce14c283 100644 --- a/src/xspice/mif/mifgetmod.c +++ b/src/xspice/mif/mifgetmod.c @@ -82,7 +82,7 @@ successful, and an error string on failure. char *MIFgetMod( CKTcircuit *ckt, /* The circuit structure */ - char *name, /* The name of the model to look for */ + const char *name, /* The name of the model to look for */ INPmodel **model, /* The model found/created */ INPtables *tab /* Table of model info from first pass */ ) diff --git a/src/xspice/mif/mifutil.c b/src/xspice/mif/mifutil.c index b1243afb9..93e968acb 100644 --- a/src/xspice/mif/mifutil.c +++ b/src/xspice/mif/mifutil.c @@ -394,7 +394,7 @@ MIFcopy This function allocates a new copy of a string. */ -char *MIFcopy(char *str) +char *MIFcopy(const char *str) { if(str) return copy(str); diff --git a/visualc/make-install-vngspiced.bat b/visualc/make-install-vngspiced.bat index 2697a5d6f..51d113836 100644 --- a/visualc/make-install-vngspiced.bat +++ b/visualc/make-install-vngspiced.bat @@ -10,9 +10,9 @@ if "%3" == "64" goto b64 set dst=c:\Spiced set cmsrc=.\codemodels\Win32\Debug -mkdir %dst%\bin -mkdir %dst%\lib\ngspice -mkdir %dst%\share\ngspice\scripts +if not exist "%dst%\bin\" mkdir "%dst%\bin" +if not exist "%dst%\lib\ngspice\" mkdir "%dst%\lib\ngspice" +if not exist "%dst%\share\ngspice\scripts\" mkdir "%dst%\share\ngspice\scripts" copy "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x86\Microsoft.VC140.OPENMP\vcomp140.dll" %dst%\bin\ copy %cmsrc%\analog.cm %dst%\lib\ngspice\analog.cm @@ -24,6 +24,8 @@ copy %cmsrc%\spice2poly.cm %dst%\lib\ngspice\spice2poly.cm copy .\spinit_all %dst%\share\ngspice\scripts\spinit copy .\spinitd .\spinit + + if "%2" == "fftw" goto copy2 if "%3" == "fftw" goto copy2 @@ -40,10 +42,9 @@ goto end set dst=c:\Spice64d set cmsrc=.\codemodels\x64\Debug -mkdir %dst%\bin -mkdir %dst%\lib\ngspice -mkdir %dst%\share\ngspice\scripts - +if not exist "%dst%\bin\" mkdir "%dst%\bin" +if not exist "%dst%\lib\ngspice\" mkdir "%dst%\lib\ngspice" +if not exist "%dst%\share\ngspice\scripts\" mkdir "%dst%\share\ngspice\scripts" copy "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\redist\x64\Microsoft.VC140.OPENMP\vcomp140.dll" %dst%\bin\ copy %cmsrc%\analog64.cm %dst%\lib\ngspice\analog.cm copy %cmsrc%\digital64.cm %dst%\lib\ngspice\digital.cm @@ -54,6 +55,18 @@ copy %cmsrc%\spice2poly64.cm %dst%\lib\ngspice\spice2poly.cm copy .\spinit_all %dst%\share\ngspice\scripts\spinit copy .\spinitd64 .\spinit +REM ADDED TO ALLOW USE OF CODE MODELS OF THE CURRENT SOLUTION +set ngspice_home=%1 +echo Adding code models to the directory of the ngspice program +copy %cmsrc%\analog64.cm %ngspice_home%\analog64.cm +copy %cmsrc%\digital64.cm %ngspice_home%\digital64.cm +copy %cmsrc%\table64.cm %ngspice_home%\table64.cm +copy %cmsrc%\xtraevt64.cm %ngspice_home%\xtraevt64.cm +copy %cmsrc%\xtradev64.cm %ngspice_home%\xtradev64.cm +copy %cmsrc%\spice2poly64.cm %ngspice_home%\spice2poly64.cm +copy spinit_dbg64_src %ngspice_home%\spinit +REM END OF ADDED TO ALLOW USE OF CODE MODELS OF THE CURRENT SOLUTION + if "%2" == "fftw" goto copy2-64 if "%3" == "fftw" goto copy2-64 diff --git a/visualc/sharedspice.vcxproj b/visualc/sharedspice.vcxproj index cf35a0786..a4dc57acb 100644 --- a/visualc/sharedspice.vcxproj +++ b/visualc/sharedspice.vcxproj @@ -33,27 +33,27 @@ DynamicLibrary - v140 + v142 DynamicLibrary - v140 + v142 DynamicLibrary - v140 + v142 DynamicLibrary - v140 + v142 DynamicLibrary - v140 + v142 DynamicLibrary - v140 + v142 diff --git a/visualc/spinit_dbg64_src b/visualc/spinit_dbg64_src new file mode 100644 index 000000000..80635eb6d --- /dev/null +++ b/visualc/spinit_dbg64_src @@ -0,0 +1,31 @@ +* Standard ngspice init file +alias exit quit +alias acct rusage all +set x11lineararcs +*set rndseed=12 +** ascii rawfile ** +set filetype=ascii +** frontend debug output ** +*set ngdebug +** asking after quit ** +*set askquit +** set the number of threads in openmp +** default (if compiled with --enable-openmp) is: 2 +set num_threads=4 +set interactive +set stepsizelimit + +strcmp __flag $program "ngspice" +if $__flag = 0 + +* Load the codemodels + codemodel spice2poly64.cm + codemodel analog64.cm + codemodel digital64.cm + codemodel xtradev64.cm + codemodel xtraevt64.cm + codemodel table64.cm + + +end +unset __flag diff --git a/visualc/spinit_dbg_src b/visualc/spinit_dbg_src new file mode 100644 index 000000000..625b8b39c --- /dev/null +++ b/visualc/spinit_dbg_src @@ -0,0 +1,32 @@ +* Standard ngspice init file +alias exit quit +alias acct rusage all +set x11lineararcs +*set rndseed=12 +** ascii rawfile ** +set filetype=ascii +** frontend debug output ** +*set ngdebug +** asking after quit ** +*set askquit +** set the number of threads in openmp +** default (if compiled with --enable-openmp) is: 2 +set num_threads=4 +set interactive +set stepsizelimit + +strcmp __flag $program "ngspice" +if $__flag = 0 + +* Load the codemodels +echo "Loading code models" + codemodel spice2poly.cm + codemodel analog.cm + codemodel digital.cm + codemodel xtradev.cm + codemodel xtraevt.cm + codemodel table.cm + + +end +unset __flag diff --git a/visualc/vngspice.vcxproj b/visualc/vngspice.vcxproj index 123d0cffb..e4bf427e1 100644 --- a/visualc/vngspice.vcxproj +++ b/visualc/vngspice.vcxproj @@ -1,2686 +1,2686 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - console_debug - Win32 - - - console_release - Win32 - - - console_debug - x64 - - - console_release - x64 - - - ReleaseOMP - Win32 - - - ReleaseOMP - x64 - - - console_release_omp - Win32 - - - console_release_omp - x64 - - - - {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A} - vngspice - Win32Proj - - - - Application - v140 - - - Application - true - v140 - - - Application - v140 - - - Application - true - v140 - - - Application - v140 - - - Application - true - v140 - - - Application - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - ngspice - $(ProjectName)\$(Configuration).$(Platform)\ - $(ProjectName)\$(Configuration).$(Platform)\obj\ - - - false - false - - - false - - - false - false - true - - - false - true - - - false - false - - - false - - - false - false - true - - - false - true - - - false - - - false - true - - - false - - - false - true - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - Disabled - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;%(PreprocessorDefinitions) - false - - - Default - MultiThreadedDebug - false - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Windows - 0 - 0 - 0 - 0 - false - - - MachineX86 - true - - - make-install-vngspiced.bat $(OutDir) - - - $(ProjectDir)ngspice-x86.exe.manifest - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Windows - 0 - 0 - 0 - 0 - true - true - UseLinkTimeCodeGeneration - true - - - MachineX86 - true - - + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + console_debug + Win32 + + + console_release + Win32 + + + console_debug + x64 + + + console_release + x64 + + + ReleaseOMP + Win32 + + + ReleaseOMP + x64 + + + console_release_omp + Win32 + + + console_release_omp + x64 + + + + {83E315C7-EDD3-4F6B-AF28-87A92A4FA49A} + vngspice + Win32Proj + + + + Application + v142 + + + Application + true + v142 + + + Application + v142 + + + Application + true + v142 + + + Application + v142 + + + Application + true + v142 + + + Application + v142 + + + Application + true + v142 + + + Application + true + v142 + + + Application + true + v142 + + + Application + true + v142 + + + Application + true + v142 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ngspice + $(ProjectName)\$(Configuration).$(Platform)\ + $(ProjectName)\$(Configuration).$(Platform)\obj\ + + + false + false + + + false + + + false + false + true + + + false + true + + + false + false + + + false + + + false + false + true + + + false + true + + + false + + + false + true + + + false + + + false + true + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + Disabled + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;%(PreprocessorDefinitions) + false + + + Default + MultiThreadedDebug + false + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Windows + 0 + 0 + 0 + 0 + false + + + MachineX86 + true + + + make-install-vngspiced.bat $(OutDir) + + + $(ProjectDir)ngspice-x86.exe.manifest + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Windows + 0 + 0 + 0 + 0 + true + true + UseLinkTimeCodeGeneration + true + + + MachineX86 + true + + make-install-vngspice.bat $(OutDir) - - - - $(ProjectDir)ngspice-x86.exe.manifest - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - X64 - - - Disabled - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONFIG64;%(PreprocessorDefinitions) - false - - - Default - MultiThreadedDebug - false - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Windows - 0 - 0 - 4194304 - 1048576 - false - - - MachineX64 - true - - + + + + $(ProjectDir)ngspice-x86.exe.manifest + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + X64 + + + Disabled + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONFIG64;%(PreprocessorDefinitions) + false + + + Default + MultiThreadedDebug + false + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Windows + 0 + 0 + 4194304 + 1048576 + false + + + MachineX64 + true + + make-install-vngspiced.bat $(OutDir) 64 - - - - $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - X64 - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONFIG64;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - false - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Windows - 0 - 0 - 4194304 - 1048576 - - - - - UseLinkTimeCodeGeneration - true - - - MachineX64 - true - - + + + + $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + X64 + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONFIG64;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + false + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Windows + 0 + 0 + 4194304 + 1048576 + + + + + UseLinkTimeCodeGeneration + true + + + MachineX64 + true + + make-install-vngspice.bat $(OutDir) 64 - - - - $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - Disabled - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;%(PreprocessorDefinitions) - false - - - Default - MultiThreadedDebug - false - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Console - 0 - 0 - 0 - 0 - false - - - MachineX86 - true - - - make-install-vngspiced.bat $(OutDir) - - - $(ProjectDir)ngspice-x86.exe.manifest - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Console - 0 - 0 - 0 - 0 - true - true - UseLinkTimeCodeGeneration - true - - - MachineX86 - true - - - make-install-vngspice.bat $(OutDir) - - - $(ProjectDir)ngspice-x86.exe.manifest - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - X64 - - - Disabled - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;CONFIG64;%(PreprocessorDefinitions) - false - - - Default - MultiThreadedDebug - false - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Console - 0 - 0 - 4194304 - 1048576 - false - - - MachineX64 - true - - + + + + $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + Disabled + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;%(PreprocessorDefinitions) + false + + + Default + MultiThreadedDebug + false + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Console + 0 + 0 + 0 + 0 + false + + + MachineX86 + true + + + make-install-vngspiced.bat $(OutDir) + + + $(ProjectDir)ngspice-x86.exe.manifest + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Console + 0 + 0 + 0 + 0 + true + true + UseLinkTimeCodeGeneration + true + + + MachineX86 + true + + + make-install-vngspice.bat $(OutDir) + + + $(ProjectDir)ngspice-x86.exe.manifest + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + X64 + + + Disabled + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;CONFIG64;%(PreprocessorDefinitions) + false + + + Default + MultiThreadedDebug + false + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Console + 0 + 0 + 4194304 + 1048576 + false + + + MachineX64 + true + + make-install-vngspiced.bat $(OutDir) 64 - - - - $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - X64 - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Console - 0 - 0 - 4194304 - 1048576 - true - true - UseLinkTimeCodeGeneration - true - - - MachineX64 - true - - + + + + $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + X64 + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Console + 0 + 0 + 4194304 + 1048576 + true + true + UseLinkTimeCodeGeneration + true + + + MachineX64 + true + + make-install-vngspice.bat $(OutDir) 64 - - - - $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - true - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Windows - 0 - 0 - 0 - 0 - true - true - UseLinkTimeCodeGeneration - true - - - MachineX86 - true - - - make-install-vngspice.bat $(OutDir) - - - $(ProjectDir)ngspice-x86.exe.manifest - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - X64 - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;CONFIG64;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - true - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Windows - 0 - 0 - 4194304 - 1048576 - - - - - UseLinkTimeCodeGeneration - true - - - MachineX64 - true - - + + + + $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + true + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Windows + 0 + 0 + 0 + 0 + true + true + UseLinkTimeCodeGeneration + true + + + MachineX86 + true + + + make-install-vngspice.bat $(OutDir) + + + $(ProjectDir)ngspice-x86.exe.manifest + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + X64 + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;CONFIG64;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + true + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Windows + 0 + 0 + 4194304 + 1048576 + + + + + UseLinkTimeCodeGeneration + true + + + MachineX64 + true + + make-install-vngspice.bat $(OutDir) 64 - - - - $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;USE_OMP;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - true - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Console - 0 - 0 - 0 - 0 - true - true - UseLinkTimeCodeGeneration - true - - - MachineX86 - true - - - make-install-vngspice.bat $(OutDir) - - - $(ProjectDir)ngspice-x86.exe.manifest - - - - - force recompilation of conf.c with actual date - if exist $(IntDir)conf.obj del $(IntDir)conf.obj - - - X64 - - - MaxSpeed - true - Speed - true - ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) - _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;USE_OMP;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - true - true - - - Level4 - ProgramDatabase - CompileAsC - true - - - psapi.lib;%(AdditionalDependencies) - true - Console - 0 - 0 - 4194304 - 1048576 - true - true - UseLinkTimeCodeGeneration - true - - - MachineX64 - true - - + + + + $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;USE_OMP;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + true + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Console + 0 + 0 + 0 + 0 + true + true + UseLinkTimeCodeGeneration + true + + + MachineX86 + true + + + make-install-vngspice.bat $(OutDir) + + + $(ProjectDir)ngspice-x86.exe.manifest + + + + + force recompilation of conf.c with actual date + if exist $(IntDir)conf.obj del $(IntDir)conf.obj + + + X64 + + + MaxSpeed + true + Speed + true + ..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\include;..\src\spicelib\parser;.;%(AdditionalIncludeDirectories) + _CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;USE_OMP;%(PreprocessorDefinitions) + false + + + Default + MultiThreaded + true + true + + + Level4 + ProgramDatabase + CompileAsC + true + + + psapi.lib;%(AdditionalDependencies) + true + Console + 0 + 0 + 4194304 + 1048576 + true + true + UseLinkTimeCodeGeneration + true + + + MachineX64 + true + + make-install-vngspice.bat $(OutDir) 64 - - - - $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - invoke win_bison.exe for %(Identity) - ..\..\flex-bison\win_bison.exe --output=.\tmp-bison\%(Filename).c --defines=.\tmp-bison\%(Filename).h %(Identity) || exit 1 - .\tmp-bison\%(Filename).c;.\tmp-bison\%(Filename).h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + $(ProjectDir)ngspice.exe.manifest %(AdditionalManifestFiles) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + invoke win_bison.exe for %(Identity) + ..\..\flex-bison\win_bison.exe --output=.\tmp-bison\%(Filename).c --defines=.\tmp-bison\%(Filename).h %(Identity) || exit 1 + .\tmp-bison\%(Filename).c;.\tmp-bison\%(Filename).h + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/visualc/xspice/analog.vcxproj b/visualc/xspice/analog.vcxproj index 61d40dd74..4bbc0fd19 100644 --- a/visualc/xspice/analog.vcxproj +++ b/visualc/xspice/analog.vcxproj @@ -22,30 +22,30 @@ analog {8271FEA2-8AC0-4B6D-BAEA-A503D37B5DB2} icmanalog - 8.1 + 10.0 DynamicLibrary NotSet - v140 + v142 DynamicLibrary NotSet true - v140 + v142 DynamicLibrary NotSet - v140 + v142 DynamicLibrary MultiByte true - v140 + v142 diff --git a/visualc/xspice/aux-cfunc.bat b/visualc/xspice/aux-cfunc.bat index 24c568dcf..a251d899d 100644 --- a/visualc/xspice/aux-cfunc.bat +++ b/visualc/xspice/aux-cfunc.bat @@ -1,24 +1,79 @@ rem invoke as rem .\aux-cfunc.bat analog +REM sub is the parent directory of all of the code models and user types that +REM are being built set sub=%1 -set CMPP_IDIR=../../src/xspice/icm/%sub% -set CMPP_ODIR=icm/%sub% -if not exist icm\%sub% mkdir icm\%sub% -.\bin\cmpp -lst -for /F %%n in (..\..\src\xspice\icm\%sub%\modpath.lst) do ( - set CMPP_IDIR=../../src/xspice/icm/%sub%/%%n - set CMPP_ODIR=icm/%sub%/%%n - if not exist icm\%sub%\%%n mkdir icm\%sub%\%%n - .\bin\cmpp -ifs - .\bin\cmpp -mod - pushd icm\%sub%\%%n - if exist %%n-cfunc.c del %%n-cfunc.c - if exist %%n-ifspec.c del %%n-ifspec.c - rename cfunc.c %%n-cfunc.c - rename ifspec.c %%n-ifspec.c - popd + +REM Step 1: Process the .lst files for code models and nodes to create +REM source files and related outputs +echo Processing lst files for code model and user-defined nodes ^ +at src/xspice/icm/%sub% + +echo CMPP_IDIR=../../src/xspice/icm/%sub% +set CMPP_IDIR=../../src/xspice/icm/%sub% + +echo CMPP_ODIR=icm/%sub% +set CMPP_ODIR=icm/%sub% +if not exist "icm\%sub%" mkdir "icm\%sub%" +echo running cmpp.exe -lst +bin\cmpp.exe -lst + + + +REM Step 2: For each path in in modpath.lst prepare the directory for a build +REM Test for any code models and process if found +REM ERRORLEVEL = -1 if cannot read modpath.lst file; else = # paths found +echo Processing paths in ..\..\src\xspice\icm\%sub%\modpath.lst +set cmpp_cmd=bin\cmpp.exe -p "..\..\src\xspice\icm\%sub%\modpath.lst" +%cmpp_cmd% > NUL +if %ERRORLEVEL% LSS 0 goto ERROR_EXIT_CM +if %ERRORLEVEL% EQU 0 goto UDN +for /F "tokens=*" %%n in ('%cmpp_cmd%') do ( + echo CMPP_IDIR=../../src/xspice/icm/%sub%/%%n + set CMPP_IDIR=../../src/xspice/icm/%sub%/%%n + + echo CMPP_ODIR=icm/%sub%/%%n + set CMPP_ODIR=icm/%sub%/%%n + if not exist "icm\%sub%\%%n" mkdir "icm\%sub%\%%n" + echo running cmpp.exe -ifs + bin\cmpp.exe -ifs + echo running cmpp.exe -mod + bin\cmpp.exe -mod + pushd "icm\%sub%\%%n" + if exist "%%n-cfunc.c" del "%%n-cfunc.c" + if exist "%%n-ifspec.c" del "%%n-ifspec.c" + rename cfunc.c "%%n-cfunc.c" + rename ifspec.c "%%n-ifspec.c" + popd ) + +:UDN +REM Step 3: For each path in in udnpath.lst prepare the directory for a build +REM Test for any user-defined types and process if found +REM ERRORLEVEL = -1 if cannot read udnpath.lst file; else = # paths found +echo Processing paths in ..\..\src\xspice\icm\%sub%\udnpath.lst +set cmpp_cmd=bin\cmpp.exe -p "..\..\src\xspice\icm\%sub%\udnpath.lst" +%cmpp_cmd% > NUL +if %ERRORLEVEL% LSS 0 goto ERROR_EXIT_UDN +if %ERRORLEVEL% EQU 0 goto EXIT +for /F "tokens=*" %%n in ('%cmpp_cmd%') do ( + if not exist "icm\%sub%\%%n" mkdir "icm\%sub%\%%n" + copy /Y "..\..\src\xspice\icm\%sub%\%%n\udnfunc.c" ^ + "icm\%sub%\%%n\%%n-udnfunc.c" +) + +:EXIT +exit 0 + +:ERROR_EXIT_MOD +echo "Unable to obtain paths for code models" +exit -1 + +:ERROR_EXIT_UDN +echo "Unable to obtain paths for user-defined types" +exit -1 + diff --git a/visualc/xspice/aux-udnfunc.bat b/visualc/xspice/aux-udnfunc.bat index 9ddcd4ea8..00923b8c3 100644 --- a/visualc/xspice/aux-udnfunc.bat +++ b/visualc/xspice/aux-udnfunc.bat @@ -1,9 +1,13 @@ rem invoke as rem .\aux-udnfunc.bat xtraevt - -set sub=%1 - -for /F %%n in (..\..\src\xspice\icm\%sub%\udnpath.lst) do ( - if not exist icm\%sub%\%%n mkdir icm\%sub%\%%n - copy /Y ..\..\src\xspice\icm\%sub%\%%n\udnfunc.c icm\%sub%\%%n\%%n-udnfunc.c -) +REM +REM set sub=%1 +REM +REM for /F %%n in (..\..\src\xspice\icm\%sub%\udnpath.lst) do ( +REM echo Processing paths in ..\..\src\xspice\icm\%sub%\udnpath.lst +REM for /F "tokens=*" %%n in ('bin\cmpp.exe ^ +REM -p "..\..\src\xspice\icm\%sub%\udnpath.lst"') do ( +REM if not exist "icm\%sub%\%%n" mkdir "icm\%sub%\%%n" +REM copy /Y "..\..\src\xspice\icm\%sub%\%%n\udnfunc.c" ^ +REM "icm\%sub%\%%n\%%n-udnfunc.c" +REM ) diff --git a/visualc/xspice/cmpp/cmpp.vcxproj b/visualc/xspice/cmpp/cmpp.vcxproj index 45cecc0ec..f14055b33 100644 --- a/visualc/xspice/cmpp/cmpp.vcxproj +++ b/visualc/xspice/cmpp/cmpp.vcxproj @@ -87,7 +87,7 @@ _CRT_SECURE_NO_WARNINGS;YY_NO_UNISTD_H;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) false MultiThreadedDebug - ..\..\..\src\xspice\cmpp + $(ProjectDir)..\..\..\src\xspice\cmpp; true @@ -106,7 +106,7 @@ false MultiThreaded ProgramDatabase - ..\..\..\src\xspice\cmpp + $(ProjectDir)..\..\..\src\xspice\cmpp; true @@ -128,7 +128,7 @@ false Default MultiThreadedDebug - ..\..\..\src\xspice\cmpp;%(AdditionalIncludeDirectories) + $(ProjectDir)..\..\..\src\xspice\cmpp;%(AdditionalIncludeDirectories) true @@ -145,7 +145,7 @@ _CRT_SECURE_NO_WARNINGS;YY_NO_UNISTD_H;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) false CompileAsC - ..\..\..\src\xspice\cmpp;%(AdditionalIncludeDirectories) + $(ProjectDir)..\..\..\src\xspice\cmpp;%(AdditionalIncludeDirectories) true @@ -169,11 +169,13 @@ + + diff --git a/visualc/xspice/digital.vcxproj b/visualc/xspice/digital.vcxproj index b9af0d9a8..b97b08a73 100644 --- a/visualc/xspice/digital.vcxproj +++ b/visualc/xspice/digital.vcxproj @@ -22,30 +22,30 @@ digital {9ABEC5F2-F6C6-41DE-88AB-02460A07F46E} icmanalog - 8.1 + 10.0 DynamicLibrary NotSet - v140 + v142 DynamicLibrary NotSet true - v140 + v142 DynamicLibrary NotSet - v140 + v142 DynamicLibrary MultiByte true - v140 + v142 diff --git a/visualc/xspice/spice2poly.vcxproj b/visualc/xspice/spice2poly.vcxproj index 91b9bb46d..a784b6016 100644 --- a/visualc/xspice/spice2poly.vcxproj +++ b/visualc/xspice/spice2poly.vcxproj @@ -22,30 +22,30 @@ spice2poly {D701EA0E-B8B0-41D6-A90E-A0D8233F15FB} icmanalog - 8.1 + 10.0 DynamicLibrary NotSet - v140 + v142 DynamicLibrary NotSet true - v140 + v142 DynamicLibrary NotSet - v140 + v142 DynamicLibrary MultiByte true - v140 + v142 diff --git a/visualc/xspice/table.vcxproj b/visualc/xspice/table.vcxproj index 165d4484b..d65d404c4 100644 --- a/visualc/xspice/table.vcxproj +++ b/visualc/xspice/table.vcxproj @@ -22,30 +22,30 @@ table {7A6473F5-AFED-4910-88D2-6204DA829832} icmanalog - 8.1 + 10.0 DynamicLibrary NotSet - v140 + v142 DynamicLibrary NotSet true - v140 + v142 DynamicLibrary NotSet - v140 + v142 DynamicLibrary MultiByte true - v140 + v142 diff --git a/visualc/xspice/xtradev.vcxproj b/visualc/xspice/xtradev.vcxproj index e6775e383..3ff05ff78 100644 --- a/visualc/xspice/xtradev.vcxproj +++ b/visualc/xspice/xtradev.vcxproj @@ -22,30 +22,30 @@ xtradev {4BB60215-9A09-4192-9DB6-1A0CA823AFCA} icmanalog - 8.1 + 10.0 DynamicLibrary NotSet - v140 + v142 DynamicLibrary NotSet true - v140 + v142 DynamicLibrary NotSet - v140 + v142 DynamicLibrary MultiByte true - v140 + v142 diff --git a/visualc/xspice/xtraevt.vcxproj b/visualc/xspice/xtraevt.vcxproj index 7bee0be6a..ddba7fde6 100644 --- a/visualc/xspice/xtraevt.vcxproj +++ b/visualc/xspice/xtraevt.vcxproj @@ -22,30 +22,30 @@ xtraevt {13500662-AF0B-4AB6-9AF9-BC3E07B5C1C6} icmanalog - 8.1 + 10.0 DynamicLibrary NotSet - v140 + v142 DynamicLibrary NotSet true - v140 + v142 DynamicLibrary NotSet - v140 + v142 DynamicLibrary MultiByte true - v140 + v142