00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00037
00038
00039
00040
00041
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
00080 if (!out.nextname.isEmpty()) {
00081 out.print (out.nextname);
00082 out.print ("=");
00083 out.nextname="";
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
00099 obj << in;
00100
00101 return in;
00102 }
00103
00105
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
00184
00185
00186
00187
00188
00189
00190
00191 return (**(const Comparable**)a).compare ((**(const Comparable**)b));
00192 }
00193
00194
00195
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
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
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
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;
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
00333 mallocinfostr* p = (mallocinfostr*) malloc (size+sizeof(mallocinfostr));
00334 if (!p)
00335 *((char*)0x0)=0;
00336
00337 strcpy (p->startsym, "MiS_S");
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
00354 memset (((char*)p)+sizeof (mallocinfostr), '\xcc', p->size);
00355
00356
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
00369 if (!res)
00370 *((char*)0x0)=0;
00371 return res;
00372 } else {
00373
00374 mallocinfostr* np = (mallocinfostr*) realloc (((char*)p)-sizeof(mallocinfostr),
00375 newsize+sizeof(mallocinfostr));
00376
00377 if (!np)
00378 *((char*)0x0)=0;
00379
00380 dbgnewmalloced -= np->size;
00381 np->size = newsize;
00382 np->filename = filename;
00383 np->lineno = lineno;
00384 np->funcname = fname;
00385 if (newcomment) {
00386 free (np->newcomment);
00387 np->newcomment = newcomment;
00388 newcomment = NULL;
00389 }
00390 np->renewed = true;
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;
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);
00406 } else {
00407 mallocinfostr* mp=(mallocinfostr*)(((char*)p)-sizeof(mallocinfostr));
00408
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
00424 memset (mp, '\xdd', mp->size + sizeof (mallocinfostr));
00425
00426 free (mp);
00427 }
00428 }
00429 }
00430
00431
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