/*
 * Copyright (c) 2013, Sandia Corporation.
 * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
 * the U.S. Government retains certain rights in this software.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 * 
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 * 
 *     * Neither the name of Sandia Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 */
///       static DiagWriterParser parser;
///     
///       return parser;
///     }
///     
///     stk::diag::Writer &
///     theDiagWriter()
///     {
///       /* %TRACE[NONE]% */  /* %TRACE% */
///       static stk::diag::Writer s_diagWriter(sierra::dwout().rdbuf(), theDiagWriterParser().parse(std::getenv("APPLOG")));
///     
///       return s_diagWriter;
///     }
///     
///     
///     DiagWriterParser::DiagWriterParser()
///         : Diag::WriterParser()
///     {
///       /* %TRACE% */  /* %TRACE% */
///       mask("bc",              (unsigned long) (LOG_BC),              "Display boundary condition information");
///       mask("debug",           (unsigned long) (LOG_DEBUG),           "Display debug diagnostic information");
///       mask("eq",              (unsigned long) (LOG_EQ),              "Display equation information");
///       mask("expression",      (unsigned long) (LOG_EXPRESSION),      "Display expression information");
///       mask("hadapt",          (unsigned long) (LOG_HADAPT),          "Display h_adapt diagnostic information");
///       mask("finite_check",    (unsigned long) (LOG_FINITE_CHECK),    "Display warning messages about any non-finite expression values or sensitivities");
///       mask("nonlinear",       (unsigned long) (LOG_NONLINEAR),       "Diaplay nonlinear solver information");
///       mask("pp",              (unsigned long) (LOG_PP),              "Display postprocessor diagnostic information");
///       mask("sens_check",      (unsigned long) (LOG_SENS_CHECK),      "Display messages generated by expression sensitivity checker");
///       mask("fast_sens_check", (unsigned long) (LOG_FAST_SENS_CHECK), "Display messages generated by sensitivity checker (skipping FAD, element, and kernel expressions)");
///       mask("species",         (unsigned long) (LOG_SPECIES),         "Display species information");
///       mask("transfer",        (unsigned long) (LOG_TRANSFER),        "Display transfer information");
///       mask("plugin",          (unsigned long) (LOG_PLUGIN),          "Display plugin information");
///       mask("chaparral",       (unsigned long) (LOG_CHAPARRAL),       "Display chaparral information");
///       mask("utility",         (unsigned long) (LOG_UTILITY),         "Display equation system utility information");
///       mask("pre_assembly",    (unsigned long) (LOG_PREASSEMBLY),     "Display pre-assembly diagnostic information");
///       mask("expression_dump", (unsigned long) (LOG_EXPRESSION_DUMP), "Display the values for every expression and its sensitivities");
///       mask("calore",          (unsigned long) (LOG_CALORE),          "Display additional calore output (hack)");
///       mask("ccfvm",           (unsigned long) (LOG_CCFVM),           "Display additional ccfvm output (hack)");
///       mask("user-sub",        (unsigned long) (LOG_USER_SUB),        "Print user subroutine execution diagnostics");
///     }
///     
///     namespace {
///     
///     void bootstrap()
///     {
///       Diag::registerWriter("applog", applog, theDiagWriterParser());
///     }
///     
///     stk::Bootstrap x(&bootstrap);
///     
///     } // namespace <empty>
///     
///     } // namespace app
///     } // namespace sierra
/// \endcode
///
/// </UL>
///
///
/// \anchor stk_util_diag_writer_howto_assign_new_log_bits
/// \section stk_util_diag_writer_assign_new_log_bits Adding additional LOG_mask
///
/// Adding a new mask and option name requires only adding the new bit to the
/// enumeration in <i>App</i>_DiagWriter_fwd.h, where 0x<i>mmmmmm00</i> is a previously
/// unusd bit:
///
/// \code
///     #ifndef SIERRA_App_DiagWriter_fwd_h
///     #define SIERRA_App_DiagWriter_fwd_h
///    
///     #include <stk_util/util/Writer_fwd.hpp>
///    
///     namespace sierra {
///     namespace app {
///    
///     enum {
///       LOG_ALWAYS          = sierra::LOG_ALWAYS,
///       LOG_TRACE           = sierra::LOG_TRACE,
///       LOG_TRACE_STATS     = sierra::LOG_TRACE_STATS,
///       LOG_TRACE_SUB_CALLS = sierra::LOG_TRACE_SUB_CALLS,
///       LOG_MEMBERS         = sierra::LOG_MEMBERS,
///    
///       ...
///       LOG_NEWUNUSEDBIT	= 0x<i>mmmmmm00</i>,
///       ...
///
///     };
///    
///     } // namespace app
///     } // namespace sierra
///    
///     #endif // SIERRA_App_DiagWriter_fwd_h
/// \endcode
///
/// And, adding a <b>mask</b> function call in the parser constructor in the <i>App</i>_DiagWriter.C
/// file.
///
/// \code
///     DiagWriterParser::DiagWriterParser()
///         : Diag::WriterParser()
///     {
///       /* %TRACE% */  /* %TRACE% */
///
///       ...
///       mask("new-bit-name", (Diag::PrintMask) (LOG_NEWUNUSEDBIT), "Some brief description");
///       ...
///     }
/// \endcode
///
///
/// \anchor stk_util_diag_writer_howto_add_dump_to_my_class
/// \section stk_util_diag_writer_add_dump_to_my_class Adding diagnostic output to your classes
///
/// To incorporate the diagnostic writer into a class or application, there are
/// only a few steps to follow.  And, by following these guidelines, the newly created
/// class can fully participate is class data diagnostic output.
///
/// In your class header:
/// <UL>
/// <LI>Include your application's diagnostic writer forward header.
///
/// \code
///     #include <App_DiagWriter_fwd.h>
/// \endcode
///
/// <LI>Declare the dump member function.  If this is a base class, be sure the
/// define this member function as virtual if inheritance may be in play.
///
/// \code
/// Writer &dump(Writer &dout) const;
/// \endcode
///
/// <LI>Define the output insertion operator, operator<< to call your member
/// function.
///
/// \code
///     inline Writer &operator<<(Writer &dout, const MyClass &my_class) {
///       return my_class.dump(dout);
///     }
/// \endcode
/// </UL>
///
/// In your class implementation:
/// <UL>
/// <LI>Include your application's diagnostic writer header.
///
/// \code
///     #include <App_DiagWriter.h>;
/// \endcode
///
/// <LI>Define your MyClass::dump(Writer &dout) const member function.  I
/// suggest using the following as a start:
///
/// \code
///     Writer &
///     MyClass::dump(
///       Writer &		dout) const
///     {
///       if (dout.shouldPrint()) {
///         dout << demangle(typeid(MyClass).name()) << ", " << m_name << push << std::endl;
///         MyParentClass::dump(dout).dendl(); // If there is a base class
///    
///         dout.m(LOG_MEMBERS) << "m_information, " << m_information << std::endl;
///         dout << pop;
///       }
///       return dout;
///     }
/// \endcode
///
/// </UL>
///
///
/// \anchor stk_util_diag_writer_howto_add_dump_to_external_class
/// \section stk_util_diag_writer_add_dump_to_external_class Adding diagnostic output to library classes
///
/// \anchor stk_util_diag_writer_howto_write_messages
/// \section stk_util_diag_writer_write_messages Writing to the appout writer
///
/// There are several functions and manipulators which control the selection and
/// formatting of the diagnostic output.
///
/// <UL>
/// <LI>The print mask and the line mask
///
/// It is the interaction of the print mask and line mask which determines is the data is
/// to be written to the diagnostic stream.  The print mask is set by the user on the
/// command line or in the input deck.  The line mask is set by the developer using the
/// <b>m</b> member function and <b>Diag::setlinemask</b> and <b>Diag::resetlinemask</b>
/// manipulators.
///
/// As each << operator is executed, the print mask and current line mask are bitwise
/// anded together.  If the result of this is non zero, then the line is output.
///
/// <LI>std::endl and Diag::dendl
///
/// Be sure to include std::endl or Diag::dendl at the end of each output line.  The end
/// line functions serve as a mask application terminator.  In other word, the mask
/// specified using the m member function are in effect until the std::endl of Diag::dendl
/// functions are called on the diagnostic stream.  Leaving one out can effect the what is
/// selected to be output.
///
/// <LI>Diag::push and Diag::pop
///
/// The push manipulator pushes the current LineMask onto a stack and the pop manipulator
/// restores the LineMask from the top element of the push stack.
///
/// </UL>
///
/// \anchor stk_util_diag_writer_howto_throw_safe
/// \section stk_util_diag_writer_throw_safe Indentation and exceptions
///
/// When exception occur, the pops put-to the output stream are skipped by the exception catch
/// block.  As a result, the indentation can start to march across the screen.  To correct this
/// behavior, add a ThrowSafe sentry within your try block prior to any push operations.
///
/// \code
/// 	try { // TimeStepError
///       stk::diag::WriterThrowSafe throw_safe_sentry;
/// 
///       appout.m(LOG_TEST) << "Executing run_it() on " << name() << push << dendl;
///       run_it();
///       appout.m(LOG_TEST) << pop;   /// Missed when run_it() throws
///     }
///     catch (std::exception &x) {
///       appout.m(LOG_TEST) << "Exception caught running run_it() on " << name() << dendl;
///     }
/// \endcode
///
/// @}
///

