From cbdd811aa5483729616ac0ce30ec41f29cc3d6ff Mon Sep 17 00:00:00 2001 From: sjborley Date: Thu, 26 May 2005 19:29:52 +0000 Subject: [PATCH] Fixed bug with define (see bug reference [ 999546 ] 'define' is broken in ngspice-15). free_pnode() now copes properly with parse trees that reuse leaf nodes. --- BUGS | 17 +-------------- ChangeLog | 5 +++++ src/frontend/define.c | 12 +++++++++-- src/frontend/parse.c | 48 ++++++++++++++++++++++++++++++++---------- src/frontend/parse.h | 4 +++- src/frontend/vectors.c | 3 ++- src/frontend/vectors.h | 4 +++- src/include/pnode.h | 2 ++ 8 files changed, 63 insertions(+), 32 deletions(-) diff --git a/BUGS b/BUGS index b9b81c22b..adb153ae4 100644 --- a/BUGS +++ b/BUGS @@ -1,21 +1,6 @@ -This file contais a list of known but not yet fixed bugs in ngspice. +This file contains a list of known but not yet fixed bugs in ngspice. =========================================================================== -Rework15fixed: - -* define/let commands: - the following code causes a segmentation fault: - - ngspice 1 -> define max(x,y) ( x gt y ) * x + ( x le y ) * y - ngspice 2 -> let z = max(2,3) - vec_free: Internal Error: not in plot - Segmentation fault (core dumped) - - The problem seems caused by the attempt to free an already freed - memory area in free_pnode and free_vec functions. - ---------------------------------------------------------------------------- - * output redirection: ngspice 1 -> print v(1) > data.txt diff --git a/ChangeLog b/ChangeLog index ec469b99f..c4c65437d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2005-05-26 Steven Borley + + * Fixed bug with define (see bug reference [ 999546 ] 'define' is broken + in ngspice-15). + 2005-05-23 Steven Borley * Fixed a divide-by-zero bug in the MOS level=2 device model diff --git a/src/frontend/define.c b/src/frontend/define.c index 94be14b95..f9bcfe548 100644 --- a/src/frontend/define.c +++ b/src/frontend/define.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group +$Id$ **********/ /* @@ -339,25 +340,32 @@ trcopy(struct pnode *tree, char *args, struct pnode *nn) } else if (tree->pn_func) { pn = alloc(struct pnode); + pn->pn_use = 0; + pn->pn_name = NULL; pn->pn_value = NULL; /* pn_func are pointers to a global constant struct */ pn->pn_func = tree->pn_func; pn->pn_op = NULL; pn->pn_left = trcopy(tree->pn_left, args, nn); + pn->pn_left->pn_use++; pn->pn_right = NULL; pn->pn_next = NULL; } else if (tree->pn_op) { pn = alloc(struct pnode); + pn->pn_use = 0; + pn->pn_name = NULL; pn->pn_value = NULL; pn->pn_func = NULL; /* pn_op are pointers to a global constant struct */ pn->pn_op = tree->pn_op; pn->pn_left = trcopy(tree->pn_left, args, nn); - if (pn->pn_op->op_arity == 2) + pn->pn_left->pn_use++; + if (pn->pn_op->op_arity == 2) { pn->pn_right = trcopy(tree->pn_right, args, nn); - else + pn->pn_right->pn_use++; + } else pn->pn_right = NULL; pn->pn_next = NULL; } else { diff --git a/src/frontend/parse.c b/src/frontend/parse.c index 20bd816f5..a34eb3e95 100644 --- a/src/frontend/parse.c +++ b/src/frontend/parse.c @@ -66,6 +66,7 @@ ft_getpnames(wordlist *wl, bool check) if (pn) { lpn->pn_next = p; + pn->pn_next->pn_use++; lpn = p; } else pn = lpn = p; @@ -713,7 +714,7 @@ struct func func_uminus = { "minus", cx_uminus }; struct func func_not = { "not", cx_not }; -/* Binop node. */ +/* Binary operator node. */ static struct pnode * mkbnode(int opnum, struct pnode *arg1, struct pnode *arg2) @@ -728,16 +729,20 @@ mkbnode(int opnum, struct pnode *arg1, struct pnode *arg2) fprintf(cp_err, "mkbnode: Internal Error: no such op num %d\n", opnum); p = alloc(struct pnode); + p->pn_use = 0; p->pn_value = NULL; + p->pn_name = NULL; /* sjb */ p->pn_func = NULL; p->pn_op = o; p->pn_left = arg1; + if(p->pn_left) p->pn_left->pn_use++; p->pn_right = arg2; + if(p->pn_right) p->pn_right->pn_use++; p->pn_next = NULL; return (p); } -/* Unop node. */ +/* Unary operator node. */ static struct pnode * mkunode(int op, struct pnode *arg) @@ -754,9 +759,12 @@ mkunode(int op, struct pnode *arg) op); p->pn_op = o; + p->pn_use = 0; p->pn_value = NULL; + p->pn_name = NULL; /* sjb */ p->pn_func = NULL; p->pn_left = arg; + if(p->pn_left) p->pn_left->pn_use++; p->pn_right = NULL; p->pn_next = NULL; return (p); @@ -818,11 +826,13 @@ mkfnode(char *func, struct pnode *arg) } p = alloc(struct pnode); + p->pn_use = 0; p->pn_name = NULL; p->pn_value = NULL; p->pn_func = f; p->pn_op = NULL; p->pn_left = arg; + if(p->pn_left) p->pn_left->pn_use++; p->pn_right = NULL; p->pn_next = NULL; return (p); @@ -840,6 +850,7 @@ mknnode(double number) p = alloc(struct pnode); v = alloc(struct dvec); ZERO(v, struct dvec); + p->pn_use = 0; p->pn_name = NULL; p->pn_value = v; p->pn_func = NULL; @@ -875,6 +886,7 @@ mksnode(char *string) struct pnode *p; p = alloc(struct pnode); + p->pn_use = 0; p->pn_name = NULL; p->pn_func = NULL; p->pn_op = NULL; @@ -910,18 +922,32 @@ mksnode(char *string) return (p); } - +/* Don't call this directly, always use the free_pnode() macro. + The linked pnodes do not necessarily form a perfect tree as some nodes get + reused. Hence, in this recursive walk trough the 'tree' we only free node + that have their pn_use value at zero. Nodes that have pn_use values above + zero have the link severed and their pn_use value decremented. + In addition, we don't walk past nodes with pn_use values avoid zero, just + in case we have a circular reference (this probable does not happen in + practice, but it does no harm playing safe) */ void -free_pnode(struct pnode *t) +free_pnode_x(struct pnode *t) { if (!t) return; - free_pnode(t->pn_left); - free_pnode(t->pn_right); - free_pnode(t->pn_next); - tfree(t->pn_name); /* va: it is a copy() of original string, can be free'd */ - if (t->pn_value) - vec_free(t->pn_value); /* patch by Stefan Jones */ - tfree(t); + + /* don't walk past node used elsewhere. We decrement the pn_use value here, + but the link gets severed by the action of the free_pnode() macro */ + if(t->pn_use) + t->pn_use--; + else { + free_pnode(t->pn_left); + free_pnode(t->pn_right); + free_pnode(t->pn_next); + tfree(t->pn_name); /* va: it is a copy() of original string, can be free'd */ + if (t->pn_value) + vec_free(t->pn_value); /* patch by Stefan Jones */ + tfree(t); + } } diff --git a/src/frontend/parse.h b/src/frontend/parse.h index 390f9afb5..06ada8412 100644 --- a/src/frontend/parse.h +++ b/src/frontend/parse.h @@ -1,6 +1,7 @@ /************* * Header file for parse.c * 1999 E. Rouat + * $Id$ ************/ #ifndef _PARSE_H @@ -10,7 +11,8 @@ #include struct pnode * ft_getpnames(wordlist *wl, bool check); -void free_pnode(struct pnode *t); +#define free_pnode(ptr) free_pnode_x(ptr); ptr=NULL; +void free_pnode_x(struct pnode *t); #endif diff --git a/src/frontend/vectors.c b/src/frontend/vectors.c index 6480df751..3ac5a1c1e 100644 --- a/src/frontend/vectors.c +++ b/src/frontend/vectors.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group +$Id$ **********/ /* @@ -590,7 +591,7 @@ vec_gc(void) */ void -vec_free(struct dvec *v) +vec_free_x(struct dvec *v) { struct plot *pl; struct dvec *lv; diff --git a/src/frontend/vectors.h b/src/frontend/vectors.h index 5a8207ef1..e0dfbf14d 100644 --- a/src/frontend/vectors.h +++ b/src/frontend/vectors.h @@ -1,6 +1,7 @@ /************* * Header file for vectors.c * 1999 E. Rouat + * $Id$ ************/ #ifndef VECTORS_H_INCLUDED @@ -16,7 +17,8 @@ struct dvec * vec_copy(struct dvec *v); struct plot * plot_alloc(char *name); void vec_new(struct dvec *d); void vec_gc(void); -void vec_free(struct dvec *v); +#define vec_free(ptr) vec_free_x(ptr); ptr=NULL +void vec_free_x(struct dvec *v); bool vec_eq(struct dvec *v1, struct dvec *v2); char * vec_basename(struct dvec *v); void plot_setcur(char *name); diff --git a/src/include/pnode.h b/src/include/pnode.h index d965b588a..a20b2f2f2 100644 --- a/src/include/pnode.h +++ b/src/include/pnode.h @@ -1,3 +1,4 @@ +/* $Id$ */ #ifndef _PNODE_H #define _PNODE_H @@ -9,6 +10,7 @@ struct pnode { struct pnode *pn_left; /* Left branch or function argument. */ struct pnode *pn_right; /* Right branch. */ struct pnode *pn_next; /* For expression lists. */ + int pn_use; /* usage counter */ } ; #endif