From 1fa4faf88cf72e96906b2c740f117dd114ffec14 Mon Sep 17 00:00:00 2001 From: h_vogt Date: Wed, 31 Dec 2008 14:42:49 +0000 Subject: [PATCH] tclspice for Windows --- ChangeLog | 10 +++++++ configure.in | 9 ++++++ src/frontend/outitf.c | 13 +++++++-- src/maths/cmaths/Makefile.am | 4 ++- src/misc/alloc.c | 50 +++++++++++++++++++++++++++++++++- src/spicelib/analysis/dctran.c | 7 +++++ src/spicelib/parser/inpfindl.c | 10 +++---- src/tclspice.c | 38 +++++++++++++++++++++++--- src/winmain.c | 15 +++++++--- 9 files changed, 138 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1b19b5110..eebc1f7aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2008-12-31 Holger Vogt + * resource.c: streamline resource info under Windows + * tclspice integration under Windows: dctran.c, inpfindl.c, outitf.c, alloc.c, + tclspice.c, winmain.c: type definitions, printf -> fprintf, + new heap for plot data to prevent memory fragmentation + * configure.in: new flags for TCL under Windows: HAS_TCLWIN + (is set instead of HAS_WINDOWS), TCLWIN (for generating makefiles, + instead of WINDOWS) + * cmath/makefile.am: prevent making test executables under TCL/Windows + 2008-12-26 Dietmar Warning * autogen.sh, configure.in: A hopeful way to integrate adms - ugly, but tested under linux, sunOS and msys with and w/o adms enabled. diff --git a/configure.in b/configure.in index b6eb42f98..9820716eb 100644 --- a/configure.in +++ b/configure.in @@ -274,9 +274,18 @@ dnl dnl The tclSpice options dnl AM_CONDITIONAL(TCL_MODULE, false) +AM_CONDITIONAL(TCLWIN, false) if test "x$with_tcl" != "x" -a "$with_tcl" != "no" ; then AM_CONDITIONAL(TCL_MODULE, true) AC_DEFINE(TCL_MODULE,1,[Tcl Module]) + case $host_os in + *mingw* ) + AM_CONDITIONAL(TCLWIN, true) + AC_DEFINE(HAS_TCLWIN,1,[Tcl Windows]);; + *) + ;; + esac + with_x=no enable_shared=no diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 3efb0815f..f71eb6ca1 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -64,6 +64,13 @@ static void freeRun(runDesc *run); #endif /*saj*/ +/* plot output data shall go into extra heap + to prevent massive memory fragmentation of standard process heap */ +#if defined(_MSC_VER) || defined(__MINGW32__) +#define newrealloc hrealloc +#else +#define newrealloc trealloc +#endif #define DOUBLE_PRECISION 15 @@ -973,12 +980,12 @@ plotAddRealValue(dataDesc *desc, double value) struct dvec *v = desc->vec; if (isreal(v)) { - v->v_realdata = (double *) trealloc((char *) v->v_realdata, + v->v_realdata = (double *) newrealloc((char *) v->v_realdata, sizeof (double) * (v->v_length + 1)); v->v_realdata[v->v_length] = value; } else { /* a real parading as a VF_COMPLEX */ - v->v_compdata = (complex *) trealloc((char *) v->v_compdata, + v->v_compdata = (complex *) newrealloc((char *) v->v_compdata, sizeof (complex) * (v->v_length + 1)); v->v_compdata[v->v_length].cx_real = value; v->v_compdata[v->v_length].cx_imag = (double) 0; @@ -994,7 +1001,7 @@ plotAddComplexValue(dataDesc *desc, IFcomplex value) { struct dvec *v = desc->vec; - v->v_compdata = (complex *) trealloc((char *) v->v_compdata, + v->v_compdata = (complex *) newrealloc((char *) v->v_compdata, sizeof (complex) * (v->v_length + 1)); v->v_compdata[v->v_length].cx_real = value.real; v->v_compdata[v->v_length].cx_imag = value.imag; diff --git a/src/maths/cmaths/Makefile.am b/src/maths/cmaths/Makefile.am index e1aed3964..ab609b386 100644 --- a/src/maths/cmaths/Makefile.am +++ b/src/maths/cmaths/Makefile.am @@ -14,7 +14,8 @@ libcmaths_la_SOURCES = \ cmath4.h ## Test programs fail to build on Windows -if !WINDOWS +if !WINDOWS +if !TCLWIN noinst_PROGRAMS = test_cx_mag test_cx_j test_cx_ph @@ -44,6 +45,7 @@ test_cx_j_LDADD = \ TESTS = test_cx_mag test_cx_j test_cx_ph +endif !TCLWIN endif !WINDOWS diff --git a/src/misc/alloc.c b/src/misc/alloc.c index 6399fd64d..719e673d5 100644 --- a/src/misc/alloc.c +++ b/src/misc/alloc.c @@ -19,6 +19,13 @@ $Id$ //#include #endif + +#if defined(_MSC_VER) || defined(__MINGW32__) +#undef BOOLEAN +#include +extern HANDLE outheap; +#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. */ @@ -81,11 +88,52 @@ trealloc(void *ptr, size_t num) #endif } if (!s) { - fprintf(stderr,"realloc: Internal Error: can't allocate %ld bytes.\n",(long)num); + fprintf(stderr,"realloc: Internal Error: can't allocate %ld bytes.\n", (long)num); + exit(EXIT_BAD); + } + return(s); +} + +/* realloc using the output heap. + Function is used in outitf.c to prevent heap fragmentation + An additional heap outheap is used to store the plot output data. +*/ +#if defined(_MSC_VER) || defined(__MINGW32__) +void * +hrealloc(void *ptr, size_t num) +{ + void *s; +/*saj*/ +#ifdef TCL_MODULE + Tcl_Mutex *alloc; + alloc = Tcl_GetAllocMutex(); +#endif + if (!num) { + if (ptr) + free(ptr); + return NULL; + } + + if (!ptr) + s = HeapAlloc(outheap, HEAP_ZERO_MEMORY, num); + else { +/*saj*/ +#ifdef TCL_MODULE + Tcl_MutexLock(alloc); +#endif + s = HeapReAlloc(outheap, HEAP_ZERO_MEMORY, ptr, num); +/*saj*/ +#ifdef TCL_MODULE + Tcl_MutexUnlock(alloc); +#endif + } + if (!s) { + fprintf(stderr,"HeapReAlloc: Internal Error: can't allocate %ld bytes.\n", (long)num); exit(EXIT_BAD); } return(s); } +#endif diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index bb4e32715..a5a28bf4f 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -324,9 +324,16 @@ DCtran(CKTcircuit *ckt, if(ckt->CKTminBreak==0) ckt->CKTminBreak=ckt->CKTmaxStep*5e-5; firsttime=0; /* To get rawfile working saj*/ + /* get namelist again */ + error = CKTnames(ckt,&numNames,&nameList); + if(error) return(error); + /* get timeUiD again */ + (*(SPfrontEnd->IFnewUid))((void *)ckt,&timeUid,(IFuid)NULL, + "time", UID_OTHER, (void **)NULL); error = (*(SPfrontEnd->OUTpBeginPlot))((void *)ckt, (void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,timeUid,IF_REAL,666,nameList, 666,&(((TRANan*)ckt->CKTcurJob)->TRANplot));/*magic 666 nums as flags */ + tfree(nameList); if(error) { fprintf(stderr, "Couldn't relink rawfile\n"); return error; diff --git a/src/spicelib/parser/inpfindl.c b/src/spicelib/parser/inpfindl.c index e3c8baead..3153a88ae 100644 --- a/src/spicelib/parser/inpfindl.c +++ b/src/spicelib/parser/inpfindl.c @@ -39,16 +39,16 @@ char *INPfindLev(char *line, int *level) sscanf(where, "%2d", level); /* We get the level number */ if (*level < 0) { *level = 1; - printf("Illegal value for level.\n"); - printf("Level must be >0 (Setting level to 1)\n"); + fprintf(stderr,"Illegal value for level.\n"); + fprintf(stderr,"Level must be >0 (Setting level to 1)\n"); return (INPmkTemp (" illegal (negative) argument to level parameter - level=1 assumed")); } if (*level > 99) { /* Limit to change in the future */ *level = 1; - printf("Illegal value for level.\n"); - printf("Level must be <99 (Setting Level to 1)\n"); + fprintf(stderr,"Illegal value for level.\n"); + fprintf(stderr,"Level must be <99 (Setting Level to 1)\n"); return (INPmkTemp (" illegal (too high) argument to level parameter - level=1 assumed")); } @@ -60,7 +60,7 @@ char *INPfindLev(char *line, int *level) else { /* no level on the line => default */ *level = 1; - printf("Warning -- Level not specified on line \"%s\"\nUsing level 1.\n", line); + fprintf(stderr,"Warning -- Level not specified on line \"%s\"\nUsing level 1.\n", line); return ((char *) NULL); } diff --git a/src/tclspice.c b/src/tclspice.c index ebd607fb6..9e32f027d 100755 --- a/src/tclspice.c +++ b/src/tclspice.c @@ -177,6 +177,13 @@ do {\ spice_interp = interp;\ } while(0) + +/* global handle for the output heap */ +#if defined(_MSC_VER) || defined(__MINGW32__) +HANDLE outheap; +#endif + + /****************************************************************************/ /* BLT and data routines */ /****************************************************************************/ @@ -601,26 +608,33 @@ static threadId_t tid, bgtid=(threadId_t)0; static bool fl_running = FALSE; static bool fl_exited = TRUE; - -static void *_thread_run(void *string){ +#if defined(__MINGW32__) || defined(_MSC_VER) +static void * WINAPI _thread_run(void *string){ +#else +static void * _thread_run(void *string){ +#endif fl_exited = FALSE; bgtid = thread_self(); cp_evloop((char *)string); FREE(string); bgtid = (threadId_t)0; fl_exited = TRUE; - return 0; + return; } /*Stops a running thread, hopefully */ +#if defined(__MINGW32__) || defined(_MSC_VER) +static int WINAPI _thread_stop(){ +#else static int _thread_stop(){ +#endif int timeout = 0; if(fl_running) { while(!fl_exited && timeout < 100){ ft_intrpt = TRUE; timeout++; #if defined(__MINGW32__) || defined(_MSC_VER) - Sleep(10); /* va: windows native */ + Sleep(100); /* va: windows native */ #else usleep(10000); #endif @@ -663,12 +677,17 @@ static int _run(int argc,char **argv){ } #endif + /* Catch Ctrl-C to break simulations */ +#ifndef _MSC_VER_ oldHandler = signal(SIGINT,ft_sigintr); if(SETJMP(jbuf, 1)!=0) { signal(SIGINT,oldHandler); return TCL_OK; } +#else + oldHandler = SIG_IGN; +#endif /*build a char * to pass to cp_evloop */ for(i=0;i------------------------------ // Alle Puffer loeschen und Zeiger auf den Anfang setzen @@ -844,10 +847,16 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLi UpdateWindow( hwMain); SetFocus( swString); - status = MakeArgcArgv(lpszCmdLine,&argc,&argv); + status = MakeArgcArgv(lpszCmdLine,&argc,&argv); + /* create private heap for current process */ + outheap = HeapCreate(0, 10000000, 0); + if (!outheap) { + fprintf(stderr,"HeapCreate: Internal Error: can't allocate private output heap"); + exit(1); + } - // Warten, bis alles klar ist + // Wait util everything is settled WaitForIdle(); // Ab nach main() @@ -855,8 +864,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLi THE_END: - // 3D abschalten -// Ctl3dUnregister( hInstance); // terminate return nReturnCode;