/* object.c ********************************************************************************
* object.c -- Routines for manipulating generic objects
*
* User routines:
* Pro_FreeObject(object) frees the memory used by an object.
* Pro_PrintObject(object) prints information about an object.
* Pro_ObjectName(object,coord) returns name of an object or one of
* its coordinates.
* Pro_RenameObject(object,coord,name)
* renames an object or one of its
* coordinates.
* Pro_ObjectDomain(object,x1,x2) returns the domain (X-limits) of an
* object.
* Pro_ObjectOverlap(object,x1,x2,xname,first)
* solves for the domain of overlap of
* multiple objects.
*
* Programmer routines:
* XPro_MakeObject(x1, x2, freefunc, printfunc, pointer)
* creates and intializes a new generic
* object.
* XPro_EnslaveObject(object, slave)
* adds a link to a "slave" object.
* XPro_PrintInfo(object) prints name and type of object.
* XPro_ObjectName(object) returns name of an object without
* checking for a class error.
* XPro_ObjectPtr(object) returns pointer to sub-object.
*
* Version 1.0: Original release.
* Mark Showalter & Neil Heather, PDS Ring-Moon Systems Node, March 1998.
* Version 1.1: QUICK compilation mode added.
* Mark Showalter, October 1999.
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "profile.h"
#include "fortran.h"
/************************************
* Prototypes for internal routines *
************************************/
static void ZPro_RemoveOwner RL_PROTO((PRO_OBJECT *object,
PRO_OBJECT *owner));
static void ZPro_DeleteObject RL_PROTO((PRO_OBJECT *object));
static RL_BOOL ZPro_TestObject RL_PROTO((PRO_OBJECT *object));
/********************
* Static variables *
********************/
static RL_INT4 object_counter = 0;
static RL_INT4 objects_active = 0;
static PRO_OBJECT empty_object = {{XPRO_OBJECT_CLASS, "object", NULL},
"Untitled", "", "", 0., 0., NULL, NULL,
FALSE, {NULL, NULL}, {NULL, NULL}};
static RL_CHAR empty_name[] = "";
/********************
* Global variables *
********************/
PRO_OBJECT XPRO_UNKNOWN_OBJECT = {{XPRO_OBJECT_CLASS, "object", NULL},
"Unknown", "", "", 0., 0., NULL, NULL,
FALSE, {NULL, NULL}, {NULL, NULL}};
/*
********************************************************************************
* EXPORTED USER ROUTINES
********************************************************************************
*$ Component_name:
* Pro_FreeObject (object.c)
*$ Abstract:
* This routine frees the specified object.
*$ Keywords:
* PROFILE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* void Pro_FreeObject(object)
* PRO_OBJECT *object;
*$ Inputs:
* object pointer to the object to free.
*$ Outputs:
* none
*$ Returns:
* none
*$ Detailed_description:
* This routine frees the specified object. Memory is deallocated,
* associated files are closed, and any linked objects are freed.
*
* Note that the user can free an object as soon it is no longer needed for
* direct manipulation. When this routine is called, the object will still
* be retained internally by the Profile toolkit until every object that
* links to it is also freed.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* Memory is deallocated, associated files are closed, and linked objects
* are freed.
*$ Examples:
* PRO_OBJECT *series, *func;
*
* series = Pro_ArraySeries(...); // create a series
* func = Pro_LSplineFunc(series); // create a function using the series
* Pro_FreeObject(series); // free the series because we won't use
* it again directly. It won't really
* disappear till func is freed
* printf("%g\n", Pro_FuncValue(func,1.));
* // function can still be used
* Pro_FreeObject(func); // freeing the function now also frees
* the series too
*$ Error_handling:
* Profile toolkit error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not a profile object.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
void Pro_FreeObject(object)
PRO_OBJECT *object;
{
XPRO_LINK *link, *save;
/* Make sure object it's a valid object */
if (ZPro_TestObject(object)) return;
/* Mark object as freed if it isn't already */
if (object->isfreed) return;
object->isfreed = TRUE;
/* Free slaves of the object */
link = object->slaves.next;
while (link != NULL) {
ZPro_RemoveOwner(link->object, object);
save = link->next;
XRL_Free((RL_VOID *) link);
link = save;
}
/* If the object has no owners, delete it */
if (object->owners.next == NULL) ZPro_DeleteObject(object);
}
/*
********************************************************************************
*$ Component_name:
* Pro_PrintObject (object.c)
*$ Abstract:
* This routine prints out information about an object.
*$ Keywords:
* PROFILE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* void Pro_PrintObject(object)
* PRO_OBJECT *object;
*$ Inputs:
* object pointer to the object to print.
*$ Outputs:
* none
*$ Returns:
* none
*$ Detailed_description:
* This routine prints out information about an object. It is used mainly
* for debugging.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* Information is printed to standard output.
*$ Examples:
* PRO_OBJECT *series;
* series = Pro_ArraySeries(...); // create a series
* Pro_PrintObject(series) // print out info about it
*$ Error_handling:
* No error conditions are ever raised by this routine.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
void Pro_PrintObject(object)
PRO_OBJECT *object;
{
XPRO_LINK *link;
/* Print out object name and class */
printf("Object ");
XPro_PrintInfo(object);
/* Print out freed status if necessary */
if (object->isfreed) {
printf("PRINT ERROR: Object is already freed\n");
return;
}
/* Print out slave list, indented */
for (link = object->slaves.next; link != NULL; link = link->next) {
printf(" slave ");
XPro_PrintInfo(link->object);
}
/* Print out owner list, indented */
for (link = object->owners.next; link != NULL; link = link->next) {
printf(" owner ");
XPro_PrintInfo(link->object);
}
/* Print generic object info */
printf("\nGeneric object parameters...\n");
printf(" xname = \"%s\"\n", XPro_ObjectName(object,1));
printf(" yname = \"%s\"\n", XPro_ObjectName(object,2));
printf(" domain = [%#g,%#g]\n", object->x1, object->x2);
/* Print the remaining info */
(object->printfunc) (object->class.pointer);
}
/*
********************************************************************************
*$ Component_name:
* Pro_ObjectName (object.c)
*$ Abstract:
* This routine returns the name of an object or one of its coordinates.
*$ Keywords:
* PROFILE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* RL_CHAR *Pro_ObjectName(object, coord)
* PRO_OBJECT *object;
* RL_INT4 coord;
*$ Inputs:
* object pointer to the object.
* coord 0 for object name;
* 1 for X-coordinate name;
* 2 for Y-coordinate name.
*$ Outputs:
* none
*$ Returns:
* a pointer to a (read-only) string containing the name of the object.
* On non-fatal error, it returns a pointer to an empty string.
*$ Detailed_description:
* This function returns a pointer to the name of an object or one of its
* coordinates.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* This snippet of code creates a series, names it, and then prints the
* names. The result is:
* Name = Series
* X = X coord
* Y = Y coord
*
* PRO_OBJECT *series;
* series = Pro_ArraySeries(...); // create a series
* Pro_RenameObject(series, 0, "Series") // name it
* Pro_RenameObject(series, 1, "X coord") // name the x coordinate
* Pro_RenameObject(series, 2, "Y coord") // name the y coordinate
*
* printf("Name = %s\n", Pro_ObjectName(series,0));// print name
* printf("X = %s\n", Pro_ObjectName(series,1)); // print X cordinate
* printf("Y = %s\n", Pro_ObjectName(series,2)); // print Y cordinate
*$ Error_handling:
* Profile toolkit error handling is in effect. On non-fatal error, a
* pointer to an empty string is returned.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not an object pointer.
* PRO_DOMAIN_ERROR if the coord is outside the range 0 to 2.
*$ Limitations:
* Names are limited to 59 characters, plus a final null character.
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
RL_CHAR *Pro_ObjectName(object, coord)
PRO_OBJECT *object;
RL_INT4 coord;
{
if (ZPro_TestObject(object)) {
return empty_name;
}
else {
return XPro_ObjectName(object, coord);
}
}
/*
********************************************************************************
*$ Component_name:
* Pro_RenameObject (object.c)
*$ Abstract:
* This routine changes the name of an object or one of its coordinates.
*$ Keywords:
* PROFILE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* void Pro_RenameObject(object, coord, name)
* PRO_OBJECT *object;
* RL_INT4 coord;
* RL_CHAR *name;
*$ Inputs:
* object pointer to the object to rename.
* coord 0 for object name;
* 1 for X-coordinate name;
* 2 for Y-coordinate name.
* name character string containing new name.
*$ Outputs:
* none
*$ Returns:
* none
*$ Detailed_description:
* This routine changes the name of an object or one of its coordinates.
* It replaces any unprintable characters with a period.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* This snippet of code creates a series, names it, and then prints the
* names. The result is:
* Name = Series
* X = X coord
* Y = Y coord
*
* PRO_OBJECT *series;
* series = Pro_ArraySeries(...); // create a series
* Pro_RenameObject(series, 0, "Series") // name it
* Pro_RenameObject(series, 1, "X coord") // name the x coordinate
* Pro_RenameObject(series, 2, "Y coord") // name the y coordinate
*
* printf("Name = %s\n", Pro_ObjectName(series,0));// print name
* printf("X = %s\n", Pro_ObjectName(series,1)); // print X cordinate
* printf("Y = %s\n", Pro_ObjectName(series,2)); // print Y cordinate
*$ Error_handling:
* Profile toolkit error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not a profile object.
* PRO_DOMAIN_ERROR if the coord is outside the range 0 to 2.
*$ Limitations:
* Names are limited to 59 characters, plus a final null character.
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
void Pro_RenameObject(object, coord, name)
PRO_OBJECT *object;
RL_INT4 coord;
RL_CHAR *name;
{
RL_CHAR *loc, *c;
if (ZPro_TestObject(object)) return;
if (coord == 0) loc = object->name;
else if (coord == 1) loc = object->xname;
else if (coord == 2) loc = object->yname;
else {
XPro_IDomainError("coordinate index", object, 0, 2, coord);
return;
}
/* Copy name into object structure */
strncpy(loc, name, PRO_NAMELEN);
loc[PRO_NAMELEN] = '\0'; /* ensure null termination */
/* Obliterate unprintable characters */
for (c = loc; *c != '\0'; c++) {
if (!isprint((int) *c)) *c = '.';
}
}
/*
********************************************************************************
*$ Component_name:
* Pro_ObjectDomain (object.c)
*$ Abstract:
* This routine returns the domain (X-limits) for an object.
*$ Keywords:
* PROFILE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* RL_FLT8 Pro_ObjectDomain(object, x1, x2)
* PRO_OBJECT *object;
* RL_FLT8 *x1, *x2;
*$ Inputs:
* object pointer to the object.
*$ Outputs:
* *x1, *x2 lower and upper limits of domain (inclusive); not
* returned if either pointer value is NULL; unchanged on
* non-fatal error.
*$ Returns:
* size of domain (x2 - x1); 0. on non-fatal error.
*$ Detailed_description:
* This routine returns the domain (X-limits) for an object. It also
* returns the size of the domain.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* none
*$ Error_handling:
* Profile library error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if the object is NULL or not a profile object.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
* 1.1: October 1999
*$ Change_history:
* 1.1: QUICK mode compile option added.
*******************************************************************************/
RL_FLT8 Pro_ObjectDomain(object, x1, x2)
PRO_OBJECT *object;
RL_FLT8 *x1, *x2;
{
#ifndef QUICK
if (ZPro_TestObject(object)) return 0.;
#endif
if (x1 != NULL) *x1 = object->x1;
if (x2 != NULL) *x2 = object->x2;
return (object->x2 - object->x1);
}
/*
********************************************************************************
*$ Component_name:
* Pro_ObjectOverlap (object.c)
*$ Abstract:
* This routine finds the domain of overlap of two or more objects.
*$ Keywords:
* PROFILE
* C, PUBLIC, SUBROUTINE
*$ Declarations:
* RL_FLT8 Pro_ObjectOverlap(object, refobj, x1, x2)
* PRO_OBJECT *object, *refobj;
* RL_FLT8 *x1, *x2;
*$ Inputs:
* object pointer to the object to test for overlap.
* refobj pointer to the reference object (see below).
* *x1, *x2 current domain limits; ignored if first is TRUE.
*$ Outputs:
* *x1, *x2 updated domain limits.
*$ Returns:
* size of overlapping domain, i.e. (*x2 - *x1), or 0. on non-fatal error.
*$ Detailed_description:
* This routine finds the domain of overlap of two or more objects. It
* also checks to confirm that the X-coordinate names match.
*
* On the first call to this routine, the object and the reference object
* should be the same. In this case, the domain is saved in x1 and x2.
* On subsequent calls, the first argument should be each new object to
* overlap with the reference object. After the last call, *x1 and *x2
* contain the intersection of all the objects' domains. If at any time
* the intersection becomes empty, an error condition is raised.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose you wish to find the overlapping domain of object1, object2 and
* object3.
*
* RL_FLT8 x1, x2;
*
* Pro_ObjectOverlap(object1, object1, &x1, &x2);
* Pro_ObjectOverlap(object2, object1, &x1, &x2);
* Pro_ObjectOverlap(object3, object1, &x1, &x2);
*
* At this point, x1 and x2 are the limits of the overlapping domain. If
* any of the X-coordinate names do not match or if the overlapping domain
* is empty, an error condition is raised.
*$ Error_handling:
* Profile toolkit error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not a profile object.
* PRO_COORD_MISMATCH if X-coordinate names of objects do not match.
* PRO_EMPTY_DOMAIN if overlapping domain is empty.
*
* On a non-fatal PRO_COORD_MISMATCH condition, the domain limits are still
* updated and the return is normal. Otherwise, 0. is returned.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
RL_FLT8 Pro_ObjectOverlap(object, refobj, x1, x2)
PRO_OBJECT *object, *refobj;
RL_FLT8 *x1, *x2;
{
RL_CHAR *aname;
RL_FLT8 size, a1, a2, b1, b2;
/* Get domain info */
size = Pro_ObjectDomain(object, &a1, &a2);
if (size <= 0.) return 0.;
/* On first call, just save domain info */
if (object == refobj) {
*x1 = a1;
*x2 = a2;
return (a2 - a1);
}
/* Otherwise, compare names */
if (strcmp(Pro_ObjectName(object,1), Pro_ObjectName(refobj,1)) != 0) {
XPro_CoordMismatch("overlap", object, refobj, Pro_ObjectName(object,1),
Pro_ObjectName(refobj,1));
}
/* Derive new domain */
b1 = (a1 > *x1 ? a1 : *x1);
b2 = (a2 < *x2 ? a2 : *x2);
/* Test for empty domain */
if (b1 >= b2) {
XPro_EmptyDomain("overlap", object, refobj, a1, a2, *x1, *x2);
return 0.;
}
/* Update domain and return */
*x1 = b1;
*x2 = b2;
return (b2 - b1);
}
/*
********************************************************************************
* EXPORTED PROGRAMMER ROUTINES
********************************************************************************
* XPro_MakeObject(x1, x2, freefunc, printfunc, pointer)
*
* This routine creates and initializes a generic object.
*
* Inputs:
* x1, x2 domain limits.
* freefunc function to free data structure.
* printfunc function to print object data.
* pointer pointer to object data structure.
*
* Returns: pointer to the new object.
*
* Errors:
* RL_MEMORY_ERROR if memory for the object could not be allocated;
* in this case, the pointer data structure is also
* freed.
*******************************************************************************/
PRO_OBJECT *XPro_MakeObject(x1, x2, freefunc, printfunc, pointer)
RL_FLT8 x1, x2;
void (*freefunc) RL_PROTO((RL_VOID * pointer));
void (*printfunc) RL_PROTO((RL_VOID * pointer));
RL_VOID *pointer;
{
PRO_OBJECT *object;
/* Allocate and initialize new object */
object = (PRO_OBJECT *) XRL_Malloc(sizeof(PRO_OBJECT));
if (object == NULL) {
(*freefunc) (pointer);
return NULL;
}
/* Fill in temporary object */
*object = empty_object;
object->class.pointer = pointer;
object->x1 = x1;
object->x2 = x2;
object->freefunc = freefunc;
object->printfunc = printfunc;
/* Generate temporary name */
object_counter++;
objects_active++;
sprintf(object->name, "Untitled #%1d", object_counter);
return object;
}
/*
********************************************************************************
* XPro_EnslaveObject(object, slave)
*
* This routine adds an object to the slave list for a given object. In this
* usage, a slave object is one that the given object uses.
*
* Inputs:
* object object to modify.
* slave slave object.
*
* Return: TRUE if an error occured; FALSE if all is well.
*
* Errors:
* RL_MEMORY_ERROR if memory for the links could not be allocated.
*******************************************************************************/
RL_BOOL XPro_EnslaveObject(object, slave)
PRO_OBJECT *object, *slave;
{
XPRO_LINK *link, *link1, *link2;
if (ZPro_TestObject(object) || ZPro_TestObject(slave)) return TRUE;
/* Search object's slave list so we don't re-enslave */
for (link = object->slaves.next; link != NULL; link = link->next) {
if (link->object == slave) return FALSE;
}
/* Allocate a pair of new links */
link1 = NULL;
link2 = NULL;
link1 = (XPRO_LINK *) XRL_Malloc(sizeof(XPRO_LINK));
link2 = (XPRO_LINK *) XRL_Malloc(sizeof(XPRO_LINK));
if (link2 == NULL) {
XRL_Free((RL_VOID *) link1);
XRL_Free((RL_VOID *) link2);
return TRUE;
}
/* Insert a new link into object's slave list */
link1->object = slave;
link1->next = object->slaves.next;
object->slaves.next = link1;
/* Insert new link into slave's owner list */
link2->object = object;
link2->next = slave->owners.next;
slave->owners.next = link2;
/* Now recursively enslave all of slave's slaves */
for (link = slave->slaves.next; link != NULL; link = link->next) {
/* On failure, remove new links and free them */
if (XPro_EnslaveObject(object, link->object)) {
object->slaves.next = link1->next;
slave->owners.next = link2->next;
XRL_Free((RL_VOID *) link1);
XRL_Free((RL_VOID *) link2);
return TRUE;
}
}
return FALSE;
}
/*
********************************************************************************
* XPro_PrintInfo(object)
*
* This function prints out one line of information about an object, giving its
* name and class.
*
* Inputs:
* object object to print.
*******************************************************************************/
void XPro_PrintInfo(object)
PRO_OBJECT *object;
{
/* Check for null object */
if (object == NULL) {
printf("PRINT ERROR: Null object\n");
return;
}
/* Print out object name and class */
printf("%s:", Pro_ObjectName(object, 0));
XPro_PrintClass(&(object->class));
printf("\n");
}
/*
********************************************************************************
* XPro_ObjectName(object, coord)
*
* This routine returns a pointer to the name of an object. Unlike routine
* Pro_ObjectName(), this one does not raise class errors.
*
* Inputs:
* object object.
* coord 0 for object name;
* 1 for X-coordinate name;
* 2 for Y-coordinate name.
*
* Return: pointer to a character string giving the object's name.
*******************************************************************************/
RL_CHAR *XPro_ObjectName(object, coord)
PRO_OBJECT *object;
RL_INT4 coord;
{
RL_CHAR *t, *loc;
/* Check for invalid pointer */
if (object == NULL || object->class.id != XPRO_OBJECT_CLASS) {
return empty_name;
}
/* Identify coordinate */
if (coord == 0) return object->name;
else if (coord == 1) return object->xname;
else if (coord == 2) return object->yname;
else {
XPro_IDomainError("coordinate index", object, 0, 2, coord);
return empty_name;
}
}
/*
********************************************************************************
* XPro_ObjectPtr(object)
*
* This function returns a pointer to the sub-object of a given object.
*
* Inputs:
* object object for which to return sub-object.
*******************************************************************************/
#ifndef QUICK /* In QUICK mode, this is defined as a macro in profile.h */
RL_VOID *XPro_ObjectPtr(object)
PRO_OBJECT *object;
{
if (ZPro_TestObject(object)) return NULL;
if (object->class.pointer == NULL)
XPro_NullError("sub-object", object);
return object->class.pointer;
}
#endif
/*
********************************************************************************
* XPro_PrintClass(class)
*
* This function recursively prints out the class name of an object. It is
* called by XPro_PrintInfo().
*
* Inputs:
* class class structure to print.
*******************************************************************************/
void XPro_PrintClass(class)
XPRO_CLASS *class;
{
if (class != NULL) {
XPro_PrintClass((XPRO_CLASS *) class->pointer);
printf(" %s", class->name);
}
}
/*
********************************************************************************
* INTERNAL ROUTINES
********************************************************************************
* ZPro_RemoveOwner(object, owner)
*
* This internal routine removes the specified owner from an object. If the
* object is marked for freeing and its last owner is removed, it is deleted.
* This routine is called by Pro_FreeObject().
*
* Inputs:
* object object to modify.
* owner owner object to remove.
*******************************************************************************/
static void ZPro_RemoveOwner(object, owner)
PRO_OBJECT *object, *owner;
{
XPRO_LINK *link, *prev;
/* Walk down owner list... */
for (prev = &(object->owners); prev->next != NULL; prev = prev->next) {
link = prev->next;
/* When link to specified owner is found, remove it */
if (link->object == owner) {
prev->next = link->next;
XRL_Free(link);
/* If object is freed and has no owners, delete it */
if (object->isfreed && object->owners.next == NULL)
ZPro_DeleteObject(object);
return;
}
}
/* We should never get to this point in the code */
}
/*
********************************************************************************
* ZPro_DeleteObject(object)
*
* This internal routine frees a given object unconditionally. It is only
* called when the object is already marked freed and has no owners.
*
* Inputs:
* object object to delete.
*******************************************************************************/
static void ZPro_DeleteObject(object)
PRO_OBJECT *object;
{
objects_active--;
(*object->freefunc) (object->class.pointer);
XRL_Free(object);
}
/*
********************************************************************************
* ZPro_TestObject(object)
*
* This internal function checks to make sure an object is not NULL and not
* already freed.
*
* Inputs:
* object object to check.
*
* Return: TRUE on error; FALSE if all is well.
*
* Errors:
* PRO_CLASS_ERROR if object is NULL or not a generic object;
*******************************************************************************/
static RL_BOOL ZPro_TestObject(object)
PRO_OBJECT *object;
{
#ifndef QUICK /* These tests are disabled in QUICK mode */
if (object == NULL) {
XPro_NullError("generic object", object);
return TRUE;
}
if (object->class.id != XPRO_OBJECT_CLASS) {
XPro_ClassError("generic object", object);
return TRUE;
}
#endif
return FALSE;
}
/*
********************************************************************************
* FORTRAN INTERFACE ROUTINES
********************************************************************************
*$ Component_name:
* FPro_FreeObject (object.c)
*$ Abstract:
* This routine frees the specified object.
*$ Keywords:
* PROFILE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* subroutine FPro_FreeObject(object)
* integer*4 object
*$ Inputs:
* object FORTRAN pointer to the object to free.
*$ Outputs:
* none
*$ Returns:
* none
*$ Detailed_description:
* This routine frees the specified object. Memory is deallocated,
* associated files are closed, and any linked objects are freed.
*
* Note that the user can free an object as soon it is no longer needed for
* direct manipulation. When this routine is called, the object will still
* be retained internally by the Profile toolkit until every object that
* links to it is also freed.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* Memory is deallocated, associated files are closed, and linked objects
* are freed.
*$ Examples:
* integer*4 series, func
*
* series = FPro_ArraySeries(...) ! create a series
* func = FPro_LSplineFunc(series) ! create a function using the series
* call FPro_FreeObject(series) ! free the series because we won't use
* ! it again directly. It won't really
* ! disappear till func is freed
* write(*,*) Pro_FuncValue(func,1.d0)
* ! function can still be used
* call FPro_FreeObject(func) ! freeing the function now also frees
* ! the series too
*$ Error_handling:
* Profile toolkit error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not a profile object.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN object pointer.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
void FORTRAN_NAME(fpro_freeobject) (object)
RL_INT4 *object;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
if (ptr == NULL) return;
Pro_FreeObject((PRO_OBJECT *) ptr);
FORT_FreePointer(*object);
}
/*
********************************************************************************
*$ Component_name:
* FPro_PrintObject (object.c)
*$ Abstract:
* This routine prints out information about an object.
*$ Keywords:
* PROFILE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* subroutine FPro_PrintObject(object)
* integer*4 object
*$ Inputs:
* object FORTRAN pointer to the object to print.
*$ Outputs:
* none
*$ Returns:
* none
*$ Detailed_description:
* This routine prints out information about an object. It is used mainly
* for debugging.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* Information is printed to standard output (i.e. the terminal).
*$ Examples:
* integer*4 series
* series = FPro_ArraySeries(...) ! create a series
* call FPro_PrintObject(series) ! print out info about it
*$ Error_handling:
* RingLib toolkit error handling is in effect. No Profile toolkit
* error conditions are raised by this routine.
*
* Conditions raised:
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN object pointer.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
void FORTRAN_NAME(fpro_printobject) (object)
RL_INT4 *object;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
if (ptr == NULL) return;
Pro_PrintObject((PRO_OBJECT *) ptr);
}
/*
********************************************************************************
*$ Component_name:
* FPro_ObjectName (object.c, fprofile.for)
*$ Abstract:
* This routine returns the name of an object or one of its coordinates.
*$ Keywords:
* PROFILE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* subroutine FPro_ObjectName(object, coord, name)
* integer*4 object, coord
* character*(*) name
*$ Inputs:
* object FORTRAN pointer to the profile object.
* coord 0 for object name;
* 1 for X-coordinate name;
* 2 for Y-coordinate name.
*
*$ Outputs:
* name name of object, possibly truncated. On error, this
* string is blank.
*$ Returns:
* none
*$ Detailed_description:
* This function returns a pointer to the name of an object or one of its
* coordinates. It also replaces unprintable characters with periods and
* limits the length to 59 characters (plus a final null character).
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* This snippet of code creates a series, names it, and then prints the
* names. The result is:
* Name = Series
* X = X coord
* Y = Y coord
*
* integer*4 series
* character*80 name
*
* series = FPro_ArraySeries(...) ! create a series
* call Pro_RenameObject(series, 0, 'Series') ! name it
* call Pro_RenameObject(series, 1, 'X coord') ! name the x coord
* call Pro_RenameObject(series, 2, 'Y coord') ! name the y coord
*
* call FPro_ObjectName(series, 0, name) ! get name
* write(*,*) 'Name = ', name ! print it
* call FPro_ObjectName(series, 1, name) ! get X cordinate
* write(*,*) 'X = ', name ! print it
* call FPro_ObjectName(series, 2, name) ! get Y cordinate
* write(*,*) 'Y = ', name ! print it
*$ Error_handling:
* Profile library error handling is in effect. On non-fatal error, it
* returns an empty string.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not a profile toolkit
* object.
* PRO_DOMAIN_ERROR if the coord is outside the range 0 to 2.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN pointer.
*$ Limitations:
* Object names are limited to 59 characters.
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
********************************************************************************
* Note: GPro_ObjectName() defined here is the intermediary routine between
* FPro_ObjectName() and Pro_ObjectName(), allowing for the fact that strings
* cannot be passed directly between FORTRAN and C. See fprofile.for for the
* rest of the code.
*
* subroutine GPro_ObjectName(object, coord, buffer, lbuffer)
* integer*4 object, coord, lbuffer
* byte buffer(*)
*******************************************************************************/
void FORTRAN_NAME(gpro_objectname)(object, coord, buffer, lbuffer)
RL_INT4 *object, *coord, *lbuffer;
RL_CHAR *buffer;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
if (ptr == NULL) {
buffer[0] = '\0';
return;
}
strncpy(buffer, Pro_ObjectName((PRO_OBJECT *) ptr, *coord), *lbuffer-1);
buffer[*lbuffer-1] = '\0';
}
/*
********************************************************************************
*$ Component_name:
* FPro_RenameObject (object.c, fprofile.for)
*$ Abstract:
* This routine changes the name of an object or one of its coordinates.
*$ Keywords:
* PROFILE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* subroutine FPro_RenameObject(object, coord, name)
* integer*4 object, coord
* character*(*) name
*$ Inputs:
* object FORTRAN pointer to the object to rename.
* coord 0 for object name;
* 1 for X-coordinate name;
* 2 for Y-coordinate name.
* name character string containing new name.
*$ Outputs:
* none
*$ Returns:
* none
*$ Detailed_description:
* This routine changes the name of an object or one of its coordinates.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* This snippet of code creates a series, names it, and then prints the
* names. The result is:
* Name = Series
* X = X coord
* Y = Y coord
*
* integer*4 series
* character*80 name
*
* series = FPro_ArraySeries(...) ! create a series
* call Pro_RenameObject(series, 0, 'Series') ! name it
* call Pro_RenameObject(series, 1, 'X coord') ! name the x coord
* call Pro_RenameObject(series, 2, 'Y coord') ! name the y coord
*
* call FPro_ObjectName(series, 0, name) ! get name
* write(*,*) 'Name = ', name ! print it
* call FPro_ObjectName(series, 1, name) ! get X cordinate
* write(*,*) 'X = ', name ! print it
* call FPro_ObjectName(series, 2, name) ! get Y cordinate
* write(*,*) 'Y = ', name ! print it
*$ Error_handling:
* Profile library error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not a profile toolkit
* object.
* PRO_DOMAIN_ERROR if the coord is outside the range 0 to 2.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN pointer.
*$ Limitations:
* Object names are limited to 59 characters.
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
********************************************************************************
* Note: GPro_RenameObject() defined here is the intermediary routine between
* FPro_RenameObject() and Pro_RenameObject(), allowing for the fact that strings
* cannot be passed directly between FORTRAN and C. See fprofile.for for the
* rest of the code.
*
* subroutine GPro_RenameObject(object, coord, name)
* integer*4 object, coord
* byte name(*)
*******************************************************************************/
void FORTRAN_NAME(gpro_renameobject) (object, coord, name)
RL_INT4 *object, *coord;
RL_CHAR *name;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
if (ptr == NULL) return;
Pro_RenameObject((PRO_OBJECT *) ptr, *coord, name);
}
/*
********************************************************************************
*$ Component_name:
* FPro_ObjectDomain (object.c)
*$ Abstract:
* This routine returns the domain (X-limits) for an object.
*$ Keywords:
* PROFILE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* real*8 function FPro_ObjectDomain(object, x1, x2)
* integer*4 object
* real*8 x1, x2
*$ Inputs:
* object pointer to the object.
*$ Outputs:
* x1, x2 lower and upper limits of domain (inclusive); unchanged
* on non-fatal error.
*$ Returns:
* size of domain (x2 - x1); 0. on non-fatal error.
*$ Detailed_description:
* This routine returns the domain (X-limits) for an object. It also
* returns the size of the domain.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* none
*$ Error_handling:
* Profile library error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if the object is NULL or not a profile object.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN pointer.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
* 1.1: October 1999
*$ Change_history:
* 1.1: QUICK mode compile option added.
*******************************************************************************/
RL_FLT8 FORTRAN_NAME(fpro_objectdomain) (object, x1, x2)
RL_INT4 *object;
RL_FLT8 *x1, *x2;
{
RL_VOID *ptr;
/* Look up object pointer */
ptr = FORT_GetPointer(*object);
#ifndef QUICK
if (ptr == NULL) return 0.;
#endif
return Pro_ObjectDomain((PRO_OBJECT *) ptr, x1, x2);
}
/*
********************************************************************************
*$ Component_name:
* FPro_ObjectOverlap (object.c)
*$ Abstract:
* This routine finds the domain of overlap of two or more objects.
*$ Keywords:
* PROFILE
* FORTRAN, PUBLIC, SUBROUTINE
*$ Declarations:
* subroutine FPro_ObjectOverlap(object, refobj, x1, x2)
* integer*4 object, refobj
* real*8 x1, x2
*$ Inputs:
* object FORTRAN pointer to the object to test for overlap.
* refobj FORTRAN pointer to the reference object (see below).
* x1, x2 current domain limits; ignored if object = refobj.
*$ Outputs:
* x1, x2 updated domain limits.
*$ Returns:
* size of overlapping domain, i.e. (x2 - x1), or 0. on non-fatal error.
*$ Detailed_description:
* This routine finds the domain of overlap of two or more objects. It
* also checks to confirm that the X-coordinate names match.
*
* On the first call to this routine, the object and the reference object
* should be the same. In this case, the domain is saved in x1 and x2.
* On subsequent calls, the first argument should be each new object to
* overlap with the reference object. After the last call, *x1 and *x2
* contain the intersection of all the objects' domains. If at any time
* the intersection becomes empty, an error condition is raised.
*$ External_references:
* Profile toolkit
*$ Side_effects:
* none
*$ Examples:
* Suppose you wish to find the overlapping domain of object1, object2 and
* object3.
*
* real*8 x1, x2
*
* call FPro_ObjectOverlap(object1, object1, x1, x2)
* call FPro_ObjectOverlap(object2, object1, x1, x2)
* call FPro_ObjectOverlap(object3, object1, x1, x2)
*
* At this point, x1 and x2 are the limits of the overlapping domain. If
* any of the X-coordinate names do not match or if the overlapping domain
* is empty, an error condition is raised.
*$ Error_handling:
* Profile toolkit error handling is in effect.
*
* Conditions raised:
* PRO_CLASS_ERROR if object is NULL or not a profile object.
* PRO_COORD_MISMATCH if X-coordinate names of objects do not match.
* PRO_EMPTY_DOMAIN if overlapping domain is empty.
* FORTRAN_POINTER_ERROR if object is not a valid FORTRAN object pointer.
*
* On a non-fatal PRO_COORD_MISMATCH condition, the domain limits are still
* updated and the return is normal. Otherwise, 0. is returned.
*$ Limitations:
* none
*$ Author_and_institution:
* Mark R. Showalter
* NASA/Ames Research Center
*$ Version_and_date:
* 1.0: March 1998
*$ Change_history:
* none
*******************************************************************************/
RL_FLT8 FORTRAN_NAME(fpro_objectoverlap) (object, refobj, x1, x2)
RL_INT4 *object, *refobj;
RL_FLT8 *x1, *x2;
{
RL_VOID *ptr1, *ptr2;
/* Look up object pointers */
ptr1 = FORT_GetPointer(*object);
if (ptr1 == NULL) return 0.;
ptr2 = FORT_GetPointer(*refobj);
if (ptr2 == NULL) return 0.;
/* Call function */
return Pro_ObjectOverlap((PRO_OBJECT *) ptr1, (PRO_OBJECT *) ptr2, x1, x2);
}
/*******************************************************************************
*/