cgma
|
00001 00002 #include <fstream> 00003 #include <iomanip> 00004 00005 #include "CubitMessage.hpp" 00006 #include "CubitDefines.h" 00007 #include "CubitString.hpp" 00008 #include "CubitUtil.hpp" 00009 #include <cassert> 00010 #include <cstring> 00011 #include <vector> 00012 #include <iostream> 00013 00014 #include "SettingHandler.hpp" 00015 00016 #ifdef _WIN32 00017 #define vsnprintf _vsnprintf 00018 //#define strdup _strdup 00019 #endif 00020 00021 int CubitMessage::errorCount = 0; 00022 int CubitMessage::warningCount = 0; 00023 // 00024 // Message type usage: 00025 // PRINT_ERROR: Message to tell user why the task did not complete. 00026 // PRINT_WARNING: Message to tell user why completed task may not be what 00027 // was requested. 00028 // PRINT_INFO: Message to tell user about status and progress. 00029 // PRINT_DEBUG: Message to developer tied to a global debug flag. 00030 // DIAGNOSTIC: Message to developer. 00031 00032 00033 struct DefaultCubitMessageHandler : public CubitMessageHandler 00034 { 00035 void print_message(const char* message) 00036 { 00037 std::cout << message; 00038 std::cout.flush(); 00039 } 00040 void print_error(const char* message) 00041 { 00042 #ifdef XTERM 00043 char esc = 0x1B; 00044 // Turn on reverse video on VT102 (xterm also) 00045 // (0=normal, 1-bold, 4-underscore, 5-blink, 7-inverse) 00046 std::cout << esc << '[' << '7' << 'm'; 00047 #endif 00048 00049 std::cout << message; 00050 std::cout.flush(); 00051 00052 #ifdef XTERM 00053 std::cout << esc << '[' << '0' << 'm'; 00054 std::cout.flush(); 00055 #endif 00056 00057 } 00058 }; 00059 00060 static DefaultCubitMessageHandler mDefaultHandler; 00061 00062 00063 CubitMessage* CubitMessage::instance_ = NULL; 00064 CubitMessageHandler* CubitMessage::mHandler = &mDefaultHandler; 00065 CubitMessageErrorHandler* CubitMessage::mErrorHandler = NULL; 00066 int CubitMessage::infoFlag = CUBIT_TRUE; 00067 int CubitMessage::diagnosticFlag = CUBIT_FALSE; 00068 int CubitMessage::warningFlag = CUBIT_TRUE; 00069 int CubitMessage::errorFlag = CUBIT_TRUE; 00070 std::ofstream* CubitMessage::loggingStream = NULL; 00071 CubitString* CubitMessage::loggingFile = NULL; 00072 std::ofstream* CubitMessage::loggingErrorStream = NULL; 00073 CubitString* CubitMessage::loggingErrorFile = NULL; 00074 int CubitMessage::expectedStartErrorCount = -1; 00075 int CubitMessage::expectedEndErrorCount = -1; 00076 bool CubitMessage::expectedLessErrorCountAccepted = false; 00077 00078 CubitMessage* CubitMessage::instance() 00079 { 00080 if (!instance_) 00081 { 00082 instance_ = new CubitMessage; 00083 if (!instance_) 00084 { 00085 std::cerr << " *** Unable to instantiate message object ***" << std::endl; 00086 exit(1); 00087 } 00088 } 00089 return instance_; 00090 } 00091 00092 void CubitMessage::free_instance() 00093 { 00094 if (instance_) 00095 delete instance_; 00096 instance_ = NULL; 00097 } 00098 00099 CubitMessage::CubitMessage() 00100 { 00101 infoFlag = CUBIT_TRUE; 00102 warningFlag = CUBIT_TRUE; 00103 errorFlag = CUBIT_TRUE; 00104 diagnosticFlag= CUBIT_FALSE; 00105 loggingStream = NULL; 00106 loggingFile = NULL; 00107 loggingErrorStream = NULL; 00108 loggingErrorFile = NULL; 00109 currentDebugFlag = CUBIT_DEBUG_1; 00110 00111 // Initialize the debugFlag array 00112 static MessageFlag staticDebugFlag[] = 00113 { 00114 MessageFlag( 0, "UNUSED"), 00115 MessageFlag( 1, "Previously used; available for reuse."), 00116 MessageFlag( 2, "Whisker weaving information"), 00117 MessageFlag( 3, "Timing information for 3D Meshing routines."), 00118 MessageFlag( 4, "Graphics Debugging (DrawingTool)"), 00119 MessageFlag( 5, "FastQ debugging"), 00120 MessageFlag( 6, "Submapping graphics debugging"), 00121 MessageFlag( 7, "Knife progress whisker weaving information"), 00122 MessageFlag( 8, "Mapping Face debug / Linear Programing debug "), 00123 MessageFlag( 9, "Paver Debugging"), 00124 MessageFlag( 10, "WW: removed hex seam flag"), 00125 MessageFlag( 11, "Nodeset Associativity debugging"), 00126 MessageFlag( 12, "Fastq activity"), 00127 MessageFlag( 13, "Mesh entities"), 00128 MessageFlag( 14, "Previously used; available for reuse."), 00129 MessageFlag( 15, "Previously used; available for reuse."), 00130 MessageFlag( 16, "Previously used; available for reuse."), 00131 MessageFlag( 17, "Use Count debugging"), 00132 MessageFlag( 18, "Webcut debugging"), 00133 MessageFlag( 19, "Feature Merge / Unmerge debugging"), 00134 MessageFlag( 20, "Parallel meshing activity"), 00135 MessageFlag( 21, "Boundary Layer Tool Debugging"), 00136 MessageFlag( 22, "ExodusMesh sizing function debugging"), 00137 MessageFlag( 23, "Draw after joining chords in WW"), 00138 MessageFlag( 24, "SelfCrossingLoop (and derivatives) debug info"), 00139 MessageFlag( 25, "Extra invalidity checking in WW"), 00140 MessageFlag( 26, "Surface Smoothing"), 00141 MessageFlag( 27, "Primal Construction debugging, see also flag 70"), 00142 MessageFlag( 28, "Plastering debugging"), 00143 MessageFlag( 29, "Volume SubMapping"), 00144 MessageFlag( 30, "Previously used; available for reuse."), 00145 MessageFlag( 31, "CleanUp debugging"), 00146 MessageFlag( 32, "Previously used; available for reuse."), 00147 MessageFlag( 33, "Whisker Weaving inside chord list face drawing"), 00148 MessageFlag( 34, "If on Whisker Weaving doesn't merge sheets"), 00149 MessageFlag( 35, "If on WW query displays sheets before joining chords"), 00150 MessageFlag( 36, "Enable/Disable idr_keyword_debugger function"), 00151 MessageFlag( 37, "Previously used; available for reuse."), 00152 MessageFlag( 38, "WW hex formation messages"), 00153 MessageFlag( 39, "Doublet Pillower graphics output"), 00154 MessageFlag( 40, "Previously used; available for reuse."), 00155 MessageFlag( 41, "Previously used; available for reuse."), 00156 MessageFlag( 42, "Auto vertex type and sweep verification"), 00157 MessageFlag( 43, "Programmer Errors for SubMapping"), 00158 MessageFlag( 44, "Submapping Graphics Debugging"), 00159 MessageFlag( 45, "Pillow Sheet debugging"), 00160 MessageFlag( 46, "Paver breakout detection (expensive)"), 00161 MessageFlag( 47, "Extra LP debugging (see flag 8 also)"), 00162 MessageFlag( 48, "Previously used; available for reuse."), 00163 MessageFlag( 49, "Draws Face by Face Creation in Paving"), 00164 MessageFlag( 50, "Debugging for AutoSchemeSelect"), 00165 MessageFlag( 51, "Previously used; available for reuse."), 00166 MessageFlag( 52, "User Interface: If flag is enabled, filenames being\n" 00167 "\t\t\t\tused for input will be echoed and each input\n" 00168 "\t\t\t\tline will be echoed prior to being parsed."), 00169 MessageFlag( 53, "Surface Morpher debugging"), 00170 MessageFlag( 54, "Parser debugging"), 00171 MessageFlag( 55, "Previously used; available for reuse."), 00172 MessageFlag( 56, "Previously used; available for reuse."), 00173 MessageFlag( 57, "Relative Interval/Length setting"), 00174 MessageFlag( 58, "StcVertex debugging of Whisker Weaving"), 00175 MessageFlag( 59, "Previously used; available for reuse."), 00176 MessageFlag( 60, "StcVertex debugging of Looping"), 00177 MessageFlag( 61, "List number of points used in curve faceting"), 00178 MessageFlag( 62, "Print verbose information on group operations"), 00179 MessageFlag( 63, "Label Whisker Weaving diagrams tersely"), 00180 MessageFlag( 64, "No label on Whisker Weaving diagrams"), 00181 MessageFlag( 65, "Volume Morpher debugging"), 00182 MessageFlag( 66, "Print debug information on importing Pro/E geometry"), 00183 MessageFlag( 67, "List number of triangles used in surface faceting"), 00184 MessageFlag( 68, "Previously used; available for reuse."), 00185 MessageFlag( 69, "Previously used; available for reuse."), 00186 MessageFlag( 70, "STC Pillowing, see also flag 27"), 00187 MessageFlag( 71, "Previously used; available for reuse."), 00188 MessageFlag( 72, "DoubletPillower text messages"), 00189 MessageFlag( 73, "Auto Surface debugging (use new auto surf select)"), 00190 MessageFlag( 74, "Feature-based decomposition info"), 00191 MessageFlag( 75, "Many-to-many sweep imprint debugging"), 00192 MessageFlag( 76, "Virtual point and partition curve"), 00193 MessageFlag( 77, "Volume interval matching"), 00194 MessageFlag( 78, "Tipton Smoother jacobian modification enabler"), 00195 MessageFlag( 79, "Previously used; available for reuse."), 00196 MessageFlag( 80, "Previously used; available for reuse."), 00197 MessageFlag( 81, "Curve Morpher Debugging"), 00198 MessageFlag( 82, "Previously used; available for reuse."), 00199 MessageFlag( 83, "Previously used; available for reuse."), 00200 MessageFlag( 84, "Surface auto decomposition"), 00201 MessageFlag( 85, "U-SubMapping debugging"), 00202 MessageFlag( 86, "Virtual curve and partition surface"), 00203 MessageFlag( 87, "Composite curve and composite surface"), 00204 MessageFlag( 88, "Volume partitioning"), 00205 MessageFlag( 89, "Previously used; available for reuse."), 00206 MessageFlag( 90, "Geometry attributes"), 00207 MessageFlag( 91, "Smoothing Debug Output"), 00208 MessageFlag( 92, "Print name changed warnings"), 00209 MessageFlag( 93, "Hex Fix Up"), 00210 MessageFlag( 94, "Entity name attribute"), 00211 MessageFlag( 95, "Group imprint errors"), 00212 MessageFlag( 96, "GraftTool debugging"), 00213 MessageFlag( 97, "Previously used; available for reuse."), 00214 MessageFlag( 98, "Color code imported THEX meshes"), 00215 MessageFlag( 99, "Geometry creation"), 00216 MessageFlag(100, "Skew Control debugging"), 00217 MessageFlag(101, "Previously used; available for reuse."), 00218 MessageFlag(102, "CAEntityId debugging"), 00219 MessageFlag(103, "Print compact interval assignment constraints"), 00220 MessageFlag(104, "Report interval matching progress"), 00221 MessageFlag(105, "Previously used; available for reuse."), 00222 MessageFlag(106, "Mesh Cleaver debugging"), 00223 MessageFlag(107, "Midpoint_subdivision debugging"), 00224 MessageFlag(108, "Simulog tetmesher debugging"), 00225 MessageFlag(109, "Transition schemes debugging"), 00226 MessageFlag(110, "Mesh Defined Geometry"), 00227 MessageFlag(111, "TriAdvance mesher debugging"), 00228 MessageFlag(112, "Auto Detail Suppression"), 00229 MessageFlag(113, "Previously used; available for reuse."), 00230 MessageFlag(114, "Blend Finder Debugging"), 00231 MessageFlag(115, "Exporting Feature Debugging Files"), 00232 MessageFlag(116, "Sizing function tool data information"), 00233 MessageFlag(117, "Extra Information on Autoscheme Decision Making"), 00234 MessageFlag(118, "Blend finding optimization file"), 00235 MessageFlag(119, "Laminate Tool debugging"), 00236 MessageFlag(120, "Print unassociated node locations on import mesh"), 00237 MessageFlag(121, "Print verbose infeasible match interval messages"), 00238 MessageFlag(122, "Mesh-Based Geometry Debug Information"), 00239 MessageFlag(123, "Collect memory statistics from Tetmesher"), 00240 MessageFlag(124, "Print verbose Tetmesher debugging information"), 00241 MessageFlag(125, "Mesh refinement debugging"), 00242 MessageFlag(126, "Previously used; available for reuse."), 00243 MessageFlag(127, "SculptingTool debug flag"), 00244 MessageFlag(128, "Previously used; available for reuse."), 00245 MessageFlag(129, "Virtual Imprint Debugging"), 00246 MessageFlag(130, "Hexsheet Insertion Debugging"), 00247 MessageFlag(131, "Mesh Cutting Debugging"), 00248 MessageFlag(132, "Global Collection Smoothing"), 00249 MessageFlag(133, "Print verbose import mesh progress"), 00250 MessageFlag(134, "Previously used; available for reuse."), 00251 MessageFlag(135, "Keep WhiskerWeave data after meshing"), 00252 MessageFlag(136, "Previously used; available for reuse."), 00253 MessageFlag(137, "GJoin"), 00254 MessageFlag(138, "Parallel CGM timing"), 00255 MessageFlag(139, "RTree Debugging"), 00256 MessageFlag(140, "Previously used; available for reuse."), 00257 MessageFlag(141, "Settings save/restore"), 00258 MessageFlag(142, "Decompose Sweep Debugging"), 00259 MessageFlag(143, "Decomp Sweep Imprint Debugging"), 00260 MessageFlag(144, "Medial Axis/Chordal Axis Debugging"), 00261 MessageFlag(145, "Virtual Geometry Facet Operations"), 00262 MessageFlag(146, "Sector Tool Meshing Scheme"), 00263 MessageFlag(147, "Previously used; available for reuse."), 00264 MessageFlag(148, "Meshing Benchmarks"), 00265 MessageFlag(149, "MeshCutting Graphical debugging"), 00266 MessageFlag(150, "MBG to Acis conversion debugging"), 00267 MessageFlag(151, "Previously used; available for reuse."), 00268 MessageFlag(152, "Boundary Conditions Debugging"), 00269 MessageFlag(153, "Print Body information in Geometry operations"), 00270 MessageFlag(154, "Split Surface Debugging"), 00271 MessageFlag(155, "Meshing Benchmarks Summary"), 00272 MessageFlag(156, "CAMAL Paver CleanUp debuging"), 00273 MessageFlag(157, "Skeleton Sizing Function timing and counts"), 00274 MessageFlag(158, "Previously used; available for reuse."), 00275 MessageFlag(159, "Previously used; available for reuse."), 00276 MessageFlag(160, "Previously used; available for reuse."), 00277 MessageFlag(161, "Previously used; available for reuse."), 00278 MessageFlag(162, "Previously used; available for reuse."), 00279 MessageFlag(163, "Previously used; available for reuse."), 00280 MessageFlag(164, "Previously used; available for reuse."), 00281 MessageFlag(165, "Previously used; available for reuse."), 00282 MessageFlag(166, "Unconstrained Paving debugging"), 00283 MessageFlag(167, "Skeleton Sizing Function Debugging (messages)"), 00284 MessageFlag(168, "Tweak Target Multiple Debugging "), 00285 MessageFlag(169, "Enable Knupp affine transformation instead of Roca"), 00286 MessageFlag(170, "Previously used; available for reuse."), 00287 MessageFlag(171, "Previously used; available for reuse."), 00288 MessageFlag(172, "Previously used; available for reuse."), 00289 MessageFlag(173, "Previously used; available for reuse."), 00290 MessageFlag(174, "Previously used; available for reuse."), 00291 MessageFlag(175, "Previously used; available for reuse."), 00292 MessageFlag(176, "Enable UCP database checking"), 00293 MessageFlag(177, "Enable Unconstrained Plastering Debug Drawing"), 00294 MessageFlag(178, "Enable Harris instead of Parrish hex refinement"), 00295 MessageFlag(179, "Enable Camal Sweeper for UCP Front Advancements.\n" 00296 "\t\t\t\tIgnored if debug 189 is on"), 00297 MessageFlag(180, "DecompAide (decomposition helper) debugging"), 00298 MessageFlag(181, "MBG. Draw curve paths."), 00299 MessageFlag(182, "UCP Detailed Debug Printing."), 00300 MessageFlag(183, "Previously used; available for reuse."), 00301 MessageFlag(184, "Enable old sheet refinement command."), 00302 MessageFlag(185, "Enable straddle elements on hardlines."), 00303 MessageFlag(186, "Disable parametric coordinates in TriAdvMesher"), 00304 MessageFlag(187, "Previously used; available for reuse."), 00305 MessageFlag(188, "Tolerant Triangle Meshing"), 00306 MessageFlag(189, "Previously used; available for reuse."), 00307 MessageFlag(190, "Count CAMAL calls to move_to and normal_at"), 00308 MessageFlag(191, "Auto clean messages"), 00309 MessageFlag(192, "Previously used; available for reuse."), 00310 MessageFlag(193, "Tetmesh with stand-alone INRIA execuable thru files"), 00311 MessageFlag(194, "Hex Mesh Matching Debug drawing"), 00312 MessageFlag(195, "Previously used; available for reuse."), 00313 MessageFlag(196, "Previously used; available for reuse."), 00314 MessageFlag(197, "CAMAL Paver debugging (no Cubit smoothing, etc.)"), 00315 MessageFlag(198, "Auto Midsurface debugging"), 00316 MessageFlag(199, "Angle smoothing debugging"), 00317 MessageFlag(200, "Paver quality data output"), 00318 MessageFlag(201, "Paver cleanup edge metrics"), 00319 MessageFlag(202, "Disable Paver cleanup 3-3 replace"), 00320 MessageFlag(203, "Disable Paver cleanup 3-offset-3/5 replace"), 00321 MessageFlag(204, "Enable Paver cleanup 3-valent quad cluster"), 00322 MessageFlag(205, "Enable Paver cleanup partial chord collapse"), 00323 MessageFlag(206, "Hex Mesh Matching, match chords one at a time."), 00324 MessageFlag(207, "Defeature and Geometry tolerant meshing"), 00325 MessageFlag(208, "Previously used; available for reuse."), 00326 MessageFlag(209, "Change sense of partial/full tet remesh (v = !v)"), 00327 MessageFlag(210, "Use tetgen tetmesher via files"), 00328 MessageFlag(211, "Use tetgen tetmesher via direct interface"), 00329 MessageFlag(212, "Create debugging groups when doing geometry/meshing association for parallel refinement"), 00330 MessageFlag(213, "Previously used; available for reuse."), 00331 MessageFlag(214, "Boundary Layers"), 00332 MessageFlag(215, "Command Parser"), 00333 MessageFlag(216, "Command Parser Detailed"), 00334 MessageFlag(217, "Graphics debugging for unite dissimilar mesh command"), 00335 MessageFlag(218, "Previously used; available for reuse."), 00336 MessageFlag(219, "Materials Interface"), 00337 MessageFlag(220, "Previously used; available for reuse."), 00338 MessageFlag(221, "Turn ON Boundary Layer Correction in New Sweeper; ignored if target evaluator is NULL."), 00339 MessageFlag(222, "Turn ON Scale Mesh option to maximize percentage of model which gets scaled."), 00340 MessageFlag(223, "Turn ON Scale Mesh Debug Drawing."), 00341 MessageFlag(224, "Turn ON Scale Mesh Extended Debug Drawing."), 00342 MessageFlag(225, "unassigned") 00343 00344 // IMPORTANT!!! 00345 // If you add a new debug flag, make sure that you change 00346 // the result of CubitMessage::number_of_debug_flags(). 00347 // In order to use this type of static initialization, 00348 // we can't use the sizeof operator, so change it manually. 00349 }; 00350 debugFlag = staticDebugFlag; 00351 00352 // Check initialization of debugFlag array. 00353 for (int i=number_of_debug_flags(); i > 0; i--) 00354 { 00355 debugFlag[i].setting = CUBIT_FALSE; 00356 assert(i == debugFlag[i].flagNumber); 00357 assert(debugFlag[i].description != NULL); 00358 } 00359 } 00360 00361 CubitMessage::~CubitMessage() 00362 { 00363 // Close all streams associated with debug flags. 00364 // If the same stream is being used for debug and logging, it 00365 // will get closed below. 00366 for (int i=number_of_debug_flags(); i > 0; i--) 00367 remove_debug_stream(i); 00368 00369 // At this time, the only open streams possible are loggingStream and loggingErrorStream. 00370 if (loggingStream != NULL) 00371 { 00372 loggingStream->close(); 00373 delete loggingStream; 00374 delete loggingFile; 00375 } 00376 if (loggingErrorStream != NULL) 00377 { 00378 loggingErrorStream->close(); 00379 delete loggingErrorStream; 00380 delete loggingErrorFile; 00381 } 00382 00383 // Set static instance_ to zero to indicated that we are dead. 00384 instance_ = 0; 00385 } 00386 00387 void CubitMessage::delete_instance() 00388 { 00389 delete instance_; 00390 instance_ = NULL; 00391 } 00392 00393 int CubitMessage::number_of_debug_flags() 00394 { 00395 return NUM_DEBUG_FLAGS; 00396 // return sizeof(debugFlag)/sizeof(debugFlag[0])-1; 00397 } 00398 00399 void CubitMessage::internal_error ( const int message_type, 00400 std::ofstream *output_stream, 00401 const CubitString& msgbuf) 00402 { 00403 int print_it = CUBIT_FALSE; 00404 00405 CubitString prefix; 00406 00407 switch (message_type) 00408 { 00409 case CUBIT_ERROR: 00410 if (errorFlag) 00411 { 00412 print_it = CUBIT_TRUE; 00413 prefix = "ERROR: "; 00414 } 00415 break; 00416 case CUBIT_ERROR_EXPECTED: 00417 if (errorFlag) 00418 { 00419 print_it = CUBIT_TRUE; 00420 prefix = "ERROR_EXPECTED: "; 00421 } 00422 break; 00423 case CUBIT_WARNING: 00424 if (warningFlag) 00425 { 00426 print_it = CUBIT_TRUE; 00427 prefix = "WARNING: "; 00428 } 00429 break; 00430 case CUBIT_INFO: 00431 if (infoFlag) 00432 print_it = CUBIT_TRUE; 00433 break; 00434 case CUBIT_DIAGNOSTIC: 00435 if (diagnosticFlag) 00436 { 00437 print_it = CUBIT_TRUE; 00438 prefix = "DIAGNOSTIC: "; 00439 } 00440 break; 00441 default: 00442 if (message_type >= CUBIT_DEBUG_1 && message_type <= number_of_debug_flags()+10) 00443 { 00444 if (debugFlag[message_type-10].setting) print_it = CUBIT_TRUE; 00445 break; 00446 } 00447 } 00448 00449 if (print_it) 00450 { 00451 // loggingStream is used to journal error, warning, and info messages. 00452 // debug messages can also be journalled there by setting the 00453 // output stream for the debug flag to the same file. 00454 if (loggingStream != NULL && (message_type == CUBIT_ERROR || 00455 message_type == CUBIT_WARNING || 00456 message_type == CUBIT_INFO)) 00457 { 00458 *loggingStream << prefix.c_str() << msgbuf.c_str(); 00459 loggingStream->flush(); 00460 } 00461 //loggingErrorStream is used to (if the user has requested it) 00462 // log only ERROR: messages 00463 if (loggingErrorStream != NULL && message_type == CUBIT_ERROR) 00464 { 00465 *loggingErrorStream << prefix.c_str() << msgbuf.c_str(); 00466 loggingErrorStream->flush(); 00467 } 00468 00469 if (output_stream == NULL) 00470 { 00471 if(message_type == CUBIT_ERROR) 00472 { 00473 CubitString ctx; 00474 if(CubitMessage::mErrorHandler) 00475 { 00476 ctx = CubitMessage::mErrorHandler->error_context().c_str(); 00477 } 00478 CubitString msg = prefix + ctx + msgbuf; 00479 CubitMessage::mHandler->print_error(msg.c_str()); 00480 } 00481 else 00482 { 00483 CubitString msg = prefix + msgbuf; 00484 CubitMessage::mHandler->print_message(msg.c_str()); 00485 } 00486 } 00487 else 00488 { 00489 *output_stream << prefix.c_str() << msgbuf.c_str(); 00490 output_stream->flush(); 00491 } 00492 } 00493 } 00494 00495 int CubitMessage::print_error ( const CubitString& str ) 00496 { 00497 int error_type = CUBIT_ERROR; 00498 if(expectedStartErrorCount != -1 && expectedEndErrorCount > expectedStartErrorCount) 00499 { 00500 error_type = CUBIT_ERROR_EXPECTED; 00501 } 00502 else 00503 { 00504 add_to_error_count(); 00505 } 00506 00507 if(expectedStartErrorCount != -1) 00508 { 00509 expectedStartErrorCount++; 00510 } 00511 00512 static char* cubit_ctest = getenv("CUBIT_CTEST"); 00513 if(cubit_ctest && error_type == CUBIT_ERROR) 00514 { 00515 internal_error(CUBIT_INFO, NULL, "<DartMeasurement name=\"Error\" type=\"text/plain\">\n"); 00516 internal_error(error_type, NULL, str); 00517 internal_error(CUBIT_INFO, NULL, "</DartMeasurement>\n"); 00518 } 00519 00520 internal_error(error_type, NULL, str); 00521 00522 return CUBIT_FAILURE; 00523 } 00524 00525 int CubitMessage::print_warning ( const CubitString& str ) 00526 { 00527 internal_error(CUBIT_WARNING, NULL, str); 00528 add_to_warning_count(); 00529 return CUBIT_FAILURE; 00530 } 00531 00532 int CubitMessage::print_info ( const CubitString& str ) 00533 { 00534 internal_error(CUBIT_INFO, NULL, str); 00535 return CUBIT_FAILURE; 00536 } 00537 00538 int CubitMessage::is_debug_flag_set( int flag ) 00539 { 00540 if( DEBUG_FLAG( flag )) 00541 { 00542 currentDebugFlag = flag; 00543 return CUBIT_TRUE; 00544 } 00545 return CUBIT_FALSE; 00546 } 00547 00548 int CubitMessage::print_debug( const CubitString& str ) 00549 { 00550 internal_error(currentDebugFlag+10, 00551 debugFlag[currentDebugFlag].outputStream, 00552 str); 00553 return CUBIT_FAILURE; 00554 } 00555 00556 void CubitMessage::print_diagnostic ( const CubitString& str ) 00557 { 00558 internal_error(CUBIT_DIAGNOSTIC, NULL, str); 00559 } 00560 00561 int CubitMessage::reset_error_count(int value) 00562 { 00563 int current_value = errorCount; 00564 if (errorCount != value) { 00565 errorCount = value; 00566 PRINT_WARNING("Error count manually changed from %d to %d\n\n", 00567 current_value, value); 00568 } 00569 return current_value; 00570 } 00571 00572 int CubitMessage::error_count() 00573 { 00574 return errorCount; 00575 } 00576 00577 void CubitMessage::add_to_error_count() 00578 { 00579 errorCount++; 00580 } 00581 00582 int CubitMessage::reset_warning_count(int value) 00583 { 00584 int current_value = warningCount; 00585 if (warningCount != value) { 00586 warningCount = value; 00587 PRINT_INFO("Warning count manually changed from %d to %d\n\n", 00588 current_value, value); 00589 } 00590 return current_value; 00591 } 00592 00593 int CubitMessage::warning_count() 00594 { 00595 return warningCount; 00596 } 00597 00598 void CubitMessage::add_to_warning_count() 00599 { 00600 warningCount++; 00601 } 00602 00603 void CubitMessage::output_debug_information(int from, int to, int step) 00604 { 00605 if (to == -1) 00606 to = number_of_debug_flags(); 00607 00608 PRINT_INFO("Debug Flag Settings " 00609 "(flag number, setting, output to, description):\n"); 00610 for (int i=from; i <= to; i+=step) { 00611 debugFlag[i].output(); 00612 } 00613 PRINT_INFO("\n"); 00614 } 00615 00616 void CubitMessage::output_debug_information(CubitString &match) 00617 { 00618 int count = 0; 00619 for (int i=1; i <= number_of_debug_flags(); i++) { 00620 char *tmp = CubitUtil::util_strdup((char*)(debugFlag[i].description)); 00621 if (tmp && strlen(tmp) > 0) { 00622 CubitString debug_description(tmp); 00623 debug_description.to_lower(); 00624 if (debug_description.find(match, 0) < debug_description.length()) { 00625 if (count == 0) { 00626 PRINT_INFO("Debug Flag Settings " 00627 "(flag number, setting, output to, description):\n"); 00628 } 00629 debugFlag[i].output(); 00630 count++; 00631 } 00632 } 00633 CubitUtil::util_strdup_free(tmp); 00634 } 00635 if (count == 0) { 00636 PRINT_WARNING("No debug descriptions contain the " 00637 "substring '%s'\n", match.c_str()); 00638 } 00639 PRINT_INFO("\n"); 00640 } 00641 00642 void CubitMessage::output_logging_information() 00643 { 00644 if (loggingStream != NULL) 00645 PRINT_INFO("logging = On, log file = '%s'\n", loggingFile->c_str()); 00646 else 00647 PRINT_INFO("logging = Off\n"); 00648 if (loggingErrorStream != NULL) 00649 PRINT_INFO("logging Errors = On, log file = '%s'\n",loggingErrorFile->c_str()); 00650 00651 } 00652 00653 void MessageFlag::output() 00654 { 00655 CubitMessage::instance()-> 00656 print_info( 00657 CubitString::format("%2d %3s %-16s %s\n", 00658 flagNumber, (setting == 1 ? "ON " : "OFF"), 00659 (filename == NULL ? "terminal" : filename->c_str()), 00660 description) 00661 ); 00662 } 00663 00664 int CubitMessage::find_file_use(const CubitString &filename) 00665 { 00666 if (filename == "terminal") { 00667 // remove_debug_stream has set the outputStream and filename to NULL. 00668 return -1; 00669 } 00670 00671 // See if any of the other debug flags have this file open 00672 for (int i=number_of_debug_flags(); i > 0; i--) { 00673 if (debugFlag[i].filename && *(debugFlag[i].filename) == filename) { 00674 return i; 00675 } 00676 } 00677 if (loggingFile && *(loggingFile) == filename) 00678 return -2; 00679 00680 if (loggingErrorFile && *(loggingErrorFile) == filename) 00681 return -3; 00682 00683 return 0; 00684 } 00685 00686 int CubitMessage::count_stream_users(const std::ofstream *stream) 00687 { 00688 int match = 0; 00689 if (stream != NULL) 00690 { 00691 for (int i=number_of_debug_flags(); i > 0; i--) 00692 { 00693 if (debugFlag[i].outputStream == stream) 00694 { 00695 match++; 00696 } 00697 } 00698 00699 if (loggingStream == stream) 00700 match++; 00701 if (loggingErrorStream == stream) 00702 match++; 00703 } 00704 return match; 00705 } 00706 00707 void CubitMessage::set_logging_file_setting(const CubitString &filename, CubitBoolean resume_flag) 00708 { 00709 // If logging is currently outputting to a file, close it if 00710 // it is the only thing using that file. (and the filenames don't match) 00711 if (loggingFile && *loggingFile == filename) 00712 return; 00713 00714 if (loggingErrorFile && *loggingErrorFile == filename) 00715 { 00716 PRINT_ERROR("Can't set the logging file to be the same as the Error logging file.\n"); 00717 return; 00718 } 00719 00720 int users = count_stream_users(loggingStream); 00721 if (users == 1) { // Just us... 00722 loggingStream->close(); 00723 delete loggingStream; 00724 loggingStream = NULL; 00725 delete loggingFile; 00726 loggingFile = NULL; 00727 } 00728 00729 int match = find_file_use(filename); 00730 00731 if (match == -1) // Filename is 'terminal' 00732 return; 00733 else if (match != 0) 00734 { 00735 loggingFile = debugFlag[match].filename; 00736 loggingStream = debugFlag[match].outputStream; 00737 } 00738 else 00739 { 00740 loggingFile = new CubitString(filename); 00741 if(resume_flag) 00742 loggingStream = new std::ofstream(CubitString::toNative(filename).c_str(), std::ios::out | std::ios::app); 00743 else 00744 loggingStream = new std::ofstream(CubitString::toNative(filename).c_str()); 00745 } 00746 } 00747 00748 void CubitMessage::set_debug_file_setting(const int index, const CubitString &filename) 00749 { 00750 // If this flag is currently outputting to a file, close it if 00751 // this is the only flag using that file. 00752 remove_debug_stream(index); 00753 00754 int match = find_file_use(filename); 00755 00756 if (match == -1) // Filename is 'terminal' 00757 return; 00758 if (match == -2 || match == -3) {// Filename is same as loggingFile or loggingErrorFile; 00759 debugFlag[index].filename = loggingFile; 00760 debugFlag[index].outputStream = loggingStream; 00761 } 00762 else if (match == index) 00763 return; 00764 else if (match != 0) { 00765 debugFlag[index].filename = debugFlag[match].filename; 00766 debugFlag[index].outputStream = debugFlag[match].outputStream; 00767 } 00768 else { 00769 debugFlag[index].filename = new CubitString(filename); 00770 debugFlag[index].outputStream = new std::ofstream(CubitString::toNative(filename).c_str()); 00771 } 00772 } 00773 00774 void CubitMessage::remove_debug_stream(const int index) 00775 { 00776 // NOTE: DO NOT USE PRINT_* CALLS, THIS IS CALLED FROM DESTRUCTOR. 00777 00778 // Multiple debug flags may be using the same output stream, 00779 // Go through the list and count who is using this stream, 00780 // If only one use, close and delete the stream. 00781 if (debugFlag[index].outputStream == NULL) 00782 return; 00783 00784 int match = count_stream_users(debugFlag[index].outputStream); 00785 00786 if (match == 1) { 00787 debugFlag[index].outputStream->close(); 00788 delete debugFlag[index].outputStream; 00789 delete debugFlag[index].filename; 00790 } 00791 debugFlag[index].filename = NULL; 00792 debugFlag[index].outputStream = NULL; 00793 } 00794 00795 void CubitMessage::set_message_handler(CubitMessageHandler *handler) 00796 { 00797 CubitMessage::mHandler = handler; 00798 if(CubitMessage::mHandler == NULL) 00799 CubitMessage::mHandler = &mDefaultHandler; 00800 } 00801 00802 CubitMessageHandler* CubitMessage::get_message_handler() 00803 { 00804 return CubitMessage::mHandler; 00805 } 00806 00807 void CubitMessage::set_error_handler(CubitMessageErrorHandler *handler) 00808 { 00809 CubitMessage::mErrorHandler = handler; 00810 } 00811 00812 CubitMessageErrorHandler* CubitMessage::get_error_handler() 00813 { 00814 return CubitMessage::mErrorHandler; 00815 } 00816 00817 MessageFlag::MessageFlag(int flag_number, const char *desc) 00818 : flagNumber(flag_number), setting(CUBIT_FALSE), 00819 description(desc), filename(NULL), outputStream(NULL) 00820 { 00821 } 00822 00823 MessageFlag::MessageFlag() 00824 { 00825 flagNumber = 0; 00826 setting = CUBIT_FALSE; 00827 description = NULL; 00828 filename = NULL; 00829 outputStream = NULL; 00830 } 00831 00832 00833 void CubitMessage::set_logging_file_setting(const char* filename) 00834 { 00835 if (loggingFile && *loggingFile == filename) 00836 return; 00837 00838 if (CubitUtil::compare(filename,"terminal")) { // Filename is 'terminal' 00839 if (loggingStream != NULL) { 00840 loggingStream->close(); 00841 delete loggingStream; 00842 loggingStream = NULL; 00843 delete loggingFile; 00844 loggingFile = NULL; 00845 } 00846 return; 00847 } 00848 else { 00849 loggingFile = new CubitString(filename); 00850 loggingStream = new std::ofstream(CubitString::toNative(filename).c_str(), std::ios::out | std::ios::app ); 00851 } 00852 } 00853 00854 void CubitMessage::set_error_logging_file_setting(const char* filename, CubitBoolean resume_flag) 00855 { 00856 if (loggingErrorFile && *loggingErrorFile == filename) 00857 return; 00858 00859 if(loggingFile && *loggingFile == filename) 00860 { 00861 PRINT_ERROR("Can't explicitly set the Error logging file to be the same as the logging file.\n"); 00862 return; 00863 } 00864 00865 if (CubitUtil::compare(filename,"terminal")) { // Filename is 'terminal' 00866 if (loggingErrorStream != NULL) { 00867 loggingErrorStream->close(); 00868 delete loggingErrorStream; 00869 loggingErrorStream = NULL; 00870 delete loggingErrorFile; 00871 loggingErrorFile = NULL; 00872 } 00873 return; 00874 } 00875 else { 00876 loggingErrorFile = new CubitString(filename); 00877 if(resume_flag) 00878 loggingErrorStream = new std::ofstream(CubitString::toNative(filename).c_str(), std::ios::out | std::ios::app ); 00879 else 00880 loggingErrorStream = new std::ofstream(CubitString::toNative(filename).c_str()); 00881 } 00882 } 00883 00884 //Initialize all settings in this class 00885 void CubitMessage::initialize_settings() 00886 { 00887 00888 SettingHandler::instance()->add_setting("Info", 00889 CubitMessage::set_info_flag, 00890 CubitMessage::get_info_flag); 00891 00892 /*SettingHandler::instance()->add_setting("Logging", 00893 CubitMessage::set_logging_file_setting, 00894 CubitMessage::get_logging_file_setting);*/ 00895 00896 SettingHandler::instance()->add_setting("Diagnostic", 00897 CubitMessage::set_diagnostic_flag, 00898 CubitMessage::get_diagnostic_flag); 00899 00900 SettingHandler::instance()->add_setting("Warning", 00901 CubitMessage::set_warning_flag, 00902 CubitMessage::get_warning_flag); 00903 } 00904 00905 CubitString CubitMessage::logging_filename() const 00906 { 00907 CubitString temp_string; 00908 if(loggingStream != NULL) 00909 temp_string = loggingFile->c_str(); 00910 00911 return temp_string; 00912 } 00913 00914 CubitString CubitMessage::logging_errors_filename() const 00915 { 00916 CubitString temp_string; 00917 if(loggingErrorStream != NULL) 00918 temp_string = loggingErrorFile->c_str(); 00919 00920 return temp_string; 00921 } 00922 00923 void CubitMessage::start_expected_error_count(int error_count, bool less_than_accepted) 00924 { 00925 this->expectedStartErrorCount = errorCount; 00926 this->expectedEndErrorCount = errorCount + error_count; 00927 this->expectedLessErrorCountAccepted = less_than_accepted; 00928 } 00929 00930 void CubitMessage::stop_expected_error_count(const CubitString &message) 00931 { 00932 bool has_error = false; 00933 if((expectedEndErrorCount != expectedStartErrorCount && expectedLessErrorCountAccepted == false) || 00934 (expectedEndErrorCount < expectedStartErrorCount && expectedLessErrorCountAccepted == true)) 00935 { 00936 has_error = true; 00937 } 00938 this->expectedStartErrorCount = -1; 00939 this->expectedEndErrorCount = -1; 00940 if(has_error) 00941 { 00942 CubitString msg = message; 00943 if(message.length() == 0) 00944 { 00945 msg = "unexpected errors"; 00946 } 00947 print_error(msg + "\n"); 00948 } 00949 } 00950 00951 MessageFlag::~MessageFlag() 00952 { 00953 // It is not safe to delete either the stream or the filename here 00954 // since multiple instances (debug flags) may refer to the same memory 00955 } 00956 00957 #ifdef STANDALONE 00958 void main() { 00959 CubitMessage::instance()->output_debug_information(1, 10, 2); 00960 CubitMessage::instance()->output_debug_information(12); 00961 CubitMessage::instance()->set_debug_file(5, "Debug_Test.file"); 00962 DEBUG_FLAG(5, CUBIT_TRUE); 00963 PRINT_DEBUG_5("This is a test\n"); 00964 CubitMessage::instance()->output_debug_information(5,5); 00965 } 00966 #endif