/*
This file is part of the FElt finite element analysis package.
Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/************************************************************************
* File: descriptor.c *
* *
* Description: This file contains the public and private function *
* definitions for descriptors. *
************************************************************************/
# include "trap.h"
# include "debug.h"
# include "desctab.h"
# include "allocate.h"
# include "descriptor.h"
# include VAR_ARGS_INCLUDE
static descriptor *reused;
/************************************************************************
* Function: CreateData *
* *
* Description: Creates new data for a descriptor using the data of *
* other descriptors if they are temporary. *
************************************************************************/
# ifdef UseFunctionPrototypes
void CreateData (descriptor *d, descriptor *a, descriptor *b, int type, ...)
# else
void CreateData (d, a, b, type, va_alist)
descriptor *d;
descriptor *a;
descriptor *b;
int type;
va_dcl
# endif
{
void *ptr;
int length;
int handler;
unsigned ncols;
unsigned nrows;
va_list ap;
if (a && D_Type (a) == type && D_Writable (a)) {
D_Type (d) = type;
D_Union (d) = D_Union (a);
D_Trapped (d) = F_False;
D_Temp (d) = F_True;
reused = a;
d_printf ("new %s (%p) from first\n", D_TypeName (d), D_Pointer (d));
} else if (b && D_Type (b) == type && D_Writable (b)) {
D_Type (d) = type;
D_Union (d) = D_Union (b);
D_Trapped (d) = F_False;
D_Temp (d) = F_True;
reused = b;
d_printf ("new %s (%p) from second\n", D_TypeName (d), D_Pointer (d));
} else {
D_Type (d) = type;
D_Trapped (d) = F_False;
D_Temp (d) = F_True;
reused = NULL;
VA_START (ap, type);
switch (type) {
case T_Null:
D_Pointer (d) = NULL;
break;
case T_Variable:
D_Pointer (d) = NULL;
break;
case T_Function:
D_Function (d) = CreateFunction (va_arg (ap, char *));
break;
case T_Intrinsic:
D_Intrinsic (d) = va_arg (ap, int);
break;
case T_String:
D_String (d) = New (char *);
*D_String (d) = Allocate (char, va_arg (ap, int));
break;
case T_Double:
D_Double (d) = New (double);
break;
case T_Int:
D_Int (d) = New (int);
break;
case T_Byte:
D_Byte (d) = New (char);
break;
case T_Array:
ptr = va_arg (ap, void *);
type = va_arg (ap, int);
length = va_arg (ap, int);
handler = va_arg (ap, int);
D_Array (d) = CreateArray (ptr, type, length, handler);
break;
case T_Row:
D_Pointer (d) = NULL;
break;
case T_Matrix:
nrows = va_arg (ap, unsigned);
ncols = va_arg (ap, unsigned);
D_Matrix (d) = CreateFullMatrix (nrows, ncols);
break;
default:
break;
}
d_printf ("new %s (%p)\n", D_TypeName (d), D_Pointer (d));
va_end (ap);
}
}
/************************************************************************
* Function: AssignData *
* *
* Description: Assigns the data of a descriptor to another. The *
* address of the source descriptor is passed so that it *
* may returned to the caller if modified. A trapped *
* variable handler may attempt to coerce the source data *
* to perform the assignment. *
************************************************************************/
int AssignData (dest, srcp)
descriptor *dest;
descriptor **srcp;
{
char *s;
Matrix a;
Matrix b;
descriptor *src;
descriptor *reuse;
if (dest == *srcp)
return 0;
if (D_Trapped (dest) != F_False)
return CallTrap (D_Trapped (dest), dest, srcp);
src = *srcp;
if (D_Temp (src) == F_True) {
d_printf ("assignment from temporary\n");
FreeData (dest);
D_Type (dest) = D_Type (src);
D_Temp (dest) = F_True;
D_Trapped (dest) = F_False;
D_Union (dest) = D_Union (src);
reused = src;
} else {
reused = NULL;
D_Temp (dest) = F_True;
d_printf ("assignment from non-temporary\n");
switch (D_Type (src)) {
case T_Null:
FreeData (dest);
D_Type (dest) = T_Null;
D_Temp (dest) = F_False;
D_Trapped (dest) = F_False;
D_Pointer (dest) = NULL;
break;
case T_Variable:
AssignData (dest, &D_Variable (src));
break;
case T_Function:
FreeData (dest);
D_Type (dest) = T_Function;
D_Temp (dest) = F_True;
D_Trapped (dest) = F_False;
D_Function (dest) = CopyFunction (D_Function (src));
break;
case T_Intrinsic:
FreeData (dest);
D_Type (dest) = T_Intrinsic;
D_Temp (dest) = F_False;
D_Trapped (dest) = F_False;
D_Intrinsic (dest) = D_Intrinsic (src);
break;
case T_String:
s = *D_String (src);
FreeData (dest);
CreateData (dest, NULL, NULL, T_String, strlen (s) + 1);
strcpy (*D_String (dest), s);
break;
case T_Double:
if (!(reuse = D_Type (dest) == T_Double ? dest : NULL))
FreeData (dest);
CreateData (dest, reuse, NULL, T_Double);
*D_Double (dest) = *D_Double (src);
break;
case T_Int:
if (!(reuse = D_Type (dest) == T_Int ? dest : NULL))
FreeData (dest);
CreateData (dest, reuse, NULL, T_Int);
*D_Int (dest) = *D_Int (src);
break;
case T_Byte:
if (!(reuse = D_Type (dest) == T_Byte ? dest : NULL))
FreeData (dest);
CreateData (dest, reuse, NULL, T_Byte);
*D_Byte (dest) = *D_Byte (src);
break;
case T_Array:
FreeData (dest);
D_Type (dest) = T_Array;
D_Temp (dest) = F_False;
D_Trapped (dest) = D_Trapped (src);
D_Array (dest) = CopyArray (D_Array (src));
break;
case T_Matrix:
a = D_Matrix (src);
reuse = NULL;
if (D_Type (dest) == T_Matrix) {
b = D_Matrix (dest);
if (Mrows (a) == Mrows (b) && Mcols (a) == Mcols (b))
reuse = dest;
}
if (!reuse)
FreeData (dest);
if (IsCompact (a)) {
FreeData (dest);
D_Type (dest) = T_Matrix;
D_Temp (dest) = F_False;
D_Trapped (dest) = F_False;
D_Matrix (dest) = CreateCopyMatrix (a);
} else {
CreateData (dest, reuse, NULL, T_Matrix, Mrows (a), Mcols (a));
CopyMatrix (D_Matrix (dest), a);
}
break;
case T_External:
D_Type (dest) = T_External;
D_Temp (dest) = F_False;
D_Trapped (dest) = F_False;
dest->u.ptr = D_External (src);
break;
default:
D_Type (dest) = D_Type (src);
D_Temp (dest) = F_False;
D_Trapped (dest) = F_False;
D_Pointer (dest) = D_Pointer (src);
break;
}
}
return 0;
}
/************************************************************************
* Function: AssignObject *
* *
* Description: Special interface to AssignData() that creates a fake *
* descriptor and also sets the destination descriptor to *
* be non-temporary. This is used in assigning to shared *
* arguments. *
************************************************************************/
int AssignObject (dest, type, temp, ptr)
descriptor *dest;
int type;
int temp;
void *ptr;
{
descriptor *src;
descriptor scratch;
int status;
src = &scratch;
D_Type (src) = type;
D_Temp (src) = temp;
D_Trapped (src) = F_False;
D_Pointer (src) = ptr;
if (!(status = AssignData (dest, &src)))
D_Temp (dest) = F_False;
return status;
}
/************************************************************************
* Function: RecycleData *
* *
* Description: Deallocates the data of a descriptor if it is *
* temporary and has not been reused by CreateData(). *
************************************************************************/
void RecycleData (d)
descriptor *d;
{
if (d && D_Temp (d) == F_True && d != reused)
FreeData (d);
else if (d && D_Trapped (d) != F_False && d != reused)
CallTrap (D_Trapped (d), d, NULL);
else if (d == reused)
reused = NULL;
}
/************************************************************************
* Function: FreeData *
* *
* Description: Deallocates the data of a descriptor. *
************************************************************************/
void FreeData (d)
descriptor *d;
{
if (d) {
d_printf ("freeing %s (%p)\n", D_TypeName (d), D_Pointer (d));
if (D_Trapped (d) != F_False)
CallTrap (D_Trapped (d), d, NULL);
switch (D_Type (d)) {
case T_Null:
break;
case T_Variable:
break;
case T_Function:
DestroyFunction (D_Function (d));
break;
case T_Intrinsic:
break;
case T_String:
Deallocate (*D_String (d));
Delete (D_String (d));
break;
case T_Double:
Delete (D_Double (d));
break;
case T_Int:
Delete (D_Int (d));
break;
case T_Byte:
Delete (D_Byte (d));
break;
case T_Array:
DestroyArray (D_Array (d));
break;
case T_Row:
break;
case T_Matrix:
DestroyMatrix (D_Matrix (d));
break;
default:
break;
}
}
}
/************************************************************************
* Function: PrintData *
* *
* Description: Prints the data of a descriptor. *
************************************************************************/
void PrintData (d)
descriptor *d;
{
if (d) {
switch (D_Type (d)) {
case T_Null:
fprintf (stderr, "\tnull\n");
break;
case T_Variable:
PrintData (D_Variable (d));
break;
case T_Function:
fprintf (stderr, "\tfunction %s\n", D_Function (d) -> name);
break;
case T_Intrinsic:
fprintf (stderr, "\tintrinsic %d\n", D_Intrinsic (d));
break;
case T_String:
fprintf (stderr, "\t%s\n", *D_String (d));
break;
case T_Double:
fprintf (stderr, "\t%g\n", *D_Double (d));
break;
case T_Int:
fprintf (stderr, "\t%d\n", *D_Int (d));
break;
case T_Byte:
fprintf (stderr, "\t%d\n", *D_Byte (d));
break;
case T_Array:
fprintf (stderr, "\tarray\n");
break;
case T_Row:
fprintf (stderr, "\trow\n");
break;
case T_Matrix:
PrintMatrix (D_Matrix (d), stderr);
break;
case T_MatrixPtr:
fprintf (stderr, "\tmatrix_ptr\n");
break;
case T_Constraint:
fprintf (stderr, "\tconstraint\n");
break;
case T_Definition:
fprintf (stderr, "\tdefinition\n");
break;
case T_Element:
fprintf (stderr, "\telement\n");
break;
case T_Force:
fprintf (stderr, "\tforce\n");
break;
case T_Load:
fprintf (stderr, "\tload\n");
break;
case T_Material:
fprintf (stderr, "\tmaterial\n");
break;
case T_Node:
fprintf (stderr, "\tnode\n");
break;
case T_Pair:
fprintf (stderr, "\tpair\n");
break;
case T_External:
fprintf (stderr, "\texternal\n");
break;
default:
fprintf (stderr, "\twhat are you trying to print?\n");
break;
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1