/* 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 <stdio.h>
#include "compiler.h"
#ifdef __STDHEADERS__
/*#include <dos.h>*/
#include <stdlib.h>
#include <string.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1