/****************************************************************************
* *
* * This file is part of GAP , a system for computational discrete algebra .
* *
* * Copyright of GAP belongs to its developers , whose names are too numerous
* * to list here . Please refer to the COPYRIGHT file for details .
* *
* * SPDX - License - Identifier : GPL - 2 . 0 - or - later
* *
* * This file contains the functions of the objects package .
*/
#include "objects.h"
#include "bool.h"
#include "calls.h"
#include "error.h"
#include "gapstate.h"
#include "gvars.h"
#include "io.h"
#include "lists.h"
#include "modules.h"
#include "opers.h"
#include "plist.h"
#include "precord.h"
#include "records.h"
#include "saveload.h"
#include "stringobj.h"
#ifdef HPCGAP
#include "hpc/aobjects.h"
#include "hpc/guards.h"
#include "hpc/thread.h"
#include "hpc/traverse.h"
#include <stdio.h> // for sprintf
#include <stdlib.h> // for getenv
#endif
#if defined (USE_THREADSAFE_COPYING)
#include "hpc/traverse.h"
#endif
enum {
MAXPRINTDEPTH = 64 ,
};
static ModuleStateOffset ObjectsStateOffset = -1 ;
typedef struct {
UInt PrintObjDepth;
Obj PrintObjThiss[MAXPRINTDEPTH];
Int PrintObjIndices[MAXPRINTDEPTH];
// This variable is used to allow a ViewObj method to call PrintObj on the
// same object without triggering use of '~'. It contains one of the
// values 0, 1 and 2 according to whether ...
// 0: there is no enclosing call to PrintObj or ViewObj still open, or
// 1: the innermost such is PrintObj, or
// 2: the innermost such is ViewObj.
UInt LastPV;
} ObjectsModuleState;
static Int lastFreePackageTNUM = FIRST_PACKAGE_TNUM;
static Obj TYPE_KERNEL_OBJECT;
/****************************************************************************
* *
* V NameOfType [ < type > ] . . . . . . . . . . . . . . . . . . . . names of types
* *
* * ' NameOfType [ < type > ] ' is the name of the type < type > .
*/
static const char * NameOfType[NUM_TYPES];
/****************************************************************************
* *
* F RegisterPackageTNUM ( < name > , < typeObjFunc > )
* *
* * Allocates a TNUM for use by a package . The parameters < name > and
* * < typeObjFunc > are used to initialize the relevant entries in the
* * InfoBags and TypeObjFuncs arrays .
* *
* * If allocation fails ( e . g . because no more TNUMs are available ) ,
* * a negative value is returned .
*/
Int RegisterPackageTNUM( const char *name, Obj (*typeObjFunc)(Obj obj) )
{
#ifdef HPCGAP
HashLock(0 );
#endif
if (lastFreePackageTNUM > LAST_PACKAGE_TNUM)
return -1 ;
Int tnum = lastFreePackageTNUM++;
#ifdef HPCGAP
HashUnlock(0 );
#endif
SET_TNAM_TNUM(tnum, name);
TypeObjFuncs[tnum] = typeObjFunc;
return tnum;
}
const Char * TNAM_TNUM(UInt tnum)
{
return NameOfType[tnum];
}
void SET_TNAM_TNUM(UInt tnum, const Char *name)
{
GAP_ASSERT(NameOfType[tnum] == 0 );
NameOfType[tnum] = name;
}
/****************************************************************************
* *
* F FuncFAMILY_TYPE ( < self > , < type > ) . . . . . . handler for ' FAMILY_TYPE '
*/
static Obj FuncFAMILY_TYPE(Obj self, Obj type)
{
return FAMILY_TYPE( type );
}
/****************************************************************************
* *
* F FuncFAMILY_OBJ ( < self > , < obj > ) . . . . . . . handler for ' FAMILY_OBJ '
*/
static Obj FuncFAMILY_OBJ(Obj self, Obj obj)
{
return FAMILY_OBJ( obj );
}
/****************************************************************************
* *
* F TYPE_OBJ ( < obj > ) . . . . . . . . . . . . . . . . . . . type of an object
* *
* * ' TYPE_OBJ ' returns the type of the object < obj > .
* *
* * ' TYPE_OBJ ' is defined in the declaration part of this package .
*/
Obj (*TypeObjFuncs[LAST_REAL_TNUM+1 ]) ( Obj obj );
static Obj TypeObjError(Obj obj)
{
ErrorQuit("Panic: basic object of type '%s' is unkind" ,
(Int )TNAM_OBJ(obj), 0 );
return 0 ;
}
/****************************************************************************
* *
* F SET_TYPE_OBJ ( < obj > , < type > ) . . . . . . . . . . . set type of an object
* *
* * ' SET_TYPE_OBJ ' sets the type of the object < obj > to < type > ; if < obj >
* * is not a posobj / comobj / datobj , attempts to first convert it to one ; if
* * that fails , an error is raised .
*/
void SET_TYPE_OBJ(Obj obj, Obj type)
{
switch (TNUM_OBJ(obj)) {
#ifdef HPCGAP
case T_ALIST:
case T_FIXALIST:
HashLock(obj);
ADDR_OBJ(obj)[1 ] = type;
CHANGED_BAG(obj);
RetypeBag(obj, T_APOSOBJ);
HashUnlock(obj);
MEMBAR_WRITE();
break ;
case T_APOSOBJ:
HashLock(obj);
ADDR_OBJ(obj)[1 ] = type;
CHANGED_BAG(obj);
HashUnlock(obj);
MEMBAR_WRITE();
break ;
case T_AREC:
case T_ACOMOBJ:
ADDR_OBJ(obj)[0 ] = type;
CHANGED_BAG(obj);
RetypeBag(obj, T_ACOMOBJ);
MEMBAR_WRITE();
break ;
#endif
case T_PREC:
#ifdef HPCGAP
MEMBAR_WRITE();
#endif
RetypeBag(obj, T_COMOBJ);
SET_TYPE_COMOBJ(obj, type);
CHANGED_BAG(obj);
break ;
case T_COMOBJ:
#ifdef HPCGAP
ReadGuard(obj);
MEMBAR_WRITE();
#endif
SET_TYPE_COMOBJ(obj, type);
CHANGED_BAG(obj);
break ;
case T_POSOBJ:
#ifdef HPCGAP
ReadGuard(obj);
MEMBAR_WRITE();
#endif
SET_TYPE_POSOBJ(obj, type);
CHANGED_BAG(obj);
break ;
case T_DATOBJ:
SetTypeDatObj(obj, type);
break ;
default :
if (!IS_PLIST(obj)) {
ErrorMayQuit("cannot change type of a %s" , (Int )TNAM_OBJ(obj), 0 );
}
// TODO: we should also reject immutable plists, but that risks
// breaking existing code
#ifdef HPCGAP
MEMBAR_WRITE();
#endif
RetypeBag(obj, T_POSOBJ);
SET_TYPE_POSOBJ(obj, type);
CHANGED_BAG(obj);
break ;
}
}
/****************************************************************************
* *
* F FuncTYPE_OBJ ( < self > , < obj > ) . . . . . . . . . handler for ' TYPE_OBJ '
*/
#ifndef WARD_ENABLED
static Obj FuncTYPE_OBJ(Obj self, Obj obj)
{
return TYPE_OBJ( obj );
}
#endif
/****************************************************************************
* *
* F FuncSET_TYPE_OBJ ( < self > , < obj > , < type > ) . . handler for ' SET_TYPE_OBJ '
*/
static Obj FuncSET_TYPE_OBJ(Obj self, Obj obj, Obj type)
{
SET_TYPE_OBJ( obj, type );
return (Obj) 0 ;
}
/****************************************************************************
* *
* F IS_MUTABLE_OBJ ( < obj > ) . . . . . . . . . . . . . . is an object mutable
* *
* * ' IS_MUTABLE_OBJ ' returns 1 if the object < obj > is mutable ( i . e . , can
* * change due to assignments ) , and 0 otherwise .
* *
* * ' IS_MUTABLE_OBJ ' is defined in the declaration part of this package .
*/
BOOL (*IsMutableObjFuncs[LAST_REAL_TNUM + 1 ])(Obj obj);
static Obj IsMutableObjFilt;
static BOOL IsMutableObjError(Obj obj)
{
ErrorQuit("Panic: tried to test mutability of unsupported type '%s'" ,
(Int )TNAM_OBJ(obj), 0 );
return FALSE ;
}
static BOOL IsMutableObjObject(Obj obj)
{
#ifdef HPCGAP
if (RegionBag(obj) == ReadOnlyRegion)
return FALSE ;
#endif
return (DoFilter( IsMutableObjFilt, obj ) == True );
}
/****************************************************************************
* *
* F FiltIS_MUTABLE_OBJ ( < self > , < obj > ) . . . handler for ' IS_MUTABLE_OBJ '
*/
static Obj FiltIS_MUTABLE_OBJ(Obj self, Obj obj)
{
return (IS_MUTABLE_OBJ( obj ) ? True : False );
}
/****************************************************************************
* *
* F FiltIS_INTERNALLY_MUTABLE_OBJ ( < self > , < obj > )
*/
#ifdef HPCGAP
static Obj IsInternallyMutableObjFilt;
static Obj FiltIS_INTERNALLY_MUTABLE_OBJ(Obj self, Obj obj)
{
return (TNUM_OBJ(obj) == T_DATOBJ &&
RegionBag(obj) != ReadOnlyRegion &&
DoFilter( IsInternallyMutableObjFilt, obj) == True ) ? True : False ;
}
BOOL IsInternallyMutableObj(Obj obj)
{
return TNUM_OBJ(obj) == T_DATOBJ &&
RegionBag(obj) != ReadOnlyRegion &&
DoFilter( IsInternallyMutableObjFilt, obj) == True ;
}
#endif
/****************************************************************************
* *
* F IS_COPYABLE_OBJ ( < obj > ) . . . . . . . . . . . . . . is an object copyable
* *
* * ' IS_COPYABLE_OBJ ' returns 1 if the object < obj > is copyable ( i . e . , can be
* * copied into a mutable object ) , and 0 otherwise .
* *
* * ' IS_COPYABLE_OBJ ' is defined in the declaration part of this package .
*/
BOOL (*IsCopyableObjFuncs[LAST_REAL_TNUM + 1 ])(Obj obj);
static Obj IsCopyableObjFilt;
static BOOL IsCopyableObjError(Obj obj)
{
ErrorQuit("Panic: tried to test copyability of unsupported type '%s'" ,
(Int )TNAM_OBJ(obj), 0 );
return FALSE ;
}
static BOOL IsCopyableObjObject(Obj obj)
{
return (DoFilter( IsCopyableObjFilt, obj ) == True );
}
/****************************************************************************
* *
* F FiltIS_COPYABLE_OBJ ( < self > , < obj > ) . . . handler for ' IS_COPYABLE_OBJ '
*/
static Obj FiltIS_COPYABLE_OBJ(Obj self, Obj obj)
{
return (IS_COPYABLE_OBJ( obj ) ? True : False );
}
/****************************************************************************
* *
* V ShallowCopyObjFuncs [ < type > ] . . . . . . . . . . shallow copier functions
*/
Obj (*ShallowCopyObjFuncs[LAST_REAL_TNUM+1 ]) ( Obj obj );
static Obj ShallowCopyObjOper;
/****************************************************************************
* *
* F ShallowCopyObjError ( < obj > ) . . . . . . . . . . . . . . . unknown type
*/
static Obj ShallowCopyObjError(Obj obj)
{
ErrorQuit("Panic: tried to shallow copy object of unsupported type '%s'" ,
(Int )TNAM_OBJ(obj), 0 );
return (Obj)0 ;
}
/****************************************************************************
* *
* F ShallowCopyObjConstant ( < obj > ) . . . . . . . . . . . . . . . do nothing
*/
static Obj ShallowCopyObjConstant(Obj obj)
{
return obj;
}
/****************************************************************************
* *
* F ShallowCopyObjObject ( < obj > ) . . . . . . . . . . . . . . . . call method
*/
static Obj ShallowCopyObjObject(Obj obj)
{
return DoOperation1Args( ShallowCopyObjOper, obj );
}
/****************************************************************************
* *
* F ShallowCopyObjDefault ( < obj > ) . . . . . . . . . . default shallow copy
*/
static Obj ShallowCopyObjDefault(Obj obj)
{
Obj new ;
const Obj * o;
Obj * n;
// make the new object and copy the contents
new = NewBag( MUTABLE_TNUM(TNUM_OBJ(obj)), SIZE_OBJ(obj) );
o = CONST_ADDR_OBJ(obj);
n = ADDR_OBJ( new );
memcpy(n, o, SIZE_OBJ(obj) );
// 'CHANGED_BAG(new);' not needed, <new> is newest object
return new ;
}
/****************************************************************************
* *
* F FuncSHALLOW_COPY_OBJ ( < self > , < obj > ) . . handler for ' SHALLOW_COPY_OBJ '
*/
static Obj FuncSHALLOW_COPY_OBJ(Obj self, Obj obj)
{
return SHALLOW_COPY_OBJ( obj );
}
/****************************************************************************
* *
* F CopyObj ( < obj > , < mut > ) . . . . . . . make a structural copy of an object
* *
* * ' CopyObj ' only calls ' COPY_OBJ ' and then ' CLEAN_OBJ ' .
*/
Obj CopyObj (
Obj obj,
Int mut )
{
#ifdef USE_THREADSAFE_COPYING
return CopyReachableObjectsFrom(obj, 0 , 0 , !mut);
#else
Obj new ; // copy of <obj>
// make a copy
new = COPY_OBJ( obj, mut );
// clean up the marks
CLEAN_OBJ( obj );
// return the copy
return new ;
#endif
}
#if !defined (USE_THREADSAFE_COPYING)
/****************************************************************************
* *
* V CopyObjFuncs [ < type > ] . . . . . . . . . . . . table of copying functions
*/
Obj (*CopyObjFuncs[ LAST_REAL_TNUM+1 ]) ( Obj obj, Int mut );
/****************************************************************************
* *
* V CleanObjFuncs [ < type > ] . . . . . . . . . . . . table of cleaning functions
*/
void (*CleanObjFuncs[ LAST_REAL_TNUM+1 ]) ( Obj obj );
/****************************************************************************
* *
* F PrepareCopy ( < obj > , < copy > ) . . . helper for use in CopyObjFuncs functions
* *
*/
void PrepareCopy(Obj obj, Obj copy)
{
// insert a forwarding pointer into <obj> which contains...
// - the value overwritten by this forwarding pointer,
// - a pointer to <copy>,
// - the TNUM of <obj>.
// Note that we cannot simply restore the overwritten value by copying
// the corresponding value from <copy>, as they may actually differ
// between original and copy (e.g. for objects, they point to the type;
// if making an immutable copy of a mutable object, the types will
// differ).
// Likewise, the TNUM of the copy and the original can and will differ;
// e.g. for a weak pointer list, the copy can be a plist.
Obj tmp = NEW_PLIST(T_PLIST, 3 );
SET_LEN_PLIST(tmp, 3 );
SET_ELM_PLIST(tmp, 1 , CONST_ADDR_OBJ(obj)[0 ]);
SET_ELM_PLIST(tmp, 2 , copy);
SET_ELM_PLIST(tmp, 3 , INTOBJ_INT(TNUM_OBJ(obj)));
// insert the forwarding pointer
GAP_ASSERT(SIZE_OBJ(obj) >= sizeof (Obj));
ADDR_OBJ(obj)[0 ] = tmp;
CHANGED_BAG(obj);
// update the TNUM to indicate the object is being copied
RetypeBag(obj, T_COPYING);
}
/****************************************************************************
* *
* F COPY_OBJ ( < obj > ) . . . . . . . . . . . make a structural copy of an object
* *
* * ' COPY_OBJ ' implements the first pass of ' CopyObj ' , i . e . , it makes the
* * structural copy of < obj > and marks < obj > as already copied .
*/
Obj COPY_OBJ(Obj obj, Int mut)
{
UInt tnum = TNUM_OBJ(obj);
Obj copy;
if (tnum == T_COPYING) {
// get the plist reference by the forwarding pointer
Obj fpl = CONST_ADDR_OBJ(obj)[0 ];
// return pointer to the copy
copy = ELM_PLIST(fpl, 2 );
}
else if (!IS_MUTABLE_OBJ(obj)) {
copy = obj;
}
else {
copy = (*CopyObjFuncs[tnum])(obj, mut);
}
return copy;
}
/****************************************************************************
* *
* F CLEAN_OBJ ( < obj > ) . . . . . . . . . . . . . clean up object after copying
* *
* * ' CLEAN_OBJ ' implements the second pass of ' CopyObj ' , i . e . , it removes the
* * mark from < obj > .
*/
void CLEAN_OBJ(Obj obj)
{
if (TNUM_OBJ(obj) != T_COPYING)
return ;
// get the plist reference by the forwarding pointer
Obj fpl = CONST_ADDR_OBJ(obj)[0 ];
// remove the forwarding pointer
ADDR_OBJ(obj)[0 ] = ELM_PLIST(fpl, 1 );
CHANGED_BAG(obj);
// restore the tnum
UInt tnum = INT_INTOBJ(ELM_PLIST(fpl, 3 ));
RetypeBag(obj, tnum);
// invoke type specific cleanup, if any
if (CleanObjFuncs[tnum])
CleanObjFuncs[tnum](obj);
}
#if !defined (USE_THREADSAFE_COPYING) && !defined (USE_BOEHM_GC)
static void MarkCopyingSubBags(Obj obj, void * ref)
{
Obj fpl = CONST_ADDR_OBJ(obj)[0 ];
// mark the forwarding pointer
MarkBag(fpl, ref);
// mark the rest as in the non-copied case
UInt tnum = INT_INTOBJ(ELM_PLIST(fpl, 3 ));
TabMarkFuncBags[tnum](obj, ref);
}
#endif
/****************************************************************************
* *
* F CopyObjError ( < obj > ) . . . . . . . . . . . . . . . . . . . unknown type
*/
static Obj CopyObjError(Obj obj, Int mut)
{
ErrorQuit("Panic: tried to copy object of unsupported type '%s'" ,
(Int )TNAM_OBJ(obj), 0 );
return (Obj)0 ;
}
/****************************************************************************
* *
* F CleanObjError ( < obj > ) . . . . . . . . . . . . . . . . . . unknown type
*/
static void CleanObjError(Obj obj)
{
ErrorQuit("Panic: tried to clean object of unsupported type '%s'" ,
(Int )TNAM_OBJ(obj), 0 );
}
/****************************************************************************
* *
* F CopyObjConstant ( < obj > ) . . . . . . . . . . . . copy a constant object
*/
static Obj CopyObjConstant(Obj obj, Int mut)
{
return obj;
}
/****************************************************************************
* *
* F CopyObjPosObj ( < obj > , < mut > ) . . . . . . . . . copy a positional object
*/
static Obj CopyObjPosObj(Obj obj, Int mut)
{
Obj copy; // copy, result
Obj tmp; // temporary variable
UInt i; // loop variable
// immutable input is handled by COPY_OBJ
GAP_ASSERT(IS_MUTABLE_OBJ(obj));
// if the object is not copyable return
if ( ! IS_COPYABLE_OBJ(obj) ) {
ErrorQuit("Panic: encountered mutable, non-copyable object" , 0 , 0 );
}
// make a copy
copy = NewBag( TNUM_OBJ(obj), SIZE_OBJ(obj) );
ADDR_OBJ(copy)[0 ] = CONST_ADDR_OBJ(obj)[0 ];
if ( !mut ) {
CALL_2ARGS( RESET_FILTER_OBJ, copy, IsMutableObjFilt );
}
// leave a forwarding pointer
PrepareCopy(obj, copy);
// copy the subvalues
for ( i = 1 ; i < SIZE_OBJ(obj)/sizeof (Obj); i++ ) {
if (CONST_ADDR_OBJ(obj)[i] != 0 ) {
tmp = COPY_OBJ(CONST_ADDR_OBJ(obj)[i], mut);
ADDR_OBJ(copy)[i] = tmp;
CHANGED_BAG( copy );
}
}
// return the copy
return copy;
}
/****************************************************************************
* *
* F CleanObjPosObj ( < obj > ) . . . . . . . . . . . . . . . . . . clean posobj
*/
static void CleanObjPosObj(Obj obj)
{
UInt i; // loop variable
// clean the subvalues
for ( i = 1 ; i < SIZE_OBJ(obj)/sizeof (Obj); i++ ) {
if (CONST_ADDR_OBJ(obj)[i] != 0 )
CLEAN_OBJ(CONST_ADDR_OBJ(obj)[i]);
}
}
/****************************************************************************
* *
* F CopyObjComObj ( < obj > , < mut > ) . . . . . . . . . . . . . . . copy a comobj
*/
static Obj CopyObjComObj(Obj obj, Int mut)
{
Obj copy; // copy, result
Obj tmp; // temporary variable
// immutable input is handled by COPY_OBJ
GAP_ASSERT(IS_MUTABLE_OBJ(obj));
// if the object is not copyable return
if ( ! IS_COPYABLE_OBJ(obj) ) {
ErrorQuit("Panic: encountered mutable, non-copyable object" , 0 , 0 );
}
// make a copy
copy = NewBag( TNUM_OBJ(obj), SIZE_OBJ(obj) );
memcpy(ADDR_OBJ(copy), CONST_ADDR_OBJ(obj), SIZE_OBJ(obj));
if ( !mut ) {
CALL_2ARGS( RESET_FILTER_OBJ, copy, IsMutableObjFilt );
}
// leave a forwarding pointer
PrepareCopy(obj, copy);
// copy the subvalues; since we used memcpy above, we don't need to worry
// about copying the length or RNAMs; and by working solely inside the
// copy, we avoid triggering tnum assertions in GET_ELM_PREC and
// SET_ELM_PREC
const UInt len = LEN_PREC(copy);
for (UInt i = 1 ; i <= len; i++) {
tmp = COPY_OBJ(GET_ELM_PREC(copy, i), mut);
SET_ELM_PREC(copy, i, tmp);
CHANGED_BAG(copy);
}
// return the copy
return copy;
}
/****************************************************************************
* *
* F CleanObjComObj ( < obj > ) . . . . . . . . . . . . . . . . . clean a comobj
*/
static void CleanObjComObj(Obj obj)
{
UInt i; // loop variable
// clean the subvalues
for ( i = 1 ; i <= LEN_PREC(obj); i++ ) {
CLEAN_OBJ( GET_ELM_PREC(obj,i) );
}
}
/****************************************************************************
* *
* F CopyObjDatObj ( < obj > , < mut > ) . . . . . . . . . . . . . . . copy a datobj
*/
static Obj CopyObjDatObj(Obj obj, Int mut)
{
Obj copy; // copy, result
// immutable input is handled by COPY_OBJ
GAP_ASSERT(IS_MUTABLE_OBJ(obj));
// if the object is not copyable return
if ( ! IS_COPYABLE_OBJ(obj) ) {
ErrorQuit("Panic: encountered mutable, non-copyable object" , 0 , 0 );
}
// make a copy
copy = NewBag( TNUM_OBJ(obj), SIZE_OBJ(obj) );
memcpy(ADDR_OBJ(copy), CONST_ADDR_OBJ(obj), SIZE_OBJ(obj));
if ( !mut ) {
CALL_2ARGS( RESET_FILTER_OBJ, copy, IsMutableObjFilt );
}
// leave a forwarding pointer
PrepareCopy(obj, copy);
// return the copy
return copy;
}
/****************************************************************************
* *
* F CleanObjDatObj ( < obj > ) . . . . . . . . . . . . . . . . . clean a datobj
*/
static void CleanObjDatObj(Obj obj)
{
}
#endif // !defined(USE_THREADSAFE_COPYING)
/****************************************************************************
* *
* F FuncIMMUTABLE_COPY_OBJ ( < self > , < obj > ) . . . . immutable copy of < obj >
*/
static Obj FuncIMMUTABLE_COPY_OBJ(Obj self, Obj obj)
{
return CopyObj( obj, 0 );
}
/****************************************************************************
* *
* F FuncDEEP_COPY_OBJ ( < self > , < obj > ) . . . . . . mutable copy of < obj >
*/
static Obj FuncDEEP_COPY_OBJ(Obj self, Obj obj)
{
return CopyObj( obj, 1 );
}
/****************************************************************************
* *
* F MakeImmutable ( < obj > . . . . . . . . . . make an object immutable inplace
* *
* * Mark an object and all subobjects immutable in - place .
* * May cause confusion if there are shared subobjects
* *
*/
static Obj PostMakeImmutableOp = 0 ;
void (*MakeImmutableObjFuncs[LAST_REAL_TNUM+1 ])( Obj );
void MakeImmutable( Obj obj )
{
if (IS_MUTABLE_OBJ( obj ))
{
(*(MakeImmutableObjFuncs[TNUM_OBJ(obj)]))(obj);
}
}
#ifdef HPCGAP
void CheckedMakeImmutable( Obj obj )
{
if (!PreMakeImmutableCheck(obj))
ErrorMayQuit("MakeImmutable: Argument has inaccessible subobjects" , 0 , 0 );
MakeImmutable(obj);
}
#endif
static void MakeImmutableError(Obj obj)
{
ErrorQuit("No make immutable function installed for a %s" ,
(Int )TNAM_OBJ(obj), 0 );
}
static void MakeImmutableComObj(Obj obj)
{
CALL_2ARGS( RESET_FILTER_OBJ, obj, IsMutableObjFilt );
CALL_1ARGS( PostMakeImmutableOp, obj);
}
static void MakeImmutablePosObj(Obj obj)
{
CALL_2ARGS( RESET_FILTER_OBJ, obj, IsMutableObjFilt );
CALL_1ARGS( PostMakeImmutableOp, obj);
}
#ifdef HPCGAP
// HPCGAP-HACK:
// There is a considerable amount of library code that currently
// relies on being able to modify immutable data objects; in order
// to not break all of that, MakeImmutableDatObj() makes immutable
// data objects public, not read-only if they are not internally
// mutable. Note that this is potentially unsafe if these objects
// are shared between threads and then modified by kernel code.
//
// By setting the environment variable GAP_READONLY_DATOBJS, one
// can restore the old behavior in order to find and debug the
// offending code.
static int ReadOnlyDatObjs = 0 ;
#endif
static void MakeImmutableDatObj(Obj obj)
{
CALL_2ARGS( RESET_FILTER_OBJ, obj, IsMutableObjFilt );
#ifdef HPCGAP
if (!IsInternallyMutableObj(obj)) {
if (ReadOnlyDatObjs)
MakeBagReadOnly(obj);
else
MakeBagPublic(obj);
}
#endif
}
static Obj FuncMakeImmutable(Obj self, Obj obj)
{
#ifdef HPCGAP
CheckedMakeImmutable(obj);
#else
MakeImmutable(obj);
#endif
return obj;
}
static Obj FuncGET_TNAM_FROM_TNUM(Obj self, Obj obj)
{
UInt tnum = GetBoundedInt(SELF_NAME, obj, 0 , NUM_TYPES - 1 );
const char * name = TNAM_TNUM(tnum);
return MakeImmString(name ? name : "<unnamed tnum>" );
}
// This function is used to keep track of which objects are already
// being printed or viewed to trigger the use of ~ when needed.
static inline BOOL IS_ON_PRINT_STACK(const ObjectsModuleState * os, Obj obj)
{
if (!(FIRST_RECORD_TNUM <= TNUM_OBJ(obj) &&
TNUM_OBJ(obj) <= LAST_LIST_TNUM))
return FALSE ;
for (UInt i = 0 ; i < os->PrintObjDepth; i++)
if (os->PrintObjThiss[i] == obj)
return TRUE ;
return FALSE ;
}
#ifdef HPCGAP
static void PrintInaccessibleObject(Obj obj)
{
Char buffer[20 ];
Char *name;
Region *region;
Obj nameobj;
region = REGION(obj);
if (!region)
nameobj = PublicRegionName; // this should not happen, but let's be safe
else
nameobj = GetRegionName(region);
if (nameobj) {
name = CSTR_STRING(nameobj);
} else {
sprintf(buffer, "%p" , (void *)region);
name = buffer;
Pr("<protected object in shared region %s (id: %d)>" , (Int ) name, (Int ) obj);
return ;
}
Pr("<protected '%s' object (id: %d)>" , (Int ) name, (Int ) obj);
}
#endif
static void PRINT_PATH(Obj obj, Int idx)
{
UInt tnum = TNUM_OBJ(obj);
if (IS_PREC(obj)) {
Pr(".%I" , (Int )NAME_RNAM(idx), 0 );
}
else if (FIRST_LIST_TNUM <= tnum && tnum <= LAST_LIST_TNUM) {
Pr("[%d]" , idx, 0 );
}
else {
ErrorQuit("Panic: tried to print a path of unsupported type '%s'" ,
(Int )tnum, 0 );
}
}
/****************************************************************************
* *
* F PrintObj ( < obj > ) . . . . . . . . . . . . . . . . . . . . print an object
* *
* * ' PrintObj ' prints the object < obj > .
*/
void PrintObj(Obj obj)
{
#if defined (HPCGAP) && !defined (WARD_ENABLED)
if (IS_BAG_REF(obj) && !CheckReadAccess(obj)) {
PrintInaccessibleObject(obj);
return ;
}
#endif
ObjectsModuleState * os = &MODULE_STATE(Objects);
// First check if <obj> is actually the current object being viewed, since
// ViewObj(<obj>) may result in a call to PrintObj(<obj>); in that case,
// we should not put <obj> on the print stack
if ((os->PrintObjDepth > 0 ) && (os->LastPV == 2 ) &&
(obj == os->PrintObjThiss[os->PrintObjDepth - 1 ])) {
os->LastPV = 1 ;
PRINT_OBJ(obj);
os->LastPV = 2 ;
}
// print the path if <obj> is on the stack
else if (IS_ON_PRINT_STACK(os, obj)) {
Pr("~" , 0 , 0 );
for (int i = 0 ; obj != os->PrintObjThiss[i]; i++) {
PRINT_PATH(os->PrintObjThiss[i], os->PrintObjIndices[i]);
}
}
// dispatch to the appropriate printing function
else if (os->PrintObjDepth < MAXPRINTDEPTH) {
Obj oldThis = os->PrintObjThiss[os->PrintObjDepth];
Int oldIndx = os->PrintObjIndices[os->PrintObjDepth];
// push obj on the stack
os->PrintObjThiss[os->PrintObjDepth] = obj;
os->PrintObjIndices[os->PrintObjDepth] = 0 ;
os->PrintObjDepth++;
UInt lastPV = os->LastPV;
os->LastPV = 1 ;
PRINT_OBJ(obj);
os->LastPV = lastPV;
// pop <obj> from the stack
os->PrintObjDepth--;
os->PrintObjThiss[os->PrintObjDepth] = oldThis;
os->PrintObjIndices[os->PrintObjDepth] = oldIndx;
}
else {
Pr("\nprinting stopped, too many recursion levels!\n" , 0 , 0 );
}
}
/****************************************************************************
* *
* V PrintObjFuncs [ < type > ] . . . . . . . . printer for objects of type < type >
* *
* * ' PrintObjFuncs ' is the dispatch table that contains for every type of
* * objects a pointer to the printer for objects of this type . The printer
* * is the function ' < func > ( < obj > ) ' that should be called to print the object
* * < obj > of this type .
*/
void (* PrintObjFuncs [ LAST_REAL_TNUM +1 ])( Obj obj );
/****************************************************************************
* *
* F PrintObjObject ( < obj > ) . . . . . . . . . . . . . . . . . print an object
*/
Obj PrintObjOper;
static void PrintObjObject(Obj obj)
{
DoOperation1Args( PrintObjOper, obj );
}
/****************************************************************************
* *
* F FuncPRINT_OBJ ( < self > , < obj > ) . . . . . . . . . . handler for ' PrintObj '
*/
static Obj FuncPRINT_OBJ(Obj self, Obj obj)
{
PrintObj( obj );
return 0 ;
}
UInt SetPrintObjState(UInt state)
{
UInt oldDepth = MODULE_STATE(Objects).PrintObjDepth;
UInt oldLastPV = MODULE_STATE(Objects).LastPV;
MODULE_STATE(Objects).PrintObjDepth = state >> 2 ;
MODULE_STATE(Objects).LastPV = state & 3 ;
return (oldDepth << 2 ) | oldLastPV;
}
void SetPrintObjIndex(Int index)
{
UInt depth = MODULE_STATE(Objects).PrintObjDepth;
if (depth == 0 )
ErrorQuit("SetPrintObjIndex: bad state, PrintObjDepth is 0" , 0 , 0 );
MODULE_STATE(Objects).PrintObjIndices[depth - 1 ] = index;
}
static Obj FuncSET_PRINT_OBJ_INDEX(Obj self, Obj index)
{
SetPrintObjIndex(GetSmallInt(SELF_NAME, index));
return 0 ;
}
/****************************************************************************
* *
* F ViewObj ( < obj > ) . . . . . . . . . . . . . . . . . . . . . view an object
* *
* * ' ViewObj ' views the object < obj > .
* *
* * ViewObj shares all the associated variables with PrintObj , so that
* * recursion works nicely .
*/
static Obj ViewObjOper;
void ViewObj(Obj obj)
{
#if defined (HPCGAP) && !defined (WARD_ENABLED)
if (IS_BAG_REF(obj) && !CheckReadAccess(obj)) {
PrintInaccessibleObject(obj);
return ;
}
#endif
ObjectsModuleState * os = &MODULE_STATE(Objects);
// print the path if <obj> is on the stack
if (IS_ON_PRINT_STACK(os, obj)) {
Pr("~" , 0 , 0 );
for (int i = 0 ; obj != os->PrintObjThiss[i]; i++) {
PRINT_PATH(os->PrintObjThiss[i], os->PrintObjIndices[i]);
}
}
// dispatch to the appropriate viewing function
else if (os->PrintObjDepth < MAXPRINTDEPTH) {
Obj oldThis = os->PrintObjThiss[os->PrintObjDepth];
Int oldIndx = os->PrintObjIndices[os->PrintObjDepth];
// push obj on the stack
os->PrintObjThiss[os->PrintObjDepth] = obj;
os->PrintObjIndices[os->PrintObjDepth] = 0 ;
os->PrintObjDepth++;
UInt lastPV = os->LastPV;
os->LastPV = 2 ;
DoOperation1Args(ViewObjOper, obj);
os->LastPV = lastPV;
// pop <obj> from the stack
os->PrintObjDepth--;
os->PrintObjThiss[os->PrintObjDepth] = oldThis;
os->PrintObjIndices[os->PrintObjDepth] = oldIndx;
}
else {
Pr("\nviewing stopped, too many recursion levels!\n" , 0 , 0 );
}
}
/****************************************************************************
* *
* F FuncVIEW_OBJ ( < self > , < obj > ) . . . . . . . . . . . handler for ' ViewObj '
*/
static Obj FuncVIEW_OBJ(Obj self, Obj obj)
{
ViewObj( obj );
return 0 ;
}
/****************************************************************************
* *
* F TypeComObj ( < obj > ) . . . . . . . . . . function version of ' TYPE_COMOBJ '
*/
#ifndef WARD_ENABLED
static Obj TypeComObj(Obj obj)
{
Obj result = TYPE_COMOBJ( obj );
#ifdef HPCGAP
MEMBAR_READ();
#endif
return result;
}
#endif
/*****************************************************************************
* *
* F FuncIS_COMOBJ ( < self > , < obj > ) . . . . . . . . handler for ' IS_COMOBJ '
*/
static Obj FuncIS_COMOBJ(Obj self, Obj obj)
{
#ifdef HPCGAP
switch (TNUM_OBJ(obj)) {
case T_COMOBJ:
case T_ACOMOBJ:
return True ;
default :
return False ;
}
#else
return (TNUM_OBJ(obj) == T_COMOBJ ? True : False );
#endif
}
/****************************************************************************
* *
* F FuncSET_TYPE_COMOBJ ( < self > , < obj > , < type > ) . . . ' SET_TYPE_COMOBJ '
*/
static Obj FuncSET_TYPE_COMOBJ(Obj self, Obj obj, Obj type)
{
switch (TNUM_OBJ(obj)) {
case T_PREC:
case T_COMOBJ:
#ifdef HPCGAP
case T_AREC:
case T_ACOMOBJ:
#endif
SET_TYPE_OBJ(obj, type);
break ;
default :
ErrorMayQuit("You can't make a component object from a %s" ,
(Int )TNAM_OBJ(obj), 0 );
}
return obj;
}
/****************************************************************************
* *
* F AssComObj ( < obj > , < rnam > , < val > )
* F UnbComObj ( < obj > , < rnam > )
* F ElmComObj ( < obj > , < rnam > )
* F IsbComObj ( < obj > , < rnam > )
*/
void AssComObj(Obj obj, UInt rnam, Obj val)
{
switch (TNUM_OBJ(obj)) {
case T_COMOBJ:
AssPRec(obj, rnam, val);
break ;
#ifdef HPCGAP
case T_ACOMOBJ:
SetARecordField(obj, rnam, val);
break ;
#endif
default :
ASS_REC(obj, rnam, val);
break ;
}
}
void UnbComObj(Obj obj, UInt rnam)
{
switch (TNUM_OBJ(obj)) {
case T_COMOBJ:
UnbPRec(obj, rnam);
break ;
#ifdef HPCGAP
case T_ACOMOBJ:
UnbARecord(obj, rnam);
break ;
#endif
default :
UNB_REC(obj, rnam);
break ;
}
}
Obj ElmComObj(Obj obj, UInt rnam)
{
switch (TNUM_OBJ(obj)) {
case T_COMOBJ:
return ElmPRec(obj, rnam);
#ifdef HPCGAP
case T_ACOMOBJ:
return ElmARecord(obj, rnam);
#endif
default :
return ELM_REC(obj, rnam);
}
}
BOOL IsbComObj(Obj obj, UInt rnam)
{
switch (TNUM_OBJ(obj)) {
case T_COMOBJ:
return IsbPRec(obj, rnam);
#ifdef HPCGAP
case T_ACOMOBJ:
return IsbARecord(obj, rnam);
#endif
default :
return ISB_REC(obj, rnam);
}
}
/****************************************************************************
* *
* F TypePosObj ( < obj > ) . . . . . . . . . . function version of ' TYPE_POSOBJ '
*/
#ifndef WARD_ENABLED
static Obj TypePosObj(Obj obj)
{
Obj result = TYPE_POSOBJ( obj );
#ifdef HPCGAP
MEMBAR_READ();
#endif
return result;
}
#endif
/****************************************************************************
* *
* F FuncIS_POSOBJ ( < self > , < obj > ) . . . . . . . handler for ' IS_POSOBJ '
*/
static Obj FuncIS_POSOBJ(Obj self, Obj obj)
{
switch (TNUM_OBJ(obj)) {
case T_POSOBJ:
#ifdef HPCGAP
case T_APOSOBJ:
#endif
return True ;
default :
return False ;
}
}
/****************************************************************************
* *
* F FuncSET_TYPE_POSOBJ ( < self > , < obj > , < type > ) . . . ' SET_TYPE_POSOB '
*/
static Obj FuncSET_TYPE_POSOBJ(Obj self, Obj obj, Obj type)
{
switch (TNUM_OBJ(obj)) {
#ifdef HPCGAP
case T_APOSOBJ:
case T_ALIST:
case T_FIXALIST:
#endif
case T_POSOBJ:
break ;
default :
if (!IS_PLIST(obj)) {
ErrorMayQuit("You can't make a positional object from a %s" ,
(Int )TNAM_OBJ(obj), 0 );
}
// TODO: we should also reject immutable plists, but that risks
// breaking existing code
break ;
}
SET_TYPE_OBJ(obj, type);
return obj;
}
/****************************************************************************
* *
* F FuncLEN_POSOBJ ( < self > , < obj > ) . . . . . . handler for ' LEN_POSOBJ '
*/
static Obj FuncLEN_POSOBJ(Obj self, Obj obj)
{
#ifdef HPCGAP
switch (TNUM_OBJ(obj)) {
case T_APOSOBJ:
case T_ALIST:
case T_FIXALIST:
return LengthAList( obj );
}
#endif
return INTOBJ_INT( SIZE_OBJ(obj) / sizeof (Obj) - 1 );
}
/****************************************************************************
* *
* F AssPosbj ( < obj > , < rnam > , < val > )
* F UnbPosbj ( < obj > , < rnam > )
* F ElmPosbj ( < obj > , < rnam > )
* F IsbPosbj ( < obj > , < rnam > )
*/
void AssPosObj(Obj obj, Int idx, Obj val)
{
if (TNUM_OBJ(obj) == T_POSOBJ) {
#ifdef HPCGAP
// Because BindOnce() functions can reallocate the list even if they
// only have read-only access, we have to be careful when accessing
// positional objects. Hence the explicit WriteGuard().
WriteGuard(obj);
#endif
if (SIZE_OBJ(obj) / sizeof (Obj) - 1 < idx) {
ResizeBag(obj, (idx + 1 ) * sizeof (Obj));
}
SET_ELM_PLIST(obj, idx, val);
CHANGED_BAG(obj);
}
#ifdef HPCGAP
else if (TNUM_OBJ(obj) == T_APOSOBJ) {
AssListFuncs[T_FIXALIST](obj, idx, val);
}
#endif
else {
ASS_LIST(obj, idx, val);
}
}
void UnbPosObj(Obj obj, Int idx)
{
if (TNUM_OBJ(obj) == T_POSOBJ) {
#ifdef HPCGAP
// Because BindOnce() functions can reallocate the list even if they
// only have read-only access, we have to be careful when accessing
// positional objects. Hence the explicit WriteGuard().
WriteGuard(obj);
#endif
if (idx <= SIZE_OBJ(obj) / sizeof (Obj) - 1 ) {
SET_ELM_PLIST(obj, idx, 0 );
}
}
#ifdef HPCGAP
else if (TNUM_OBJ(obj) == T_APOSOBJ) {
UnbListFuncs[T_FIXALIST](obj, idx);
}
#endif
else {
UNB_LIST(obj, idx);
}
}
Obj ElmPosObj(Obj obj, Int idx)
{
Obj elm;
if (TNUM_OBJ(obj) == T_POSOBJ) {
#ifdef HPCGAP
// Because BindOnce() functions can reallocate the list even if they
// only have read-only access, we have to be careful when accessing
// positional objects.
const Bag * contents = CONST_PTR_BAG(obj);
MEMBAR_READ(); // essential memory barrier
if (SIZE_BAG_CONTENTS(contents) / sizeof (Obj) - 1 < idx) {
ErrorMayQuit(
"PosObj Element: <PosObj>![%d] must have an assigned value" ,
(Int )idx, 0 );
}
elm = contents[idx];
#else
if (SIZE_OBJ(obj) / sizeof (Obj) - 1 < idx) {
ErrorMayQuit(
"PosObj Element: <PosObj>![%d] must have an assigned value" ,
(Int )idx, 0 );
}
elm = ELM_PLIST(obj, idx);
#endif
if (elm == 0 ) {
ErrorMayQuit(
"PosObj Element: <PosObj>![%d] must have an assigned value" ,
(Int )idx, 0 );
}
}
#ifdef HPCGAP
else if (TNUM_OBJ(obj) == T_APOSOBJ) {
elm = ElmListFuncs[T_FIXALIST](obj, idx);
}
#endif
else {
elm = ELM_LIST(obj, idx);
}
return elm;
}
BOOL IsbPosObj(Obj obj, Int idx)
{
BOOL isb;
if (TNUM_OBJ(obj) == T_POSOBJ) {
#ifdef HPCGAP
// Because BindOnce() functions can reallocate the list even if they
// only have read-only access, we have to be careful when accessing
// positional objects.
const Bag * contents = CONST_PTR_BAG(obj);
if (idx > SIZE_BAG_CONTENTS(contents) / sizeof (Obj) - 1 )
isb = FALSE ;
else
isb = contents[idx] != 0 ;
#else
isb = (idx <= SIZE_OBJ(obj) / sizeof (Obj) - 1 &&
ELM_PLIST(obj, idx) != 0 );
#endif
}
#ifdef HPCGAP
else if (TNUM_OBJ(obj) == T_APOSOBJ) {
isb = IsbListFuncs[T_FIXALIST](obj, idx);
}
#endif
else {
isb = ISB_LIST(obj, idx);
}
return isb;
}
/****************************************************************************
* *
* F TypeDatObj ( < obj > ) . . . . . . . . . . function version of ' TYPE_DATOBJ '
*/
static Obj TypeDatObj(Obj obj)
{
Obj type = TYPE_DATOBJ( obj );
return type ? type : TYPE_KERNEL_OBJECT;
}
void SetTypeDatObj( Obj obj, Obj type)
{
SET_TYPE_DATOBJ(obj, type);
#ifdef HPCGAP
if (TNUM_OBJ(obj) == T_DATOBJ &&
!IsMutableObjObject(obj) && !IsInternallyMutableObj(obj)) {
if (ReadOnlyDatObjs)
MakeBagReadOnly(obj);
else
MakeBagPublic(obj);
}
#endif
CHANGED_BAG(obj);
}
/*****************************************************************************
* *
* F FuncIS_DATOBJ ( < self > , < obj > ) . . . . . . . . handler for ' IS_DATOBJ '
*/
static Obj FuncIS_DATOBJ(Obj self, Obj obj)
{
return (TNUM_OBJ(obj) == T_DATOBJ ? True : False );
}
/****************************************************************************
* *
* F FuncSET_TYPE_DATOBJ ( < self > , < obj > , < type > ) . . . ' SET_TYPE_DATOBJ '
*/
static Obj FuncSET_TYPE_DATOBJ(Obj self, Obj obj, Obj type)
{
#ifndef WARD_ENABLED
#ifdef HPCGAP
ReadGuard( obj );
#endif
SET_TYPE_DATOBJ(obj, type);
RetypeBag( obj, T_DATOBJ );
CHANGED_BAG( obj );
return obj;
#endif
}
/****************************************************************************
* *
* F NewKernelBuffer ( < size > ) . . . . . . . . . . return a new kernel buffer
*/
Obj NewKernelBuffer(UInt size)
{
Obj obj = NewBag(T_DATOBJ, size);
SET_TYPE_DATOBJ(obj, TYPE_KERNEL_OBJECT);
return obj;
}
/****************************************************************************
* *
* F FuncIS_IDENTICAL_OBJ ( < self > , < obj1 > , < obj2 > ) . . . . . handler for ' = = '
* *
* * ' FuncIS_IDENTICAL_OBJ ' implements ' IsIdentical '
*/
static Obj FuncIS_IDENTICAL_OBJ(Obj self, Obj obj1, Obj obj2)
{
return (obj1 == obj2 ? True : False );
}
/****************************************************************************
* *
* V SaveObjFuncs ( < type > ) . . . . . . . . . . . . . functions to save objects
* *
* * ' SaveObjFuncs ' is the dispatch table that contains , for every type
* * of objects , a pointer to the saving function for objects of that type
* * These should not handle the file directly , but should work via the
* * functions ' SaveSubObj ' , ' SaveUInt < n > ' ( < n > = 1 , 2 , 4 or 8 ) , and others
* * to be determined . Their role is to identify the C types of the various
* * parts of the bag , and perhaps to leave out some information that does
* * not need to be saved . By the time this function is called , the bag
* * size and type have already been saved
* * No saving function may allocate any bag
*/
#ifdef GAP_ENABLE_SAVELOAD
void (*SaveObjFuncs[LAST_REAL_TNUM+1 ]) ( Obj obj );
void SaveObjError( Obj obj )
{
ErrorQuit("Panic: tried to save an object of unsupported type '%s'" ,
(Int )TNAM_OBJ(obj), 0 );
}
#endif
/****************************************************************************
* *
* V LoadObjFuncs ( < type > ) . . . . . . . . . . . . . functions to load objects
* *
* * ' LoadObjFuncs ' is the dispatch table that contains , for every type
* * of objects , a pointer to the loading function for objects of that type
* * These should not handle the file directly , but should work via the
* * functions ' LoadObjRef ' , ' LoadUInt < n > ' ( < n > = 1 , 2 , 4 or 8 ) , and others
* * to be determined . Their role is to reinstall the information in the bag
* * and reconstruct anything that was left out . By the time this function is
* * called , the bag size and type have already been loaded and the bag argument
* * contains the bag in question
* * No loading function may allocate any bag
*/
#ifdef GAP_ENABLE_SAVELOAD
void (*LoadObjFuncs[LAST_REAL_TNUM+1 ]) ( Obj obj );
void LoadObjError( Obj obj )
{
ErrorQuit("Panic: tried to load an object of unsupported type '%s'" ,
(Int )TNAM_OBJ(obj), 0 );
}
#endif
/****************************************************************************
* *
* F SaveComObj ( Obj comobj )
* *
*/
#ifdef GAP_ENABLE_SAVELOAD
static void SaveComObj(Obj comobj)
{
UInt len,i;
SaveSubObj(TYPE_COMOBJ( comobj ));
len = LEN_PREC(comobj);
SaveUInt(len);
for (i = 1 ; i <= len; i++)
{
SaveUInt(GET_RNAM_PREC(comobj, i));
SaveSubObj(GET_ELM_PREC(comobj, i));
}
}
#endif
/****************************************************************************
* *
* F SavePosObj ( Obj posobj )
* *
*/
#ifdef GAP_ENABLE_SAVELOAD
static void SavePosObj(Obj posobj)
{
UInt len,i;
SaveSubObj(TYPE_POSOBJ( posobj ));
len = (SIZE_OBJ(posobj)/sizeof (Obj) - 1 );
for (i = 1 ; i <= len; i++)
{
SaveSubObj(CONST_ADDR_OBJ(posobj)[i]);
}
}
#endif
/****************************************************************************
* *
* F SaveDatObj ( Obj datobj )
* *
* * Here we lose endianness protection , because we don ' t know if this is really
* * UInts , or if it might be smaller data
*/
#ifdef GAP_ENABLE_SAVELOAD
static void SaveDatObj(Obj datobj)
{
UInt len,i;
const UInt * ptr;
SaveSubObj(TYPE_DATOBJ( datobj ));
len = ((SIZE_OBJ(datobj)+sizeof (UInt)-1 )/sizeof (UInt) - 1 );
ptr = (const UInt *)CONST_ADDR_OBJ(datobj) + 1 ;
for (i = 1 ; i <= len; i++)
{
SaveUInt(*ptr++);
}
}
#endif
/****************************************************************************
* *
* F LoadComObj ( Obj comobj )
* *
*/
#ifdef GAP_ENABLE_SAVELOAD
static void LoadComObj(Obj comobj)
{
UInt len,i;
SET_TYPE_COMOBJ(comobj, LoadSubObj());
len = LoadUInt();
SET_LEN_PREC(comobj,len);
for (i = 1 ; i <= len; i++)
{
SET_RNAM_PREC(comobj, i, LoadUInt());
SET_ELM_PREC(comobj, i, LoadSubObj());
}
}
#endif
/****************************************************************************
* *
* F LoadPosObj ( Obj posobj )
* *
*/
#ifdef GAP_ENABLE_SAVELOAD
static void LoadPosObj(Obj posobj)
{
UInt len,i;
SET_TYPE_POSOBJ(posobj, LoadSubObj());
len = (SIZE_OBJ(posobj)/sizeof (Obj) - 1 );
for (i = 1 ; i <= len; i++)
{
ADDR_OBJ(posobj)[i] = LoadSubObj();
}
}
#endif
/****************************************************************************
* *
* F LoadDatObj ( Obj datobj )
* *
* * Here we lose endianness protection , because we don ' t know if this is really
* * UInts , or if it might be smaller data
*/
#ifdef GAP_ENABLE_SAVELOAD
static void LoadDatObj(Obj datobj)
{
UInt len,i;
UInt *ptr;
SET_TYPE_DATOBJ(datobj, LoadSubObj());
len = ((SIZE_OBJ(datobj)+sizeof (UInt)-1 )/sizeof (UInt) - 1 );
ptr = (UInt *)ADDR_OBJ(datobj)+1 ;
for (i = 1 ; i <= len; i++)
{
*ptr ++ = LoadUInt();
}
}
#endif
/****************************************************************************
* *
* F * * * * * * * * GAP functions for " to be defined " objects * * * * * * * *
*/
/****************************************************************************
* *
* F FuncCLONE_OBJ ( < self > , < dst > , < src > ) . . . . . . . clone < src > to < dst >
* *
* * ` CLONE_OBJ ' clones the source < src > into < dst > . It is not allowed to
* * clone small integers or finite field elements .
* *
* * If < src > is a constant , than a " shallow " copy , that is to say , a bit - copy
* * of the bag of < src > is created . If < src > is mutable than a " structural
* * copy is created , which is then in turn " shallow " cloned into < dst > .
* *
* * WARNING : at the moment the functions breaks on cloning ` [ 1 , ~ ] ' . This can
* * be fixed if necessary .
*/
static Obj IsToBeDefinedObj;
static Obj REREADING;
static Obj FuncCLONE_OBJ(Obj self, Obj dst, Obj src)
{
const Obj * psrc;
Obj * pdst;
// check <src>
if ( IS_INTOBJ(src) ) {
ErrorMayQuit("small integers cannot be cloned" , 0 , 0 );
}
if ( IS_FFE(src) ) {
ErrorMayQuit("finite field elements cannot be cloned" , 0 , 0 );
}
if ( TNUM_OBJ(src) == T_BOOL ) {
ErrorMayQuit("booleans cannot be cloned" , 0 , 0 );
}
#ifdef HPCGAP
switch (TNUM_OBJ(src)) {
case T_AREC:
case T_ACOMOBJ:
case T_TLREC:
ErrorMayQuit("cannot clone %ss" , (Int )TNAM_OBJ(src), 0 );
}
if (!REGION(dst)) {
ErrorMayQuit("CLONE_OBJ() cannot overwrite public objects" , 0 , 0 );
}
if (REGION(src) != REGION(dst) && REGION(src)) {
ErrorMayQuit("objects can only be cloned to replace objects within"
"the same region or if the object is public" ,
0 , 0 );
}
#endif
// if object is mutable, produce a structural copy
if ( IS_MUTABLE_OBJ(src) ) {
src = CopyObj( src, 1 );
}
// now shallow clone the object
#ifdef HPCGAP
Obj tmp = NewBag(TNUM_OBJ(src), SIZE_OBJ(src));
pdst = ADDR_OBJ(tmp);
#else
ResizeBag( dst, SIZE_OBJ(src) );
RetypeBag( dst, TNUM_OBJ(src) );
pdst = ADDR_OBJ(dst);
#endif
psrc = CONST_ADDR_OBJ(src);
memcpy(pdst, psrc, SIZE_OBJ(src));
CHANGED_BAG(dst);
#ifdef HPCGAP
SET_REGION(dst, REGION(src));
MEMBAR_WRITE();
// The following is a no-op unless the region is public
SET_PTR_BAG(dst, PTR_BAG(tmp));
#endif
return 0 ;
}
/****************************************************************************
* *
* F FuncSWITCH_OBJ ( < self > , < obj1 > , < obj2 > ) . . . switch < obj1 > and < obj2 >
* *
* * ` SWITCH_OBJ ' exchanges the objects referenced by its two arguments . It
* * is not allowed to switch clone small integers or finite field elements .
* *
* * This is inspired by the Smalltalk ' become : ' operation .
*/
static Obj FuncSWITCH_OBJ(Obj self, Obj obj1, Obj obj2)
{
if ( IS_INTOBJ(obj1) || IS_INTOBJ(obj2) ) {
ErrorMayQuit("small integer objects cannot be switched" , 0 , 0 );
}
if ( IS_FFE(obj1) || IS_FFE(obj2) ) {
ErrorMayQuit("finite field elements cannot be switched" , 0 , 0 );
}
#ifdef HPCGAP
Region * ds1 = REGION(obj1);
Region * ds2 = REGION(obj2);
if (!ds1 || ds1->owner != GetTLS())
ErrorQuit("SWITCH_OBJ: Cannot write to first object's region." , 0 , 0 );
if (!ds2 || ds2->owner != GetTLS())
ErrorQuit("SWITCH_OBJ: Cannot write to second object's region." , 0 , 0 );
SET_REGION(obj2, ds1);
SET_REGION(obj1, ds2);
#endif
SwapMasterPoint(obj1, obj2);
return 0 ;
}
/****************************************************************************
* *
* F FuncFORCE_SWITCH_OBJ ( < self > , < obj1 > , < obj2 > ) . switch < obj1 > and < obj2 >
* *
* * ` FORCE_SWITCH_OBJ ' exchanges the objects referenced by its two arguments .
* * It is not allowed to switch clone small integers or finite field
* * elements .
* *
* * In GAP , FORCE_SWITCH_OBJ does the same thing as SWITCH_OBJ . In HPC_GAP
* * it allows public objects to be exchanged .
*/
static Obj FuncFORCE_SWITCH_OBJ(Obj self, Obj obj1, Obj obj2)
{
if ( IS_INTOBJ(obj1) || IS_INTOBJ(obj2) ) {
ErrorMayQuit("small integer objects cannot be switched" , 0 , 0 );
}
if ( IS_FFE(obj1) || IS_FFE(obj2) ) {
ErrorMayQuit("finite field elements cannot be switched" , 0 , 0 );
}
#ifdef HPCGAP
Region * ds1 = REGION(obj1);
Region * ds2 = REGION(obj2);
if (ds1 && ds1->owner != GetTLS())
ErrorQuit("FORCE_SWITCH_OBJ: Cannot write to first object's region." , 0 , 0 );
if (ds2 && ds2->owner != GetTLS())
ErrorQuit("FORCE_SWITCH_OBJ: Cannot write to second object's region." , 0 , 0 );
SET_REGION(obj2, ds1);
SET_REGION(obj1, ds2);
#endif
SwapMasterPoint(obj1, obj2);
return 0 ;
}
/****************************************************************************
* *
* F FuncDEBUG_TNUM_NAMES
* *
* * Print all defined TNUM values and names
*/
#define START_SYMBOLIC_TNUM(name) \
if (k == name) { \
Pr("%3d: %s" , k, (Int )indentStr); \
Pr("%s" #name "\n" , (Int )indentStr, 0 ); \
assert(indentLvl + 1 < sizeof (indentStr)); \
indentStr[indentLvl++] = ' ' ; \
indentStr[indentLvl] = 0 ; \
}
#define STOP_SYMBOLIC_TNUM(name) \
if (k == name) { \
assert(indentLvl > 0 ); \
indentStr[--indentLvl] = 0 ; \
Pr("%3d: %s" , k, (Int )indentStr); \
Pr("%s" #name "\n" , (Int )indentStr, 0 ); \
}
static Obj FuncDEBUG_TNUM_NAMES(Obj self)
{
UInt indentLvl = 0 ;
Char indentStr[20 ] = "" ;
for (UInt k = 0 ; k < NUM_TYPES; k++) {
START_SYMBOLIC_TNUM(FIRST_REAL_TNUM);
START_SYMBOLIC_TNUM(FIRST_CONSTANT_TNUM);
START_SYMBOLIC_TNUM(FIRST_MULT_TNUM);
START_SYMBOLIC_TNUM(FIRST_IMM_MUT_TNUM);
START_SYMBOLIC_TNUM(FIRST_RECORD_TNUM);
START_SYMBOLIC_TNUM(FIRST_LIST_TNUM);
START_SYMBOLIC_TNUM(FIRST_PLIST_TNUM);
START_SYMBOLIC_TNUM(FIRST_OBJSET_TNUM);
#ifdef HPCGAP
START_SYMBOLIC_TNUM(FIRST_SHARED_TNUM);
START_SYMBOLIC_TNUM(FIRST_ATOMIC_TNUM);
START_SYMBOLIC_TNUM(FIRST_ATOMIC_LIST_TNUM);
START_SYMBOLIC_TNUM(FIRST_ATOMIC_RECORD_TNUM);
#endif
START_SYMBOLIC_TNUM(FIRST_EXTERNAL_TNUM);
START_SYMBOLIC_TNUM(FIRST_PACKAGE_TNUM);
const char *name = TNAM_TNUM(k);
Pr("%3d: %s" , k, (Int )indentStr);
Pr("%s%s\n" , (Int )indentStr, (Int )(name ? name : "." ));
if (name == 0 && k >= FIRST_PACKAGE_TNUM) {
// scan ahead and skip over all unused package slots
int i = k + 1 ;
while (i <= LAST_PACKAGE_TNUM && TNAM_TNUM(i) == 0 )
i++;
i--;
if (i > k + 1 )
Pr("... %s%s.\n" , (Int )indentStr, (Int )indentStr);
if (i > k) {
Pr("%3d: %s" , i, (Int )indentStr);
Pr("%s.\n" , (Int )indentStr, 0 );
}
k = i;
}
STOP_SYMBOLIC_TNUM(LAST_MULT_TNUM);
STOP_SYMBOLIC_TNUM(LAST_CONSTANT_TNUM);
STOP_SYMBOLIC_TNUM(LAST_RECORD_TNUM);
STOP_SYMBOLIC_TNUM(LAST_PLIST_TNUM);
STOP_SYMBOLIC_TNUM(LAST_LIST_TNUM);
STOP_SYMBOLIC_TNUM(LAST_OBJSET_TNUM);
STOP_SYMBOLIC_TNUM(LAST_IMM_MUT_TNUM);
#ifdef HPCGAP
STOP_SYMBOLIC_TNUM(LAST_SHARED_TNUM);
STOP_SYMBOLIC_TNUM(LAST_ATOMIC_RECORD_TNUM);
STOP_SYMBOLIC_TNUM(LAST_ATOMIC_LIST_TNUM);
STOP_SYMBOLIC_TNUM(LAST_ATOMIC_TNUM);
#endif
STOP_SYMBOLIC_TNUM(LAST_PACKAGE_TNUM);
STOP_SYMBOLIC_TNUM(LAST_EXTERNAL_TNUM);
STOP_SYMBOLIC_TNUM(LAST_REAL_TNUM);
}
return 0 ;
}
#undef START_SYMBOLIC_TNUM
#undef STOP_SYMBOLIC_TNUM
/****************************************************************************
* *
* F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
*/
/****************************************************************************
* *
* V BagNames . . . . . . . . . . . . . . . . . . . . . . . list of bag names
*/
static StructBagNames BagNames[] = {
{ T_COMOBJ, "component object" },
{ T_POSOBJ, "positional object" },
{ T_DATOBJ, "data object" },
#if !defined (USE_THREADSAFE_COPYING)
{ T_COPYING, "copy in progress" },
#endif
{ -1 , "" }
};
/****************************************************************************
* *
* V GVarFilts . . . . . . . . . . . . . . . . . . . list of filters to export
*/
static StructGVarFilt GVarFilts [] = {
GVAR_FILT(IS_MUTABLE_OBJ, "obj" , &IsMutableObjFilt),
GVAR_FILT(IS_COPYABLE_OBJ, "obj" , &IsCopyableObjFilt),
#ifdef HPCGAP
GVAR_FILT(IS_INTERNALLY_MUTABLE_OBJ, "obj" , &IsInternallyMutableObjFilt),
#endif
{ 0 , 0 , 0 , 0 , 0 }
};
/****************************************************************************
* *
* V GVarOpers . . . . . . . . . . . . . . . . . list of operations to export
*/
static StructGVarOper GVarOpers [] = {
GVAR_OPER_1ARGS(SHALLOW_COPY_OBJ, obj, &ShallowCopyObjOper),
GVAR_OPER_1ARGS(PRINT_OBJ, obj, &PrintObjOper),
GVAR_OPER_1ARGS(VIEW_OBJ, obj, &ViewObjOper),
{ 0 , 0 , 0 , 0 , 0 , 0 }
};
/****************************************************************************
* *
* V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
*/
static StructGVarFunc GVarFuncs[] = {
GVAR_FUNC_1ARGS(FAMILY_TYPE, type),
GVAR_FUNC_1ARGS(TYPE_OBJ, obj),
GVAR_FUNC_2ARGS(SET_TYPE_OBJ, obj, type),
GVAR_FUNC_1ARGS(FAMILY_OBJ, obj),
GVAR_FUNC_1ARGS(IMMUTABLE_COPY_OBJ, obj),
GVAR_FUNC_1ARGS(DEEP_COPY_OBJ, obj),
GVAR_FUNC_2ARGS(IS_IDENTICAL_OBJ, obj1, obj2),
GVAR_FUNC_1ARGS(IS_COMOBJ, obj),
GVAR_FUNC_2ARGS(SET_TYPE_COMOBJ, obj, type),
GVAR_FUNC_1ARGS(IS_POSOBJ, obj),
GVAR_FUNC_2ARGS(SET_TYPE_POSOBJ, obj, type),
GVAR_FUNC_1ARGS(LEN_POSOBJ, obj),
GVAR_FUNC_1ARGS(IS_DATOBJ, obj),
GVAR_FUNC_2ARGS(SET_TYPE_DATOBJ, obj, type),
GVAR_FUNC_2ARGS(CLONE_OBJ, dst, src),
GVAR_FUNC_2ARGS(SWITCH_OBJ, obj1, obj2),
GVAR_FUNC_2ARGS(FORCE_SWITCH_OBJ, obj1, obj2),
GVAR_FUNC_1ARGS(SET_PRINT_OBJ_INDEX, index),
GVAR_FUNC_1ARGS(MakeImmutable, obj),
GVAR_FUNC_1ARGS(GET_TNAM_FROM_TNUM, obj),
GVAR_FUNC_0ARGS(DEBUG_TNUM_NAMES),
{ 0 , 0 , 0 , 0 , 0 }
};
/****************************************************************************
* *
* F InitKernel ( < module > ) . . . . . . . . initialise kernel data structures
*/
static Int InitKernel (
StructInitInfo * module )
{
Int t; // loop variable
// set the bag type names (for error messages and debugging)
InitBagNamesFromTable( BagNames );
// install the marking methods
InitMarkFuncBags( T_COMOBJ , MarkPRecSubBags );
InitMarkFuncBags( T_POSOBJ , MarkAllSubBags );
InitMarkFuncBags( T_DATOBJ , MarkOneSubBags );
#if !defined (USE_THREADSAFE_COPYING) && !defined (USE_BOEHM_GC)
InitMarkFuncBags(T_COPYING, MarkCopyingSubBags);
#endif
for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(TypeObjFuncs[ t ] == 0 );
TypeObjFuncs[ t ] = TypeObjError;
}
TypeObjFuncs[ T_COMOBJ ] = TypeComObj;
TypeObjFuncs[ T_POSOBJ ] = TypePosObj;
TypeObjFuncs[ T_DATOBJ ] = TypeDatObj;
// functions for 'to-be-defined' objects
ImportFuncFromLibrary( "IsToBeDefinedObj" , &IsToBeDefinedObj );
ImportFuncFromLibrary( "PostMakeImmutable" , &PostMakeImmutableOp );
ImportGVarFromLibrary( "REREADING" , &REREADING );
ImportGVarFromLibrary( "TYPE_KERNEL_OBJECT" , &TYPE_KERNEL_OBJECT );
// init filters and functions
InitHdlrFiltsFromTable( GVarFilts );
InitHdlrOpersFromTable( GVarOpers );
InitHdlrFuncsFromTable( GVarFuncs );
// make and install the 'IS_MUTABLE_OBJ' filter
for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(IsMutableObjFuncs[ t ] == 0 );
IsMutableObjFuncs[ t ] = IsMutableObjError;
}
for ( t = FIRST_CONSTANT_TNUM; t <= LAST_CONSTANT_TNUM; t++ )
IsMutableObjFuncs[ t ] = AlwaysNo;
for ( t = FIRST_EXTERNAL_TNUM; t <= LAST_EXTERNAL_TNUM; t++ )
IsMutableObjFuncs[ t ] = IsMutableObjObject;
// make and install the 'IS_COPYABLE_OBJ' filter
for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(IsCopyableObjFuncs[ t ] == 0 );
IsCopyableObjFuncs[ t ] = IsCopyableObjError;
}
for ( t = FIRST_CONSTANT_TNUM; t <= LAST_CONSTANT_TNUM; t++ )
IsCopyableObjFuncs[ t ] = AlwaysNo;
for ( t = FIRST_EXTERNAL_TNUM; t <= LAST_EXTERNAL_TNUM; t++ )
IsCopyableObjFuncs[ t ] = IsCopyableObjObject;
// make and install the 'SHALLOW_COPY_OBJ' operation
for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(ShallowCopyObjFuncs[ t ] == 0 );
ShallowCopyObjFuncs[ t ] = ShallowCopyObjError;
}
for ( t = FIRST_CONSTANT_TNUM; t <= LAST_CONSTANT_TNUM; t++ )
ShallowCopyObjFuncs[ t ] = ShallowCopyObjConstant;
for ( t = FIRST_RECORD_TNUM; t <= LAST_RECORD_TNUM; t++ )
ShallowCopyObjFuncs[ t ] = ShallowCopyObjDefault;
for ( t = FIRST_LIST_TNUM; t <= LAST_LIST_TNUM; t++ )
ShallowCopyObjFuncs[ t ] = ShallowCopyObjDefault;
for ( t = FIRST_EXTERNAL_TNUM; t <= LAST_EXTERNAL_TNUM; t++ )
ShallowCopyObjFuncs[ t ] = ShallowCopyObjObject;
#ifdef USE_THREADSAFE_COPYING
SetTraversalMethod(T_POSOBJ, TRAVERSE_ALL_BUT_FIRST, 0 , 0 );
SetTraversalMethod(T_COMOBJ, TRAVERSE_BY_FUNCTION, TraversePRecord, CopyPRecord);
SetTraversalMethod(T_DATOBJ, TRAVERSE_NONE, 0 , 0 );
#else
// make and install the 'COPY_OBJ' function
for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(CopyObjFuncs [ t ] == 0 );
CopyObjFuncs [ t ] = CopyObjError;
assert(CleanObjFuncs[ t ] == 0 );
CleanObjFuncs[ t ] = CleanObjError;
}
for ( t = FIRST_CONSTANT_TNUM; t <= LAST_CONSTANT_TNUM; t++ ) {
CopyObjFuncs [ t ] = CopyObjConstant;
CleanObjFuncs[ t ] = 0 ;
}
CopyObjFuncs[ T_POSOBJ ] = CopyObjPosObj;
CleanObjFuncs[ T_POSOBJ ] = CleanObjPosObj;
CopyObjFuncs[ T_COMOBJ ] = CopyObjComObj;
CleanObjFuncs[ T_COMOBJ ] = CleanObjComObj;
CopyObjFuncs[ T_DATOBJ ] = CopyObjDatObj;
CleanObjFuncs[ T_DATOBJ ] = CleanObjDatObj;
#endif
// make and install the 'PRINT_OBJ' operation
for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(PrintObjFuncs[ t ] == 0 );
PrintObjFuncs[ t ] = PrintObjObject;
}
#ifdef GAP_ENABLE_SAVELOAD
// enter 'SaveObjError' and 'LoadObjError' for all types initially
for ( t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(SaveObjFuncs[ t ] == 0 );
SaveObjFuncs[ t ] = SaveObjError;
assert(LoadObjFuncs[ t ] == 0 );
LoadObjFuncs[ t ] = LoadObjError;
}
// install the saving functions
SaveObjFuncs[ T_COMOBJ ] = SaveComObj;
SaveObjFuncs[ T_POSOBJ ] = SavePosObj;
SaveObjFuncs[ T_DATOBJ ] = SaveDatObj;
// install the loading functions
LoadObjFuncs[ T_COMOBJ ] = LoadComObj;
LoadObjFuncs[ T_POSOBJ ] = LoadPosObj;
LoadObjFuncs[ T_DATOBJ ] = LoadDatObj;
#endif
for (t = FIRST_REAL_TNUM; t <= LAST_REAL_TNUM; t++ ) {
assert(MakeImmutableObjFuncs[ t ] == 0 );
MakeImmutableObjFuncs[t] = MakeImmutableError;
}
// install the makeimmutableing functions
MakeImmutableObjFuncs[ T_COMOBJ ] = MakeImmutableComObj;
MakeImmutableObjFuncs[ T_POSOBJ ] = MakeImmutablePosObj;
MakeImmutableObjFuncs[ T_DATOBJ ] = MakeImmutableDatObj;
#ifdef HPCGAP
ReadOnlyDatObjs = (getenv("GAP_READONLY_DATOBJS" ) != 0 );
#endif
return 0 ;
}
/****************************************************************************
* *
* F InitLibrary ( < module > ) . . . . . . . initialise library data structures
*/
static Int InitLibrary (
StructInitInfo * module )
{
// init filters and functions
InitGVarFiltsFromTable( GVarFilts );
InitGVarOpersFromTable( GVarOpers );
InitGVarFuncsFromTable( GVarFuncs );
// export certain TNUM values as global variable
ExportAsConstantGVar(FIRST_REAL_TNUM);
ExportAsConstantGVar(LAST_REAL_TNUM);
ExportAsConstantGVar(FIRST_CONSTANT_TNUM);
ExportAsConstantGVar(LAST_CONSTANT_TNUM);
ExportAsConstantGVar(FIRST_MULT_TNUM);
ExportAsConstantGVar(LAST_MULT_TNUM);
ExportAsConstantGVar(FIRST_IMM_MUT_TNUM);
ExportAsConstantGVar(LAST_IMM_MUT_TNUM);
ExportAsConstantGVar(FIRST_RECORD_TNUM);
ExportAsConstantGVar(LAST_RECORD_TNUM);
ExportAsConstantGVar(FIRST_LIST_TNUM);
ExportAsConstantGVar(LAST_LIST_TNUM);
ExportAsConstantGVar(FIRST_PLIST_TNUM);
ExportAsConstantGVar(LAST_PLIST_TNUM);
ExportAsConstantGVar(FIRST_OBJSET_TNUM);
ExportAsConstantGVar(LAST_OBJSET_TNUM);
ExportAsConstantGVar(FIRST_EXTERNAL_TNUM);
ExportAsConstantGVar(LAST_EXTERNAL_TNUM);
ExportAsConstantGVar(FIRST_PACKAGE_TNUM);
ExportAsConstantGVar(LAST_PACKAGE_TNUM);
#ifdef HPCGAP
ExportAsConstantGVar(FIRST_SHARED_TNUM);
ExportAsConstantGVar(LAST_SHARED_TNUM);
#endif
ExportAsConstantGVar(T_INT);
ExportAsConstantGVar(T_INTPOS);
ExportAsConstantGVar(T_INTNEG);
ExportAsConstantGVar(T_RAT);
ExportAsConstantGVar(T_CYC);
ExportAsConstantGVar(T_FFE);
ExportAsConstantGVar(T_PERM2);
ExportAsConstantGVar(T_PERM4);
ExportAsConstantGVar(T_TRANS2);
ExportAsConstantGVar(T_TRANS4);
ExportAsConstantGVar(T_PPERM2);
ExportAsConstantGVar(T_PPERM4);
ExportAsConstantGVar(T_BOOL);
ExportAsConstantGVar(T_CHAR);
ExportAsConstantGVar(T_FUNCTION);
ExportAsConstantGVar(T_BODY);
ExportAsConstantGVar(T_FLAGS);
ExportAsConstantGVar(T_MACFLOAT);
ExportAsConstantGVar(T_LVARS);
ExportAsConstantGVar(T_HVARS);
ExportAsConstantGVar(T_PREC);
ExportAsConstantGVar(T_PLIST);
ExportAsConstantGVar(T_PLIST_NDENSE);
ExportAsConstantGVar(T_PLIST_DENSE);
ExportAsConstantGVar(T_PLIST_DENSE_NHOM);
ExportAsConstantGVar(T_PLIST_DENSE_NHOM_SSORT);
ExportAsConstantGVar(T_PLIST_DENSE_NHOM_NSORT);
ExportAsConstantGVar(T_PLIST_EMPTY);
ExportAsConstantGVar(T_PLIST_HOM);
ExportAsConstantGVar(T_PLIST_HOM_NSORT);
ExportAsConstantGVar(T_PLIST_HOM_SSORT);
ExportAsConstantGVar(T_PLIST_TAB);
ExportAsConstantGVar(T_PLIST_TAB_NSORT);
ExportAsConstantGVar(T_PLIST_TAB_SSORT);
ExportAsConstantGVar(T_PLIST_TAB_RECT);
ExportAsConstantGVar(T_PLIST_TAB_RECT_NSORT);
ExportAsConstantGVar(T_PLIST_TAB_RECT_SSORT);
ExportAsConstantGVar(T_PLIST_CYC);
ExportAsConstantGVar(T_PLIST_CYC_NSORT);
ExportAsConstantGVar(T_PLIST_CYC_SSORT);
ExportAsConstantGVar(T_PLIST_FFE);
ExportAsConstantGVar(T_RANGE_NSORT);
ExportAsConstantGVar(T_RANGE_SSORT);
ExportAsConstantGVar(T_BLIST);
ExportAsConstantGVar(T_BLIST_NSORT);
ExportAsConstantGVar(T_BLIST_SSORT);
ExportAsConstantGVar(T_STRING);
ExportAsConstantGVar(T_STRING_NSORT);
ExportAsConstantGVar(T_STRING_SSORT);
ExportAsConstantGVar(T_OBJSET);
ExportAsConstantGVar(T_OBJMAP);
ExportAsConstantGVar(T_COMOBJ);
ExportAsConstantGVar(T_POSOBJ);
ExportAsConstantGVar(T_DATOBJ);
ExportAsConstantGVar(T_WPOBJ);
#ifdef HPCGAP
ExportAsConstantGVar(T_APOSOBJ);
ExportAsConstantGVar(T_ACOMOBJ);
ExportAsConstantGVar(T_THREAD);
ExportAsConstantGVar(T_MONITOR);
ExportAsConstantGVar(T_REGION);
ExportAsConstantGVar(T_SEMAPHORE);
ExportAsConstantGVar(T_CHANNEL);
ExportAsConstantGVar(T_BARRIER);
ExportAsConstantGVar(T_SYNCVAR);
ExportAsConstantGVar(T_FIXALIST);
ExportAsConstantGVar(T_ALIST);
ExportAsConstantGVar(T_AREC);
ExportAsConstantGVar(T_AREC_INNER);
ExportAsConstantGVar(T_TLREC);
ExportAsConstantGVar(T_TLREC_INNER);
#endif
#if !defined (USE_THREADSAFE_COPYING)
ExportAsConstantGVar(T_COPYING);
#endif
// export positions of data in type objects
ExportAsConstantGVar(POS_FAMILY_TYPE);
ExportAsConstantGVar(POS_FLAGS_TYPE);
ExportAsConstantGVar(POS_DATA_TYPE);
ExportAsConstantGVar(POS_NUMB_TYPE);
ExportAsConstantGVar(POS_FIRST_FREE_TYPE);
// export small integer limits
AssConstantGVar(GVarName("INTOBJ_MIN" ), INTOBJ_MIN);
AssConstantGVar(GVarName("INTOBJ_MAX" ), INTOBJ_MAX);
return 0 ;
}
/****************************************************************************
* *
* F InitInfoObjects ( ) . . . . . . . . . . . . . . . . table of init functions
*/
static StructInitInfo module = {
// init struct using C99 designated initializers; for a full list of
// fields, please refer to the definition of StructInitInfo
.type = MODULE_BUILTIN,
.name = "objects" ,
.initKernel = InitKernel,
.initLibrary = InitLibrary,
.moduleStateSize = sizeof (ObjectsModuleState),
.moduleStateOffsetPtr = &ObjectsStateOffset,
};
StructInitInfo * InitInfoObjects ( void )
{
return &module;
}
Messung V0.5 in Prozent C=86 H=97 G=91
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.40Bemerkung:
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland