cgma
CubitMessage.cpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines