diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2018-01-09 19:26:44 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2018-01-09 19:26:44 (GMT) |
commit | 1332d38f2805d986ea130e43218c0d2e870b4dc1 (patch) | |
tree | aa72853cb8d0d8fcd53a6f5eddf196a374226706 /ast/object.c | |
parent | 5e545ec8058cc5238dc870468b34b5d4617f307f (diff) | |
download | blt-1332d38f2805d986ea130e43218c0d2e870b4dc1.zip blt-1332d38f2805d986ea130e43218c0d2e870b4dc1.tar.gz blt-1332d38f2805d986ea130e43218c0d2e870b4dc1.tar.bz2 |
update ast 8.6.2
Diffstat (limited to 'ast/object.c')
-rw-r--r-- | ast/object.c | 8950 |
1 files changed, 0 insertions, 8950 deletions
diff --git a/ast/object.c b/ast/object.c deleted file mode 100644 index 2f8d869..0000000 --- a/ast/object.c +++ /dev/null @@ -1,8950 +0,0 @@ -/* -*class++ - -* Name: -* Object - -* Purpose: -* Base class for all AST Objects. - -* Constructor Function: -* None. - -* Description: -* This class is the base class from which all other classes in the -* AST library are derived. It provides all the basic Object -* behaviour and Object manipulation facilities required throughout -* the library. There is no Object constructor, however, as Objects -* on their own are not useful. - -* Inheritance: -* The Object base class does not inherit from any other class. - -* Attributes: -* All Objects have the following attributes: -* -* - Class: Object class name -* - ID: Object identification string -* - Ident: Permanent Object identification string -* - Nobject: Number of Objects in class -* - ObjSize: The in-memory size of the Object in bytes -* - RefCount: Count of active Object pointers -* - UseDefs: Allow use of default values for Object attributes? - -* Functions: -c The following functions may be applied to all Objects: -f The following routines may be applied to all Objects: -* -c - astAnnul: Annul a pointer to an Object -c - astBegin: Begin a new AST context -c - astClear: Clear attribute values for an Object -c - astClone: Clone a pointer to an Object -c - astCopy: Copy an Object -c - astCreatedAt: Returns information about where an object was created -c - astDelete: Delete an Object -c - astEnd: End an AST context -c - astEscapes: Control whether graphical escape sequences are removed -c - astExempt: Exempt an Object pointer from AST context handling -c - astExport: Export an Object pointer to an outer context -c - astGet<X>: Get an attribute value for an Object -c - astHasAttribute: Test if an Object has a named attribute -c - astImport: Import an Object pointer to the current context -c - astIsA<Class>: Test class membership -c - astLock: Lock an Object for use by the calling thread -c - astToString: Create an in-memory serialisation of an Object -c - astSame: Do two AST pointers refer to the same Object? -c - astSet: Set attribute values for an Object -c - astSet<X>: Set an attribute value for an Object -c - astShow: Display a textual representation of an Object on standard -c output -c - astTest: Test if an attribute value is set for an Object -c - astTune: Set or get an integer AST tuning parameter -c - astTuneC: Set or get a character AST tuning parameter -c - astUnlock: Unlock an Object for use by other threads -c - astFromString: Re-create an Object from an in-memory serialisation -c - astVersion: Return the verson of the AST library being used. -f - AST_ANNUL: Annul a pointer to an Object -f - AST_BEGIN: Begin a new AST context -f - AST_CLEAR: Clear attribute values for an Object -f - AST_CLONE: Clone a pointer to an Object -f - AST_COPY: Copy an Object -f - AST_DELETE: Delete an Object -f - AST_END: End an AST context -f - AST_ESCAPES: Control whether graphical escape sequences are removed -f - AST_EXEMPT: Exempt an Object pointer from AST context handling -f - AST_EXPORT: Export an Object pointer to an outer context -f - AST_GET<X>: Get an attribute value for an Object -f - AST_HASATTRIBUTE: Test if an Object has a named attribute -f - AST_IMPORT: Import an Object pointer to the current context -f - AST_ISA<CLASS>: Test class membership -f - AST_SAME: Do two AST pointers refer to the same Object? -f - AST_SET: Set attribute values for an Object -f - AST_SET<X>: Set an attribute value for an Object -f - AST_SHOW: Display a textual representation of an Object on standard -f output -f - AST_TEST: Test if an attribute value is set for an Object -f - AST_TUNE: Set or get an integer AST tuning parameter -f - AST_TUNEC: Set or get a character AST tuning parameter -f - AST_VERSION: Return the verson of the AST library being used. - -* Copyright: -* Copyright (C) 1997-2006 Council for the Central Laboratory of the -* Research Councils -* Copyright (C) 2010 Science & Technology Facilities Council. -* All Rights Reserved. - -* Licence: -* This program is free software: you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation, either -* version 3 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 Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General -* License along with this program. If not, see -* <http://www.gnu.org/licenses/>. - -* Authors: -* RFWS: R.F. Warren-Smith (Starlink) -* DSB: David S. Berry (Starlink) - -* History: -* 1-FEB-1996 (RFWS): -* Original version. -* 22-APR-1996 (RFWS): -* Added attribute setting functions. -* 2-JUL-1996 (RFWS): -* Added functions to support the external interface (using -* identfiers). -* 10-SEP-1996 (RFWS): -* Added I/O facilities. -* 30-MAY-1997 (RFWS): -* Add ID attribute. -* 14-JUL-1997 (RFWS): -* Add astExempt function. -* 14-OCT-1997 (RFWS): -* Fixed uninitialised use of "dynamic" in astCopy_. -* 14-NOV-1997 (RFWS): -* Remove the subversive C "strtok" function. -* 20-JAN-1998 (RFWS): -* Make the astClear and astRVSet methods virtual. -* 29-APR-1998 (RFWS): -* Fixed bug in algorithm for encoding Object IDs. -* 15-SEP-1999 (RFWS) -* Made astAnnulId accessible from protected code. -* 12-APR-2000 (DSB): -* Zero all memory allocated for a new Object in InitObject before -* storing any new values in the memory. -* 3-APR-2001 (DSB): -* Added the Ident attribute. -* 28-SEP-2001 (DSB): -* Modified VSet to ensure a non-null string always follows the equal -* sign in the attribute setting passed to SetAttrib. -* 27-NOV-2002 (DSB): -* Modified astShow to use astWrite instead of astDump, so that -* invocations of astShow will be included in the count of the -* number of invocations of astWrite returned by astWriteInvocations. -* 8-JAN-2003 (DSB): -* Changed private InitVtab method to protected astInitObjectVtab -* method. -* 8-FEB-2004 (DSB): -* Added astEscapes. -* 10-FEB-2004 (DSB): -* Added debug conditional code to keep track of memory leaks. -* 22-AUG-2004 (DSB): -* Added astEqual -* 27-JAN-2005 (DSB): -* Correct use of ->ident pointers, and added further DEBUG blocks. -* 11-MAR-2005 (DSB): -* Added attribute UseDefs. -* 14-FEB-2006 (DSB): -* Added attribute ObjSize. -* 23-FEB-2006 (DSB): -* Added MemoryCaching tuning parameter. -* 27-FEB-2006 (DSB): -* Include Objects returned by astCopy in the ObjectCaching system. -* 28-FEB-2006 (DSB): -* Use astOK to protect against errors within astGrow. -* 1-MAR-2006 (DSB): -* Replace astSetPermMap within DEBUG blocks by astBeginPM/astEndPM. -* 26-MAY-2006 (DSB): -* Correct handling of commas within the attribute value supplied -* to astSetC. -* 30-MAY-2006 (DSB): -* Correct the correction made to handle commas within attribute -* 6-JUN-2007 (DSB): -* Fix harmless compiler warnings. -* 21-JUN-2007 (DSB): -* In astSet<X>, ignore trailing spaces in the attribute name. -* 22-JUN-2007 (DSB): -* - Make astVSet return a pointer to dynamic memory holding the -* expanded setting string. -* - Add astSetVtab, and astCast. -* 27-JUN-2007 (DSB): -* Modify astInitObject so that it ignores the supplied "size" value -* if some memory is supplied. -* 2-JULY-2007 (DSB): -* Fix memory access problem in VSet. -* 20-SEP-2007 (DSB): -* In astDelete, ensure the error status is reset before calling -* astGrow to extend the vtab free list. -* 22-APR-2008 (DSB): -* Added astSame. -* 24-OCT-2008 (DSB): -* Prevent a mutex deadlock that could occur when annulling an -* Object ID. -* 28-JAN-2008 (DSB): -* Allow unlocked objects to be annulled using astAnnul. -* 14-OCT-2009 (DSB): -* Modify astCast to make it a virtual function and add type -* checking. -* 7-APR-2010 (DSB): -* Added method astHasAttribute. -* 24-AUG-2010 (DSB): -* Allow commas to be included in attribute values supplied to -* astSet or astVSet by putting quotes around the attribute value. -* 16-JUN-2011 (DSB): -* Added component "iref" to the Object structure. This is an -* integer identifier for each object that is unique within the -* class of the object. Useful for debugging. -* 22-JUL-2011 (DSB): -* Add methods astSetProxy and astGetProxy. -* 2-SEP-2011 (DSB): -* Add functions astToString and astFromString. -* 13-SEP-2013 (DSB): -* Report an error in astAnnul if the supplied object handle is owned by -* a different thread. Note, the Object itself does not need to be owned -* by the current thread, since it should be possible for a thread to -* relinquish a pointer to an object (i.e. a handle) without actually -* owning the object itself. -* 6-JAN-2014 (DSB): -* Added method astEnvSet. -* 9-APR-2015 (DSB): -* Modify VSet to handle "%s" setting strings (i.e. where the whole -* list of settings is provided as a single variable argument). -* This is needed because supplying the while settings string in -* place of "%s" is considered a security issue by many compilers. -* 4-JUL-2017 (DSB): -* Within astLockId, perform the correct check that the supplied -* object handle is not locked by another thread. -* 17-SEP-2017 (DSB): -* Add function astCreatedAt. This increases the size of a Handle -* structure by 20 bytes. If this turns out to be problematic -* this facility could be controlled using a configure option. -*class-- -*/ - -/* Module Macros. */ -/* ============== */ -/* Set the name of the class we are implementing. This indicates to - the header files that define class interfaces that they should make - "protected" symbols available. */ -#define astCLASS Object - -#define INVALID_CONTEXT -1 /* Context value for handles that have no - associated Object */ -#define UNOWNED_CONTEXT -2 /* Context value for handles for objects - that are not locked by any thread */ - - -/* Include files. */ -/* ============== */ - -/* Configuration information */ -/* ------------------------ */ -#include "version.h" /* Version numbers */ -#if HAVE_CONFIG_H -#include <config.h> -#endif - -/* Interface definitions. */ -/* ---------------------- */ -#include "error.h" /* Error reporting facilities */ -#include "memory.h" /* Memory allocation facilities */ -#include "channel.h" /* I/O channels */ -#include "keymap.h" /* Hash tables */ -#include "object.h" /* Interface definition for this class */ -#include "plot.h" /* Plot class (for astStripEscapes) */ -#include "globals.h" /* Thread-safe global data access */ - -/* Error code definitions. */ -/* ----------------------- */ -#include "ast_err.h" /* AST error codes */ - -/* C header files. */ -/* --------------- */ -#include <ctype.h> -#include <errno.h> -#include <float.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <limits.h> - -/* Type Definitions */ -/* ================ */ -/* Structure used to pass data between astToString/FromString and the - corresponding Channel source and sink functions. */ -typedef struct StringData { - char *ptr; /* Pointer to serialisation text */ - char *buff; /* Pointer to a buffer for a single line of text */ - int len; /* Current length of serialisation text */ -} StringData; - -/* Module Variables. */ -/* ================= */ - -/* The following globals have the same values in all threads and so do - not need to be in thread-specific data. */ -/* ------------------------------------------------------------------ */ - -/* Character-valued tuning parameters. */ -#define MAXLEN_TUNEC 200 -static char hrdel[ MAXLEN_TUNEC ] = "%-%^50+%s70+h%+"; -static char mndel[ MAXLEN_TUNEC ] = "%-%^50+%s70+m%+"; -static char scdel[ MAXLEN_TUNEC ] = "%-%^50+%s70+s%+"; -static char dgdel[ MAXLEN_TUNEC ] = "%-%^53+%s60+o%+"; -static char amdel[ MAXLEN_TUNEC ] = "%-%^20+%s85+'%+"; -static char asdel[ MAXLEN_TUNEC ] = "%-%^20+%s85+\"%+"; -static char exdel[ MAXLEN_TUNEC ] = "10%-%^50+%s70+"; - -/* A pointer full of zeros. */ -static AstObject *zero_ptr; - -/* A flag which indicates what should happen when an AST Object is - deleted. If this flag is non-zero, the memory used by the Object is - not freed, but a pointer to it is placed on the end of a list of free - memory chunk pointers so that the memory can be re-used if necessary - avoiding the need to re-allocate memory with malloc (which is slow). - A separate list of free memory chunks is kept for each class because - each class object will require chunks of a different size. Pointers - to these lists are stored in the virtual function table associated - with each class. All memory on these lists is freed when object - caching is switched off via the astTune function. */ -static int object_caching = 0; - -/* Set up global data access, mutexes, etc, needed for thread safety. */ -#ifdef THREAD_SAFE - -/* Define the initial values for the global data for this module. */ -#define GLOBAL_inits \ - globals->Retain_Esc = 0; \ - globals->Context_Level = 0; \ - globals->GetAttrib_Buff[ 0 ] = 0; \ - globals->AstGetC_Init = 0; \ - globals->AstGetC_Istr = 0; \ - globals->Active_Handles = NULL; \ - globals->Class_Init = 0; \ - globals->Nvtab = 0; \ - globals->Known_Vtabs = NULL; - -/* Create the function that initialises global data for this module. */ -astMAKE_INITGLOBALS(Object) - -/* Define macros for accessing each item of thread specific global data. */ -#define retain_esc astGLOBAL(Object,Retain_Esc) -#define context_level astGLOBAL(Object,Context_Level) -#define active_handles astGLOBAL(Object,Active_Handles) -#define getattrib_buff astGLOBAL(Object,GetAttrib_Buff) -#define astgetc_strings astGLOBAL(Object,AstGetC_Strings) -#define astgetc_istr astGLOBAL(Object,AstGetC_Istr) -#define astgetc_init astGLOBAL(Object,AstGetC_Init) -#define class_init astGLOBAL(Object,Class_Init) -#define class_vtab astGLOBAL(Object,Class_Vtab) -#define nvtab astGLOBAL(Object,Nvtab) -#define known_vtabs astGLOBAL(Object,Known_Vtabs) - -/* mutex1 is used to prevent tuning parameters being accessed by more - than one thread at any one time. */ -static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_MUTEX1 pthread_mutex_lock( &mutex1 ); -#define UNLOCK_MUTEX1 pthread_mutex_unlock( &mutex1 ); - -/* mutex2 is used to prevent the global lists of object handles being - accessed by more than one thread at any one time. */ -static pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_MUTEX2 pthread_mutex_lock( &mutex2 ); -#define UNLOCK_MUTEX2 pthread_mutex_unlock( &mutex2 ); - -/* Each Object contains two mutexes. The primary mutex (mutex1) is used - to guard access to all aspects of the Object except for the "locker" - and "ref_count" items. The secondary mutex (mutex2) is used to guard - access to these two remaining items. We need this secondary mutex - since the "locker" and "ref_count" items need to be accessable within - a thread even if that thread has not locked the Object using astLock. - Define macros for accessing these two mutexes. */ -#define LOCK_PMUTEX(this) (pthread_mutex_lock(&((this)->mutex1))) -#define UNLOCK_PMUTEX(this) (pthread_mutex_unlock(&((this)->mutex1))) -#define LOCK_SMUTEX(this) (pthread_mutex_lock(&((this)->mutex2))) -#define UNLOCK_SMUTEX(this) (pthread_mutex_unlock(&((this)->mutex2))) - - - - - -/* If thread safety is not needed, declare and initialise globals at static - variables. */ -#else - -/* Define the class virtual function table and its initialisation flag as - static variables. */ -static int class_init = 0; /* Virtual function table initialised? */ -static AstObjectVtab class_vtab; /* Virtual function table */ - -/* A list of pointers to all the known class virtual function tables. */ -static int nvtab = 0; -static AstObjectVtab **known_vtabs = NULL; - -/* A flag which indicates if AST functions which return text strings - should retain any graphical escape sequences (as interpreted by the - Plot class). */ -static int retain_esc = 0; - -/* Context level (Begin/End/Exempt/Export) */ -static int context_level = 0; - -/* Array of list heads for each context (each list is a list of Handle - structures). */ -static int *active_handles = NULL; - -/* String returned by GetAttrib. */ -static char getattrib_buff[ AST__GETATTRIB_BUFF_LEN + 1 ] = ""; - -/* Pointers to string buffers returned by astGetC. */ -static char *astgetc_strings[ AST__ASTGETC_MAX_STRINGS ]; - -/* Offset of next string in "AstGetC_Strings" */ -static int astgetc_istr = 0; - -/* "AstGetC_Strings" array initialised? */ -static int astgetc_init = 0; - -/* Null macros for mutex locking and unlocking */ -#define LOCK_MUTEX1 -#define UNLOCK_MUTEX1 -#define LOCK_MUTEX2 -#define UNLOCK_MUTEX2 -#define LOCK_PMUTEX(this) -#define LOCK_SMUTEX(this) -#define UNLOCK_PMUTEX(this) -#define UNLOCK_SMUTEX(this) - -#endif - - -/* Prototypes for Private Member Functions. */ -/* ======================================== */ -static AstObject *Cast( AstObject *, AstObject *, int * ); -static const char *GetID( AstObject *, int * ); -static const char *GetAttrib( AstObject *, const char *, int * ); -static const char *GetIdent( AstObject *, int * ); -static const char *Get( AstObject *, const char *, int * ); -static const char *FromStringSource( void ); -static int Equal( AstObject *, AstObject *, int * ); -static int GetObjSize( AstObject *, int * ); -static int HasAttribute( AstObject *, const char *, int * ); -static int Same( AstObject *, AstObject *, int * ); -static int TestAttrib( AstObject *, const char *, int * ); -static int TestID( AstObject *, int * ); -static int TestIdent( AstObject *, int * ); -static unsigned long Magic( const AstObject *, size_t, int * ); -static void CleanAttribs( AstObject *, int * ); -static void Clear( AstObject *, const char *, int * ); -static void ClearAttrib( AstObject *, const char *, int * ); -static void ClearIdent( AstObject *, int * ); -static void ClearID( AstObject *, int * ); -static void Dump( AstObject *, AstChannel *, int * ); -static void EmptyObjectCache( int * ); -static void ToStringSink( const char * ); -static void SetAttrib( AstObject *, const char *, int * ); -static void SetID( AstObject *, const char *, int * ); -static void SetIdent( AstObject *, const char *, int * ); -static void Show( AstObject *, int * ); -static void VSet( AstObject *, const char *, char **, va_list, int * ); -static void EnvSet( AstObject *, int * ); - -static int GetUseDefs( AstObject *, int * ); -static int TestUseDefs( AstObject *, int * ); -static void ClearUseDefs( AstObject *, int * ); -static void SetUseDefs( AstObject *, int, int * ); - -#if defined(THREAD_SAFE) -static void ChangeThreadVtab( AstObject *, int * ); -static int ManageLock( AstObject *, int, int, AstObject **, int * ); -#endif - -/* Member functions. */ -/* ================= */ -AstObject *astAnnul_( AstObject *this, int *status ) { -/* -*++ -* Name: -c astAnnul -f AST_ANNUL - -* Purpose: -* Annul a pointer to an Object. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c AstObject *astAnnul( AstObject *this ) -f CALL AST_ANNUL( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function annuls a pointer to an Object so that it is no -f This routine annuls a pointer to an Object so that it is no -* longer recognised as a valid pointer by the AST library. Any -* resources associated with the pointer are released and made -* available for re-use. -* -c This function also decrements the Object's RefCount attribute by -f This routine also decrements the Object's RefCount attribute by -* one. If this attribute reaches zero (which happens when the last -* pointer to the Object is annulled), then the Object is deleted. - -* Parameters: -c this -c The Object pointer to be annulled. -f THIS = INTEGER (Given and Returned) -f The Object pointer to be annulled. A null pointer value (AST__NULL) -f is always returned. -f STATUS = INTEGER (Given and Returned) -f The global status. - -c Returned Value: -c astAnnul() -c A null Object pointer (AST__NULL) is always returned. -c -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Notes: -c - This function will attempt to annul the pointer even if the -c Object is not currently locked by the calling thread (see astLock). -c - This function attempts to execute even if the AST error -c status is set -f - This routine attempts to execute even if STATUS is set to an -f error value -* on entry, although no further error report will be -* made if it subsequently fails under these circumstances. In -* particular, it will fail if the pointer suppled is not valid, -* but this will only be reported if the error status is clear on -* entry. -*-- -*/ - -/* Check the pointer to ensure it identifies a valid Object (this - generates an error if it doesn't). */ - if ( !astIsAObject( this ) ) return NULL; - -/* Get a lock on the object's secondary mutex. This mutex guards access - to the "ref_count" and "locker" components of the AstObject structure. */ - LOCK_SMUTEX(this); - -#ifdef MEM_DEBUG - { int rc; - char buf[100]; - rc = this->ref_count; - sprintf(buf,"annulled (refcnt: %d -> %d)", rc, rc-1 ); - astMemoryUse( this, buf ); - } -#endif - -/* Decrement the Object's reference count. */ - --(this->ref_count); - -/* Unlock the object's secondary mutex. */ - UNLOCK_SMUTEX(this); - -/* Decrement the Object's reference count and delete the Object if - necessary. */ - if ( !this->ref_count ) (void) astDelete( this ); - -/* Always return NULL. */ - return NULL; -} - -static AstObject *Cast( AstObject *this, AstObject *obj, int *status ) { -/* -*+ -* Name: -* astCast - -* Purpose: -* Cast an Object into an instance of a sub-class. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* AstObject *astCast( AstObject *this, AstObject *obj ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a deep copy of an ancestral component of the -* supplied object. The required class of the ancestral component is -* specified by another object. Specifically, if "this" and "new" are -* of the same class, a copy of "this" is returned. If "this" is an -* instance of a subclass of "obj", then a copy of the component -* of "this" that matches the class of "obj" is returned. Otherwise, -* a NULL pointer is returned without error. - -* Parameters: -* this -* Pointer to the Object to be cast. -* obj -* Pointer to an Object that defines the class of the returned Object. -* The returned Object will be of the same class as "obj". - -* Returned Value: -* A pointer to the new Object. NULL if "this" is not a sub-class of -* "obj", or if an error occurs. - -* Notes: -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - AstObject *new; - int generation_gap; - -/* Initialise */ - new = NULL; - -/* Check inherited status */ - if( !astOK ) return new; - -/* Check pointer have been supplied. */ - if( this && obj ) { - -/* See how many steps up the class inheritance ladder it is from "this" to - "obj". A positive value is returned if "this" is a sub-class of "obj". - A negative value is returned if "obj" is a sub-class of "this". Zero - is returned if they are of the same class. AST__COUSIN is returned if - they share a common ancestor but are not on the same line of descent. */ - generation_gap = astClassCompare( astVTAB( this ), astVTAB( obj ) ); - -/* If the two objects are of the same class, just return a copy of - "this". */ - if( generation_gap == 0 ) { - new = astCopy( this ); - -/* If "this" is a subclass of "obj", return a deep copy of "this" cast - into the class of "obj". */ - } else if( generation_gap != AST__COUSIN && generation_gap > 0 ) { - new = astCastCopy( this, obj ); - - } - } - -/* Return the new pointer. */ - return new; -} - -AstObject *astCastCopy_( AstObject *this, AstObject *obj, int *status ) { -/* -*+ -* Name: -* astCastCopy - -* Purpose: -* Cast an Object into an instance of a sub-class, without type-checking. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astCastCopy( AstObject *this, AstObject *obj ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a deep copy of an ancestral component of the -* supplied object. The required class of the ancestral component is -* specified by another object. No checks are performed that "this" is -* a sub-class of "obj". -* -* It works by temporarily changing the vtab in "this" to be the same -* as in "obj", and then doing a deep copy, and then re-instating the -* original vtab. - -* Parameters: -* this -* Pointer to the Object to be cast. -* obj -* Pointer to an Object that defines the class of the returned Object. -* The returned Object will be of the same class as "obj". - -* Returned Value: -* A pointer to the new Object. - -* Notes: -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - AstObject *new; - AstObjectVtab *this_vtab; - size_t this_size; - -/* Initialise */ - new = NULL; - -/* Check inherited status */ - if( !astOK ) return new; - -/* Check pointer have been supplied. */ - if( this && obj ) { - -/* Save a pointer to the original virtual function tables for "this". */ - this_vtab = astVTAB( this ); - -/* Temporarily change the vtab of "this" to that of "obJ". */ - this->vtab = astVTAB( obj ); - -/* Temporarily change the size of "this" to be the size of "obj". */ - this_size = this->size; - this->size = obj->size; - -/* Now take a copy of the object (now considered to be an instance of the - class specified by "obj"). */ - new = astCopy( this ); - -/* Re-instate the original Object vtab and size. */ - this->vtab = this_vtab; - this->size = this_size; - -/* The sub-clas to which "this" originally belonged may have extended the - range of values allowed for one or more of the attributes inherited from - the "obj" class. This means that the current attribute values stored - in the returned object may be inappropriate for the class of "obj". An - example is the System attribute defined by the Frame class, and extended - by sub-classes of Frame. So we now call astCleanAttribs to ensure that - any inappropriate attribute values are cleared in the returned object. */ - astCleanAttribs( new ); - } - -/* Return the new pointer. */ - return new; -} - -#if defined(THREAD_SAFE) -static void ChangeThreadVtab( AstObject *this, int *status ){ -/* -* Name: -* ChangeThreadVtab - -* Purpose: -* Modify an Object structure so that it refers to a vtab created by -* the currently executing thread. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* void ChangeThreadVtab( AstObject *this, int *status ) - -* Class Membership: -* Object member function. - -* Description: -* Each Object structure contains a pointer to a virtual function -* table (vtab) that identifies information about the class to -* which the Object belongs (function pointers, Object caches, -* etc). In order to avoid use of mutexes (which can slow down AST -* applications enormously), each thread has its own set of vtab -* structures (one for each AST class) stored in thread-specific -* data. Each time an Object is locked by the currently executing -* thread, this function should be called to change the vtab pointer -* in the Object to refer to the vtab relevant to the currently -* executing thread. - -* Parameters: -* this -* Pointer to the Object. -* status -* Pointer to the inherited status variable. - -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS - const char *class; - int i; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to Thread-specific data for the currently executing thread. */ - astGET_GLOBALS(this); - -/* Get the class name for the supplied Object. This uses the existing - vtab pointer in the Object structure to locate the required GetClass - method and the class name. This vtab pointer may be for a vtab created - by a different thread to the one currently executing, but this shouldn't - matter since we are not modifying the vtab contents. */ - class = astGetClass( this ); - -/* Check a class name was obtained */ - if( class ) { - -/* Loop round the vtab structures created by the currently executing thread. */ - for( i = 0; i < nvtab; i++ ) { - -/* If the current vtab is for a class that matches the class of the - supplied Object, then store a pointer to the vtab in the Object - structure, and exit. */ - if( !strcmp( class, known_vtabs[ i ]->class ) ) { - this->vtab = known_vtabs[ i ]; - break; - } - } - } -} -#endif - -AstObject *astCheckLock_( AstObject *this, int *status ) { -/* -*+ -* Name: -* astCheckLock - -* Purpose: -* Check that supplied Object is locked by the calling thread. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astCheckLock( AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function reports an error if the supplied object has not -* previously been locked (using astLock) by the calling thread. - -* Parameters: -* this -* Pointer to the Object. - -* Returned Value: -* A copy of the supplied pointer ("this") is returned. The Object -* reference count is not changed. - -* Notes: -* - This function attempts to execute even if an error has already -* occurred. - -*- -*/ - -/* This function does nothing in the non-threads version of libast. */ -#if defined(THREAD_SAFE) - -/* Local Variables; */ - AstObject *fail; - -/* Check the supplied pointer. */ - if( this ) { - -/* First use the private ManageLock function rather than the virtual - astManageLock method to check the top level Object is locked for use - by the current thread. This saves time and allows a more appropriate - error message to be issued. */ - if( ManageLock( this, AST__CHECKLOCK, 0, NULL, status ) ) { - if( astOK ) { - astError( AST__LCKERR, "astCheckLock(%s): The supplied %s cannot " - "be used since it is not locked for use by the current " - "thread (programming error).", status, astGetClass( this ), - astGetClass( this ) ); - } - -/* If the top level Object is locked, now use the virtual astManageLock - method to check any objects contained within the top level Object. */ - } else if( astManageLock( this, AST__CHECKLOCK, 0, &fail ) ) { - if( astOK ) { - astError( AST__LCKERR, "astCheckLock(%s): The supplied %s cannot " - "be used since a %s contained within the %s is not " - "locked for use by the current thread (programming " - "error).", status, astGetClass( this ), - astGetClass( this ), astGetClass( fail ), - astGetClass( this ) ); - } - } - } -#endif - -/* Return the supploed pointer. */ - return this; - -} - -int astClassCompare_( AstObjectVtab *class1, AstObjectVtab *class2, - int *status ) { -/* -*+ -* Name: -* astClassCompare - -* Purpose: -* Determine the relationship between two AST classes. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* int astClassCompare( AstObjectVtab *class1, AstObjectVtab *class2 ) - -* Class Membership: -* Object method. - -* Description: -* This function returns the number of steps up the class inheritance -* ladder from the class specified by "class1" to the class specified -* by "class2". - -* Parameters: -* class1 -* Pointer to a virtual function table describing the first AST class. -* class2 -* Pointer to a virtual function table describing the second AST class. - -* Returned Value: -* The generation gap between "class1" and "class2". The result will be -* positive if "class1" is a subclass of "class2", negative if "class2" -* is a subclass of "class1", zero if they are of the same class (or -* an error occurs), or AST__COUSIN if they are not on the same line -* of descent. - -*- -*/ - -/* Local Variables: */ - AstClassIdentifier *class1_id; - AstClassIdentifier *class2_id; - AstClassIdentifier *id; - int *class1_check; - int *class2_check; - int result; - -/* Initialise */ - result = 0; - -/* Check inherited status */ - if( !astOK ) return result; - -/* Check pointer have been supplied. */ - if( class1 && class2 ) { - -/* Get pointers to the AstClassIdentifier that identifies the top-level - class of each vtab. */ - class1_id = class1->top_id; - class2_id = class2->top_id; - -/* Class membership is specified by the "check" value in each class - identifier. Get the check values for both vtabs. */ - class1_check = class1_id->check; - class2_check = class2_id->check; - -/* Try walking up the class heirarchy of "class1" until the class of - "class2" is reached. The top-level AstObject class has a NULL "parent" - pointer in its class identifier structure. */ - id = class1_id; - while( id && ( id->check != class2_check ) ) { - id = id->parent; - result++; - } - -/* If "class1" is not a subclass of "class2", try walking up the class - heirarchy of "class2" until the class of "class1" is reached. */ - if( !id ) { - result = 0; - id = class2_id; - while( id && ( id->check != class1_check ) ) { - id = id->parent; - result--; - } - -/* If "class2" is not a subclass of "class1", return AST__COUSIN. */ - if( !id ) result = AST__COUSIN; - } - } - -/* Return the generation gap. */ - return result; -} - -static void CleanAttribs( AstObject *this_object, int *status ) { -/* -*+ -* Name: -* astCleanAttribs - -* Purpose: -* Clear any invalid set attribute values. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* void astCleanAttribs( AstObject *this, int *status ) - -* Class Membership: -* Object method. - -* Description: -* This function clears any attributes that are currently set to -* invalid values in the supplied object. This can happen for instance -* when an object is cast into an instance of a parent class using -* astCast, since sub-classes can extend the range of valid values -* an attribute can take. - -* Parameters: -* this -* Pointer to the Object to be cleaned. -*- -*/ - -/* The base Object class has no attributes that need cleaning. */ - -} - -static void Clear( AstObject *this, const char *attrib, int *status ) { -/* -*++ -* Name: -c astClear -f AST_CLEAR - -* Purpose: -* Clear attribute values for an Object. - -* Type: -* Public virtual function. - -* Synopsis: -c #include "object.h" -c void astClear( AstObject *this, const char *attrib ) -f CALL AST_CLEAR( THIS, ATTRIB, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function clears the values of a specified set of attributes -f This routine clears the values of a specified set of attributes -* for an Object. Clearing an attribute cancels any value that has -* previously been explicitly set for it, so that the standard -* default attribute value will subsequently be used instead. This -c also causes the astTest function to return the value zero for -f also causes the AST_TEST function to return the value .FALSE. for -* the attribute, indicating that no value has been set. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object. -c attrib -f ATTRIB = CHARACTER * ( * ) (Given) -c Pointer to a null-terminated character string containing a -c comma-separated list of the names of the attributes to be cleared. -f A character string containing a comma-separated list of the -f names of the attributes to be cleared. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Notes: -* - Attribute names are not case sensitive and may be surrounded -* by white space. -* - It does no harm to clear an attribute whose value has not been -* set. -* - An error will result if an attempt is made to clear the value -* of a read-only attribute. -*-- -*/ - -/* Local Variables: */ - char *buff; /* Pointer to character buffer */ - char *name; /* Pointer to individual attribute name */ - char *name_end; /* Pointer to null at end of name */ - int i; /* Loop counter for characters */ - int j; /* Non-blank character count */ - int len; /* Length of attrib string */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain the length of the attrib string. */ - len = (int) strlen( attrib ); - if ( len != 0 ) { - -/* Allocate memory and store a copy of the string. */ - buff = astStore( NULL, attrib, (size_t) ( len + 1 ) ); - if ( astOK ) { - -/* Loop to process each element in the comma-separated list. */ - name = buff; - while ( name ) { - -/* Change the comma at the end of each element to a null to terminate - the name. */ - if ( ( name_end = strchr( name, ',' ) ) ) *name_end = '\0'; - -/* Remove white space and upper case characters from the attribute - name. */ - for ( i = j = 0; name[ i ]; i++ ) { - if ( !isspace( name[ i ] ) ) name[ j++ ] = tolower( name[ i ] ); - } - -/* Terminate the attribute name and pass it to astClearAttrib to clear - the attribute (unless it is all blank, in which case we ignore - it). */ - name[ j ] = '\0'; - if ( j ) astClearAttrib( this, name ); - -/* Check for errors and abort if any clear operation fails. Otherwise, - process the next attribute. */ - if ( !astOK ) break; - name = name_end ? name_end + 1 : NULL; - } - } - -/* Free the memory allocated for the string buffer. */ - buff = astFree( buff ); - } -} - -static void ClearAttrib( AstObject *this, const char *attrib, int *status ) { -/* -*+ -* Name: -* astClearAttrib - -* Purpose: -* Clear an attribute value for an Object. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* void astClearAttrib( AstObject *this, const char *attrib ) - -* Class Membership: -* Object method. - -* Description: -* This function clears the value of a specified attribute for an -* Object, so that the default value will subsequently be used. - -* Parameters: -* this -* Pointer to the Object. -* attrib -* Pointer to a null-terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. - -* Notes: -* - The Object class does not have any writable attributes, so -* this function merely reports an error. It is intended to be -* extended by other class definitions. -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Check the attribute name and clear the appropriate attribute. */ - -/* ID. */ -/* --- */ - if ( !strcmp( attrib, "id" ) ) { - astClearID( this ); - -/* Ident. */ -/* ------ */ - } else if ( !strcmp( attrib, "ident" ) ) { - astClearIdent( this ); - -/* UseDefs. */ -/* -------- */ - } else if ( !strcmp( attrib, "usedefs" ) ) { - astClearUseDefs( this ); - -/* Read-only attributes. */ -/* --------------------- */ -/* Test if the attribute string matches any of the read-only - attributes of this class. If it does, then report an error. */ - } else if ( !strcmp( attrib, "class" ) || - !strcmp( attrib, "nobject" ) || - !strcmp( attrib, "objsize" ) || - !strcmp( attrib, "refcount" ) ) { - astError( AST__NOWRT, "astClear: Invalid attempt to clear the \"%s\" " - "value for a %s.", status, attrib, astGetClass( this ) ); - astError( AST__NOWRT, "This is a read-only attribute." , status); - -/* Since no writable attributes are defined for the Object class, any - attempt to clear a value for anything else is also an error. */ - } else { - astError( AST__BADAT, "astClear: The attribute name \"%s\" is invalid " - "for a %s.", status, attrib, astGetClass( this ) ); - } -} - -AstObject *astClone_( AstObject *this, int *status ) { -/* -*++ -* Name: -c astClone -f AST_CLONE - -* Purpose: -* Clone (duplicate) an Object pointer. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c AstObject *astClone( AstObject *this ) -f RESULT = AST_CLONE( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a duplicate pointer to an existing -* Object. It also increments the Object's RefCount attribute to -* keep track of how many pointers have been issued. -* -* Note that this function is NOT equivalent to an assignment -* statement, as in general the two pointers will not have the same -* value. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Original pointer to the Object. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astClone() -f AST_CLONE = INTEGER -* A duplicate pointer to the same Object. - -* Applicability: -* Object -* This function applies to all Objects. - -* Notes: -* - A null Object pointer (AST__NULL) will be returned if this -c function is invoked with the AST error status set, or if it -f function is invoked with STATUS set to an error value, or if it -* should fail for any reason. -*-- -*/ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a lock on the object's secondary mutex. This mutex guards access - to the "ref_count" and "locker" components of the AstObject structure. */ - LOCK_SMUTEX(this); - -#ifdef MEM_DEBUG - { int rc; - char buf[100]; - rc = this->ref_count; - sprintf(buf,"cloned (refcnt: %d -> %d)", rc, rc+1 ); - astMemoryUse( this, buf ); - } -#endif - -/* Increment the Object's reference count. */ - this->ref_count++; - -/* Unlock the object's secondary mutex. */ - UNLOCK_SMUTEX(this); - -/* Return a new pointer to the Object. */ - return this; -} - -AstObject *astCopy_( const AstObject *this, int *status ) { -/* -*++ -* Name: -c astCopy -f AST_COPY - -* Purpose: -* Copy an Object. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c AstObject *astCopy( const AstObject *this ) -f RESULT = AST_COPY( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -* This function creates a copy of an Object and returns a pointer -* to the resulting new Object. It makes a "deep" copy, which -* contains no references to any other Object (i.e. if the original -* Object contains references to other Objects, then the actual -* data are copied, not simply the references). This means that -* modifications may safely be made to the copy without indirectly -* affecting any other Object. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object to be copied. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astCopy() -f AST_COPY = INTEGER -* Pointer to the new Object. - -* Applicability: -* Object -* This function applies to all Objects. - -* Notes: -* - A null Object pointer (AST__NULL) will be returned if this -c function is invoked with the AST error status set, or if it -f function is invoked with STATUS set to an error value, or if it -* should fail for any reason. -*-- -*/ - -/* Local Variables: */ - AstObject *new; /* Pointer to new object */ - AstObjectVtab *vtab; /* Pointer to object vtab */ - int i; /* Loop counter for copy constructors */ - -/* Initiallise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Re-use cached memory, or allocate new memory using the size of the input - object, to store the output Object. */ - - vtab = this->vtab; - if( object_caching ){ - - if( vtab->nfree > 0 ) { - new = vtab->free_list[ --(vtab->nfree) ]; - vtab->free_list[ vtab->nfree ] = NULL; - } else { - new = astMalloc( this->size ); - } - - } else { - new = astMalloc( this->size ); - } - - if ( astOK ) { - -/* Perform an initial byte-by-byte copy of the entire object - structure. */ - (void) memcpy( (void *) new, (const void *) this, this->size ); - -/* Initialise any components of the new Object structure that need to - differ from the input. */ - new->check = Magic( new, new->size, status ); - new->dynamic = 1; - new->ref_count = 1; - new->id = NULL; /* ID attribute is not copied (but Ident is copied) */ - new->proxy = NULL; - -/* Copy the persistent identifier string. */ - if( this->ident ) { - new->ident = astStore( NULL, this->ident, strlen( this->ident ) + 1 ); - } - -/* Create a new mutex for the new Object, and lock it for use by the - current thread. */ -#ifdef THREAD_SAFE - if( pthread_mutex_init( &(new->mutex1), NULL ) != 0 && astOK ) { - astError( AST__INTER, "astInitObject(%s): Failed to " - "initialise POSIX mutex1 for the new Object.", status, - vtab->class ); - } - if( pthread_mutex_init( &(new->mutex2), NULL ) != 0 && astOK ) { - astError( AST__INTER, "astInitObject(%s): Failed to " - "initialise POSIX mutex2 for the new Object.", status, - vtab->class ); - } - new->locker = -1; - new->globals = NULL; - (void) ManageLock( new, AST__LOCK, 0, NULL, status ); -#endif - -/* Loop to execute any copy constructors declared by derived classes. */ - for ( i = 0; i < vtab->ncopy; i++ ) { - -/* Invoke each copy constructor in turn. */ - (*vtab->copy[ i ])( this, new, status ); - -/* If any copy constructor fails, work backwards through the - corresponding destructor functions, invoking each in turn to undo - the copy operations that have been completed so far. */ - if ( !astOK ) { - for ( ; i >= 0; i-- ) { - (*vtab->delete[ i ])( new, status ); - } - -/* Zero the entire new Object structure (to prevent accidental re-use - of any of its values after deletion). */ - (void) memset( new, 0, new->size ); - -/* Free the Object's memory and ensure that a NULL pointer will be - returned. */ - new = astFree( new ); - -/* Quit trying to copy the Object. */ - break; - } - } - } - -/* If OK, increment the count of active objects. */ - if ( astOK ) vtab->nobject++; - -/* Return a pointer to the new Object. */ - return new; -} - -AstObject *astDelete_( AstObject *this, int *status ) { -/* -*++ -* Name: -c astDelete -f AST_DELETE - -* Purpose: -* Delete an Object. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c AstObject *astDelete( AstObject *this ) -f CALL AST_DELETE( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function deletes an Object, freeing all resources -f This routine deletes an Object, freeing all resources -* associated with it and rendering any remaining pointers to the -* Object invalid. -* -* Note that deletion is unconditional, regardless of whether other -* pointers to the Object are still in use (possibly within other -* Objects). A safer approach is to defer deletion, until all -c references to an Object have expired, by using astBegin/astEnd -c (together with astClone and astAnnul if necessary). -f references to an Object have expired, by using AST_BEGIN/AST_END -f (together with AST_CLONE and AST_ANNUL if necessary). - -* Parameters: -c this -c Pointer to the Object to be deleted. -f THIS = INTEGER (Given and Returned) -f Pointer to the Object to be deleted. A null pointer value -f (AST__NULL) is always returned. -f STATUS = INTEGER (Given and Returned) -f The global status. - -c Returned Value: -c astDelete() -c A null Object pointer (AST__NULL) is always returned. -c -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Notes: -c - This function attempts to execute even if the AST error status -c is set -f - This routine attempts to execute even if STATUS is set to an error -f value -* on entry, although no further error report will be -* made if it subsequently fails under these circumstances. -*-- -*/ - -/* Local Variables: */ - AstObjectVtab *vtab; /* Pointer to virtual function table */ - int dynamic; /* Was memory allocated dynamically? */ - int i; /* Loop counter for destructors */ - int ifree; /* Index of next slot on free list */ - int status_value; /* AST error status value */ - size_t size; /* Object size */ - -/* Check the pointer to ensure it identifies a valid Object (this - generates an error if it doesn't). */ - if ( !astIsAObject( this ) ) return NULL; - -/* Loop through all the destructors associated with the Object by derived - classes (working up the class hierarchy). */ - for ( i = this->vtab->ndelete - 1; i >= 0; i-- ) { - -/* Invoke each destructor in turn. Attempt to continue even if destructors - fail. */ - ( *this->vtab->delete[ i ] )( this, status ); - } - -/* Free the ID strings. */ - this->id = astFree( this->id ); - this->ident = astFree( this->ident ); - -/* Attempt to unlock the Object and destroy its mutexes. */ -#if defined(THREAD_SAFE) - (void) ManageLock( this, AST__UNLOCK, 0, NULL, status ); - pthread_mutex_destroy( &(this->mutex1) ); - pthread_mutex_destroy( &(this->mutex2) ); -#endif - -/* Save the virtual function table address and note if the Object's - memory was allocated dynamically. Also note its size. */ - vtab = this->vtab; - dynamic = this->dynamic; - size = this->size; - -/* Zero the entire Object structure (to prevent accidental re-use of - any of its values after deletion). */ - (void) memset( this, 0, size ); - -/* If necessary, free the Object's memory. If object caching is switched - on, the memory is not in fact freed; it is merely placed onto the end - of the list of free memory blocks included in the virtual function table - of the AST class concerned. astGrow returns immediately if an error - has already occurred, so we need to reset the error status explicitly - before calling astGrow. */ - if ( dynamic ) { - if( object_caching ) { - ifree = (vtab->nfree)++; - - status_value = astStatus; - astClearStatus; - vtab->free_list = astGrow( vtab->free_list, vtab->nfree, - sizeof(AstObject *) ); - astSetStatus( status_value ); - - if( vtab->free_list ) vtab->free_list[ ifree ] = this; - } else { - (void) astFree( this ); - } - } - -/* Decrement the count of active Objects. */ - vtab->nobject--; - -/* Always return NULL. */ - return NULL; -} - -static void Dump( AstObject *this, AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astDump - -* Purpose: -* Write an Object to a Channel. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* void astDump( AstObject *this, AstChannel *channel ) - -* Class Membership: -* Object method. - -* Description: -* This function writes an Object to a Channel, appending it to any -* previous Objects written to that Channel. - -* Parameters: -* this -* Pointer to the Object to be written. -* channel -* Pointer to the output Channel. -*- -*/ - -/* Local Variables: */ - AstObjectVtab *vtab; /* Pointer to virtual function table */ - const char *sval; /* Pointer to string value */ - int helpful; /* Helpful to show value even if not set? */ - int idump; /* Loop counter for dump functions */ - int ival; /* Attribute value */ - int set; /* Attribute value set? */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Write an initial "Begin" item, giving the class name of the Object - being written. Also supply a pointer to the comment associated with - the most recently-declared dump function in the Object's virtual - function table. This should describe the class to which the Object - belongs (assuming it has correctly declared its dump function). */ - astWriteBegin( channel, astGetClass( this ), - this->vtab->dump_comment[ this->vtab->ndump - 1 ] ); - -/* Write out instance variable information for the base Object - class. Accompany these with appropriate comment strings, possibly - depending on the values being written.*/ - -/* In the case of attributes, we first use the appropriate (private) - Test... member function to see if they are set. If so, we then use - the (private) Get... function to obtain the value to be written - out. - - For attributes which are not set, we use the astGet... method to - obtain the value instead. This will supply a default value - (possibly provided by a derived class which over-rides this method) - which is more useful to a human reader as it corresponds to the - actual default attribute value. Since "set" will be zero, these - values are for information only and will not be read back. */ - -/* ID. */ -/* --- */ - set = TestID( this, status ); - sval = set ? GetID( this, status ) : astGetID( this ); - -/* Don't show an un-set ID value if it is blank. */ - helpful = ( sval && *sval ); - astWriteString( channel, "ID", set, helpful, sval, - "Object identification string" ); - -/* Ident. */ -/* --- */ - set = TestIdent( this, status ); - sval = set ? GetIdent( this, status ) : astGetIdent( this ); - -/* Don't show an un-set Ident value if it is blank. */ - helpful = ( sval && *sval ); - astWriteString( channel, "Ident", set, helpful, sval, - "Permanent Object identification string" ); - -/* UseDefs */ -/* ------- */ - set = TestUseDefs( this, status ); - ival = set ? GetUseDefs( this, status ) : astGetUseDefs( this ); - astWriteInt( channel, "UseDfs", set, 0, ival, - ival ? "Default attribute values can be used" : - "Default values cannot be used" ); - -/* RefCnt. */ -/* ------- */ - LOCK_SMUTEX(this); - ival = this->ref_count; - UNLOCK_SMUTEX(this); - - astWriteInt( channel, "RefCnt", 0, 0, ival, - "Count of active Object pointers" ); - - -/* Nobj. */ -/* ----- */ - vtab = this->vtab; - astWriteInt( channel, "Nobj", 0, 0, vtab->nobject, - "Count of active Objects in same class" ); - -/* Terminate the information above with an "IsA" item for the base - Object class. */ - astWriteIsA( channel, "Object", "AST Object" ); - -/* Now loop to perform the same operation for each additional class - from which the Object inherits (the Object class itself does not - declare a dump function). Invoke the dump function for each class - in turn, working down the class hierarchy, to write out instance - variable information for that class. */ - for ( idump = 0; idump < this->vtab->ndump; idump++ ) { - ( *this->vtab->dump[ idump ] )( this, channel, status ); - -/* Terminate the output from all except the final dump function with - an appropriate "IsA" item describing the class whose data have just - been written. */ - if ( idump != ( this->vtab->ndump - 1 ) ) { - astWriteIsA( channel, this->vtab->dump_class[ idump ], - this->vtab->dump_comment[ idump ] ); - } - -/* Quit looping if an error occurs. */ - if ( !astOK ) break; - } - -/* Terminate the output from the final dump function with an "End" - item to match the initial "Begin" item. */ - astWriteEnd( channel, astGetClass( this ) ); -} - -static void EmptyObjectCache( int *status ){ -/* -* Name: -* EmptyObjectCache - -* Purpose: -* Free all memory blocks currently on the free list of any class. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* EmptyObjectCache( int *status ) - -* Class Membership: -* Object member function. - -* Description: -* This function empties the cache of Object memory by freeing all -* memory blocks on the free_list of all classes. - -* Parameters: -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function attempts to execute even if an error has occurred. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int iblock; /* Index of next entry in free list */ - int itab; /* Index of next virtual function table */ - AstObjectVtab *vtab; /* Pointer to next virtual function table */ - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Loop round all the virtual function tables which are known about. */ - for( itab = 0; itab < nvtab; itab++ ) { - vtab = known_vtabs[ itab ]; - -/* Free all memory blocks stored on the free list for this class. */ - for( iblock = 0; iblock < vtab->nfree; iblock++ ) { - (vtab->free_list)[ iblock ] = astFree( (vtab->free_list)[ iblock ] ); - } - -/* Free the memory used to hold the free list, and indicate it has zero - length. */ - vtab->free_list = astFree( vtab->free_list ); - vtab->nfree = 0; - } -} - -static void EnvSet( AstObject *this, int *status ) { -/* -*+ -* Name: -* astEnvSet - -* Purpose: -* Set default values for an Object's attributes. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* void astEnvSet( AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function assigns a set of attribute values for an Object, -* the attributes and their values being specified by means of an -* environment variable of the form "<CLASSNAME>_OPTIONS" that has -* a value of the form: -* -* "attribute1 = value1, attribute2 = value2, ... " -* -* Here, "attribute" specifies an attribute name and the value to -* the right of each "=" sign should be a suitable textual -* representation of the value to be assigned to that -* attribute. This will be interpreted according to the attribute's -* data type. - -* Parameters: -* this -* Pointer to the Object. - -* Notes: -* - See astVSet for details of how the setting strings are -* interpreted. -*- -*/ - -/* Local Variables: */ - char varname[ 100 ]; - const char *attrs = NULL; - const char *class = NULL; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get the string holding default attribute values for the class of the - supplied object. This string is held in the class virtual function - table. */ - attrs = this->vtab->defaults; - -/* If this is the first time the defaults have been requested, get the - list of defaults from the environment variable "<CLASSNAME>_OPTIONS" - and store in the virtual function table. */ - if( !attrs ) { - -/* Get the class name. */ - class = astGetClass( this ); - -/* Form the upper-case name of the environment variable. */ - if( class ) { - sprintf( varname, "%s_OPTIONS", class ); - astChrCase( NULL, varname, 1, sizeof( varname ) ); - -/* Get the value of the environment variable. */ - attrs = getenv( varname ); - -/* If no defaults were specified store the string "None". */ - if( ! attrs ) attrs = "None"; - -/* Store a copy in the virtual function table. */ - astBeginPM; - this->vtab->defaults = astStore( NULL, attrs, strlen( attrs ) + 1 ); - astEndPM; - } - } - -/* If any defaults were specified, set the corresponding attributes. */ - if( attrs && strcmp( attrs, "None" ) ) astSet( this, attrs, status ); - -} - -static int Equal( AstObject *this, AstObject *that, int *status ){ -/* -*+ -* Name: -* astEqual - -* Purpose: -* Check equality of two AST Objects. - -* Type: -* Public (but undocumented) function. - -* Synopsis: -* #include "object.h" -* int astEqual( AstObject *this, AstObject *this ) - -* Class Membership: -* Object virtual function. - -* Description: -* This function returns non-zero if the two pointers identify -* equivalent objects. - -* Parameters: -* this -* Pointer to the first Object. -* that -* Pointer to the second Object. - -* Returned Value: -* Non-zero if the objects are equivalent. - -* Notes: -* - This function is available in the public interface even though it is -* documented as protected. This is because it is difficult to document -* precisely which aspects of two Objects must be equal in order for this -* function to return a non-zero value. Each class of Object supplies -* its own Equal method that tests which-ever attributes the class -* considers to be significiant. -* - The implementation of this function provided by the base Object -* class simply compares the class names and the structure size. -* Sub-classes should override this method to provide more appropriate tests. -* - Zero is returned if an error has already occurred, or if -* this function should fail for any reason. - -*- -*/ - -/* Local Variables: */ - int result; - -/* Check inherited status */ - if( !astOK ) return 0; - -/* Objects are equivalent if they are the same object. */ - if( this == that ) { - result = 1; - -/* Otherwise, check the structure size and class names */ - } else { - result = ( this->size == that->size && - !strcmp( astGetClass( this ), astGetClass( that ) ) ); - } - - return result; -} - -static const char *Get( AstObject *this, const char *attrib, int *status ) { -/* -* Name: -* Get - -* Purpose: -* Get the value of a specified attribute for an Object. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* const char *Get( AstObject *this, const char *attrib, int *status ) - -* Class Membership: -* Object member function. - -* Description: -* This function returns a pointer to the value of a specified -* attribute for an Object, formatted as a character string. It is -* mainly a wrap-up used internally for invoking the astGetAttrib -* method. It converts the attribute name to lower case and removes -* white space before invoking the method. This saves derived -* classes that over-ride the astGetAttrib method from having to do -* this themselves. - -* Parameters: -* this -* Pointer to the Object. -* attrib -* Pointer to a null-terminated string containing the name of -* the attribute whose value is required. This may contain mixed -* case and white space, but should not be composed entirely of -* white space. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* - Pointer to a null-terminated string containing the attribute -* value. - -* Notes: -* - The returned string pointer may point at memory allocated -* within the Object, or at static memory. The contents of the -* string may be over-written or the pointer may become invalid -* following a further invocation of the same function or any -* modification of the Object. A copy of the string should -* therefore be made if necessary. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - char *buff; /* Pointer to local string buffer */ - const char *result; /* Pointer value to return */ - int i; /* Loop counter for characters */ - int j; /* Non-blank character count */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Allocate a local buffer long enough to hold the attribute name - string. */ - buff = astMalloc( strlen( attrib ) + (size_t) 1 ); - if ( astOK ) { - -/* Copy the attribute name characters into the buffer, omitting all - white space and converting to lower case. */ - for ( i = j = 0; attrib[ i ]; i++ ) { - if ( !isspace( attrib[ i ] ) ) buff[ j++ ] = tolower( attrib[ i ] ); - } - -/* Terminate the copied string. */ - buff[ j ] = '\0'; - -/* If no characters were copied, the attribute name was blank, so - report an error. */ - if ( !j ) { - if( astOK ) astError( AST__BADAT, "astGet(%s): A blank attribute " - "name was given.", status, astGetClass( this ) ); - -/* Of OK, invoke astGetAttrib to obtain a pointer to the attribute - value formatted as a character string. */ - } else { - result = astGetAttrib( this, buff ); - -/* If required, strip out graphical escape sequences. */ - if( !astEscapes( -1 ) ) result = astStripEscapes( result ); - } - } - -/* Free the local string buffer. */ - buff = astFree( buff ); - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = NULL; - -/* Return the result. */ - return result; -} - -static const char *GetAttrib( AstObject *this, const char *attrib, int *status ) { -/* -*+ -* Name: -* astGetAttrib - -* Purpose: -* Get the value of a specified attribute for an Object. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* const char *astGetAttrib( AstObject *this, const char *attrib ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a pointer to the value of a specified -* attribute for an Object, formatted as a character string. - -* Parameters: -* this -* Pointer to the Object. -* attrib -* Pointer to a null-terminated string containing the name of -* the attribute whose value is required. This name should be in -* lower case, with all white space removed. - -* Returned Value: -* - Pointer to a null-terminated string containing the attribute -* value. - -* Notes: -* - The returned string pointer may point at memory allocated -* within the Object, or at static memory. The contents of the -* string may be over-written or the pointer may become invalid -* following a further invocation of the same function or any -* modification of the Object. A copy of the string should -* therefore be made if necessary. -* - A NULL pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - const char *result; /* Pointer value to return */ - int nobject; /* Nobject attribute value */ - int objsize; /* ObjSize attribute value */ - int ref_count; /* RefCount attribute value */ - int usedefs; /* UseDefs attribute value */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(this); - -/* Compare "attrib" with each recognised attribute name in turn, - obtaining the value of the required attribute. If necessary, write - the value into "getattrib_buff" as a null-terminated string in an - appropriate format. Set "result" to point at the result string. */ - -/* Class. */ -/* ------ */ - if ( !strcmp( attrib, "class" ) ) { - result = astGetClass( this ); - -/* ID. */ -/* --- */ - } else if ( !strcmp( attrib, "id" ) ) { - result = astGetID( this ); - -/* Ident. */ -/* ------ */ - } else if ( !strcmp( attrib, "ident" ) ) { - result = astGetIdent( this ); - -/* UseDefs */ -/* ------- */ - } else if ( !strcmp( attrib, "usedefs" ) ) { - usedefs = astGetUseDefs( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", usedefs ); - result = getattrib_buff; - } - -/* Nobject. */ -/* -------- */ - } else if ( !strcmp( attrib, "nobject" ) ) { - nobject = astGetNobject( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", nobject ); - result = getattrib_buff; - } - -/* ObjSize */ -/* ------- */ - } else if ( !strcmp( attrib, "objsize" ) ) { - objsize = astGetObjSize( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", objsize ); - result = getattrib_buff; - } - -/* RefCount. */ -/* --------- */ - } else if ( !strcmp( attrib, "refcount" ) ) { - ref_count = astGetRefCount( this ); - if ( astOK ) { - (void) sprintf( getattrib_buff, "%d", ref_count ); - result = getattrib_buff; - } - -/* If the attribute name was not recognised, then report an error. */ - } else if( astOK ){ - astError( AST__BADAT, "astGet: The %s given does not have an attribute " - "called \"%s\".", status, astGetClass( this ), attrib ); - } - -/* Return the result. */ - return result; -} - -const char *astGetClass_( const AstObject *this, int *status ) { -/* -*+ -* Name: -* astGetClass - -* Purpose: -* Obtain the value of the Class attribute for an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* const char *astGetClass( const AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a pointer to the Class string for an -* Object. This contains the name of the class which created the -* Object. - -* Parameters: -* this -* Pointer to the Object. - -* Returned Value: -* Pointer to a string containing the class name. - -* Notes: -* - This function does not check the global error status before -* executing. This is to allow it to be used to obtain class names -* for inclusion in error messages. -* - A pointer to an explanatory string will be returned if this -* function is given a pointer which does not identify an Object. -*- -*/ - -/* Local Variables: */ - const char *name; /* Pointer to returned string */ - -/* First check if the Object pointer supplied is NULL, and set the - returned pointer accordingly. */ - if ( !this ) { - name = "<NULL>"; - -/* Also check if the supposed Object has the correct "magic number" in - its check field. If not, it is not an Object. */ - } else if ( this->check != Magic( this, this->size, status ) ) { - name = "<unknown>"; - -/* If OK, obtain a pointer to the class name from the Object's virtual - function table. */ - } else { - name = this->vtab->class; - } - -/* Return the result. */ - return name; -} - -int astGetNobject_( const AstObject *this, int *status ) { -/* -*+ -* Name: -* astGetNobject - -* Purpose: -* Obtain the value of the Nobject attribute for an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* int astGetNobject( const AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function returns the value of the Nobject attribute for an -* Object. This is a count of the number of active Objects in the -* same class as the Object supplied. This count does not include -* Objects in derived classes. - -* Parameters: -* this -* Pointer to the Object. - -* Returned Value: -* The number of active Objects. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Return the active object count. */ - return this->vtab->nobject; -} - -static int GetObjSize( AstObject *this, int *status ) { -/* -*+ -* Name: -* astGetObjSize - -* Purpose: -* Determine the in-memory size of the Object. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* int astGetObjSize( AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function returns the in-memory size of an Object. - -* Parameters: -* this -* Pointer to the Object. - -* Returned Value: -* The Object size, in bytes. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Return the object size. */ - return this->size; -} - -void *astGetProxy_( AstObject *this, int *status ) { -/* -*+ -* Name: -* astGetProxy - -* Purpose: -* Get a pointer to the foreign language proxy used to represent a -* given AST Object. - -* Type: -* Undocumented public function. - -* Synopsis: -* #include "object.h" -* void *astGetProxy( AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function returns any pointer stored previously in the AST -* Object using astSetProxy. If no such pointer has been stored, a -* NULL pointer is returned. - -* Parameters: -* this -* Pointer to the Object. - -* Returned Value: -* Pointer to the proxy object, or NULL. - -* Notes: -* - This function is public, but is currently undocumented since it -* is only of interest to people writing AST interfaces for other -* languages. -* - This function attempts to execute even if the AST error status -* is set on entry, although no further error report will be made -* if it subsequently fails under these circumstances. -*- -*/ - return this ? this->proxy : NULL; -} - -int astGetRefCount_( AstObject *this, int *status ) { -/* -*+ -* Name: -* astGetRefCount - -* Purpose: -* Obtain the value of the RefCount attribute for an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* int astGetRefCount( const AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function returns the value of the read-only RefCount -* attribute for an Object. This is a "reference count" of the -* number of active pointers to it, as accounted for by astClone -* and astAnnul (plus the pointer issued when it was created). If -* the reference count for an Object falls to zero when astAnnul is -* invoked, the object will be deleted. - -* Parameters: -* this -* Pointer to the Object. - -* Returned Value: -* The reference count. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables; */ - int result; /* Returned value */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Get a lock on the object's secondary mutex. This mutex guards access - to the "ref_count" and "locker" components of the AstObject structure. */ - LOCK_SMUTEX(this); - -/* Get the reference count. */ - result = this->ref_count; - -/* Unlock the object's secondary mutex. */ - UNLOCK_SMUTEX(this); - -/* Return the result. */ - return result; -} - -/* -*++ -* Name: -c astGet<X> -f AST_GET<X> - -* Purpose: -* Get an attribute value for an Object. - -* Type: -* Public functions. - -* Synopsis: -c #include "object.h" -c <X>type astGet<X>( AstObject *this, const char *attrib ) -f RESULT = AST_GET<X>( THIS, ATTRIB, STATUS ) - -* Class Membership: -* Object methods. - -* Description: -* This is a family of functions which return a specified attribute -* value for an Object using one of several different data -* types. The type is selected by replacing <X> in the function name -c by C, D, F, I or L, to obtain a result in const char* (i.e. string), -c double, float, int, or long format, respectively. -f by C, D, I, L or R, to obtain a result in Character, Double -f precision, Integer, Logical or Real format, respectively. -* -* If possible, the attribute value is converted to the type you -* request. If conversion is not possible, an error will result. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object. -c attrib -f ATTRIB = CHARACTER * ( * ) (Given) -c Pointer to a null-terminated string containing the name of -c the attribute whose value is required. -f A character string containing the name of the attribute whose -f value is required. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astGet<X>() -f AST_GET<X> = <X>type -c The attribute value, in the data type corresponding to <X> (or, -c in the case of astGetC, a pointer to a constant null-terminated -c character string containing this value). -f The attribute value, in the data type corresponding to <X>. - -* Applicability: -* Object -* These functions apply to all Objects. - -* Examples: -c printf( "RefCount = %d\n", astGetI( z, "RefCount" ) ); -c Prints the RefCount attribute value for Object "z" as an int. -c title = astGetC( axis, "Title" ); -c Obtains a pointer to a null-terminated character string containing -c the Title attribute of Object "axis". -f WRITE( *, '('' RefCount = '', A10 )' ) AST_GETC( Z, 'RefCount', STATUS ) -f Prints the RefCount attribute value for Object Z as a character -f string. -f NAXES = AST_GETI( FRAME, 'Naxes', STATUS ) -f Obtains the value of the Naxes attribute for Object FRAME as an -f integer. - -* Notes: -* - Attribute names are not case sensitive and may be surrounded -* by white space. -* - An appropriate "null" value will be returned if this function -c is invoked with the AST error status set, or if it should -f is invoked with STATUS set to an error value, or if it should -* fail for any reason. This null value is zero for numeric -c values and NULL for pointer values. -f values, .FALSE. for logical values, and blank for character values. -f - Numerical attribute values of zero translate to logical value -f .FALSE. and all other numerical values translate to .TRUE.. -c - The pointer returned by astGetC is guaranteed to remain valid -c and the string to which it points will not be over-written for a -c total of 50 successive invocations of this function. After this, -c the memory containing the string may be re-used, so a copy of -c the string should be made if it is needed for longer than this. -*-- -*/ - -/* Define a macro that expands to implement the astGetX_ member - functions required. The arguments to this macro are: - - code - The character that appears at the end of the function name. - type - The C type of the function return value. - format - A quoted string containing a astSscanf format specifier that - will read the attribute value into a variable of the required - data type. This format should transfer 1 astSscanf value. -*/ -#define MAKE_GETX(code,type,format) \ -type astGet##code##_( AstObject *this, const char *attrib, int *status ) { \ -\ -/* Local Variables: */ \ - const char *str; /* Pointer to string attribute value */ \ - int nc; /* Number of characters read from string */ \ - int nval; /* Number of values read from string */ \ - type result; /* Value to return */ \ - type value; /* Converted value */ \ -\ -/* Initialise. */ \ - result = (type) 0; \ -\ -/* Check the global error status. */ \ - if ( !astOK ) return result; \ -\ -/* Obtain the attribute value as a string. */ \ - str = Get( this, attrib, status ); \ - if ( astOK ) { \ -\ -/* Read the value from the string, ignoring surrounding white \ - space. */ \ - nc = 0; \ - nval = astSscanf( str, " " format " %n", &value, &nc ); \ -\ -/* Check that the number of values read was 1 and that all the \ - string's characters were consumed. If so, use the result. */ \ - if ( ( nval == 1 ) && ( nc >= (int) strlen( str ) ) ) { \ - result = value; \ -\ -/* If the read was unsuccessful, report an error. */ \ - } else if( astOK ) { \ - astError( AST__ATGER, "astGet" #code "(%s): The attribute " \ - "value \"%s=%s\" cannot be read using the requested data " \ - "type.", status,astGetClass( this ), attrib, str ); \ - } \ - } \ -\ -/* Return the result. */ \ - return result; \ -} - -/* Use this macro to create all the GetX_ private member functions, - except SetC (which is handled separately). */ -MAKE_GETX(D,double,"%lf") -MAKE_GETX(F,float,"%f") -MAKE_GETX(I,int,"%d") -MAKE_GETX(L,long,"%ld") - -/* Handle GetC separately because memory must be allocated to hold the - returned character values. */ -const char *astGetC_( AstObject *this, const char *attrib, int *status ) { - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - const char *result; /* Pointer value to return */ - const char *value; /* Pointer to attribute value */ - int i; /* Loop count */ - -/* Initialise. */ - result = NULL; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(this); - -/* If the "strings" array has not been initialised, fill it with - NULL pointers. */ - if ( !astgetc_init ) { - astgetc_init = 1; - for ( i = 0; i < AST__ASTGETC_MAX_STRINGS; i++ ) astgetc_strings[ i ] = NULL; - } - -/* Obtain a pointer to the required attribute value, formatted as a - character string. */ - value = Get( this, attrib, status ); - -/* Use a null string if a NULL pointer was returned by Get. */ - if( !value ) value = ""; - -/* If OK, store a copy of the resulting string in dynamically - allocated memory, putting a pointer to the copy into the next - element of the "astgetc_strings" array. (This process also de-allocates - any previously allocated memory pointed at by this "strings" - element, so the earlier string is effectively replaced by the new - one.) */ - if ( astOK ) { - - astBeginPM; - astgetc_strings[ astgetc_istr ] = astStore( astgetc_strings[ astgetc_istr ], - value, strlen( value ) + (size_t) 1 ); - astEndPM; - -/* If OK, return a pointer to the copy and increment "astgetc_istr" to use the - next element of "astgetc_strings" on the next invocation. Recycle - "astgetc_istr" to zero when all elements have been used. */ - if ( astOK ) { - result = astgetc_strings[ astgetc_istr++ ]; - if ( astgetc_istr == ( AST__ASTGETC_MAX_STRINGS - 1 ) ) astgetc_istr = 0; - } - } - -/* Return the result. */ - return result; - -} - -static int HasAttribute( AstObject *this, const char *attrib, int *status ) { -/* -*++ -* Name: -c astHasAttribute -f AST_HASATTRIBUTE - -* Purpose: -* Test if an Object has a named attribute. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c int astHasAttribute( AstObject *this, const char *attrib ) -f RESULT = AST_HASATTRIBUTE( THIS, ATTRIB, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function returns a boolean result (0 or 1) to indicate -f This function returns a logical result to indicate -* whether the supplied Object has an attribute with the supplied name. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the first Object. -c attrib -f ATTRIB = INTEGER (Given) -c Pointer to a string holding the -f The -* name of the attribute to be tested. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astHasAttribute() -c One if the Object has the named attribute, otherwise zero. -f AST_SAME = LOGICAL -f .TRUE. if the Object has the named attribute, otherwise -f .FALSE. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Notes: -c - A value of zero will be returned if this function is invoked -c with the AST error status set, or if it should fail for any reason. -f - A value of .FALSE. will be returned if this function is invoked -f with STATUS set to an error value, or if it should fail for any reason. -*-- -*/ - -/* Local Variables: */ - int oldrep; /* Original AST error reporting flag */ - int result; /* Returned value */ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Temporarily switch off error reporting. */ - oldrep = astReporting( 0 ); - -/* Attempt to get a value for the specified attribute. */ - (void) Get( this, attrib, status ); - -/* An error will have been reported if the object does not have the - requested attribute. Set the result and clear the error status. */ - if( !astOK ) { - result = 0; - astClearStatus; - } else { - result = 1; - } - -/* Re-instate the original error reporting flag. */ - (void) astReporting( oldrep ); - -/* Return the result. */ - return result; -} - -static unsigned long Magic( const AstObject *this, size_t size, int *status ) { -/* -* Name: -* Magic - -* Purpose: -* Generate a "magic number" for an Object. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* unsigned long Magic( const AstObject *this, size_t size, int *status ) - -* Class Membership: -* Object member function. - -* Description: -* This function generates a "magic number" which is a function of an Object -* pointer (address) and an Object size. This number may be stored in an -* Object to allow it to be recognised as a valid Object by other routines -* and to provide security against argument passing errors, etc. - -* Parameters: -* this -* Pointer to an Object. -* size -* The Object size. -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The magic number. - -* Notes: -* - This function does not perform any error checking. -*/ - -/* Form the bit-wise exclusive OR between the Object address and the Object - size, then add 2 and invert the bits. Return the result as an unsigned - long integer. */ - return ~( ( ( (unsigned long) this ) ^ ( (unsigned long) size ) ) + - ( (unsigned long) 2 ) ); -} - -#if defined(THREAD_SAFE) -static int ManageLock( AstObject *this, int mode, int extra, - AstObject **fail, int *status ) { -/* -*+ -* Name: -* astManageLock - -* Purpose: -* Manage the thread lock on an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* int astManageLock( AstObject *this, int mode, int extra, -* AstObject **fail ) - -* Class Membership: -* Object method. - -* Description: -* This function manages the thread lock on the supplied Object. The -* lock can be locked, unlocked or checked by this function as -* deteremined by parameter "mode". See astLock for details of the way -* these locks are used. - -* Parameters: -* this -* Pointer to the Object. -* mode -* An integer flag indicating what the function should do: -* -* AST__LOCK: Lock the Object for exclusive use by the calling -* thread. The "extra" value indicates what should be done if the -* Object is already locked (wait or report an error - see astLock). -* -* AST__UNLOCK: Unlock the Object for use by other threads. -* -* AST__CHECKLOCK: Check that the object is locked for use by the -* calling thread. -* extra -* Extra mode-specific information. -* fail -* If a non-zero function value is returned, a pointer to the -* Object that caused the failure is returned at "*fail". This may -* be "this" or it may be an Object contained within "this". Note, -* the Object's reference count is not incremented, and so the -* returned pointer should not be annulled. A NULL pointer is -* returned if this function returns a value of zero. - -* Returned Value: -* A status value: -* 0 - Success. -* 1 - Could not lock or unlock the object because it was already -* locked by another thread. -* 2 - Failed to lock a POSIX mutex -* 3 - Failed to unlock a POSIX mutex -* 4 - Bad "mode" value supplied. -* 5 - Check failed - object is locked by a different thread -* 6 - Check failed - object is unlocked -* - -* Notes: -* - This function attempts to execute even if an error has already -* occurred. - -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int result; /* Returned value */ - -/* Initialise */ - result = 0; - if( fail ) *fail = NULL; - -/* Check the supplied point is not NULL. */ - if( ! this ) return result; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Get a lock on the object's secondary mutex. This gives us exclusive - access to the "locker" (and "ref_count") component in the AstObject - structure. All other components in the structure are guarded by the - primary mutex (this->mutex1). */ - if( LOCK_SMUTEX(this) ) { - result = 2; - -/* If the secondary mutex was locked succesfully, first deal with cases - where the caller wants to lock the Object for exclusive use by the - calling thread. */ - } else if( mode == AST__LOCK ) { - -/* If the Object is not currently locked, lock the Object primary mutex - and record the identity of the calling thread in the Object. */ - if( this->locker == -1 ) { - if( LOCK_PMUTEX(this) ) result = 2; - this->locker = AST__THREAD_ID; - this->globals = AST__GLOBALS; - ChangeThreadVtab( this, status ); - -/* If the Object is already locked by the calling thread, do nothing. */ - } else if( this->locker == AST__THREAD_ID ) { - -/* If the object is locked by a different thread, and the caller is - willing to wait, attempt to lock the Object primary mutex. This will - cause the calling thread to block until the Object is release by the - thread that currently has it locked. Then store the identity of the - calling thread (the new lock owner). We first need to release the - secondary mutex so that the other thread can modify the "locker" - component in the AstObject structure when it releases the Object - (using this function). We then re-lock the secondary mutex so this - thread can change the "locker" component safely. */ - } else if( extra ) { - if( UNLOCK_SMUTEX(this) ) { - result = 3; - } else if( LOCK_PMUTEX(this) ) { - result = 2; - } else if( LOCK_SMUTEX(this) ) { - result = 2; - } - this->locker = AST__THREAD_ID; - this->globals = AST__GLOBALS; - ChangeThreadVtab( this, status ); - -/* If the caller does not want to wait until the Object is available, - return a status of 1. */ - } else { - result = 1; - } - -/* Unlock the Object for use by other threads. */ - } else if( mode == AST__UNLOCK ) { - -/* Do nothing if the Object is currently unlocked. */ - if( this->locker == -1 ) { - -/* If the object is currently locked by the calling thread, clear the - identity of the thread that owns the lock and unlock the primary - mutex. */ - } else if( this->locker == AST__THREAD_ID ) { - this->locker = -1; - this->globals = NULL; - if( UNLOCK_PMUTEX(this) ) result = 3; - -/* Return an error status value if the Object is locked by another - thread. */ - } else { - result = 1; - } - -/* Check the Object is locked by the calling thread. Return a status of 1 if - not. */ - } else if( mode == AST__CHECKLOCK ) { - if( this->locker == -1 ) { - result = 6; - } else if( this->locker != AST__THREAD_ID ) { - result = 5; - } - -/* Return a status of 4 for any other modes. */ - } else { - result = 4; - } - -/* Unlock the secondary mutex so that other threads can access the "locker" - component in the Object to see if it is locked. */ - if( UNLOCK_SMUTEX(this) ) result = 3; - -/* If the operation failed, return a pointer to the failed object. */ - if( result && fail ) *fail = this; - -/* Return the status value */ - return result; -} -#endif - -char *astToString_( AstObject *this, int *status ) { -/* -c++ -* Name: -* astToString - -* Purpose: -* Create an in-memory serialisation of an Object - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* char *astToString( AstObject *this ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a string holding a minimal textual -* serialisation of the supplied AST Object. The Object can re -* re-created from the serialisation using astFromString. - -* Parameters: -* this -* Pointer to the Object to be serialised. - -* Returned Value: -* astToString() -* Pointer to dynamically allocated memory holding the -* serialisation, or NULL if an error occurs. The pointer -* should be freed when no longer needed using astFree. - -c-- -*/ - -/* Local Variables: */ - StringData data; /* Data passed to the sink function */ - AstChannel *channel; /* Pointer to output Channel */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Create a Channel which will write to an expanding dynamically - allocated memory buffer. Set Channel attributes to exclude all - non-essential characters. */ - channel = astChannel( NULL, ToStringSink, "Comment=0,Full=-1,Indent=0", - status ); - -/* Initialise the data structure used to communicate with the sink - function, and store a pointer to it in the Channel. */ - data.ptr = NULL; - data.buff = NULL; - data.len = 0; - astPutChannelData( channel, &data ); - -/* Write the Object to the Channel. */ - astWrite( channel, this ); - -/* Annul the Channel pointer. */ - channel = astAnnul( channel ); - -/* Free the returned string if an error has occurred. */ - if( !astOK ) data.ptr = astFree( data.ptr ); - -/* Return the pointer. */ - return data.ptr; -} - -static void ToStringSink( const char *text ){ -/* -* Name: -* ToStringSink - -* Purpose: -* A Channel sink function for use by the astToString method. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* ToStringSink( const char *text ) - -* Class Membership: -* Object member function. - -* Description: -* This function appends the supplied line of text to the end of a -* dynamically growing memory block. - -* Parameters: -* text -* Pointer to the null-terminated line of text to be stored. - -*/ - -/* Local Variables: */ - StringData *data; /* Data passed to the sink function */ - int *status; /* Pointer to local status value */ - int status_value; /* Local status value */ - -/* Set up the local status */ - status_value = 0; - status = &status_value; - -/* Get a pointer to the structure holding the current memory pointer and - the length of the currently allocated memory. */ - data = astChannelData; - -/* Append the supplied text to the end of the string, and update the - string length. */ - data->ptr = astAppendString( data->ptr, &(data->len), text ); - -/* Append a newline character to the end of the string, and update the - string length. */ - data->ptr = astAppendString( data->ptr, &(data->len), "\n" ); -} - -void astSet_( void *this_void, const char *settings, int *status, ... ) { -/* -*++ -* Name: -c astSet -f AST_SET - -* Purpose: -* Set attribute values for an Object. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astSet( AstObject *this, const char *settings, ... ) -f CALL AST_SET( THIS, SETTINGS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function assigns a set of attribute values to an Object, -f This routine assigns a set of attribute values to an Object, -* over-riding any previous values. The attributes and their new -* values are specified via a character string, which should -* contain a comma-separated list of the form: -* -* "attribute_1 = value_1, attribute_2 = value_2, ... " -* -* where "attribute_n" specifies an attribute name, and the value -* to the right of each "=" sign should be a suitable textual -* representation of the value to be assigned. This value will be -* interpreted according to the attribute's data type. -c -c The string supplied may also contain "printf"-style format -c specifiers, identified by "%" signs in the usual way. If -c present, these will be substituted by values supplied as -c additional optional arguments (using the normal "printf" rules) -c before the string is used. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object. -c settings -f SETTINGS = CHARACTER * ( * ) (Given) -c Pointer to a null-terminated character string containing a -c comma-separated list of attribute settings in the form described -c above. -f A character string containing a comma-separated list of -f attribute settings in the form described above. -c ... -c Optional additional arguments which supply values to be -c substituted for any "printf"-style format specifiers that -c appear in the "settings" string. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Examples: -c astSet( map, "Report = 1, Zoom = 25.0" ); -c Sets the Report attribute for Object "map" to the value 1 and -c the Zoom attribute to 25.0. -c astSet( frame, "Label( %d ) =Offset along axis %d", axis, axis ); -c Sets the Label(axis) attribute for Object "frame" to a -c suitable string, where the axis number is obtained from -c "axis", a variable of type int. -c astSet( frame, "Title =%s", mystring ); -c Sets the Title attribute for Object "frame" to the contents of -c the string "mystring". -f CALL AST_SET( MAP, 'Report = 1, Zoom = 25.0', STATUS ) -f Sets the Report attribute for Object MAP to the value 1 and -f the Zoom attribute to 25.0. -f CALL AST_SET( FRAME, 'Label( 1 ) =Offset from cluster axis', STATUS ) -f Sets the Label(1) attribute for Object FRAME to a suitable -f string. - -* Notes: -* - Attribute names are not case sensitive and may be surrounded -* by white space. -* - White space may also surround attribute values, where it will -* generally be ignored (except for string-valued attributes where -* it is significant and forms part of the value to be assigned). -* - To include a literal comma in the value assigned to an attribute, -* the whole attribute value should be enclosed in quotation markes. -c Alternatively, you can use "%s" format and supply the value as a -c separate additional argument to astSet (or use the astSetC -c function instead). -c - The same procedure may be adopted if "%" signs are to be included -c and are not to be interpreted as format specifiers (alternatively, -c the "printf" convention of writing "%%" may be used). -* - An error will result if an attempt is made to set a value for -* a read-only attribute. -*-- - -* Implementation Notes: -* - Because this function has a variable argument list, it is -* invoked by a macro that evaluates to a function pointer (not a -* function invocation) and no checking or casting of arguments is -* performed before the function is invoked. Because of this, the -* Object identifier is of type (void *) and is converted and -* validated within the function itself. -* - This implementation of astSet is designed to be used within AST, -* and has an explicit status parameter. From outside AST, the astSet -* macro will invoke the astSetId_ function which does not have an -* status parameter. - -*-- -*/ - -/* Local Variables: */ - AstObject *this; /* Pointer to the Object structure */ - va_list args; /* Variable argument list */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain and validate a pointer to the Object structure. */ - this = astCheckObject( this_void ); - if ( astOK ) { - -/* Obtain the variable argument list and pass all arguments to the - astVSet method for interpretation. */ - va_start( args, status ); - astVSet( this, settings, NULL, args ); - va_end( args ); - } -} - -static void SetAttrib( AstObject *this, const char *setting, int *status ) { -/* -*+ -* Name: -* astSetAttrib - -* Purpose: -* Set an attribute value for an Object. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* void astSetAttrib( AstObject *this, const char *setting ) - -* Class Membership: -* Object method. - -* Description: -* This function assigns an attribute value for an Object, the attribute and -* its value being specified by means of a string of the form: -* -* "attribute= value " -* -* Here, "attribute" specifies the attribute name and should be in lower -* case with no white space present. The value to the right of the "=" -* should be a suitable textual representation of the value to be assigned -* and this will be interpreted according to the attribute's data type. -* White space surrounding the value is only significant for string -* attributes. - -* Parameters: -* this -* Pointer to the Object. -* setting -* Pointer to a null-terminated string specifying the new attribute -* value. - -* Notes: -* - The Object class does not have any writable attributes, so -* this function merely reports an error. It is intended to be -* extended by other class definitions. -*- -*/ - -/* Local Variables: */ - int id; /* Offset of ID string */ - int ival; /* Integer attribute value */ - int len; /* Length of setting string */ - int nc; /* Number of characters read by astSscanf */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain the length of the setting string. */ - len = (int) strlen( setting ); - -/* Test for each recognised attribute in turn, using "astSscanf" to parse - the setting string and extract the attribute value (or an offset to - it in the case of string values). In each case, use the value set - in "nc" to check that the entire string was matched. Once a value - has been obtained, use the appropriate method to set it. */ - -/* ID. */ -/* --- */ - if ( nc = 0, ( 0 == astSscanf( setting, "id=%n%*[^\n]%n", &id, &nc ) ) - && ( nc >= len ) ) { - astSetID( this, setting + id ); - -/* Ident. */ -/* ------ */ - } else if ( nc = 0, ( 0 == astSscanf( setting, "ident=%n%*[^\n]%n", &id, &nc ) ) - && ( nc >= len ) ) { - astSetIdent( this, setting + id ); - -/* UseDefs */ -/* ------- */ - } else if ( nc = 0, - ( 1 == astSscanf( setting, "usedefs= %d %n", &ival, &nc ) ) - && ( nc >= len ) ) { - astSetUseDefs( this, ival ); - -/* Define a macro to see if the setting string matches any of the - read-only attributes of this class and use this to report an error - if it does. */ -#define MATCH(attrib) \ - ( nc = 0, ( 0 == astSscanf( setting, attrib "=%*[^\n]%n", &nc ) ) && \ - ( nc >= len ) ) - - } else if ( MATCH( "class" ) || - MATCH( "nobject" ) || - MATCH( "objsize" ) || - MATCH( "refcount" ) ) { - astError( AST__NOWRT, "astSet: The setting \"%s\" is invalid for a %s.", status, - setting, astGetClass( this ) ); - astError( AST__NOWRT, "This is a read-only attribute." , status); - -/* Since no writable attributes are defined for the Object class, any - attempt to set a value for anything else is also an error. */ - } else { - astError( AST__BADAT, "astSet: The attribute setting \"%s\" is invalid " - "for a %s.", status, setting, astGetClass( this ) ); - } - -/* Undefine macros local to this function. */ -#undef MATCH -} - -void astSetCopy_( AstObjectVtab *vtab, - void (* copy)( const AstObject *, AstObject *, int * ), int *status ) { -/* -*+ -* Name: -* astSetCopy - -* Purpose: -* Declare a copy constructor for an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* void astSetCopy( AstObjectVtab *vtab, -* void (* copy)( const AstObject *, AstObject * ) ) - -* Class Membership: -* Object method. - -* Description: -* This function is provided so that class definitions can declare a copy -* constructor to be associated with an Object that is being constructed. -* When a copy is later performed on the Object, the copy constructor of -* each class to which the Object belongs will be invoked in turn (working -* down the class hierarchy). The copy constructor is passed pointers to the -* source and destination Objects. It should implement the copy and return -* void. - -* Parameters: -* vtab -* Pointer to the Object's virtual function table, in which the copy -* constructor's pointer is to be stored for future use. -* copy -* Pointer to the copy constructor function. - -* Notes: -* - When an Object is copied, a byte-by-byte copy of its structure is -* automatically made before any copy constructors are invoked. A copy -* constructor need only be provided if this does not suffice (e.g. if the -* structure contains pointers to other data). -* - If a copy constructor is declared for a class, then a -* destructor for that class must also be declared (using -* astSetDelete) so that there is a one-to-one correspondence -* between copy constructors and their associated destructors. -* - Copy constructors should check the global error status in the normal -* way and should set it (and report an error) if they fail. -*- -*/ - - -/* Check the global status. */ - if ( !astOK ) return; - -/* Indicate that subsequent memory allocations may never be freed (other - than by any AST exit handler). */ - astBeginPM; - -/* Expand the array of copy constructor pointers in the virtual function table - (if necessary) to accommodate the new one. */ - vtab->copy = astGrow( vtab->copy, vtab->ncopy + 1, - sizeof( void (*)( const AstObject *, AstObject * ) ) ); - -/* If OK, store the new function pointer and increment the count of copy - constructors. */ - if ( astOK ) { - vtab->copy[ vtab->ncopy++ ] = copy; - } - -/* Mark the end of the section in which memory allocations may never be freed - (other than by any AST exit handler). */ - astEndPM; - -} - -void astSetDelete_( AstObjectVtab *vtab, void (* delete)( AstObject *, int * ), int *status ) { -/* -*+ -* Name: -* astSetDelete - -* Purpose: -* Declare a destructor for an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* void astSetDelete( AstObjectVtab *vtab, void (* delete)( AstObject * ) ) - -* Class Membership: -* Object method. - -* Description: -* This function is provided so that class definitions can declare a -* destructor to be associated with an Object. When the Object is later -* deleted, the destructor declared by each class to which the Object -* belongs will be invoked in turn (working up the class hierarchy). The -* destructor is passed a pointer to the Object. It should free any -* resources (e.g. memory) associated with it and return void. It should -* not free the memory containing the Object itself. - -* Parameters: -* vtab -* Pointer to the Object's virtual function table, in which the -* destructor's pointer is to be stored for future use. -* delete -* Pointer to the destructor function. - -* Notes: -* - A destructor need not be declared for a class if there are no -* resources to free. -* - If a destructor is declared for a class, then a copy -* constructor for that class must also be declared (using -* astSetCopy) so that there is a one-to-one correspondence between -* copy constructors and their associated destructors. -* - A destructor function should generally attempt to execute even -* if the global error status is set on entry, but should not -* report further errors in that case (errors should be reported -* normally if status is not set on entry). -*- -*/ - - -/* Check the global status. */ - if ( !astOK ) return; - -/* Indicate that subsequent memory allocations may never be freed (other - than by any AST exit handler). */ - astBeginPM; - -/* Expand the array of destructor pointers in the virtual function table (if - necessary) to accommodate the new one. */ - vtab->delete = astGrow( vtab->delete, vtab->ndelete + 1, - sizeof( void (*)( AstObject * ) ) ); - -/* If OK, store the new function pointer and increment the count of - destructors. */ - if ( astOK ) { - vtab->delete[ vtab->ndelete++ ] = delete; - } - -/* Mark the end of the section in which memory allocations may never be freed - (other than by any AST exit handler). */ - astEndPM; - -} - -void astSetDump_( AstObjectVtab *vtab, - void (* dump)( AstObject *, AstChannel *, int * ), - const char *class, const char *comment, int *status ) { -/* -*+ -* Name: -* astSetDump - -* Purpose: -* Declare a dump function for an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* void astSetDump( AstObjectVtab *vtab, -* void (* dump)( AstObject *, AstChannel * ), -* const char *class, const char *comment ) - -* Class Membership: -* Object method. - -* Description: -* This function is provided so that class definitions can declare -* a dump function to be associated with an Object that is being -* constructed. When the astWrite (or astShow or astToString) method -* is later used to write the Object to a Channel, the dump function -* of each class to which the Object belongs will be invoked in turn -* (working down the class hierarchy). The dump function is passed -* pointers to the Object and the output Channel. It should write -* out any internal values (e.g. instance variables) for its class -* that are to be kept (using the protected astWrite... methods of -* the Channel) and return void. - -* Parameters: -* vtab -* Pointer to the Object's virtual function table, in which the -* dump function's pointer is to be stored for future use. -* dump -* Pointer to the dump function. -* class -* Pointer to a constant null-terminated string (residing in -* static memory) containing the name of the class that is -* declaring the dump function. -* comment -* Pointer to a constant null-terminated string (residing in -* static memory) containing a comment to associate with the -* dump function. This should normally describe the purpose of -* the class that is declaring the dump function. - -* Notes: -* - Dump functions should check the global error status in the -* normal way and should set it (and report an error) if they fail. -*- -*/ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Indicate that subsequent memory allocations may never be freed (other - than by any AST exit handler). */ - astBeginPM; - -/* Expand the arrays of pointers to dump functions and related data in - the virtual function table (if necessary) to accommodate the new - one. */ - vtab->dump = astGrow( vtab->dump, vtab->ndump + 1, - sizeof( void (*)( AstObject *, AstChannel * ) ) ); - vtab->dump_class = astGrow( vtab->dump_class, vtab->ndump + 1, - sizeof( char * ) ); - vtab->dump_comment = astGrow( vtab->dump_comment, vtab->ndump + 1, - sizeof( char * ) ); - -/* If OK, store the new pointers (to the dump function, class name and - comment) and increment the count of dump functions. */ - if ( astOK ) { - vtab->dump[ vtab->ndump ] = dump; - vtab->dump_class[ vtab->ndump ] = class; - vtab->dump_comment[ vtab->ndump ] = comment; - vtab->ndump++; - } - -/* Mark the end of the section in which memory allocations may never be - freed (other than by any AST exit handler). */ - astEndPM; -} - -void astSetProxy_( AstObject *this, void *proxy, int *status ) { -/* -*+ -* Name: -* astSetProxy - -* Purpose: -* Store a pointer to the foreign language proxy used to represent a -* given AST Object. - -* Type: -* Undocumented public function. - -* Synopsis: -* #include "object.h" -* void astSetProxy( AstObject *this, void *proxy ) - -* Class Membership: -* Object method. - -* Description: -* This function stores the supplied pointer in the AST Object so that -* it can be retrieved later using astGetProxy. -* -* The supplied pointer should point to a structure that is used -* to represent the AST Object within some external system. It is -* expected that the external system will check each object reference -* returned by AST to see if it has an associated proxy object. If not -* (i.e. if astGetProxy returns NULL), a new external object will be -* created to represent the AST Object, and a pointer to it will be -* stored in the AST Object using astSetProxy. If the AST Object -* already has a proxy, the AST reference is annulled and the existing -* proxy object is used by the external system. - -* Parameters: -* this -* Pointer to the Object. -* proxy -* Pointer to the proxy object, or NULL. - -* Notes: -* - The suppied pointer is not used within AST itself, other than to -* be returned by the astGetProxy method. -* - This function is public, but is currently undocumented since it -* is only of interest to people writing AST interfaces for other -* languages. -*- -*/ - if( !astOK ) return; - this->proxy = proxy; -} - -void astSetVtab_( AstObject *this, AstObjectVtab *vtab, int *status ) { -/* -*+ -* Name: -* astSetVtab - -* Purpose: -* Change the virtual function table associated with an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* void astSetVtab( AstObject *this, AstObjectVtab *vtab ) - -* Class Membership: -* Object method. - -* Description: -* This function changes the virtual function table associated with an -* Object. This may be needed, for instance, if a super-class -* initialises a parent class structure with a NULL vtab, causing the -* vtab of the parent class to be used instead of the super-class. -* Whilst the super-class object is being constructed its inherited methods -* will be determined by the parent class. Once the super-class object -* has been constructed, it can invoke this fuction in order to -* set the vtab to the super-class vtab, thus causing the method -* implementations provided by the super-cvlass to be used. - -* Parameters: -* this -* Pointer to the Object to be modified. -* vtab -* Pointer to the virtual function table to store in the Object. -*- -*/ - if( this ) this->vtab = vtab; -} - -static int Same( AstObject *this, AstObject *that, int *status ) { -/* -*++ -* Name: -c astSame -f AST_SAME - -* Purpose: -* Test if two AST pointers refer to the same Object. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c int astSame( AstObject *this, AstObject *that ) -f RESULT = AST_SAME( THIS, THAT, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function returns a boolean result (0 or 1) to indicate -f This function returns a logical result to indicate -* whether two pointers refer to the same Object. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the first Object. -c that -f THAT = INTEGER (Given) -* Pointer to the second Object. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astSame() -c One if the two pointers refer to the same Object, otherwise zero. -f AST_SAME = LOGICAL -f .TRUE. if the two pointers refer to the same Object, otherwise -f .FALSE. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Notes: -* - Two independent Objects that happen to be identical are not -* considered to be the same Object by this function. -c - A value of zero will be returned if this function is invoked -c with the AST error status set, or if it should fail for any reason. -f - A value of .FALSE. will be returned if this function is invoked -f with STATUS set to an error value, or if it should fail for any reason. -*-- -*/ - -/* Check the global error status. */ - if ( !astOK ) return 0; - -/* Return the result. */ - return ( this == that ) ? 1 : 0; -} - -/* -*++ -* Name: -c astSet<X> -f AST_SET<X> - -* Purpose: -* Set an attribute value for an Object. - -* Type: -* Public functions. - -* Synopsis: -c #include "object.h" -c void astSet<X>( AstObject *this, const char *attrib, <X>type value ) -f CALL AST_SET<X>( THIS, ATTRIB, VALUE, STATUS ) - -* Class Membership: -* Object methods. - -* Description: -c This is a family of functions which set a specified attribute -f This is a family of routines which set a specified attribute -* value for an Object using one of several different data -c types. The type is selected by replacing <X> in the function name -f types. The type is selected by replacing <X> in the routine name -c by C, D, F, I or L, to supply a value in const char* (i.e. string), -c double, float, int, or long format, respectively. -f by C, D, I, L or R, to supply a value in Character, Double -f precision, Integer, Logical or Real format, respectively. -* -* If possible, the value you supply is converted to the type of -* the attribute. If conversion is not possible, an error will -* result. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object. -c attrib -f ATTRIB = CHARACTER * ( * ) (Given) -c Pointer to a null-terminated character string containing the -c name of the attribute whose value is to be set. -f A character string containing the name of the attribute whose -f value is to be set. -c value -f VALUE = <X>type (Given) -c The value to be set for the attribute, in the data type corresponding -c to <X> (or, in the case of astSetC, a pointer to a null-terminated -c character string containing this value). -f The value to be set for the attribute, in the data type corresponding -f to <X>. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c These functions apply to all Objects. -f These routines apply to all Objects. - -* Examples: -c astSetI( frame, "Preserve", 1 ); -c Sets the Preserve attribute value for Object "frame" to 1. -c astSetC( plot, "Format(1)", "%.2g" ); -c Sets the Format(1) attribute value for Object "plot" to the -c character string "%.2g". -f CALL AST_SETC( PLOT, 'Title', CVALUE, STATUS ) -f Sets the Title attribute value for Object PLOT to the contents -f of the character variable CVALUE. -f CALL AST_SETL( FRAME, 'Preserve', .TRUE., STATUS ); -f Sets the Preserve attribute value for Object FRAME to 1 (true). - -* Notes: -* - Attribute names are not case sensitive and may be surrounded -* by white space. -f - The logical value .FALSE. will translate to a numerical attribute -f value of zero and logical .TRUE. will translate to one. -* - An error will result if an attempt is made to set a value for -* a read-only attribute. -*-- -*/ - -/* Define a macro that expands to implement the astSetX_ member - functions required. The arguments to this macro are: - - code - The character that appears at the end of the function name. - type - The C type of the function "value" parameter. - format - A quoted string containing a sprintf format specifier that will - format the supplied value as a character string. This format should - consume 2 sprintf arguments: a field width and the value to be - formatted. - fmtlen - The number of characters in the format specifier (above). - fieldsz - The value of the field width to be used by the format specifier. -*/ -#define MAKE_SETX(code,type,format,fmtlen,fieldsz) \ -void astSet##code##_( AstObject *this, const char *attrib, type value, int *status ) { \ -\ -/* Local Variables: */ \ - char *setting; /* Pointer to attribute setting string */ \ - int len; /* Length of attribute name */ \ -\ -/* Check the global status. */ \ - if ( !astOK ) return; \ -\ -/* Obtain the length of the attribute name and allocate memory to hold \ - this name plus the format specifier to be appended to it. */ \ - len = (int) astChrLen( attrib ); \ - setting = astMalloc( (size_t) ( len + fmtlen + 2 ) ); \ -\ -/* Make a copy of the attribute name in the allocated memory. */ \ - if ( astOK ) { \ - (void) memcpy( setting, attrib, (size_t) len ); \ - setting[ len ] = 0; \ -\ -/* Append "=", followed by the format specifier, to construct a \ - suitable "setting" string for use by astSet. */ \ - (void) strcat( setting, "=" format ); \ -\ -/* Invoke astSet to set the attribute value. */ \ - astSet( this, setting, status, fieldsz, value ); \ - } \ -\ -/* Free the allocated memory. */ \ - setting = astFree( setting ); \ -} - -/* Use this macro to create all the SetX_ private member functions. */ -MAKE_SETX(D,double,"%.*g",4,AST__DBL_DIG) -MAKE_SETX(F,float,"%.*g",4,FLT_DIG) -MAKE_SETX(I,int,"%.*d",4,1) -MAKE_SETX(L,long,"%.*ld",5,1) - - -/* The astSetC_ function is implemented separately so that commas can be - handled. Since astSetC can only be used to set a single attribute - value, we know that any commas in the supplied value are included - within the attribuite value, rather than being used as delimiters - between adjacent attribute settings. To avoid VSet using them as - delimiters, they are replaced here by '\r' before calling astSet, and - VSet then converts them back to commas. */ - -void astSetC_( AstObject *this, const char *attrib, const char *value, int *status ) { - -/* Local Variables: */ - char *d; /* Pointer to next setting character */ - char *newv; /* Pointer to new attribute value string */ - char *setting; /* Pointer to attribute setting string */ - const char *c; /* Pointer to next value character */ - int len; /* Length of attribute name */ - -/* Check the global status. */ - if ( !astOK ) return; - -/* Produce a copy of the supplied attribute value in which any commas - are replaced by carriage returns ("\r"). */ - newv = astMalloc( (size_t)( strlen( value ) + 1 ) ); - if( newv ) { - d = newv; - c = value; - while( *c ) { - if( *c == ',' ) { - *d = '\r'; - } else { - *d = *c; - } - c++; - d++; - } - *d = 0; - -/* Obtain the length of the attribute name and allocate memory to hold - this name plus the format specifier to be appended to it. */ - len = (int) astChrLen( attrib ); - setting = astMalloc( (size_t) ( len + 5 ) ); - -/* Make a copy of the attribute name in the allocated memory. */ - if ( astOK ) { - (void) memcpy( setting, attrib, (size_t) len ); - setting[ len ] = 0; - -/* Append "=", followed by the format specifier, to construct a - suitable "setting" string for use by astSet. */ - (void) strcat( setting, "=%*s" ); - -/* Invoke astSet to set the attribute value. */ - astSet( this, setting, status, 0, newv ); - } - -/* Free the allocated memory. */ - setting = astFree( setting ); - } - newv = astFree( newv ); -} - -static void Show( AstObject *this, int *status ) { -/* -*++ -* Name: -c astShow -f AST_SHOW - -* Purpose: -* Display a textual representation of an Object on standard output. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astShow( AstObject *this ) -f CALL AST_SHOW( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function displays a textual description of any AST Object -f This routine displays a textual description of any AST Object -* on standard output. It is provided primarily as an aid to -* debugging. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object to be displayed. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. -*-- -*/ - -/* Local Variables: */ - AstChannel *channel; /* Pointer to output Channel */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Create a Channel which will write to standard output. */ - channel = astChannel( NULL, NULL, "", status ); - -/* Write the Object to the Channel. */ - astWrite( channel, this ); - -/* Annul the Channel pointer. */ - channel = astAnnul( channel ); -} - -int astTest_( AstObject *this, const char *attrib, int *status ) { -/* -*++ -* Name: -c astTest -f AST_TEST - -* Purpose: -* Test if an Object attribute value is set. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c int astTest( AstObject *this, const char *attrib ) -f RESULT = AST_TEST( THIS, ATTRIB, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function returns a boolean result (0 or 1) to indicate -f This function returns a logical result to indicate -* whether a value has been explicitly set for one of an Object's -* attributes. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object. -c attrib -f ATTRIB = CHARACTER * ( * ) (Given) -c Pointer to a null-terminated character string containing -c the name of the attribute to be tested. -f A character string containing the name of the attribute to be -f tested. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astTest() -c One if a value has previously been explicitly set for the attribute -c (and hasn't been cleared), otherwise zero. -f AST_TEST = LOGICAL -f .TRUE. if a value has previously been explicitly set for the -f attribute (and hasn't been cleared), otherwise .FALSE.. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Notes: -* - Attribute names are not case sensitive and may be surrounded -* by white space. -c - A value of zero will be returned if this function is invoked -f - A value of .FALSE. will be returned if this function is invoked -c with the AST error status set, or if it should fail for any reason. -f with STATUS set to an error value, or if it should fail for any reason. -c - A value of zero will also be returned if this function is used -f - A value of .FALSE. will also be returned if this function is used -* to test a read-only attribute, although no error will result. -*-- -*/ - -/* Local Variables: */ - char *buff; /* Pointer to character buffer */ - int i; /* Loop counter for characters */ - int j; /* Non-blank character count */ - int len; /* Length of attrib string */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Obtain the length of the attrib string. */ - len = (int) strlen( attrib ); - -/* Allocate memory and store a copy of the string. */ - buff = astStore( NULL, attrib, (size_t) ( len + 1 ) ); - if ( astOK ) { - -/* Remove white space and upper case characters. */ - for ( i = j = 0; buff[ i ]; i++ ) { - if ( !isspace( buff[ i ] ) ) buff[ j++ ] = tolower( buff[ i ] ); - } - -/* Terminate the attribute name and pass it to astTestAttrib to test - the attribute. */ - buff[ j ] = '\0'; - result = astTestAttrib( this, buff ); - } - -/* Free the memory allocated for the string buffer. */ - buff = astFree( buff ); - -/* If an error occurred, clear the result value. */ - if ( !astOK ) result = 0; - -/* Return the result. */ - return result; -} - -static int TestAttrib( AstObject *this, const char *attrib, int *status ) { -/* -*+ -* Name: -* astTestAttrib - -* Purpose: -* Test if a specified attribute value is set for an Object. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* int astTestAttrib( AstObject *this, const char *attrib ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a boolean result (0 or 1) to indicate whether -* a value has been set for one of an Object's attributes. - -* Parameters: -* this -* Pointer to the Object. -* attrib -* Pointer to a null-terminated string specifying the attribute -* name. This should be in lower case with no surrounding white -* space. - -* Returned Value: -* One if a value has been set, otherwise zero. - -* Notes: -* - A value of zero will be returned if this function is invoked -* with the global status set, or if it should fail for any reason. -*- -*/ - -/* Local Variables: */ - int result; /* Result value to return */ - -/* Initialise. */ - result = 0; - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Check the attribute name and test the appropriate attribute. */ - -/* ID. */ -/* --- */ - if ( !strcmp( attrib, "id" ) ) { - result = astTestID( this ); - -/* Ident. */ -/* ------ */ - } else if ( !strcmp( attrib, "ident" ) ) { - result = astTestIdent( this ); - -/* UseDefs */ -/* ------- */ - } else if ( !strcmp( attrib, "usedefs" ) ) { - result = astTestUseDefs( this ); - -/* Test if the attribute string matches any of the read-only - attributes of this class. If it does, then return zero. */ - } else if ( !strcmp( attrib, "class" ) || - !strcmp( attrib, "nobject" ) || - !strcmp( attrib, "objsize" ) || - !strcmp( attrib, "refcount" ) ) { - result = 0; - -/* Any attempt to test any other attribute is an error. */ - } else if( astOK ){ - astError( AST__BADAT, "astTest: The attribute name \"%s\" is invalid " - "for a %s.", status, attrib, astGetClass( this ) ); - } - -/* Return the result, */ - return result; -} - -int astTune_( const char *name, int value, int *status ) { -/* -*++ -* Name: -c astTune -f AST_TUNE - -* Purpose: -* Set or get an integer-valued AST global tuning parameter. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c int astTune( const char *name, int value ) -f RESULT = AST_TUNE( NAME, VALUE, STATUS ) - -* Class Membership: -* Object function. - -* Description: -* This function returns the current value of an integer-valued AST -* global tuning parameter, optionally storing a new value for the -* parameter. For character-valued tuning parameters, see -c astTuneC. -f AST_TUNEC. - -* Parameters: -c name -f NAME = CHARACTER * ( * ) (Given) -* The name of the tuning parameter (case-insensitive). -c value -f VALUE = INTEGER (Given) -* The new value for the tuning parameter. If this is AST__TUNULL, -* the existing current value will be retained. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astTune() -f AST_TUNE = INTEGER -c The original value of the tuning parameter. A default value will -* be returned if no value has been set for the parameter. - -* Tuning Parameters: -* ObjectCaching -* A boolean flag which indicates what should happen -* to the memory occupied by an AST Object when the Object is deleted -* (i.e. when its reference count falls to zero or it is deleted using -c astDelete). -f AST_DELETE). -* If this is zero, the memory is simply freed using the systems "free" -* function. If it is non-zero, the memory is not freed. Instead a -* pointer to it is stored in a pool of such pointers, all of which -* refer to allocated but currently unused blocks of memory. This allows -* AST to speed up subsequent Object creation by re-using previously -* allocated memory blocks rather than allocating new memory using the -* systems malloc function. The default value for this parameter is -* zero. Setting it to a non-zero value will result in Object memory -* being cached in future. Setting it back to zero causes any memory -* blocks currently in the pool to be freed. Note, this tuning parameter -* only controls the caching of memory used to store AST Objects. To -* cache other memory blocks allocated by AST, use MemoryCaching. -* MemoryCaching -* A boolean flag similar to ObjectCaching except -* that it controls caching of all memory blocks of less than 300 bytes -* allocated by AST (whether for internal or external use), not just -* memory used to store AST Objects. - -* Notes: -c - This function attempts to execute even if the AST error -c status is set -f - This routine attempts to execute even if STATUS is set to an -f error value -* on entry, although no further error report will be -* made if it subsequently fails under these circumstances. -* - All threads in a process share the same AST tuning parameters -* values. -*-- -*/ - - int result = AST__TUNULL; - - if( name ) { - - LOCK_MUTEX1; - - if( astChrMatch( name, "ObjectCaching" ) ) { - result = object_caching; - if( value != AST__TUNULL ) { - object_caching = value; - if( !object_caching ) EmptyObjectCache( status ); - } - - } else if( astChrMatch( name, "MemoryCaching" ) ) { - result = astMemCaching( value ); - - } else if( astOK ) { - astError( AST__TUNAM, "astTune: Unknown AST tuning parameter " - "specified \"%s\".", status, name ); - } - - UNLOCK_MUTEX1; - - } - - return result; -} - -void astTuneC_( const char *name, const char *value, char *buff, - int bufflen, int *status ) { -/* -*++ -* Name: -c astTuneC -f AST_TUNEC - -* Purpose: -* Set or get a character-valued AST global tuning parameter. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astTuneC( const char *name, const char *value, char *buff, -c int bufflen ) -f CALL AST_TUNEC( NAME, VALUE, BUFF, STATUS ) - -* Class Membership: -* Object function. - -* Description: -* This function returns the current value of a character-valued -* AST global tuning parameter, optionally storing a new value -* for the parameter. For integer-valued tuning parameters, see -c astTune. -f AST_TUNE. - -* Parameters: -c name -f NAME = CHARACTER * ( * ) (Given) -* The name of the tuning parameter (case-insensitive). -c value -f VALUE = CHARACTER * ( ) (Given) -* The new value for the tuning parameter. If this is -f AST__TUNULLC, -c NULL, -* the existing current value will be retained. -c buff -f BUFF = CHARACTER * ( ) (Given) -* A character string in which to return the original value of -* the tuning parameter. An error will be reported if the buffer -* is too small to hold the value. -c NULL may be supplied if the old value is not required. -c bufflen -c The size of the supplied "buff" array. Ignored if "buff" is NULL. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Tuning Parameters: -* HRDel -* A string to be drawn following the hours field in a formatted -* sky axis value when "g" format is in use (see the Format -* attribute). This string may include escape sequences to produce -* super-scripts, etc. (see the Escapes attribute for details -* of the escape sequences allowed). The default value is -* "%-%^50+%s70+h%+" which produces a super-script "h". -* MNDel -* A string to be drawn following the minutes field in a formatted -* sky axis value when "g" format is in use. The default value is -* "%-%^50+%s70+m%+" which produces a super-script "m". -* SCDel -* A string to be drawn following the seconds field in a formatted -* sky axis value when "g" format is in use. The default value is -* "%-%^50+%s70+s%+" which produces a super-script "s". -* DGDel -* A string to be drawn following the degrees field in a formatted -* sky axis value when "g" format is in use. The default value is -* "%-%^53+%s60+o%+" which produces a super-script "o". -* AMDel -* A string to be drawn following the arc-minutes field in a formatted -* sky axis value when "g" format is in use. The default value is -* "%-%^20+%s85+'%+" which produces a super-script "'" (single quote). -* ASDel -* A string to be drawn following the arc-seconds field in a formatted -* sky axis value when "g" format is in use. The default value is -* "%-%^20+%s85+\"%+" which produces a super-script """ (double quote). -* EXDel -* A string to be drawn to introduce the exponent in a value when "g" -* format is in use. The default value is "10%-%^50+%s70+" which -* produces "10" followed by the exponent as a super-script. - -* Notes: -c - This function attempts to execute even if the AST error -c status is set -f - This routine attempts to execute even if STATUS is set to an -f error value -* on entry, although no further error report will be -* made if it subsequently fails under these circumstances. -* - All threads in a process share the same AST tuning parameters -* values. -*-- -*/ - -/* Local Variables: */ - char *p = NULL; - int len; - -/* Check the name of a tuning parameter was supplied. */ - if( name ) { - -/* Serialise access to the tuning parameters since they are common to all - threads. */ - LOCK_MUTEX1; - -/* Get a pointer to the buffer that holds the value of the requested - tuning parameter. */ - if( astChrMatch( name, "hrdel" ) ) { - p = hrdel; - } else if( astChrMatch( name, "mndel" ) ) { - p = mndel; - } else if( astChrMatch( name, "scdel" ) ) { - p = scdel; - } else if( astChrMatch( name, "dgdel" ) ) { - p = dgdel; - } else if( astChrMatch( name, "amdel" ) ) { - p = amdel; - } else if( astChrMatch( name, "asdel" ) ) { - p = asdel; - } else if( astChrMatch( name, "exdel" ) ) { - p = exdel; - -/* Report an error if an the tuning parameter name is unknown. */ - } else if( astOK ) { - p = NULL; - astError( AST__TUNAM, "astTuneC: Unknown AST tuning parameter " - "specified \"%s\".", status, name ); - } - -/* If the existing value was found. */ - if( p ) { - -/* And is to be returned in the supplied buffer... */ - if( buff ) { - -/* Check that the buffer is long enough. If so, copy the current value - into the buffer, otherwise report an error. */ - len = strlen( p ) ; - if( len < bufflen ) { - strcpy( buff, p ); - } else { - astError( AST__TUNAM, "astTuneC: Supplied string variable " - "is too small - the current '%s' value (%s) has " - "%d characters.", status, name, p, len ); - } - } - -/* If a new value is to be stored.... */ - if( value ) { - -/* Report an error if it is too long to fit in the static buffer. */ - len = strlen( value ) ; - if( len >= MAXLEN_TUNEC ) { - astError( AST__TUNAM, "astTuneC: Supplied value for '%s' " - "(%s) is too long - must not be longer than %d " - "characters.", status, name, value, MAXLEN_TUNEC ); - -/* Otherwise, copy the new value into the static buffer. */ - } else { - strcpy( p, value ); - } - } - } - - UNLOCK_MUTEX1; - } -} - -AstObject *astFromString_( const char *string, int *status ) { -/* -c++ -* Name: -* astFromString - -* Purpose: -* Re-create an Object from an in-memory serialisation - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* AstObject *astFromString( const char *string ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a pointer to a new Object created from the -* supplied text string, which should have been created by astToString. - -* Parameters: -* string -* Pointer to a text string holding an Object serialisation created -* previously by astToString. - -* Returned Value: -* astFromString() -* Pointer to a new Object created from the supplied serialisation, -* or NULL if the serialisation was invalid, or an error occurred. - -c-- -*/ - -/* Local Variables: */ - StringData data; /* Data passed to the source function */ - AstChannel *channel; /* Pointer to output Channel */ - AstObject *result; /* Pointer to returned Object */ - -/* Check the global error status and supplied serialisation. */ - if ( !astOK || !string ) return NULL; - -/* Create a Channel which will read from the supplied serialisation. */ - channel = astChannel( FromStringSource, NULL, "", status ); - -/* Initialise the data structure used to communicate with the source - function, and store a pointer to it in the Channel. */ - data.ptr = (char *) string; - data.buff = NULL; - data.len = 0; - astPutChannelData( channel, &data ); - -/* Read an Object from the Channel. */ - result = astRead( channel ); - -/* Annul the Channel pointer. */ - channel = astAnnul( channel ); - -/* Free the line buffer. */ - data.buff = astFree( data.buff ); - -/* Annul the returned Object if an error has occurred. */ - if( !astOK ) result = astAnnul( result ); - -/* Return the Object pointer. */ - return result; -} - -static const char *FromStringSource( void ){ -/* -* Name: -* FromStringSource - -* Purpose: -* A Channel source function for use by the astFromString method. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* result = FromStringSource( void ) - -* Class Membership: -* Object member function. - -* Description: -* This function reads the next line of text from a serialisation and -* returns a pointer to it, or NULL if no lines remain. - -* Returned Value: -* Pointer to the null terminated line of text or NULL if no lines -* remain. -*/ - -/* Local Variables: */ - StringData *data; /* Data passed to the sink function */ - char *nl; /* Pointer to next newline character */ - int *status; /* Pointer to local status value */ - int nc; /* Number of characters to read from serialisation */ - int status_value; /* Local status value */ - -/* Set up the local status */ - status_value = 0; - status = &status_value; - -/* Get a pointer to the structure holding a pointer to the next line, and - to the buffer to return. */ - data = astChannelData; - -/* Return NULL if no text remains to be read. */ - if( !data->ptr || (data->ptr)[0] == 0 ) return NULL; - -/* Find the next newline (if any) in the serialisation. */ - nl = strchr( data->ptr, '\n' ); - -/* Get the number of characters to copy. */ - nc = nl ? nl - data->ptr : strlen( data->ptr ); - -/* Copy them into the returned buffer, including an extra character for - the terminating null. */ - data->buff = astStore( data->buff, data->ptr, nc + 1 ); - -/* Store the terminating null. */ - (data->buff)[ nc ] = 0; - -/* Update the pointer to the next character to read from the - serialisation. */ - data->ptr = nl ? nl + 1 : NULL; - -/* Return the buffer. */ - return data->buff; -} - -static void VSet( AstObject *this, const char *settings, char **text, - va_list args, int *status ) { -/* -*+ -* Name: -* astVSet - -* Purpose: -* Set values for an Object's attributes. - -* Type: -* Protected virtual function. - -* Synopsis: -* #include "object.h" -* void astVSet( AstObject *this, const char *settings, char **text, -* va_list args ) - -* Class Membership: -* Object method. - -* Description: -* This function assigns a set of attribute values for an Object, -* the attributes and their values being specified by means of a -* string containing a comma-separated list of the form: -* -* "attribute1 = value1, attribute2 = value2, ... " -* -* Here, "attribute" specifies an attribute name and the value to -* the right of each "=" sign should be a suitable textual -* representation of the value to be assigned to that -* attribute. This will be interpreted according to the attribute's -* data type. -* -* The string supplied may also contain "printf"-style format -* specifiers identified by a "%" sign in the usual way. If -* present, these will be substituted by values supplied as -* optional arguments (as a va_list variable argument list), using -* the normal "printf" rules, before the string is used. - -* Parameters: -* this -* Pointer to the Object. -* settings -* Pointer to a null-terminated string containing a -* comma-separated list of attribute settings. -* text -* Pointer to a location at which to return a pointer to dynamic -* memory holding a copy of the expanded setting string. This memory -* should be freed using astFree when no longer needed. If a NULL -* pointer is supplied, no string is created. -* args -* The variable argument list which contains values to be -* substituted for any "printf"-style format specifiers that -* appear in the "settings" string. - -* Notes: -* - Attribute names are not case sensitive. -* - White space may surround attribute names and will be ignored. -* - White space may also surround attribute values where it will -* be ignored (except for string-valued attributes where it is -* significant and forms part of the value to be assigned). -* - After this function has substituted values for "printf"-style -* format specifiers it splits the "settings" string into -* individual attribute settings which it passes one at a time to -* the protected astSetAttrib method (after removal of white space -* and conversion of attribute names to lower case). The -* astSetAttrib method should therefore be extended by derived -* classes which define new attributes, and this will allow the -* astVSet (and astSet) methods to have access to those attributes. -* - This function provides the same functionality as the astSet -* public method but accepts a va_list variable argument list -* instead of a variable number of arguments. It is provided for -* use by functions in other class implementations which accept a -* variable number of arguments and must therefore pass their -* argument list to this method in va_list form. -*- -*/ - -#define MIN_BUFF_LEN 1024 -#define ERRBUF_LEN 80 - -/* Local Variables: */ - char errbuf[ ERRBUF_LEN ]; /* Buffer for system error message */ - char setting_buf[ MIN_BUFF_LEN ]; /* Expanded "%s" settting string */ - char *dyn_buf; /* Pointer to dynamic buffer for expanded setting */ - char *errstat; /* Pointer to error message */ - char *assign; /* Pointer to assigment substring */ - char *assign_end; /* Pointer to null at end of assignment */ - char *buff1; /* Pointer to temporary string buffer */ - char *buff2; /* Pointer to temporary string buffer */ - char *buff3; /* Pointer to temporary string buffer */ - char *eq1; /* Pointer to 1st equals sign */ - int buff_len; /* Length of temporary buffer */ - int expanded; /* Has the Settings string been expanded yet? */ - int i; /* Loop counter for characters */ - int j; /* Offset for revised assignment character */ - int len; /* Length of settings string */ - int lo; /* Convert next character to lower case? */ - int nc; /* Number of vsprintf output characters */ - int quoted; /* Are we in a quoted string? */ - int stat; /* Value of errno after an error */ - int tq; /* Test if the next non-space is a quote? */ - -/* Initialise */ - if( text ) *text = NULL; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain the length of the "settings" string and test it is not - zero. If it is, there is nothing more to do. */ - len = (int) strlen( settings ); - if ( len != 0 ) { - -/* If the setting string is just "%s" (with optional trailing and leading - white space) then the variable argument potentially contains more than - one attribute setting, in which case we expand the setting string now - and use the expanded string in place of the supplied string in the rest - of this function. */ - nc = 0; - sscanf( settings, " %%s %n", &nc ); - if( nc == len ) { - -/* Expand the supplied string using a fixed-length buffer. This writes at - most MIN_BUFF_LEN characters to "buf", but returns the number of - characters that would have been needed to write the whole string. */ - len = vsnprintf( setting_buf, sizeof(setting_buf), settings, args ); - -/* If the fixed-length buffer is too short, use a dynamically allocated - buffer instead. */ - if( len + 1 > MIN_BUFF_LEN ) { - dyn_buf = astMalloc( len + 1 ); - if( astOK ) { - len = vsnprintf( dyn_buf, len + 1, settings, args ); - settings = dyn_buf; - } - } else { - dyn_buf = NULL; - settings = setting_buf; - } - -/* Indicate that "settings" has been expanded. */ - expanded = 1; - - } else { - expanded = 0; - dyn_buf = NULL; - } - -/* Allocate memory and store a copy of the string. */ - buff1 = astStore( NULL, settings, (size_t) ( len + 1 ) ); - if ( astOK ) { - -/* Convert each comma in the string into '\n'. This is to distinguish - commas initially present from those introduced by the formatting to - be performed below. We only do this if there is more than one equals - sign in the setting string, since otherwise any commas are probably - characters contained within a string attribute value. Ignore commas - that occur within quoted strings. */ - eq1 = strchr( buff1, '=' ); - if( eq1 && strchr( eq1 + 1, '=' ) ) { - quoted = 0; - for ( i = 0; i < len; i++ ) { - if( !quoted ) { - if ( buff1[ i ] == ',' ) { - buff1[ i ] = '\n'; - } else if( buff1[ i ] == '"' ) { - quoted = 1; - } - } else if( buff1[ i ] == '"' ){ - quoted = 0; - } - } - } - -/* Calculate a size for a further buffer twice the size of the first - one. Ensure it is not less than a minimum size and then allocate - this buffer. */ - buff_len = 2 * len; - if ( buff_len < MIN_BUFF_LEN ) buff_len = MIN_BUFF_LEN; - buff2 = astMalloc( (size_t) ( buff_len + 1 ) ); - if ( astOK ) { - -/* Use "vsprintf" to substitute values for any format specifiers in - the "settings" string, writing the resulting string into the second - buffer. If the "settings" string has already been expanded, then just - copy it. */ - errno = 0; - if( !expanded ) { - nc = vsprintf( buff2, buff1, args ); - } else { - strcpy( buff2, buff1 ); - nc = strlen( buff1 ); - } - -/* Get a copy of the expanded string to return as the function value and - convert newlines back to commas. */ - if( text ) { - *text = astStore( NULL, buff2, nc + 1 ); - if( *text ) { - for ( i = 0; i <= nc; i++ ) { - if ( (*text)[ i ] == '\n' ) (*text)[ i ] = ','; - } - } - } - -/* The possibilities for error detection are limited here, but check - if an error value was returned and report an error. Include - information from errno if it was set. */ - if ( nc < 0 ) { - if( astOK ) { - stat = errno; - - if( stat ) { -#if HAVE_STRERROR_R - strerror_r( stat, errbuf, ERRBUF_LEN ); - errstat = errbuf; -#else - errstat = strerror( stat ); -#endif - } else { - *errbuf = 0; - errstat = errbuf; - } - - astError( AST__ATSER, "astVSet(%s): Error formatting an " - "attribute setting%s%s.", status, astGetClass( this ), - stat? " - " : "", errstat ); - astError( AST__ATSER, "The setting string was \"%s\".", status, - settings ); - } - -/* Also check that the result buffer did not overflow. If it did, - memory will probably have been corrupted but this cannot be - prevented with "vsprintf" (although we try and make the buffer - large enough). Report the error and abort. */ - } else if ( nc > buff_len ) { - if( astOK ) { - astError( AST__ATSER, "astVSet(%s): Internal buffer overflow " - "while formatting an attribute setting - the result " - "exceeds %d characters.", status, astGetClass( this ), - buff_len ); - astError( AST__ATSER, "The setting string was \"%s\".", status, - settings ); - } - -/* If all is OK, loop to process each formatted attribute assignment - (these are now separated by '\n' characters). */ - } else { - assign = buff2; - while ( assign ) { - -/* Change the '\n' at the end of each assignment to a null to - terminate it. */ - if ( ( assign_end = strchr( assign, '\n' ) ) ) { - *assign_end = '\0'; - } - -/* Before making the assignment, loop to remove white space and upper - case characters from the attribute name. */ - lo = 1; - tq = -1; - quoted = 0; - for ( i = j = 0; assign[ i ]; i++ ) { - -/* Note when an '=' sign is encountered (this signals the end of the - attribute name). */ - if ( assign[ i ] == '=' ) lo = 0; - -/* Before the '=' sign, convert all characters to lower case and move - everything to the left to eliminate white space. Afer the '=' sign, - copy all characters to their new location unchanged, except for any - delimiting quotes, which are removed. astSetC replaces commas in the - attribute value by '\r' characters. Reverse this now. */ - if ( !lo || !isspace( assign[ i ] ) ) { - if( assign[ i ] == '\r' ) { - assign[ j++ ] = ','; - - } else if( lo ) { - assign[ j++ ] = tolower( assign[ i ] ); - - } else { - assign[ j++ ] = assign[ i ]; - - if( tq > 0 && !isspace( assign[ i ] ) ) { - if( assign[ i ] == '"' ) { - quoted = 1; - j--; - } - tq = 0; - } - - } - } - -/* If the current character is the initial '=' sign, set "tq" positive, - meaning "check if the next non-space character is a quote". */ - if ( assign[ i ] == '=' && tq == -1 ) tq = 1; - } - -/* if the value was quoted. remove the trailing quote. */ - if( quoted ) { - j--; - while( isspace( assign[ j ] ) ) j--; - if( assign[ j ] == '"' ) j--; - j++; - } - -/* Terminate the revised assignment string and pass it to astSetAttrib - to make the assignment (unless the string was all blank, in which - case we ignore it). */ - assign[ j ] = '\0'; - if ( j ) { - -/* If there are no characters to the right of the equals sign append a - space after the equals sign. Without this, a string such as "Title=" - would not be succesfully matched against the attribute name "Title" - within SetAttrib. */ - if( assign[ j - 1 ] == '=' ) { - buff3 = astStore( NULL, assign, - (size_t) j + 2 ); - if ( astOK ) { - buff3[ j ] = ' '; - buff3[ j + 1 ] = '\0'; - astSetAttrib( this, buff3 ); - } - buff3 = astFree( buff3 ); - - } else { - astSetAttrib( this, assign ); - } - } - -/* Check for errors and abort if any assignment fails. Otherwise, - process the next assignment substring. */ - if ( !astOK ) break; - assign = assign_end ? assign_end + 1 : NULL; - } - } - } - -/* Free the memory allocated for string buffers. */ - buff2 = astFree( buff2 ); - dyn_buf = astFree( dyn_buf ); - } - buff1 = astFree( buff1 ); - } -} -#undef ERRBUF_LEN -#undef MIN_BUFF_LEN - -/* Attribute access functions. */ -/* --------------------------- */ -/* -*att++ -* Name: -* Class - -* Purpose: -* Object class name. - -* Type: -* Public attribute. - -* Synopsis: -* Character string, read-only. - -* Description: -* This attribute gives the name of the class to which an Object -* belongs. - -* Applicability: -* Object -* All Objects have this attribute. -*att-- -*/ - -/* -*att++ -* Name: -* ID - -* Purpose: -* Object identification string. - -* Type: -* Public attribute. - -* Synopsis: -* String. - -* Description: -* This attribute contains a string which may be used to identify -* the Object to which it is attached. There is no restriction on -* the contents of this string, which is not used internally by the -* AST library, and is simply returned without change when -* required. The default value is an empty string. -* -* An identification string can be valuable when, for example, -c several Objects have been stored in a file (using astWrite) and -f several Objects have been stored in a file (using AST_WRITE) and -c are later retrieved (using astRead). Consistent use of the ID -f are later retrieved (using AST_READ). Consistent use of the ID -* attribute allows the retrieved Objects to be identified without -* depending simply on the order in which they were stored. -* -* This attribute may also be useful during debugging, to -c distinguish similar Objects when using astShow to display them. -f distinguish similar Objects when using AST_SHOW to display them. - -* Applicability: -* Object -* All Objects have this attribute. - -* Notes: -* - Unlike most other attributes, the value of the ID attribute is -* not transferred when an Object is copied. Instead, its value is -* undefined (and therefore defaults to an empty string) in any -* copy. However, it is retained in any external representation of -c an Object produced by the astWrite function. -f an Object produced by the AST_WRITE routine. -*att-- -*/ -/* Clear the ID value by freeing the allocated memory and assigning a - NULL pointer. */ -astMAKE_CLEAR(Object,ID,id,astFree( this->id )) - -/* If the ID value is not set, supply a default in the form of a - pointer to the constant string "". */ -astMAKE_GET(Object,ID,const char *,NULL,( this->id ? this->id : "" )) - -/* Set an ID value by freeing any previously allocated memory, - allocating new memory and storing the string. */ -astMAKE_SET(Object,ID,const char *,id,astStore( this->id, value, - strlen( value ) + (size_t) 1 )) - -/* The ID value is set if the pointer to it is not NULL. */ -astMAKE_TEST(Object,ID,( this->id != NULL )) - -/* -*att++ -* Name: -* Ident - -* Purpose: -* Permanent Object identification string. - -* Type: -* Public attribute. - -* Synopsis: -* String. - -* Description: -* This attribute is like the ID attribute, in that it contains a -* string which may be used to identify the Object to which it is -* attached. The only difference between ID and Ident is that Ident -* is transferred when an Object is copied, but ID is not. - -* Applicability: -* Object -* All Objects have this attribute. - -*att-- -*/ -/* Clear the Ident value by freeing the allocated memory and assigning a - NULL pointer. */ -astMAKE_CLEAR(Object,Ident,ident,astFree( this->ident )) - -/* If the Ident value is not set, supply a default in the form of a - pointer to the constant string "". */ -astMAKE_GET(Object,Ident,const char *,NULL,( this->ident ? this->ident : "" )) - -/* Set an Ident value by freeing any previously allocated memory, - allocating new memory and storing the string. */ -astMAKE_SET(Object,Ident,const char *,ident,astStore( this->ident, value, - strlen( value ) + (size_t) 1 )) - -/* The Ident value is set if the pointer to it is not NULL. */ -astMAKE_TEST(Object,Ident,( this->ident != NULL )) - -/* -*att++ -* Name: -* UseDefs - -* Purpose: -* Use default values for unspecified attributes? - -* Type: -* Public attribute. - -* Synopsis: -* Integer (boolean). - -* Description: -* This attribute specifies whether default values should be used -* internally for object attributes which have not been assigned a -* value explicitly. If a non-zero value (the default) is supplied for -* UseDefs, then default values will be used for attributes which have -* not explicitly been assigned a value. If zero is supplied for UseDefs, -* then an error will be reported if an attribute for which no explicit -* value has been supplied is needed internally within AST. -* -* Many attributes (including the UseDefs attribute itself) are unaffected -* by the setting of the UseDefs attribute, and default values will always -* be used without error for such attributes. The "Applicability:" section -* below lists the attributes which are affected by the setting of UseDefs. - -* Note, UseDefs only affects access to attributes internally within -* AST. The public accessor functions such as -c astGetC -f AST_GETC -* is unaffected by the UseDefs attribute - default values will always -* be returned if no value has been set. Application code should use the -c astTest -f AST_TEST -* function if required to determine if a value has been set for an -* attribute. - -* Applicability: -* Object -* All Objects have this attribute, but ignore its setting except -* as described below for individual classes. -* FrameSet -* The default value of UseDefs for a FrameSet is redefined to be -* the UseDefs value of its current Frame. -* CmpFrame -* The default value of UseDefs for a CmpFrame is redefined to be -* the UseDefs value of its first component Frame. -* Region -* The default value of UseDefs for a Region is redefined to be -* the UseDefs value of its encapsulated Frame. -* Frame -* If UseDefs is zero, an error is reported when aligning Frames if the -* Epoch, ObsLat or ObsLon attribute is required but has not been -* assigned a value explicitly. -* SkyFrame -* If UseDefs is zero, an error is reported when aligning SkyFrames -* if any of the following attributes are required but have not been -* assigned a value explicitly: Epoch, Equinox. -* SpecFrame -* If UseDefs is zero, an error is reported when aligning SpecFrames -* if any of the following attributes are required but have not been -* assigned a value explicitly: Epoch, RefRA, RefDec, RestFreq, -* SourceVel, StdOfRest. -* DSBSpecFrame -* If UseDefs is zero, an error is reported when aligning DSBSpecFrames -* or when accessing the ImagFreq attribute if any of the following -* attributes are required but have not been assigned a value explicitly: -* Epoch, DSBCentre, IF. -*att-- -*/ -astMAKE_CLEAR(Object,UseDefs,usedefs,CHAR_MAX) -astMAKE_GET(Object,UseDefs,int,1,((this->usedefs!=CHAR_MAX)?this->usedefs:1)) -astMAKE_SET(Object,UseDefs,int,usedefs,((value)?1:0)) -astMAKE_TEST(Object,UseDefs,(this->usedefs!=CHAR_MAX)) - -/* -*att++ -* Name: -* Nobject - -* Purpose: -* Number of Objects in class. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute gives the total number of Objects currently in -* existence in the same class as the Object whose attribute value -* is requested. This count does not include Objects which belong -* to derived (more specialised) classes. -* -* This attribute is mainly intended for debugging. It can be used -* to detect whether Objects which should have been deleted have, -* in fact, been deleted. - -* Applicability: -* Object -* All Objects have this attribute. -*att-- -*/ - -/* -*att++ -* Name: -* ObjSize - -* Purpose: -* The in-memory size of the Object. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute gives the total number of bytes of memory used by -* the Object. This includes any Objects which are encapsulated within -* the supplied Object. - -* Applicability: -* Object -* All Objects have this attribute. -*att-- -*/ - -/* -*att++ -* Name: -* RefCount - -* Purpose: -* Count of active Object pointers. - -* Type: -* Public attribute. - -* Synopsis: -* Integer, read-only. - -* Description: -* This attribute gives the number of active pointers associated -* with an Object. It is modified whenever pointers are created or -c annulled (by astClone, astAnnul or astEnd for example). The count -f annulled (by AST_CLONE, AST_ANNUL or AST_END for example). The count -* includes the initial pointer issued when the Object was created. -* -* If the reference count for an Object falls to zero as the result -* of annulling a pointer to it, then the Object will be deleted. - -* Applicability: -* Object -* All Objects have this attribute. -*att-- -*/ - -/* Standard class functions. */ -/* ========================= */ -/* -*+ -* Name: -* astCheck<Class> - -* Purpose: -* Validate class membership. - -* Type: -* Protected function. - -* Synopsis: -* #include "class.h" -* Ast<Class> *astCheck<Class>( Ast<Class> *this ) - -* Class Membership: -* <Class> class function. - -* Description: -* This function validates membership of the class called <Class>, -* or of any class derived from it. If the Object is not a member, -* or the pointer supplied does not identify a valid Object, an -* error is reported and the global error status is set to -* AST__OBJIN. - -* Parameters: -* this -* Pointer to the Object. - -* Returned Value: -* The function always returns a copy of the "this" pointer -* (whether it finds it valid or not). - -* Notes: -* - Each class provides a function (astCheck<Class>) of this form, -* where <Class> and <class> are replaced by the class name (with -* appropriate capitalisation). -* - Normal error status checking is performed, so this function -* will not execute if the global error status is set on entry (the -* usual function value will be returned, however). -* - This function is primarily intended for validating Object -* pointers passed to member functions as part of a class -* interface. -*- -*/ - -/* Implement the astCheckObject function using the macro defined for this - purpose in the "object.h" header file. */ -astMAKE_CHECK(Object) - -int astIsAObject_( const AstObject *this, int *status ) { -/* -*++ -* Name: -c astIsA<Class> -f AST_ISA<CLASS> - -* Purpose: -* Test membership of a class by an Object. - -* Type: -* Public function. - -* Synopsis: -c #include "class.h" -c int astIsA<Class>( const Ast<Class> *this ) -f RESULT = AST_ISA<CLASS>( THIS, STATUS ) - -* Class Membership: -* Class function. - -* Description: -* This is a family of functions which test whether an Object is a -c member of the class called <Class>, or of any class derived from -f member of the class called <CLASS>, or of any class derived from -* it. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Pointer to the Object. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Returned Value: -c astIsA<Class>() -c One if the Object belongs to the class called <Class> (or to a -c class derived from it), otherwise zero. -f AST_ISA<CLASS> = LOGICAL -f .TRUE. if the Object belongs to the class called <CLASS> (or to -f a class derived from it), otherwise .FALSE.. - -* Applicability: -* Object -* These functions apply to all Objects. - -* Examples: -c member = astIsAFrame( obj ); -c Tests whether Object "obj" is a member of the Frame class, or -c of any class derived from a Frame. -f MEMBER = AST_ISAFRAME( OBJ, STATUS ); -f Tests whether Object OBJ is a member of the Frame class, or -f of any class derived from a Frame. - -* Notes: -c - Every AST class provides a function (astIsA<Class>) of this -c form, where <Class> should be replaced by the class name. -f - Every AST class provides a function (AST_ISA<CLASS>) of this -f form, where <CLASS> should be replaced by the class name. -c - This function attempts to execute even if the AST error status -c is set -f - This function attempts to execute even if STATUS is set to an -f error value -* on entry, although no further error report will be made -* if it subsequently fails under these circumstances. -c - A value of zero will be returned if this function should fail -f - A value of .FALSE. will be returned if this function should fail -* for any reason. In particular, it will fail if the pointer -* supplied does not identify an Object of any sort. -*-- -*/ - -/* Local Variables: */ - int valid; /* Valid object? */ - -/* Since this is the base class, the implementation of this function - differs from that in derived classes (in that it fails and - potentially reports an error if the returned result is zero). */ - -/* Initialise. */ - valid = 0; - -/* Check if a NULL pointer was supplied (this can never be valid). If - OK, check if the Object contains the correct "magic number" in its - check field. */ - if ( !this || ( this->check != Magic( this, this->size, status ) ) ) { - -/* If it is not a valid Object, then report an error (but only if the - global error status has not already been set). */ - if ( astOK ) { - astError( AST__OBJIN, "astIsAObject(%s): Invalid Object pointer " - "given (points at address %p).", status, astGetClass( this ), - (void *) this ); - } - -/* Otherwise, note that the Object is valid. */ - } else { - valid = 1; - } - -/* Return the result. */ - return valid; -} - -void astInitObjectVtab_( AstObjectVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitObjectVtab - -* Purpose: -* Initialise a virtual function table for a Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* void astInitObjectVtab( AstObjectVtab *vtab, const char *name ) - -* Class Membership: -* Object vtab initialiser. - -* Description: -* This function initialises the component of a virtual function -* table which is used by the Object class. - -* Parameters: -* vtab -* Pointer to the virtual function table. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the virtual function table belongs (it -* is this pointer value that will subsequently be returned by the Object -* astClass function). -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int ivtab; /* Index of next entry in known_vtabs */ - -/* Check the local error status. */ - if ( !astOK ) return; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Initialise the contents of the class identifier. Since this is the - base class, we assign null values to the fields. */ - vtab->id.check = NULL; - vtab->id.parent = NULL; - -/* Store pointers to the member functions (implemented here) that provide - virtual methods for this class. */ - vtab->Clear = Clear; - vtab->ClearAttrib = ClearAttrib; - vtab->ClearID = ClearID; - vtab->ClearIdent = ClearIdent; - vtab->Dump = Dump; - vtab->Equal = Equal; - vtab->GetAttrib = GetAttrib; - vtab->GetID = GetID; - vtab->GetIdent = GetIdent; - vtab->HasAttribute = HasAttribute; - vtab->Same = Same; - vtab->SetAttrib = SetAttrib; - vtab->SetID = SetID; - vtab->SetIdent = SetIdent; - vtab->Show = Show; - vtab->TestAttrib = TestAttrib; - vtab->TestID = TestID; - vtab->TestIdent = TestIdent; - vtab->EnvSet = EnvSet; - vtab->VSet = VSet; - vtab->Cast = Cast; - vtab->GetObjSize = GetObjSize; - vtab->CleanAttribs = CleanAttribs; - - vtab->TestUseDefs = TestUseDefs; - vtab->SetUseDefs = SetUseDefs; - vtab->ClearUseDefs = ClearUseDefs; - vtab->GetUseDefs = GetUseDefs; - -#if defined(THREAD_SAFE) - vtab->ManageLock = ManageLock; -#endif - -/* Store the pointer to the class name. */ - vtab->class = name; - -/* Initialise the count of active objects and the number of destructors, - copy constructors and dump functions. */ - vtab->nobject = 0; - vtab->ndelete = 0; - vtab->ncopy = 0; - vtab->ndump = 0; - -/* Initialise the arrays of destructor, copy constructor and dump - function pointers. */ - vtab->delete = NULL; - vtab->copy = NULL; - vtab->dump = NULL; - vtab->dump_class = NULL; - vtab->dump_comment = NULL; - -/* Initialise the default attributes to use when creating objects. */ - vtab->defaults = NULL; - -/* The virtual function table for each class contains a list of pointers - to memory blocks which have previously been used to store an Object of - the same class, but which have since been deleted using astDelete. - These memory blocks are free to be re-used when a new Object of the - same class is initialised. This saves on the overheads associated with - continuously allocating small blocks of memory using malloc. */ - vtab->nfree = 0; - vtab->free_list = NULL; - -/* Add the supplied virtual function table pointer to the end of the list - of known vtabs. */ - ivtab = nvtab++; - - astBeginPM; - known_vtabs = astGrow( known_vtabs, nvtab, sizeof( AstObjectVtab *) ); - astEndPM; - - if( astOK && known_vtabs ) known_vtabs[ ivtab ] = vtab; - -/* Fill a pointer value with zeros (not necessarily the same thing as a - NULL pointer) for subsequent use. */ - (void) memset( &zero_ptr, 0, sizeof( AstObject * ) ); - -/* If we have just initialised the vtab for the current class, indicate - that the vtab is now initialised. */ - if( vtab == &class_vtab ) class_init = 1; -} - -AstObject *astInitObject_( void *mem, size_t size, int init, - AstObjectVtab *vtab, const char *name, int *status ) { -/* -*+ -* Name: -* astInitObject - -* Purpose: -* Initialise an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astInitObject( void *mem, size_t size, int init, -* AstObjectVtab *vtab, const char *name ) - -* Class Membership: -* Object initialiser. - -* Description: -* This function is provided for use by class implementations to initialise -* a new Object. It allocates memory (if necessary) to accommodate the -* Object plus any additional data associated with the derived class. It -* then initialises an Object structure at the start of this memory. If the -* "init" flag is set, it also initialises the contents of a virtual -* function table for an Object at the start of the memory passed via the -* "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory in which the Object is to be initialised. -* This must be of sufficient size to accommodate the Object data -* (sizeof(Object)) plus any data used by the derived class. If a value -* of NULL is given, this function will allocate the memory itself using -* the "size" parameter to determine its size. -* size -* The amount of memory used by the Object (plus derived class data). -* This will be used to allocate memory if a value of NULL is given for -* the "mem" parameter. This value is also stored in the Object -* structure, so a valid value must be supplied even if not required for -* allocating memory. -* init -* A logical flag indicating if the Object's virtual function table is -* to be initialised. If this value is non-zero, the virtual function -* table will be initialised by this function. -* vtab -* Pointer to the start of the virtual function table to be associated -* with the new Object. -* name -* Pointer to a constant null-terminated character string which contains -* the name of the class to which the new object belongs (it is this -* pointer value that will subsequently be returned by the Object -* astClass function). - -* Returned Value: -* A pointer to the new Object. - -* Notes: -* - A null pointer will be returned if this function is invoked with the -* global error status set, or if it should fail for any reason. -*- -*/ - -/* Local Variables: */ - AstObject *new; /* Pointer to new Object */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Determine if memory must be allocated dynamically. If so, use the last - block of memory in the list of previously allocated but currently - unused blocks identified by the vtab "free_list" array, reducing the - length of the free list by one, and nullifying the entry in the list - for safety. If the list is originally empty, allocate memory for a new - object using astMalloc. */ - if( !mem ) { - if( object_caching ) { - if( vtab->nfree > 0 ) { - mem = vtab->free_list[ --(vtab->nfree) ]; - vtab->free_list[ vtab->nfree ] = NULL; - if( astSizeOf( mem ) != size && astOK ) { - astError( AST__INTER, "astInitObject(%s): Free block has size " - "%d but the %s requires %d bytes (internal AST " - "programming error).", status, vtab->class, - (int) astSizeOf( mem ), vtab->class, (int) size ); - } - } else { - mem = astMalloc( size ); - } - - } else { - mem = astMalloc( size ); - } - -/* If memory had already been allocated, adjust the "size" value to match - the size of the allocated memory. */ - } else { - size = astSizeOf( mem ); - } - -/* Obtain a pointer to the new Object. */ - if ( astOK ) { - new = (AstObject *) mem; - -/* Zero the entire new Object structure (to prevent accidental re-use - of any of its values after deletion). */ - (void) memset( new, 0, size ); - -/* If necessary, initialise the virtual function table. */ -/* ---------------------------------------------------- */ - if ( init ) astInitObjectVtab( vtab, name ); - if( astOK ) { - -/* Initialise the Object data. */ -/* --------------------------- */ -/* Store a unique "magic" value in the Object structure. This will be - used (e.g. by astIsAObject) to determine if a pointer identifies a - valid Object. Note that this differs from the practice in derived - classes, where this number is stored in the virtual function - table. We take a different approach here so that we need not follow - a pointer to the virtual function table obtained from a structure - that hasn't yet been validated as an Object. This minimises the - risk of a memory access violation. */ - new->check = Magic( new, size, status ); - -/* Associate the Object with its virtual function table. */ - new->vtab = vtab; - -/* Store the Object size and note if its memory was dynamically allocated. */ - new->size = size; - new->dynamic = astIsDynamic( new ); - -/* Initialise the reference count (of Object pointers in use). */ - new->ref_count = 1; - -/* Initialise the ID strings. */ - new->id = NULL; - new->ident = NULL; - -/* Use default values for unspecified attributes. */ - new->usedefs = CHAR_MAX; - -/* Increment the count of active Objects in the virtual function table. - Use the count as a unique identifier (unique within the class) for - the Object. */ - new->iref = vtab->nobject++; - -/* Initialise the pointer to an external object that acts as a proxy for - the AST Object within foreign language interfaces. */ - new->proxy = NULL; - } - -/* If an error occurred, clean up by deleting the new Object. Otherwise - lock the object for use by the currently executing thread. */ - if ( !astOK ) { - new = astDelete( new ); - -#ifdef THREAD_SAFE - } else { - if( pthread_mutex_init( &(new->mutex1), NULL ) != 0 && astOK ) { - astError( AST__INTER, "astInitObject(%s): Failed to " - "initialise POSIX mutex1 for the new Object.", status, - vtab->class ); - } - if( pthread_mutex_init( &(new->mutex2), NULL ) != 0 && astOK ) { - astError( AST__INTER, "astInitObject(%s): Failed to " - "initialise POSIX mutex2 for the new Object.", status, - vtab->class ); - } - new->locker = -1; - new->globals = NULL; - (void) ManageLock( new, AST__LOCK, 0, NULL, status ); - if( !astOK ) new = astDelete( new ); -#endif - } - } - -/* Return a pointer to the new Object. */ - return new; -} - -AstObject *astLoadObject_( void *mem, size_t size, - AstObjectVtab *vtab, const char *name, - AstChannel *channel, int *status ) { -/* -*+ -* Name: -* astLoadObject - -* Purpose: -* Load an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astLoadObject( void *mem, size_t size, -* AstObjectVtab *vtab, const char *name, -* AstChannel *channel ) - -* Class Membership: -* Object loader. - -* Description: -* This function is provided to load a new Object using data read -* from a Channel, and to allocate memory for it if necessary. -* -* If the "init" flag is set, it also initialises the contents of a -* virtual function table for an Object at the start of the memory -* passed via the "vtab" parameter. - -* Parameters: -* mem -* A pointer to the memory into which the Object is to be -* loaded. This must be of sufficient size to accommodate the -* Object data (sizeof(Object)) plus any data used by derived -* classes. If a value of NULL is given, this function will -* allocate the memory itself using the "size" parameter to -* determine its size. -* size -* The amount of memory used by the Object (plus derived class -* data). This will be used to allocate memory if a value of -* NULL is given for the "mem" parameter. This value is also -* stored in the Object structure, so a valid value must be -* supplied even if not required for allocating memory. -* -* If the "vtab" parameter is NULL, the "size" value is ignored -* and sizeof(AstObject) is used instead. -* vtab -* Pointer to the start of the virtual function table to be -* associated with the new Object. If this is NULL, a pointer to -* the (static) virtual function table for the Object class is -* used instead. -* name -* Pointer to a constant null-terminated character string which -* contains the name of the class to which the new Object -* belongs (it is this pointer value that will subsequently be -* returned by the astGetClass method). -* -* If the "vtab" parameter is NULL, the "name" value is ignored -* and a pointer to the string "Object" is used instead. - -* Returned Value: -* A pointer to the new Object. - -* Notes: -* - A null pointer will be returned if this function is invoked -* with the global error status set, or if it should fail for any -* reason. -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - AstObject *new; /* Pointer to the new Object */ - -/* Initialise. */ - new = NULL; - -/* Check the global error status. */ - if ( !astOK ) return new; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(channel); - -/* If a NULL virtual function table has been supplied, then this is - the first loader to be invoked for this Object. In this case the - Object belongs to this class, so supply appropriate values for - initialising it and its virtual function table. */ - if ( !vtab ) { - size = sizeof( AstObject ); - vtab = &class_vtab; - name = "Object"; - -/* If required, initialise the virtual function table for this class. */ - if ( !class_init ) { - astInitObjectVtab( vtab, name ); - class_init = 1; - } - } - -/* There is no parent class to load, so simply initialise a new Object - structure as if a new Object were being created from scratch. */ - new = astInitObject( mem, size, 0, vtab, name ); - if ( astOK ) { - -/* Read input data. */ -/* ================ */ -/* Request the input Channel to read all the input data appropriate to - this class into the internal "values list". */ - astReadClassData( channel, "Object" ); - -/* Now read each individual data item from this list and use it to - initialise the appropriate instance variable(s) for this class. */ - new->id = astReadString( channel, "id", NULL ); - new->ident = astReadString( channel, "ident", NULL ); - new->usedefs = astReadInt( channel, "usedfs", CHAR_MAX ); - -/* We simply read the values for the read-only attributes (just in - case they've been un-commented in the external representation) and - discard them. This prevents any possibility of error due to un-read - input. */ - (void) astReadInt( channel, "refcnt", 0 ); - (void) astReadInt( channel, "nobj", 0 ); - -/* Initialise the pointer to an external object that acts as a proxy for - the AST Object within foreign language interfaces. */ - new->proxy = NULL; - -/* If an error occurred, clean up by deleting the new Object. */ - if ( !astOK ) new = astDelete( new ); - } - -/* Return the new Object pointer. */ - return new; -} - -/* Virtual function interfaces. */ -/* ============================ */ -/* These provide the external interface to the virtual functions defined by - this class. Each simply checks the global error status and then locates and - executes the appropriate member function, using the function pointer stored - in the object's virtual function table (this pointer is located using the - astMEMBER macro defined in "object.h"). - - Note that the member function may not be the one defined here, as it may - have been over-ridden by a derived class. However, it should still have the - same interface. */ -void astClear_( AstObject *this, const char *attrib, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,Clear))( this, attrib, status ); -} -void astClearAttrib_( AstObject *this, const char *attrib, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,ClearAttrib))( this, attrib, status ); -} -void astDump_( AstObject *this, AstChannel *channel, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,Dump))( this, channel, status ); -} - -#if defined(THREAD_SAFE) -int astManageLock_( AstObject *this, int mode, int extra, AstObject **fail, - int *status ) { - if( !this ) return 0; - return (**astMEMBER(this,Object,ManageLock))( this, mode, extra, fail, status ); -} -#endif - -int astEqual_( AstObject *this, AstObject *that, int *status ) { - if ( !astOK ) return 0; - if( this == that ) return 1; - return (**astMEMBER(this,Object,Equal))( this, that, status ); -} -const char *astGetAttrib_( AstObject *this, const char *attrib, int *status ) { - if ( !astOK ) return NULL; - return (**astMEMBER(this,Object,GetAttrib))( this, attrib, status ); -} -void astSetAttrib_( AstObject *this, const char *setting, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,SetAttrib))( this, setting, status ); -} -void astShow_( AstObject *this, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,Show))( this, status ); -} -int astTestAttrib_( AstObject *this, const char *attrib, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Object,TestAttrib))( this, attrib, status ); -} -void astEnvSet_( AstObject *this, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,EnvSet))( this, status ); -} -void astVSet_( AstObject *this, const char *settings, char **text, va_list args, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,VSet))( this, settings, text, args, status ); -} -int astGetObjSize_( AstObject *this, int *status ) { - if ( !astOK || !this ) return 0; - return (**astMEMBER(this,Object,GetObjSize))( this, status ); -} -void astCleanAttribs_( AstObject *this, int *status ) { - if ( !astOK ) return; - (**astMEMBER(this,Object,CleanAttribs))( this, status ); -} -AstObject *astCast_( AstObject *this, AstObject *obj, int *status ) { - if ( !astOK ) return NULL; - return (**astMEMBER(this,Object,Cast))( this, obj, status ); -} -int astSame_( AstObject *this, AstObject *that, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Object,Same))( this, that, status ); -} -int astHasAttribute_( AstObject *this, const char *attrib, int *status ) { - if ( !astOK ) return 0; - return (**astMEMBER(this,Object,HasAttribute))( this, attrib, status ); -} - -/* External interface. */ -/* =================== */ -/* The following relates to the external interface to Objects and not - specifically to the implementation of the Object class itself - (although it contains external functions which replace the internal - versions defined earlier). */ - - -/* Type Definitions. */ -/* ----------------- */ -/* Define the Handle structure. This is attached to Objects when they - are accessed via the public (external, user-callable) interface. - Handles provide a buffer between the Object identifiers issued to - external users and the naked C pointers used to handle Objects - internally. They also implement the context levels used by - astBegin, astEnd, astExempt and astExport (which are only available - to external users). */ -typedef struct Handle { - AstObject *ptr; /* C Pointer to the associated Object */ - int context; /* Context level for this Object */ - int check; /* Check value to ensure validity */ - -#if defined(THREAD_SAFE) - int thread; /* Identifier for owning thread */ -#endif - -#if defined(MEM_DEBUG) - int id; /* The id associated with the memory block - holding the Object last associated with - this handle. */ - AstObjectVtab *vtab; /* Pointer to the firtual function table of - the Object last associated with this - handle. */ -#endif - -/* Links between Handles are implemented using integer offsets rather - than through pointers. */ - int flink; /* Backward link to previous Handle */ - int blink; /* Forward link to next Handle */ - -/* Information that records where the Handle was created. */ - const char *routine; /* Routine name */ - const char *file; /* File name */ - int line; /* Line number */ - -} Handle; - -/* Define a union with an overlapping int and AstObject*. This is used - to transfer an integer bit pattern into and out of a pointer - variable used to store an Object identifier. This avoids any - implementation dependent aspects of integer-to-pointer - conversions. */ -typedef union IdUnion { - AstObject *pointer; - int integer; -} IdUnion; - -/* Define a union which allows a bit pattern to be accessed as a - signed or unsigned int. */ -typedef union MixedInts { - int i; - unsigned u; -} MixedInts; - -/* Static Variables. */ -/* ----------------- */ -/* The array of Handle structures is a pool of resources available to all - threads. Each thread has its own conext level and its own "active_handles" - array to identify the first Handle at each context level. */ -static Handle *handles = NULL; /* Pointer to allocated array of Handles */ -static int free_handles = -1; /* Offset to head of free Handle list */ -static int nhandles = 0; /* Number of Handles in "handles" array */ -static unsigned nids = 0; /* Number of IDs issued to external users */ - -#if defined(THREAD_SAFE) -static int unowned_handles = -1; /* Offset to head of unowned Handle - list. In a single threaded environment, - all handles must be owned by a thread. */ -#endif - -#ifdef MEM_DEBUG -static int Watched_Handle = -1; /* A handle index to be watched. Activity - on this handle is reported using - astHandleUse and astHandleAlarm. */ -#endif - - -/* External Interface Function Prototypes. */ -/* --------------------------------------- */ -/* MYSTATIC should normally be set to "static" to make the following - function have local symbols. But it may be set to blank for debugging - purposes in order to enable these functions to appear in a backtrace - such as produced by the astBacktrace function. */ -#define MYSTATIC - -/* Private functions associated with the external interface. */ -MYSTATIC AstObject *AssocId( int, int * ); -MYSTATIC int CheckId( AstObject *, int, int * ); -MYSTATIC void AnnulHandle( int, int * ); -MYSTATIC void InitContext( int * ); -MYSTATIC void InsertHandle( int, int *, int * ); -MYSTATIC void RemoveHandle( int, int *, int * ); - -#if defined(MEM_DEBUG) -MYSTATIC void CheckList( int *, int * ); -MYSTATIC void CheckInList( int, int *, int, int * ); -MYSTATIC int CheckThread( int, int *, int * ); -MYSTATIC const char *HandleString( int, char * ); -MYSTATIC const char *HeadString( int *, char * ); -#endif - - -/* The following functions have public prototypes only (i.e. no - protected prototypes), so we must provide local prototypes for use - within this module. */ -AstObject *astDeleteId_( AstObject *, int * ); -void astBegin_( void ); -void astEnd_( int * ); -void astExemptId_( AstObject *, int * ); -void astImportId_( AstObject *, int * ); -void astSetId_( void *, const char *, ... ); -void astLockId_( AstObject *, int, int * ); -void astUnlockId_( AstObject *, int, int * ); - - -/* External Interface Functions. */ -/* ----------------------------- */ -AstKeyMap *astActiveObjects_( const char *class, int subclass, int current, - int *status ) { -/* -c++ -* Name: -* astActiveObjects - -* Purpose: -* Return pointers for all active Objects. - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* AstKeyMap *astActiveObjects( const char *class, int subclass, -* int current ) - -* Class Membership: -* Object method. - -* Description: -* This function returns a KeyMap holding currently active AST Object -* pointers. Each entry in the KeyMap will have a key that is an AST -* class name such as "FrameSet", "SkyFrame", "ZoomMap", etc. The -* value of the entry will be a 1-dimensional list of pointers for -* objects of the same class. Note, the returned pointers should NOT -* be annulled when they are no longer needed. -* -* The pointers to return in the KeyMap may be restricted either by -* class or by context level using the function arguments. - -* Parameters: -* class -* If NULL, then the returned KeyMap will contain pointers ofr -* Objects of all classes. If not NULL, then "class" should be a -* pointer to a null-terminated string holding the name of an AST -* class. The returned KeyMap will contain pointers only for the -* specified class. See also "subclass". -* subclass -* A Boolean flag indicating if all subclasses of the class -* specified by "class" should be included in the returned KeyMap. -* If zero, then subclass objects are not returned. Otherwise they -* are returned. The supplied "subclass" value is ignored if -* "class" is NULL. -* current -* A Boolean flag indicating if the returned list of pointers -* should be restricted to pointers issued within the current AST -* object context (see astBegin and astEnd). - -* Returned Value: -* astActiveObjects() -* A pointer to a new KeyMap holding the required object pointers. -* They KeyMap pointer should be annulled when it is no longer -* needed, but the object pointers within the KeyMap should not be -* annulled. A NULL pointer is returned if an error has occurred -* prior to calling this function. -* -* The values stored in the KeyMap should be accessed as generic C -* pointers using the KeyMap "P" data type (e.g. using function -* astMapGetlemP etc). - -* Notes: -* - This function will only return objects locked by the currently -* executing thread. -* - The KeyMap pointer returned by this function is not included in the -* list of active objects stored in the KeyMap. -* - Objects that were created using the Fortran interface will have a -* null "file" value and will have a routine name equal to the upper case -* Fortran routine that issued the pointer (e.g. "AST_CLONE", "AST_FRAME", -* etc). - -c-- -*/ - -/* Local Variables: */ - AstKeyMap *result; /* Returned KeyMap */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int i; /* Loop count */ - int ihandle; /* Offset of Handle to be annulled */ - AstObjectVtab *req_vtab; /* Vtab for requested class */ - Handle *handle; /* Pointer to current Handle */ - int generation_gap; /* Hereditary relationshp between two classes */ - -/* Check the global error status. */ - if ( !astOK ) return NULL; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Create an empty KeyMap to hold the results. */ - result = astKeyMap( " ", status ); - -/* If we will need to check if each object is a subclass of a specified - class, we need a pointer to the VTAB descriibing the specified class. */ - req_vtab = NULL; - if( class && subclass ) { - -/* Loop round the vtab structures created by the currently executing thread. */ - for( i = 0; i < nvtab; i++ ) { - -/* If the current vtab is for a class that matches the requested class, - store a pointer to the vtab. */ - if( !strcmp( class, known_vtabs[ i ]->class ) ) { - req_vtab = known_vtabs[ i ]; - break; - } - } - } - -/* Get exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Get the index of the first Handle to check. If we are checking only the - current context level, then get this index from the appropriate element - of the active_handles array. Otherwise, we check the whole of the - handles array, starting at element zero. */ - if( current && active_handles ) { - ihandle = active_handles[ context_level ]; - } else { - ihandle = 0; - } - -/* Loop over the Handles array, starting from the above element. */ - handle = handles + ihandle; - for( ; ihandle < nhandles; ihandle++,handle++ ) { - -/* Skip Handles that have no associated object. */ - if( !handle->ptr ) continue; - -/* Skip handles that are in an unrequired context. */ - if( current && handle->context != context_level ) continue; - -#if defined(THREAD_SAFE) -/* Skip handles that are not locked for use by the current thread. */ - if( handle->thread != AST__THREAD_ID ) continue; -#endif - -/* If required, check that the current handle is for an object of the - specified class. */ - if( class ) { - -/* Skip the handle if no VTAB was found for the requested class. */ - if( !req_vtab ) continue; - -/* Get the generation gap between the current handle's object and the - specified class. */ - generation_gap = astClassCompare( astVTAB( handle->ptr ), req_vtab ); - -/* Skip the handle if it is not for the specified class or a subclass. */ - if( generation_gap < 0 || generation_gap == AST__COUSIN || - ( generation_gap > 0 && !subclass ) ) continue; - } - -/* Get the integer identifier associated with the handle, convert it to a - pointer and append to the end of the KeyMap entry describing the handle's - class. */ - astMapPutElemP( result, astGetClass( handle->ptr ), -1, - astI2P( handle->check ) ); - } - -/* Relinquish access to the handles array. */ - UNLOCK_MUTEX2; - -/* Return the KeyMap. */ - return result; -} - -MYSTATIC void AnnulHandle( int ihandle, int *status ) { -/* -* Name: -* AnnulHandle - -* Purpose: -* Annul a Handle and its associated Object pointer. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* void AnnulHandle( int ihandle, int *status ) - -* Class Membership: -* Object member function. - -* Description: -* This function annuls an active Handle by annulling the Object -* pointer it is associated with, deactivating the Handle and -* returning it to the free Handle list for re-use. -* -* The reference count for the associated Object is decremented by -* this function and the Object will be deleted if this reference -* count falls to zero. - -* Parameters: -* ihandle -* Array offset that identifies the Handle to be annulled in the -* "handles" array. This is fully validated by this function. -* status -* Pointer to the inherited status variable. - -* Notes: -* - The Handle supplied should be active, otherwise an error will -* result and the Handle will not be touched (but no error report -* will be made if the global error status has already been set). -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - AstObject *ptr; /* Object pointer */ - int context; /* Context level where Handle was issued */ - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Check that the handle offset supplied is valid and report an error - if it is not (but only if the global error status has not already - been set). */ - if ( ( ihandle < 0 ) || ( ihandle >= nhandles ) ) { - if ( astOK ) { - astError( AST__INHAN, "astAnnulHandle: Invalid attempt to annul an " - "Object Handle (no. %u).", status, ihandle ); - astError( AST__INHAN, "This Handle number is not valid (possible " - "internal programming error)." , status); - } - -/* If OK, obtain the Handle's context level. */ - } else { - context = handles[ ihandle ].context; - -/* If this indicates that the Handle isn't active, then report an - error (but only if the global error status has not already been - set). We allow handles that are currently not owned by any thread to - be annulled. */ - if ( context < 0 && context != UNOWNED_CONTEXT ) { - if ( astOK ) { - astError( AST__INHAN, "astAnnulHandle: Invalid attempt to annul " - "an Object Handle (no. %u).", status, ihandle ); - astError( AST__INHAN, "This Handle is not active (possible " - "internal programming error)." , status); - } - -/* If the Handle is active, annul its Object pointer. The astAnnul - function may call Delete functions supplied by any class, and these - Delete functions may involve annulling external Object IDs, which in - turn requires access to the handles array. For this reason, we release - the mutex that protects access to the handles arrays so that it can - potentially be re-aquired within astAnnul without causing deadlock. */ - } else { - -#ifdef MEM_DEBUG - astHandleUse( ihandle, "annulled using check value %d ", - handles[ ihandle ].check ); -#endif - - ptr = handles[ ihandle ].ptr; - UNLOCK_MUTEX2; - ptr = astAnnul( ptr ); - LOCK_MUTEX2; - -/* Remove the Handle from the active list for its context level. */ - if( context == UNOWNED_CONTEXT ) { - -#if defined(THREAD_SAFE) - RemoveHandle( ihandle, &unowned_handles, status ); -#else - if( astOK ) astError( AST__INTER, "AnnulHandle: reference to " - "'unowned_handles' in a non-thread-safe context " - "(internal AST programming error).", status ); -#endif - - } else if( active_handles ) { - RemoveHandle( ihandle, &active_handles[ context ], status ); - - } else if( astOK ){ - astError( AST__INTER, "AnnulHandle: active_handles array has " - "not been initialised (internal AST programming error).", - status ); - } - -/* Reset the Handle's "context" value (making it inactive) and its "check" - value (so it is no longer associated with an identifier value). */ - handles[ ihandle ].ptr = NULL; - handles[ ihandle ].context = INVALID_CONTEXT; - handles[ ihandle ].check = 0; -#if defined(THREAD_SAFE) - handles[ ihandle ].thread = -1; -#endif - -/* Place the modified Handle on the free Handles list ready for re-use. */ - InsertHandle( ihandle, &free_handles, status ); - - } - } -} - -AstObject *astAnnulId_( AstObject *this_id, int *status ) { -/* -*+ -* Name: -* AnnulId - -* Purpose: -* Annul an external Object identifier. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astAnnulId( AstObject *this ) - -* Class Membership: -* Object member function. - -* Description: -* This function implements the external (public) interface to the -* astAnnul method. It accepts an active Object identifier, which -* it annuls, causing the associated Handle to be deactivated and -* returned to the free Handles list for re-use. It also causes the -* reference count of the associated Object to be decremented and -* the Object to be deleted if this reference count falls to zero. - -* Parameters: -* this -* The Object identifier to be annulled. - -* Returned Value: -* A NULL C pointer is always returned (this should be translated -* into an identifier value of zero for external use). - -* Notes: -* - This function attempts to execute even if the global error -* status is set. -* - The identifier supplied should be associated with an active -* Object, otherwise an error will result (but no error report will -* be made if the global error status has already been set). -* - This function is invoked via the astAnnul macro for external use. -* For internal use (from protected code which needs to handle external -* IDs) it should be invoked via the astAnnulId macro (since astAnnul -* expects a true C pointer as its argument when used internally). -*- -*/ - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object (this generates an - error if it doesn't). Note, we use "astMakePointer_NoLockCheck", - rather than the usual "astMakePointer" since a thread should be able - to renounce interest in an object without needing to own the object. - If we used "astMakePointer" then a thread could not annul a pointer - unless it owned the object. But having annulled the pointer it could - then not unlock the object for use by another thread (since the - pointer it would need to do this has just been annulled). */ - if ( !astIsAObject( astMakePointer_NoLockCheck( this_id ) ) ) return NULL; - -/* Obtain the Handle offset for this Object and annul the Handle and - its associated Object pointer. Report an error if the handle is - currently owned by a different thread. That is, the *Object* need - not be locked by the current thread (as indicated by the use of - astMakePointer above), but the *handle* must be owned by the current - thread. */ - LOCK_MUTEX2; - AnnulHandle( CheckId( this_id, 1, status ), status ); - UNLOCK_MUTEX2; - -/* Always return a NULL pointer value. */ - return NULL; -} - -MYSTATIC AstObject *AssocId( int ihandle, int *status ) { -/* -* Name: -* AssocId - -* Purpose: -* Associate an identifier value with a Handle. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* AstObject *AssocId( int ihandle ) - -* Class Membership: -* Object member function. - -* Description: -* This function takes a zero-based offset into the "handles" array -* that identifies a Handle associated with an active Object. It -* encodes this into an identifier value to be issued to an -* external user to identify that Handle and its Object, and then -* associates this identifier value with the Handle. - -* Parameters: -* ihandle -* Offset in the "handles" array that identifies the Handle, -* which should be active (i.e. associated with an active -* Object). This function will modify the "check" field in this -* Handle to associate it with the identifier value it returns. - -* Returned Value: -* The resulting identifier value. - -* Notes: -* - The returned identifier value is, in fact, an int. This -* allows the value to be passed easily to other languages -* (e.g. Fortran) and stored as an integer without loss of -* information. -* - The value is stored within C code as type AstObject*. This -* means that C code (e.g. function prototypes, etc.) need not be -* aware that an identifier (as opposed to an Object pointer) is -* being used, even though the actual bit patterns will be -* different. The same C code can then be used for both internal -* and external purposes so long as care is taken to convert -* between the two representations at appropriate points. -* - The reverse operation (conversion of an ID back to a handle -* offset) is performed by CheckId. -* - A zero identifier value will be returned if this function is -* invoked with the global status set or if it should fail for any -* reason. -*/ - -/* Local Variables: */ - AstObject *result; /* Pointer value to return */ - MixedInts test; /* Union for testing encoding */ - MixedInts work; /* Union for encoding ID value */ - -/* Initialise. */ - result = astI2P( 0 ); - -/* Check the global error status. */ - if ( !astOK ) return result; - -/* Copy the Handle offset and clear the lowest 8 bits by shifting - left. */ - work.i = ihandle; - work.u = work.u << 8U; - -/* Make a copy of the result shifted right again. Test if any bits - have been lost in this process. If so, there are too many Handles - in use at once to encode them into IDs, so report an error. */ - test.u = work.u >> 8U; - if ( test.i != ihandle ) { - astError( AST__XSOBJ, "AssocId(%s): There are too many AST Objects in " - "use at once.", status, astGetClass( handles[ ihandle ].ptr ) ); - -/* If OK, scramble the value by exclusive-ORing with the bit pattern - in AST__FAC (a value unique to this library), also shifted left by - 8 bits. This makes it even less likely that numbers from other - sources will be accepted in error as valid IDs. */ - } else { - work.u ^= ( ( (unsigned) AST__FAC ) << 8U ); - -/* Fill the lowest 8 bits with a count of the total number of IDs - issued so far (which we increment here). This makes each ID unique, - so that an old one that identifies a Handle that has been annulled - and re-used (i.e. associated with a new ID) can be spotted. We - only use the lowest 8 bits of this count because this provides - adequate error detection to reveal programming errors and we do not - need higher security than this. We also prevent a count of zero - being used, as this could result in a zero identifier value (this - being reserved as the "null" value). */ - if ( ++nids > 255U ) nids = 1U; - work.u |= nids; - -/* Store the value as a check count in the Handle. This will be used - to validate the ID in future. */ - handles[ ihandle ].check = work.i; - -/* Pack the value into the pointer to be returned. */ - result = astI2P( work.i ); - } - -/* Return the result. */ - return result; -} - -void astBegin_( void ) { -/* -*++ -* Name: -c astBegin -f AST_BEGIN - -* Purpose: -* Begin a new AST context. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astBegin -f CALL AST_BEGIN( STATUS ) - -* Class Membership: -* Object class function. - -* Description: -c This macro invokes a function to begin a new AST context. -c Any Object pointers -f This routine begins a new AST context. Any Object pointers -* created within this context will be annulled when it is later -c ended using astEnd (just as if astAnnul had been invoked), -f ended using AST_END (just as if AST_ANNUL had been invoked), -c unless they have first been exported using astExport or rendered -c exempt using astExempt. If -f unless they have first been exported using AST_EXPORT or rendered -f exempt using AST_EXEMPT. If -* annulling a pointer causes an Object's RefCount attribute to -* fall to zero (which happens when the last pointer to it is -* annulled), then the Object will be deleted. - -f Parameters: -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This macro applies to all Objects. -f This routine applies to all Objects. - -* Notes: -c - astBegin attempts to execute even if the AST error status -c is set on entry. -f - This routine attempts to execute even if STATUS is set to an -f error value. -c - Contexts delimited by astBegin and astEnd may be nested to any -c depth. -f - Contexts delimited by AST_BEGIN and AST_END may be nested to any -f depth. -*-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int stat; /* Copy of global status */ - int *status; /* Pointer to inherited status value */ - -/* Get a pointer to thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Now that the thread-specific data has been initialised, we can get a - pointer to the threads inherited status value. */ - status = astGetStatusPtr; - -/* Save and clear the global status so that memory allocation can be - performed within this function even under error conditions. */ - stat = astStatus; - astClearStatus; - -/* Ensure that the active_handles array has been initialised. */ - if ( !active_handles ) InitContext( status ); - -/* Extend the "active handles" array to accommodate a new context - level. This array contains integer offsets into the "handles" array - to identify the handle which is at the head of the list of active - handles for each context level. */ - astBeginPM; - active_handles = astGrow( active_handles, context_level + 2, - sizeof( int ) ); - astEndPM; - -/* Initialise the array element for the new context level to indicate - an empty Handle list. */ - if ( astOK ) active_handles[ ++context_level ] = -1; - -/* Restore the original global status value. */ - astSetStatus( stat ); -} - -MYSTATIC int CheckId( AstObject *this_id, int lock_check, int *status ) { -/* -* Name: -* CheckId - -* Purpose: -* Check an identifier value and convert it into a Handle offset. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* int CheckId( AstObject *this, int lock_check, int *status ) - -* Class Membership: -* Object member function. - -* Description: -* This function takes an identifier value encoded by AssocId and -* validates it to ensure it is associated with an active -* Handle. If valid, it converts it back into a zero-based offset -* which may be used to access the Handle in the "handles" -* array. Otherwise, an error is reported. - -* Parameters: -* this -* The identifier value to be decoded. -* lock_check -* Should an error be reported if the handle is in an Object -* context for a different thread? -* status -* Pointer to the inherited status variable. - -* Returned Value: -* The resulting Handle offset, or -1 if the identifier is not -* valid or any other error occurs. - -* Notes: -* - This function attempts to execute even if the global error -* status is set, but no further error report will be made if it -* fails under these circumstances. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - MixedInts work; /* Union for decoding ID value */ - int id; /* ID value as an int */ - int ihandle; /* Result to return */ - -#ifdef MEM_DEBUG - int oldok = astOK; -#endif - -/* Initialise. */ - ihandle = -1; - -/* Get a pointer to thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Retrieve the integer Object identifier value from the pointer - supplied. */ - id = astP2I( this_id ); - -/* Check if a value of zero has been supplied and report an error if - it has. */ - if ( !id ) { - if ( astOK ) { - astError( AST__OBJIN, "Invalid Object pointer given (value is " - "zero)." , status); - } - -/* If OK, reverse the encoding process performed by AssocId to - retrieve the Handle offset. */ - } else { - work.i = id; - work.u = ( work.u ^ ( ( (unsigned) AST__FAC ) << 8U ) ) >> 8U; - -/* Check that the offset obtained doesn't extend beyond the limits of - the "handles" array. Report an error if it does. */ - if ( ( work.i < 0 ) || ( work.i >= nhandles ) ) { - if ( astOK ) { - astError( AST__OBJIN, "Invalid Object pointer given (value is " - "%d).", status, id ); - } - -/* See if the "check" field matches the ID value and the Handle is - valid (i.e. is associated with an active Object). If not, the - Handle has been annulled and possibly re-used, so report an - error. */ - } else if ( ( handles[ work.i ].check != id ) || - ( handles[ work.i ].context == INVALID_CONTEXT ) ) { - if ( astOK ) { - astError( AST__OBJIN, "Invalid Object pointer given (value is " - "%d).", status, id ); - astError( AST__OBJIN, "This pointer has been annulled, or the " - "associated Object deleted." , status); - } -#if defined(THREAD_SAFE) - } else if( lock_check && handles[ work.i ].context != UNOWNED_CONTEXT && - handles[ work.i ].thread != AST__THREAD_ID ) { - if ( astOK ) { - astError( AST__OBJIN, "Invalid Object pointer given (value is " - "%d).", status, id ); - astError( AST__OBJIN, "This pointer is currently owned by " - "another thread (possible programming error)." , status); - } -#endif - -/* If OK, set the Handle offset to be returned. */ - } else { - ihandle = work.i; - } - -#ifdef MEM_DEBUG - if ( oldok && !astOK && ( work.i >= 0 ) && ( work.i < nhandles ) ) { - char buf[200]; - astError( astStatus, "Handle properties: %s ", status, - HandleString( work.i, buf ) ); - } -#endif - - } - -/* Return the result. */ - return ihandle; -} - -void astCreatedAtId_( AstObject *this_id, const char **routine, - const char **file, int *line, int *status ){ -/* -c++ -* Name: -* astCreatedAt - -* Purpose: -* Return the routine, file and line number at which an Object was -* created. - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* void astCreatedAt( AstObject *this, const char **routine, -* const char **file, int *line ) - -* Class Membership: -* Object method. - -* Description: -* This function returns pointers to two strings containing the -* name of the routine or function within which the object was created -* and the name of the source file containing that routine. It also -* returns the number of the line within the file at which the object -* was created. It is intended for use in debugging memory leaks etc. -* -* Precisely, the information returned identifies the point at which -* the Object's public identifier (i.e. the supplied pointer) was -* first issued. This may not correspond to the actual creation of the -* Object if the object is contained within some higher level Object. -* For instance, if the astGetFrame method is used to get a pointer to -* a Frame within a FrameSet, the information returned by this -* function if supplied with the Frame pointer would identify the call -* to astGetFrame, rather than the line at which the FrameSet created -* its internal copy of the Frame. Likewise, if this function is used -* to get information from an Object pointer returned by astClone, the -* information will describe the call to astClone, not the call that -* created the original Object. - -* Parameters: -* this -* Pointer to the Object. -* routine -* Address of a pointer to a null terminated C string in which to -* return the routine name (the string will reside in static memory). -* The pointer will be set to NULL on exit if no routine name is -* available. -* file -* Address of a pointer to a null terminated C string in which to -* return the file name (the string will reside in static memory). -* The pointer will be set to NULL on exit if no file name is -* available. -* line -* Address of an int in which to store the line number in the file. -* A line number of zero is returned if no line number is available. - -* Notes: -* - NULL pointers and a line number of zero are returned if an error -* has already occurred prior to calling this function. - -c-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int ihandle; /* Result to return */ - -/* Initialise */ - *routine = NULL; - *file = NULL; - *line = 0; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Obtain the Handle offset for this Object. */ - ihandle = CheckId( this_id, 1, status ); - if ( ihandle != -1 ) { - -/* Copy the required pointers etc to the supplied addresses. */ - *routine = handles[ ihandle ].routine; - *file = handles[ ihandle ].file; - *line = handles[ ihandle ].line; - } - -/* Unlock the mutex that guards access to the handles array */ - UNLOCK_MUTEX2; - -} - -AstObject *astDeleteId_( AstObject *this_id, int *status ) { -/* -*+ -* Name: -* astDeleteId - -* Purpose: -* Delete an Object via an identifier. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astDeleteId_( AstObject *this ) - -* Class Membership: -* Object member function. - -* Description: -* This function implements the external (public) interface to the -* astDelete method. It accepts an active Object identifier and -* deletes the associated Object. Before doing so, it annuls all -* active identifiers associated with the object, deactivates their -* Handles and returns these Handles to the free Handles list for -* re-use. - -* Parameters: -* this -* An identifier for the Object to be deleted. - -* Returned Value: -* A NULL C pointer is always returned (this should be translated -* into an identifier value of zero for external use). - -* Notes: -* - This function attempts to execute even if the global error -* status is set. -* - The identifier supplied should be associated with an active -* Object, otherwise an error will result (but no error report will -* be made if the global error status has already been set). -* - Although this function is documented as "private" and should -* not be invoked directly from outside this class, it is not a -* static function and has a public prototype. This is because it -* must be invoked via the astDelete macro (defined in the -* "object.h" include file) as part of the public interface. -*- -*/ - -/* Local Variables: */ - AstObject *this; /* Pointer to Object */ - int i; /* Loop counter for Handles */ - int ihandle; /* Object Handle offset */ - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object (this generates an - error if it doesn't). */ - if ( !astIsAObject( this = astMakePointer( this_id ) ) ) return NULL; - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Obtain the Handle offset for this Object. */ - ihandle = CheckId( this_id, 1, status ); - if ( ihandle != -1 ) { - -/* Since the Object is to be deleted, we must annul all identifiers - that refer to it. Loop to inspect each currently allocated Handle - in the "handles" array. */ - for ( i = 0; i < nhandles; i++ ) { - -/* Select active handles and test if their Object pointer refers to - the Object to be deleted. */ - if ( ( handles[ i ].context != INVALID_CONTEXT ) && - ( handles[ i ].ptr == this ) ) { - -/* If so, explicitly set the reference count for the Object to 2 so - that it will not be deleted (yet) when we annul the pointer - associated with the Handle. */ - handles[ i ].ptr->ref_count = 2; - -/* Annul the Handle, which frees its resources, decrements the Object - reference count and makes any ID associated with the Handle become - invalid. */ - AnnulHandle( i, status ); - } - } - -/* If required, tell the user that the handle's object has been deleted. */ -#ifdef MEM_DEBUG - astHandleUse( ihandle, "object-deleted" ); -#endif - } - - UNLOCK_MUTEX2; - -/* When all Handles associated with the Object have been annulled, - delete the object itself. This over-rides the reference count and - causes any remaining pointers to the Object (e.g. in internal code - or within other Objects) to become invalid. */ - this = astDelete( this ); - -/* Always return a NULL pointer value. */ - return NULL; -} - -void astEnd_( int *status ) { -/* -*++ -* Name: -c astEnd -f AST_END - -* Purpose: -* End an AST context. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astEnd -f CALL AST_END( STATUS ) - -* Class Membership: -* Object class function. - -* Description: -c This macro invokes a function to end an AST context which was -f This routine ends an AST context which was -c begun with a matching invocation of astBegin. Any Object -f begun with a matching invocation of AST_BEGIN. Any Object -* pointers created within this context will be annulled (just as -c if astAnnul had been invoked) and will cease to be valid -f if AST_ANNUL had been invoked) and will cease to be valid -* afterwards, unless they have previously been exported using -c astExport or rendered exempt using astExempt. -f AST_EXPORT or rendered exempt using AST_EXEMPT. -* If annulling a pointer causes an Object's RefCount attribute to -* fall to zero (which happens when the last pointer to it is -* annulled), then the Object will be deleted. - -* Parameters: -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This macro applies to all Objects. -f This routine applies to all Objects. - -* Notes: -c - astEnd attempts to execute even if the AST error status is set. -f - This routine attempts to execute even if STATUS is set to an -f error value. -c - Contexts delimited by astBegin and astEnd may be nested to any -c depth. -f - Contexts delimited by AST_BEGIN and AST_END may be nested to any -f depth. -*-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int ihandle; /* Offset of Handle to be annulled */ - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Check that the current context level is at least 1, otherwise there - has been no matching use of astBegin, so report an error (unless - the global status has already been set). */ - if ( context_level < 1 ) { - if ( astOK ) { - astError( AST__ENDIN, "astEnd: Invalid use of astEnd without a " - "matching astBegin." , status); - } - -/* If OK, loop while there are still active Handles associated with - the current context level. First gain exclusive access to the handles - array. */ - } else if ( active_handles ) { - LOCK_MUTEX2; - while ( ( ihandle = active_handles[ context_level ] ) != -1 ) { - -/* Annul the Handle at the head of the active Handles list. */ - AnnulHandle( ihandle, status ); - -/* It is just posible that under error conditions inactive Handles - might get left in the active_handles list and AnnulHandle would - then fail. Since this would result in an infinite loop, we check to - see if the handle we have just annulled is still in the list. If - so, transfer it to the free Handles list for re-use. */ - if ( ihandle == active_handles[ context_level ] ) { - RemoveHandle( ihandle, &active_handles[ context_level ], status ); - InsertHandle( ihandle, &free_handles, status ); - } - } - -/* Ensure the context level is decremented unless it was zero to start - with. */ - context_level--; - -/* Relinquish access to the handles array. */ - UNLOCK_MUTEX2; - } - -} - -void astExemptId_( AstObject *this_id, int *status ) { -/* -*++ -* Name: -c astExempt -f AST_EXEMPT - -* Purpose: -* Exempt an Object pointer from AST context handling. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astExempt( AstObject *this ) -f CALL AST_EXEMPT( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function exempts an Object pointer from AST context -f This routine exempts an Object pointer from AST context -c handling, as implemented by astBegin and astEnd. This means that -f handling, as implemented by AST_BEGIN and AST_END. This means that -c the pointer will not be affected when astEnd is invoked and will -f the pointer will not be affected when AST_END is called and will -* remain active until the end of the program, or until explicitly -c annulled using astAnnul. -f annulled using AST_ANNUL. -* -c If possible, you should avoid using this function when writing -f If possible, you should avoid using this routine when writing -* applications. It is provided mainly for developers of other -* libraries, who may wish to retain references to AST Objects in -* internal data structures, and who therefore need to avoid the -c effects of astBegin and astEnd. -f effects of AST_BEGIN and AST_END. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Object pointer to be exempted from context handling. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. -*-- - -* Implementation Notes: -* - This function does not exist in the "protected" interface to -* the Object class and is not available to other class -* implementations. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int context; /* Handle context level */ - int ihandle; /* Offset of Handle in "handles" array */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object. */ - (void) astCheckObject( astMakePointer( this_id ) ); - if ( astOK ) { - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Obtain the Handle offset for this Object. */ - ihandle = CheckId( this_id, 1, status ); - if ( ihandle != -1 ) { - -/* Extract the context level at which the Object was created. */ - context = handles[ ihandle ].context; - -/* Set the new context level to zero, where it cannot be affected by - ending any context. */ - handles[ ihandle ].context = 0; - -/* Remove the object's Handle from its original active Handles list - and insert it into the list appropriate to its new context - level. */ - -#if defined(THREAD_SAFE) - if( context == UNOWNED_CONTEXT ) { - RemoveHandle( ihandle, &unowned_handles, status ); - } else { - RemoveHandle( ihandle, &active_handles[ context ], status ); - } -#else - RemoveHandle( ihandle, &active_handles[ context ], status ); -#endif - - InsertHandle( ihandle, &active_handles[ 0 ], status ); - -/* If required, tell the user that the handle has been exempted. */ -#ifdef MEM_DEBUG - astHandleUse( ihandle, "exempted" ); -#endif - } - - UNLOCK_MUTEX2; - } -} - -void astExportId_( AstObject *this_id, int *status ) { -/* -*++ -* Name: -c astExport -f AST_EXPORT - -* Purpose: -* Export an Object pointer to an outer context. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astExport( AstObject *this ) -f CALL AST_EXPORT( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function exports an Object pointer from the current AST context -f This routine exports an Object pointer from the current AST context -* into the context that encloses the current one. This means that -* the pointer will no longer be annulled when the current context -c is ended (with astEnd), but only when the next outer context (if -f is ended (with AST_END), but only when the next outer context (if -* any) ends. - -* Parameters: -c this -f THIS = INTEGER (Given) -* Object pointer to be exported. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -* Notes: -c - It is only sensible to apply this function to pointers that -f - It is only sensible to apply this routine to pointers that -* have been created within (or exported to) the current context -c and have not been rendered exempt using astExempt. -f and have not been rendered exempt using AST_EXEMPT. -* Applying it to an unsuitable Object pointer has no effect. -*-- - -* Implementation Notes: -* - This function does not exist in the "protected" interface to -* the Object class and is not available to other class -* implementations. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int context; /* Handle context level */ - int ihandle; /* Offset of Handle in "handles" array */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object. */ - (void) astCheckObject( astMakePointer( this_id ) ); - if ( astOK ) { - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Obtain the Handle offset for this Object. */ - ihandle = CheckId( this_id, 1, status ); - if ( ihandle != -1 ) { - -/* Check that the current context level is at least 1 and report an - error if it is not. */ - if ( context_level < 1 ) { - if( astOK ) astError( AST__EXPIN, "astExport(%s): Attempt to export an Object " - "from context level zero.", status, - astGetClass( handles[ ihandle ].ptr ) ); - -/* Extract the context level at which the Object was created. */ - } else { - context = handles[ ihandle ].context; - -/* Check that the Object's existing context level is high enough to be - affected by being exported to the next outer context level. If not, - do nothing. */ - if ( context > ( context_level - 1 ) ) { - -/* Set the new context level. */ - handles[ ihandle ].context = context_level - 1; - -/* Remove the object's Handle from its original active Handles list - and insert it into the list appropriate to its new context - level. */ - RemoveHandle( ihandle, &active_handles[ context ], status ); - InsertHandle( ihandle, &active_handles[ context_level - 1 ], - status ); - -/* If required, tell the user that the handle has been exempted. */ -#ifdef MEM_DEBUG - astHandleUse( ihandle, "exported from context level %d", - context_level ); -#endif - } - } - } - UNLOCK_MUTEX2; - } -} - -void astImportId_( AstObject *this_id, int *status ) { -/* -*++ -* Name: -c astImport -f AST_IMPORT - -* Purpose: -* Import an Object pointer to the current context. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c void astImport( AstObject *this ) -f CALL AST_IMPORT( THIS, STATUS ) - -* Class Membership: -* Object method. - -* Description: -c This function -f This routine -* imports an Object pointer that was created in a higher or lower -* level context, into the current AST context. -* This means that the pointer will be annulled when the current context -c is ended (with astEnd). -f is ended (with AST_END). - -* Parameters: -c this -f THIS = INTEGER (Given) -* Object pointer to be imported. -f STATUS = INTEGER (Given and Returned) -f The global status. - -* Applicability: -* Object -c This function applies to all Objects. -f This routine applies to all Objects. - -*-- - -* Implementation Notes: -* - This function does not exist in the "protected" interface to -* the Object class and is not available to other class -* implementations. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int context; /* Handle context level */ - int ihandle; /* Offset of Handle in "handles" array */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object. */ - (void) astCheckObject( astMakePointer( this_id ) ); - if ( astOK ) { - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Obtain the Handle offset for this Object. */ - ihandle = CheckId( this_id, 1, status ); - if ( ihandle != -1 ) { - -/* Extract the context level at which the Object was created. */ - context = handles[ ihandle ].context; - -/* Do nothing if the Identifier already belongs to the current context. */ - if( context != context_level ) { - -/* Set the new context level. */ - handles[ ihandle ].context = context_level; - -/* Remove the object's Handle from its original active Handles list - and insert it into the list appropriate to its new context - level. */ - RemoveHandle( ihandle, &active_handles[ context ], status ); - InsertHandle( ihandle, &active_handles[ context_level ], status ); - -/* If required, tell the user that the handle has been imported. */ -#ifdef MEM_DEBUG - astHandleUse( ihandle, "imported into context level %d", - context_level ); -#endif - } - } - UNLOCK_MUTEX2; - } -} - -void astLockId_( AstObject *this_id, int wait, int *status ) { -/* -c++ -* Name: -* astLock - -* Purpose: -* Lock an Object for exclusive use by the calling thread. - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* void astLock( AstObject *this, int wait ) - -* Class Membership: -* Object method. - -* Description: -* The thread-safe public interface to AST is designed so that an -* error is reported if any thread attempts to use an Object that it -* has not previously locked for its own exclusive use using this -* function. When an Object is created, it is initially locked by the -* thread that creates it, so newly created objects do not need to be -* explicitly locked. However, if an Object pointer is passed to -* another thread, the original thread must first unlock it (using -* astUnlock) and the new thread must then lock it (using astLock) -* before the new thread can use the Object. -* -* The "wait" parameter determines what happens if the supplied Object -* is curently locked by another thread when this function is invoked. - -* Parameters: -* this -* Pointer to the Object to be locked. -* wait -* If the Object is curently locked by another thread then this -* function will either report an error or block. If a non-zero value -* is supplied for "wait", the calling thread waits until the object -* is available for it to use. Otherwise, an error is reported and -* the function returns immediately without locking the Object. - -* Applicability: -* Object -* This function applies to all Objects. - -* Notes: -* - The astAnnul function is exceptional in that it can be used on -* pointers for Objects that are not currently locked by the calling -* thread. All other AST functions will report an error. -* - The Locked object will belong to the current AST context. -* - This function returns without action if the Object is already -* locked by the calling thread. -* - If simultaneous use of the same object is required by two or more -* threads, astCopy should be used to to produce a deep copy of -* the Object for each thread. Each copy should then be unlocked by -* the parent thread (i.e. the thread that created the copy), and then -* locked by the child thread (i.e. the thread that wants to use the -* copy). -* - This function is only available in the C interface. -* - This function returns without action if the AST library has -* been built without POSIX thread support (i.e. the "-with-pthreads" -* option was not specified when running the "configure" script). -c-- -*/ - -/* This function odes nothing if thread support is not enabvled. */ -#if defined(THREAD_SAFE) - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - AstObject *fail; /* Pointer to Object that failed to lock */ - AstObject *this; /* Pointer to Object */ - int ihandle; /* Index of supplied objetc handle */ - int lstat; /* Local status value */ - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object (this generates an - error if it doesn't). Note, we use the "astMakePointer_NoLockCheck", - since the usual "astMakePointer" macro invokes astCheckLock to report - an error if the Object is not currently locked by the calling thread. */ - if ( !astIsAObject( this = astMakePointer_NoLockCheck( this_id ) ) ) return; - -/* Ensure the global data for this class is accessable. Do not use the - globals pointer stored in "*this" because "*this" may be locked by - another thread and so we would pick up the wrong globals. */ - astGET_GLOBALS(NULL); - -/* Ensure the running thread has sole access to the static handles arrays. */ - LOCK_MUTEX2; - -/* Ensure the Handles arrays have been initialised. */ - if ( !active_handles ) InitContext( status ); - -/* Get the Handle index for the supplied object identifier. No error is - reported if the handle is not curently associated with a thread. - However, an error is reported if the Handle is associated with any - thread other than the running thread. */ - ihandle = CheckId( this_id, 1, status ); - -/* We've finished with the handles arrays, for the moment. */ - UNLOCK_MUTEX2; - -/* Check the object pointer was valid. */ - if( ihandle != -1 ){ - -/* The protected astManageLock function implements the public functions, - astLock and astUnlock. */ - lstat = astManageLock( this, AST__LOCK, wait, &fail ); - if( astOK ) { - if( lstat == 1 ) { - if( fail == this ) { - astError( AST__LCKERR, "astLock(%s): Failed to lock the %s because" - " it is already locked by another thread (programming " - "error).", status, astGetClass( this ), - astGetClass( this ) ); - - } else { - astError( AST__LCKERR, "astLock(%s): Failed to lock the %s because" - " a %s contained within it is already locked by another " - "thread (programming error).", status, - astGetClass( this ), astGetClass( this ), - astGetClass( fail ) ); - } - - } else if( lstat == 2 ) { - astError( AST__LCKERR, "astLock(%s): Failed to lock a POSIX mutex.", status, - astGetClass( this ) ); - -/* If the Object is now locked for the running thread... */ - } else { - -/* We need access to the handles arrays again. */ - LOCK_MUTEX2; - -/* If the supplied handle is not currently assigned to any thread, assign - it to the running thread. */ - if( handles[ ihandle ].context == UNOWNED_CONTEXT ) { - RemoveHandle( ihandle, &unowned_handles, status ); - -#if defined(MEM_DEBUG) - astHandleUse( ihandle, "locked by thread %d at context level %d", - handles[ ihandle ].thread, context_level ); -#endif - - handles[ ihandle ].thread = AST__THREAD_ID; - handles[ ihandle ].context = context_level; - InsertHandle( ihandle, &active_handles[ context_level ], - status ); - } - -/* Finished with the handles arrays again. */ - UNLOCK_MUTEX2; - } - } - } -#endif -} - -void astUnlockId_( AstObject *this_id, int report, int *status ) { -/* -c++ -* Name: -* astUnlock - -* Purpose: -* Unlock an Object for use by other threads. - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* void astUnlock( AstObject *this, int report ) - -* Class Membership: -* Object method. - -* Description: -* Unlocks an Object previously locked using astLock, so that other -* threads can use the Object. See astLock for further details. - -* Parameters: -* this -* Pointer to the Object to be unlocked. -* report -* If non-zero, an error will be reported if the supplied Object, -* or any Object contained within the supplied Object, is not -* currently locked by the running thread. If zero, such Objects -* will be left unchanged, and no error will be reported. - -* Applicability: -* Object -* This function applies to all Objects. - -* Notes: -* - This function attempts to execute even if the global error -* status is set, but no further error report will be made if it -* subsequently fails under these circumstances. -* - All unlocked Objects are excluded from AST context handling until -* they are re-locked using astLock. -* - This function is only available in the C interface. -* - This function returns without action if the Object is not currently -* locked by any thread. If it is locked by the running thread, it is -* unlocked. If it is locked by another thread, an error will be reported -* if "error" is non-zero. -* - This function returns without action if the AST library has -* been built without POSIX thread support (i.e. the "-with-pthreads" -* option was not specified when running the "configure" script). -c-- -*/ - -/* This function odes nothing if thread support is not enabvled. */ -#if defined(THREAD_SAFE) - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - AstErrorContext error_context;/* Info about the current error context */ - AstObject *fail; /* Pointer to Object that failed */ - AstObject *this; /* Pointer to Object */ - int ihandle; /* Index of supplied objetc handle */ - int lstat; /* Local status value */ - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object (this generates an - error if it doesn't). Note, we use the "astMakePointer_NoLockCheck", - since the usual "astMakePointer" macro invokes astCheckLock to report - an error if the Object is not currently locked by the calling thread. */ - if ( !astIsAObject( this = astMakePointer_NoLockCheck( this_id ) ) ) return; - -/* Ensure the global data for this class is accessable. */ - astGET_GLOBALS(this); - -/* Start a new error reporting context. This saves any existing error status - and then clear the status value. It also defer further error reporting. */ - astErrorBegin( &error_context ); - -/* Ensure the running thread has sole access to the static handles arrays. */ - LOCK_MUTEX2; - -/* Ensure the Handles arrays have been initialised. */ - if ( !active_handles ) InitContext( status ); - -/* Get the Handle index for the supplied object identifier. Report an - error if the handle is associated with a different thread (no error - if the handle has no associated thread or is associated with the - current thread). */ - ihandle = CheckId( this_id, 1, status ); - -/* Break the associated of the handle with the current thread so that the - handle is not assigned to any thread. We do this before unlocking the - Object structure (using astManageLock) since as soon as astManageLock - returns, another thread that is waiting for the object to be unlocked - may start up and modify the handle properties. */ - if( ihandle >= 0 && handles[ ihandle ].context >= 0 ) { - RemoveHandle( ihandle, &active_handles[ handles[ ihandle ].context ], - status ); -#if defined(MEM_DEBUG) - astHandleUse( ihandle, "unlocked from thread %d at context " - "level %d", handles[ ihandle ].thread, - handles[ ihandle ].context ); -#endif - handles[ ihandle ].thread = -1; - handles[ ihandle ].context = UNOWNED_CONTEXT; - InsertHandle( ihandle, &unowned_handles, status ); - } - -/* We've finished with the handles arrays, for the moment. */ - UNLOCK_MUTEX2; - -/* Check the supplied object pointer was valid. */ - if( ihandle != -1 ){ - -/* The protected astManageLock function implements the public functions, - astLock and astUnlock. */ - lstat = astManageLock( this, AST__UNLOCK, 0, &fail ); - if( astOK ) { - if( lstat == 1 ) { - if( report ) { - if( fail == this ) { - astError( AST__LCKERR, "astUnlock(%s): Failed to unlock the %s " - "because it is locked by another thread (programming " - "error).", status, astGetClass( this ), - astGetClass( this ) ); - - } else { - astError( AST__LCKERR, "astUnlock(%s): Failed to unlock the %s " - "because a %s contained within it is locked by another " - "thread (programming error).", status, - astGetClass( this ), astGetClass( this ), - astGetClass( fail ) ); - } - } - - } else if( lstat == 3 ) { - astError( AST__LCKERR, "astUnlock(%s): Failed to unlock a POSIX mutex.", status, - astGetClass( this ) ); - - } - } - } - -/* End the error reporting context. If an error has occurred within this - function, then this will display the deferred error messages so long - as there was no error condition on entry to this function. If there - was an error condition on entry, then the original status value will be - re-instated. */ - astErrorEnd( &error_context ); - -#endif -} - -AstObject *astI2P_( int integer, int *status ) { -/* -*+ -* Name: -* astI2P - -* Purpose: -* Pack an integer Object ID into a pointer. - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* AstObject *astI2P( int integer ) - -* Class Membership: -* Object class function. - -* Description: -* This function accepts an integer (int) value representing an -* Object identifier and packs its bit pattern into a pointer value -* (from which it may subsequently be retrieved using astP2I). -* -* These functions should be used to avoid any dependency on -* integer-to-pointer conversions (given that the values are not -* true pointers) which might affect the exchange of Object -* identifier values with other languages, such as Fortran 77, -* where they are stored as integers. - -* Parameters: -* integer -* The integer value to be stored. - -* Returned Value: -* The resulting pointer value (which is not usually a valid C pointer). - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -* - This is a protected function in the sense that it is not -* intended that external users should invoke it directly. It is -* accessible from external code, however, in order that public -* macros invoked from that code can make use of it. -*- -*/ - -/* Local Variables: */ - IdUnion temp; /* Overlapping int and pointer */ - -/* Clear the pointer value in the "temp" IdUnion and then set the - integer part of it to the value to be stored. */ - temp.pointer = zero_ptr; - temp.integer = integer; - -/* Return the resulting pointer value. */ - return temp.pointer; -} - -MYSTATIC void InitContext( int *status ) { -/* -* Name: -* InitContext - -* Purpose: -* Initialise the first AST context level. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* void InitContext( int *status ) - -* Class Membership: -* Object member function. - -* Description: -* This function initialises the first AST context level (the level -* before any call to astBegin has been made). It should be invoked -* once, before any use is made of context levels. - -* Parameters: -* status -* Pointer to the inherited status variable. - -* Parameters: -* None. - -* Notes: -* - This function does nothing after the first successful invocation. -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Check that the active_handles array hasn't already been allocated. */ - if ( !active_handles ) { - -/* Allocate and initialise the "active_handles" array. */ - - astBeginPM; - active_handles = astMalloc( sizeof( int ) ); - astEndPM; - - if ( astOK ) active_handles[ 0 ] = -1; - } -} - -MYSTATIC void InsertHandle( int ihandle, int *head, int *status ) { -/* -* Name: -* InsertHandle - -* Purpose: -* Insert a Handle into a list. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* void InsertHandle( int ihandle, int *head, int *status ) - -* Class Membership: -* Object member function. - -* Description: -* This function inserts a Handle structure into a doubly linked -* list of such structures composed of elements drawn from the -* "handles" array. The new list member is inserted in front of the -* member previously occupying the "head of list" position. - -* Parameters: -* ihandle -* Offset in the "handles" array that identifies the handle to -* be added to the list. -* head -* Address of an int which holds the offset in the "handles" -* array of the element at the head of the list (or -1 if the -* list is empty). This value will be updated to identify the -* new list member. -* status -* Pointer to the inherited status variable. - -* Notes: -* - This function does not perform error chacking and does not -* generate errors. -* - The lists generated by this function use integer offsets into -* the "handles" array for their links, rather than pointers. This -* is because the array may be re-located in memory when it needs -* to be extended, so pointers to its element would not remain -* valid. -* - The list elements are drawn from the "handles" array in the -* first place so that they can be addressed by small integers (the -* offset in the array). This allows references to Handles to be -* encoded along with security information into an integer that is -* sufficiently short to be exported to other languages -* (e.g. Fortran) which might not be able to accommodate -* full-length C pointers. -*/ - - -#if defined(MEM_DEBUG) - char buf[80]; - astHandleUse( ihandle, "about to be inserted into %s (%d)", - HeadString( head, buf ), head ); - CheckList( head, status ); - CheckInList( ihandle, head, 0, status ); -#endif - -/* Check a head pointer was supplied (may not be if an error has - occurred). */ - if( ! head ) return; - -/* If the list is empty, the sole new element points at itself. */ - if ( *head == -1 ) { - handles[ ihandle ].flink = ihandle; - handles[ ihandle ].blink = ihandle; - -/* Otherwise, insert the new element in front of the element at the - head of the list. */ - } else { - handles[ ihandle ].flink = *head; - handles[ ihandle ].blink = handles[ *head ].blink; - handles[ ( handles[ *head ].blink) ].flink = ihandle; - handles[ *head ].blink = ihandle; - } - -/* Update the list head to identify the new element. */ - *head = ihandle; - -#if defined(MEM_DEBUG) - CheckList( head, status ); - astHandleUse( ihandle, "has been inserted into %s", buf ); -#endif -} - -AstObject *astMakeId_( AstObject *this, int *status ) { -/* -*+ -* Name: -* astMakeId - -* Purpose: -* Issue an identifier for an Object. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astMakeId( AstObject *this ) - -* Class Membership: -* Object member function. - -* Description: -* This function takes a normal C pointer to an Object and -* associates an identifier with it. - -* Parameters: -* this -* Pointer to an Object. Note that this function copies this -* value (it is not cloned), so the caller should not annul the -* pointer afterwards. - -* Returned Value: -* The resulting identifier value. - -* Notes: -* - An identifier value of zero will be returned and the supplied -* Object pointer will be annulled if this function is invoked with -* the global error status set or if it should fail for any reason. -* - A zero identifier value will also be returned if a NULL object -* pointer is supplied, but this will not provoke an error. -* - This is a protected function in the sense that it is not -* intended that external users should invoke it directly. It is -* accessible from external code, however, in order that public -* macros invoked from that code can make use of it. -*- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - AstObject *id; /* ID value to return */ - int ihandle; /* Handle offset */ - -/* Initialise. */ - id = astI2P( 0 ); - ihandle = 0; - -/* Check the global error status. */ - if ( astOK ) { - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(this); - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* If a non-NULL Object pointer was given, we must obtain a Handle - structure to associate with it (otherwise a zero identifier value - is returned without error). */ - if ( this ) { - -/* If the free Handles list is not empty, obtain a Handle from it. */ - if ( free_handles != -1 ) { - ihandle = free_handles; - RemoveHandle( ihandle, &free_handles, status ); - -/* Otherwise, allocate a new Handle by extending the "handles" array - and using the offset of the new element. */ - } else { - - astBeginPM; - handles = astGrow( handles, nhandles + 1, sizeof( Handle ) ); - astEndPM; - - if ( astOK ) { - ihandle = nhandles++; - - handles[ ihandle ].ptr = NULL; - handles[ ihandle ].context = INVALID_CONTEXT; - handles[ ihandle ].check = 0; - handles[ ihandle ].flink = -1; - handles[ ihandle ].blink = -1; - handles[ ihandle ].line = 0; - handles[ ihandle ].file = NULL; - handles[ ihandle ].routine = NULL; -#if defined(THREAD_SAFE) - handles[ ihandle ].thread = 0; -#endif - -#if defined(MEM_DEBUG) - handles[ ihandle ].id = 0; - handles[ ihandle ].vtab = NULL; -#endif - } - } - -/* If the first AST context level has not yet been initialised, invoke - InitContext to initialise it and allocate memory for the - "active_handles" array which stores context information. */ - if ( astOK ) { - if ( !active_handles ) InitContext( status ); - -/* Store the Object pointer and current context level in the Handle. */ - if ( astOK ) { - handles[ ihandle ].ptr = this; - handles[ ihandle ].context = context_level; -#if defined(THREAD_SAFE) - handles[ ihandle ].thread = AST__THREAD_ID; -#endif - -/* Store information that records where the Handle is created - routine - name, file name and line number. */ - astGetAt( &handles[ ihandle ].routine, - &handles[ ihandle ].file, - &handles[ ihandle ].line ); - -/* Store extra debugging information in the handle if enabled */ -#if defined(MEM_DEBUG) - handles[ ihandle ].id = astMemoryId( this ); - handles[ ihandle ].vtab = this->vtab; - astHandleUse( ihandle, "associated with a %s (id %d)", - astGetClass( this ), astMemoryId( this )); -#endif - -/* Insert the Handle into the active Handles list for the current - context level. */ - InsertHandle( ihandle, &active_handles[ context_level ], status ); - -/* Associate an identifier value with the Handle. */ - id = AssocId( ihandle, status ); - -/* If an error occurred, clean up by annulling the Handle. This - ensures that the Object pointer is annulled and returns the unused - Handle to the Free Handle list. */ - if ( !astOK ) { - AnnulHandle( ihandle, status ); - this = NULL; - } - -/* If the Handle wasn't used (because of an earlier error), return it - to the free Handles list. */ - } else { - InsertHandle( ihandle, &free_handles, status ); - } - } - } - UNLOCK_MUTEX2; - } - -/* If a bad status value was either supplied or generated within this - function, then annul the supplied pointer (unless it is NULL). */ - if ( !astOK && this ) (void) astAnnul( this ); - -/* Return the identifier value. */ - return id; -} - -AstObject *astMakePointer_( AstObject *this_id, int *status ) { -/* -*+ -* Name: -* astMakePointer - -* Purpose: -* Obtain a true C pointer from an Object identifier. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astMakePointer( AstObject *this ) - -* Class Membership: -* Object class function. - -* Description: -* This function accepts an external Object identifier and returns -* a true C Object pointer that may be de-referenced to access the -* Object's data and methods. - -* Parameters: -* this -* The identifier value. - -* Returned Value: -* The true C pointer value. - -* Notes: -* - In a thread-safe context, an error is reported if the supplied -* Object has not been locked by the calling thread (using astLock) -* prior to invoking this function. -* - The object reference count is not modified by this function, -* so the returned pointer should not be annulled by the caller. -* - Typically, this function should be used whenever a public -* function must accept identifier values directly (rather than -* having them translated automatically into pointers during -* argument validation by the astCheck<Class> range of functions). -* - Note that this function will NOT accept a true C pointer as an -* argument, even when invoked from internal code (with astCLASS -* defined). An identifier value MUST be supplied, and an error -* will result if it is not associated with an active Object. -* - This function attempts to execute even if the global error -* status is set, but no further error report will be made if it -* subsequently fails under these circumstances. -* - This is a protected function in the sense that it is not -* intended that external users should invoke it directly. It is -* accessible from external code, however, in order that public -* macros invoked from that code can make use of it. -*- -*/ - -/* Local Variables: */ - AstObject *ptr; /* Pointer value to return */ - int ihandle; /* Handle offset in "handles" array */ - -/* Initialise. */ - ptr = NULL; - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Validate the identifier supplied and derive the Handle offset. */ - ihandle = CheckId( this_id, 1, status ); - -/* If the identifier was valid, extract the Object pointer from the - Handle. */ - if ( ihandle != -1 ) ptr = handles[ ihandle ].ptr; - - UNLOCK_MUTEX2; - -/* Return the result. */ - return ptr; -} - -AstObject *astMakePointer_NoLockCheck_( AstObject *this_id, int *status ) { -/* -*+ -* Name: -* astMakePointer_NoLockCheck - -* Purpose: -* Obtain a true C pointer from an Object identifier. - -* Type: -* Protected function. - -* Synopsis: -* #include "object.h" -* AstObject *astMakePointer_NoLockCheck( AstObject *this ) - -* Class Membership: -* Object class function. - -* Description: -* This function accepts an external Object identifier and returns -* a true C Object pointer that may be de-referenced to access the -* Object's data and methods. -* -* It is identicial to astMakePointer except that it does not check -* that the supplied Object is locked by the running thread. - -* Parameters: -* this -* The identifier value. - -* Returned Value: -* The true C pointer value. - -* Notes: -* - The object reference count is not modified by this function, -* so the returned pointer should not be annulled by the caller. -* - Typically, this function should be used whenever a public -* function must accept identifier values directly (rather than -* having them translated automatically into pointers during -* argument validation by the astCheck<Class> range of functions). -* - Note that this function will NOT accept a true C pointer as an -* argument, even when invoked from internal code (with astCLASS -* defined). An identifier value MUST be supplied, and an error -* will result if it is not associated with an active Object. -* - This function attempts to execute even if the global error -* status is set, but no further error report will be made if it -* subsequently fails under these circumstances. -* - This is a protected function in the sense that it is not -* intended that external users should invoke it directly. It is -* accessible from external code, however, in order that public -* macros invoked from that code can make use of it. -*- -*/ - -/* Local Variables: */ - AstObject *ptr; /* Pointer value to return */ - int ihandle; /* Handle offset in "handles" array */ - -/* Initialise. */ - ptr = NULL; - -/* Gain exclusive access to the handles array. */ - LOCK_MUTEX2; - -/* Validate the identifier supplied and derive the Handle offset. */ - ihandle = CheckId( this_id, 0, status ); - -/* If the identifier was valid, extract the Object pointer from the - Handle. */ - if ( ihandle != -1 ) ptr = handles[ ihandle ].ptr; - - UNLOCK_MUTEX2; - -/* Return the result. */ - return ptr; -} - -int astP2I_( AstObject *pointer, int *status ) { -/* -*+ -* Name: -* astP2I - -* Purpose: -* Extract an integer Object ID from a pointer. - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* int astP2I( AstObject *pointer ) - -* Class Membership: -* Object class function. - -* Description: -* This function retrieves an integer (int) value representing an -* Object identifier from a pointer value (into which it has -* previously been packed using astI2P). -* -* These functions should be used to avoid any dependency on -* integer-to-pointer conversions (given that the values are not -* true pointers) which might affect the exchange of Object -* identifier values with other languages, such as Fortran 77, -* where they are stored as integers. - -* Parameters: -* pointer -* The pointer value into which the ID has previously been packed. - -* Returned Value: -* The extracted Object identifier value as an integer (int). - -* Notes: -* - This function does not perform error checking and does not -* generate errors. -* - This is a protected function in the sense that it is not -* intended that external users should invoke it directly. It is -* accessible from external code, however, in order that public -* macros invoked from that code can make use of it. -*- -*/ - -/* Local Variables: */ - IdUnion temp; /* Overlapping int and pointer */ - -/* Store the pointer value supplied. */ - temp.pointer = pointer; - -/* Return the integer part of it. */ - return temp.integer; -} - -MYSTATIC void RemoveHandle( int ihandle, int *head, int *status ) { -/* -* Name: -* RemoveHandle - -* Purpose: -* Remove a Handle from a list. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* void RemoveHandle( int ihandle, int *head ) - -* Class Membership: -* Object member function. - -* Description: -* This function removes a Handle structure from a doubly linked -* list of such structures composed of elements drawn from the -* "handles" array. The "head of list" position is updated if -* necessary. - -* Parameters: -* ihandle -* Offset in the "handles" array that identifies the Handle to -* be removed from the list (note that the Handle must actually -* be in the list, although this function does not check this). -* head -* Address of an int which holds the offset in the "handles" -* array of the element at the head of the list. This value will -* be updated if necessary to identify the new list head (or set -* to -1 if removing the Handle causes the list to become -* empty). - -* Notes: -* - This function does not perform error chacking and does not -* generate errors. -* - See the InsertHandle function for details of how and why lists -* of Handles are constructed. -*/ - - -#if defined(MEM_DEBUG) - char buf[80]; - astHandleUse( ihandle, "about to be removed from %s", HeadString( head, buf ) ); - CheckList( head, status ); - CheckInList( ihandle, head, 1, status ); -#endif - -/* Check a head pointer was supplied (may not be if an error has - occurred). */ - if( ! head ) return; - -/* Remove the Handle from the list by re-establishing links between - the elements on either side of it. */ - handles[ ( handles[ ihandle ].blink ) ].flink = handles[ ihandle ].flink; - handles[ ( handles[ ihandle ].flink ) ].blink = handles[ ihandle ].blink; - -/* If the element removed was at the head of the list, update the head - of list offset to identify the following element. */ - if ( ihandle == *head ) { - *head = handles[ ihandle ].flink; - -/* If the head of list still identifies the removed element, then note - that the list is now empty. */ - if ( *head == ihandle ) *head = -1; - } - -/* Make the removed element point at itself. */ - handles[ ihandle ].flink = ihandle; - handles[ ihandle ].blink = ihandle; - -#if defined(MEM_DEBUG) - astHandleUse( ihandle, "has been removed from %s", buf ); - CheckList( head, status ); -#endif -} - -void astSetId_( void *this_id_void, const char *settings, ... ) { -/* -* Name: -* astSetId_ - -* Purpose: -* Set values for an Object's attributes via an identifier. - -* Type: -* Private function. - -* Synopsis: -* #include "object.h" -* void astSetId_( AstObject *this, const char *settings, ... ) - -* Class Membership: -* Object member function. - -* Description: -* This function implements the axternal interface to the astSet -* method (q.v.). It accepts an Object identifier, but otherwise -* behaves identically to astSet. - -* Parameters: -* this -* Object identifier. -* settings -* Pointer to a null-terminated string containing a -* comma-separated list of attribute settings. -* ... -* Optional arguments which supply values to be substituted for -* any "printf"-style format specifiers that appear in the -* "settings" string. - -* Notes: -* - Because this function has a variable argument list, it is -* invoked by a macro that evaluates to a function pointer (not a -* function invocation) and no checking or casting of arguments is -* performed before the function is invoked. Because of this, the -* Object identifier is of type (void *) and is converted and -* validated within the function itself. -*/ - -/* Local Variables: */ - AstObject *this; /* Pointer to the Object structure */ - int *status; /* Pointer to inherited status variable */ - va_list args; /* Variable argument list */ - -/* Get a pointer to the integer holding the inherited status value. */ - status = astGetStatusPtr; - -/* Check the global error status. */ - if ( !astOK ) return; - -/* Obtain the Object pointer from the ID supplied and validate the - pointer to ensure it identifies a valid Object. */ - this = astCheckObject( astMakePointer( this_id_void ) ); - if ( astOK ) { - -/* Obtain the variable argument list and pass all arguments to the - astVSet method for interpretation. */ - va_start( args, settings ); - astVSet( this, settings, NULL, args ); - va_end( args ); - } -} - -int astThreadId_( AstObject *this_id, int ptr, int *status ) { -/* -c++ -* Name: -* astThread - -* Purpose: -* Determine the thread that owns an Object. - -* Type: -* Public function. - -* Synopsis: -* #include "object.h" -* int astThread( AstObject *this, int ptr ) - -* Class Membership: -* Object method. - -* Description: -* Returns an integer that indicates whether the supplied Object (or -* Object pointer) is currently unlocked, or is currently locked by -* the running thread, or another thread. - -* Parameters: -* this -* Pointer to the Object to be checked. -* ptr -* If non-zero, returns information about the supplied Object -* pointer, rather than the Object structure itself. See "Object -* Pointers and Structures" below. - -* Returned Value: -* astThread() -* A value of AST__UNLOCKED is returned if the Object (or pointer) -* is currently unlocked (i.e. has been unlocked using astUnlock -* but has not yet been locked using astLock). A value of -* AST__RUNNING is returned if the Object (or pointer) is currently -* locked by the running thread. A value of AST__OTHER is returned -* if the Object (or pointer) is currently locked by the another -* thread. - -* Object Pointers and Structures: -* At any one time, an AST Object can have several distinct pointers, -* any one of which can be used to access the Object structure. For -* instance, the astClone function will produce a new distinct pointer -* for a given Object. In fact, an AST "pointer" is not a real pointer -* at all - it is an identifier for a "handle" structure, encoded to -* make it look like a pointer. Each handle contains (amongst othere -* things) a "real" pointer to the Object structure. This allows more -* than one handle to refer to the same Object structure. So when you -* call astClone (for instance) you get back an identifier for a new -* handle that refers to the same Object as the supplied handle. -* -* In order to use an Object for anything useful, it must be locked -* for use by the running thread (either implicitly at creation or -* explicitly using astLock). The identity of the thread is stored in -* both the Object structure, and in the handle that was passed to -* astLock (or returned by the constructor function). Thus it is -* possible for a thread to have active pointers for Objects that are -* currently locked by another thread. In general, if such a pointer is -* passed to an AST function an error will be reported indicating that -* the Object is currently locked by another thread. The two exceptions -* to this is that astAnnul can be used to annull such a pointer, and -* this function can be used to return information about the pointer. -* -* The other practical consequence of this is that when astEnd is -* called, all active pointers currently owned by the running thread -* (at the current context level) are annulled. This includes pointers -* for Objects that are currently locked by other threads. -* -* If the "ptr" parameter is zero, then the returned value describes -* the Object structure itself. If "ptr" is non-zero, then the returned -* value describes the supplied Object pointer (i.e. handle), rather -* than the Object structure. - -* Notes: -* - This function attempts to execute even if the global error -* status is set, but no further error report will be made if it -* subsequently fails under these circumstances. -* - This function is only available in the C interface. -* - This function always returns AST__RUNNING if the AST library has -* been built without POSIX thread support (i.e. the "-with-pthreads" -* option was not specified when running the "configure" script). -c-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS /* Thread-specific global data */ - int result; /* The returned value */ - -#if defined(THREAD_SAFE) - -/* More local Variables: */ - AstObject *this; - int ihandle; - int check; - -/* Ensure global variables are accessable. */ - astGET_GLOBALS(NULL); -#endif - -/* Initialise the returned value */ - result = AST__RUNNING; - -/* Nothing more to do if AST was not build with thread support. */ -#if defined(THREAD_SAFE) - -/* If the ownership of the handle is being queried... */ - if( ptr ) { - -/* Lock the mutex that guards access to the handles array */ - LOCK_MUTEX2; - -/* Check the supplied object identifier is valid and get the - corresponding index into the handles array. */ - ihandle = CheckId( this_id, 1, status ); - if( ihandle != -1 ) { - -/* Set the returned value on the basis of the threa didentifier stored in - the handle structure. */ - if( handles[ ihandle ].thread == -1 ) { - result = AST__UNLOCKED; - } else if( handles[ ihandle ].thread != AST__THREAD_ID ) { - result = AST__OTHER; - } - } - -/* Unlock the mutex that guards access to the handles array */ - UNLOCK_MUTEX2; - -/* Otherwise, the ownership of the Object is being queried. Obtain the - Object pointer from the ID supplied and validate the pointer to ensure - it identifies a valid Object (this generates an error if it doesn't). - Note, we use the "astMakePointer_NoLockCheck", since the usual - "astMakePointer" macro invokes astCheckLock to report an error if the - Object is not currently locked by the calling thread. */ - } else if( astIsAObject( this = astMakePointer_NoLockCheck( this_id ) ) ) { - -/* Determine which thread (if any) has the object locked, and set an - appropriate return value. */ - check = astManageLock( this, AST__CHECKLOCK, 0, NULL ); - - if( check == 5 ) { - result = AST__OTHER; - } else if( check == 6 ) { - result = AST__UNLOCKED; - } - } - -#endif - -/* Return the result. */ - return result; -} - -int astVersion_( int *status ) { -/* -*++ -* Name: -c astVersion -f AST_VERSION - -* Purpose: -* Return the version of the AST library being used. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c int astVersion -f RESULT = AST_VERSION() - -* Class Membership: -* Object class function. - -* Description: -c This macro invokes a function which -f This function -* returns an integer representing the version of the AST library -* being used. The library version is formatted as a string such as -* "2.0-7" which contains integers representing the "major version" (2), -* the "minor version" (0) and the "release" (7). The integer returned -* by this function combines all three integers together into a single -* integer using the expresion: -* -* (major version)*1E6 + (minor version)*1E3 + (release) - -* Returned Value: -c astVersion -f AST_VERSION = INTEGER -* The major version, minor version and release numbers for the AST -* library, encoded as a single integer. - -* Applicability: -* Object -c This macro applies to all Objects. -f This routine applies to all Objects. - -*-- -*/ - - return (int) AST__VMAJOR*1E6 + AST__VMINOR*1E3 + AST__RELEASE; -} - -int astEscapes_( int new_value, int *status ) { -/* -*++ -* Name: -c astEscapes -f AST_ESCAPES - -* Purpose: -* Control whether graphical escape sequences are included in strings. - -* Type: -* Public function. - -* Synopsis: -c #include "object.h" -c int astEscapes( int new_value ) -f RESULT = AST_ESCAPES( NEWVAL, STATUS ) - -* Class Membership: -* Object class function. - -* Description: -* The Plot class defines a set of escape sequences which can be -* included within a text string in order to control the appearance of -* sub-strings within the text. See the Escape attribute for a -* description of these escape sequences. It is usually inappropriate -* for AST to return strings containing such escape sequences when -* called by application code. For instance, an application which -* displays the value of the Title attribute of a Frame usually does -* not want the displayed string to include potentially long escape -* sequences which a human read would have difficuly interpreting. -* Therefore the default behaviour is for AST to strip out such escape -* sequences when called by application code. This default behaviour -* can be changed using this function. - -* Parameters: -c new_value -f NEWVAL = INTEGER (Given) -* A flag which indicates if escapes sequences should be included -* in returned strings. If zero is supplied, escape sequences will -* be stripped out of all strings returned by any AST function. If -* a positive value is supplied, then any escape sequences will be -* retained in the value returned to the caller. If a negative -* value is supplied, the current value of the flag will be left -* unchanged. - -* Returned Value: -c astEscapes -f AST_ESCAPES = INTEGER -* The value of the flag on entry to this function. - -* Applicability: -* Object -c This macro applies to all Objects. -f This routine applies to all Objects. - -* Notes: -* - This function also controls whether the -c astStripEscapes -f AST_STRIPESCAPES -* function removes escape sequences from the supplied string, or -* returns the supplied string without change. -* - This function attempts to execute even if an error has already -* occurred. - -*-- -*/ - -/* Local Variables: */ - astDECLARE_GLOBALS - int old_val; - -/* Get a pointer to Thread-specific global data. */ - astGET_GLOBALS(NULL); - -/* Save the old value. */ - old_val = retain_esc; - -/* Set the new value. */ - if( new_value > 0 ) { - retain_esc = 1; - - } else if( new_value == 0 ) { - retain_esc = 0; - } - -/* Return the old value. */ - return old_val; -} - - -#if defined(MEM_DEBUG) - -/* Check each handle in a list is uniquely connected to one other handle - in both the forward and backward directions. */ - -void CheckList( int *head, int *status ) { - int ok; - int ihandle; - char buf[200]; - astDECLARE_GLOBALS - if( !astOK ) return; - - astGET_GLOBALS(NULL); - - ok = 1; - if ( *head != -1 ) { - ihandle = *head; - if( handles[ handles[ ihandle ].blink ].flink != ihandle || - handles[ handles[ ihandle ].flink ].blink != ihandle ) { - ok = 0; - - } else { - if( CheckThread( ihandle, head, status ) ) { - ihandle= handles[ *head ].blink; - while( ihandle != *head ) { - if( handles[ handles[ ihandle ].blink ].flink != ihandle || - handles[ handles[ ihandle ].flink ].blink != ihandle || - CheckThread( ihandle, head, status ) == 0 ) { - ok = 0; - break; - } - ihandle= handles[ ihandle ].blink; - } - } - } - } - - if( !ok ) { - printf("CheckList error in %s\n", HeadString( head, buf ) ); - printf(" Central handle: %s\n", HandleString( ihandle, buf ) ); - - if( handles[ handles[ ihandle ].blink ].flink != ihandle ) { - printf(" Central handle->blink: %s\n", - HandleString( handles[ ihandle ].blink, buf ) ); - printf(" Central handle->blink->flink: %s\n", - HandleString( handles[ handles[ ihandle ].blink ].flink, buf ) ); - } - - if( handles[ handles[ ihandle ].flink ].blink != ihandle ) { - printf(" Central handle->flink: %s\n", - HandleString( handles[ ihandle ].flink, buf ) ); - printf(" Central handle->flink->blink: %s\n", - HandleString( handles[ handles[ ihandle ].flink ].blink, buf ) ); - } - } - -} - - -/* Check if a specified handle is, or is not, in a given list of handles. */ - -void CheckInList( int ihandle, int *head, int in, int *status ){ - char list[80], buf[200]; - int found = 0; - if( !astOK ) return; - - if ( *head != -1 ) { - if( ihandle == *head ) { - found = 1; - } else { - if( CheckThread( ihandle, head, status ) ) { - int jhandle= handles[ *head ].blink; - while( jhandle != *head ) { - if( ihandle == jhandle ) { - found = 1; - break; - } - jhandle= handles[ jhandle ].blink; - } - } - } - } - - if( in && !found ) { - printf("Error: Handle %s not in %s\n", HandleString( ihandle, buf ), - HeadString( head, list ) ); - } else if( !in && found ) { - printf("Error: Handle %s is in %s\n", HandleString( ihandle, buf ), - HeadString( head, list ) ); - } - -} - -/* Check that a handle is owned by the currently executing thread. */ - -int CheckThread( int ihandle, int *head, int *status ) { - int result = 1; - -#if defined(THREAD_SAFE) - - char buf[200]; - astDECLARE_GLOBALS - if( !astOK ) return result; - - astGET_GLOBALS(NULL); - - if( *head == unowned_handles ) { - if( handles[ ihandle ].thread != -1 ) { - printf("Handle %s has wrong thread: is %d, should " - "be -1 (i.e. unowned)\n", HandleString( ihandle, buf ), - handles[ ihandle ].thread ); - - result = 0; - } - - } else if( *head == free_handles ) { - if( handles[ ihandle ].thread != -1 ) { - printf("Handle %s has wrong thread: is %d, should " - "be -1 (i.e. free)\n", HandleString( ihandle, buf ), - handles[ ihandle ].thread ); - result = 0; - } - - } else if( handles[ ihandle ].thread != AST__THREAD_ID ) { - printf("Handle %s has wrong thread: is %d, should " - "be %d\n", HandleString( ihandle, buf ), - handles[ ihandle ].thread, AST__THREAD_ID ); - result = 0; - } - -#endif - - return result; -} - -void astWatchHandle_( int handle ){ - Watched_Handle = handle; -} - -void astHandleUse_( int handle, const char *verb, ... ){ - va_list args; - if( handle == Watched_Handle ) { - va_start( args, verb ); - astHandleAlarm( verb, args ); - va_end( args ); - } -} - -void astHandleAlarm_( const char *verb, va_list args ){ - char buff[200], hbuf[200]; - astDECLARE_GLOBALS - astGET_GLOBALS(NULL); - - vsprintf( buff, verb, args ); - -#if defined(THREAD_SAFE) - printf( "astHandleAlarm: Handle %s %s (current thread is %d).\n\n", - HandleString( Watched_Handle, hbuf ), buff, AST__THREAD_ID ); -#else - printf( "astHandleAlarm: Handle %s %s.\n\n", - HandleString( Watched_Handle, hbuf ), buff ); -#endif -} - -MYSTATIC const char *HandleString( int ihandle, char *buf ){ -#if defined(THREAD_SAFE) - astDECLARE_GLOBALS - astGET_GLOBALS(NULL); - - if( ihandle >= 0 ) { - sprintf( buf, "(index:%d v:%d c:%d t:%d i:%d cl:%s) [cur. thread: %d]", - ihandle, - handles[ ihandle ].check, - handles[ ihandle ].context, handles[ ihandle ].thread, - handles[ ihandle ].id, - handles[ ihandle ].vtab ? handles[ ihandle ].vtab->class : "<none>", - AST__THREAD_ID ); - } else { - sprintf( buf, "(index:%d <invalid>) [cur. thread: %d]", ihandle, - AST__THREAD_ID ); - } - -#else - if( ihandle >= 0 ) { - sprintf( buf, "(index:%d v:%d c:%d i:%d cl:%s)", ihandle, - handles[ ihandle ].check, - handles[ ihandle ].context, handles[ ihandle ].id, - handles[ ihandle ].vtab ? handles[ ihandle ].vtab->class : "<none>" ); - } else { - sprintf( buf, "(index:%d <invalid>)", ihandle ); - } -#endif - return buf; -} - -MYSTATIC const char *HeadString( int *head, char *list ){ - int i; - astDECLARE_GLOBALS - astGET_GLOBALS(NULL); - - if( head == &free_handles ) { - strcpy( list, "free_handles" ); - -#if defined(THREAD_SAFE) - } else if( head == &unowned_handles ) { - strcpy( list, "unowned_handles" ); -#endif - - } else { - *list = 0; - for( i = 0; i <= context_level; i++ ) { - if( *head == active_handles[ i ] ) { - sprintf( list, "active_handles[%d]", i ); - break; - } - } - if( *list == 0 ) sprintf( list, "unknown handles list with head %d", - *head ); - } - return list; -} - -#endif |