static char *SccsId = "@(#)lump.c 4.14 (TU-Delft) 06/01/93";
/**********************************************************

Name/Version      : space/4.14

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
		  : N.P. van der Meijs
Creation date     : 15-Mar-1988
Modified by       :
Modification date :


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1988. All rights reserved.
**********************************************************/
#include <stdio.h>
#include "include/config.h"
#include "include/type.h"
#include "aux/aux.h"
#include "lump/define.h"
#include "lump/extern.h"
#include "lump/lump.h"

extern bool_t optAccWL;
extern char prickName[];


subnodeNew (subn, type)
subnode_t * subn;
char type;
{
    node_t * n;
    group_t * grp;

    subn -> node = NEW (node_t, 1);
    subn -> next_node = NULL;

    n = subn -> node;
    n -> flag = 0;
    n -> keep = 0;
    n -> names = NULL;
    n -> subs = subn;
    if (optFineNtw)
	n -> type = 't';
    else
	n -> type = type;
    n -> gndCap = 0;
    n -> con = NULL;
    n -> cap = NULL;
    n -> res_cnt = 0;
    n -> cap_cnt = 0;
    n -> ports = NULL;
    n -> netEq = NULL;
    n -> pin = NULL;

    inSubnod++;
    currIntSubnod++;
    if (currIntSubnod > maxIntSubnod)
	maxIntSubnod = currIntSubnod;

    inNod++;
    currIntNod++;
    if (currIntNod > maxIntNod)
	maxIntNod = currIntNod;
    if (currIntNod + outNod > maxNodIfKept)
	maxNodIfKept = currIntNod + outNod;
    if (currIntNod + condemnCnt > maxIntANod)
	maxIntANod = currIntNod + condemnCnt;

    if (node_list) 
	node_list -> prev = n;
    n -> prev = NULL;
    n -> next = node_list;   /* place new node at beginning of node_list */
    node_list = n;

    grp = NEW (group_t, 1);

    /* NEW !! */
    n -> grp = grp;
    n -> gr_father = n; 		/* n is a root */
    n -> n_children = 0;
    n -> condemned = FALSE;

    grp -> nod_cnt = 1;
    grp -> res_cnt = 0;
    grp -> cap_cnt = 0;
    grp -> notReady = 1;
    grp -> supply = 0;
    grp -> prick = 0;
    if (onlyRes)
	grp -> noResis = 1;
    else
	grp -> noResis = 0;
    grp -> rSource = -1.0;
    if ((prePass2 && (optSelectiveRes || optPrick)) || optBackInfo) {
	grp -> tileInfo = NEW (groupTileInfo_t, 1);
	grp -> tileInfo -> resWeight = 0.0;
	grp -> tileInfo -> tiles = NULL;
    }
    else
	grp -> tileInfo = NULL;
    currIntGrp++;
    if (currIntGrp > maxIntGrp)
	maxIntGrp = currIntGrp;
}

subnodeJoin (subnA, subnB)
subnode_t * subnA;
subnode_t * subnB;
{
    node_t *nA;
    node_t *nB;

    if (noSubnodeJoin) {
	noSubnodeJoin = FALSE;
	return;
    }

    nA = subnA -> node;
    nB = subnB -> node;

    nodeJoin (nA, nB);
}

nodeJoin (nA, nB)
node_t *nA;
node_t *nB;
{
    element_t * el;
    element_t * help;
    subnode_t * last;
    subnode_t * sub;
    struct group *tmp;

    if (nA == nB) {
	return;
    }

    if (nB -> type == 't') {
	nA -> type = 't';
    }
    else if (nB -> type == 'a' && nA -> type == 'i') {
	nA -> type = 'a';
    }

    if (nB -> keep)
	nA -> keep = 1;  /* or was already 1 */


    nodeRelJoin (nA, nB);

    last = NULL;
    for (sub = nB -> subs; sub != NULL; sub = sub -> next_node) {
	sub -> node = nA;
	last = sub;
    }
    if (last) {
        last -> next_node = nA -> subs;
        nA -> subs = nB -> subs;
    }

    nA -> gndCap += nB -> gndCap;

    if (Grp (nA) != Grp (nB)) {
	mergeGrps (nA, nB);
    }
    Grp (nA) -> nod_cnt--;
    if (Grp (nA) -> notReady > 0)
	Grp (nA) -> notReady--;
    /* account for not ready only once */

    if (Grp (nA) -> nod_cnt > maxIntNodGrp)
	maxIntNodGrp = Grp (nA) -> nod_cnt;
    if (Grp (nA) -> cap_cnt > maxIntCapGrp)
	maxIntCapGrp = Grp (nA) -> cap_cnt;
    if (Grp (nA) -> res_cnt > maxIntResGrp)
	maxIntResGrp = Grp (nA) -> res_cnt;

    nodeDel (nB);
}

nodeRelJoin (nA, nB)
node_t * nA;
node_t * nB;
{
    terminal_t * tm;
    subnode_t * last;
    subnode_t * sub;
    netEquiv_t * ne;
    netEquiv_t * ne2;
    netEquiv_t * neInvest;
    netEquiv_t * neOrig;
    nodeTorLink_t * nTL;
    nodeTorLink_t * help_nTL;
    int doubleFound;

    nTL = nB -> ports;
    while (nTL != NULL) {
	nTLinkAdd (nTL -> type, nA, nTL -> t);
	help_nTL = nTL;
	nTL = nTL -> nextN;
	nTLinkDel (help_nTL);
    }

    tm = nA -> names;
    if (tm == NULL) {
	nA -> names = nB -> names;
    }
    else {
	while (tm -> next != NULL) {
	    tm = tm -> next;
	}
	tm -> next = nB -> names;
    }
    nB -> names = NULL;

    if (nA -> netEq == NULL) {
	nA -> netEq = nB -> netEq;
	nB -> netEq = NULL;

	if (optDsConJoin) {
	    ne = nA -> netEq;
	    while (ne != NULL) {
		ne -> net = nA;
		ne = ne -> next;
	    }
	}

	/* note: for !optDsConJoin member 'net' is currently not updated */
    }
    else if (nB -> netEq != NULL) {

	if (optDsConJoin) {

	    neOrig = nA -> netEq;

	    while ((neInvest = nB -> netEq) != NULL) {

		nB -> netEq = nB -> netEq -> next;

		doubleFound = 0;

		if (neInvest -> instType == TOR
		&& (neInvest -> term == 'd' || neInvest -> term == 's')) {

		    ne = neInvest -> nextDsRing;
		    while (ne != neInvest) {
			if (ne -> net == nA) {
			    doubleFound = 1;
			    break;
			}
			ne = ne -> nextDsRing;
		    }
		}

		if (doubleFound) {

		    /* drain/source connected ! */
		    /* merge them (and do not add to nA) */

		    /* remove neInvest from ring ! */
		    ne2 = neInvest -> nextDsRing;
		    while (ne2 -> nextDsRing != neInvest)
			ne2 = ne2 -> nextDsRing;
		    ne2 -> nextDsRing = neInvest -> nextDsRing;

		    DISPOSE (neInvest);
		    currNeqv--;
		} 
		else {
		
		    /* just add neInvest to nA */

		    neInvest -> next = nA -> netEq;
		    nA -> netEq = neInvest;
		    neInvest -> net = nA;
		}
	    }
	}
	else {

	    ne = nB -> netEq;
	    while (ne -> next != NULL)
		ne = ne -> next;

	    ne -> next = nA -> netEq;
	    nA -> netEq = nB -> netEq;
	    nB -> netEq = NULL;
	}
    }
    if (nB -> pin) {
	if (nA -> pin) {
	    subnodeDel (nB -> pin);
	    DISPOSE (nB -> pin);
	}
	else
	    nA -> pin = nB -> pin;
    }
}

/* subnodeCopy (subnA, subnB) is a short-hand for
 *    subnodeNew (subnB);
 *    subnodeCopy (subnA, subnB);
 */

subnodeCopy (subnA, subnB)
subnode_t * subnA;
subnode_t * subnB;
{
    if (noSubnodeJoin) {
	noSubnodeJoin = FALSE;
	subnodeNew (subnB);
	return;
    }

    inSubnod++;
    currIntSubnod++;
    if (currIntSubnod > maxIntSubnod)
	maxIntSubnod = currIntSubnod;

    subnB -> node = subnA -> node;
    subnB -> next_node = subnA -> node -> subs;
    subnA -> node -> subs = subnB;
}

nameAdd (subn, tm)
subnode_t * subn;
terminal_t * tm;
{
    node_t * n;
    strRef_t * strR;
    int i, j;
    int len1, len2;
    int match;

    n = subn -> node;
    n -> type = 't';

    if (n -> names == NULL
    || (n -> names -> instName != NULL)
    || ((n -> names -> termX >= 0 || n -> names -> termY >= 0)
	 && tm -> instName == NULL)) {
	tm -> next = n -> names;
	n -> names = tm;
    }
    else {
	tm -> next = n -> names -> next;
	n -> names -> next = tm;
    }

    if ((tm -> termName[0] == 'v' || tm -> termName[0] == 'V')
         && (tm -> termName[1] == 'd' || tm -> termName[1] == 'D')
         && (tm -> termName[2] == 'd' || tm -> termName[2] == 'D')) {
	if (Grp (n) -> supply == 1) {
	    supplyShort ();
	    Grp (n) -> supply = 3;
	}
	else
	    Grp (n) -> supply = 2;
    }
    if (((tm -> termName[0] == 'v' || tm -> termName[0] == 'V')
	 && (tm -> termName[1] == 's' || tm -> termName[1] == 'S')
	 && (tm -> termName[2] == 's' || tm -> termName[2] == 'S'))
        || ((tm -> termName[0] == 'g' || tm -> termName[0] == 'G')
	 && (tm -> termName[1] == 'n' || tm -> termName[1] == 'N')
	 && (tm -> termName[2] == 'd' || tm -> termName[2] == 'D'))) {
	if (Grp (n) -> supply == 2) {
	    supplyShort ();
	    Grp (n) -> supply = 3;
	}
	else
	    Grp (n) -> supply = 1;
    }

    if (optRes && (omitRes || onlyRes) && tm -> instName == NULL) {
	strR = resNetList;
	while (strR != NULL) {

	    /* try to match strR -> str with (a part of) tm -> termName.
	    /* the character '*' may be used at the beginning and at the
	    /* end of strR -> str to denote an arbitrarily string part.
	    */

	    len1 = strlen (strR -> str);
	    len2 = strlen (tm -> termName);

	    if (strR -> str[0] == '*') {
		match = 0;
		for (i = 0; i < len2; i++) {
		    j = 0;
		    while (1 + j < len1 && i + j < len2
			   && strR -> str[1+j] != '*'
			   && strR -> str[1+j] == tm -> termName[i+j]) {
			j++;
		    }

		    if (strR -> str[1+j] == '*' 
		        || (strR -> str[1+j] == '\0' 
			    && tm -> termName[i+j] == '\0')) {

			match = 1;
			break;
		    }
		}

		if (match == 1)

		    break;  /* matched ! */
	    }
	    else {
		j = 0;
		while (j < len1 && j < len2
		       && strR -> str[j] != '*'
		       && strR -> str[j] == tm -> termName[j]) {
		    j++;
		}

		if (strR -> str[j] == '*' 
		   || (strR -> str[j] == '\0' && tm -> termName[j] == '\0'))

		    break;   /* matched ! */
	    }
	    strR = strR -> next;
	}

	if (omitRes && strR != NULL) {
	    Grp (n) -> noResis = 1;
	    verbose ("no resistances extracted for net %s\n", tm -> termName);
	}
	if (onlyRes && strR != NULL) {
	    Grp (n) -> noResis = 0;
	    verbose ("only resistances extracted for net %s\n", tm -> termName);
	}
    }

    if (prePass2 && optPrick && prickName != '\0') {
	if (strcmp (tm -> termName, prickName) == 0)
	    Grp (subn -> node) -> prick = 1;
    }
}

supplyShort ()
{
#ifdef MES_SUPPLYSHORT
    say ("Vdd connected to Vss/Gnd at (%d, %d)",
	     currX / currScale, currY / currScale );
#endif
}


makeAreaNode (subn)
subnode_t * subn;
{
    if (subn -> node -> type != 't')
	subn -> node -> type = 'a';
}

subnodeDel (subn)
subnode_t * subn;
{
    node_t * n;
    node_t * neigh;
    subnode_t * sub;
    group_t * grp;

    n = subn -> node;

    if (n -> subs == subn) {
	n -> subs = subn -> next_node;
    }
    else {
	sub = n -> subs;
	while (sub -> next_node != subn)
	    sub = sub -> next_node;
	sub -> next_node = subn -> next_node;
    }

    if (n -> subs == NULL) {

	grp = Grp (n);
	grp -> notReady--;

	if ((n -> type == 'i' 
	     || (optNoReduc && n -> type == 'a'))) {


	    elim (n);

	}
	else {
	    if (grp -> notReady == 0) 
		readyGroup (n);
	}
    }

    /* set subn -> node to NULL to ensure that that a reference via
       subn to node can no longer occur; if it does occur it's a bug
    */
    subn -> node = NULL;

    currIntSubnod--;
}

subtorNew (tile, name)
tile_t * tile;
char * name;
{
    transistor_t * t;

    ASSERT (strlen (name) < 6);

    tile -> tor = NEW (transistor_t, 1);
    tile -> next_tor = NULL;

    t = tile -> tor;
    t -> subs = tile;
    strcpy (t -> name, name);
    t -> gate = NULL;
    t -> drains = NULL;
    t -> totPerimeter = 0;
    t -> dsPerimeter = 0;
    t -> surface = 0;
    t -> boundaries = NULL;
    if (optBackInfo) {
	t -> tileInfo = NEW (transTileInfo_t, 1);
	t -> tileInfo -> tiles = NULL;
    }
    else
	t -> tileInfo = NULL;

    inSubtor++;
    currIntSubtor++;
    if (currIntSubtor > maxIntSubtor)
	maxIntSubtor = currIntSubtor;

    inTor++;
    currIntTor++;
    if (currIntTor > maxIntTor)
	maxIntTor = currIntTor;
    if (currIntTor + outTor > maxTorIfKept)
	maxTorIfKept = currIntTor + outTor;
}

subtorJoin (tileA, tileB)
tile_t * tileA;
tile_t * tileB;
{
    transistor_t * tA;
    transistor_t * tB;
    tile_t * sub;
    tile_t * lasttile;
    nodeTorLink_t * nTL;
    nodeTorLink_t * help_nTL;
    dsBoundary_t * dsBdrA;
    dsBoundary_t * dsBdrB;
    dsBoundary_t * nextDsBdrB;
    dsBoundary_t * dsBdr;
    dsCoor_t * pointA;
    dsCoor_t * pointB;
    dsCoor_t * nextPointB;
    dsCoor_t * p;
    dsCoor_t * p_single;
    dsCoor_t * p_prev;
    int added;
    tileRef_t * tileR;

    tA = tileA -> tor;
    tB = tileB -> tor;

    if (tA == tB) {
	return;
    }

    ASSERT (strsame (tA -> name, tB -> name));

    ASSERT (tB -> subs != NULL);

    for (sub = tB -> subs; sub != NULL; sub = sub -> next_tor) {
	sub -> tor = tA;
	lasttile = sub;
    }
    lasttile -> next_tor = tA -> subs;
    tA -> subs = tB -> subs;

    /* update torBoundary structure */

    dsBdrB = tB -> boundaries;
    while (dsBdrB) {
	nextDsBdrB = dsBdrB -> next;

	added = 0;
	pointB = dsBdrB -> points;
	while (pointB && !added) {
	    nextPointB = pointB -> next;
	    dsBdrA = tA -> boundaries;
	    while (dsBdrA && !added) {
		pointA = dsBdrA -> points;
		while (pointA && !added) {
		    if (pointA -> x == pointB -> x
			&& pointA -> y == pointB -> y) {

			/* because tileB is joined with tileA,
			   a DS boundary of B is added to 
			   a DS boundary of A at point pointB*/

			addDsBdr (dsBdrA, dsBdrB, pointB);
			pointA -> nr++;
			added = 1;
		    }
		    pointA = pointA -> next;
		}
		dsBdrA = dsBdrA -> next; 
	    }
	    pointB = nextPointB;
	}

	if (! added) {
	    /* add it to tile A as a separate boundary */
	    dsBdrB -> next = tA -> boundaries;
	    tA -> boundaries = dsBdrB;
	}

	dsBdrB = nextDsBdrB;
    }

    /* update perimeter and surface values */

    tA -> totPerimeter += tB -> totPerimeter;
    tA -> dsPerimeter += tB -> dsPerimeter;
    tA -> surface += tB -> surface;
    if (tB -> xl < tA -> xl) {
	tA -> xl = tB -> xl;
	tA -> yb = tB -> yb;
    } 
    else if (tB -> xl == tB -> xl) {
	if (tB -> yb < tA -> yb) {
	    tA -> xl = tB -> xl;
	    tA -> yb = tB -> yb;
	}
    }

    /* The gate of the tile that will stay longest in the stateruler
       is used as the gate node of the joined transistor */

    if (tileB -> xr > tileA -> xr
    || (tileB -> xr == tileA -> xr && tileB -> tr > tileA -> tr)) {
	if (tA -> gate != NULL)
	    nTLinkDel (tA -> gate);
	if (tB -> gate != NULL)
	    nTLinkAdd ('g', tB -> gate -> n, tA);
    }
    if (tB -> gate != NULL)
	nTLinkDel (tB -> gate);

    nTL = tB -> drains;
    while (nTL != NULL) {
	nTLinkAdd (nTL -> type, nTL -> n, tA);
	help_nTL = nTL;
	nTL = nTL -> nextT;
	nTLinkDel (help_nTL);
    }


    torDel (tB);
}


addDsBdr (dsBdrA, dsBdrB, pointB)
dsBoundary_t * dsBdrA;
dsBoundary_t * dsBdrB;
dsCoor_t * pointB;
{
    dsBoundary_t * dsBdrA2;
    dsBoundary_t * nextDsBdrA2;
    dsBoundary_t * dsBdrB2;
    dsCoor_t * pointA2;
    dsCoor_t * nextPointA2;
    dsCoor_t * pointB2;
    dsCoor_t * nextPointB2;
    int joined;
    int also_con;

    if (optReadNetTerm && optNoCore)
	EnableNoSubnodeJoin ();
    subnodeJoin (dsBdrA -> dsCond, dsBdrB -> dsCond);
    subnodeDel (dsBdrB -> dsCond);
    DISPOSE (dsBdrB -> dsCond);

    pointB2 = dsBdrB -> points;
    while (pointB2) {
	nextPointB2 = pointB2 -> next;
	if (pointB2 != pointB) {

	    /* first check if pointB2 is also connected to dsBdrA */

            also_con = 0;
	    pointA2 = dsBdrA -> points;
	    while (pointA2 && !also_con) {
		if (pointA2 -> x == pointB2 -> x 
		&& pointA2 -> y == pointB2 -> y) {

		    DISPOSE (pointB2);    /* the DS area is a closed ring */
		    pointA2 -> nr++;
		    also_con = 1;
		}

		pointA2 = pointA2 -> next;
	    }

            if (!also_con) {

	        /* add it to dsBdrA */

	        pointB2 -> next = dsBdrA -> points;
	        dsBdrA -> points = pointB2;

	        joined = 0;
	        dsBdrA2 = dsBdrA -> next;
	        while (dsBdrA2 && ! joined) {
		    nextDsBdrA2 = dsBdrA2 -> next;
		    pointA2 = dsBdrA2 -> points;
		    while (pointA2 && ! joined) {
		        nextPointA2 = pointA2 -> next;
		        if (pointA2 -> x == pointB2 -> x
			    && pointA2 -> y == pointB2 -> y) {
    
			    /* so, because B is added to A, two separate ds
			       boundaries of A are joined through B */
    
			    joinDsBdr (dsBdrA, dsBdrA2, pointA2);
			    pointB2 -> nr++;
			    joined = 1;
		        }
		        pointA2 = nextPointA2;
		    }
		    dsBdrA2 = nextDsBdrA2;
	        }
	    }
	}
	else {
	    DISPOSE (pointB);
	}
	pointB2 = nextPointB2;
    }
    DISPOSE (dsBdrB);
}


joinDsBdr (dsBdrA, dsBdrA2, pointA2)
dsBoundary_t * dsBdrA;
dsBoundary_t * dsBdrA2;
dsCoor_t * pointA2;
{
    dsBoundary_t * dsBdrA3;
    dsCoor_t * pointA3;
    dsCoor_t * nextPointA3;

    if (optReadNetTerm && optNoCore)
	EnableNoSubnodeJoin ();
    subnodeJoin (dsBdrA -> dsCond, dsBdrA2 -> dsCond);
    subnodeDel (dsBdrA2 -> dsCond);
    DISPOSE (dsBdrA2 -> dsCond);

    pointA3 = dsBdrA2 -> points;
    while (pointA3) {
	nextPointA3 = pointA3 -> next;
	if (pointA3 != pointA2) {
	    /* add it to dsBdrA */
	    pointA3 -> next = dsBdrA -> points;
	    dsBdrA -> points = pointA3;
	}
	else {
	    DISPOSE (pointA2);
	}
	pointA3 = nextPointA3;
    }

    dsBdrA3 = dsBdrA;  /* dsBdrA2 should be behind dsBdrA */
    while (dsBdrA3 -> next != dsBdrA2) {
	dsBdrA3 = dsBdrA3 -> next;
    }

    dsBdrA3 -> next = dsBdrA2 -> next;
    DISPOSE (dsBdrA2);
}


/* subtorCopy (tileA, tileB) is a short-hand for
 *    subtorNew (tileB);
 *    subtorJoin (tileA, tileB);
 */

subtorCopy (tileA, tileB)
tile_t * tileA;
tile_t * tileB;
{
    inSubtor++;
    currIntSubtor++;
    if (currIntSubtor > maxIntSubtor)
	maxIntSubtor = currIntSubtor;

    tileB -> tor = tileA -> tor;
    tileB -> next_tor = tileA -> tor -> subs;
    tileA -> tor -> subs = tileB;
}

subtorDel (tile, dsn)
tile_t * tile;
node_t * dsn;
{
    transistor_t * t;
    tile_t * sub;

    t = tile -> tor;

    if (t -> subs == tile) {
	t -> subs = tile -> next_tor;
    }
    else {
	sub = t -> subs;
	while (sub -> next_tor != tile)
	    sub = sub -> next_tor;
	sub -> next_tor = tile -> next_tor;
    }

    if (t -> subs == NULL) {

        if (t -> gate)
	    t -> gate -> n -> type = 't';

	outTransistor (t, dsn);
    }

    currIntSubtor--;
}

portAdd (subn, tile, port)
subnode_t * subn;
tile_t * tile;
char port;
{
    tile_t * subtile;

    if (port != 'g') {
	nTLinkAdd (port, subn -> node, tile -> tor);
	subn -> node -> type = 't';
    }
    else {
	subtile = tile -> tor -> subs;
	while (subtile != NULL) {
	    if (subtile -> xr > tile -> xr
	    || (subtile -> xr == tile -> xr && subtile -> tr > tile -> tr))
		return;
	    subtile = subtile -> next_tor;
	}
	if (tile -> tor -> gate != NULL)
	    nTLinkDel (tile -> tor -> gate);
	nTLinkAdd (port, subn -> node, tile -> tor);
    }
}


torBoundary (tor, x1, y1, x2, y2, length, subn)
transistor_t * tor;
coor_t x1, y1, x2, y2;
double length;
subnode_t * subn;
{
    dsBoundary_t * dsBdr;
    dsBoundary_t * dsBdr1;
    dsBoundary_t * dsBdr2;
    dsBoundary_t * newDsBdr;
    dsCoor_t * point;
    dsCoor_t * point1 = NULL;
    dsCoor_t * point2 = NULL;

    subn -> node -> type = 't';

    dsBdr = tor -> boundaries;
    while (dsBdr) {
	point = dsBdr -> points;
	while (point) {
	    if ((point -> x == x1 && point -> y == y1)
	        || (point -> x == x2 && point -> y == y2)) {
		if (!point1) {
		    point1 = point;
		    dsBdr1 = dsBdr;
		}
		else {
		    point2 = point;
		    dsBdr2 = dsBdr;
		    break;
		}
	    }
	    point = point -> next;
	}
	if (point2) break;
	dsBdr = dsBdr -> next;
    }

    if (point1) {

	if (point2) {

            if (dsBdr1 != dsBdr2) {

		/* add points from dsBdr1 to dsBdr2 */

		if (optReadNetTerm && optNoCore)
		    EnableNoSubnodeJoin ();
		subnodeJoin (dsBdr2 -> dsCond, dsBdr1 -> dsCond);

		point = point2;
		while (point -> next) {
		    point = point -> next;
		}
		point -> next = dsBdr1 -> points;
		if ((dsBdr = tor -> boundaries) == dsBdr1) {
		    tor -> boundaries = dsBdr1 -> next;
		}
		else {
		    while (dsBdr -> next != dsBdr1) {
			dsBdr = dsBdr -> next;
		    }
		    dsBdr -> next = dsBdr1 -> next;
		}

		subnodeDel (dsBdr1 -> dsCond);
		DISPOSE (dsBdr1 -> dsCond);
		DISPOSE (dsBdr1);
	    }

	    /* increase nr of point1 and point2 since (x1, y1)
	       and (x2, y2) coincide with it */ 

	    point1 -> nr++;
	    point2 -> nr++;
	}
	else if (length > 0) {

	    /* add new point to dsBdr1 */

	    point = NEW (dsCoor_t, 1);
	    if (point1 -> x == x1 && point1 -> y == y1) {
		point -> x = x2;
		point -> y = y2;
	    }
	    else {
		point -> x = x1;
		point -> y = y1;
	    }
	    point -> nr = 1;
	    point -> next = dsBdr1 -> points;
	    dsBdr1 -> points = point;

	    /* increase nr of point1 since (x1, y1) 
	       or (x2, y2) coincides with it */ 

	    point1 -> nr++;
	}
    }
    else {

	/* add new boundary and new points */

	newDsBdr = NEW (dsBoundary_t, 1);
	newDsBdr -> next = tor -> boundaries;
	tor -> boundaries = newDsBdr;
	newDsBdr -> dsCond = NEW (subnode_t, 1);
	if (optReadNetTerm && optNoCore)
	    EnableNoSubnodeJoin ();
	subnodeCopy (subn, newDsBdr -> dsCond);
	newDsBdr -> points = NEW (dsCoor_t, 1);
	newDsBdr -> points -> nr = 1;
	newDsBdr -> points -> x = x1;
	newDsBdr -> points -> y = y1;
	if (length > 0) {
	    newDsBdr -> points -> next = NEW (dsCoor_t, 1);
	    newDsBdr -> points -> next -> nr = 1;
	    newDsBdr -> points -> next -> x = x2;
	    newDsBdr -> points -> next -> y = y2;
	    newDsBdr -> points -> next -> next = NULL;
	}
	else {
	    newDsBdr -> points -> next = NULL;
	}
    }
}

