00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "pnotify.h"
00016 #include "notifyCategory.h"
00017 #include "configPageManager.h"
00018 #include "configVariableFilename.h"
00019 #include "configVariableBool.h"
00020 #include "filename.h"
00021 #include "config_prc.h"
00022
00023 #include <ctype.h>
00024
00025 #ifdef BUILD_IPHONE
00026 #include <fcntl.h>
00027 #endif
00028
00029 Notify *Notify::_global_ptr = (Notify *)NULL;
00030
00031
00032
00033
00034
00035
00036 Notify::
00037 Notify() {
00038 _ostream_ptr = &cerr;
00039 _owns_ostream_ptr = false;
00040 _null_ostream_ptr = new fstream;
00041
00042 _assert_handler = (AssertHandler *)NULL;
00043 _assert_failed = false;
00044 }
00045
00046
00047
00048
00049
00050
00051 Notify::
00052 ~Notify() {
00053 if (_owns_ostream_ptr) {
00054 delete _ostream_ptr;
00055 }
00056 delete _null_ostream_ptr;
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 void Notify::
00069 set_ostream_ptr(ostream *ostream_ptr, bool delete_later) {
00070 if (_owns_ostream_ptr && ostream_ptr != _ostream_ptr) {
00071 delete _ostream_ptr;
00072 }
00073
00074 if (ostream_ptr == (ostream *)NULL) {
00075 _ostream_ptr = &cerr;
00076 _owns_ostream_ptr = false;
00077 } else {
00078 _ostream_ptr = ostream_ptr;
00079 _owns_ostream_ptr = delete_later;
00080 }
00081 }
00082
00083
00084
00085
00086
00087
00088
00089 ostream *Notify::
00090 get_ostream_ptr() const {
00091 return _ostream_ptr;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 ios_fmtflags Notify::
00109 get_literal_flag() {
00110 static bool got_flag = false;
00111 static ios_fmtflags flag;
00112
00113 if (!got_flag) {
00114 #ifndef PHAVE_IOSTREAM
00115 flag = ios::bitalloc();
00116 #else
00117
00118
00119 flag = (ios_fmtflags)0;
00120 #endif
00121 got_flag = true;
00122 }
00123
00124 return flag;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 void Notify::
00144 set_assert_handler(Notify::AssertHandler *assert_handler) {
00145 _assert_handler = assert_handler;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 void Notify::
00155 clear_assert_handler() {
00156 _assert_handler = (AssertHandler *)NULL;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165 bool Notify::
00166 has_assert_handler() const {
00167 return (_assert_handler != (AssertHandler *)NULL);
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 Notify::AssertHandler *Notify::
00177 get_assert_handler() const {
00178 return _assert_handler;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 bool Notify::
00202 has_assert_failed() const {
00203 return _assert_failed;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212 const string &Notify::
00213 get_assert_error_message() const {
00214 return _assert_error_message;
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 void Notify::
00224 clear_assert_failed() {
00225 _assert_failed = false;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 NotifyCategory *Notify::
00237 get_top_category() {
00238 return get_category(string());
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 NotifyCategory *Notify::
00250 get_category(const string &basename, NotifyCategory *parent_category) {
00251
00252 nassertr(basename.find(':') == string::npos, (NotifyCategory *)NULL);
00253
00254 string fullname;
00255 if (parent_category != (NotifyCategory *)NULL) {
00256 fullname = parent_category->get_fullname() + ":" + basename;
00257 } else {
00258
00259
00260
00261
00262 if (!basename.empty()) {
00263 parent_category = get_top_category();
00264 fullname = ":" + basename;
00265 }
00266 }
00267
00268 pair<Categories::iterator, bool> result =
00269 _categories.insert(Categories::value_type(fullname, (NotifyCategory *)NULL));
00270
00271 bool inserted = result.second;
00272 NotifyCategory *&category = (*result.first).second;
00273
00274 if (inserted) {
00275
00276
00277
00278 category = new NotifyCategory(fullname, basename, parent_category);
00279 }
00280
00281 return category;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 NotifyCategory *Notify::
00295 get_category(const string &basename, const string &parent_fullname) {
00296 return get_category(basename, get_category(parent_fullname));
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 NotifyCategory *Notify::
00311 get_category(const string &fullname) {
00312 Categories::const_iterator ci;
00313 ci = _categories.find(fullname);
00314 if (ci != _categories.end()) {
00315 return (*ci).second;
00316 }
00317
00318
00319
00320 NotifyCategory *parent_category = (NotifyCategory *)NULL;
00321 string basename = fullname;
00322
00323 size_t colon = fullname.rfind(':');
00324 if (colon != string::npos) {
00325 parent_category = get_category(fullname.substr(0, colon));
00326 basename = fullname.substr(colon + 1);
00327
00328 } else if (!fullname.empty()) {
00329
00330 parent_category = get_top_category();
00331 }
00332
00333 return get_category(basename, parent_category);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 ostream &Notify::
00345 out() {
00346 return *(ptr()->_ostream_ptr);
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356 ostream &Notify::
00357 null() {
00358 return *(ptr()->_null_ostream_ptr);
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 void Notify::
00370 write_string(const string &str) {
00371 out() << str << "\n";
00372 }
00373
00374
00375
00376
00377
00378
00379
00380 Notify *Notify::
00381 ptr() {
00382 if (_global_ptr == (Notify *)NULL) {
00383 init_memory_hook();
00384 _global_ptr = new Notify;
00385 }
00386 return _global_ptr;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 bool Notify::
00404 assert_failure(const string &expression, int line,
00405 const char *source_file) {
00406 return assert_failure(expression.c_str(), line, source_file);
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 bool Notify::
00424 assert_failure(const char *expression, int line,
00425 const char *source_file) {
00426 ostringstream message_str;
00427 message_str
00428 << expression << " at line " << line << " of " << source_file;
00429 string message = message_str.str();
00430
00431 if (!_assert_failed) {
00432
00433
00434 _assert_failed = true;
00435 _assert_error_message = message;
00436 }
00437
00438 if (has_assert_handler()) {
00439 return (*_assert_handler)(expression, line, source_file);
00440 }
00441
00442 nout << "Assertion failed: " << message << "\n";
00443
00444
00445
00446 ConfigVariableBool assert_abort("assert-abort", false);
00447 if (assert_abort) {
00448 #ifdef WIN32
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 int *ptr = (int *)NULL;
00465 *ptr = 1;
00466
00467 #else // WIN32
00468 abort();
00469 #endif // WIN32
00470 }
00471
00472 return true;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482 NotifySeverity Notify::
00483 string_severity(const string &str) {
00484
00485
00486 string lstring;
00487 for (string::const_iterator si = str.begin();
00488 si != str.end();
00489 ++si) {
00490 lstring += tolower(*si);
00491 }
00492
00493 if (lstring == "spam") {
00494 return NS_spam;
00495
00496 } else if (lstring == "debug") {
00497 return NS_debug;
00498
00499 } else if (lstring == "info") {
00500 return NS_info;
00501
00502 } else if (lstring == "warning") {
00503 return NS_warning;
00504
00505 } else if (lstring == "error") {
00506 return NS_error;
00507
00508 } else if (lstring == "fatal") {
00509 return NS_fatal;
00510
00511 } else {
00512 return NS_unspecified;
00513 }
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 void Notify::
00526 config_initialized() {
00527 static bool already_initialized = false;
00528 if (already_initialized) {
00529 nout << "Notify::config_initialized() called more than once.\n";
00530 return;
00531 }
00532 already_initialized = true;
00533
00534 if (_ostream_ptr == &cerr) {
00535 ConfigVariableFilename notify_output
00536 ("notify-output", "",
00537 "The filename to which to write all the output of notify");
00538
00539 if (!notify_output.empty()) {
00540 if (notify_output == "stdout") {
00541 cout.setf(ios::unitbuf);
00542 set_ostream_ptr(&cout, false);
00543
00544 } else if (notify_output == "stderr") {
00545 set_ostream_ptr(&cerr, false);
00546
00547 } else {
00548 Filename filename = notify_output;
00549 filename.set_text();
00550 #ifdef BUILD_IPHONE
00551
00552
00553
00554 string os_specific = filename.to_os_specific();
00555 int logfile_fd = open(os_specific.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
00556 if (logfile_fd < 0) {
00557 nout << "Unable to open file " << filename << " for output.\n";
00558 } else {
00559 dup2(logfile_fd, STDOUT_FILENO);
00560 dup2(logfile_fd, STDERR_FILENO);
00561 close(logfile_fd);
00562
00563 set_ostream_ptr(&cerr, false);
00564 }
00565 #else
00566 pofstream *out = new pofstream;
00567 if (!filename.open_write(*out)) {
00568 nout << "Unable to open file " << filename << " for output.\n";
00569 delete out;
00570 } else {
00571 out->setf(ios::unitbuf);
00572 set_ostream_ptr(out, true);
00573 }
00574 #endif // BUILD_IPHONE
00575 }
00576 }
00577 }
00578 }