diff --git a/ChangeLog b/ChangeLog index 0b0f0ae4e..827978ce8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2003-08-01 Stefan Jones + + * src/xspice/mif/mif_inp2.c: + Reverted to version 1.1.2.2 so POLY and codemodels work + + * src/Makefile.am: + Fixed libspice.so dependancies + + * configure.in src/tclspice.c: + tclspice can now be built without thread support + + * src/frontend/{com_let.c,device.c,evaluate.c}: + more memory leak fixes by Vera Albrecht + 2003-07-18 Vera Albrecht * src/{main.c,tclspice.c} diff --git a/configure.in b/configure.in index bae2ced93..d19aa2949 100644 --- a/configure.in +++ b/configure.in @@ -217,6 +217,8 @@ else fi rm -f conftest.tcl +AC_CHECK_LIB(pthread,pthread_create) + else TCL_PACKAGE_PATH="" TCL_BUILD_LIB_SPEC="" diff --git a/src/Makefile.am b/src/Makefile.am index 7a2bf72fd..5e47bca79 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -213,8 +213,8 @@ install-tclspice: ${TCL_FILES} tclspice.o: tclspice.c $(COMPILE) -c -fpic tclspice.c -DTCLSPICE_version="\"$(TCLSPICE_VERSION)\"" -libspice.so: $(ngspice_OBJECTS) $(LIBSPICE_OBJS) $(ngspice_DEPENDENCIES) - $(LINK) $(ngspice_LDFLAGS) $(ngspice_OBJECTS) $(ngspice_LDADD) $(LIBS) $(LIBSPICE_OBJS) -shared -lpthread -Wl,--version-script=tclspice.map +libspice.so: $(ngspice_OBJECTS) $(LIBSPICE_OBJS) $(ngspice_LDADD) + $(LINK) $(ngspice_LDFLAGS) $(ngspice_OBJECTS) $(ngspice_LDADD) $(LIBS) $(LIBSPICE_OBJS) -shared -Wl,--version-script=tclspice.map if test -f .libs/$@ ; then \ mv .libs/$@ ./ ;\ rmdir .libs ;\ diff --git a/src/frontend/com_let.c b/src/frontend/com_let.c index 9928d832f..ebf256b86 100644 --- a/src/frontend/com_let.c +++ b/src/frontend/com_let.c @@ -41,6 +41,7 @@ com_let(wordlist *wl) *rhs++ = 0; } else { fprintf(cp_err, "Error: bad let syntax\n"); + tfree(p); return; } if ((s =strchr(p, '['))) { @@ -63,6 +64,7 @@ com_let(wordlist *wl) if (depth != 0 || !*q) { printf("syntax error specifyingstrchr\n"); + tfree(p); return; } @@ -86,6 +88,7 @@ com_let(wordlist *wl) /* sanity check */ if (eq(p, "all") ||strchr(p, '@')) { fprintf(cp_err, "Error: bad variable name %s\n", p); + tfree(p); return; } @@ -100,8 +103,8 @@ com_let(wordlist *wl) t = ft_evaluate(nn); if (!t) { fprintf(cp_err, "Error: Can't evaluate %s\n", rhs); - tfree(p); free_pnode(nn); + tfree(p); return; } @@ -117,9 +120,7 @@ com_let(wordlist *wl) } else { if (numdims) { fprintf(cp_err, "Can't assign into a subindex of a new vector\n"); - tfree(p); - free_pnode(nn); - return; + goto quit; } /* create and assign a new vector */ @@ -177,18 +178,14 @@ com_let(wordlist *wl) length * cube); if (newvec) n->v_flags &= ~VF_PERMANENT; - tfree(p); - free_pnode(nn); - return; + goto quit; } if (isreal(t) != isreal(n)) { fprintf(cp_err, "Types of vectors are not the same (real vs. complex)\n"); if (newvec) n->v_flags &= ~VF_PERMANENT; - tfree(p); - free_pnode(nn); - return; + goto quit; } else if (isreal(t)) { bcopy((char *) t->v_realdata, (char *) (n->v_realdata + offset), length * sizeof (double)); @@ -205,7 +202,10 @@ com_let(wordlist *wl) if (newvec) cp_addkword(CT_VECTOR, n->v_name); +quit: + /* va: garbage collection for t, if pnode nn is no simple value */ + if (nn->pn_value==NULL && t!=NULL) vec_free(t); + free_pnode(nn); /* frees also t, if pnode nn is simple value */ tfree(p); - free_pnode(nn); return; } diff --git a/src/frontend/device.c b/src/frontend/device.c index 952b4b5cf..180bf1e3c 100644 --- a/src/frontend/device.c +++ b/src/frontend/device.c @@ -648,8 +648,9 @@ com_alter_common(wordlist *wl, int do_model) if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model); - free_pnode(names); - + /* va: garbage collection for dv, if pnode names is no simple value */ + if (names->pn_value==NULL && dv!=NULL) vec_free(dv); + free_pnode(names); /* free also dv, if pnode names is simple value */ return; } diff --git a/src/frontend/evaluate.c b/src/frontend/evaluate.c index 774bb8363..16017b0aa 100644 --- a/src/frontend/evaluate.c +++ b/src/frontend/evaluate.c @@ -39,14 +39,16 @@ sig_matherr(void) /* Note that ft_evaluate will return NULL on invalid expressions. */ - +/* va: NOTE: ft_evaluate returns a new vector for expressions (func, op, ...) + and an existing vector (node->pn_value) when node->pn_value != NULL. + For garbage collection caller must vec_free() expression-vector. */ struct dvec * ft_evaluate(struct pnode *node) { struct dvec *d = NULL; if (!node) - return (NULL); + d = NULL; else if (node->pn_value) d = node->pn_value; else if (node->pn_func) @@ -55,21 +57,22 @@ ft_evaluate(struct pnode *node) if (node->pn_op->op_arity == 1) d = (struct dvec *) ((*node->pn_op->op_func) (node->pn_left)); - else if (node->pn_op->op_arity == 2) + else if (node->pn_op->op_arity == 2) { d = (struct dvec *) ((*node->pn_op->op_func) (node->pn_left, node->pn_right)); + } } else { fprintf(cp_err, "ft_evaluate: Internal Error: bad node\n"); - return (NULL); + d = NULL; } - if (!d) { + if (d==NULL) { return NULL; } if (node->pn_name && !ft_evdb && d && !d->v_link2) { - if(d->v_name) - tfree(d->v_name); + if (d->v_name) + tfree(d->v_name); /* patch by Stefan Jones */ d->v_name = copy(node->pn_name); } @@ -294,6 +297,9 @@ doop(char what, } } + /* va: garbage collection */ + if (arg1->pn_value==NULL && v1!=NULL) vec_free(v1); + if (arg2->pn_value==NULL && v2!=NULL) vec_free(v2); return (res); } @@ -493,6 +499,10 @@ op_range(struct pnode *arg1, struct pnode *arg2) */ vec_new(res); + + /* va: garbage collection */ + if (arg1->pn_value==NULL && v!=NULL) vec_free(v); + if (arg1->pn_value==NULL && ind!=NULL) vec_free(ind); return (res); } @@ -642,6 +652,10 @@ op_ind(struct pnode *arg1, struct pnode *arg2) */ vec_new(res); + + /* va: garbage collection */ + if (arg1->pn_value==NULL && v!=NULL) vec_free(v); + if (arg1->pn_value==NULL && ind!=NULL) vec_free(ind); return (res); } @@ -768,6 +782,8 @@ apply_func(struct func *func, struct pnode *arg) end = t; } + /* va: garbage collection */ + if (arg->pn_value==NULL && v!=NULL) vec_free(v); return (newv); } diff --git a/src/tclspice.c b/src/tclspice.c index a158a42ac..9532db619 100755 --- a/src/tclspice.c +++ b/src/tclspice.c @@ -81,8 +81,10 @@ extern jmp_buf jbuf; #include #include +#ifdef HAVE_LIBPTHREAD /* run spicein background */ #include +#endif #include /* for va_copy() */ @@ -95,7 +97,9 @@ extern int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator); /*For blt spice to use*/ typedef struct { char *name; +#ifdef HAVE_LIBPTHREAD pthread_mutex_t mutex;/*lock for this vector*/ +#endif double *data;/* vector data*/ int size;/*data it can store*/ int length;/*actual amount of data*/ @@ -187,7 +191,9 @@ void blt_init(void *run) { if(ownVectors) FREE(vectors[i].data); FREE(vectors[i].name); +#ifdef HAVE_LIBPTHREAD pthread_mutex_destroy(&vectors[i].mutex); +#endif } FREE(vectors); } @@ -198,7 +204,9 @@ void blt_init(void *run) { vectors = (vector *)MALLOC(cur_run->numData*sizeof(vector)); for(i = 0;i < cur_run->numData;i++){ vectors[i].name = copy((cur_run->data[i]).name); +#ifdef HAVE_LIBPTHREAD pthread_mutex_init(&vectors[i].mutex,NULL); +#endif vectors[i].data = NULL; vectors[i].size = 0; vectors[i].length = 0; @@ -212,20 +220,26 @@ void blt_init(void *run) { void blt_add(int index,double value){ vector *v; v = &vectors[index]; +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&vectors[index].mutex); +#endif if(!(v->length < v->size)){ v->size += 100; v->data = (double *)REALLOC(v->data,sizeof(double)*v->size); } v->data[v->length] = value; v->length ++; +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&vectors[index].mutex); +#endif return; } /* Locks the vector data to stop conflicts*/ void blt_lockvec(int index){ +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&vectors[index].mutex); +#endif return; } @@ -237,7 +251,9 @@ void blt_relink(int index,void *tmp){ vectors[index].data = v->v_realdata; vectors[index].length = v->v_length; vectors[index].size = v->v_length;/*silly spice doesn't use v_rlength*/ +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&vectors[index].mutex); +#endif return; } @@ -270,9 +286,13 @@ static int lastVector TCL_CMDPROCARGS(clientData,interp,argc,argv) { } for(i=0;i < blt_vnum;i++){ +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&vectors[i].mutex); +#endif V[i] = vectors[i].data[vectors[i].length-1]; +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&vectors[i].mutex); +#endif } Blt_ResetVector(vec,V,blt_vnum, blt_vnum,TCL_VOLATILE); @@ -319,7 +339,9 @@ static int spicetoblt TCL_CMDPROCARGS(clientData,interp,argc,argv) { if(argc == 5) end = atoi(argv[4]); if(vectors[index].length) { +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&vectors[index].mutex); +#endif len = vectors[index].length; @@ -337,8 +359,10 @@ static int spicetoblt TCL_CMDPROCARGS(clientData,interp,argc,argv) { Blt_ResetVector(vec,(vectors[index].data + start),len, len,TCL_VOLATILE); - + +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&vectors[index].mutex); +#endif } return TCL_OK; } @@ -348,6 +372,7 @@ static int spicetoblt TCL_CMDPROCARGS(clientData,interp,argc,argv) { /* Main spice command executions and thread control */ /*****************************************************************/ +#ifdef HAVE_LIBPTHREAD static pthread_t tid, bgtid=(pthread_t)0; static bool fl_running = FALSE; static bool fl_exited = TRUE; @@ -389,11 +414,14 @@ static int _thread_stop(){ } return TCL_OK; } +#endif /*HAVE_LIBPTHREAD*/ static int _run(int argc,char **argv){ - char buf[1024] = "", *string; + char buf[1024] = ""; int i; sighandler_t oldHandler; +#ifdef HAVE_LIBPTHREAD + char *string; bool fl_bg = FALSE; /* run task in background if preceeded by "bg"*/ if(!strcmp(argv[0],"bg")) { @@ -401,6 +429,7 @@ static int _run(int argc,char **argv){ argv = &argv[1]; fl_bg = TRUE; } +#endif /* Catch Ctrl-C to break simulations */ oldHandler = signal(SIGINT,ft_sigintr); @@ -415,7 +444,7 @@ static int _run(int argc,char **argv){ strcat(buf," "); } - +#ifdef HAVE_LIBPTHREAD /* run in the background */ if(fl_bg){ if(fl_running) _thread_stop(); @@ -449,6 +478,9 @@ static int _run(int argc,char **argv){ cp_evloop(buf); } } +#else + cp_evloop(buf); +#endif /*HAVE_LIBPTHREAD*/ signal(SIGINT,oldHandler); return TCL_OK; } @@ -471,12 +503,13 @@ static int _spice_dispatch TCL_CMDPROCARGS(clientData,interp,argc,argv) { return _run(argc-1,(char **)&argv[1]); } +#ifdef HAVE_LIBPTHREAD /*Checks if spice is runnuing in the background */ static int running TCL_CMDPROCARGS(clientData,interp,argc,argv) { Tcl_SetObjResult(interp,Tcl_NewIntObj((long) (fl_running && !fl_exited))); return TCL_OK; } - +#endif /**************************************/ /* plot manipulation functions */ @@ -1098,7 +1131,9 @@ struct triggerEvent { struct triggerEvent *eventQueue=NULL; struct triggerEvent *eventQueueEnd=NULL; +#ifdef HAVE_LIBPTHREAD pthread_mutex_t triggerMutex; +#endif struct watch { struct watch *next; @@ -1114,14 +1149,18 @@ struct watch *watches=NULL; int Tcl_ExecutePerLoop() { struct watch *current; - + +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&vectors[0].mutex); pthread_mutex_lock(&triggerMutex); +#endif for(current=watches;current;current = current->next) { vector *v; v = &vectors[current->vector]; +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&v->mutex); +#endif if((current->type > 0 && current->state && v->data[v->length-1] > current->Vmax) || (current->type < 0 && current->state && v->data[v->length-1] < current->Vmin) ) { @@ -1149,18 +1188,24 @@ int Tcl_ExecutePerLoop() { if((current->type > 0 && v->data[v->length-1] < current->Vmin) || (current->type < 0 && v->data[v->length-1] > current->Vmax)) current->state = 1; - pthread_mutex_unlock(&v->mutex); +#ifdef HAVE_LIBPTHREAD + pthread_mutex_unlock(&v->mutex); +#endif } +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&triggerMutex); pthread_mutex_unlock(&vectors[0].mutex); - +#endif + return 0; } static int resetTriggers() { +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&triggerMutex); +#endif while(watches) { struct watch *tmp = watches; @@ -1176,7 +1221,9 @@ static int resetTriggers() { eventQueueEnd = NULL; +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&triggerMutex); +#endif return 0; } @@ -1207,7 +1254,9 @@ static int registerTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){ return TCL_ERROR; } else index = i; +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&triggerMutex); +#endif tmp = (struct watch *)MALLOC(sizeof(struct watch)); @@ -1224,7 +1273,9 @@ static int registerTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){ watches->Vmin = atof(argv[2]); watches->Vmax = atof(argv[3]); +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&triggerMutex); +#endif return TCL_OK; } @@ -1258,7 +1309,9 @@ static int unregisterTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){ else type = 1; +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&triggerMutex); +#endif cut = &watches; @@ -1275,8 +1328,10 @@ static int unregisterTrigger TCL_CMDPROCARGS(clientData,interp,argc,argv){ tmp = tmp->next; } +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&triggerMutex); - +#endif + return TCL_OK; } @@ -1294,8 +1349,10 @@ static int popTriggerEvent TCL_CMDPROCARGS(clientData,interp,argc,argv){ struct triggerEvent *popedEvent; Tcl_Obj *list; +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&triggerMutex); - +#endif + popedEvent = eventQueue; eventQueue = popedEvent->next; @@ -1315,7 +1372,9 @@ static int popTriggerEvent TCL_CMDPROCARGS(clientData,interp,argc,argv){ FREE(popedEvent); +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&triggerMutex); +#endif } return TCL_OK; @@ -1332,13 +1391,17 @@ static int listTriggers TCL_CMDPROCARGS(clientData,interp,argc,argv){ list = Tcl_NewListObj(0,NULL); +#ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&triggerMutex); +#endif for(tmp=watches;tmp;tmp=tmp->next) Tcl_ListObjAppendElement(interp,list,Tcl_NewStringObj(vectors[tmp->vector].name,strlen(vectors[tmp->vector].name))); +#ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&triggerMutex); - +#endif + Tcl_SetObjResult(interp,list); return TCL_OK; @@ -1406,8 +1469,10 @@ int Spice_Init(Tcl_Interp *interp) { ARCHsize = 1; /* init the mutex */ +#ifdef HAVE_LIBPTHREAD pthread_mutex_init(&triggerMutex,NULL); - +#endif + /*register functions*/ for (i = 0;(key = cp_coms[i].co_comname); i++) { sprintf(buf,"%s%s",TCLSPICE_prefix,key); @@ -1424,13 +1489,10 @@ int Spice_Init(Tcl_Interp *interp) { Tcl_CreateCommand(interp, TCLSPICE_prefix "lastVector", lastVector, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "spice", _spice_dispatch, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "get_output", get_output, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); - 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); Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_variables", plot_variables, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_get_value", plot_get_value, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "plot_datapoints", plot_datapoints, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); @@ -1443,6 +1505,12 @@ int Spice_Init(Tcl_Interp *interp) { Tcl_CreateCommand(interp, TCLSPICE_prefix "unregisterTrigger", unregisterTrigger, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateCommand(interp, TCLSPICE_prefix "listTriggers", listTriggers, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); +#ifdef HAVE_LIBPTHREAD + 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 "running", running, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); +#endif + Tcl_LinkVar(interp, TCLSPICE_prefix "steps_completed", (char *)&steps_completed, TCL_LINK_READ_ONLY|TCL_LINK_INT); Tcl_LinkVar(interp, TCLSPICE_prefix "blt_vnum", (char *)&blt_vnum, TCL_LINK_READ_ONLY|TCL_LINK_INT); } @@ -1478,8 +1546,11 @@ int tcl_vfprintf(FILE *f, const char *fmt, va_list args_in) char *outptr, *bigstr = NULL, *finalstr = NULL; int i, nchars, result, escapes = 0; - if((f != stdout && f != stderr) || - ( fl_running && bgtid == pthread_self()) ) + if((f != stdout && f != stderr) +#ifdef HAVE_LIBPTHREAD + || ( fl_running && bgtid == pthread_self()) +#endif + ) return vfprintf(f,fmt,args_in); strcpy (outstr + 19, (f == stderr) ? "err \"" : "out \""); @@ -1576,8 +1647,10 @@ void tcl_stdflush(FILE *f) static char stdstr[] = "flush stdxxx"; char *stdptr = stdstr + 9; +#ifdef HAVE_LIBPTHREAD if ( fl_running && bgtid == pthread_self()) return; +#endif Tcl_SaveResult(spice_interp, &state); strcpy(stdptr, (f == stderr) ? "err" : "out"); diff --git a/src/xspice/mif/mif_inp2.c b/src/xspice/mif/mif_inp2.c index 55f6ac1d4..b85ef0947 100755 --- a/src/xspice/mif/mif_inp2.c +++ b/src/xspice/mif/mif_inp2.c @@ -188,7 +188,6 @@ card *current; /* the card we are to parse */ /* and return a pointer to its structure in 'thismodel' */ current->error = MIFgetMod(ckt, model, &thismodel, tab); - tfree(name); if(current->error) { return; @@ -196,8 +195,8 @@ card *current; /* the card we are to parse */ #ifdef TRACE /* SDB debug statement */ - printf("In MIF_INP2A, about to get ports on line %s\n", - current->line); + printf("In MIF_INP2A, after tokenizing, name = %s, model = %s\n", + name, model); #endif @@ -232,21 +231,20 @@ card *current; /* the card we are to parse */ /* and reading the first token following */ line = current->line; - MIFgettok(&line); /* read instance name again . . . .*/ + MIFgettok(&line); + next_token = MIFget_token(&line,&next_token_type); + + + /* loop through the fixed number of connections expected */ - /******* loop through the fixed number of connections expected *******/ for(i = 0; i < DEVices[type]->DEVpublic.num_conn; i++) { /* there better be at least one more token besides the model name */ if(*line == '\0') { - LITERR("Encountered end of line before all connections were found in model."); + LITERR("Missing connections on A device"); return; } - /* now get next token, should be a % after this statement */ - next_token = MIFget_token(&line,&next_token_type); - - /* prepare a pointer for fast access to info about this connection */ conn_info = &(DEVices[type]->DEVpublic.conn[i]); @@ -254,34 +252,6 @@ card *current; /* the card we are to parse */ def_port_type = conn_info->default_port_type; def_port_type_str = conn_info->default_type; - - /* Now get real info about connection type (instead of default info) */ - if(next_token_type == MIF_PERCENT_TOK) { /* next_token_type should be a % */ - - /* get the port type identifier and check it for validity */ - next_token = MIFget_token(&line,&next_token_type); - MIFget_port_type(ckt, - tab, - current, - &line, - &next_token, - &next_token_type, - &def_port_type, - &def_port_type_str, - conn_info, - &status); - if(status == MIF_ERROR) - return; - } - else { - LITERR("Non percent token encountered when expecting MIF_PERCENT_TOK"); - return; - } - - - /* At this point, next_token should hold the token *after* the port type - identified (%v, %id, etc). */ - /* set analog and event_driven flags on instance and model */ if((def_port_type == MIF_DIGITAL) || (def_port_type == MIF_USER_DEFINED)) { fast->event_driven = MIF_TRUE; @@ -292,8 +262,8 @@ card *current; /* the card we are to parse */ mdfast->analog = MIF_TRUE; } - /* check for a null connection and continue to next connection if found */ + if(next_token_type == MIF_NULL_TOK) { /* make sure null is allowed */ @@ -315,13 +285,10 @@ card *current; /* the card we are to parse */ fast->conn[i]->is_null = MIF_FALSE; } + /* process connection as appropriate for scalar or array */ - - /* ===== process connection as appropriate for scalar or array ====== */ if(! conn_info->is_array) { /* a scalar connection - the simpler case */ - /* At this point, next_token should hold the first netname in the port netlist. */ - /* do a couple of error checks */ if(next_token_type == MIF_LARRAY_TOK) { LITERR("ERROR - Scalar connection expected, [ found"); @@ -348,27 +315,44 @@ card *current; /* the card we are to parse */ 0, /* port index for scalar connection */ &status); - /* upon leaving MIFget_port, we should be *ready* to read a % with the next - get_token */ - if(status == MIF_ERROR) return; fast->conn[i]->size = 1; } - else { /* ====== the connection is an array - much to be done ... ====== */ + else { /* the connection is an array - much to be done ... */ - /* At this point, the next_token should be a [ */ + /* get the leading port type for the array if any */ + /* it will distribute across all ports inside the braces */ + /* overriding the default type in the interface spec */ + + if(next_token_type == MIF_PERCENT_TOK) { + + /* get the port type identifier and check it for validity */ + next_token = MIFget_token(&line,&next_token_type); + MIFget_port_type(ckt, + tab, + current, + &line, + &next_token, + &next_token_type, + &def_port_type, + &def_port_type_str, + conn_info, + &status); + if(status == MIF_ERROR) + return; + } /* check for required leading array delim character and eat it if found */ if(next_token_type != MIF_LARRAY_TOK) { LITERR("Missing [, an array connection was expected"); return; } - else /* eat the [ */ + else next_token = MIFget_token(&line,&next_token_type); - /*------ get and process ports until ] is encountered ------*/ + /* get and process ports until ] is encountered */ for(j = 0; (next_token_type != MIF_RARRAY_TOK) && @@ -402,24 +386,16 @@ card *current; /* the card we are to parse */ if(status == MIF_ERROR) return; - } /*------ end of for loop until ] is encountered ------*/ - - /* At this point, next_token should hold the next token after the - port netnames. This token should be a ]. */ + } /* make sure we exited because the end of the array connection */ - /* was reached. If so, eat the closing array delimiter ] */ + /* was reached. If so, eat the closing array delimiter */ if(*line == '\0') { LITERR("Missing ] in array connection"); return; } - - /* else { - * next_token = MIFget_token(&line,&next_token_type); - * } - */ - - /* At this point, the next time we get_token, we should get a % */ + else + next_token = MIFget_token(&line,&next_token_type); /* record the number of ports found for this connection */ if(j < 1) { @@ -428,13 +404,12 @@ card *current; /* the card we are to parse */ } fast->conn[i]->size = j; - } /* ====== array connection processing ====== */ + } /* array connection processing */ /* be careful about putting stuff here, there is a 'continue' used */ /* in the processing of NULL connections above */ - - } /******* for number of connections *******/ + } /* for number of connections */ /* *********************** */ @@ -443,12 +418,8 @@ card *current; /* the card we are to parse */ /* check for too many connections */ - /* At this point, we should have eaten all the net connections. At - this point, line should hold only the remainder of the model line (i.e. - the model name). */ - - if(strcmp(line,name) != 0) { - LITERR("Too many connections -- expecting model name but encountered other tokens."); + if(*line != '\0') { + LITERR("Too many connections"); return; } @@ -615,17 +586,7 @@ static void MIFinit_inst( /* MIFget_port_type -This function gets the port type identifier and checks it for validity. It also -replaces false default information in conn_info with the real info based upon -the discovered port type string. - -When we call it, we expect that the next token type (sent from above) -should be the port type (MIF_STRING_TOK type). That is, we should be sitting right -on the def of the port type (i.e. %vnam, %vd, %id, etc.) Note that the parser -should have stripped the % already. - -Upon return, this fcn should leave next_token holding the token *after* the -port type (i.e. the thing after vnam, v, vd, id, etc). +This function gets the port type identifier and checks it for validity. */ @@ -682,20 +643,8 @@ MIFget_port_type( LITERR("Port type is invalid"); *status = MIF_ERROR; } - else { - - /* Fix by SDB so that the netlist parser uses the actual nature - of the port instead of the default state to decide if it is an array. */ - if ( (*port_type == MIF_DIFF_VOLTAGE) || - (*port_type == MIF_DIFF_CURRENT) || - (*port_type == MIF_DIFF_CONDUCTANCE) || - (*port_type == MIF_DIFF_RESISTANCE) ) { - conn_info->is_array = 1; - } - + else *status = MIF_OK; - } - } @@ -709,13 +658,6 @@ MIFget_port This function processes a port being parsed, either single ended, or both connections of a differential. - -When we call this fcn, next_token should be the *first* netname in the port -net list. Depending upon the type of port, this fcn should eat the appropriate -number of net tokens. - -When we leave this fcn, next_token should hold the next token after the last -netname processed. */ @@ -745,6 +687,27 @@ MIFget_port( char *node; + /* get the leading port type if any */ + + if(*next_token_type == MIF_PERCENT_TOK) { + + /* get the port type identifier and check it for validity */ + *next_token = MIFget_token(line, next_token_type); + MIFget_port_type(ckt, + tab, + current, + line, + next_token, + next_token_type, + &def_port_type, + &def_port_type_str, + conn_info, + status); + + if(*status == MIF_ERROR) { + return; + } + } /* allocate space in the instance data struct for this port */ if(port_num == 0) { diff --git a/src/xspice/mif/mifutil.c b/src/xspice/mif/mifutil.c index 8e69a04e7..54540cc42 100755 --- a/src/xspice/mif/mifutil.c +++ b/src/xspice/mif/mifutil.c @@ -314,11 +314,8 @@ This function allocates a new copy of a string. char *MIFcopy(char *str) { - char *temp; - - /* Allocate space for the string and then copy it */ - temp = MALLOC(strlen(str) + 1); - strcpy(temp,str); - - return(temp); + if(str) + return copy(str); + else + return NULL; }