1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

0031731: Draw Harness - colorize errors and exception messages

Draw_Interpretor, CommandCmd() - catched exceptions and messages put into Tcl string result
before throwing a Tcl exception (return 1) are now print in intense red (using Message::SendFail()).
Duplication of exception message in std::cout and Tcl output has been removed.

Draw Harness plugins have been updated to use either Message::SendFail() or theDI instead of std::cout/std::cerr
for printing colored error message before throwing a Tcl exception.
This commit is contained in:
kgv
2020-08-24 19:13:08 +03:00
parent 1d99a2baaa
commit d99f0355e3
98 changed files with 514 additions and 620 deletions

View File

@@ -59,7 +59,7 @@ extern Standard_Boolean Draw_ParseFailed;
Standard_EXPORT Draw_Viewer dout;
Standard_EXPORT Draw_Interpretor theCommands;
Standard_EXPORT Standard_Boolean Draw_Batch;
Standard_EXPORT Standard_Boolean Draw_Batch = Standard_False;
Standard_EXPORT Standard_Boolean Draw_Spying = Standard_False;
Standard_EXPORT Standard_Boolean Draw_Chrono = Standard_False;
Standard_EXPORT Standard_Boolean Draw_VirtualWindows = Standard_False;
@@ -504,14 +504,7 @@ void Draw_Appli(int argc, char** argv, const FDraw_InitAppli Draw_InitAppli)
if (!isInteractiveForced)
{
// disable console messages colorization to avoid spoiling log with color codes
for (Message_SequenceOfPrinters::Iterator aPrinterIter (Message::DefaultMessenger()->Printers());
aPrinterIter.More(); aPrinterIter.Next())
{
if (Handle(Message_PrinterOStream) aPrinter = Handle(Message_PrinterOStream)::DownCast (aPrinterIter.Value()))
{
aPrinter->SetToColorize (Standard_False);
}
}
theCommands.SetToColorize (Standard_False);
}
ReadInitFile (aRunFile);
// provide a clean exit, this is useful for some analysis tools
@@ -637,7 +630,15 @@ Standard_Boolean Draw_Interprete(const char* com)
if (*theCommands.Result())
{
if (c > 0 && theCommands.ToColorize())
{
Message_PrinterOStream::SetConsoleTextColor (&std::cout, Message_ConsoleColor_Red, true);
}
std::cout << theCommands.Result() << std::endl;
if (c > 0 && theCommands.ToColorize())
{
Message_PrinterOStream::SetConsoleTextColor (&std::cout, Message_ConsoleColor_Default, false);
}
}
if (Draw_Chrono && hadchrono) {

View File

@@ -259,9 +259,9 @@ static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const cha
{
if (n != 2 && n != 3)
{
std::cout << "Enable or disable logging: " << a[0] << " {on|off}" << std::endl;
std::cout << "Reset log: " << a[0] << " reset" << std::endl;
std::cout << "Get log content: " << a[0] << " get" << std::endl;
Message::SendFail() << "Enable or disable logging: " << a[0] << " {on|off}\n"
<< "Reset log: " << a[0] << " reset\n"
<< "Get log content: " << a[0] << " get";
return 1;
}
@@ -292,7 +292,7 @@ static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const cha
di << (di.GetDoLog() ? "on" : "off");
}
else {
std::cout << "Unrecognized option(s): " << a[1] << std::endl;
Message::SendFail() << "Unrecognized option(s): " << a[1];
return 1;
}
return 0;
@@ -302,7 +302,7 @@ static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const ch
{
if (n != 2)
{
std::cout << "Enable or disable echoing: " << a[0] << " {on|off}" << std::endl;
Message::SendFail() << "Enable or disable echoing: " << a[0] << " {on|off}";
return 1;
}
@@ -315,7 +315,7 @@ static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const ch
di.SetDoEcho (Standard_False);
}
else {
std::cout << "Unrecognized option: " << a[1] << std::endl;
Message::SendFail() << "Unrecognized option: " << a[1];
return 1;
}
return 0;
@@ -762,7 +762,7 @@ static int dlocale (Draw_Interpretor& di, Standard_Integer n, const char** argv)
else if ( ! strcmp (cat, "LC_TIME") ) category = LC_TIME;
else
{
std::cout << "Error: cannot recognize argument " << cat << " as one of LC_ macros" << std::endl;
Message::SendFail() << "Error: cannot recognize argument " << cat << " as one of LC_ macros";
return 1;
}
}
@@ -884,7 +884,7 @@ static int dparallel (Draw_Interpretor& theDI,
const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
if (aVal <= 0 || aVal > aDefPool->NbThreads())
{
std::cout << "Syntax error: maximum number of threads to use should be <= of threads in the pool\n";
Message::SendFail() << "Syntax error: maximum number of threads to use should be <= of threads in the pool";
return 1;
}
aDefPool->SetNbDefaultThreadsToLaunch (aVal);
@@ -915,7 +915,7 @@ static int dparallel (Draw_Interpretor& theDI,
}
else
{
std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
return 1;
}
}
@@ -989,7 +989,7 @@ static int dsetsignal (Draw_Interpretor& theDI, Standard_Integer theArgNb, const
}
else
{
std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
return 1;
}
}
@@ -1023,7 +1023,7 @@ static int dtracelevel (Draw_Interpretor& theDI,
Message_Gravity aLevel = Message_Info;
if (theArgNb < 1 || theArgNb > 2)
{
std::cout << "Error: wrong number of arguments! See usage:\n";
Message::SendFail() << "Error: wrong number of arguments! See usage:";
theDI.PrintHelp (theArgVec[0]);
return 1;
}
@@ -1054,7 +1054,7 @@ static int dtracelevel (Draw_Interpretor& theDI,
}
else
{
std::cout << "Error: unknown gravity '" << theArgVec[1] << "'!\n";
Message::SendFail() << "Error: unknown gravity '" << theArgVec[1] << "'";
return 1;
}
}
@@ -1062,14 +1062,14 @@ static int dtracelevel (Draw_Interpretor& theDI,
Handle(Message_Messenger) aMessenger = Message::DefaultMessenger();
if (aMessenger.IsNull())
{
std::cout << "Error: default messenger is unavailable!\n";
Message::SendFail() << "Error: default messenger is unavailable";
return 1;
}
Message_SequenceOfPrinters& aPrinters = aMessenger->ChangePrinters();
if (aPrinters.Length() < 1)
{
std::cout << "Error: no printers registered in default Messenger!\n";
Message::SendFail() << "Error: no printers registered in default Messenger";
return 0;
}
@@ -1108,7 +1108,7 @@ static int dtracelevel (Draw_Interpretor& theDI,
//function : dputs
//purpose :
//==============================================================================
static int dputs (Draw_Interpretor& ,
static int dputs (Draw_Interpretor& theDI,
Standard_Integer theArgNb,
const char** theArgVec)
{
@@ -1169,6 +1169,11 @@ static int dputs (Draw_Interpretor& ,
}
else if (anArgIter + 1 == theArgNb)
{
if (!theDI.ToColorize())
{
toIntense = false;
aColor = Message_ConsoleColor_Default;
}
if (toIntense || aColor != Message_ConsoleColor_Default)
{
Message_PrinterOStream::SetConsoleTextColor (aStream, aColor, toIntense);

View File

@@ -25,6 +25,7 @@
#include <Draw_ProgressIndicator.hxx>
#include <Draw_Text2D.hxx>
#include <Draw_Text3D.hxx>
#include <Message.hxx>
#include <Standard_Stream.hxx>
#include <TCollection_AsciiString.hxx>
@@ -195,12 +196,12 @@ static Standard_Integer wzoom(Draw_Interpretor& di, Standard_Integer argc, const
id = atoi(argv[1]);
if ((id < 0) || (id >= MAXVIEW))
{
std::cout << "Incorrect view-id, must be in 0.."<<MAXVIEW-1<<std::endl;
Message::SendFail() << "Incorrect view-id, must be in 0.." << (MAXVIEW-1);
return 1;
}
if (!dout.HasView(id))
{
std::cout <<"View "<<id<<" does not exist."<<std::endl;
Message::SendFail() << "View " << id << " does not exist";
return 1;
}
X1 = atoi (argv [2]);

View File

@@ -15,18 +15,20 @@
// commercial license or contractual agreement.
#include <Draw_Interpretor.hxx>
#include <Draw_Appli.hxx>
#include <Message.hxx>
#include <Message_PrinterOStream.hxx>
#include <OSD.hxx>
#include <OSD_File.hxx>
#include <OSD_Path.hxx>
#include <OSD_Process.hxx>
#include <Standard_SStream.hxx>
#include <Standard_RangeError.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Macro.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
#include <OSD_Process.hxx>
#include <OSD_Path.hxx>
#include <OSD.hxx>
#include <OSD_File.hxx>
#include <string.h>
#include <tcl.h>
@@ -114,8 +116,7 @@ namespace {
static Standard_Integer CommandCmd (ClientData theClientData, Tcl_Interp* interp, Standard_Integer argc, const char* argv[])
{
static Standard_Integer code;
code = TCL_OK;
Standard_Integer code = TCL_OK;
Draw_Interpretor::CallBackData* aCallback = (Draw_Interpretor::CallBackData* )theClientData;
Draw_Interpretor& di = *(aCallback->myDI);
@@ -143,24 +144,26 @@ static Standard_Integer CommandCmd (ClientData theClientData, Tcl_Interp* interp
dumpArgs (std::cout, argc, argv);
// run command
try {
try
{
OCC_CATCH_SIGNALS
// get exception if control-break has been pressed
OSD::ControlBreak();
// OCC680: Transfer UTF-8 directly to OCC commands without locale usage
Standard_Integer fres = aCallback->Invoke ( di, argc, argv /*anArgs.GetArgv()*/ );
if (fres != 0)
if (fres != 0)
{
code = TCL_ERROR;
}
}
catch (Standard_Failure const& anException) {
catch (Standard_Failure const& anException)
{
// fail if Draw_ExitOnCatch is set
std::cout << "An exception was caught " << anException << std::endl;
const char* toExitOnCatch = Tcl_GetVar (interp, "Draw_ExitOnCatch", TCL_GLOBAL_ONLY);
if (toExitOnCatch != NULL && Draw::Atoi (toExitOnCatch))
{
Message::SendFail() << "An exception was caught " << anException;
#ifdef _WIN32
Tcl_Exit(0);
#else
@@ -168,18 +171,17 @@ static Standard_Integer CommandCmd (ClientData theClientData, Tcl_Interp* interp
#endif
}
// get the error message
Standard_SStream ss;
ss << "** Exception ** " << anException << std::ends;
ss << "An exception was caught " << anException << std::ends;
Tcl_SetResult(interp,(char*)(ss.str().c_str()),TCL_VOLATILE);
code = TCL_ERROR;
}
catch (std::exception const& theStdException)
{
std::cout << "An exception was caught " << theStdException.what() << " [" << typeid(theStdException).name() << "]" << std::endl;
const char* toExitOnCatch = Tcl_GetVar (interp, "Draw_ExitOnCatch", TCL_GLOBAL_ONLY);
if (toExitOnCatch != NULL && Draw::Atoi (toExitOnCatch))
{
Message::SendFail() << "An exception was caught " << theStdException.what() << " [" << typeid(theStdException).name() << "]";
#ifdef _WIN32
Tcl_Exit (0);
#else
@@ -187,18 +189,17 @@ static Standard_Integer CommandCmd (ClientData theClientData, Tcl_Interp* interp
#endif
}
// get the error message
Standard_SStream ss;
ss << "** Exception ** " << theStdException.what() << " [" << typeid(theStdException).name() << "]" << std::ends;
Tcl_SetResult (interp, (char*)(ss.str().c_str()), TCL_VOLATILE);
ss << "An exception was caught " << theStdException.what() << " [" << typeid(theStdException).name() << "]" << std::ends;
Tcl_SetResult(interp,(char*)(ss.str().c_str()),TCL_VOLATILE);
code = TCL_ERROR;
}
catch (...)
{
std::cout << "UNKNOWN exception was caught " << std::endl;
const char* toExitOnCatch = Tcl_GetVar (interp, "Draw_ExitOnCatch", TCL_GLOBAL_ONLY);
if (toExitOnCatch != NULL && Draw::Atoi (toExitOnCatch))
{
Message::SendFail() << "UNKNOWN exception was caught ";
#ifdef _WIN32
Tcl_Exit (0);
#else
@@ -206,10 +207,9 @@ static Standard_Integer CommandCmd (ClientData theClientData, Tcl_Interp* interp
#endif
}
// get the error message
Standard_SStream ss;
ss << "** Exception ** UNKNOWN" << std::ends;
Tcl_SetResult (interp, (char* )(ss.str().c_str()), TCL_VOLATILE);
ss << "UNKNOWN exception was caught " << std::ends;
Tcl_SetResult(interp,(char*)(ss.str().c_str()),TCL_VOLATILE);
code = TCL_ERROR;
}
@@ -244,15 +244,34 @@ static void CommandDelete (ClientData theClientData)
//=======================================================================
//function : Draw_Interpretor
//purpose :
//purpose :
//=======================================================================
Draw_Interpretor::Draw_Interpretor() :
isAllocated(Standard_False), myDoLog(Standard_False), myDoEcho(Standard_False), myFDLog(-1)
Draw_Interpretor::Draw_Interpretor()
: // the tcl interpreter is not created immediately as it is kept
// by a global variable and created and deleted before the main()
myInterp (NULL),
isAllocated (Standard_False),
myDoLog (Standard_False),
myDoEcho (Standard_False),
myToColorize (Standard_True),
myFDLog (-1)
{
// The tcl interpreter is not created immediately as it is kept
// by a global variable and created and deleted before the main().
myInterp = NULL;
//
}
//=======================================================================
//function : Draw_Interpretor
//purpose :
//=======================================================================
Draw_Interpretor::Draw_Interpretor (const Draw_PInterp& theInterp)
: myInterp (theInterp),
isAllocated (Standard_False),
myDoLog (Standard_False),
myDoEcho (Standard_False),
myToColorize (Standard_True),
myFDLog (-1)
{
//
}
//=======================================================================
@@ -269,17 +288,20 @@ void Draw_Interpretor::Init()
}
//=======================================================================
//function : Draw_Interpretor
//purpose :
//function : SetToColorize
//purpose :
//=======================================================================
Draw_Interpretor::Draw_Interpretor(const Draw_PInterp& p) :
isAllocated(Standard_False),
myInterp(p),
myDoLog(Standard_False),
myDoEcho(Standard_False),
myFDLog(-1)
void Draw_Interpretor::SetToColorize (Standard_Boolean theToColorize)
{
myToColorize = theToColorize;
for (Message_SequenceOfPrinters::Iterator aPrinterIter (Message::DefaultMessenger()->Printers());
aPrinterIter.More(); aPrinterIter.Next())
{
if (Handle(Message_PrinterOStream) aPrinter = Handle(Message_PrinterOStream)::DownCast (aPrinterIter.Value()))
{
aPrinter->SetToColorize (Standard_False);
}
}
}
//=======================================================================

View File

@@ -251,6 +251,12 @@ public:
//! Returns current value of the log file descriptor
Standard_Integer GetLogFileDescriptor() { return myFDLog; }
//! Return TRUE if console output should be colorized; TRUE by default.
Standard_Boolean ToColorize() const { return myToColorize; }
//! Set if console output should be colorized.
Standard_EXPORT void SetToColorize (Standard_Boolean theToColorize);
protected:
Standard_EXPORT void add (Standard_CString theCommandName,
@@ -261,10 +267,11 @@ protected:
private:
Standard_Boolean isAllocated;
Draw_PInterp myInterp;
Standard_Boolean isAllocated;
Standard_Boolean myDoLog;
Standard_Boolean myDoEcho;
Standard_Boolean myToColorize;
Standard_Integer myFDLog; //!< file descriptor of log file
public:

View File

@@ -258,7 +258,7 @@ static Standard_Integer dtryload (Draw_Interpretor& di, Standard_Integer n, cons
{
if (n != 2)
{
std::cout << "Error: specify path to library to be loaded" << std::endl;
Message::SendFail() << "Error: specify path to library to be loaded";
return 1;
}

View File

@@ -25,6 +25,7 @@
#include <Draw_Number.hxx>
#include <Draw_ProgressIndicator.hxx>
#include <Draw_SequenceOfDrawable3D.hxx>
#include <Message.hxx>
#include <NCollection_Map.hxx>
#include <Standard_SStream.hxx>
#include <Standard_Stream.hxx>
@@ -388,7 +389,7 @@ static Standard_Integer draw(Draw_Interpretor& , Standard_Integer n, const char*
if (n < 3) return 1;
Standard_Integer id = Draw::Atoi(a[1]);
if (!dout.HasView(id)) {
std::cout << "bad view number in draw"<<std::endl;
Message::SendFail() << "bad view number in draw";
return 1;
}
Standard_Integer mo = Draw::Atoi(a[2]);
@@ -587,7 +588,7 @@ static Standard_Integer set(Draw_Interpretor& di, Standard_Integer n, const char
static Standard_Integer dsetenv(Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
{
if (argc < 2) {
std::cout << "Use: " << argv[0] << " {varname} [value]" << std::endl;
Message::SendFail() << "Use: " << argv[0] << " {varname} [value]";
return 1;
}
@@ -610,7 +611,7 @@ static Standard_Integer dsetenv(Draw_Interpretor& /*di*/, Standard_Integer argc,
static Standard_Integer dgetenv(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
{
if (argc < 2) {
std::cout << "Use: " << argv[0] << " {varname}" << std::endl;
Message::SendFail() << "Use: " << argv[0] << " {varname}";
return 1;
}