Main Page   Class Hierarchy   Compound List   File List   Compound Members  

mobject.cc

00001 /***************************************************************************
00002  *   This file is part of the MagiC++ library.                             *
00003  *                                                                         *
00004  *   Copyright (C) 1998-2001 Marko Grönroos <magi@iki.fi>                  *
00005  *                                                                         *
00006  ***************************************************************************
00007  *                                                                         *
00008  *  This library is free software; you can redistribute it and/or          *
00009  *  modify it under the terms of the GNU Library General Public            *
00010  *  License as published by the Free Software Foundation; either           *
00011  *  version 2 of the License, or (at your option) any later version.       *
00012  *                                                                         *
00013  *  This library is distributed in the hope that it will be useful,        *
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
00016  *  Library General Public License for more details.                       *
00017  *                                                                         *
00018  *  You should have received a copy of the GNU Library General Public      *
00019  *  License along with this library; see the file COPYING.LIB.  If         *
00020  *  not, write to the Free Software Foundation, Inc., 59 Temple Place      *
00021  *  - Suite 330, Boston, MA 02111-1307, USA.                               *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #include <iostream.h>
00026 #include <malloc.h>
00027 #include <stdlib.h>
00028 
00029 #include "magic/mobject.h"
00030 #include "magic/mclass.h"
00031 #include "magic/mmath.h"
00032 #include "magic/mmagisupp.h"
00033 
00034 decl_module (object);
00035 
00036 //- Standard object.hierarchy<BR>
00037 //- Käytetty seuraavissa käyttöympäristöissä, vaikkakaan yhteensopivuus
00038 //- ei välttämättä ole täysin ajan tasalla:
00039 //-      MSDOS Borland C++ 3.0
00040 //-      Unix gcc 2.7.0 C++ (Solaris, Linux)
00041 //-      Unix egcs C++ (Solaris, Linux)
00042 
00043 
00044 const char nullchar = '\x00';
00045 FILE* dbgout = stderr;
00046 
00047 impl_abstract (Object, {})
00048 impl_abstract (Comparable, {Object});
00049 impl_dynamic (Int, {Comparable})
00050 
00051 ostream& operator<< (ostream& out, const Object& obj) {
00052     obj >> out;
00053     return out;
00054 }
00055 
00056 istream& operator>> (istream& in, Object& obj) {
00057     obj << in;
00058     return in;
00059 }
00060 
00061 OStream& operator<< (OStream& out, const Object& obj) {
00062     obj >> out;
00063     return out;
00064 }
00065 
00066 CArchive& operator<< (CArchive& out, const Object& obj) {
00067     if (out.mode & DUMP_TEXT)
00068         out.printComma ();
00069     out.depth++;
00070     if (out.mode & DUMP_RECORD) {
00071         if (out.depth==1)
00072             obj >> out;
00073         else
00074             out.attribs->add (new String (out.nextname));
00075     } else {
00076         if (out.mode & DUMP_TEXT) {
00077             if ((out.mode & DUMP_CLASSNAMES) && !isnull (obj.getclass().getname()))
00078                 out.print (obj.getclass().getname());
00079             //      , out.print ("::");
00080             if (!out.nextname.isEmpty()) {
00081                 out.print (out.nextname);
00082                 out.print ("=");
00083                 out.nextname="";  // NULL originally, but causes ambiquity with some compilers
00084             }
00085             out.print ("{");
00086         }
00087 
00088         obj >> out;
00089 
00090         if (out.mode & DUMP_TEXT)
00091             out.print ("}");
00092     }
00093     out.depth--;
00094     return out;
00095 }
00096 
00097 IStream& operator>> (IStream& in, Object& obj) {
00098     // in.depth++;
00099     obj << in;
00100     // in.depth--;
00101     return in;
00102 }
00103 
00105 //                       ___          o                                      //
00106 //                      |   | |          ___   ___   |                       //
00107 //                      |   | |---    | /   ) |   \ -+-                      //
00108 //                      |   | |   )   | |---  |      |                       //
00109 //                      `___´ |__/  \_|  \__   \__/   \                      //
00111 
00112 Object::~Object () {
00113 }
00114 
00115 ostream& Object::operator>> (ostream& out) const {return out;}
00116 
00117 istream& Object::operator<< (istream& in) {return in;}
00118 
00119 CArchive& Object::operator>> (CArchive& out) const {return out;}
00120 
00121 void Object::operator>> (OStream& out) const {;}
00122 
00123 IStream& Object::operator<< (IStream& in) {return in;}
00124 
00125 Object* Object::clone () const {
00126     MUST_OVERLOAD;
00127     return NULL;
00128 }
00129 
00130 bool Object::isOK () const {
00131     try {
00132         check ();
00133     } catch (...) {
00134         return false;
00135     }
00136     return true;
00137 }
00138 
00139 const String& Object::getclassname () const {
00140     return getclass().getname ();
00141 }
00142 
00143 int Object::is_a (const String& classname) const {
00144     return getclass().getname () == classname;
00145 }
00146 
00147 bool nextNewIsObject = false;
00148 
00149 #ifdef DEBUG_OBJECT_NEW
00150 #ifdef new
00151 #undef new
00152 void* Object::operator new[] (size_t size, const char* filen, int lineno, const char* funcn) {
00153     nextNewIsObject = true;
00154     return ::operator new[] (size, filen, lineno, funcn);
00155 }
00156 
00157 void* Object::operator new (size_t size, const char* filen, int lineno, const char* funcn) {
00158     nextNewIsObject = true;
00159     return ::operator new[] (size, filen, lineno, funcn);
00160 }
00161 
00162 void* Object::operator new[] (size_t size) {
00163     nextNewIsObject = true;
00164     return ::operator new[] (size, "unknown", -1, "unknown");
00165 }
00166 
00167 void* Object::operator new (size_t size) {
00168     nextNewIsObject = true;
00169     return ::operator new[] (size, "unknown", -1, "unknown");
00170 }
00171 #define new DEBUG_NEW
00172 #endif
00173 #endif
00174 
00175 
00177 
00178 
00180 
00181 int compareComparable   (const void* a, const void* b) {
00182     /*
00183       // :WEIRDNESS: The code below crashes... What's the difference
00184       ASSERT (a);
00185       ASSERT (b);
00186       const Comparable& ac = *static_cast<const Comparable*> (a);
00187       const Comparable& bc = *static_cast<const Comparable*> (b);
00188       return ac.compare (bc);
00189       */
00190 
00191     return (**(const Comparable**)a).compare ((**(const Comparable**)b));
00192 }
00193 /*
00194 int compareComparable   (const void* a, const void* b) {
00195     return (**(const Comparable**)a).compare ((**(const Comparable**)b));
00196 }
00197 */
00198 
00200 
00201 Int::Int (const String& o) {
00202     data = o.toInt();
00203 }
00204 
00205 int Int::operator == (const Comparable& o) const {
00206     if (o.is_a ("Int"))
00207         return data==((const Int&)o).data;
00208 }
00209 
00210 
00211 
00213 // Apufunktioita
00214 
00215 
00216 CPPModule::CPPModule (const char* n) {
00217     name = strdup (n);
00218     #ifdef MODULEDEBUG
00219     printf ("Module %s loading...\n", name);
00220     #endif
00221 }
00222 
00223 
00224 //
00225 
00226 int rnd (int range) {
00227     return (int) (double(range)*rand()/(RAND_MAX+1.0));
00228 }
00229 
00230 double frnd () {
00231     return rand()/(RAND_MAX+1.0);
00232 }
00233 
00234 double gaussrnd (double stdv) {
00235     if (stdv>0.0) {
00236         double r = rand()/(RAND_MAX+1.0)-0.5;
00237         return stdv * log ((r+0.5)/(0.5-r));
00238     }
00239     return 0.0;
00240 }
00241 
00242 // From mmagisupp.h
00243 
00244 Exception::Exception (const String& what_arg) : mWhat (new String (what_arg)) {
00245 }
00246 
00247 Exception::Exception (const Exception& orig) : mWhat (new String (*orig.mWhat)) {
00248 }
00249 
00250 Exception::~Exception () {
00251     delete mWhat;
00252 }
00253 
00254 
00256 //                                                                          //
00257 //              _                             o                             //
00258 //             / \   ____  ____  ___       |           _    ____            //
00259 //            /   \ (     (     /   ) |/\ -+- |  __  |/ \  (                //
00260 //            |---|  \__   \__  |---  |    |  | /  \ |   |  \__             //
00261 //            |   | ____) ____)  \__  |     \ | \__/ |   | ____)            //
00262 //                                                                          //
00264 
00265 int assertmode=ASSERT_THROW;
00266 
00267 void assertwith (const char* filename, int lineno, const char* funcname,
00268                  const char* condition, const char* message) {
00269     String errormsg = format("Condition '%s' violated at %s[%d]: %s()",
00270                                condition, filename, lineno, funcname);
00271     if (message)
00272         errormsg += format ("\n%%ERR: %s", message);
00273 
00274     switch (assertmode) {
00275       case ASSERT_CRASH:
00276           fprintf (stderr, "\n%%ERR: %s\n", (CONSTR) errormsg);
00277           fprintf (stderr, "%%ERR: Intentional assertion crash. "
00278                    "I hope you are under debugger now...\n");
00279           *((int*)NULL) = 1; // So you're under debugger. Ok, now just backtrace
00280           break;
00281       case ASSERT_EXIT:
00282           fprintf (stderr, "\n%%ERR: %s\n", (CONSTR) errormsg);
00283           exit (1);
00284           break;
00285       case ASSERT_DONTCARE:
00286           fprintf (stderr, "\n%%ERR: %s\n", (CONSTR) errormsg);
00287           break;
00288       case ASSERT_THROW:
00289       default:
00290           throw assertion_failed (format ("%s", (CONSTR)errormsg));
00291     };
00292 }
00293 
00294 
00295 
00304 
00305 #ifndef DISABLE_ALL_MEMORY_DEBUGGING
00306 #ifdef new
00307 #undef new
00308 #endif
00309 #warning "Memory debugging enabled"
00310 
00311 int dbgnewmalloced=0;
00312 mallocinfostr* lastmalloced=NULL;
00313 int newtrace_disabled = 1;
00314 char* newcomment=NULL;
00315 
00316 void newComment (const char* comment) {
00317     if (newcomment)
00318         free (newcomment);
00319     newcomment = strdup(comment);
00320 }
00321 
00322 
00323 void* operator new[] (size_t size, const char* filename, int lineno, const char* fname) {
00324     
00325     if (newtrace_disabled) {
00326         void* res = malloc(size);
00327         if (!res)
00328             *((char*)0x0)=0;
00329         return res;
00330     }
00331 
00332     // Reserve the memory block PLUS space for the info structure
00333     mallocinfostr* p = (mallocinfostr*) malloc (size+sizeof(mallocinfostr));
00334     if (!p)
00335         *((char*)0x0)=0;
00336 
00337     strcpy (p->startsym, "MiS_S");  // Set a recognition label
00338     p->size         = size;
00339     p->filename     = filename;
00340     p->lineno       = lineno;
00341     p->funcname     = fname;
00342     p->newcomment   = newcomment? newcomment : NULL;
00343     newcomment      = NULL;
00344     p->renewed      = false;
00345     p->isObject     = nextNewIsObject;
00346     nextNewIsObject = false;
00347     p->prev         = lastmalloced;
00348     p->next         = NULL;
00349     if (p->prev)
00350         p->prev->next = p;
00351     lastmalloced    = p;
00352     
00353     // Fill with 0x00
00354     memset (((char*)p)+sizeof (mallocinfostr), '\xcc', p->size);
00355 
00356     // Add to global counter
00357     dbgnewmalloced += size + sizeof(mallocinfostr);
00358     return ((char*)p)+sizeof (mallocinfostr);
00359 }
00360 
00361 void* operator new (size_t size, const char* filename, int lineno, const char* fname) {
00362     return operator new[] (size, filename, lineno, fname);
00363 }
00364 
00365 void* _renew (void* p, size_t newsize, const char* filename, int lineno, const char* fname) {
00366     if (memcmp (((char*)p)-sizeof(mallocinfostr), "MiS_S", 5) || newtrace_disabled) {
00367         void* res = realloc ((char*) p, newsize);
00368         // Again, should not be null
00369         if (!res)
00370             *((char*)0x0)=0;
00371         return res;
00372     } else {
00373         // Realloc the memory block PLUS space for the info structure
00374         mallocinfostr* np = (mallocinfostr*) realloc (((char*)p)-sizeof(mallocinfostr),
00375                                                       newsize+sizeof(mallocinfostr));
00376         // Again, should not be null
00377         if (!np)
00378             *((char*)0x0)=0;
00379         
00380         dbgnewmalloced -= np->size; // Substract old size from total size register
00381         np->size = newsize;         // Refresh
00382         np->filename = filename;    // Refresh
00383         np->lineno = lineno;        // Refresh
00384         np->funcname = fname;       // Refresh
00385         if (newcomment) {           // Refresh
00386             free (np->newcomment);
00387             np->newcomment = newcomment;
00388             newcomment = NULL;
00389         }
00390         np->renewed = true;         // Now we have been renewed
00391         if (np->prev)
00392             np->prev->next = np;
00393         if (np->next)
00394             np->next->prev = np;
00395         if ((void*) (((char*)p)-sizeof(mallocinfostr)) == (void*) lastmalloced)
00396             lastmalloced = np;
00397         dbgnewmalloced += newsize;  // Add new size to total size register
00398         return ((char*)np)+sizeof (mallocinfostr);
00399     }
00400 }
00401 
00402 void operator delete (void* p) {
00403     if (p) {
00404         if (memcmp (((char*)p)-sizeof(mallocinfostr), "MiS_S", 5)) {
00405             free (p); // Allocated with ordinary malloc or new
00406         } else {
00407             mallocinfostr* mp=(mallocinfostr*)(((char*)p)-sizeof(mallocinfostr));
00408             //TRACE3 ("%d, %s, %d", mp->size, mp->filename, mp->lineno);
00409             if (mp->next)
00410                 mp->next->prev = mp->prev; 
00411             if (mp->prev)
00412                 mp->prev->next = mp->next;
00413             if (mp == lastmalloced)
00414                 if (mp->next)
00415                     while (lastmalloced->next)
00416                         lastmalloced=lastmalloced->next;
00417                 else
00418                     lastmalloced = mp->prev;
00419             if (mp->newcomment)
00420                 free (mp->newcomment);
00421             dbgnewmalloced -= mp->size + sizeof (mallocinfostr);
00422 
00423             // Fill the block with 0xdd
00424             memset (mp, '\xdd', mp->size + sizeof (mallocinfostr));
00425 
00426             free (mp);
00427         }
00428     }
00429 }
00430 
00431 // int listAllocationsLimit=100;
00432 
00433 void list_allocations (int number, FILE* out) {
00434     fprintf (out, "Dumping all reserved memory blocks:\n");
00435     int i=0;
00436     for (mallocinfostr* p=lastmalloced; p && (number==0 || i<number); p=p->prev, i++) {
00437         fprintf (out, "%9d bytes (%8x) %s at %s#%d %s",
00438                  p->size, ((char*)p)+sizeof (mallocinfostr),
00439                  (p->renewed)? "renewed  ":"allocated", 
00440                  p->filename, p->lineno, p->funcname);
00441         if (p->isObject) {
00442             Object* op = (Object*)(void*)(((char*)p)+sizeof(mallocinfostr));
00443             fprintf (out, " (%s)", (CONSTR) op->getclassname());
00444         }
00445         if (p->newcomment)
00446             fprintf (out, " : \042%s\042", (CONSTR) p->newcomment);
00447         fprintf (out, "\n");
00448     }
00449     if (number>0 && i>=number)
00450         fprintf (out, "** Only %d first items listed\n", number);
00451     fprintf (out, "Total amount of memory allocated: %d "
00452              "(including the DEBUG_NEW overhead)\n", dbgnewmalloced);
00453 }
00454 
00455 #endif

Generated at Tue Dec 4 19:53:26 2001 for MagiC++ by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001