********> bugfix.44 Author: Bill Ross Date: Aug 2 1999 Programs: xleap Severity: Possible crash Description: Mistakes in memory use could cause crash in the Unit Editor's 'Build' and 'Add H and Build' commands when rings are present in the unit. Fix: Replace ring.c with the following: --------------------------------------------------------------------------- /* * ************************************************************************ * LEAP * * * * Copyright (c) 1992, 1995 * * Regents of the University of California * * All Rights Reserved. * * * * This software provided pursuant to a license agreement containing * * restrictions on its disclosure, duplication, and use. This software * * contains confidential and proprietary information, and may not be * * extracted or distributed, in whole or in part, for any purpose * * whatsoever, without the express written permission of the authors. * * This notice, and the associated author list, must be attached to * * all copies, or extracts, of this software. Any additional * * restrictions set forth in the license agreement also apply to this * * software. * ************************************************************************ * * * Designed by: Christian Schafmeister * * Author: Christian Schafmeister * * * * VERSION: 1.0 * * Programmers: * * Christian Schafmeister * * David Rivkin * * * * Principal Investigator: Peter A. Kollman * * * ************************************************************************ * * Description: * Maintain a RING structure. A doubly linked list of * nodes where insertions can be made relative to other * elements within the RING. Each node of the RING * has a pointer to an arbitrary data type. * */ #include "basics.h" #include "ring.h" /* *------------------------------------------------------------------- * * Private routines */ /* * zrnPRingCreateNode * * Author: Christian Schafmeister (1991) * * Create and return a RING node. */ FUNC RINGNODEt* zrnPRingCreateNode() { RINGNODEt* rnPNew; BEGIN MALLOC( rnPNew, RINGNODEt*, sizeof(RINGNODEt) ); rnPNew->rnPPrev = NULL; rnPNew->rnPNext = NULL; rnPNew->PData = NULL; RETURN(rnPNew); } /* * zRingNodeDestroy * * Author: Christian Schafmeister (1991) * * Destroy the RING node and set the pointer to NULL. */ FUNC void zRingNodeDestroy( rnPPNode ) RINGNODEt** rnPPNode; { BEGIN FREE( (*rnPPNode) ); *rnPPNode = NULL; END } /* * zrnPRingFind * * Author: Christian Schafmeister (1991) * * Find the node that has the data the caller wants. * If PData is NULL then just return the first node. */ FUNC RINGNODEt* zrnPRingFind( rRing, PData ) RING rRing; GENP PData; { RINGLOOP rlSearch; GENP PCur; BEGIN if ( PData == NULL ) RETURN(rRing->rnPFirst); rlSearch = rlRingLoop(rRing); while ( (PCur = PRingNext(&rlSearch)) != NULL ) { if ( PCur == PData ) RETURN(rnPRingNode(rlSearch)); } RETURN(NULL); } /* *================================================================= * * Public routines * */ /* * rRingCreate * * Author: Christian Schafmeister (1991) * * Create and return a RING. */ FUNC RING rRingCreate() { RING rNew; BEGIN MALLOC( rNew, RING, sizeof(RINGt) ); rNew->iElements = 0; rNew->rnPFirst = NULL; RETURN(rNew); } /* * RingDestroy * * Author: Christian Schafmeister (1991) * * Destroy the RING. * The caller is expected to take care of the contents. */ FUNC void RingDestroy( rPRing ) RING* rPRing; { RINGLOOP rlElements; /* Destroy all of the nodes of the RING */ BEGIN rlElements = rlRingLoop(*rPRing); while ( PRingNext(&rlElements) != NULL ) { FREE( rnPRingNode(rlElements) ); } FREE( *rPRing ); END } /* * RingAfterAdd * * Author: Christian Schafmeister (1991) * * Add a node to the RING directly after the node with * the caller specified data in (PAfter). * If PAfter is NULL then the data will be added after the * first node. */ FUNC void RingAfterAdd( rRing, PAfter, PData ) RING rRing; GENP PAfter; GENP PData; { RINGNODEt* rnPCur; RINGNODEt* rnPNew; BEGIN rnPNew = zrnPRingCreateNode(); rnPNew->PData = PData; /* If the RING is empty then just add the node */ if ( bRingEmpty(rRing) ) { rRing->rnPFirst = rnPNew; } else { rnPCur = zrnPRingFind( rRing, PAfter ); if (rnPCur == NULL) DFATAL((" PAfter missing\n" )); rnPNew->rnPPrev = rnPCur; rnPNew->rnPNext = rnPCur->rnPNext; rnPCur->rnPNext = rnPNew; if (rnPNew->rnPNext != NULL) rnPNew->rnPNext->rnPPrev = rnPNew; } rRing->iElements++; END } /* * RingBeforeAdd * * Author: Christian Schafmeister (1991) * * Add a node to the RING directly before the node with * the caller specified data in (PBefore). */ FUNC void RingBeforeAdd( rRing, PBefore, PData ) RING rRing; GENP PBefore; GENP PData; { RINGNODEt* rnPCur; RINGNODEt* rnPNew; BEGIN rnPNew = zrnPRingCreateNode(); rnPNew->PData = PData; /* If the RING is empty then just add the node */ if ( bRingEmpty(rRing) ) { rRing->rnPFirst = rnPNew; } else { rnPCur = zrnPRingFind( rRing, PBefore ); if (rnPCur == NULL) DFATAL((" PBefore missing\n" )); rnPNew->rnPNext = rnPCur; rnPNew->rnPPrev = rnPCur->rnPPrev; rnPCur->rnPPrev = rnPNew; if (rnPNew->rnPPrev != NULL) rnPNew->rnPPrev->rnPNext = rnPNew; if (rRing->rnPFirst == rnPCur) rRing->rnPFirst = rnPNew; } rRing->iElements++; END } /* * rlRingLoop * * Author: Christian Schafmeister (1991) * * Set up a loop over the elements of the RING. */ FUNC RINGLOOP rlRingLoop( rRing ) RING rRing; { RINGLOOP rlNew; BEGIN rlNew.iCount = iRingSize(rRing); rlNew.rnPNext = rRing->rnPFirst; rlNew.rnPCur = NULL; RETURN(rlNew); } /* * PRingNext * * Author: Christian Schafmeister (1991) * * Return a pointer to the next piece of data in the RING. */ FUNC GENP PRingNext( rlPLoop ) RINGLOOP* rlPLoop; { GENP PData; BEGIN rlPLoop->iCount--; if ( rlPLoop->iCount < 0 ) RETURN(NULL); PData = rlPLoop->rnPNext->PData; rlPLoop->rnPCur = rlPLoop->rnPNext; rlPLoop->rnPNext = rlPLoop->rnPNext->rnPNext; RETURN(PData); } /* * bRingRemove * * Author: Christian Schafmeister (1991) * * Remove the node with the data PData from the RING. */ FUNC BOOL bRingRemove( rRing, PData ) RING rRing; GENP PData; { RINGNODEt* rnPNode; /* Look for the data in the RING */ BEGIN rnPNode = zrnPRingFind( rRing, PData ); if ( rnPNode == NULL ) RETURN(FALSE); /* Remove the node from the RING */ rRing->iElements--; if ( rRing->iElements == 0 ) { zRingNodeDestroy( &rnPNode ); rRing->rnPFirst = NULL; } else { if (rnPNode->rnPPrev != NULL) rnPNode->rnPPrev->rnPNext = rnPNode->rnPNext; if (rnPNode->rnPNext != NULL) rnPNode->rnPNext->rnPPrev = rnPNode->rnPPrev; if (rRing->rnPFirst == rnPNode) rRing->rnPFirst = rnPNode->rnPNext; zRingNodeDestroy( &rnPNode ); } RETURN(TRUE); } ---------------------------------------------------------------------------