diff --git a/ChangeLog b/ChangeLog index 082b93ad7..0b0f0ae4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2003-07-18 Vera Albrecht + + * src/{main.c,tclspice.c} + src/frontend/{Makefile.am,control.c,control.h,display.c,dotcards.c, + hcomp.c,hpgl.c,outitf.c,parse.c,postcoms.c,postsc.c,runcoms.c, + spiceif.c,variable.c,variable.h,parser/complete.c,plotting/pvec.c} + src/include/{cktdefs.h,ngspice.h} + src/misc/{ivars.c,string.c,stringutil.h} + src/spicelib/analysis/{acan.c,ckt.h,dcop.c} + src/spicelib/devices/bsim3/b3temp.c + src/spicelib/parser/{ifnewuid.c,inp2dot.c,inperror.c} : + Memory leaks and some WINDOWS compile fixes. + 2003-07-17 Stefan Jones * src/frontend/{subckt.c,vectors.c} diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am index e5e96e2f3..f6ce27204 100644 --- a/src/frontend/Makefile.am +++ b/src/frontend/Makefile.am @@ -157,7 +157,8 @@ libfte_a_SOURCES = \ vectors.c \ vectors.h \ where.c \ - where.h + where.h \ + hpgl.c # TESTS = testcommands # diff --git a/src/frontend/control.c b/src/frontend/control.c index 7b1a3e403..aba974a9a 100644 --- a/src/frontend/control.c +++ b/src/frontend/control.c @@ -47,6 +47,14 @@ int stackp = 0; * blown away every time we return -- probably every time we type * source at the keyboard and every time a source returns to keyboard * input is ok though -- use ft_controlreset. */ + + /* Notes by CDHW: + * This routine leaked like a sieve because each getcommand() created a + * wordlist that was never freed because it might have been added into + * the control structure. I've tackled this by making sure that everything + * put into the cend[stackp] is a copy. This means that wlist can be + * destroyed safely + */ static char *noredirect[] = { "stop", NULL } ; /* Only one?? */ @@ -79,6 +87,37 @@ pwlist(wordlist *wlist, char *name) } +/* CDHW defined functions */ + +static void +pwlist_echo(wlist, name) /*CDHW used to perform function of set echo */ + wordlist *wlist; + char *name; +{ + wordlist *wl; + + if ((!cp_echo)||cp_debug) /* cpdebug prints the same info */ + return; + fprintf(cp_err, "%s ", name); + for (wl = wlist; wl; wl = wl->wl_next) + fprintf(cp_err, "%s ", wl->wl_word); + fprintf(cp_err, "\n"); + return; +} + +/*CDHW Remove control structure and free the memory its hogging CDHW*/ + +void ctl_free(struct control *ctrl) { + if (!ctrl) return; + wl_free(ctrl->co_cond); ctrl->co_cond = NULL; + tfree(ctrl->co_foreachvar); ctrl->co_foreachvar = NULL; + wl_free(ctrl->co_text); ctrl->co_text = NULL; + ctl_free(ctrl->co_children); ctrl->co_children = NULL; + ctl_free(ctrl->co_elseblock); ctrl->co_elseblock = NULL; + ctl_free(ctrl->co_next); ctrl->co_next = NULL; + tfree(ctrl); ctrl = NULL; +} + /* Note that we only do io redirection when we get to here - we also * postpone some other things until now. */ @@ -108,8 +147,10 @@ docommand(wordlist *wlist) wlist = cp_doglob(wlist); pwlist(wlist, "After globbing"); + + pwlist_echo(wlist, "Becomes >"); - if (!wlist || !wlist->wl_word) + if (!wlist || !wlist->wl_word) /*CDHW need to free wlist in second case? CDHW*/ return; /* Now loop through all of the commands given. */ @@ -185,7 +226,7 @@ docommand(wordlist *wlist) for (wl = wlist->wl_next; wl; wl = wl->wl_next) nargs++; if (command->co_stringargs) { - lcom = wl_flatten(wlist->wl_next); + lcom = wl_flatten(wlist->wl_next); /*CDHW lcom will need freeing CDHW*/ (*command->co_func) ((void *)(lcom)); } else { if (nargs < command->co_minargs) { @@ -196,8 +237,9 @@ docommand(wordlist *wlist) } } else if (nargs > command->co_maxargs) { fprintf(cp_err, "%s: too many args.\n", s); - } else + } else { (*command->co_func) (wlist->wl_next); + } } /* Now fix the pointers and advance wlist. */ @@ -241,10 +283,17 @@ doblock(struct control *bl, int *num) wordlist *wl; char *i; int nn; - + + nn = *num + 1 ; /*CDHW this is a guess... CDHW*/ + switch (bl->co_type) { case CO_WHILE: + if (!bl->co_children) { + fprintf(cp_err, "Warning: Executing empty 'while' block.\n"); + fprintf(cp_err, " (Use a label statement as a no-op to suppress this warning.)\n"); + } while (bl->co_cond && cp_istrue(bl->co_cond)) { + if (!bl->co_children) cp_periodic(); /*CDHW*/ for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); @@ -316,10 +365,21 @@ doblock(struct control *bl, int *num) break; case CO_REPEAT: - while ((bl->co_numtimes > 0) || - (bl->co_numtimes == -1)) { + if (!bl->co_children) { + fprintf(cp_err, "Warning: Executing empty 'repeat' block.\n"); + fprintf(cp_err, " (Use a label statement as a no-op to suppress this warning.)\n"); + } + if (!bl->co_timestodo) bl->co_timestodo = bl->co_numtimes; + /*...CDHW*/ + while ((bl->co_timestodo > 0) || + (bl->co_timestodo == -1)) { if (bl->co_numtimes != -1) bl->co_numtimes--; + + if (!bl->co_children) cp_periodic(); /*CDHW*/ + + if (bl->co_timestodo != -1) bl->co_timestodo--; + for (ch = bl->co_children; ch; ch = cn) { cn = ch->co_next; i = doblock(ch, &nn); @@ -447,11 +507,12 @@ doblock(struct control *bl, int *num) case CO_GOTO: wl = cp_variablesubst(cp_bquote(cp_doglob( - wl_copy(bl->co_text)))); + wl_copy(bl->co_text)))); /*CDHW Leak ? CDHW*/ return (wl->wl_word); case CO_LABEL: /* Do nothing. */ + cp_periodic(); /*CDHW needed to avoid lock-ups when loop contains only a label CDHW*/ break; case CO_STATEMENT: @@ -511,7 +572,7 @@ getcommand(char *string) return (wlist); } - +/* va: TODO: free control structure(s) before overwriting (memory leakage) */ int cp_evloop(char *string) { @@ -556,7 +617,9 @@ cp_evloop(char *string) /* Add this to the control structure list. If cend->co_type is * CO_UNFILLED, the last line was the beginning of a block, - * and this is the unfilled first statement. */ + * and this is the unfilled first statement. + */ + /* va: TODO: free old structure and its content, before overwriting */ if (cend[stackp] && (cend[stackp]->co_type != CO_UNFILLED)) { cend[stackp]->co_next = alloc(struct control); ZERO(cend[stackp]->co_next, struct control); @@ -574,15 +637,16 @@ cp_evloop(char *string) cend[stackp]->co_cond = wlist->wl_next; if (!cend[stackp]->co_cond) { fprintf(stderr, - "Error: missing while condition.\n"); + "Error: missing while condition, 'false' will be assumed.\n"); } newblock; } else if (eq(wlist->wl_word, "dowhile")) { cend[stackp]->co_type = CO_DOWHILE; cend[stackp]->co_cond = wlist->wl_next; if (!cend[stackp]->co_cond) { + /* va: prevent misinterpretation as trigraph sequence with \-sign */ fprintf(stderr, - "Error: missing dowhile condition.\n"); + "Error: missing dowhile condition, '?\?\?' will be assumed.\n"); } newblock; } else if (eq(wlist->wl_word, "repeat")) { @@ -592,10 +656,11 @@ cp_evloop(char *string) } else { char *s; double *dd; - wlist = cp_variablesubst(cp_bquote( - cp_doglob(wl_copy(wlist)))); - s = wlist->wl_next->wl_word; - + struct wordlist *t; /*CDHW*/ + /*CDHW wlist = cp_variablesubst(cp_bquote(cp_doglob(wl_copy(wlist)))); Wrong order? Leak? CDHW*/ + t = cp_doglob(cp_bquote(cp_variablesubst(wl_copy(wlist)))); /*CDHW leak from cp_doglob? */ + s = t->wl_next->wl_word; + dd = ft_numparse(&s, FALSE); if (dd) { if (*dd < 0) { @@ -607,7 +672,8 @@ cp_evloop(char *string) } else fprintf(cp_err, "Error: bad repeat argument %s\n", - wlist->wl_next->wl_word); + t->wl_next->wl_word); /* CDHW */ + wl_free(t); t = NULL; /* CDHW */ } newblock; } else if (eq(wlist->wl_word, "if")) { @@ -618,6 +684,7 @@ cp_evloop(char *string) "Error: missing if condition.\n"); } newblock; + } else if (eq(wlist->wl_word, "foreach")) { cend[stackp]->co_type = CO_FOREACH; if (wlist->wl_next) { @@ -628,7 +695,7 @@ cp_evloop(char *string) } else fprintf(stderr, "Error: missing foreach variable.\n"); - wlist = cp_doglob(wlist); + wlist = cp_doglob(wlist); /*CDHW Possible leak around here? */ cend[stackp]->co_text = wl_copy(wlist); newblock; } else if (eq(wlist->wl_word, "label")) { @@ -642,6 +709,7 @@ cp_evloop(char *string) "Warning: ignored extra junk after label.\n"); } else fprintf(stderr, "Error: missing label.\n"); + } else if (eq(wlist->wl_word, "goto")) { /* Incidentally, this won't work if the values 1 and 2 ever get * to be valid character pointers -- I think it's reasonably @@ -685,12 +753,12 @@ cp_evloop(char *string) cend[stackp]->co_prev->co_next = NULL; x = cend[stackp]; cend[stackp] = cend[stackp]->co_parent; - tfree(x); + tfree(x); x=NULL; } else { x = cend[stackp]; cend[stackp] = cend[stackp]->co_parent; cend[stackp]->co_children = NULL; - tfree(x); + tfree(x); x=NULL; } } else if (eq(wlist->wl_word, "else")) { if (!cend[stackp]->co_parent || @@ -708,14 +776,15 @@ cp_evloop(char *string) } } else { cend[stackp]->co_type = CO_STATEMENT; - cend[stackp]->co_text = wlist; + cend[stackp]->co_text = wl_copy(wlist); } + if (!cend[stackp]->co_parent) { x = cend[stackp]; /* We have to toss this do-while loop in here so * that gotos at the top level will work. */ - do { + do { nn = 0; /* CDHW */ i = doblock(x, &nn); switch (*i) { case NORMAL: @@ -737,15 +806,20 @@ cp_evloop(char *string) x = x->co_next; } while (x); } - if (string) + wl_free(wlist); wlist = NULL; + if (string) { return (1); /* The return value is irrelevant. */ + } } + wl_free(wlist); wlist = NULL; + return (0); /* va: which value? */ } /* This blows away the control structures... */ void cp_resetcontrol(void) { + fprintf(cp_err, "Warning: clearing control structures\n"); if (cend[stackp] && cend[stackp]->co_parent) fprintf(cp_err, "Warning: EOF before block terminated\n"); /* We probably should free the control structures... */ @@ -764,8 +838,9 @@ cp_popcontrol(void) fprintf(cp_err, "pop: stackp: %d -> %d\n", stackp, stackp - 1); if (stackp < 1) fprintf(cp_err, "cp_popcontrol: Internal Error: stack empty\n"); - else + else { stackp--; + } return; } @@ -797,5 +872,3 @@ cp_toplevel(void) cend[stackp] = cend[stackp]->co_parent; return; } - - diff --git a/src/frontend/control.h b/src/frontend/control.h index 7b5132193..c2982a837 100644 --- a/src/frontend/control.h +++ b/src/frontend/control.h @@ -14,6 +14,7 @@ struct control { wordlist *co_cond; /* if, while, dowhile */ char *co_foreachvar; /* foreach */ int co_numtimes; /* repeat, break & continue levels */ + int co_timestodo; wordlist *co_text; /* Ordinary text and foreach values. */ struct control *co_parent; /* If this is inside a block. */ struct control *co_children; /* The contents of this block. */ diff --git a/src/frontend/display.c b/src/frontend/display.c index 75a93f2af..2e1ca4f82 100644 --- a/src/frontend/display.c +++ b/src/frontend/display.c @@ -24,8 +24,6 @@ static int nop(void); static int nodev(void); - - #ifndef X_DISPLAY_MISSING extern int X11_Init(void), X11_NewViewport(GRAPH *graph), X11_Close(void), X11_Clear(void), X11_DrawLine(int x1, int y1, int x2, int y2), X11_Arc(int x0, int y0, int radius, double theta1, double theta2), X11_Text(char *text, int x, int y), X11_DefineColor(int colorid, double red, double green, double blue), @@ -34,9 +32,17 @@ extern int X11_Init(void), X11_NewViewport(GRAPH *graph), X11_Close(void), X11_ X11_Input(REQUEST *request, RESPONSE *response); #endif +#ifdef HAS_WINDOWS /* Grafik-IO über MS Windows */ +extern int WIN_Init(), WIN_NewViewport(), WIN_Close(), WIN_Clear(), + WIN_DrawLine(), WIN_Arc(), WIN_Text(), WIN_DefineColor(), + WIN_DefineLinestyle(), WIN_SetLinestyle(), WIN_SetColor(), + WIN_Update(), WIN_DiagramReady(); - - +extern int WPRINT_Init(), WPRINT_NewViewport(), WPRINT_Close(), WPRINT_Clear(), + WPRINT_DrawLine(), WPRINT_Arc(), WPRINT_Text(), WPRINT_DefineColor(), + WPRINT_DefineLinestyle(), WPRINT_SetLinestyle(), WPRINT_SetColor(), + WPRINT_Update(), WPRINT_DiagramReady(); +#endif extern int Plt5_Init(void), Plt5_NewViewport(GRAPH *graph), Plt5_Close(void), Plt5_Clear(void), Plt5_DrawLine(int x1, int y1, int x2, int y2), Plt5_Arc(int x0, int y0, int radius, double theta1, double theta2), Plt5_Text(char *text, int x, int y), @@ -48,6 +54,11 @@ extern int PS_Init(void), PS_NewViewport(GRAPH *graph), PS_Close(void), PS_Clea PS_DefineLinestyle(), PS_SetLinestyle(int linestyleid), PS_SetColor(int colorid), PS_Update(void); +extern int GL_Init(void), GL_NewViewport(GRAPH *graph), GL_Close(void), GL_Clear(void), + GL_DrawLine(int x1, int y1, int x2, int y2), GL_Arc(int x0, int y0, int r, double theta1, double theta2), GL_Text(char *text, int x, int y), + GL_DefineLinestyle(), GL_SetLinestyle(int linestyleid), GL_SetColor(int colorid), + GL_Update(void); + DISPDEVICE device[] = { {"error", 0, 0, 0, 0, 0, 0, nop, nop, @@ -66,6 +77,23 @@ DISPDEVICE device[] = { gen_DatatoScreen,}, #endif +#ifdef HAS_WINDOWS /* Grafik-IO über MS Windows */ + {"Windows", 0, 0, 1000, 1000, 0, 0, WIN_Init, WIN_NewViewport, + WIN_Close, WIN_Clear, + WIN_DrawLine, WIN_Arc, WIN_Text, WIN_DefineColor, WIN_DefineLinestyle, + WIN_SetLinestyle, WIN_SetColor, WIN_Update, + nodev, nodev, nodev, gen_Input, + gen_DatatoScreen, WIN_DiagramReady}, + + // Achtung: Namen "WinPrint" nicht ändern! + {"WinPrint", 0, 0, 1000, 1000, 0, 0, WPRINT_Init, WPRINT_NewViewport, + WPRINT_Close, WPRINT_Clear, + WPRINT_DrawLine, WPRINT_Arc, WPRINT_Text, WPRINT_DefineColor, WPRINT_DefineLinestyle, + WPRINT_SetLinestyle, WPRINT_SetColor, WPRINT_Update, + nodev, nodev, nodev, nodev, + gen_DatatoScreen, WPRINT_DiagramReady}, +#endif + #ifdef TCL_MODULE {"Tk", 0, 0, 1024, 864, 0, 0, sp_Tk_Init, sp_Tk_NewViewport, sp_Tk_Close, sp_Tk_Clear, @@ -89,6 +117,13 @@ DISPDEVICE device[] = { nodev, nodev, nodev, nodev, gen_DatatoScreen,}, + {"hpgl", 0, 0, 1000, 1000, 0, 0, GL_Init, GL_NewViewport, + GL_Close, GL_Clear, + GL_DrawLine, GL_Arc, GL_Text, nodev, nodev, + GL_SetLinestyle, GL_SetColor, GL_Update, + nodev, nodev, nodev, nodev, + gen_DatatoScreen,}, + {"printf", 0, 0, 24, 80, 0, 0, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, nodev, @@ -99,6 +134,7 @@ DISPDEVICE device[] = { }; DISPDEVICE *dispdev = device + NUMELEMS(device) - 1; +// DISPDEVICE *dispdev = device ; /* GCC257 stuertzt hier ab */ #define XtNumber(arr) (sizeof(arr) / sizeof(arr[0])) @@ -124,8 +160,9 @@ DISPDEVICE *FindDev(char *name) void DevInit(void) { - - char buf[128]; +#ifndef X_DISPLAY_MISSING + char buf[128]; /* va: used with NOT X_DISPLAY_MISSING only */ +#endif /* X_DISPLAY_MISSING */ /* note: do better determination */ @@ -139,10 +176,13 @@ DevInit(void) #ifndef X_DISPLAY_MISSING /* determine display type */ if (getenv("DISPLAY") || cp_getvar("display", VT_STRING, buf)) { - -#ifndef X_DISPLAY_MISSING dispdev = FindDev("X11"); + } #endif + +#ifdef HAS_WINDOWS + if (!dispdev) { + dispdev = FindDev("Windows"); } #endif @@ -159,7 +199,6 @@ DevInit(void) "Warning: can't initialize display device for graphics.\n"); dispdev = FindDev("error"); } - } /* NewViewport is responsible for filling in graph->viewport */ diff --git a/src/frontend/dotcards.c b/src/frontend/dotcards.c index 620af5462..14c87c5e4 100644 --- a/src/frontend/dotcards.c +++ b/src/frontend/dotcards.c @@ -380,7 +380,7 @@ ft_cktcoms(bool terse) static void fixdotplot(wordlist *wl) { - char buf[BSIZE_SP], *s; + char *s; char numbuf[128]; /* Printnum Fix */ double *d, d1, d2; diff --git a/src/frontend/hcomp.c b/src/frontend/hcomp.c index 657296618..6319fc7a5 100644 --- a/src/frontend/hcomp.c +++ b/src/frontend/hcomp.c @@ -1,4 +1,5 @@ #include +#include int hcomp(const void *a, const void *b) diff --git a/src/frontend/hpgl.c b/src/frontend/hpgl.c new file mode 100644 index 000000000..a2259ab5e --- /dev/null +++ b/src/frontend/hpgl.c @@ -0,0 +1,315 @@ +/********** +Author: Jim Groves +**********/ + +/* + HPGL driver +*/ + +/* + 1000 plotter units / inch - 1pu = 0.025mm 1pu = 1mil + + SP - select pen + PU - pen up (PU x,y) + PD - pen down (PD x,y) + LT - line type + 0 dots only at plotted points + 1 . . . . . + 2 ___ ___ ___ ___ + 3 ---- ---- ---- ---- + 4 ----- . ----- . ----- . -----. + 5 ---- - ---- - ---- - + 6 --- - - --- - - --- - - --- - - + null - solid line + IN - initialize + DF - default values (PA, solid line, set 0) + PA - plot absolute + SI - absolute character size (SI width, height) in cm + +*/ + + + +#include "ngspice.h" +#include "cpdefs.h" +#include "graph.h" +#include "ftedbgra.h" +#include "ftedev.h" +#include "fteinput.h" + +#include "variable.h" + +#define RAD_TO_DEG (180.0 / M_PI) +#define DEVDEP(g) (*((GLdevdep *) (g)->devdep)) +#define MAX_GL_LINES 9999 +#define SOLID 0 +#define DOTTED 1 + +#define gtype graph->grid.gridtype +#define xoff dispdev->minx +#define yoff dispdev->miny +#define XOFF 25 /* printer left margin */ +#define YOFF 28 /* printer bottom margin */ +#define XTADJ 0 /* printer text adjustment x */ +#define YTADJ 0 /* printer text adjustment y */ + +#define DELXMAX 360 /* printer gridsize divisible by 10, [7-2] */ +#define DELYMAX 360 /* printer gridsize divisible by [10-8], [6-2] */ + +#define FONTWIDTH 6 /* printer default fontwidth */ +#define FONTHEIGHT 8 /* printer default fontheight */ + +typedef struct { + int lastlinestyle; /* initial invalid value */ + int lastx, lasty, linecount; +} GLdevdep; + +static char *linestyle[] = { + "", /* solid */ + "1", /* was 1 - dotted */ + "", /* longdashed */ + "3", /* shortdashed */ + "4", /* longdotdashed */ + "5", /* shortdotdashed */ + "1" + }; + +static FILE *plotfile; +char psfont[128], psfontsize[32], psscale[32]; +static int fontwidth = FONTWIDTH; +static int fontheight = FONTHEIGHT; +static int jgmult = 10; +static int screenflag = 0; +static double tocm = 0.0025; +static double scale; /* Used for fine tuning */ +static int hcopygraphid; + +extern int DestroyGraph (int id); +extern void internalerror (char *message); + +int GL_Init() +{ + if (!cp_getvar("hcopyscale", VT_STRING, psscale)) { + scale = 1.0; + } else { + sscanf(psscale, "%lf", &scale); + if ((scale <= 0) || (scale > 10)) + scale = 1.0; + } + + dispdev->numlinestyles = NUMELEMS(linestyle); + dispdev->numcolors = 6; + + dispdev->width = DELXMAX * scale; + dispdev->height = DELYMAX * scale; + + + screenflag = 0; + dispdev->minx = XOFF * 1.0; + dispdev->miny = YOFF * 1.0; + + return(0); + +} + +/* devdep initially contains name of output file */ +int GL_NewViewport(graph) +GRAPH *graph; +{ +/* double scaleps, scalex, scaley; */ + + hcopygraphid = graph->graphid; + + if (!(plotfile = fopen(graph->devdep, "w"))) { + perror(graph->devdep); + graph->devdep = (char *) NULL; + return(1); + } + + if (graph->absolute.width) { + /* hardcopying from the screen */ + + screenflag = 1; + + /* scale to fit on 8 1/2 square */ + + } + + /* reasonable values, used in gr_ for placement */ + graph->fontwidth = fontwidth * scale; /* was 12, p.w.h. */ + graph->fontheight = fontheight * scale; /* was 24, p.w.h. */ + + graph->absolute.width = dispdev->width; + graph->absolute.height = dispdev->height; + /* Also done in gr_init, if called . . . */ + graph->viewportxoff = 16 * fontwidth; + graph->viewportyoff = 8 * fontheight; + + xoff = XOFF; + yoff = YOFF; + + /* start file off with a % */ + fprintf(plotfile, "IN;DF;PA;"); + fprintf(plotfile, "SI %f,%f;", tocm*jgmult*fontwidth*scale,tocm*jgmult*fontheight*scale); + +#ifdef notdef + if (!screenflag) +#endif + + graph->devdep = tmalloc(sizeof(GLdevdep)); + DEVDEP(graph).lastlinestyle = -1; + DEVDEP(graph).lastx = -1; + DEVDEP(graph).lasty = -1; + DEVDEP(graph).linecount = 0; + graph->linestyle = -1; + + return 0; +} + +int GL_Close() +{ + + /* in case GL_Close is called as part of an abort, + w/o having reached GL_NewViewport */ + if (plotfile) { + if (DEVDEP(currentgraph).lastlinestyle != -1) { + DEVDEP(currentgraph).linecount = 0; + } + fclose(plotfile); + plotfile = NULL; + } + /* In case of hardcopy command destroy the hardcopy graph + * and reset currentgraph to graphid 1, if possible + */ + if (!screenflag) { + DestroyGraph(hcopygraphid); + currentgraph = FindGraph(1); + } + + return 0; +} + +int GL_Clear() +{ + + /* do nothing */ + + + return 0; +} + +int GL_DrawLine(x1, y1, x2, y2) +int x1, y1, x2, y2; +{ + + /* note: this is not extendible to more than one graph + => will have to give NewViewport a writeable graph XXX */ + + + if (DEVDEP(currentgraph).linecount == 0 + || x1 != DEVDEP(currentgraph).lastx + || y1 != DEVDEP(currentgraph).lasty) + { + fprintf(plotfile, "PU;PA %d , %d ;", jgmult*(x1 + xoff), jgmult*(y1 + yoff)); + } + if (x1 != x2 || y1 != y2) { + fprintf(plotfile, "PD;PA %d , %d ;", jgmult*(x2 + xoff), jgmult*(y2 + yoff)); + DEVDEP(currentgraph).linecount += 1; + } + + DEVDEP(currentgraph).lastx = x2; + DEVDEP(currentgraph).lasty = y2; + DEVDEP(currentgraph).lastlinestyle = currentgraph->linestyle; + + return 0; +} + +/* ARGSUSED */ +int GL_Arc(x0, y0, r, theta1, theta2) +int x0, y0, r; +double theta1, theta2; +{ + double x1, y1; + double angle1, angle2; + + while (theta1 >= theta2) + theta2 += 2 * M_PI; + + angle1 = (double) (RAD_TO_DEG * theta1); + angle2 = (double) (RAD_TO_DEG * theta2); + x1 = (double) x0 + r * cos(theta1); + y1 = (double) y0 + r * sin(theta1); +/* + fprintf(plotfile, "%lf %lf moveto ", x1+(double)xoff, y1+(double)yoff); + fprintf(plotfile, "%d %d %d %lf %lf arc\n", x0+xoff, y0+yoff, r, + angle1, angle2); + fprintf(plotfile, "stroke\n"); + */ + DEVDEP(currentgraph).linecount = 0; + + return 0; +} + +int GL_Text(text, x, y) +char *text; +int x, y; +{ + +/* int savedlstyle; */ + + + /* move to (x, y) */ + + fprintf(plotfile, "PU;PA %d , %d;", jgmult*(x+xoff+XTADJ), jgmult*(y+yoff+YTADJ)); + fprintf(plotfile, "LB %s \x03", text); + + DEVDEP(currentgraph).lastx = -1; + DEVDEP(currentgraph).lasty = -1; + + + return 0; +} + +int +GL_SetLinestyle(linestyleid) +int linestyleid; +{ + + /* special case + get it when GL_Text restores a -1 linestyle */ + if (linestyleid == -1) { + currentgraph->linestyle = -1; + return 0; + } + + if (linestyleid < 0 || linestyleid > dispdev->numlinestyles) { + internalerror("bad linestyleid"); + return 0; + } + + if (currentgraph->linestyle != linestyleid) { + fprintf(plotfile, "LT %s ;", linestyle[linestyleid]); + currentgraph->linestyle = linestyleid; + } + return 0; + +} + +/* ARGSUSED */ +int GL_SetColor(colorid) +int colorid; +{ +/*va: unused: static int flag = 0;*/ /* A hack */ + + fprintf(plotfile, "SP %d;", colorid); + + return 0; +} + +int GL_Update() +{ + + fflush(plotfile); + + return 0; +} diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index f33cfbb85..04378097e 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -337,10 +337,8 @@ beginPlot(void *analysisPtr, void *circuitPtr, char *cktName, char *analName, ch } if (numNames && - (run->numData == 1 - && run->refIndex != -1 - || run->numData == 0 - && run->refIndex == -1)) + ( (run->numData == 1 && run->refIndex != -1) + || (run->numData == 0 && run->refIndex == -1))) { fprintf(cp_err, "Error: no data saved for %s; analysis not run\n", spice_analysis_get_description(((JOB *) analysisPtr)->JOBtype)); diff --git a/src/frontend/parse.c b/src/frontend/parse.c index 21b8fb016..e59da1f44 100644 --- a/src/frontend/parse.c +++ b/src/frontend/parse.c @@ -27,7 +27,7 @@ static struct pnode * mkunode(int op, struct pnode *arg); static struct pnode * mkfnode(char *func, struct pnode *arg); static struct pnode * mknnode(double number); static struct pnode * mksnode(char *string); -static void print_elem(struct element *elem); /* va: for debugging */ +void print_elem(struct element *elem); /* va: for debugging */ static int lasttoken = END, lasttype; @@ -557,7 +557,7 @@ makepnode(struct element *elem) } } -static void print_elem(struct element *elem) +void print_elem(struct element *elem) { printf("e_token = %d", elem->e_token); if (elem->e_token == VALUE) { diff --git a/src/frontend/parser/complete.c b/src/frontend/parser/complete.c index 8e4e0d082..6d1d0221e 100644 --- a/src/frontend/parser/complete.c +++ b/src/frontend/parser/complete.c @@ -125,6 +125,9 @@ cp_ccom(wordlist *wlist, char *buf, bool esc) pmatches = ccmatch(buf, &commands); i = strlen(buf); } + + tfree(buf); /*CDHW*/ + if (!esc) { printem(pmatches); wl_free(pmatches); @@ -574,10 +577,12 @@ cp_ccrestart(bool kwords) void throwaway(struct ccom *dbase) { + if (!dbase) return; /* va: security first */ if (dbase->cc_child) throwaway(dbase->cc_child); if (dbase->cc_sibling) throwaway(dbase->cc_sibling); + tfree(dbase->cc_name); /* va: also tfree dbase->cc_name (memory leak) */ tfree(dbase); return; } @@ -727,8 +732,8 @@ cdelete(struct ccom *node, struct ccom **top) /* now free() everything and check the top */ if (node == *top) *top = node->cc_sibling; - free(node->cc_name); - free(node); + tfree(node->cc_name); /* va: we should allways use tfree */ + tfree(node); return; } diff --git a/src/frontend/plotting/pvec.c b/src/frontend/plotting/pvec.c index b4584c861..0b38041c0 100644 --- a/src/frontend/plotting/pvec.c +++ b/src/frontend/plotting/pvec.c @@ -49,6 +49,7 @@ pvec(struct dvec *d) break; default: + break; } switch (d->v_plottype) { @@ -62,6 +63,7 @@ pvec(struct dvec *d) break; default: + break; } if (d->v_defcolor) { sprintf(buf2, ", color = %s", d->v_defcolor); diff --git a/src/frontend/postcoms.c b/src/frontend/postcoms.c index 15ee068f4..39ab9ea81 100644 --- a/src/frontend/postcoms.c +++ b/src/frontend/postcoms.c @@ -18,6 +18,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include "postcoms.h" #include "quote.h" #include "variable.h" +#include "parser/complete.h" /* static declarations */ static void killplot(struct plot *pl); @@ -609,10 +610,12 @@ killplot(struct plot *pl) fprintf(cp_err, "Error: can't destroy the constant plot\n"); return; } + /* pl_dvecs, pl_scale */ for (v = pl->pl_dvecs; v; v = nv) { nv = v->v_next; vec_free(v); } + /* unlink from plot_list (linked via pl_next) */ if (pl == plot_list) { plot_list = pl->pl_next; if (pl == plot_cur) @@ -632,9 +635,17 @@ killplot(struct plot *pl) tfree(pl->pl_name); tfree(pl->pl_typename); wl_free(pl->pl_commands); - - /* Never mind about the rest... */ - + tfree(pl->pl_date); /* va: also tfree (memory leak) */ + if (pl->pl_ccom) /* va: also tfree (memory leak) */ + { + throwaway((struct ccom *)pl->pl_ccom); + } + if (pl->pl_env) /* The 'environment' for this plot. */ + { + /* va: HOW to do? */ + printf("va: killplot should tfree pl->pl_env=(%p)\n", pl->pl_env); fflush(stdout); + } + tfree(pl); /* va: also tfree pl itself (memory leak) */ return; } diff --git a/src/frontend/postsc.c b/src/frontend/postsc.c index d736b71bc..abb974d53 100644 --- a/src/frontend/postsc.c +++ b/src/frontend/postsc.c @@ -39,7 +39,7 @@ Author: 1988 Jeffrey M. Hsu #define FONTHEIGHT 14 /* printer default fontheight */ typedef struct { - int lastlinestyle; /* initial invalid value */ + int lastlinestyle, lastcolor; /* initial invalid value */ int lastx, lasty, linecount; } PSdevdep; @@ -56,11 +56,12 @@ static char *linestyle[] = { }; static FILE *plotfile; -char psfont[128], psfontsize[32], psscale[32]; +char psfont[128], psfontsize[32], psscale[32], pscolor[32]; static int fontsize = FONTSIZE; static int fontwidth = FONTWIDTH; static int fontheight = FONTHEIGHT; static int screenflag = 0; +static int colorflag = 0; static double scale; /* Used for fine tuning */ static int xtadj; /* text adjustment x */ static int ytadj; /* text adjustment y */ @@ -68,12 +69,16 @@ static int hcopygraphid; extern int DestroyGraph (int id); -int PS_SetLinestyle (int linestyleid); extern void internalerror (char *message); +void PS_LinestyleColor(int linestyleid, int colorid); +void PS_SelectColor(int colorid); +void PS_Stroke(void); int PS_Init(void) { + char pswidth[30], psheight[30]; + if (!cp_getvar("hcopyscale", VT_STRING, psscale)) { scale = 1.0; } else { @@ -82,11 +87,35 @@ PS_Init(void) scale = 1.0; } - dispdev->numlinestyles = NUMELEMS(linestyle); + if (!cp_getvar("hcopypscolor", VT_STRING, pscolor)) { + colorflag = 0; dispdev->numcolors = 2; + dispdev->numlinestyles = NUMELEMS(linestyle); + } else { + colorflag = 1; + dispdev->numcolors = 18; /* don't know what the maximum should be */ + dispdev->numlinestyles = 1; + } + pscolor[0]='\0'; + if (!cp_getvar("hcopywidth", VT_STRING, pswidth)) { dispdev->width = 7.75 * 72.0 * scale; /* (8 1/2 - 3/4) * 72 */ + } else { + sscanf(pswidth, "%d", &(dispdev->width)); + if (dispdev->width <= 100) + dispdev->width = 100; + if (dispdev->width >= 10000) + dispdev->width = 10000; + } + if (!cp_getvar("hcopyheight", VT_STRING, psheight)) { dispdev->height = dispdev->width; + } else { + sscanf(psheight, "%d", &(dispdev->height)); + if (dispdev->height <= 100) + dispdev->height = 100; + if (dispdev->height >= 10000) + dispdev->height = 10000; + } /* The following side effects have to be considered * when the printer is called by com_hardcopy ! @@ -128,6 +157,7 @@ PS_Init(void) int PS_NewViewport(GRAPH *graph) { + int x1,x2,y1,y2; hcopygraphid = graph->graphid; if (!(plotfile = fopen(graph->devdep, "w"))) { @@ -155,24 +185,37 @@ PS_NewViewport(GRAPH *graph) xoff = scale * XOFF; yoff = scale * YOFF; + x1 = 0.75 * 72; + y1 = x1; + x2 = graph->absolute.width + .75 * 72; + y2 = graph->absolute.height + .75 * 72; /* start file off with a % */ fprintf(plotfile, "%%!PS-Adobe-3.0 EPSF-3.0\n"); fprintf(plotfile, "%%%%Creator: nutmeg\n"); - fprintf(plotfile, "%%%%BoundingBox: %d %d %d %d\n", - (int) (.75 * 72), (int) (.75 * 72), - (int) (8.5 * 72), (int) (8.5 * 72)); + fprintf(plotfile, "%%%%BoundingBox: %d %d %d %d\n",x1,y1,x2,y2); fprintf(plotfile, "%g %g scale\n", 1.0 / scale, 1.0 / scale); + if (colorflag == 1){ /* set the background to color0 */ + PS_SelectColor(0); + fprintf(plotfile,"%s setrgbcolor\n",pscolor); + fprintf(plotfile,"newpath\n"); + fprintf(plotfile,"%d %d moveto %d %d lineto\n",x1,y1,x2,y1); + fprintf(plotfile,"%d %d lineto %d %d lineto\n",x2,y2,x1,y2); + fprintf(plotfile,"closepath fill\n"); + } + /* set up a reasonable font */ - fprintf(plotfile, "/%s findfont %d scalefont setfont\n", + fprintf(plotfile, "/%s findfont %d scalefont setfont\n\n", psfont, (int) (fontsize * scale)); graph->devdep = tmalloc(sizeof(PSdevdep)); DEVDEP(graph).lastlinestyle = -1; + DEVDEP(graph).lastcolor = -1; DEVDEP(graph).lastx = -1; DEVDEP(graph).lasty = -1; DEVDEP(graph).linecount = 0; + PS_SelectColor(0); graph->linestyle = -1; return 0; @@ -185,12 +228,8 @@ PS_Close(void) /* in case PS_Close is called as part of an abort, w/o having reached PS_NewViewport */ if (plotfile) { - if (DEVDEP(currentgraph).lastlinestyle != -1) { - /* haven't stroked last path */ - fprintf(plotfile, "stroke\n"); - DEVDEP(currentgraph).linecount = 0; - } - fprintf(plotfile, "showpage\n"); + PS_Stroke(); + fprintf(plotfile, "showpage\n%%%%EOF\n"); fclose(plotfile); plotfile = NULL; } @@ -218,19 +257,14 @@ PS_DrawLine(int x1, int y1, int x2, int y2) /* note: this is not extendible to more than one graph => will have to give NewViewport a writeable graph XXX */ - if (DEVDEP(currentgraph).lastlinestyle != currentgraph->linestyle - || DEVDEP(currentgraph).linecount > MAX_PS_LINES) - { - fprintf(plotfile, "stroke\n"); - fprintf(plotfile, "newpath\n"); - DEVDEP(currentgraph).linecount = 0; - } - - if (DEVDEP(currentgraph).linecount == 0 + if (DEVDEP(currentgraph).linecount > MAX_PS_LINES + || DEVDEP(currentgraph).linecount == 0 || x1 != DEVDEP(currentgraph).lastx - || y1 != DEVDEP(currentgraph).lasty) - { - fprintf(plotfile, "%d %d moveto ", x1 + xoff, y1 + yoff); + || y1 != DEVDEP(currentgraph).lasty){ + PS_Stroke(); + fprintf(plotfile, "newpath\n"); + fprintf(plotfile, "%d %d moveto\n", x1 + xoff, y1 + yoff); + DEVDEP(currentgraph).linecount += 1; } if (x1 != x2 || y1 != y2) { fprintf(plotfile, "%d %d lineto\n", x2 + xoff, y2 + yoff); @@ -239,17 +273,14 @@ PS_DrawLine(int x1, int y1, int x2, int y2) DEVDEP(currentgraph).lastx = x2; DEVDEP(currentgraph).lasty = y2; - DEVDEP(currentgraph).lastlinestyle = currentgraph->linestyle; - } - void PS_Arc(int x0, int y0, int r, double theta1, double theta2) { double x1, y1; double angle1, angle2; - + PS_Stroke(); while (theta1 >= theta2) theta2 += 2 * M_PI; @@ -269,19 +300,18 @@ PS_Arc(int x0, int y0, int r, double theta1, double theta2) void PS_Text(char *text, int x, int y) { - - int savedlstyle; + int savedlstyle, savedcolor; /* set linestyle to solid or may get funny color text on some plotters */ savedlstyle = currentgraph->linestyle; - PS_SetLinestyle(SOLID); + savedcolor = currentgraph->currentcolor; - if (DEVDEP(currentgraph).linecount) { - fprintf(plotfile, "stroke\n"); - fprintf(plotfile, "newpath\n"); - DEVDEP(currentgraph).linecount = 0; - } + PS_SetLinestyle(SOLID); + PS_SetColor(1); + + /* stroke the path if there's an open one */ + PS_Stroke(); /* move to (x, y) */ fprintf(plotfile, "%d %d moveto\n", x + xoff + xtadj, y + yoff + ytadj); fprintf(plotfile, "(%s) show\n", text); @@ -290,10 +320,14 @@ PS_Text(char *text, int x, int y) DEVDEP(currentgraph).lasty = -1; /* restore old linestyle */ - PS_SetLinestyle(savedlstyle); + PS_SetColor(savedcolor); + PS_SetLinestyle(savedlstyle); } +/* PS_DefineColor */ +/* PS_DefineLinestyle */ + int PS_SetLinestyle(int linestyleid) { @@ -304,48 +338,141 @@ PS_SetLinestyle(int linestyleid) currentgraph->linestyle = -1; return 0; } - if (linestyleid < 0 || linestyleid > dispdev->numlinestyles) { - internalerror("bad linestyleid"); + internalerror("bad linestyleid inside PS_SetLinestyle"); return 0; } - - if (currentgraph->linestyle != linestyleid) { - if (DEVDEP(currentgraph).lastlinestyle != -1) { - fprintf(plotfile, "stroke\n"); - fprintf(plotfile, "newpath\n"); - DEVDEP(currentgraph).linecount = 0; + PS_LinestyleColor(linestyleid, currentgraph->currentcolor); + return 0; } - fprintf(plotfile, "%s 0 setdash\n", linestyle[linestyleid]); - currentgraph->linestyle = linestyleid; - } - return 0; - -} - void PS_SetColor(int colorid) { - static int flag = 0; /* A hack */ - - /* XXXX Set line style dotted for smith grids */ - if ((colorid == 18) || (colorid == 19)) { - PS_SetLinestyle(DOTTED); - flag = 1; - } - if (flag && (colorid == 1)) { - PS_SetLinestyle(SOLID); - flag = 0; - } - + PS_LinestyleColor(currentgraph->linestyle, colorid); } void PS_Update(void) { - - fflush(plotfile); - + fflush(plotfile); +} + +/**************** PRIVAT FUNCTIONS OF PS FRONTEND *****************************/ + +void +PS_SelectColor(int colorid) /* should be replaced by PS_DefineColor */ +{ + char colorN[30]="", colorstring[30]=""; + char rgb[30], s_red[30]="0x", s_green[30]="0x", s_blue[30]="0x"; + long red=0, green=0, blue=0, scale=1; + int i; + typedef struct { int red, green, blue;} COLOR; + /* duplicated colors from src/frontend/plotting/x11.c in rgb-style */ + const COLOR colors[]= {{ 0, 0, 0}, /*0: black */ + {255, 255, 255}, /*1: white */ + {255, 0, 0}, /*2: red */ + { 0, 0, 255}, /*3: blue */ + {255, 165, 0}, /*4: orange */ + { 0, 255, 0}, /*5: green */ + {255, 192, 203}, /*6: pink */ + {165, 42, 42}, /*7: brown */ + {240, 230, 140}, /*8: khaki */ + {221, 160, 221}, /*9: plum */ + {218, 112, 214}, /*10: orchid */ + {238, 130, 238}, /*11: violet */ + {176, 48, 96}, /*12: maroon */ + { 64, 224, 208}, /*13: turqoise */ + {160, 82, 45}, /*14: sienna */ + {255, 127, 80}, /*15: coral */ + { 0, 255, 255}, /*16: cyan */ + {255, 0, 255}, /*17: magenta */ + /*{255, 215, 0}, 18: gold */ + { 96, 96, 96}, /*18: gray for smith grid */ + /*{255, 255, 0}, 19: yello */ + {150, 150, 150}, /*19: gray for smith grid */ + {128, 128, 128}}; /*20: gray for normal grid */ + + /* Extract the rgbcolor, format is: "rgb://" */ + sprintf(colorN, "color%d",colorid); + if (cp_getvar(colorN, VT_STRING, colorstring)){ + for (i=0; colorstring[i]; i++) + if (colorstring[i] == '/' || colorstring[i] == ':') + colorstring[i] = ' '; + + sscanf(colorstring,"%s %s %s %s",rgb, &(s_red[2]), &(s_green[2]), &(s_blue[2])); + + if ((strlen(s_blue) == strlen(s_red) && strlen(s_green) == strlen(s_red)) + && (strlen(s_blue) > 2) && (strlen(s_blue) < 7)){ + sscanf(s_red,"%lx",&red); + sscanf(s_green,"%lx",&green); + sscanf(s_blue,"%lx",&blue); + scale= (1 << (strlen(s_blue) - 2) * 4) - 1; + sprintf(colorstring,"%1.3f %1.3f %1.3f", + (float) red/scale, (float) green/scale, (float) blue/scale); + strcpy(pscolor, colorstring); + } + } + if (colorid < 0 || colorid > 20) { + internalerror("bad colorid inside PS_SelectColor"); + }else if (scale == 1){ /* colorN is not an rgbstring, use default color */ + sprintf(colorstring,"%1.3f %1.3f %1.3f",colors[colorid].red/255.0, + colors[colorid].green/255.0, colors[colorid].blue/255.0) ; + strcpy(pscolor, colorstring); + } + } + +void +PS_LinestyleColor(int linestyleid, int colorid) +{ + /* we have some different linestyles and colors: + - color and linestyle we got via function call + - color and linestyle we used last time for drawing + - generated color and linestyle we'll use for drawing this time */ + /* these are the rules: + DOTTED and colored ps -> color20 (used for grid) and SOLID + color18 or 19 and black-white -> linestyle is DOTTED */ + + int gencolor=0,genstyle=0; + + if (colorflag == 1){ + genstyle = SOLID; + if (linestyleid==DOTTED) + gencolor = 20; + else + gencolor = colorid; + } else { /* colorflag == 0 -> mono*/ + if ((colorid == 18) || (colorid == 19)) + genstyle=DOTTED; + else + genstyle=linestyleid; + } + + /* change color if nessecary */ + if (colorflag == 1 && gencolor != DEVDEP(currentgraph).lastcolor){ + PS_SelectColor(gencolor); + PS_Stroke(); + fprintf(plotfile,"%s setrgbcolor\n",pscolor); + DEVDEP(currentgraph).lastcolor = gencolor; + } + currentgraph->currentcolor = colorid; + + /* change linestyle if nessecary */ + if (colorflag == 0 && genstyle != DEVDEP(currentgraph).lastlinestyle){ + PS_Stroke(); + fprintf(plotfile, "%s 0 setdash\n", linestyle[genstyle]); + DEVDEP(currentgraph).lastlinestyle= genstyle; + } + currentgraph->linestyle = linestyleid; +} + +void +PS_Stroke(void) +{ + /* strokes an open path */ + if (DEVDEP(currentgraph).linecount > 0) { + fprintf(plotfile, "stroke\n"); + DEVDEP(currentgraph).linecount = 0; + } } diff --git a/src/frontend/runcoms.c b/src/frontend/runcoms.c index 560df7738..adba7315d 100644 --- a/src/frontend/runcoms.c +++ b/src/frontend/runcoms.c @@ -223,12 +223,33 @@ dosim(char *what, wordlist *wl) #endif /* PARALLEL_ARCH */ if (!*wl->wl_word) rawfileFp = stdout; +#ifdef __MINGW32__ +// ask if binary or ASCII, open file with w or wb hvogt 15.3.2000 + else if (ascii) { + if(!(rawfileFp = fopen(wl->wl_word, "w"))) { + perror(wl->wl_word); + ft_setflag = FALSE; + return 1; + } + fprintf(cp_out,"ASCII raw file\n"); + } + else if (!ascii) { + if(!(rawfileFp = fopen(wl->wl_word, "wb"))) { + perror(wl->wl_word); + ft_setflag = FALSE; + return 1; + } + fprintf(cp_out,"binary raw file\n"); + } +//------------------------------------------------------------------------- +#else else if (!(rawfileFp = fopen(wl->wl_word, "w"))) { setvbuf(rawfileFp, rawfileBuf, _IOFBF, RAWBUF_SIZE); perror(wl->wl_word); ft_setflag = FALSE; return 1; } +#endif /* __MINGW32__ */ rawfileBinary = !ascii; #ifdef PARALLEL_ARCH } else { @@ -239,7 +260,8 @@ dosim(char *what, wordlist *wl) rawfileFp = NULL; } /*save rawfile name saj*/ - if(last_used_rawfile) free((void *)last_used_rawfile); + if(last_used_rawfile) + tfree(last_used_rawfile); if(rawfileFp){ last_used_rawfile = copy(wl->wl_word); }else { @@ -293,6 +315,14 @@ dosim(char *what, wordlist *wl) } ft_curckt->ci_runonce = TRUE; ft_setflag = FALSE; + + /* va: garbage collection: unlink first word (inserted here) and tfree it */ + if (!dofile) { + tfree(ww->wl_word); + if (wl) + wl->wl_prev = NULL; + tfree(ww); + } return err; } diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index 679325775..0e9c2162a 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -154,6 +154,7 @@ if_run(char *t, char *what, wordlist *args, char *tab) int j; int which = -1; IFuid specUid,optUid; + char *s; /* First parse the line... */ @@ -168,7 +169,9 @@ if_run(char *t, char *what, wordlist *args, char *tab) || eq(what,"tf") || eq(what, "noise")) { - (void) sprintf(buf, ".%s", wl_flatten(args)); + s = wl_flatten(args); /* va: tfree char's tmalloc'ed in wl_flatten */ + (void) sprintf(buf, ".%s", s); + tfree(s); deck.li_next = deck.li_actual = NULL; deck.li_error = NULL; deck.li_linenum = 0; @@ -301,6 +304,7 @@ if_run(char *t, char *what, wordlist *args, char *tab) ||(eq(what, "sens")) ||(eq(what,"tf")) ||(eq(what, "run")) ) { + ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; if ((err = (*(ft_sim->doAnalyses))(ckt, 1, ft_curckt->ci_curTask))!=OK){ ft_sperror(err, "doAnalyses"); /* wrd_end(); */ diff --git a/src/frontend/variable.c b/src/frontend/variable.c index 4d98a4730..aa780de4c 100644 --- a/src/frontend/variable.c +++ b/src/frontend/variable.c @@ -28,6 +28,7 @@ bool cp_noglob = TRUE; bool cp_nonomatch = FALSE; bool cp_noclobber = FALSE; bool cp_ignoreeof = FALSE; +bool cp_echo = FALSE; /* CDHW */ struct variable *variables = NULL; @@ -156,6 +157,8 @@ cp_vset(char *varname, char type, char *value) cp_maxhistlength = v->va_real; else if (eq(copyvarname, "noclobber")) cp_noclobber = TRUE; + else if (eq(varname, "echo")) /*CDHW*/ + cp_echo = TRUE; /*CDHW*/ else if (eq(copyvarname, "prompt") && (type == VT_STRING)) cp_promptstring = copy(v->va_string); else if (eq(copyvarname, "ignoreeof")) @@ -205,17 +208,30 @@ cp_vset(char *varname, char type, char *value) alreadythere = FALSE; if (ft_curckt) { for (u = ft_curckt->ci_vars; u; u = u->va_next) + { if (eq(copyvarname, u->va_name)) { alreadythere = TRUE; break; } + } if (!alreadythere) { v->va_next = ft_curckt->ci_vars; ft_curckt->ci_vars = v; } else { + /* va: avoid memory leak within bcopy */ + if (u->va_type==VT_STRING) tfree(u->va_string); + else if (u->va_type==VT_LIST) tfree(u->va_vlist); + u->va_V = v->va_V; + /* va_name is the same string */ + u->va_type = v->va_type; + /* va_next left unchanged */ + tfree(v->va_name); + tfree(v); +/* va: old version with memory leaks w = u->va_next; bcopy(v, u, sizeof(*u)); u->va_next = w; +*/ } } break; @@ -234,7 +250,7 @@ cp_vset(char *varname, char type, char *value) return; } - +/*CDHW This needs leak checking carefully CDHW*/ struct variable * cp_setparse(wordlist *wl) { @@ -245,8 +261,6 @@ cp_setparse(wordlist *wl) int balance; while (wl) { - if(name) - tfree(name); name = cp_unquote(wl->wl_word); wl = wl->wl_next; if (((wl == NULL) || (*wl->wl_word != '=')) && @@ -277,9 +291,7 @@ cp_setparse(wordlist *wl) *s = '\0'; if (*val == '\0') { if (!wl) { - fprintf(cp_err, - "Error: %s equals what?.\n", - name); + fprintf(cp_err, "Error: %s equals what?.\n", name); tfree(name);/*DG: cp_unquote Memory leak: free name before exiting*/ return (NULL); } else { @@ -329,6 +341,7 @@ cp_setparse(wordlist *wl) } if (balance && !wl) { fprintf(cp_err, "Error: bad set form.\n"); + tfree(name); /* va: cp_unquote memory leak: free name before exiting */ return (NULL); } @@ -358,9 +371,8 @@ cp_setparse(wordlist *wl) vv->va_string = copy(val); } tfree(copyval);/*DG: must free ss any way to avoid cp_unquote memory leak */ + tfree(name); /* va: cp_unquote memory leak: free name for every loop */ } - if(name) - tfree(name); return (vars); } @@ -395,6 +407,8 @@ cp_remvar(char *varname) cp_nonomatch = FALSE; else if (eq(varname, "noclobber")) cp_noclobber = FALSE; + else if (eq(varname, "echo")) /*CDHW*/ + cp_echo = FALSE; /*CDHW*/ else if (eq(varname, "prompt")){ /* cp_promptstring = ""; Memory leak here the last allocated reference wil be lost*/ if(cp_promptstring) { @@ -561,7 +575,7 @@ cp_variablesubst(wordlist *wlist) { wordlist *wl, *nwl; char *s, *t, buf[BSIZE_SP], wbuf[BSIZE_SP], tbuf[BSIZE_SP]; - /* MW. tbuf holds curret word after wl_splice() calls free() on it */ + /* MW. tbuf holds current word after wl_splice() calls free() on it */ int i; for (wl = wlist; wl; wl = wl->wl_next) { @@ -595,7 +609,7 @@ cp_variablesubst(wordlist *wlist) } (void) strcpy(tbuf, t); /* MW. Save t*/ - if (!(wl = wl_splice(wl, nwl))) + if (!(wl = wl_splice(wl, nwl))) /*CDHW this frees wl CDHW*/ return (NULL); /* This is bad... */ for (wlist = wl; wlist->wl_prev; wlist = wlist->wl_prev) diff --git a/src/frontend/variable.h b/src/frontend/variable.h index 161d6b90e..6c8b6ae9a 100644 --- a/src/frontend/variable.h +++ b/src/frontend/variable.h @@ -42,6 +42,7 @@ extern bool cp_noglob; extern bool cp_nonomatch; extern bool cp_noclobber; extern bool cp_ignoreeof; +extern bool cp_echo; // extern struct variable *variables; wordlist * cp_varwl(struct variable *var); diff --git a/src/include/cktdefs.h b/src/include/cktdefs.h index 6cb71e9ca..6a53e602c 100644 --- a/src/include/cktdefs.h +++ b/src/include/cktdefs.h @@ -282,6 +282,7 @@ extern int CKTdestroy( void *); extern int CKTdltAnal( void *, void *, void *); extern int CKTdltInst( void *, void *); extern int CKTdltMod( void *, void *); +extern int CKTdltNNum(void *, int ); extern int CKTdltNod( void *, void *); extern int CKTdoJob( void *, int , void *); extern void CKTdump( CKTcircuit *, double, void *); @@ -344,7 +345,7 @@ extern int DCOaskQuest( CKTcircuit *, void *, int , IFvalue *); extern int DCOsetParm( CKTcircuit *, void *, int , IFvalue *); extern int DCTaskQuest( CKTcircuit *, void *, int , IFvalue *); extern int DCTsetParm( CKTcircuit *, void *, int , IFvalue *); -extern int DCop( CKTcircuit *); +extern int DCop( CKTcircuit *, int ); extern int DCtrCurv( CKTcircuit *, int ); extern int DCtran( CKTcircuit *, int ); extern int DISTOan(CKTcircuit *, int); diff --git a/src/include/ngspice.h b/src/include/ngspice.h index 268cfc4df..43e72a687 100644 --- a/src/include/ngspice.h +++ b/src/include/ngspice.h @@ -103,6 +103,11 @@ struct timeb timebegin; #ifdef HAVE_INDEX # define strchr index # define strrchr rindex +#else /* va: no index, but strchr */ + #ifdef HAVE_STRCHR + #define index strchr + #define rindex strrchr + #endif /* va: no index, but strchr */ #endif #ifdef HAS_TIME_ @@ -115,6 +120,10 @@ struct timeb timebegin; #define index strchr #endif +#ifdef HAS_WINDOWS +#include "wstdio.h" +#endif + extern char *gettok(char **s); extern char *gettok_noparens(char **s); extern int get_l_paren(char **s); diff --git a/src/main.c b/src/main.c index b04d6bd46..53840e5f6 100644 --- a/src/main.c +++ b/src/main.c @@ -45,6 +45,8 @@ #endif #endif +extern void DevInit(void); + /* Main options */ static bool ft_servermode = FALSE; static bool ft_batchmode = FALSE; @@ -210,7 +212,7 @@ int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator) SIMinfo.numDevices = DEVmaxnum = num_devices(); SIMinfo.devices = devices_ptr(); SIMinfo.numAnalyses = spice_num_analysis(); - SIMinfo.analyses = spice_analysis_ptr(); + SIMinfo.analyses = (IFanalysis **)spice_analysis_ptr(); #endif /* SIMULATOR */ SPfrontEnd = frontEnd; @@ -302,8 +304,13 @@ append_to_stream(FILE *dest, FILE *source) OUTattributes }; #endif + int +#ifdef HAS_WINDOWS +xmain(int argc, char **argv) +#else main(int argc, char **argv) +#endif { int c; int err; @@ -377,7 +384,7 @@ main(int argc, char **argv) #ifdef MALLOCTRACE mallocTraceInit("malloc.out"); #endif -#ifdef HAVE_ISATTY +#if defined(HAVE_ISATTY) && !defined(HAS_WINDOWS) istty = (bool) isatty(fileno(stdin)); #endif @@ -566,11 +573,8 @@ main(int argc, char **argv) asprintf(&s, "%s/.spiceinit", pw->pw_dir); #else /* ~ HAVE_ASPRINTF */ #define INITSTR "/.spiceinit" -if ( (s=(char *) malloc(1 + strlen(pw->pw_dir)+strlen(INITSTR))) == NULL){ - fprintf(stderr,"malloc failed\n"); - exit(1); - } - sprintf(s,"%s%s",pw->pw_dir,INITSTR); + s=(char *) tmalloc(1 + strlen(pw->pw_dir)+strlen(INITSTR)); + sprintf(s,"%s%s",pw->pw_dir,INITSTR); #endif /* HAVE_ASPRINTF */ if (access(s, 0) == 0) diff --git a/src/misc/ivars.c b/src/misc/ivars.c index 4db2aa877..f100d530b 100644 --- a/src/misc/ivars.c +++ b/src/misc/ivars.c @@ -42,19 +42,13 @@ mkvar(char **p, char *path_prefix, char *var_dir, char *env_var) asprintf(p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir); #else /* ~ HAVE_ASPRINTF */ if (buffer){ - if ( (*p = (char *) malloc(strlen(buffer)+1)) == NULL){ - fprintf(stderr,"malloc failed\n"); - exit(1); - } + p = (char *) tmalloc(strlen(buffer)+1); sprintf(*p,"%s",buffer); /* asprintf(p, "%s", buffer); */ } else{ - if ( (*p = (char *) malloc(strlen(path_prefix) + - strlen(DIR_PATHSEP) + strlen(var_dir) + 1)) == NULL){ - fprintf(stderr,"malloc failed\n"); - exit(1); - } + ip = (char *) tmalloc(strlen(path_prefix) + + strlen(DIR_PATHSEP) + strlen(var_dir) + 1); sprintf(*p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir); /* asprintf(p, "%s%s%s", path_prefix, DIR_PATHSEP, var_dir); */ } @@ -89,9 +83,9 @@ ivars(void) void cleanvars(void) { - txfree(News_File); - txfree(Default_MFB_Cap); - txfree(Help_Path); - txfree(Lib_Path); - txfree(Spice_Path); + tfree(News_File); + tfree(Default_MFB_Cap); + tfree(Help_Path); + tfree(Lib_Path); + tfree(Spice_Path); } diff --git a/src/misc/string.c b/src/misc/string.c index ccba3b4e4..3c74d39b2 100644 --- a/src/misc/string.c +++ b/src/misc/string.c @@ -235,8 +235,10 @@ get_r_paren(char **s) #ifndef bcopy void -bcopy(register char *from, register char *to, register int num) +bcopy(const void *vfrom, void *vto, size_t num) { + register const char *from=vfrom; + register char *to=vto; while (num-- > 0) *to++ = *from++; return; @@ -246,12 +248,13 @@ bcopy(register char *from, register char *to, register int num) #ifndef bzero /* can't declare void here, because we've already used it in this file */ /* and haven't declared it void before the use */ -int -bzero(register char *ptr, register int num) +void +bzero(void *vptr, size_t num) { + register char *ptr=vptr; while (num-- > 0) *ptr++ = '\0'; - return (0); + return; } #endif diff --git a/src/misc/stringutil.h b/src/misc/stringutil.h index 350c2fdd3..759a1cd39 100644 --- a/src/misc/stringutil.h +++ b/src/misc/stringutil.h @@ -25,8 +25,8 @@ char * rindex(register char *s,register char c ); #ifndef HAVE_BCOPY -void bcopy(register char *from, register char *to, register int num); -int bzero(register char *ptr, register int num); +void bcopy(const void *from, void *to, size_t num); +void bzero(void *ptr, size_t num); #endif /* HAVE_BCOPY */ diff --git a/src/spicelib/analysis/acan.c b/src/spicelib/analysis/acan.c index 02ea0cf51..c68a9e585 100644 --- a/src/spicelib/analysis/acan.c +++ b/src/spicelib/analysis/acan.c @@ -133,6 +133,7 @@ ACan(CKTcircuit *ckt, int restart) (*(SPfrontEnd->OUTpBeginPlot))((void *)ckt,(void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,(IFuid)NULL,IF_REAL,numNames,nameList, IF_REAL,&acPlot); + tfree(nameList); ipc_send_dcop_prefix(); @@ -169,6 +170,7 @@ ACan(CKTcircuit *ckt, int restart) (void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname,freqUid,IF_REAL,numNames,nameList, IF_COMPLEX,&acPlot); + tfree(nameList); if(error) return(error); if (((ACAN*)ckt->CKTcurJob)->ACstepType != LINEAR) { diff --git a/src/spicelib/analysis/ckt.h b/src/spicelib/analysis/ckt.h index 301002e9e..3a26f12bb 100644 --- a/src/spicelib/analysis/ckt.h +++ b/src/spicelib/analysis/ckt.h @@ -90,7 +90,7 @@ int DCOaskQuest( CKTcircuit *, void *, int , IFvalue *); int DCOsetParm( CKTcircuit *, void *, int , IFvalue *); int DCTaskQuest( CKTcircuit *, void *, int , IFvalue *); int DCTsetParm( CKTcircuit *, void *, int , IFvalue *); -int DCop( CKTcircuit *); +int DCop( CKTcircuit *, int ); int DCtrCurv( CKTcircuit *, int ); int DCtran( CKTcircuit *, int ); int DISTOan(CKTcircuit *, int); diff --git a/src/spicelib/analysis/dcop.c b/src/spicelib/analysis/dcop.c index 73088abfe..bda14dd64 100644 --- a/src/spicelib/analysis/dcop.c +++ b/src/spicelib/analysis/dcop.c @@ -12,7 +12,7 @@ Modified: 2000 AlansFixes int -DCop(CKTcircuit *ckt) +DCop(CKTcircuit *ckt, int notused) { int CKTload(CKTcircuit *ckt); int converged; @@ -26,6 +26,7 @@ DCop(CKTcircuit *ckt) error = (*(SPfrontEnd->OUTpBeginPlot))((void *)ckt, (void*)ckt->CKTcurJob, ckt->CKTcurJob->JOBname, (IFuid)NULL,IF_REAL,numNames,nameList, IF_REAL,&plot); + tfree(nameList); if(error) return(error); converged = CKTop(ckt, diff --git a/src/spicelib/devices/bsim3/b3temp.c b/src/spicelib/devices/bsim3/b3temp.c index 2fe8580a1..24768997b 100644 --- a/src/spicelib/devices/bsim3/b3temp.c +++ b/src/spicelib/devices/bsim3/b3temp.c @@ -56,6 +56,7 @@ int Size_Not_Found; { model->BSIM3GatesidewallJctPotential = 0.1; fprintf(stderr, "Given pbswg is less than 0.1. Pbswg is set to 0.1.\n"); } + FREE(model->pSizeDependParamKnot); model->pSizeDependParamKnot = NULL; pLastKnot = NULL; diff --git a/src/spicelib/parser/ifnewuid.c b/src/spicelib/parser/ifnewuid.c index ee59dcc9c..1d1633c57 100644 --- a/src/spicelib/parser/ifnewuid.c +++ b/src/spicelib/parser/ifnewuid.c @@ -33,12 +33,8 @@ IFnewUid(void *ckt, IFuid * newuid, IFuid olduid, char *suffix, int type, #ifdef HAVE_ASPRINTF asprintf(&newname, "%s#%s", (char *) olduid, suffix); #else /* ~ HAVE_ASPRINTF */ - if ( (newname = (char *) malloc(strlen((char *) olduid) + - strlen(suffix) + 2)) /* 2 = strlen("#\0") */ - == NULL){ - fprintf(stderr,"malloc failed\n"); - exit(1); - } + newname = (char *) tmalloc(strlen((char *) olduid) + + strlen(suffix) + 2); /* 2 = strlen("#\0") */ sprintf(newname, "%s#%s", (char *) olduid, suffix); #endif /* HAVE_ASPRINTF */ @@ -47,10 +43,7 @@ IFnewUid(void *ckt, IFuid * newuid, IFuid olduid, char *suffix, int type, #ifdef HAVE_ASPRINTF asprintf(&newname, "%s", suffix); #else /* ~ HAVE_ASPRINTF */ - if ( (newname = (char *) malloc(strlen(suffix) + 2 )) == NULL){ - fprintf(stderr,"malloc failed\n"); - exit(1); - } + newname = (char *) tmalloc(strlen(suffix) + 1 ); sprintf(newname, "%s", suffix); #endif /* HAVE_ASPRINTF */ } diff --git a/src/spicelib/parser/inp2dot.c b/src/spicelib/parser/inp2dot.c index a47287a90..1868dccf4 100644 --- a/src/spicelib/parser/inp2dot.c +++ b/src/spicelib/parser/inp2dot.c @@ -215,6 +215,7 @@ dot_ac(char *line, void *ckt, INPtables *tab, card *current, INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */ ptemp.iValue = 1; GCA(INPapName, (ckt, which, foo, steptype, &ptemp)); + tfree(steptype); parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* number of points */ GCA(INPapName, (ckt, which, foo, "numsteps", parm)); parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */ @@ -306,11 +307,11 @@ dot_dc(char *line, void *ckt, INPtables *tab, card *current, INPinsert(&name, tab); ptemp.uValue = name; GCA(INPapName, (ckt, which, foo, "name2", &ptemp)); - parm = INPgetValue(ckt, &line, IF_REAL, tab); /* vstart1 */ + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* vstart2 */ GCA(INPapName, (ckt, which, foo, "start2", parm)); - parm = INPgetValue(ckt, &line, IF_REAL, tab); /* vstop1 */ + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* vstop2 */ GCA(INPapName, (ckt, which, foo, "stop2", parm)); - parm = INPgetValue(ckt, &line, IF_REAL, tab); /* vinc1 */ + parm = INPgetValue(ckt, &line, IF_REAL, tab); /* vinc2 */ GCA(INPapName, (ckt, which, foo, "step2", parm)); } return 0; diff --git a/src/spicelib/parser/inperror.c b/src/spicelib/parser/inperror.c index 5c3df032b..d65597b61 100644 --- a/src/spicelib/parser/inperror.c +++ b/src/spicelib/parser/inperror.c @@ -40,18 +40,12 @@ char *INPerror(int type) asprintf(&ebuf, "%s\n", val); #else /* ~ HAVE_ASPRINTF */ if (errRtn){ - if ( (ebuf = (char *) malloc(strlen(val) + - strlen(errRtn) + 25)) == NULL){ - fprintf(stderr,"malloc failed\n"); - exit(1); - } + ebuf = (char *) tmalloc(strlen(val) + + strlen(errRtn) + 25); sprintf(ebuf, "%s detected in routine \"%s\"\n", val, errRtn); } else{ - if ( (ebuf = (char *) malloc(strlen(val) + 2)) == NULL){ - fprintf(stderr,"malloc failed\n"); - exit(1); - } + ebuf = (char *) tmalloc(strlen(val) + 2); sprintf(ebuf, "%s\n", val); } #endif /* HAVE_ASPRINTF */ diff --git a/src/tclspice.c b/src/tclspice.c index c1bc1e4c1..a158a42ac 100755 --- a/src/tclspice.c +++ b/src/tclspice.c @@ -22,6 +22,14 @@ #ifdef HAVE_STRING_H #include #endif /* HAVE_STRING_H */ +#ifdef __MINGW32__ + #include + #include + #include /* Sleep */ + #define srandom(a) srand(a) /* srandom */ +#else + #include /* usleep */ +#endif /* __MINGW32__ */ #define _GNU_SOURCE @@ -52,9 +60,23 @@ extern jmp_buf jbuf; #include #include #include + +#ifdef __CYGWIN__ +#undef WIN32 +#endif #include #include +/* defines for Tcl support + * Tcl 8.3 and Tcl 8.4 support, + * suggested by http://mini.net/tcl/3669, 07.03.03 */ +#ifndef CONST84 +#define CONST84 +#endif /* CONST84 */ +/* Arguments of Tcl_CmpProc for Tcl/Tk 8.4.x */ +#define TCL_CMDPROCARGS(clientData,interp,argc,argv) \ + (ClientData clientData, Tcl_Interp *interp, int argc, CONST84 char *argv[]) + /*For get_output*/ #include #include @@ -90,8 +112,7 @@ static int ownVectors = 0; static Tcl_Interp *spice_interp=NULL; #define save_interp() \ do {\ -if ((spice_interp = Tcl_GetMaster(interp)) == NULL)\ - spice_interp = interp;\ + spice_interp = interp;\ } while(0) /****************************************************************************/ @@ -106,11 +127,10 @@ static int blt_vnum = 0; /*Native Tcl functions */ -static int spice_header(ClientData clientData, Tcl_Interp *interp, - int args, char **argv){ +static int spice_header TCL_CMDPROCARGS(clientData,interp,argc,argv){ char buf[256]; char *date, *name, *title; - if (args != 1) { + if (argc != 1) { Tcl_SetResult(interp, "Wrong # args. spice::spice_header",TCL_STATIC); return TCL_ERROR; } @@ -126,12 +146,11 @@ static int spice_header(ClientData clientData, Tcl_Interp *interp, } -static int spice_data(ClientData clientData, Tcl_Interp *interp, - int args, char **argv){ +static int spice_data TCL_CMDPROCARGS(clientData,interp,argc,argv) { char buf[256]; int i, type; char *name; - if (args != 1) { + if (argc != 1) { Tcl_SetResult(interp, "Wrong # args. spice::spice_data",TCL_STATIC); return TCL_ERROR; } @@ -230,17 +249,16 @@ void blt_relink(int index,void *tmp){ /* This copys the last Spice state vector to the given blt_vector * arg1: blt_vector */ -static int lastVector(ClientData clientData, Tcl_Interp *interp, - int args, char **argv){ +static int lastVector TCL_CMDPROCARGS(clientData,interp,argc,argv) { Blt_Vector *vec; char *blt; int i; double *V; - if (args != 2) { + if (argc != 2) { Tcl_SetResult(interp, "Wrong # args. spice::lastVector vecName",TCL_STATIC); return TCL_ERROR; } - blt = argv[1]; + blt = (char *)argv[1]; if(Blt_GetVector(interp,blt,&vec)){ Tcl_SetResult(interp, "Bad blt vector ",TCL_STATIC); Tcl_AppendResult(interp, (char *)blt, TCL_STATIC); @@ -267,20 +285,19 @@ static int lastVector(ClientData clientData, Tcl_Interp *interp, *arg3: start copy index, optional *arg4: end copy index. optional */ -static int spicetoblt(ClientData clientData, Tcl_Interp *interp, - int args, char **argv){ +static int spicetoblt TCL_CMDPROCARGS(clientData,interp,argc,argv) { Blt_Vector *vec; int index, i; char *blt, *var; int start=0,end=-1,len; - if (args < 3 || args > 5) { + if (argc < 3 || argc > 5) { Tcl_SetResult(interp, "Wrong # args. spice::spicetoblt spice_variable vecName ?start? ?end?",TCL_STATIC); return TCL_ERROR; } - var = argv[1]; - blt = argv[2]; + var = (char *)argv[1]; + blt = (char *)argv[2]; for(i=0;i < blt_vnum && strcmp(var,vectors[i].name);i++); @@ -297,9 +314,9 @@ static int spicetoblt(ClientData clientData, Tcl_Interp *interp, } - if(args >= 4) + if(argc >= 4) start = atoi(argv[3]); - if(args == 5) + if(argc == 5) end = atoi(argv[4]); if(vectors[index].length) { pthread_mutex_lock(&vectors[index].mutex); @@ -353,7 +370,11 @@ static int _thread_stop(){ while(!fl_exited && timeout < 100){ ft_intrpt = TRUE; timeout++; - sleep(1); +#ifdef __MINGW32__ + Sleep(10); /* va: windows native */ +#else + usleep(10000); +#endif } if(!fl_exited) { fprintf(stderr,"couldn't stop tclspice\n"); @@ -369,14 +390,14 @@ static int _thread_stop(){ return TCL_OK; } -static int _run(int args,char **argv){ +static int _run(int argc,char **argv){ char buf[1024] = "", *string; int i; sighandler_t oldHandler; bool fl_bg = FALSE; /* run task in background if preceeded by "bg"*/ if(!strcmp(argv[0],"bg")) { - args--; + argc--; argv = &argv[1]; fl_bg = TRUE; } @@ -389,7 +410,7 @@ static int _run(int args,char **argv){ } /*build a char * to pass to cp_evloop */ - for(i=0;i 1) + if(argc > 1) cp_evloop(buf); else{ _thread_stop(); @@ -432,28 +453,26 @@ static int _run(int args,char **argv){ return TCL_OK; } -static int _tcl_dispatch(ClientData clientData, Tcl_Interp *interp, - int args, char **argv){ +static int _tcl_dispatch TCL_CMDPROCARGS(clientData,interp,argc,argv) { int i; save_interp(); /* Looks backwards through the first command and strips the :: part */ for(i = strlen(argv[0])-1;i > 0;i--) if(argv[0][i] == *":") argv[0] += i + 1; - return _run(args,argv); + return _run(argc,(char **)argv); } /* Runs the spice command given in spice */ -static int _spice_dispatch(ClientData clientData, Tcl_Interp *interp, - int args, char **argv){ +static int _spice_dispatch TCL_CMDPROCARGS(clientData,interp,argc,argv) { save_interp(); - if(args == 1) return TCL_OK; - return _run(args-1,&argv[1]); + if(argc == 1) return TCL_OK; + return _run(argc-1,(char **)&argv[1]); } /*Checks if spice is runnuing in the background */ -static int running(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int running TCL_CMDPROCARGS(clientData,interp,argc,argv) { Tcl_SetObjResult(interp,Tcl_NewIntObj((long) (fl_running && !fl_exited))); return TCL_OK; } @@ -477,7 +496,7 @@ inline static struct plot * get_plot(int plot){ } /*Outputs the names of all variables in the plot */ -static int plot_variables(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int plot_variables TCL_CMDPROCARGS(clientData,interp,argc,argv) { struct plot *pl; int plot; struct dvec *v; @@ -501,7 +520,7 @@ static int plot_variables(ClientData clientData, Tcl_Interp *interp, int argc, c } /*returns the value of a variable */ -static int plot_get_value(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int plot_get_value TCL_CMDPROCARGS(clientData,interp,argc,argv) { struct plot *pl; struct dvec *v; char *name; @@ -512,7 +531,7 @@ static int plot_get_value(ClientData clientData, Tcl_Interp *interp, int argc, c return TCL_ERROR; } - name = argv[1]; + name = (char *)argv[1]; plot = atoi(argv[2]); index = atoi(argv[3]); @@ -536,7 +555,7 @@ static int plot_get_value(ClientData clientData, Tcl_Interp *interp, int argc, c /*The length of the first vector in a plot*/ -static int plot_datapoints(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int plot_datapoints TCL_CMDPROCARGS(clientData,interp,argc,argv) { struct plot *pl; struct dvec *v; int plot; @@ -561,11 +580,11 @@ static int plot_datapoints(ClientData clientData, Tcl_Interp *interp, int argc, /*These functions give you infomation about a plot*/ -static int plot_title(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int plot_title TCL_CMDPROCARGS(clientData,interp,argc,argv) { struct plot *pl; int plot; if (argc != 2) { - Tcl_SetResult(interp, "Wrong # args. spice::plot_nvars plot",TCL_STATIC); + Tcl_SetResult(interp, "Wrong # args. spice::plot_title plot",TCL_STATIC); return TCL_ERROR; } @@ -579,12 +598,12 @@ static int plot_title(ClientData clientData, Tcl_Interp *interp, int argc, char return TCL_OK; } -static int plot_date(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int plot_date TCL_CMDPROCARGS(clientData,interp,argc,argv) { struct plot *pl; int plot; if (argc != 2) { - Tcl_SetResult(interp, "Wrong # args. spice::plot_nvars plot",TCL_STATIC); + Tcl_SetResult(interp, "Wrong # args. spice::plot_date plot",TCL_STATIC); return TCL_ERROR; } @@ -598,11 +617,11 @@ static int plot_date(ClientData clientData, Tcl_Interp *interp, int argc, char * return TCL_OK; } -static int plot_name(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int plot_name TCL_CMDPROCARGS(clientData,interp,argc,argv) { struct plot *pl; int plot; if (argc != 2) { - Tcl_SetResult(interp, "Wrong # args. spice::plot_nvars plot",TCL_STATIC); + Tcl_SetResult(interp, "Wrong # args. spice::plot_name plot",TCL_STATIC); return TCL_ERROR; } @@ -618,7 +637,7 @@ static int plot_name(ClientData clientData, Tcl_Interp *interp, int argc, char * /*number of variables in a plot*/ -static int plot_nvars(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int plot_nvars TCL_CMDPROCARGS(clientData,interp,argc,argv){ struct plot *pl; struct dvec *v; int plot; @@ -647,7 +666,7 @@ static int plot_nvars(ClientData clientData, Tcl_Interp *interp, int argc, char /*******************************************/ /*Runs a tcl script and returns the output*/ -static int get_output(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) { +static int get_output TCL_CMDPROCARGS(clientData,interp,argc,argv) { FILE *pipein; int tmp_1,tmp_2=0; char buf[1024]; @@ -707,7 +726,7 @@ static int get_output(ClientData clientData, Tcl_Interp *interp, int argc, char /* Returns the current value of a parameter * has lots of memory leaks */ -static int get_param(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int get_param TCL_CMDPROCARGS(clientData,interp,argc,argv) { wordlist *wl= NULL; char *device, *param; struct variable *v; @@ -721,8 +740,8 @@ static int get_param(ClientData clientData, Tcl_Interp *interp, int argc, char * return TCL_ERROR; } - device = argv[1]; - param = argv[2]; + device = (char *)argv[1]; + param = (char *)argv[2]; /* copied from old_show(wordlist *) */ v = (*if_getparam)(ft_curckt->ci_ckt, &device, param, 0, 0); @@ -744,15 +763,96 @@ static int get_param(ClientData clientData, Tcl_Interp *interp, int argc, char * } +/* va - added + call: s. errormessage + returns: param == all: list of all model parameters of device/model + param == name: description of given model parameter +*/ +int get_mod_param TCL_CMDPROCARGS(clientData,interp,argc,argv) { + char *name; + char *paramname; + GENinstance *devptr=(GENinstance *)NULL; + GENmodel *modptr=(GENmodel *)NULL; + IFdevice *device; + IFparm *opt; + IFvalue pv; + int i, err, typecode=-1; + char buf[128]; + bool found; + + if (argc < 2 || argc >3) { + Tcl_SetResult(interp, + "Wrong # args. spice::get_mod_param device|model [all|param]", TCL_STATIC); + return TCL_ERROR; + } + if (ft_curckt==NULL) { + Tcl_SetResult(interp, "No circuit loaded ",TCL_STATIC); + return TCL_ERROR; + } + + name = (char *)argv[1]; + if (argc>2) { + paramname=(char *)argv[2]; + } else { + paramname="all"; + } + if (name==NULL || name[0]=='\0') { + Tcl_SetResult(interp, "No model or device name provided.",TCL_STATIC); + return TCL_ERROR; + } + + /* get the unique IFuid for name (device/model) */ + INPretrieve(&name,(INPtables *)ft_curckt->ci_symtab); + err = (*(ft_sim->findInstance))(ft_curckt->ci_ckt,&typecode,(void **)&devptr,name,NULL,NULL); + if (err != OK) { + typecode = -1; + devptr = (void *)NULL; + err = (*(ft_sim->findModel))(ft_curckt->ci_ckt,&typecode,(void **)&modptr,name); + } + if (err != OK) { + sprintf(buf,"No such device or model name %s",name); + Tcl_SetResult(interp,buf,TCL_VOLATILE); + return TCL_ERROR; + } + device = ft_sim->devices[typecode]; + found = FALSE; + for (i = 0; i < *(device->numModelParms); i++) { + opt = &device->modelParms[i]; + if (opt->dataType != (IF_SET|IF_ASK|IF_REAL)) continue; /* only real IO-parameter */ + if (strcmp(paramname,"all")==0) { + Tcl_AppendElement(interp,opt->keyword); + found=TRUE; + } else if (strcmp(paramname,opt->keyword)==0) { + if (devptr) + err = (*(ft_sim->askInstanceQuest))(ft_curckt->ci_ckt, (void *)devptr, + opt->id, &pv, (IFvalue *)NULL); + else + err = (*(ft_sim->askModelQuest))(ft_curckt->ci_ckt, (void *)modptr, + opt->id, &pv, (IFvalue *)NULL); + if (err==OK) { + sprintf(buf,"%g",pv.rValue); /* dataType is here always real */ + Tcl_SetResult(interp,buf,TCL_VOLATILE); + return TCL_OK; + } + } + } + if (found!=TRUE) { + sprintf(buf,"unknown parameter %s",paramname); + Tcl_SetResult(interp,buf,TCL_VOLATILE); + return TCL_ERROR; + } + return TCL_OK; +} + /* Direct control over the step size * Spice will still adjust it to keep accuracy wuithin reltol and abstol */ -static int delta(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int delta TCL_CMDPROCARGS(clientData,interp,argc,argv) { if (argc < 1 ||argc > 2) { Tcl_SetResult(interp, "Wrong # args. spice::delta ?value?",TCL_STATIC); return TCL_ERROR; } - if (!ft_curckt) { + if (ft_curckt==NULL) { Tcl_SetResult(interp, "No circuit loaded ",TCL_STATIC); return TCL_ERROR; } @@ -769,13 +869,13 @@ static int delta(ClientData clientData, Tcl_Interp *interp, int argc, char *argv /* Direct control over the maximum stepsize * Spice will still adjust it to keep accuracy wuithin reltol and abstol */ -static int maxstep(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int maxstep TCL_CMDPROCARGS(clientData,interp,argc,argv) { TRANan *job; if (argc < 1 ||argc > 2) { Tcl_SetResult(interp, "Wrong # args. spice::maxstep ?value?",TCL_STATIC); return TCL_ERROR; } - if (!ft_curckt) { + if (ft_curckt == NULL) { Tcl_SetResult(interp, "No circuit loaded ",TCL_STATIC); return TCL_ERROR; } @@ -809,7 +909,7 @@ int sp_Tk_Init(void) { #include int sp_Tk_NewViewport(GRAPH *graph) { - char *result; + const char *result; int width, height, fontwidth, fontheight; graph->devdep = (char *) NULL; @@ -1087,7 +1187,7 @@ static int resetTriggers() { *arg2: Vmax *arg3: 1 / -1 for +ive(voltage goes +ive) or -ive trigger */ -static int registerTrigger(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int registerTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){ int i, index; char *var; struct watch *tmp; @@ -1097,7 +1197,7 @@ static int registerTrigger(ClientData clientData, Tcl_Interp *interp, int argc, return TCL_ERROR; } - var = argv[1]; + var = (char *)argv[1]; for(i=0;i < blt_vnum && strcmp(var,vectors[i].name);i++); @@ -1132,7 +1232,7 @@ static int registerTrigger(ClientData clientData, Tcl_Interp *interp, int argc, *arg0: Vector name *arg1: type */ -static int unregisterTrigger(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int unregisterTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){ int i, index, type; char *var; struct watch *tmp; @@ -1143,7 +1243,7 @@ static int unregisterTrigger(ClientData clientData, Tcl_Interp *interp, int argc return TCL_ERROR; } - var = argv[1]; + var = (char *)argv[1]; for(i=0;i < blt_vnum && strcmp(var,vectors[i].name);i++); @@ -1183,7 +1283,7 @@ static int unregisterTrigger(ClientData clientData, Tcl_Interp *interp, int argc /* returns: "vecName" "time" "stepNumber" "type" */ -static int popTriggerEvent(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int popTriggerEvent TCL_CMDPROCARGS(clientData,interp,argc,argv){ if (argc != 1) { Tcl_SetResult(interp, "Wrong # args. spice::popTriggerEvent",TCL_STATIC); @@ -1221,7 +1321,7 @@ static int popTriggerEvent(ClientData clientData, Tcl_Interp *interp, int argc, return TCL_OK; } -static int listTriggers(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]){ +static int listTriggers TCL_CMDPROCARGS(clientData,interp,argc,argv){ struct watch *tmp; Tcl_Obj *list; @@ -1327,6 +1427,7 @@ int Spice_Init(Tcl_Interp *interp) { Tcl_CreateCommand(interp, TCLSPICE_prefix "bg", _tcl_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "halt", _tcl_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "get_param", get_param, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); + Tcl_CreateCommand(interp, TCLSPICE_prefix "get_mod_param", get_mod_param, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "delta", delta, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "maxstep", maxstep, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "running", running, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);