#include "Col.ph" #ifdef __GNUG__ #pragma implementation #endif #include "Class.h" #include "Error.h" #include "Storage.h" #include "String.h" #include "ObjArray.h" #include "OrdColl.h" #include "ObjectTable.h" #include "ClassManager.h" #include "Env.h" #include "AccessMem.h" #include "ET_stdio.h" static const double cClassVersion= 3.1; #ifdef ET_ static char *EtPrefix= _QUOTE_(ET_); #else static char *EtPrefix= ""; #endif extern void _InitModule(), _TermModule(); //---- Class ------------------------------------------------------------------- NewMetaImpl(Class,Object, (T(version), TP(super), TP(className), T(size), TP(proto), TS(declFileName), T(declFileLine), TS(implFileName), T(implFileLine), TP(subclasses), T(instanceCount), TP(methods))); Class *Class::classptr; Class::Class(const char *name, int sz, Object *pro, const char *implfn, const char *declfn, int il, int dl, bool abstract, double vers) { Init(name, sz, pro, implfn, declfn, il, dl, abstract, vers); showfunc= 0; } Class::Class(const char *name, int sz, Class *sup, Object *pro, const char *implfn, const char *declfn, int il, int dl, bool abstract, double vers) { Init(name, sz, pro, implfn, declfn, il, dl, abstract, vers); showfunc= 0; super= sup; } Class::Class(const char *name, int sz, const char *implfn, int il, classShowFunc f) { Init(name, sz, 0, implfn, implfn, il, il, FALSE, cClassVersion); showfunc= f; } Class::Class(const char *name, double vers) { className= name; version= vers; proto= 0; methods= 0; subclasses= 0; showfunc= 0; } void Class::Init(const char *name, int sz, Object *pro, const char *implfn, const char *declfn, int il, int dl, bool abstract, double vers) { size= sz; if (vers == 0.0) version= cClassVersion; else version= vers; className= name; if (strncmp(name, EtPrefix, sizeof(EtPrefix)-1) == 0) className= &name[sizeof(EtPrefix)-1]; if (gDebug) fprintf(stderr, "%s\n", className); declFileName= declfn; implFileName= implfn; declFileLine= dl; implFileLine= il; proto= pro; subclasses= 0; instanceCount= 0; methods= 0; SetFlag(eClassAbstract, abstract); if (gClassManager == 0) gClassManager= new ClassManager; gClassManager->Add(this); SetFlag(eClassObject, proto != 0); classptr= 0; _InitModule(); } Class::~Class() { if (proto) { delete (void*) proto; // avoid call of destructor for prototype proto= 0; } if (methods) { methods->FreeAll(); SafeDelete(methods); } SafeDelete(subclasses); if (gClassManager && gClassManager->Remove(this)) _TermModule(); } //---- class hierarchy --------------------------------------------------------- void Class::SetSuper() { super= classptr; classptr= this; } bool Class::isKindOf(register Class *c) { register Class *cc; for (cc= this; cc; cc= cc->super) if (cc == c) return TRUE; return FALSE; } void Class::AddSubclass(Class *cl) { if (subclasses == 0) subclasses= new OrdCollection; subclasses->Add(cl); } Iterator *Class::SubclassIterator() { if (subclasses == 0) subclasses= new OrdCollection; return subclasses->MakeIterator(); } //---- comparing --------------------------------------------------------------- u_long Class::Hash() { register u_long hash; register const char *p= className; for (hash= 0; *p; p++) hash= (hash << 1) ^ *p; return hash; } bool Class::IsEqual(Object *op) { if (!op->IsKindOf(Class)) return FALSE; return strcmp(className, ((Class*)op)->className) == 0; } int Class::Compare(Object *op) { return strcmp(className, Guard(op,Class)->className); } //---- converting, input/output ------------------------------------------------ const char *Class::AsString() { return (char*) className; } void Class::Show(char *buf, void *addr, int l, bool isptr) { if (showfunc) { showfunc(buf, addr, l, isptr); } else { if (isptr) { if (ObjectTable::PtrIsValid((Object*)addr)) sprintf(buf, "<%s>", ((Object*)addr)->ClassName()); } else sprintf(buf, ""); } } OStream &Class::PrintOn(OStream &os) { return os << className SP << cClassVersion SP; } // always called on prototype object !!! Object *Class::ReadAndMap(IStream &is) { char name[100]; double vers; is >> name >> vers; Class *clp= gClassManager->FindOrLoad(name, vers); if (clp) { if (vers < clp->Version()) fprintf(stderr, "older version of: %s (%g)\n", name, vers); else if (vers > clp->Version()) fprintf(stderr, "newer version of: %s (%g)\n", name, vers); clp->SetLoadVersion(vers); } return clp; } //---- members ----------------------------------------------------------------- Object *Class::SomeMember() { return ObjectTable::SomeMember(this); } void Class::EnumerateMyMembers(AccessMembers *ac) { if (className && ac) ac->ClassName((char*)className); if (proto) proto->Members(ac); } void Class::EnumerateMembers(AccessMembers *ac) { EnumerateMyMembers(ac); if (super) super->EnumerateMembers(ac); } Object *Class::SomeInstance() { return ObjectTable::SomeInstance(this); }