/* Functions for working with tree nodes - Jan 1989 Copyright (C) 1990 Marty White This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include "compiler.h" #ifdef __STDHEADERS__ /*#include */ #include #include #endif #include "physcalc.h" #include "physdecl.h" #ifdef __PROTOTYPES__ NODEP allocnode(int t, int bytes); LOCAL void dealloclist(NODEP n); #else LOCAL void dealloclist(); #endif #define STACKSIZE (1024 * 8) /* 8K stack space */ EXPORT int nodecount; EXPORT void initnodes() /* WARNING!! May not be compatible! */ { #ifdef __DESMETC__ freeall(STACKSIZE); /* Leave stack space */ #endif } #ifdef __TURBOC__ extern unsigned _stklen = STACKSIZE; /* set stack */ #endif EXPORT void out_of_memory(s) char const *s; { printf("\nOut of memory. [%s]\n%d nodes were allocated.\n",s,nodecount); exit(1); } EXPORT NODEP allocnode(t,bytes) /* allocate a node & data space & set type */ int t,bytes; { NODEP n; n = (NODEP) malloc(sizeof(NODE)); /* Allocate space for node itself */ if (n==NULL) out_of_memory("allocnode"); n->type = t; n->data=malloc(bytes); /* Allocate space for data */ if (n->data==NULL) out_of_memory("allocnode"); nodecount++; return n; } EXPORT char *reallocnode(n,t,bytes) /* Reset data size & type */ NODEP n; int t,bytes; { register VOID *p; if (n->type >= LNODE) dealloclist(n); p = realloc(n->data,bytes); if (p==NULL) out_of_memory("reallocnode"); n->type = t; n->data = p; return p; } EXPORT NODEP allocsnode(s) /* allocate & initialize a string-node */ char const *s; { NODEP n; n = allocnode(SNODE,strlen(s)+1); strcpy(n->data->str,s); return n; } EXPORT NODEP allocdnode(x) /* allocate & init a double-type node */ double x; { NODEP n; n = allocnode(DNODE,sizeof(double)); n->data->dbl = x; return n; } EXPORT NODEP allocinode(i) /* alloc a long-int node */ long i; { NODEP n; n = allocnode(INODE,sizeof(long)); n->data->lng = i; return n; } EXPORT NODEP allocfnode(num,den) /* alloc a fracton node */ int num,den; { NODEP n; n = allocnode(FNODE,sizeof(struct fractstruct)); n->data->frt.numer = num; n->data->frt.denom = den; return n; } EXPORT NODEP allocnnode() { NODEP n; n = allocnode(NNODE,sizeof(struct d_num)); erasednum((DNUM *)(n->data)); return n; } EXPORT NODEP alloclnode(t) /* allocate an empty list-type node of type t */ int t; { NODEP n; n = allocnode(t,sizeof(n)); n->data->list[0] = NULL; return n; } EXPORT NODEP alloclnode1(t,n1) int t; NODEP n1; { NODEP n2; n2 = alloclnode(t); linknode(n2,n1); return n2; } EXPORT NODEP alloclnode2(t,n1,n2) /* allocate a list node with 2 sub nodes */ int t; NODEP n1,n2; { NODEP n3; n3 = alloclnode(t); linknode(n3,n1); linknode(n3,n2); return n3; } EXPORT NODEP linknode(n1,n2) /* Point n1 to n2, return n2 */ NODEP n1,n2; /* On failure, return NULL and do not link */ { int i=0; VOID *p; if (n1->type < LNODE) return NULL; while (n1->data->list[i]) /* set i to end of list */ i++; p = realloc(n1->data,sizeof(n1->data->list[0])*(i+2)); if (p==NULL) out_of_memory("linknode"); n1->data = p; n1->data->list[i] = n2; n1->data->list[++i] = NULL; return n2; } EXPORT NODEP unlinknode(n1,n2) /* zap n1's pointer to n2 (if it has one);return n2 */ NODEP n1,n2; /* On failure, return NULL */ { int i=0; if (n1->type < LNODE) return NULL; while ( n1->data->list[i] && n1->data->list[i]!=n2 ) i++; if (n1->data->list[i]) { while (n1->data->list[i]=n1->data->list[i+1]) i++; i++; n1->data = realloc( n1->data, sizeof(n1->data->list[0])*i ); if (n1->data==NULL) out_of_memory("unlinknode"); } return n2; } LOCAL void dealloclist(n) /* de-allocate all the sub-nodes of n */ NODEP n; { int i=0; if (n->type >= LNODE && n->data) { while (n->data->list[i]) deallocnode(n->data->list[i++]); n->data->list[0] = NULL; } } EXPORT void deallocnode(n) /* de-allocate a node & its sub-nodes if any */ NODEP n; { if (n) { if (n->type >= LNODE) dealloclist(n); free(n->data); free(n); nodecount--; } } EXPORT int cmpnode(n1,n2) /* compare for equal contents */ NODEP n1,n2; { NODEP n3,n4; int i; if (n1==n2) /* simple case of the same node */ return TRUE; if (!n1 || !n2 || n1->type != n2->type) return FALSE; switch (n1->type) { case 0 /*NULL*/: return TRUE; case SNODE: return !strcmp(n1->data->str,n2->data->str); case DNODE: return n1->data->dbl == n2->data->dbl; case INODE: return n1->data->lng == n2->data->lng; case FNODE: /* TD: Compare fractional and dimensional nodes */ case NNODE: return FALSE; default: i=0; while (n3 = n1->data->list[i]) { n4 = n2->data->list[i]; if (!n4 || !cmpnode(n3,n4)) return FALSE; i++; } return !n2->data->list[i]; } return 0; /* code is never reached */ } EXPORT int nodesize(n) /* return size in bytes of associated data */ NODEP n; { register int b,i; switch (n->type) { case 0 /*NULL*/: b = 0; break; case INODE: b = sizeof(long); break; case FNODE: b = sizeof(struct fractstruct); break; case DNODE: b = sizeof(double); break; case NNODE: b = sizeof(DNUM); break; case SNODE: b = strlen(n->data->str) + 1; break; default: i = 0; while (n->data->list[i++]) ; b = i * sizeof(NODEP); } return b; } EXPORT void bytecopy(dst, src, bytes) char *dst; char const *src; int bytes; { while (bytes--) *dst++ = *src++; } EXPORT NODEP copynode(n) /* Create a duplicate of node n (including sub-nodes) */ NODEP n; /* Will hang on self-referential node structures */ { NODEP n2,n3; int i=0; switch (n->type ) { case 0 /*NULL*/: n2 = NULL; break; case SNODE: case INODE: case FNODE: case DNODE: case NNODE: n2 = allocnode(n->type,i=nodesize(n)); bytecopy(n2->data,n->data,i); break; default: /* List node */ n2 = alloclnode(n->type); while (n->data->list[i]) { n3 = copynode(n->data->list[i]); linknode(n2,n3); i++; } } return n2; }