/usr/share/yacas/include/lispobject.h is in yacas 1.3.3-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | /** \file lispobject.h
* Implementation of basic LispObject, which is the base class for
* anything that can be put in a linked list.
*
* class LispObject. This class implements one lisp object, which is a
* abstract class containing reference counting and a next pointer.
* derive from this to implement specific types of list elements.
* The local class LispPtr implements automatic garbage collection
* through reference counting.
*
*/
#ifndef __lispobject_h__
#define __lispobject_h__
#include "yacasbase.h"
#include "refcount.h"
#include "lispstring.h"
#include "genericobject.h"
#ifdef YACAS_DEBUG
#define DBG_(xxx) xxx
#else
#define DBG_(xxx) /*xxx*/
#endif
class LispObject;
class BigNumber;
/** class LispPtr. A LispPtr is a smart pointer to a LispObject.
* It does the reference counting, and consequent destruction if needed.
* LispPtr is used in LispObject as a pointer to the next object; and
* LispPtr::GoNext() advances one step in this LispObject::Nixed() chain.
* Diverse built-in functions use LispPtr to hold temporary values.
*/
typedef RefPtr<LispObject> LispPtr;
/** \class LispPtrArray is similar to LispPtr, but implements an array
* of pointers to objects.
*/
typedef CArrayGrower<LispPtr, ArrOpsCustomObj<LispPtr> > LispPtrArray;
#ifdef YACAS_DEBUG
void IncNrObjects();
void DecNrObjects();
#else
#define IncNrObjects()
#define DecNrObjects()
#endif
// Should we DecNrObjects by the delete, or in the destructor?
// Put a DecNrObjects_xxx() macro in both places, and CHOOSE here.
#define DecNrObjects_delete() DECNROBJECTS_CHOOSE(DecNrObjects(),)
#define DecNrObjects_destructor() DECNROBJECTS_CHOOSE(,DecNrObjects())
#define DECNROBJECTS_CHOOSE(bydelete,bydestructor) bydestructor
template <int> struct Undefined;
template <> struct Undefined<1>{};
/** class LispObject is the base object class that can be put in
* linked lists. It either has a pointer to a string, obtained through
* String(), or it is a holder for a sublist, obtainable through SubList(),
* or it is a generic object, in which case Generic() returns non-NULL.
* Only one of these three functions should return a non-NULL value.
* It is a reference-counted object. LispPtr handles the reference counting.
*/
class LispObject : public YacasBase
{
public:
inline LispPtr& Nixed();
public: //Derivables
virtual ~LispObject();
/** Return string representation, or NULL if the object doesn't have one.
* the string representation is only relevant if the object is a
* simple atom. This method returns NULL by default.
*/
virtual LispString * String() { return NULL; }
/** If this object is a list, return a pointer to it.
* Default behaviour is to return NULL.
*/
virtual LispPtr* SubList() { return NULL; }
virtual GenericClass* Generic() { return NULL; }
/** If this is a number, return a BigNumber representation
*/
virtual BigNumber* Number(LispInt aPrecision) { return NULL; }
virtual LispObject* Copy() = 0;
/** Return a pointer to extra info. This allows for annotating
* an object. Returns NULL by default.
* LispObject's implementation of this handles almost all derived classes.
*/
virtual LispObject* ExtraInfo() { return NULL; }
virtual LispObject* SetExtraInfo(LispObject* aData) = 0;
public:
LispInt Equal(LispObject& aOther);
inline LispInt operator==(LispObject& aOther);
inline LispInt operator!=(LispObject& aOther);
DBG_( LispChar * iFileName; )
DBG_( LispInt iLine; )
inline void SetFileAndLine(LispChar * aFileName, LispInt aLine)
{
DBG_( iFileName = aFileName; )
DBG_( iLine = aLine; )
}
protected:
inline LispObject() :
#ifdef YACAS_DEBUG
iFileName(NULL),iLine(0),
#endif // YACAS_DEBUG
iNext(),iReferenceCount()
{
IncNrObjects();
DBG_( iFileName = NULL; )
DBG_( iLine = 0; )
}
inline LispObject(const LispObject& other) :
#ifdef YACAS_DEBUG
iFileName(other.iFileName),iLine(other.iLine),
#endif // YACAS_DEBUG
iNext(),iReferenceCount()
{
IncNrObjects();
}
inline LispObject& operator=(const LispObject& other)
{
#ifdef YACAS_DEBUG
iFileName = other.iFileName;
iLine = other.iLine;
#endif // YACAS_DEBUG
IncNrObjects();
return *this;
}
private:
LispPtr iNext;
public:
ReferenceCount iReferenceCount;
};
template <class T>
class WithExtraInfo : public T
{
public:
WithExtraInfo(T& aT, LispObject* aData = 0) : T(aT), iExtraInfo(aData) {}
WithExtraInfo(const WithExtraInfo& other) : T(other), iExtraInfo(other.iExtraInfo) {}
virtual LispObject* ExtraInfo() { return iExtraInfo; }
virtual LispObject* SetExtraInfo(LispObject* aData) { iExtraInfo = aData; return this; }
virtual LispObject* Copy()
{
if (!iExtraInfo.ptr()) return T::Copy();
return NEW WithExtraInfo(*this, iExtraInfo->Copy());
}
private:
LispPtr iExtraInfo;
};
template <class T, class U = LispObject>
class ObjectHelper : public U
{
protected:
typedef ObjectHelper ASuper; // for use by the derived class
ObjectHelper() {}
ObjectHelper(const ObjectHelper& other) : U(other) {}
virtual ~ObjectHelper() = 0; // so we're abstract
virtual LispObject* SetExtraInfo(LispObject* aData)
{
if (!aData) return this;
//T * pT = dynamic_cast<T*>(this); LISPASSERT(pT);
LispObject * pObject = NEW WithExtraInfo<T>(*static_cast<T*>(this), aData);
return pObject;
}
};
template <typename T, class U>
inline ObjectHelper<T,U>::~ObjectHelper() {}
/**
* class LispIterator works almost like LispPtr, but doesn't enforce
* reference counting, so it should be faster. Use LispIterator
* (instead of LispPtr) to traverse a lisp expression non-destructively.
*/
class LispIterator : public YacasBase
{
public:
// ala TEMPLATE CLASS iterator
//typedef forward_iterator_tag iterator_category;
typedef LispPtr value_type;
typedef int /*ptrdiff_t*/ difference_type;
typedef LispPtr* pointer;
typedef LispPtr& reference;
public:
LispIterator() : _Ptr(0) {} // construct with null node pointer
LispIterator(pointer ptr) : _Ptr(ptr) {} // construct with node pointer
/*non-standard*/ LispIterator(reference ref) : _Ptr(&ref) {} // construct with node reference
reference operator*() const { return (*(_Ptr)); } // return designated value
pointer operator->() const { return (_Ptr); } // return pointer to class object
inline LispIterator& operator++() // preincrement
{
//precondition: _Ptr != NULL
LISPASSERT(_Ptr != NULL);
//expand: _Ptr = _Nextnode(_Ptr);
LispObject * pObj = _Ptr->operator->();
_Ptr = pObj ? &(pObj->Nixed()) : NULL;
return (*this);
}
LispIterator operator++(int) { LispIterator _Tmp = *this; ++*this; return (_Tmp); } // postincrement
bool operator==(const LispIterator& other) const { return (_Ptr == other._Ptr); } // test for iterator equality
bool operator!=(const LispIterator& other) const { return (!(*this == other)); } // test for iterator inequality
// The following operators are not used yet, and would need to be tested before used.
//LispIterator& operator--() { _Ptr = _Prevnode(_Ptr); return (*this); } // predecrement
//LispIterator operator--(int) { LispIterator _Tmp = *this; --*this; return (_Tmp); } // postdecrement
protected:
pointer _Ptr; // pointer to node
public:
inline LispObject* getObj() const { return (*_Ptr).operator->(); }
};
#include "lispobject.inl"
#endif
|