0028673: getsourcefile Draw command return different output on Linux and Windows...
[occt.git] / src / Draw / Draw_Interpretor.cxx
index bbceedf..025df31 100644 (file)
@@ -26,6 +26,7 @@
 #include <OSD_Process.hxx>
 #include <OSD_Path.hxx>
 #include <OSD.hxx>
+#include <OSD_File.hxx>
 
 #include <string.h>
 #include <tcl.h>
@@ -34,7 +35,7 @@
 #endif
 
 // for capturing of cout and cerr (dup(), dup2())
-#ifdef _MSC_VER
+#ifdef _WIN32
 #include <io.h>
 #endif
 
 #define TCL_USES_UTF8
 #endif
 
-//
-// Auxiliary tool to convert strings in command arguments from UTF-8 
-// (Tcl internal encoding since Tcl 8.1) to system local encoding, 
-// normally extended Ascii as expected by OCC commands
-//
-class TclUTFToLocalStringSentry {
- public:
-
-#ifdef TCL_USES_UTF8
-  TclUTFToLocalStringSentry (int argc, const char **argv) :
-    nb(0),
-    TclArgv(new Tcl_DString[argc]),
-    Argv(new char*[argc])
-  {
-    for (; nb < argc; nb++ ) {
-      Tcl_UtfToExternalDString ( NULL, argv[nb], -1, &TclArgv[nb] );
-      Argv[nb] = Tcl_DStringValue ( &TclArgv[nb] );
-    }
-  }
-  
-  ~TclUTFToLocalStringSentry () 
-  {
-    delete[] Argv;
-    while ( nb-- >0 ) Tcl_DStringFree ( &TclArgv[nb] );
-    delete[] TclArgv;
-  }
-#else
-  TclUTFToLocalStringSentry (int, const char **argv) : 
-          nb(0),
-       TclArgv(NULL),
-          Argv((char**)argv)
-  {}
-#endif
-
-  const char **GetArgv () const { return (const char **)Argv; }
-  
- private:
-  int nb;
-  Tcl_DString *TclArgv;
-  char **Argv;
-};
-
 // logging helpers
 namespace {
   void dumpArgs (Standard_OStream& os, int argc, const char *argv[])
@@ -108,52 +67,38 @@ namespace {
     cout << flush;
   }
 
-  FILE* capture_start (int std_fd, int *save_fd, char*& tmp_name)
+  int capture_start (OSD_File& theTmpFile, int std_fd)
   {
-    *save_fd = 0;
-
-    // open temporary files
-  #if defined(_WIN32)
-    // use _tempnam() to decrease chances of failure (tmpfile() creates 
-    // file in root folder and will fail if it is write protected), see #24132
-    static const char* tmpdir = getenv("TEMP");
-    static char prefix[256] = ""; // prefix for temporary files, initialize once per process using pid
-    if (prefix[0] == '\0')
-      sprintf (prefix, "drawtmp%d_", (int)OSD_Process().ProcessId());
-    tmp_name = _tempnam (tmpdir, prefix);
-    FILE* aTmpFile = (tmp_name != NULL ? fopen (tmp_name, "w+b") : tmpfile());
-  #else
-    tmp_name = NULL;
-    FILE* aTmpFile = tmpfile();
-  #endif
-    int fd_tmp = (aTmpFile != NULL ? fileno (aTmpFile) : -1);
-    if (fd_tmp < 0)
+    theTmpFile.BuildTemporary();
+    if (theTmpFile.Failed())
     {
       cerr << "Error: cannot create temporary file for capturing console output" << endl;
-      fclose (aTmpFile);
-      return NULL;
+      return -1;
     }
 
     // remember current file descriptors of standard stream, and replace it by temporary
-    (*save_fd) = dup(std_fd);
-    dup2(fd_tmp, std_fd);
-    return aTmpFile;
+    return theTmpFile.Capture(std_fd);
   }
 
-  void capture_end (FILE* tmp_file, int std_fd, int save_fd, char* tmp_name, Standard_OStream &log, Standard_Boolean doEcho)
+  void capture_end (OSD_File* tmp_file, int std_fd, int save_fd, Standard_OStream &log, Standard_Boolean doEcho)
   {
-    if (! tmp_file)
+    if (!tmp_file)
       return;
 
     // restore normal descriptors of console stream
-    dup2 (save_fd, std_fd);
+  #ifdef _WIN32
+    _dup2(save_fd, std_fd);
+    _close(save_fd);
+  #else
+    dup2(save_fd, std_fd);
     close(save_fd);
+  #endif
 
     // extract all output and copy it to log and optionally to cout
     const int BUFSIZE = 2048;
-    char buf[BUFSIZE];
-    rewind(tmp_file);
-    while (fgets (buf, BUFSIZE, tmp_file) != NULL)
+    TCollection_AsciiString buf;
+    tmp_file->Rewind();
+    while (tmp_file->ReadLine (buf, BUFSIZE) > 0)
     {
       log << buf;
       if (doEcho) 
@@ -161,13 +106,14 @@ namespace {
     }
 
     // close temporary file
-    fclose (tmp_file);
+    tmp_file->Close();
 
     // remove temporary file if this is not done by the system
-    if (tmp_name)
-      remove (tmp_name);
+    if (tmp_file->Exists())
+      tmp_file->Remove();
   }
-};
+
+} // anonymous namespace
 
 // MKV 29.03.05
 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))) && !defined(USE_NON_CONST)
@@ -199,15 +145,13 @@ static Standard_Integer CommandCmd
   flush_standard_streams();
 
   // capture cout and cerr to log
-  char *err_name = NULL, *out_name = NULL;
-  FILE * aFile_err = NULL;
-  FILE * aFile_out = NULL;
-  int fd_err_save = 0;
-  int fd_out_save = 0;
+  OSD_File aFile_out, aFile_err;
+  int fd_err_save = -1;
+  int fd_out_save = -1;
   if (doLog)
   {
-    aFile_out = capture_start (STDOUT_FILENO, &fd_out_save, out_name);
-    aFile_err = capture_start (STDERR_FILENO, &fd_err_save, err_name);
+    fd_out_save = capture_start (aFile_out, STDOUT_FILENO);
+    fd_err_save = capture_start (aFile_err, STDERR_FILENO);
   }
 
   // run command
@@ -217,17 +161,13 @@ static Standard_Integer CommandCmd
     // get exception if control-break has been pressed 
     OSD::ControlBreak();
 
-    // OCC63: Convert strings from UTF-8 to local encoding, normally expected by OCC commands
-    TclUTFToLocalStringSentry anArgs ( argc, (const char**)argv );
+    // OCC680: Transfer UTF-8 directly to OCC commands without locale usage
       
-    Standard_Integer fres = aCallback->Invoke ( di, argc, anArgs.GetArgv() );
+    Standard_Integer fres = aCallback->Invoke ( di, argc, argv /*anArgs.GetArgv()*/ );
     if (fres != 0) 
       code = TCL_ERROR;
   }
-  catch (Standard_Failure) {
-
-    Handle(Standard_Failure) E = Standard_Failure::Caught();
-
+  catch (Standard_Failure const& anException) {
     // fail if Draw_ExitOnCatch is set
     // MKV 29.03.05
 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))) && !defined(USE_NON_CONST)
@@ -238,10 +178,10 @@ static Standard_Integer CommandCmd
                          "Draw_ExitOnCatch",TCL_GLOBAL_ONLY);
 #endif
 
-    cout << "An exception was caught " << E << endl;
+    cout << "An exception was caught " << anException << endl;
 
     if (cc && Draw::Atoi(cc)) {
-#ifdef WNT
+#ifdef _WIN32
       Tcl_Exit(0);
 #else      
       Tcl_Eval(interp,"exit");
@@ -250,7 +190,7 @@ static Standard_Integer CommandCmd
 
     // get the error message
     Standard_SStream ss;
-    ss << "** Exception ** " << E << ends;
+    ss << "** Exception ** " << anException << ends;
     Tcl_SetResult(interp,(char*)(ss.str().c_str()),TCL_VOLATILE);
     code = TCL_ERROR;
   }
@@ -261,8 +201,8 @@ static Standard_Integer CommandCmd
   // end capturing cout and cerr 
   if (doLog) 
   {
-    capture_end (aFile_err, STDERR_FILENO, fd_err_save, err_name, di.Log(), doEcho);
-    capture_end (aFile_out, STDOUT_FILENO, fd_out_save, out_name, di.Log(), doEcho);
+    capture_end (&aFile_err, STDERR_FILENO, fd_err_save, di.Log(), doEcho);
+    capture_end (&aFile_out, STDOUT_FILENO, fd_out_save, di.Log(), doEcho);
   }
 
   // log command result
@@ -371,6 +311,8 @@ void Draw_Interpretor::add (const Standard_CString          theCommandName,
   aPath.SetNode ("");
   TCollection_AsciiString aSrcPath;
   aPath.SystemName (aSrcPath);
+  if (aSrcPath.Value(1) == '/')
+    aSrcPath.Remove(1);
   Tcl_SetVar2 (myInterp, "Draw_Files", aName, aSrcPath.ToCString(), TCL_GLOBAL_ONLY);
 }
 
@@ -530,11 +472,7 @@ void Draw_Interpretor::AppendElement(const Standard_CString s)
 
 Standard_Integer Draw_Interpretor::Eval(const Standard_CString line)
 {
-  Standard_PCharacter pLine;
-  //
-  pLine=(Standard_PCharacter)line;
-  //
-  return Tcl_Eval(myInterp,pLine);
+  return Tcl_Eval(myInterp,line);
 }
 
 
@@ -546,10 +484,7 @@ Standard_Integer Draw_Interpretor::Eval(const Standard_CString line)
 Standard_Integer Draw_Interpretor::RecordAndEval(const Standard_CString line,
                                                 const Standard_Integer flags)
 {
-  Standard_PCharacter pLine;
-  //
-  pLine=(Standard_PCharacter)line;
-  return Tcl_RecordAndEval(myInterp,pLine,flags);
+  return Tcl_RecordAndEval(myInterp,line,flags);
 }
 
 //=======================================================================
@@ -559,10 +494,7 @@ Standard_Integer Draw_Interpretor::RecordAndEval(const Standard_CString line,
 
 Standard_Integer Draw_Interpretor::EvalFile(const Standard_CString fname)
 {
-  Standard_PCharacter pfname;
-  //
-  pfname=(Standard_PCharacter)fname;
-  return Tcl_EvalFile(myInterp,pfname);
+  return Tcl_EvalFile(myInterp,fname);
 }
 
 //=======================================================================
@@ -587,7 +519,7 @@ Standard_Boolean Draw_Interpretor::Complete(const Standard_CString line)
   Standard_PCharacter pLine;
   //
   pLine=(Standard_PCharacter)line;
-  return Tcl_CommandComplete(pLine);
+  return Tcl_CommandComplete (pLine) != 0;
 }
 
 //=======================================================================
@@ -604,12 +536,12 @@ Draw_Interpretor::~Draw_Interpretor()
     Tcl_Exit(0);
   }
   catch (Standard_Failure) {
-#ifdef DEB
+#ifdef OCCT_DEBUG
     cout <<"Tcl_Exit have an exeption" << endl;
 #endif
   }
 #else
-#ifdef WNT
+#ifdef _WIN32
   Tcl_Exit(0);
 #endif  
 #endif