Storage and retrieval of a document by means of a stream is distributed to TObj model.
Modified files:
-TObj_Model.hxx, cxx - the virtual methods Load() and SaveAs() obtained a stream as an argument instead of a file name.
-TObj_Application.hxx, cxx - same extension: the virtual methods LoadDocument() and SaveDocument() use a stream to open and save a document.
-TObjDRAW.cxx - draw-commands TObjSave and TObjLoad are extended for -stream parameter, which allows usage of a file input or output stream instead of a file name.
A new test:
- bugs caf bug29901 - it creates a simple TObj-model, saves it on disk using a file stream, loads it by means of a file stream and checks the content.
Modified test:
- bugs caf bug28425 - just improved to proper manipulate a test-file on disk.
(const Handle(TDocStd_Document)& theSourceDoc,
const TCollection_ExtendedString& theTargetFile)
{
- myIsError = Standard_False;
- PCDM_StoreStatus aStatus = SaveAs (theSourceDoc, theTargetFile);
- myIsError = aStatus != PCDM_SS_OK;
+ const PCDM_StoreStatus aStatus = SaveAs (theSourceDoc, theTargetFile);
+ myIsError = (aStatus != PCDM_SS_OK);
if (myIsError)
- {
- switch (aStatus)
- {
- case PCDM_SS_DriverFailure:
- ErrorMessage (Message_Msg("TObj_Appl_SDriverFailure") << theTargetFile);
- break;
- case PCDM_SS_WriteFailure:
- ErrorMessage (Message_Msg("TObj_Appl_SWriteFailure") << theTargetFile);
- break;
- case PCDM_SS_Failure:
- ErrorMessage (Message_Msg("TObj_Appl_SFailure") << theTargetFile);
- break;
- case PCDM_SS_Doc_IsNull:
- ErrorMessage (Message_Msg("TObj_Appl_SDocIsNull") << theTargetFile);
- break;
- case PCDM_SS_No_Obj:
- ErrorMessage (Message_Msg("TObj_Appl_SNoObj") << theTargetFile);
- break;
- case PCDM_SS_Info_Section_Error:
- ErrorMessage (Message_Msg("TObj_Appl_SInfoSectionError") << theTargetFile);
- break;
- default:
- ErrorMessage (Message_Msg("TObj_Appl_SUnknownFailure") << theTargetFile);
- break;
- }
- }
+ SetError (aStatus, theTargetFile);
+
+ // Release free memory
+ Standard::Purge();
+ return myIsError ? Standard_False : Standard_True;
+}
+
+//=======================================================================
+//function : SaveDocument
+//purpose : Saving the OCAF document to a stream
+//=======================================================================
+
+Standard_Boolean TObj_Application::SaveDocument
+ (const Handle(TDocStd_Document)& theSourceDoc,
+ Standard_OStream& theOStream)
+{
+ const PCDM_StoreStatus aStatus = SaveAs (theSourceDoc, theOStream);
+ myIsError = (aStatus != PCDM_SS_OK);
+ if (myIsError)
+ SetError (aStatus, "");
// Release free memory
Standard::Purge();
(const TCollection_ExtendedString& theSourceFile,
Handle(TDocStd_Document)& theTargetDoc)
{
- myIsError = Standard_False;
PCDM_ReaderStatus aStatus = PCDM_RS_ReaderException;
{
try
ErrorMessage (Message_Msg("TObj_Appl_Exception") <<
anException.GetMessageString());
#endif
- (void)anException;
+ (void) anException;
}
}
- myIsError = aStatus != PCDM_RS_OK;
+ myIsError = (aStatus != PCDM_RS_OK);
if (myIsError)
+ SetError (aStatus, theSourceFile);
+
+ // Release free memory
+ Standard::Purge();
+ return myIsError ? Standard_False : Standard_True;
+}
+
+//=======================================================================
+//function : LoadDocument
+//purpose : Loading the OCAF document from a stream
+//=======================================================================
+
+Standard_Boolean TObj_Application::LoadDocument
+ (Standard_IStream& theIStream,
+ Handle(TDocStd_Document)& theTargetDoc)
+{
+ PCDM_ReaderStatus aStatus = PCDM_RS_ReaderException;
{
- switch (aStatus)
+ try
{
- case PCDM_RS_UnknownDocument:
- ErrorMessage (Message_Msg("TObj_Appl_RUnknownDocument") << theSourceFile);
- break;
- case PCDM_RS_AlreadyRetrieved:
- ErrorMessage (Message_Msg("TObj_Appl_RAlreadyRetrieved") << theSourceFile);
- break;
- case PCDM_RS_AlreadyRetrievedAndModified:
- ErrorMessage (Message_Msg("TObj_Appl_RAlreadyRetrievedAndModified") << theSourceFile);
- break;
- case PCDM_RS_NoDriver:
- ErrorMessage (Message_Msg("TObj_Appl_RNoDriver") << theSourceFile);
- break;
- case PCDM_RS_UnknownFileDriver:
- ErrorMessage (Message_Msg("TObj_Appl_RNoDriver") << theSourceFile);
- break;
- case PCDM_RS_OpenError:
- ErrorMessage (Message_Msg("TObj_Appl_ROpenError") << theSourceFile);
- break;
- case PCDM_RS_NoVersion:
- ErrorMessage (Message_Msg("TObj_Appl_RNoVersion") << theSourceFile);
- break;
- case PCDM_RS_NoModel:
- ErrorMessage (Message_Msg("TObj_Appl_RNoModel") << theSourceFile);
- break;
- case PCDM_RS_NoDocument:
- ErrorMessage (Message_Msg("TObj_Appl_RNoDocument") << theSourceFile);
- break;
- case PCDM_RS_FormatFailure:
- ErrorMessage (Message_Msg("TObj_Appl_RFormatFailure") << theSourceFile);
- break;
- case PCDM_RS_TypeNotFoundInSchema:
- ErrorMessage (Message_Msg("TObj_Appl_RTypeNotFound") << theSourceFile);
- break;
- case PCDM_RS_UnrecognizedFileFormat:
- ErrorMessage (Message_Msg("TObj_Appl_RBadFileFormat") << theSourceFile);
- break;
- case PCDM_RS_MakeFailure:
- ErrorMessage (Message_Msg("TObj_Appl_RMakeFailure") << theSourceFile);
- break;
- case PCDM_RS_PermissionDenied:
- ErrorMessage (Message_Msg("TObj_Appl_RPermissionDenied") << theSourceFile);
- break;
- case PCDM_RS_DriverFailure:
- ErrorMessage (Message_Msg("TObj_Appl_RDriverFailure") << theSourceFile);
- break;
- case PCDM_RS_ReaderException:
- ErrorMessage (Message_Msg("TObj_Appl_RException") << theSourceFile);
- break;
- default:
- ErrorMessage (Message_Msg("TObj_Appl_RUnknownFail") << theSourceFile);
- break;
+ aStatus = Open (theIStream, theTargetDoc);
+ }
+ catch (Standard_Failure const& anException) {
+#ifdef OCCT_DEBUG
+ ErrorMessage(Message_Msg("TObj_Appl_Exception") << anException.GetMessageString());
+#endif
+ (void) anException;
}
}
+ myIsError = (aStatus != PCDM_RS_OK);
+ if (myIsError)
+ SetError (aStatus, "");
// Release free memory
Standard::Purge();
OCCT_DUMP_BASE_CLASS (theOStream, theDepth, TDocStd_Application)
}
+
+//=======================================================================
+//function : SetError
+//purpose : Sets an error occured on storage of a document.
+//=======================================================================
+
+void TObj_Application::SetError (const PCDM_StoreStatus theStatus, const TCollection_ExtendedString& theInfo)
+{
+ switch (theStatus)
+ {
+ case PCDM_SS_DriverFailure:
+ ErrorMessage(Message_Msg("TObj_Appl_SDriverFailure") << theInfo);
+ break;
+ case PCDM_SS_WriteFailure:
+ ErrorMessage(Message_Msg("TObj_Appl_SWriteFailure") << theInfo);
+ break;
+ case PCDM_SS_Failure:
+ ErrorMessage(Message_Msg("TObj_Appl_SFailure") << theInfo);
+ break;
+ case PCDM_SS_Doc_IsNull:
+ ErrorMessage(Message_Msg("TObj_Appl_SDocIsNull") << theInfo);
+ break;
+ case PCDM_SS_No_Obj:
+ ErrorMessage(Message_Msg("TObj_Appl_SNoObj") << theInfo);
+ break;
+ case PCDM_SS_Info_Section_Error:
+ ErrorMessage(Message_Msg("TObj_Appl_SInfoSectionError") << theInfo);
+ break;
+ default:
+ ErrorMessage(Message_Msg("TObj_Appl_SUnknownFailure") << theInfo);
+ break;
+ }
+}
+
+//=======================================================================
+//function : SetError
+//purpose : Sets an error occured on reading of a document.
+//=======================================================================
+
+void TObj_Application::SetError(const PCDM_ReaderStatus theStatus, const TCollection_ExtendedString& theInfo)
+{
+ switch (theStatus)
+ {
+ case PCDM_RS_UnknownDocument:
+ ErrorMessage(Message_Msg("TObj_Appl_RUnknownDocument") << theInfo);
+ break;
+ case PCDM_RS_AlreadyRetrieved:
+ ErrorMessage(Message_Msg("TObj_Appl_RAlreadyRetrieved") << theInfo);
+ break;
+ case PCDM_RS_AlreadyRetrievedAndModified:
+ ErrorMessage(Message_Msg("TObj_Appl_RAlreadyRetrievedAndModified") << theInfo);
+ break;
+ case PCDM_RS_NoDriver:
+ ErrorMessage(Message_Msg("TObj_Appl_RNoDriver") << theInfo);
+ break;
+ case PCDM_RS_UnknownFileDriver:
+ ErrorMessage(Message_Msg("TObj_Appl_RNoDriver") << theInfo);
+ break;
+ case PCDM_RS_OpenError:
+ ErrorMessage(Message_Msg("TObj_Appl_ROpenError") << theInfo);
+ break;
+ case PCDM_RS_NoVersion:
+ ErrorMessage(Message_Msg("TObj_Appl_RNoVersion") << theInfo);
+ break;
+ case PCDM_RS_NoModel:
+ ErrorMessage(Message_Msg("TObj_Appl_RNoModel") << theInfo);
+ break;
+ case PCDM_RS_NoDocument:
+ ErrorMessage(Message_Msg("TObj_Appl_RNoDocument") << theInfo);
+ break;
+ case PCDM_RS_FormatFailure:
+ ErrorMessage(Message_Msg("TObj_Appl_RFormatFailure") << theInfo);
+ break;
+ case PCDM_RS_TypeNotFoundInSchema:
+ ErrorMessage(Message_Msg("TObj_Appl_RTypeNotFound") << theInfo);
+ break;
+ case PCDM_RS_UnrecognizedFileFormat:
+ ErrorMessage(Message_Msg("TObj_Appl_RBadFileFormat") << theInfo);
+ break;
+ case PCDM_RS_MakeFailure:
+ ErrorMessage(Message_Msg("TObj_Appl_RMakeFailure") << theInfo);
+ break;
+ case PCDM_RS_PermissionDenied:
+ ErrorMessage(Message_Msg("TObj_Appl_RPermissionDenied") << theInfo);
+ break;
+ case PCDM_RS_DriverFailure:
+ ErrorMessage(Message_Msg("TObj_Appl_RDriverFailure") << theInfo);
+ break;
+ case PCDM_RS_ReaderException:
+ ErrorMessage(Message_Msg("TObj_Appl_RException") << theInfo);
+ break;
+ default:
+ ErrorMessage(Message_Msg("TObj_Appl_RUnknownFail") << theInfo);
+ break;
+ }
+}
//! Saving the OCAF document to a file
Standard_EXPORT virtual Standard_Boolean SaveDocument
- (const Handle(TDocStd_Document)& theSourceDoc,
- const TCollection_ExtendedString& theTargetFile);
+ (const Handle(TDocStd_Document)& theSourceDoc,
+ const TCollection_ExtendedString& theTargetFile);
+
+ //! Saving the OCAF document to a stream
+ Standard_EXPORT virtual Standard_Boolean SaveDocument
+ (const Handle(TDocStd_Document)& theSourceDoc,
+ Standard_OStream& theOStream);
//! Loading the OCAF document from a file
Standard_EXPORT virtual Standard_Boolean LoadDocument
(const TCollection_ExtendedString& theSourceFile,
Handle(TDocStd_Document)& theTargetDoc);
+ //! Loading the OCAF document from a stream
+ Standard_EXPORT virtual Standard_Boolean LoadDocument
+ (Standard_IStream& theIStream,
+ Handle(TDocStd_Document)& theTargetDoc);
+
//! Create the OCAF document from scratch
virtual Standard_EXPORT Standard_Boolean CreateNewDocument
(Handle(TDocStd_Document)& theDoc,
//! the static instance of the object (or derive your own application)
Standard_EXPORT TObj_Application();
+ //! Sets an error occured on storage of a document.
+ void SetError (const PCDM_StoreStatus theStatus, const TCollection_ExtendedString& theInfo);
+
+ //! Sets an error occured on reading of a document.
+ void SetError (const PCDM_ReaderStatus theStatus, const TCollection_ExtendedString& theInfo);
+
private:
/**
* Fields
return aStatus;
}
+//=======================================================================
+//function : Load
+//purpose : Load the OCAF model from a stream. If case of failure,
+// it initializes the model by empty data.
+//=======================================================================
+
+Standard_Boolean TObj_Model::Load (Standard_IStream& theIStream)
+{
+ Handle(TDocStd_Document) aDoc;
+ Standard_Boolean aStatus = Standard_True, isFileLoaded = Standard_False;
+ const Handle(TObj_Application) anApplication = GetApplication();
+
+ // Current model
+ const Handle(TObj_Model) me = this;
+ TObj_Assistant::SetCurrentModel (me);
+ TObj_Assistant::ClearTypeMap();
+
+ // Retrieve TDocStd_Document from the stream.
+ Messenger()->Send (Message_Msg ("TObj_M_LoadDocument"), Message_Info);
+ aStatus = anApplication->LoadDocument (theIStream, aDoc);
+ if (aStatus)
+ {
+ // Check for validity of the model read:
+ // if it had wrong type, it has not been not properly restored
+ TDF_Label aLabel = GetLabel();
+ Standard_Boolean isValid = (!aLabel.IsNull() && !aDoc.IsNull());
+ try
+ {
+ isValid = (isValid && aLabel.Data() == aDoc->GetData());
+ }
+ catch (Standard_Failure const&)
+ {
+ isValid = Standard_False;
+ }
+ if (!isValid)
+ {
+ if (!aDoc.IsNull())
+ CloseDocument (aDoc);
+ myLabel.Nullify();
+ Messenger()->Send (Message_Msg ("TObj_M_WrongFile"), Message_Alarm);
+ aStatus = Standard_False;
+ }
+ isFileLoaded = isValid;
+ }
+ else
+ {
+ // release document from session
+ // no message is needed as it has been put in anApplication->LoadDocument()
+ if (!aDoc.IsNull())
+ CloseDocument (aDoc);
+ myLabel.Nullify();
+
+ aStatus = anApplication->CreateNewDocument (aDoc, GetFormat());
+ if (aStatus)
+ {
+ // Put model in a new attribute on root label
+ TDF_Label aLabel = aDoc->Main();
+ Handle(TObj_TModel) anAtr = new TObj_TModel;
+ aLabel.AddAttribute (anAtr);
+ anAtr->Set (me);
+ // Record that label in the model object, and initialise the new model
+ SetLabel (aLabel);
+ }
+ }
+
+ // Initialise the new model
+ if (aStatus)
+ {
+ Standard_Boolean isInitOk = Standard_False;
+ try
+ {
+ isInitOk = initNewModel (!isFileLoaded);
+ }
+ catch (Standard_Failure const& anException) {
+#ifdef OCCT_DEBUG
+ TCollection_ExtendedString aString(anException.DynamicType()->Name());
+ aString = aString + ": " + anException.GetMessageString();
+ Messenger()->Send (Message_Msg ("TObj_Appl_Exception") << aString);
+#endif
+ (void) anException;
+ Messenger()->Send (Message_Msg ("TObj_M_WrongFile"), Message_Alarm);
+ }
+ if (!isInitOk)
+ {
+ if (!aDoc.IsNull())
+ CloseDocument (aDoc);
+ myLabel.Nullify();
+ aStatus = Standard_False;
+ }
+ }
+
+ TObj_Assistant::UnSetCurrentModel();
+ TObj_Assistant::ClearTypeMap();
+ return aStatus;
+}
+
//=======================================================================
//function : GetFile
//purpose : Returns the full file name this model is to be saved to,
return aStatus;
}
+//=======================================================================
+//function : SaveAs
+//purpose : Save the model to a stream
+//=======================================================================
+
+Standard_Boolean TObj_Model::SaveAs (Standard_OStream& theOStream)
+{
+ TObj_Assistant::ClearTypeMap();
+ // OCAF document
+ Handle(TDocStd_Document) aDoc = TDocStd_Document::Get(GetLabel());
+ if (aDoc.IsNull())
+ return Standard_False;
+
+ // store transaction mode
+ Standard_Boolean aTrMode = aDoc->ModificationMode();
+ aDoc->SetModificationMode(Standard_False);
+ // store all trancienmt fields of object in OCAF document if any
+ Handle(TObj_ObjectIterator) anIterator;
+ for (anIterator = GetObjects(); anIterator->More(); anIterator->Next())
+ {
+ Handle(TObj_Object) anOCAFObj = anIterator->Value();
+ if (anOCAFObj.IsNull())
+ continue;
+ anOCAFObj->BeforeStoring();
+ } // end of for(anIterator = ...)
+ // set transaction mode back
+ aDoc->SetModificationMode(aTrMode);
+
+ // call Application->SaveAs()
+ Standard_Boolean aStatus = GetApplication()->SaveDocument(aDoc, theOStream);
+ TObj_Assistant::ClearTypeMap();
+ return aStatus;
+}
+
//=======================================================================
//function : Close
//purpose : Close the model and free related OCAF document
/**
* Implementation of Load/Save for OCAF based models
*/
-
+
//! Load the OCAF model from a file. If the filename is empty or file does
//! not exists, it just initializes model by empty data.
Standard_EXPORT virtual Standard_Boolean Load (const TCollection_ExtendedString& theFile);
+ //! Load the OCAF model from a stream. If case of failure,
+ //! it initializes the model by empty data.
+ Standard_EXPORT virtual Standard_Boolean Load (Standard_IStream& theIStream);
+
//! Save the model to a file
Standard_EXPORT virtual Standard_Boolean SaveAs (const TCollection_ExtendedString& theFile);
+ //! Save the model to a stream
+ Standard_EXPORT virtual Standard_Boolean SaveAs (Standard_OStream& theOStream);
+
//! Save the model to the same file
Standard_EXPORT Standard_Boolean Save ();
#include <BinTObjDrivers.hxx>
#include <XmlTObjDrivers.hxx>
+#include <OSD_OpenFile.hxx>
#include <stdio.h>
//=======================================================================
static Standard_Integer saveModel (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
{
- if (argc < 2) {di<<"Use "<< argv[0] << "nameDoc [fileName]\n";return 1;}
+ if (argc < 2) {di<<"Use "<< argv[0] << "nameDoc [fileName] [-stream]\n";return 1;}
Handle(TObj_Model) aModel = getModelByName(argv[1]);
if ( aModel.IsNull() ) return 1;
Standard_Boolean isSaved = Standard_False;
if (argc > 2 )
- isSaved = aModel->SaveAs( TCollection_ExtendedString (argv[2], Standard_True) );
+ {
+ Standard_Boolean anUseStream(Standard_False);
+ for (Standard_Integer i = 3; i < argc && !anUseStream; i++)
+ {
+ if (!strcmp(argv[i], "-stream"))
+ {
+ di << "standard SEEKABLE stream is used\n";
+ anUseStream = Standard_True;
+ }
+ }
+ if (anUseStream)
+ {
+ std::ofstream aFileStream;
+ OSD_OpenStream (aFileStream, argv[2], std::ios::out | std::ios::binary);
+ isSaved = aModel->SaveAs (aFileStream);
+ }
+ else
+ isSaved = aModel->SaveAs ( TCollection_ExtendedString (argv[2], Standard_True) );
+ }
else
isSaved = aModel->Save();
//=======================================================================
static Standard_Integer loadModel (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
{
- if (argc < 3) {di<<"Use "<< argv[0] << "nameDoc fileName\n";return 1;}
-
+ if (argc < 3) {di<<"Use "<< argv[0] << "nameDoc fileName [-stream]\n";return 1;}
+
+ Standard_Boolean anUseStream = Standard_False;
+ for (Standard_Integer i = 3; i < argc && !anUseStream; i++)
+ {
+ if (!strcmp(argv[i], "-stream"))
+ {
+ di << "standard SEEKABLE stream is used\n";
+ anUseStream = Standard_True;
+ }
+ }
+
Standard_Boolean isLoaded = Standard_False;
Handle(TObj_Model) aModel = getModelByName(argv[1]);
TCollection_ExtendedString aPath(argv[2], Standard_True);
{
// create new
aModel = new TObjDRAW_Model();
- isLoaded = aModel->Load(aPath);
+ if (anUseStream)
+ {
+ std::ifstream aFileStream;
+ OSD_OpenStream (aFileStream, aPath, std::ios::in | std::ios::binary);
+ isLoaded = aModel->Load (aFileStream);
+ }
+ else
+ isLoaded = aModel->Load (aPath);
+
if ( isLoaded )
{
Handle(TDocStd_Document) D = aModel->GetDocument();
- Handle(DDocStd_DrawDocument) DD = new DDocStd_DrawDocument(D);
+ Handle(DDocStd_DrawDocument) DD = new DDocStd_DrawDocument (D);
TDataStd_Name::Set(D->GetData()->Root(),argv[1]);
Draw::Set(argv[1],DD);
{
isLoaded = aModel->Load(aPath);
}
-
-
+
if (!isLoaded) {
di << "Error: Document not loaded\n";
return 1;
di.Add ("TObjNew","DocName \t: Create new TObj model with document named DocName",
__FILE__, newModel, g);
- di.Add ("TObjSave","DocName [Path] \t: Save Model with DocName",
+ di.Add ("TObjSave","DocName [Path] [-stream] \t: Save Model with DocName [by file path] [into a file stream]",
__FILE__, saveModel, g);
- di.Add ("TObjLoad","DocName Path \t: Load model DocName from file Path",
+ di.Add ("TObjLoad","DocName Path [-stream] \t: Load model DocName from file Path [file stream]",
__FILE__, loadModel, g);
di.Add ("TObjClose","DocName\t: Close model DocName",
############################################################
pload QAcommands
+set aTestFileBin $imagedir/${casename}.cbf
+set aTestFileXml $imagedir/${casename}.xml
vertex v 1 2 3
box b 10 20 30
} else {
puts "OK: order of shapes is correct"
}
-SaveAs D1 test.cbf
+SaveAs D1 ${aTestFileBin}
Close D1
-Open test.cbf D2
+Open ${aTestFileBin} D2
GetNewShapes D2 0:1 s
set info [whatis s_1]
if { [regexp "SOLID" $info] != 1 } {
} else {
puts "OK: order of shapes is correct"
}
-SaveAs D1 test.xml
+SaveAs D1 ${aTestFileXml}
Close D1
-Open test.xml D2
+Open ${aTestFileXml} D2
GetNewShapes D2 0:1 s
set info [whatis s_1]
if { [regexp "SOLID" $info] != 1 } {
--- /dev/null
+puts "============"
+puts "0029901: Support save to and restore from Stream interface in TObj package"
+puts "============"
+
+set status 0
+set BugNumber 29901
+pload TOBJ
+
+# Create a new document
+TObjNew TD1
+TObjAddObj TD1 obj1
+TObjSetVal TD1 obj1 ${BugNumber}
+
+# Save the document
+set aFile $imagedir/${test_image}-[file tail [info script]].cbf
+catch {[file delete ${aFile}]}
+catch {TObjSave TD1 ${aFile} -stream}
+if { ![file exists ${aFile}] } {
+ set status 1
+ puts "There is not ${aFile} file; TObjSave command: Error"
+ puts "bug${BugNumber}: ERROR"
+} else {
+ puts "Save the document to ${aFile} file"
+}
+
+TObjClose TD1
+unset TD1
+
+# Restore the document
+if [catch { TObjLoad TD2 ${aFile} -stream} catch_result] {
+ puts "bug${BugNumber}: ERROR"
+}
+
+# check stored single integer value
+set retInt [TObjGetVal TD2 obj1 -i]
+if { $retInt != ${BugNumber} } {
+ set status 1
+ puts "bug${BugNumber}: check stored single integer value; ERROR"
+}
+
+if { ${status} != 0 } {
+ puts "Faulty bug${BugNumber}"
+} else {
+ puts "OK bug${BugNumber}"
+}
+