]> OCCT Git - occt-wok.git/commitdiff
Initial revision
authorcas <cas@opencascade.com>
Fri, 22 Oct 1999 18:05:40 +0000 (18:05 +0000)
committercas <cas@opencascade.com>
Fri, 22 Oct 1999 18:05:40 +0000 (18:05 +0000)
63 files changed:
src/WOKUnix/FILES [new file with mode: 0755]
src/WOKUnix/INTERNLIB [new file with mode: 0755]
src/WOKUnix/WOKUnix.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_ASyncStatus.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_ASyncStatus.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_AdmFile.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_AdmFile.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Buffer.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_Buffer.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_CMPLRS.edl [new file with mode: 0755]
src/WOKUnix/WOKUnix_CantBlockBuffer.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_CantBlockBuffer.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Dir.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_DirEnt.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_DumbOutput.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_DumbOutput.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_DumpScript.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_DumpScript.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_FDSet.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_FDescr.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_FDescr.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_FileBuffer.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_FileBuffer.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_MaxPipeSize.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_MixedOutput.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_MixedOutput.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_NoBuffer.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_NoBuffer.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_OutErrOutput.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_OutErrOutput.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Path.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_Path.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Path.lxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_PathIterator.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_PathIterator.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Process.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_Process.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_ProcessManager.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_ProcessManager.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_ProcessOutput.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_ProcessOutput.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_RegExp.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_RegExp.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_RemoteShell.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_RemoteShell.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Shell.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_Shell.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_ShellManager.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_ShellManager.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_ShellStatus.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_ShellStatus.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_SigHandler.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Signal.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_Signal.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_StatBuf.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_SyncStatus.cdl [new file with mode: 0755]
src/WOKUnix/WOKUnix_SyncStatus.cxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_TimeStat.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_Timeval.hxx [new file with mode: 0755]
src/WOKUnix/WOKUnix_WOKSteps.edl [new file with mode: 0755]
src/WOKUnix/WOKUnix_regexp.h [new file with mode: 0755]
src/WOKUnix/WOKUnix_regexp_1.c [new file with mode: 0755]

diff --git a/src/WOKUnix/FILES b/src/WOKUnix/FILES
new file mode 100755 (executable)
index 0000000..5bcfc1d
--- /dev/null
@@ -0,0 +1,13 @@
+WOKUnix_TimeStat.hxx
+WOKUnix_Timeval.hxx
+WOKUnix_FDSet.hxx
+WOKUnix_SigHandler.hxx
+WOKUnix_MaxPipeSize.hxx
+WOKUnix_regexp.h
+WOKUnix_regexp_1.c
+WOKUnix_WOKSteps.edl
+WOKUnix_CMPLRS.edl
+WOKUnix_StatBuf.hxx
+WOKUnix_Dir.hxx
+WOKUnix_DirEnt.hxx
+INTERNLIB
diff --git a/src/WOKUnix/INTERNLIB b/src/WOKUnix/INTERNLIB
new file mode 100755 (executable)
index 0000000..209e6e8
--- /dev/null
@@ -0,0 +1,7 @@
+WOKUnix
+MMgt
+TColStd
+TCollection
+Standard
+OSD
+WOKTools
diff --git a/src/WOKUnix/WOKUnix.cdl b/src/WOKUnix/WOKUnix.cdl
new file mode 100755 (executable)
index 0000000..81ebde5
--- /dev/null
@@ -0,0 +1,99 @@
+-- File:       WOKUnix.cdl
+-- Created:    Fri Jan 31 18:34:49 1997
+-- Author:     Jean GAUTIER
+--             <jga@cobrax.paris1.matra-dtv.fr>
+---Copyright:   Matra Datavision 1997
+
+
+package WOKUnix 
+
+       ---Purpose: 
+
+uses
+    EDL,
+    OSD,
+    TCollection,
+    TColStd,
+    SortTools,
+    MMgt,
+    WOKTools
+is
+
+    imported TimeStat;
+    imported Timeval;
+    imported FDSet;
+    imported SigHandler;
+    private imported Dir;
+    private imported DirEnt;
+    private imported StatBuf;
+
+    enumeration Signals         is SIGPIPE, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSEGV,  SIGCHILD;
+    enumeration BufferIs        is STDOUT, STDERR;
+    enumeration PopenOutputMode is POPEN_MIX_OUT_ERR, POPEN_OUT_ERR;
+    enumeration PopenBufferMode is POPEN_BUFFERED, POPEN_IMMEDIATE, POPEN_ECHOIFBLOCKED;
+    enumeration ShellMode       is SynchronousMode, AsynchronousMode, DumpScriptMode;
+
+
+    enumeration Extension       is CFile, HFile, CDLFile, ODLFile, IDLFile, CXXFile,
+                                  HXXFile, IXXFile, JXXFile, LXXFile,  GXXFile, INCFile,
+                                  PXXFile, F77File, CSHFile, 
+                                  DBFile, FDDBFile,  DDLFile, HO2File,  
+                                  LibSchemaFile, AppSchemaFile,
+                                  LexFile, YaccFile, PSWFile, LWSFile, TemplateFile,
+                                  ObjectFile, MFile, CompressedFile,  ArchiveFile, DSOFile, DATFile,  
+                                  LispFile,  IconFile, TextFile, TarFile, 
+                                  --- WNT extensions
+                                  LIBFile, DEFile, RCFile, RESFile, IMPFile, EXPFile,
+                                  UnknownFile, NoExtFile;
+    enumeration RESyntax        is RESyntaxAWK, RESyntaxEGREP, RESyntaxGREP, RESyntaxEMACS;
+
+    exception BufferOverflow inherits Failure from Standard;
+    exception ProcessTimeOut inherits Failure from Standard;
+
+    class Signal;
+
+    class AdmFile;
+    class Path;
+    class PathIterator;
+    class FDescr;
+    class RegExp;
+     
+    private deferred class Buffer;
+       private class FileBuffer;
+       private class NoBuffer;
+       private class CantBlockBuffer;
+
+    private deferred class ProcessOutput;
+       private class MixedOutput;
+       private class OutErrOutput;
+       private class DumbOutput;
+
+    private class Process;
+    class ProcessManager;
+    class ShellManager;
+
+    private deferred class ShellStatus;
+       private class ASyncStatus;
+       private class SyncStatus;
+       private class DumpScript;
+    
+    class Shell;
+    class RemoteShell;
+
+    
+    private class SequenceOfProcess 
+       instantiates  Sequence from TCollection ( Process from  WOKUnix);
+
+    private class StackOfDir
+       instantiates     Stack from TCollection ( Dir from WOKUnix );
+
+    SystemLastError returns Integer from Standard;
+
+    SystemMessage(i : Integer from Standard) 
+       returns CString from Standard;
+       
+    LastSystemMessage
+       returns CString from Standard;
+      
+end WOKUnix;
diff --git a/src/WOKUnix/WOKUnix.cxx b/src/WOKUnix/WOKUnix.cxx
new file mode 100755 (executable)
index 0000000..43cd18e
--- /dev/null
@@ -0,0 +1,26 @@
+
+
+#include <WOKUnix.ixx>
+
+#include <string.h>
+#include <errno.h>
+
+
+Standard_Integer WOKUnix::SystemLastError()
+{
+  return errno;
+}
+
+
+Standard_CString WOKUnix::SystemMessage(const Standard_Integer errCode)
+{
+  return strerror(errCode);
+}
+
+
+
+Standard_CString WOKUnix::LastSystemMessage()
+{
+  return strerror(SystemLastError());
+}
+
diff --git a/src/WOKUnix/WOKUnix_ASyncStatus.cdl b/src/WOKUnix/WOKUnix_ASyncStatus.cdl
new file mode 100755 (executable)
index 0000000..807281d
--- /dev/null
@@ -0,0 +1,25 @@
+-- File:       WOKUnix_ASyncStatus.cdl
+-- Created:    Thu Jun  8 20:05:09 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class ASyncStatus from WOKUnix 
+inherits ShellStatus from WOKUnix
+
+       ---Purpose: 
+
+uses
+    Shell  from WOKUnix,
+    AsciiString from TCollection
+is
+    Create returns mutable ASyncStatus from WOKUnix;
+    Create(apath    : AsciiString      from TCollection)
+                        returns mutable ASyncStatus from WOKUnix;
+       
+    EndCmd(me:mutable; ashell : Shell from WOKUnix) is redefined;
+    Sync(me:mutable;   ashell : Shell from WOKUnix) is redefined;
+    Reset(me:mutable;  ashell : Shell from WOKUnix) is redefined;
+    
+end ASyncStatus;
diff --git a/src/WOKUnix/WOKUnix_ASyncStatus.cxx b/src/WOKUnix/WOKUnix_ASyncStatus.cxx
new file mode 100755 (executable)
index 0000000..97e45d3
--- /dev/null
@@ -0,0 +1,86 @@
+
+#include <WOKTools_Messages.hxx>
+#include <TCollection_HAsciiString.hxx>
+#include <TCollection_AsciiString.hxx>
+
+#include <WOKUnix_ASyncStatus.ixx>
+
+//=======================================================================
+//function : WOKUnix_ASyncStatus
+//purpose  : 
+//=======================================================================
+ WOKUnix_ASyncStatus::WOKUnix_ASyncStatus()
+{
+  
+}
+
+//=======================================================================
+//function : WOKUnix_ASyncStatus
+//purpose  : 
+//=======================================================================
+ WOKUnix_ASyncStatus::WOKUnix_ASyncStatus(const TCollection_AsciiString & apath)
+                     :WOKUnix_ShellStatus(apath)
+{
+  
+}
+
+//=======================================================================
+//function : EndCmd
+//purpose  : 
+//=======================================================================
+void WOKUnix_ASyncStatus::EndCmd(const Handle(WOKUnix_Shell)& ashell)
+{
+   static Handle(TCollection_HAsciiString) abuf = new TCollection_HAsciiString("\n@ wok_csh_status += $status\n");
+
+   ashell->WOKUnix_Process::Send(abuf);
+   
+#ifdef WOK_VERBOSE
+   VerboseMsg("WOK_PROCESS") << "WOKUnix_ASyncStatus::EndCmd" << "Accumulating Status" << endm;
+#endif
+   return;
+}
+
+//=======================================================================
+//function : Sync
+//purpose  : 
+//=======================================================================
+void WOKUnix_ASyncStatus::Sync(const Handle(WOKUnix_Shell)& ashell)
+{
+#ifdef USE_SYNCHRO
+  Handle(TCollection_HAsciiString) abuf = new TCollection_HAsciiString(TCollection_AsciiString("\n/tmp/synchro "));
+  abuf->AssignCat(Name());
+  abuf->AssignCat(" $wok_csh_status\n");
+#else
+  Handle(TCollection_HAsciiString) abuf = new TCollection_HAsciiString(TCollection_AsciiString("\necho $wok_csh_status > "));
+
+  abuf->AssignCat(Name());
+  abuf->AssignCat("\n");
+#endif
+
+  ashell->WOKUnix_Process::Send(abuf);
+  
+  mystatus = ashell->SyncAndStatus();
+  
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_ASyncStatus::Sync" << "GotStatus : " << mystatus << endm;
+#endif
+
+  Reset(ashell);
+
+  return;
+}
+
+//=======================================================================
+//function : Reset
+//purpose  : 
+//=======================================================================
+void WOKUnix_ASyncStatus::Reset(const Handle(WOKUnix_Shell)& ashell)
+{
+   static Handle(TCollection_HAsciiString) abuf = new TCollection_HAsciiString("\nset wok_csh_status = 0\n");
+   ashell->WOKUnix_Process::Send(abuf);
+#ifdef WOK_VERBOSE
+   VerboseMsg("WOK_PROCESS") << "WOKUnix_ASyncStatus::Reset" << "Reset Shell" << endm;
+#endif
+   return;
+}
+
diff --git a/src/WOKUnix/WOKUnix_AdmFile.cdl b/src/WOKUnix/WOKUnix_AdmFile.cdl
new file mode 100755 (executable)
index 0000000..6845474
--- /dev/null
@@ -0,0 +1,40 @@
+-- File:       WOKUnix_AdmFile.cdl
+-- Created:    Wed Jun 21 17:53:44 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+class AdmFile from WOKUnix
+
+---Purpose: Reads a file in WOK format :
+--          
+--          - lines beginning with # are ignored
+--          
+--          - lines ending with \ are continued
+--          
+--          - empty lines are ignored
+--          
+inherits FDescr from WOKUnix
+uses
+    HAsciiString from TCollection,
+    HSequenceOfHAsciiString from TColStd,
+    Path from WOKUnix
+raises
+    ProgramError
+is
+    Create 
+    ---Purpose: empty contructor
+       returns AdmFile from WOKUnix;
+    
+    Create(apath : HAsciiString from TCollection) 
+    ---Purpose: constructor initialising mypath
+       returns AdmFile from WOKUnix;
+
+    Create(apath : Path from WOKUnix) 
+    ---Purpose: constructor initialising mypath
+       returns AdmFile from WOKUnix;
+
+    Read(me : out) 
+    ---Purpose: Reads the file
+       returns HSequenceOfHAsciiString from TColStd raises  ProgramError;
+end;
diff --git a/src/WOKUnix/WOKUnix_AdmFile.cxx b/src/WOKUnix/WOKUnix_AdmFile.cxx
new file mode 100755 (executable)
index 0000000..b9dbb45
--- /dev/null
@@ -0,0 +1,103 @@
+
+#include <fstream.h>
+
+#include <WOKUnix_AdmFile.ixx>
+
+#include <WOKTools_Messages.hxx>
+
+#include <TColStd_HSequenceOfHAsciiString.hxx>
+
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_HAsciiString.hxx>
+
+#include <OSD_Protection.hxx>
+
+#define MAX_READBUFFER 1024
+
+//=======================================================================
+//function : WOKUnix_AdmFile
+//purpose  : 
+//=======================================================================
+WOKUnix_AdmFile::WOKUnix_AdmFile()
+{
+}
+
+//=======================================================================
+//function : WOKUnix_AdmFile
+//purpose  : 
+//=======================================================================
+WOKUnix_AdmFile::WOKUnix_AdmFile(const Handle(WOKUnix_Path)& apath) 
+{
+  SetPath(OSD_Path(apath->Name()->String()));
+}
+
+//=======================================================================
+//function : WOKUnix_AdmFile
+//purpose  : 
+//=======================================================================
+WOKUnix_AdmFile::WOKUnix_AdmFile(const Handle(TCollection_HAsciiString)& apath) 
+{
+  SetPath(OSD_Path(apath->String()));
+}
+
+//=======================================================================
+//function : Read
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_AdmFile::Read()  
+{
+  Handle(TColStd_HSequenceOfHAsciiString) aresult = new TColStd_HSequenceOfHAsciiString;
+  Standard_Boolean tobecontinued;
+  Standard_Boolean iscontinued;
+  char buffer[MAX_READBUFFER];
+
+  if(Exists() == Standard_False) 
+    {
+      ErrorMsg << "WOKUnix_AdmFile::Read" <<  "File : " << Name() << "does not exists" << endm;
+      Standard_ProgramError::Raise("WOKUnix_AdmFile::Read : File dos not exists");
+    }
+  
+  if(KindOfFile() != OSD_FILE)  
+    {
+      ErrorMsg << "WOKUnix_AdmFile::Read" <<  "File : " << Name() << " is not a plain file" << endm;
+      Standard_ProgramError::Raise("WOKUnix_AdmFile::Read");
+    }
+
+  ifstream astream(Name()->ToCString(), ios::in);
+
+  tobecontinued = Standard_False;
+
+  *buffer = '\0';
+  while(astream.getline(buffer, MAX_READBUFFER))
+    {
+      TCollection_AsciiString linebuf(buffer);
+      linebuf.LeftAdjust();
+
+      if(!linebuf.IsEmpty() && linebuf.Value(1) != '#' )
+       {
+         if(linebuf.Value(linebuf.Length()) == '\\') 
+           {
+             linebuf.Trunc(linebuf.Length() - 1);
+             iscontinued = Standard_True;
+           }
+         else 
+           {
+             iscontinued = Standard_False;
+           }
+
+         if(tobecontinued) {
+           aresult->Value(aresult->Length())->AssignCat(linebuf.ToCString());
+         }
+         else {
+           aresult->Append(new TCollection_HAsciiString(linebuf.ToCString()));
+         }
+
+         tobecontinued = iscontinued;
+       }
+      else tobecontinued = Standard_False;
+      *buffer = '\0';
+    }
+  astream.close();
+  return aresult;
+}
+
diff --git a/src/WOKUnix/WOKUnix_Buffer.cdl b/src/WOKUnix/WOKUnix_Buffer.cdl
new file mode 100755 (executable)
index 0000000..f7dbf65
--- /dev/null
@@ -0,0 +1,43 @@
+-- File:       WOKUnix_Buffer.cdl
+-- Created:    Thu May  4 16:33:47 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+private deferred class Buffer from WOKUnix
+inherits TShared from MMgt
+uses 
+    BufferIs from WOKUnix,
+    FDescr   from WOKUnix,
+    FDSet    from WOKUnix,
+    Timeval  from WOKUnix,
+    HSequenceOfHAsciiString from TColStd
+    
+raises
+    BufferOverflow from WOKUnix,
+    ProcessTimeOut from WOKUnix
+is
+    Initialize(afd : FDescr   from WOKUnix; astd : BufferIs from WOKUnix);
+
+    Clear(me : mutable);
+    
+    GetFDescr(me) returns FDescr from WOKUnix;
+    SetFDescr(me:mutable; afd : FDescr from WOKUnix);
+
+    BufferIs(me) returns BufferIs from WOKUnix;  
+    AssociatedChannel(me) returns FDescr from WOKUnix;
+    
+    Select(me; afd : out Integer; atimeout : in out Timeval from WOKUnix; aset : in out FDSet from WOKUnix) is deferred;
+    Acquit(me:mutable;  astatus : Integer from Standard; aset : FDSet from WOKUnix) raises ProcessTimeOut from WOKUnix is deferred;
+    
+    Echo(me : mutable)   returns HSequenceOfHAsciiString from TColStd is virtual;
+    Errors(me : mutable) returns HSequenceOfHAsciiString from TColStd is virtual;
+    Write(me : mutable ; afd : in out FDescr from WOKUnix) ;
+    
+    Close(me:mutable) is virtual;
+    
+fields
+    myfd  : FDescr from WOKUnix;
+    mystd : BufferIs from WOKUnix;
+end;
diff --git a/src/WOKUnix/WOKUnix_Buffer.cxx b/src/WOKUnix/WOKUnix_Buffer.cxx
new file mode 100755 (executable)
index 0000000..8750cc6
--- /dev/null
@@ -0,0 +1,181 @@
+
+#include <WOKUnix_Buffer.ixx>
+
+#include <WOKTools_Messages.hxx>
+
+#include <TCollection_HAsciiString.hxx>
+
+//=======================================================================
+//function : WOKUnix_Buffer
+//purpose  : 
+//=======================================================================
+WOKUnix_Buffer::WOKUnix_Buffer(const WOKUnix_FDescr& afd, const WOKUnix_BufferIs astd) : myfd(afd), mystd(astd)
+{
+}
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+void WOKUnix_Buffer::Clear()
+{
+  Standard_Integer nb = myfd.GetNbToRead();
+  while(nb > 0)
+    {
+      TCollection_AsciiString buffer;
+      myfd.Read(buffer, nb);
+      nb = myfd.GetNbToRead();
+    }
+  return;
+}
+
+//=======================================================================
+//function : GetFDescr
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr WOKUnix_Buffer::GetFDescr() const 
+{
+  return myfd;
+}
+
+//=======================================================================
+//function : SetFDescr
+//purpose  : 
+//=======================================================================
+void WOKUnix_Buffer::SetFDescr(const WOKUnix_FDescr& afd)
+{
+  myfd = afd;
+}
+
+//=======================================================================
+//function : BufferIs
+//purpose  : 
+//=======================================================================
+WOKUnix_BufferIs WOKUnix_Buffer::BufferIs() const 
+{
+  return mystd;
+}
+
+//=======================================================================
+//function : AssociatedChannel
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr WOKUnix_Buffer::AssociatedChannel() const
+{
+  switch(mystd)
+    {
+    case WOKUnix_STDOUT: 
+      return WOKUnix_FDescr::Stdout();
+    case WOKUnix_STDERR:
+      return WOKUnix_FDescr::Stderr();
+    default:
+      return WOKUnix_FDescr(-1);
+    }
+}
+
+
+//=======================================================================
+//function : Echo
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_Buffer::Echo()  
+{
+  Handle(TColStd_HSequenceOfHAsciiString) aseq = new TColStd_HSequenceOfHAsciiString;
+  Standard_Integer nbtoread = myfd.GetNbToRead();
+  Standard_Integer i=1;
+
+  if(!nbtoread) return aseq;
+
+  TCollection_AsciiString buffer;
+  TCollection_AsciiString astr;
+
+  myfd.Read(buffer, nbtoread);
+
+  Standard_CString aptr   = buffer.ToCString();
+  Standard_CString aptr2  = buffer.ToCString();
+  
+  i=0;
+  while(i<nbtoread)
+    {
+      if(*aptr2 == '\n')
+       {
+         *aptr2 = '\0';
+         aseq->Append(new TCollection_HAsciiString(aptr));
+         aptr = aptr2;
+         aptr++;
+       }
+      aptr2++;
+      i++;
+    }
+  if(aptr < aptr2)
+    {
+      aseq->Append(new TCollection_HAsciiString(aptr));
+    }
+
+  return aseq;
+}
+
+//=======================================================================
+//function : Errors
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_Buffer::Errors()  
+{
+  Handle(TColStd_HSequenceOfHAsciiString) aseq = new TColStd_HSequenceOfHAsciiString;
+  Standard_Integer nbtoread = myfd.GetNbToRead();
+  Standard_Integer i=1;
+  TCollection_AsciiString buffer;
+  TCollection_AsciiString astr;
+
+  myfd.Read(buffer, nbtoread);
+
+  Standard_CString aptr   = buffer.ToCString();
+  Standard_CString aptr2  = buffer.ToCString();
+  
+  i=0;
+  while(i<nbtoread)
+    {
+      if(*aptr2 == '\n')
+       {
+         *aptr2 = '\0';
+         aseq->Append(new TCollection_HAsciiString(aptr));
+         aptr = aptr2;
+         aptr++;
+       }
+      aptr2++;
+      i++;
+    }
+  if(aptr < aptr2)
+    {
+      aseq->Append(new TCollection_HAsciiString(aptr));
+    }
+
+  return aseq;
+}
+
+//=======================================================================
+//function : Write
+//purpose  : 
+//=======================================================================
+void WOKUnix_Buffer::Write( WOKUnix_FDescr& afd)  
+{
+  Standard_Integer nb = myfd.GetNbToRead();
+
+  if(nb > 0 )
+    {
+      TCollection_AsciiString buffer;
+
+      myfd.Read(buffer, nb);
+      afd.Reset();
+      afd.Write(buffer, nb);
+    }
+}
+
+//=======================================================================
+//function : Close
+//purpose  : 
+//=======================================================================
+void WOKUnix_Buffer::Close()
+{
+  if(myfd.FileNo() >= 0) myfd.Close();
+}
diff --git a/src/WOKUnix/WOKUnix_CMPLRS.edl b/src/WOKUnix/WOKUnix_CMPLRS.edl
new file mode 100755 (executable)
index 0000000..35a358d
--- /dev/null
@@ -0,0 +1,14 @@
+-- File:       WOKUnix_CMPLRS.edl
+-- Author:     Prestataire Pascal BABIN
+-- History:    Wed Jan 29 14:13:00 1997        Prestataire Pascal BABIN        Creation
+-- Copyright:   Matra Datavision 1997
+
+@ifnotdefined ( %WOKUnix_CMPLRS_EDL) then
+@set %WOKUnix_CMPLRS_EDL = "";
+
+@if ( %Station == "hp" ) then
+  @string %CMPLRS_C_Options = %CMPLRS_C_Options " -Ae";
+  @string %CMPLRS_CXX_Options = %CMPLRS_CXX_Options " -w +a1";
+@endif;
+
+@endif;
diff --git a/src/WOKUnix/WOKUnix_CantBlockBuffer.cdl b/src/WOKUnix/WOKUnix_CantBlockBuffer.cdl
new file mode 100755 (executable)
index 0000000..b63d175
--- /dev/null
@@ -0,0 +1,28 @@
+-- File:       WOKUnix_CantBlockBuffer.cdl
+-- Created:    Tue May  9 13:56:16 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class CantBlockBuffer from WOKUnix
+inherits Buffer  from WOKUnix
+uses 
+    BufferIs from WOKUnix,
+    FDescr   from WOKUnix,
+    FDSet    from WOKUnix,
+    Timeval  from WOKUnix
+raises
+    BufferOverflow from WOKUnix,
+    ProcessTimeOut from WOKUnix    
+is
+    Create(afd : FDescr   from WOKUnix; astd : BufferIs from WOKUnix) returns mutable CantBlockBuffer from WOKUnix;
+    
+    Select(me; afd : out Integer; atimeout : in out Timeval from WOKUnix; aset : in out FDSet from WOKUnix) is redefined;
+    Acquit(me:mutable; astatus : Integer from Standard; aset : FDSet from WOKUnix) raises ProcessTimeOut from WOKUnix is redefined;
+
+    Close(me:mutable) is redefined;
+
+fields
+    mybuffer : FDescr from WOKUnix;
+end;
diff --git a/src/WOKUnix/WOKUnix_CantBlockBuffer.cxx b/src/WOKUnix/WOKUnix_CantBlockBuffer.cxx
new file mode 100755 (executable)
index 0000000..ff51117
--- /dev/null
@@ -0,0 +1,46 @@
+
+
+#include <WOKUnix_CantBlockBuffer.ixx>
+
+#include <WOKUnix_MaxPipeSize.hxx>
+
+//=======================================================================
+//function : WOKUnix_CantBlockBuffer
+//purpose  : Constructs a CantBlockBuffer
+//=======================================================================
+WOKUnix_CantBlockBuffer::WOKUnix_CantBlockBuffer(const WOKUnix_FDescr& afd, const WOKUnix_BufferIs astd) : WOKUnix_Buffer(afd, astd)
+{
+}
+
+//=======================================================================
+//function : Select
+//purpose  : Performs settings for the select operation 
+//=======================================================================
+void WOKUnix_CantBlockBuffer::Select(Standard_Integer& afd, WOKUnix_Timeval& atimeout, WOKUnix_FDSet& aset) const 
+{
+  afd = ( (afd) > (GetFDescr().FileNo()) ) ? afd : GetFDescr().FileNo();
+  atimeout.tv_sec = 0;
+  atimeout.tv_usec = 500;
+  return;
+}
+
+//=======================================================================
+//function : Acquit
+//purpose  : Performs Acquitement of the select operation
+//=======================================================================
+void WOKUnix_CantBlockBuffer::Acquit(const Standard_Integer astatus, const WOKUnix_FDSet& aset)  
+{
+  WOKUnix_FDescr  afd = AssociatedChannel();
+  Standard_Integer nbtoread = GetFDescr().GetNbToRead();
+  if(nbtoread >= MAX_PIPE_SIZE)
+    {
+      cerr << "Error : CantBlockBuffer::Acquit : Could be blocked : Echo of " << AssociatedChannel().FileNo() << endl;
+      Write(afd);
+    }
+}
+
+void WOKUnix_CantBlockBuffer::Close()
+{
+  if(mybuffer.FileNo() >= 0) mybuffer.Close();
+  WOKUnix_Buffer::Close();
+}
diff --git a/src/WOKUnix/WOKUnix_Dir.hxx b/src/WOKUnix/WOKUnix_Dir.hxx
new file mode 100755 (executable)
index 0000000..2225f6e
--- /dev/null
@@ -0,0 +1,21 @@
+// File:       WOKUnix_Dir.hxx
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_Dir_HeaderFile
+#define WOKUnix_Dir_HeaderFile
+
+#ifndef WNT 
+
+#include <dirent.h>
+
+typedef DIR* WOKUnix_Dir;
+
+#else
+
+#error "Type Dir does not exist on WNT"
+
+#endif
+
+#endif
diff --git a/src/WOKUnix/WOKUnix_DirEnt.hxx b/src/WOKUnix/WOKUnix_DirEnt.hxx
new file mode 100755 (executable)
index 0000000..6ed5002
--- /dev/null
@@ -0,0 +1,21 @@
+// File:       WOKUnix_Dir.hxx
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_DirEnt_HeaderFile
+#define WOKUnix_DirEnt_HeaderFile
+
+#ifndef WNT 
+
+#include <dirent.h>
+
+typedef struct dirent* WOKUnix_DirEnt;
+
+#else
+
+#error "Type DirEnt does not exist on WNT"
+
+#endif
+
+#endif
diff --git a/src/WOKUnix/WOKUnix_DumbOutput.cdl b/src/WOKUnix/WOKUnix_DumbOutput.cdl
new file mode 100755 (executable)
index 0000000..6743d6c
--- /dev/null
@@ -0,0 +1,36 @@
+-- File:       WOKUnix_DumbOutput.cdl
+-- Created:    Tue May  9 14:02:54 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class DumbOutput from WOKUnix 
+inherits ProcessOutput from WOKUnix
+       ---Purpose: 
+
+uses
+    Timeval from WOKUnix,
+    FDSet   from WOKUnix,
+    FDescr  from WOKUnix,
+    Buffer  from WOKUnix,
+    HSequenceOfHAsciiString from TColStd
+
+is
+    Create returns mutable DumbOutput from WOKUnix;
+
+    Clear(me) is redefined;
+    Echo(me)   returns HSequenceOfHAsciiString from TColStd is redefined;
+    Errors(me) returns HSequenceOfHAsciiString from TColStd is redefined;
+
+    Select(me; afdmax : out Integer from Standard; atimeout : in out Timeval from WOKUnix; aset : out FDSet from WOKUnix) is redefined;
+    
+    Acquit(me; selectstatus : Integer; aset : FDSet from WOKUnix) is redefined;
+
+    Close(me:mutable) is redefined;
+
+fields
+    myout : Buffer from WOKUnix;
+    myerr : Buffer from WOKUnix;
+
+end DumbOutput;
diff --git a/src/WOKUnix/WOKUnix_DumbOutput.cxx b/src/WOKUnix/WOKUnix_DumbOutput.cxx
new file mode 100755 (executable)
index 0000000..76167b7
--- /dev/null
@@ -0,0 +1,62 @@
+
+#include <WOKUnix_DumbOutput.ixx>
+
+//=======================================================================
+//function : WOKUnix_DumbOutput
+//purpose  : 
+//=======================================================================
+ WOKUnix_DumbOutput::WOKUnix_DumbOutput()
+{
+}
+
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+void WOKUnix_DumbOutput::Clear() const 
+{
+}
+
+//=======================================================================
+//function : Echo
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_DumbOutput::Echo() const 
+{
+  return new TColStd_HSequenceOfHAsciiString;
+}
+
+//=======================================================================
+//function : Errors
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString)  WOKUnix_DumbOutput::Errors() const 
+{
+  return new TColStd_HSequenceOfHAsciiString;
+}
+
+//=======================================================================
+//function : Select
+//purpose  : 
+//=======================================================================
+void WOKUnix_DumbOutput::Select(Standard_Integer& afdmax, WOKUnix_Timeval& atimeout,  WOKUnix_FDSet& aset) const 
+{
+}
+
+//=======================================================================
+//function : Acquit
+//purpose  : 
+//=======================================================================
+void WOKUnix_DumbOutput::Acquit(const Standard_Integer selectstatus, const WOKUnix_FDSet& aset) const 
+{
+}
+
+//=======================================================================
+//function : Close
+//purpose  : 
+//=======================================================================
+void WOKUnix_DumbOutput::Close()
+{
+}
+
diff --git a/src/WOKUnix/WOKUnix_DumpScript.cdl b/src/WOKUnix/WOKUnix_DumpScript.cdl
new file mode 100755 (executable)
index 0000000..dd8d9d7
--- /dev/null
@@ -0,0 +1,26 @@
+-- File:       WOKUnix_DumpScript.cdl
+-- Created:    Thu Jun  8 20:07:55 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class DumpScript from WOKUnix 
+inherits ShellStatus from WOKUnix
+       ---Purpose: 
+
+uses
+    AsciiString from TCollection,
+    Shell  from WOKUnix
+is
+    Create returns mutable DumpScript from WOKUnix;
+    Create(apath    : AsciiString      from TCollection)
+                        returns mutable  DumpScript from WOKUnix;
+    
+    EndCmd(me:mutable; ashell : Shell from WOKUnix) is redefined;
+    Sync(me:mutable;   ashell : Shell from WOKUnix) is redefined;
+    Reset(me:mutable;  ashell : Shell from WOKUnix) is redefined;
+    
+    Get(me:mutable) returns Integer is redefined;
+    
+end DumpScript;
diff --git a/src/WOKUnix/WOKUnix_DumpScript.cxx b/src/WOKUnix/WOKUnix_DumpScript.cxx
new file mode 100755 (executable)
index 0000000..59d477a
--- /dev/null
@@ -0,0 +1,53 @@
+#include <TCollection_AsciiString.hxx>
+#include <WOKUnix_DumpScript.ixx>
+
+//=======================================================================
+//function : WOKUnix_DumpScript
+//purpose  : 
+//=======================================================================
+ WOKUnix_DumpScript::WOKUnix_DumpScript()
+{
+}
+
+//=======================================================================
+//function : WOKUnix_DumpScript
+//purpose  : 
+//=======================================================================
+ WOKUnix_DumpScript::WOKUnix_DumpScript(const TCollection_AsciiString & apath)
+                     :WOKUnix_ShellStatus(apath)
+{
+}
+
+//=======================================================================
+//function : EndCmd
+//purpose  : 
+//=======================================================================
+void WOKUnix_DumpScript::EndCmd(const Handle(WOKUnix_Shell)& ashell)
+{
+}
+
+//=======================================================================
+//function : Sync
+//purpose  : 
+//=======================================================================
+void WOKUnix_DumpScript::Sync(const Handle(WOKUnix_Shell)& ashell)
+{
+}
+
+//=======================================================================
+//function : Reset
+//purpose  : 
+//=======================================================================
+void WOKUnix_DumpScript::Reset(const Handle(WOKUnix_Shell)& ashell)
+{
+}
+
+//=======================================================================
+//function : Get
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_DumpScript::Get()
+{
+  return 0;
+}
+
diff --git a/src/WOKUnix/WOKUnix_FDSet.hxx b/src/WOKUnix/WOKUnix_FDSet.hxx
new file mode 100755 (executable)
index 0000000..e7fedf9
--- /dev/null
@@ -0,0 +1,25 @@
+// File:       WOKUnix_FDSet.hxx
+// Created:    Tue May  9 15:25:38 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_FDSet_HeaderFile
+#define WOKUnix_FDSet_HeaderFile
+
+#ifndef HPUX
+#include <sys/select.h>
+#define WOKUnix_FDSet_CAST fd_set *
+#endif
+
+#ifdef HPUX
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#define WOKUnix_FDSet_CAST fd_set *
+#endif
+
+typedef struct fd_set WOKUnix_FDSet;
+
+#endif
+
diff --git a/src/WOKUnix/WOKUnix_FDescr.cdl b/src/WOKUnix/WOKUnix_FDescr.cdl
new file mode 100755 (executable)
index 0000000..8c9b757
--- /dev/null
@@ -0,0 +1,48 @@
+-- File:       WOKUnix_FDescr.cdl
+-- Created:    Thu May  4 16:55:43 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+class FDescr from WOKUnix
+inherits File from OSD
+uses
+    Path from OSD,
+    HAsciiString from TCollection,
+    AsciiString from TCollection
+    
+raises
+    OSDError from OSD
+is
+    Create returns FDescr from WOKUnix;
+    Create( afd : Integer from Standard ) returns FDescr from WOKUnix; 
+    Create( afd : Integer from Standard; apath : HAsciiString from TCollection) returns FDescr from WOKUnix;
+    Create( apath : HAsciiString from TCollection) returns FDescr from WOKUnix;
+
+    EmptyAndOpen(me: in out);
+
+    BuildTemporary(me: in out);
+    BuildTemporary(me: in out ; apath : AsciiString from TCollection);    
+    BuildNamedPipe(me: in out);
+    
+    GetNbToRead(me : in out) returns Integer from Standard;
+    SetUnBuffered(me : in out);
+    SetNonBlock(me : in out);
+    Flush(me : in out);
+    Dup(me : in out);
+    FileNo(me) returns Integer from Standard;
+    GetSize(me:in out) returns Integer from Standard;
+    Name(me) returns HAsciiString from TCollection;
+
+    ReadLine(me:out) returns HAsciiString from TCollection;
+
+    Pipe(myclass; anin : out FDescr from WOKUnix; anout : out FDescr from WOKUnix) 
+       raises OSDError from OSD;
+
+    Stdin(myclass)  returns FDescr from WOKUnix;
+    Stdout(myclass) returns FDescr from WOKUnix;
+    Stderr(myclass) returns FDescr from WOKUnix;
+    
+fields 
+    myFILE : Address from Standard;
+end;
diff --git a/src/WOKUnix/WOKUnix_FDescr.cxx b/src/WOKUnix/WOKUnix_FDescr.cxx
new file mode 100755 (executable)
index 0000000..5a71d94
--- /dev/null
@@ -0,0 +1,396 @@
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+#ifdef SOLARIS
+#include <sys/filio.h>
+#else 
+#include <sys/ioctl.h>
+#endif
+#include <fcntl.h>
+
+#include <WOKUnix_FDescr.ixx>
+
+#include <WOKTools_Messages.hxx>
+
+#include <OSD_Protection.hxx>
+#include <OSD_OSDError.hxx>
+#include <Standard_ProgramError.hxx>
+
+extern "C" { extern int  mknod (const char *, mode_t , dev_t ); }
+
+extern int errno;
+
+const OSD_WhoAmI Iam = OSD_WFile;
+
+//=======================================================================
+//function : WOKUnix_FDescr
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr::WOKUnix_FDescr()
+{
+  myFILE=NULL;
+}
+
+//=======================================================================
+//function : WOKUnix_FDescr
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr::WOKUnix_FDescr(const Standard_Integer afd) {myFileChannel = afd;myFILE = fdopen(afd, "r");}
+
+//=======================================================================
+//function : WOKUnix_FDescr
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr::WOKUnix_FDescr(const Standard_Integer afd, const Handle(TCollection_HAsciiString)& apath)
+{
+  myFileChannel = afd;
+  myFILE = fdopen(afd, "r");
+  SetPath(apath->String());
+}
+
+//=======================================================================
+//function : WOKUnix_FDescr
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr::WOKUnix_FDescr(const Handle(TCollection_HAsciiString)& apath)
+{
+  SetPath(apath->String());
+  myFILE = NULL;
+}
+
+//=======================================================================
+//function : EmptyAndOpen
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::EmptyAndOpen()
+{
+  fclose((FILE *)myFILE);
+  close(myFileChannel);
+  myFileChannel = open(Name()->ToCString(), 
+                      O_RDWR | O_CREAT | O_TRUNC, 
+                      S_IRUSR|S_IWUSR|S_IWUSR|S_IRGRP|S_IROTH);
+
+  myFILE = fdopen(myFileChannel, "r");
+}
+
+//=======================================================================
+//function : GetNbToRead
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_FDescr::GetNbToRead()  
+{
+  Standard_Integer nbtoread = 0;
+  if(ioctl(myFileChannel, FIONREAD, &nbtoread) < 0)
+    {
+      Perror();
+      return -1;
+    }
+  return nbtoread;
+}
+
+//=======================================================================
+//function : SetUnBuffered
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::SetUnBuffered()  
+{
+  if(fcntl(myFileChannel, F_SETFL, O_SYNC) < 0)
+    {
+      Perror();
+      return;
+    }
+  return;
+}
+
+//=======================================================================
+//function : BuildTemporary
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::BuildTemporary()  
+{
+
+ char *name = tmpnam((char*) 0) ;
+
+ TCollection_AsciiString aName ( name ) ;
+ OSD_Path aPath( aName ) ;
+
+ SetPath( aPath ) ;
+
+ Build(OSD_ReadWrite , OSD_Protection());
+ SetUnBuffered();
+
+}
+
+//=======================================================================
+//function : BuildTemporary
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::BuildTemporary(const TCollection_AsciiString & apath)  
+{
+  TCollection_AsciiString astr(apath);
+  
+  astr.AssignCat("/WOKXXXXXX");
+
+  char *name = mktemp(astr.ToCString()) ;
+
+  TCollection_AsciiString aName ( name ) ;
+  OSD_Path aPath( aName ) ;
+  
+  SetPath( aPath ) ;
+
+  Build(OSD_ReadWrite, OSD_Protection());
+  SetUnBuffered();
+
+}
+
+//=======================================================================
+//function : BuildNamedPipe
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::BuildNamedPipe()  
+{
+  TCollection_AsciiString apath;
+  WOKUnix_FDescr         writeend;
+
+  apath = tmpnam(NULL);
+  SetPath(OSD_Path(apath));
+
+  if(mknod(apath.ToCString(), 0700 |  S_IFIFO, 0)) 
+    { perror(apath.ToCString());}
+
+  myFileChannel = open(apath.ToCString(),  O_RDONLY | O_NDELAY | O_CREAT);
+  SetUnBuffered();
+
+  // write end of pipe is unbuffered also 
+  writeend.SetPath(OSD_Path(Name()->String()));
+  writeend.Open(OSD_WriteOnly, OSD_Protection());
+  writeend.SetUnBuffered();
+  
+}
+
+//=======================================================================
+//function : SetNonBlock
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::SetNonBlock()  
+{
+  if(fcntl(myFileChannel, F_SETFL, O_NONBLOCK) < 0)
+    {
+      Perror();
+      return;
+    }
+  return;
+}
+
+//=======================================================================
+//function : Flush
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::Flush()  
+{
+  if(fsync(myFileChannel) < 0)
+    {
+      Perror();
+    }
+  return;
+}
+
+//=======================================================================
+//function : Dup
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::Dup()  
+{
+  dup(myFileChannel);
+}
+
+//=======================================================================
+//function : FileNo
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_FDescr::FileNo() const
+{
+  return myFileChannel;
+}
+
+//=======================================================================
+//function : GetSize
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_FDescr::GetSize()
+{
+  struct stat buffer;
+  Handle(TCollection_HAsciiString) aname;
+  int status;
+  
+  aname = Name();
+
+  if (aname->Length()==0)
+    Standard_ProgramError::Raise("OSD_File::Size : empty file name");
+  
+  if(FileNo() == -1)
+    {
+      // si le fichier n;est pas ouvert pas le choix
+      status = stat( aname->ToCString() ,&buffer );
+    }
+  else
+    {
+       // si le fichier n;est pas ouvert pas le choix
+      status = fstat( FileNo() ,&buffer );
+    }     
+  if (status == -1) 
+    {
+      myError.SetValue (errno, Iam, "Size");
+      return (-1);
+    }
+  
+  return ( buffer.st_size );
+  
+}
+
+//=======================================================================
+//function : Name
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_FDescr::Name() const
+{
+  OSD_Path apath;
+  TCollection_AsciiString astring;
+
+  Path(apath);
+
+  apath.SystemName(astring);
+  
+  return new TCollection_HAsciiString(astring);
+}
+
+//=======================================================================
+//function : ReadLine
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_FDescr::ReadLine() 
+{
+  Handle(TCollection_HAsciiString) astr;
+
+  if(myFILE == NULL)
+    {
+      TCollection_AsciiString abuf;
+      Standard_Integer nbread = 0;
+
+      while(IsAtEnd() == Standard_False)
+       {
+         OSD_File::ReadLine(abuf, 1024, nbread);
+         if(astr.IsNull() && nbread < 1024)
+           {
+             astr = new TCollection_HAsciiString(abuf.ToCString());
+             return astr;
+           }
+         if(astr.IsNull() && nbread == 1024)
+           {
+             astr = new TCollection_HAsciiString(abuf.ToCString());
+           }
+         else if (!astr.IsNull() &&  nbread < 1024)
+           {
+             astr->AssignCat(abuf.ToCString());
+             return astr;
+           }
+         else // !astr.IsNull() &&  nbread == 1024
+           {
+             astr->AssignCat(abuf.ToCString());
+           }
+       }
+    }
+  else
+    {
+      TCollection_AsciiString abuf;
+      Standard_Integer nbread = 0;
+
+      while(GetNbToRead() != 0)
+       {
+         fgets(abuf.ToCString(), 1024, (FILE *) myFILE);
+         nbread = strlen(abuf.ToCString());
+         if(astr.IsNull() && nbread < 1024)
+           {
+             astr = new TCollection_HAsciiString(abuf.ToCString());
+             return astr;
+           }
+         if(astr.IsNull() && nbread == 1024)
+           {
+             astr = new TCollection_HAsciiString(abuf.ToCString());
+           }
+         else if (!astr.IsNull() &&  nbread < 1024)
+           {
+             astr->AssignCat(abuf.ToCString());
+             return astr;
+           }
+         else // !astr.IsNull() &&  nbread == 1024
+           {
+             astr->AssignCat(abuf.ToCString());
+           }
+       }
+    }
+  return astr;
+}
+
+
+//=======================================================================
+//function : Pipe
+//purpose  : 
+//=======================================================================
+void WOKUnix_FDescr::Pipe(WOKUnix_FDescr &anin, WOKUnix_FDescr &anout)
+{
+  Standard_Integer in[2];
+
+  if(pipe(in))  
+    {
+      OSD_OSDError::Raise("WOKUnix_FDescr::Pipe : pipe system call Failed");
+    }
+
+  anin = WOKUnix_FDescr(in[1]);
+  anout = WOKUnix_FDescr(in[0]);
+
+  return;
+}
+
+//=======================================================================
+//function : Stdin
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr WOKUnix_FDescr::Stdin()
+{
+  static WOKUnix_FDescr StdinFD(0, new TCollection_HAsciiString("/dev/null/stdin"));
+
+  return StdinFD;
+}
+
+//=======================================================================
+//function : Stdout
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr WOKUnix_FDescr::Stdout()
+{
+  static WOKUnix_FDescr StdoutFD(1, new TCollection_HAsciiString("/dev/null/stdout"));
+
+  return StdoutFD;
+}
+
+//=======================================================================
+//function : Stderr
+//purpose  : 
+//=======================================================================
+WOKUnix_FDescr WOKUnix_FDescr::Stderr()
+{
+  static WOKUnix_FDescr StderrFD(2, new TCollection_HAsciiString("/dev/null/stderr"));
+
+  return StderrFD;
+}
+
+
+
+
+
+
diff --git a/src/WOKUnix/WOKUnix_FileBuffer.cdl b/src/WOKUnix/WOKUnix_FileBuffer.cdl
new file mode 100755 (executable)
index 0000000..0e67d55
--- /dev/null
@@ -0,0 +1,34 @@
+-- File:       WOKUnix_FileBuffer.cdl
+-- Created:    Thu May  4 18:27:14 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+private class FileBuffer from WOKUnix
+inherits Buffer  from WOKUnix
+uses 
+    BufferIs from WOKUnix,
+    FDescr   from WOKUnix,
+    FDSet    from WOKUnix,
+    Timeval  from WOKUnix,
+    HSequenceOfHAsciiString from TColStd
+
+raises 
+    BufferOverflow from WOKUnix,
+    ProcessTimeOut from WOKUnix
+is
+    Create(afd : FDescr   from WOKUnix; astd : BufferIs from WOKUnix) returns mutable FileBuffer from WOKUnix;
+    
+    Select(me; afd : out Integer; atimeout : in out Timeval from WOKUnix; aset : in out FDSet from WOKUnix) is redefined;
+    Acquit(me:mutable; astatus : Integer from Standard; aset : FDSet from WOKUnix) raises ProcessTimeOut from WOKUnix is redefined;
+    
+    Echo(me : mutable)   returns HSequenceOfHAsciiString from TColStd is redefined;
+    Errors(me : mutable) returns HSequenceOfHAsciiString from TColStd is redefined;
+
+    Dump(me:mutable) raises BufferOverflow from WOKUnix is private;
+
+    Close(me:mutable) is redefined;
+
+fields
+    mybuffer : FDescr from WOKUnix;
+end;
diff --git a/src/WOKUnix/WOKUnix_FileBuffer.cxx b/src/WOKUnix/WOKUnix_FileBuffer.cxx
new file mode 100755 (executable)
index 0000000..e32b458
--- /dev/null
@@ -0,0 +1,150 @@
+
+
+#include <OSD_Environment.hxx>
+#include <OSD_Path.hxx>
+
+
+#include <WOKTools_Messages.hxx>
+
+#include <WOKUnix_FileBuffer.ixx>
+
+#include <WOKUnix_MaxPipeSize.hxx>
+
+#include <TCollection_HAsciiString.hxx>
+
+// default buffer max size 1Mo : overided by WOK_MAXBUFFEREDSIZE var
+#define MAX_BUFFEREDSIZE    1048576  
+
+//=======================================================================
+//function : WOKUnix_FileBuffer
+//purpose  : contructs a file buffer with a FDescr
+//=======================================================================
+WOKUnix_FileBuffer::WOKUnix_FileBuffer(const WOKUnix_FDescr& afd, const WOKUnix_BufferIs astd) : WOKUnix_Buffer(afd, astd)
+{
+}
+
+//=======================================================================
+//function : Select
+//purpose  : performs select settings
+//=======================================================================
+void WOKUnix_FileBuffer::Select(Standard_Integer& afd, WOKUnix_Timeval& atimeout, WOKUnix_FDSet& aset) const 
+{
+  afd = ( (afd) > (GetFDescr().FileNo()) ) ? afd : GetFDescr().FileNo();
+  FD_SET(GetFDescr().FileNo(), &aset);
+  atimeout.tv_sec = 0;
+  atimeout.tv_usec = 500000;
+  return;
+}
+
+
+//=======================================================================
+//function : Errors
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_FileBuffer::Errors()
+{
+ return Echo();
+}
+
+//=======================================================================
+//function : Echo
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString)  WOKUnix_FileBuffer::Echo()
+{
+  if(mybuffer.FileNo() != -1)
+    {
+      Handle(TColStd_HSequenceOfHAsciiString) aseq = new TColStd_HSequenceOfHAsciiString;
+      Standard_Integer nbread;
+
+      mybuffer.Reset();
+
+      mybuffer.Seek( 0, OSD_FromBeginning);
+
+      TCollection_AsciiString abuf;
+
+      while(mybuffer.IsAtEnd() == Standard_False)
+       {
+         aseq->Append(mybuffer.ReadLine());
+       }
+      aseq->Append(WOKUnix_Buffer::Echo());
+
+      mybuffer.Close();
+      mybuffer.Remove();
+
+      return aseq;
+    }
+  else return WOKUnix_Buffer::Echo();
+}
+
+//=======================================================================
+//function : Acquit
+//purpose  : Acquits select
+//=======================================================================
+void WOKUnix_FileBuffer::Acquit(const Standard_Integer astatus, const WOKUnix_FDSet& aset)  
+{
+  Standard_Integer nbtoread = GetFDescr().GetNbToRead();
+  
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_FileBuffer::Acquit"
+                            << "There is " << nbtoread << " bytes to read on process output" << endm;
+#endif
+
+  if(nbtoread >= MAX_PIPE_SIZE)
+    {    
+      Dump();
+    }
+}
+
+
+//=======================================================================
+//function : Dump
+//purpose  : Dumps contents of buffer in a FDescr
+//=======================================================================
+void WOKUnix_FileBuffer::Dump()  
+{
+  OSD_Environment  maxbsize("WOK_MAXBUFFEREDSIZE");
+  TCollection_AsciiString astring;
+  Standard_Integer maxsize;
+  
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_FileBuffer::Dump"
+    << "Dumping" << endm;
+#endif
+
+  if(mybuffer.FileNo() == -1)
+    {
+      mybuffer.BuildTemporary();
+    }
+  else
+    {
+      astring = maxbsize.Value();
+      if(astring.IsIntegerValue() == Standard_False)  maxsize = MAX_BUFFEREDSIZE;
+      else                                            maxsize = astring.IntegerValue();
+      
+      if(mybuffer.Size() >= maxsize)
+       {
+         WOKUnix_BufferOverflow::Raise("WOKUnix_FileBuffer::Dump : Buffer Overflow");
+       }
+    }
+  WOKUnix_Buffer::Write(mybuffer);
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_FileBuffer::Dump"
+    << "Dumped" << endm;
+#endif
+
+}
+
+//=======================================================================
+//function : Close
+//purpose  : Closes 
+//=======================================================================
+void WOKUnix_FileBuffer::Close()
+{
+  OSD_Path apath;
+
+  mybuffer.Path(apath);
+  
+  if( apath.Name().IsEmpty() != Standard_True && mybuffer.FileNo() >= 0) mybuffer.Close();
+  WOKUnix_Buffer::Close();
+}
diff --git a/src/WOKUnix/WOKUnix_MaxPipeSize.hxx b/src/WOKUnix/WOKUnix_MaxPipeSize.hxx
new file mode 100755 (executable)
index 0000000..c07d95b
--- /dev/null
@@ -0,0 +1,27 @@
+// File:       WOKUnix_MaxPipeSize.hxx
+// Created:    Fri May 12 10:09:01 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_MaxPipeSize_HeaderFile
+#define WOKUnix_MaxPipeSize_HeaderFile
+
+
+#ifdef HPUX
+#include <sys/inode.h>
+//#define MAX_PIPE_SIZE  PIPSIZ
+#define MAX_PIPE_SIZE 8190
+#elif  IRIX
+#include <limits.h>
+#define MAX_PIPE_SIZE PIPE_MAX
+#elif  DECOSF1
+#include <sys/param.h>
+#define MAX_PIPE_SIZE PIPE_BUF
+#elif SOLARIS
+#include <sys/param.h>
+#define MAX_PIPE_SIZE PIPE_MAX
+#endif
+
+
+#endif
diff --git a/src/WOKUnix/WOKUnix_MixedOutput.cdl b/src/WOKUnix/WOKUnix_MixedOutput.cdl
new file mode 100755 (executable)
index 0000000..e560b75
--- /dev/null
@@ -0,0 +1,35 @@
+-- File:       WOKUnix_MixedOutput.cdl
+-- Created:    Thu May  4 16:30:11 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+private class MixedOutput from WOKUnix
+inherits ProcessOutput from WOKUnix
+uses
+    Timeval from WOKUnix,
+    FDSet from WOKUnix,
+    FDescr from WOKUnix,
+    Buffer from WOKUnix,
+    PopenBufferMode from WOKUnix,
+    HSequenceOfHAsciiString from TColStd
+is
+    Create returns mutable MixedOutput from WOKUnix;
+    Create(afd : FDescr from WOKUnix; amode : PopenBufferMode from WOKUnix)           returns mutable MixedOutput from WOKUnix; 
+    Create(anoutput : MixedOutput from WOKUnix; amode : PopenBufferMode from WOKUnix) returns mutable MixedOutput from WOKUnix;
+
+    Clear(me)  is redefined;
+    Echo(me)   returns HSequenceOfHAsciiString from TColStd is redefined;
+    Errors(me) returns HSequenceOfHAsciiString from TColStd is redefined;
+
+    Select(me; afdmax : out Integer from Standard; atimeout : in out Timeval from WOKUnix; aset : out FDSet from WOKUnix) is redefined;
+    
+    Acquit(me; selectstatus : Integer; aset : FDSet from WOKUnix) is redefined;
+
+    Close(me:mutable) is redefined;
+
+fields
+    myout : Buffer from WOKUnix;
+    
+end MixedOutput;
+
diff --git a/src/WOKUnix/WOKUnix_MixedOutput.cxx b/src/WOKUnix/WOKUnix_MixedOutput.cxx
new file mode 100755 (executable)
index 0000000..a386c53
--- /dev/null
@@ -0,0 +1,86 @@
+
+#include <WOKUnix_MixedOutput.ixx>
+
+
+#include <WOKUnix_FileBuffer.hxx>
+#include <WOKUnix_NoBuffer.hxx>
+#include <WOKUnix_CantBlockBuffer.hxx>
+
+//=======================================================================
+//function : WOKUnix_MixedOutput
+//purpose  : 
+//=======================================================================
+WOKUnix_MixedOutput::WOKUnix_MixedOutput()
+{
+}
+
+//=======================================================================
+//function : WOKUnix_MixedOutput
+//purpose  : 
+//=======================================================================
+WOKUnix_MixedOutput::WOKUnix_MixedOutput(const WOKUnix_FDescr& afd, const WOKUnix_PopenBufferMode amode)
+{
+  switch(amode)
+    {
+    case WOKUnix_POPEN_BUFFERED:
+      myout = new WOKUnix_FileBuffer(afd, WOKUnix_STDOUT);
+      break;
+    case WOKUnix_POPEN_IMMEDIATE:
+      myout = new WOKUnix_NoBuffer(afd, WOKUnix_STDOUT);
+      break;
+    case WOKUnix_POPEN_ECHOIFBLOCKED:
+      myout = new WOKUnix_CantBlockBuffer(afd, WOKUnix_STDOUT);
+      break;
+    }      
+}
+
+//=======================================================================
+//function : Echo
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_MixedOutput::Echo() const 
+{
+  return myout->Echo();
+}
+
+void WOKUnix_MixedOutput::Clear() const 
+{
+  myout->Clear();
+}
+
+//=======================================================================
+//function : Errors
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString)  WOKUnix_MixedOutput::Errors() const 
+{
+  return myout->Errors();
+}
+
+//=======================================================================
+//function : Select
+//purpose  : 
+//=======================================================================
+void WOKUnix_MixedOutput::Select(Standard_Integer& afdmax, WOKUnix_Timeval& atimeout,  WOKUnix_FDSet& aset) const 
+{
+  myout->Select(afdmax, atimeout, aset);
+}
+
+//=======================================================================
+//function : Acquit
+//purpose  : 
+//=======================================================================
+void WOKUnix_MixedOutput::Acquit(const Standard_Integer afd, const WOKUnix_FDSet& aset) const 
+{
+  myout->Acquit(afd, aset);
+}
+
+//=======================================================================
+//function : Close
+//purpose  : 
+//=======================================================================
+void WOKUnix_MixedOutput::Close()
+{
+  myout->Close();
+}
+
diff --git a/src/WOKUnix/WOKUnix_NoBuffer.cdl b/src/WOKUnix/WOKUnix_NoBuffer.cdl
new file mode 100755 (executable)
index 0000000..e2c3a96
--- /dev/null
@@ -0,0 +1,28 @@
+-- File:       WOKUnix_NoBuffer.cdl
+-- Created:    Thu May  4 18:30:08 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class NoBuffer from WOKUnix
+inherits Buffer  from WOKUnix
+uses 
+    BufferIs from WOKUnix,
+    FDescr   from WOKUnix,
+    FDSet    from WOKUnix,
+    Timeval  from WOKUnix
+raises 
+    BufferOverflow from WOKUnix,
+    ProcessTimeOut from WOKUnix
+is
+    Create(afd : FDescr   from WOKUnix; astd : BufferIs from WOKUnix) returns mutable NoBuffer from WOKUnix;
+    
+    Select(me; afd : out Integer; atimeout : in out Timeval from WOKUnix; aset : in out FDSet from WOKUnix) is redefined;
+    Acquit(me:mutable; astatus : Integer from Standard; aset : FDSet from WOKUnix) raises ProcessTimeOut from WOKUnix is redefined;
+
+    Close(me:mutable) is redefined;
+
+fields
+    mybuffer : FDescr from WOKUnix;
+end;
diff --git a/src/WOKUnix/WOKUnix_NoBuffer.cxx b/src/WOKUnix/WOKUnix_NoBuffer.cxx
new file mode 100755 (executable)
index 0000000..f931fb8
--- /dev/null
@@ -0,0 +1,44 @@
+#include <WOKUnix_NoBuffer.ixx>
+
+ WOKUnix_NoBuffer::WOKUnix_NoBuffer(const WOKUnix_FDescr& afd, const WOKUnix_BufferIs astd) : WOKUnix_Buffer(afd, astd)
+{
+}
+
+void WOKUnix_NoBuffer::Select(Standard_Integer& afd, WOKUnix_Timeval& atimeout, WOKUnix_FDSet& aset) const 
+{
+  afd = ( afd > GetFDescr().FileNo() ) ? afd : GetFDescr().FileNo();
+  if(atimeout.tv_sec < 0)
+    {
+      atimeout.tv_usec = 0;
+    }
+  else
+    {
+      atimeout.tv_sec = 0;
+      atimeout.tv_usec = 0;
+    }
+
+  FD_SET(GetFDescr().FileNo(), &aset);
+  GetFDescr().Flush();
+  return;
+}
+
+void WOKUnix_NoBuffer::Acquit(const Standard_Integer astatus, const WOKUnix_FDSet& aset)  
+{
+  WOKUnix_FDescr afd = AssociatedChannel();
+  if(astatus == 0)
+    {
+      WOKUnix_ProcessTimeOut::Raise("NoBuffer::Acquit : time out\n");
+      return;
+    }
+  else
+    {
+      Write(afd);
+    }
+  return;
+}
+
+
+void WOKUnix_NoBuffer::Close()
+{
+  
+}
diff --git a/src/WOKUnix/WOKUnix_OutErrOutput.cdl b/src/WOKUnix/WOKUnix_OutErrOutput.cdl
new file mode 100755 (executable)
index 0000000..6524f11
--- /dev/null
@@ -0,0 +1,41 @@
+-- File:       WOKUnix_OutErrOutput.cdl
+-- Created:    Tue May  9 13:57:51 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class OutErrOutput from WOKUnix 
+inherits ProcessOutput from WOKUnix
+
+       ---Purpose: 
+
+uses
+    Timeval         from WOKUnix,
+    FDSet           from WOKUnix,
+    FDescr          from WOKUnix,
+    Buffer          from WOKUnix,
+    PopenBufferMode from WOKUnix,
+    HSequenceOfHAsciiString from TColStd
+is
+    Create returns mutable OutErrOutput from WOKUnix;
+    Create(aoutfd : FDescr from WOKUnix; aerrfd : FDescr from WOKUnix;  amode : PopenBufferMode from WOKUnix)  
+       returns mutable OutErrOutput from WOKUnix;
+    Create(anoutput : OutErrOutput from WOKUnix; amode : PopenBufferMode from WOKUnix)  
+       returns mutable OutErrOutput from WOKUnix;
+     
+    Clear(me) is redefined;
+    Echo(me)   returns HSequenceOfHAsciiString from TColStd is redefined;
+    Errors(me) returns HSequenceOfHAsciiString from TColStd is redefined; 
+    
+    
+    Select(me; afdmax : out Integer from Standard; atimeout : in out Timeval from WOKUnix; aset : out FDSet from WOKUnix) is redefined;
+    
+    Acquit(me; selectstatus : Integer; aset : FDSet from WOKUnix) is redefined;
+
+    Close(me:mutable) is redefined;
+
+fields
+    myout : Buffer from WOKUnix;
+    myerr : Buffer from WOKUnix;
+end OutErrOutput;
diff --git a/src/WOKUnix/WOKUnix_OutErrOutput.cxx b/src/WOKUnix/WOKUnix_OutErrOutput.cxx
new file mode 100755 (executable)
index 0000000..150b02b
--- /dev/null
@@ -0,0 +1,112 @@
+
+#include <WOKUnix_OutErrOutput.ixx>
+#include <WOKUnix_FileBuffer.hxx>
+#include <WOKUnix_NoBuffer.hxx>
+#include <WOKUnix_CantBlockBuffer.hxx>
+
+
+//=======================================================================
+//function : WOKUnix_OutErrOutput
+//purpose  : 
+//=======================================================================
+WOKUnix_OutErrOutput::WOKUnix_OutErrOutput()
+{
+}
+
+
+//=======================================================================
+//function : WOKUnix_OutErrOutput
+//purpose  : 
+//=======================================================================
+WOKUnix_OutErrOutput::WOKUnix_OutErrOutput(const WOKUnix_FDescr& aoutfd, 
+                                            const WOKUnix_FDescr& aerrfd, 
+                                            const WOKUnix_PopenBufferMode amode)
+{
+  switch(amode)
+    {
+    case WOKUnix_POPEN_BUFFERED:
+      myout = new WOKUnix_FileBuffer(aoutfd, WOKUnix_STDOUT);
+      myerr = new WOKUnix_FileBuffer(aerrfd, WOKUnix_STDERR);
+      break;
+    case WOKUnix_POPEN_IMMEDIATE:
+      myout = new WOKUnix_NoBuffer(aoutfd, WOKUnix_STDOUT);
+      myerr = new WOKUnix_NoBuffer(aerrfd, WOKUnix_STDERR);
+      break;
+    case WOKUnix_POPEN_ECHOIFBLOCKED:
+      myout = new WOKUnix_CantBlockBuffer(aoutfd, WOKUnix_STDOUT);
+      myerr = new WOKUnix_CantBlockBuffer(aerrfd, WOKUnix_STDERR);
+      break;
+    }      
+}
+
+//=======================================================================
+//function : WOKUnix_OutErrOutput
+//purpose  : 
+//=======================================================================
+WOKUnix_OutErrOutput::WOKUnix_OutErrOutput(const Handle(WOKUnix_OutErrOutput)& anoutput, 
+                                             const WOKUnix_PopenBufferMode amode)
+{
+}
+
+//=======================================================================
+//function : Echo
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_OutErrOutput::Echo() const 
+{
+  Handle(TColStd_HSequenceOfHAsciiString) aseq = myout->Echo();
+  aseq->Append(myerr->Echo());
+  return aseq;
+}
+
+//=======================================================================
+//function : Clear
+//purpose  : 
+//=======================================================================
+void WOKUnix_OutErrOutput::Clear() const 
+{
+  myout->Clear();
+  myerr->Clear();
+}
+
+//=======================================================================
+//function : Errors
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_OutErrOutput::Errors() const 
+{
+  Handle(TColStd_HSequenceOfHAsciiString) aseq = myout->Errors();
+  aseq->Append(myerr->Errors());
+  return aseq;
+}
+
+//=======================================================================
+//function : Select
+//purpose  : 
+//=======================================================================
+void WOKUnix_OutErrOutput::Select(Standard_Integer& afdmax, WOKUnix_Timeval& atimeout,  WOKUnix_FDSet& aset) const 
+{
+  myout->Select(afdmax, atimeout, aset);
+  myerr->Select(afdmax, atimeout, aset);
+}
+
+//=======================================================================
+//function : Acquit
+//purpose  : 
+//=======================================================================
+void WOKUnix_OutErrOutput::Acquit(const Standard_Integer aselectstatus, const WOKUnix_FDSet& aset) const 
+{
+  myout->Acquit(aselectstatus, aset);
+  myerr->Acquit(aselectstatus, aset);
+}
+
+//=======================================================================
+//function : Close
+//purpose  : 
+//=======================================================================
+void WOKUnix_OutErrOutput::Close()
+{
+  myout->Close();
+  myerr->Close();
+}
+
diff --git a/src/WOKUnix/WOKUnix_Path.cdl b/src/WOKUnix/WOKUnix_Path.cdl
new file mode 100755 (executable)
index 0000000..1e50142
--- /dev/null
@@ -0,0 +1,152 @@
+-- File:       WOKUnix_Path.cdl
+-- Created:    Mon May 29 15:09:14 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+class Path from WOKUnix
+
+       ---Purpose: Supplee aux insuffisances de OSD_File
+
+inherits TShared from MMgt
+uses
+    HAsciiString from TCollection,
+    FDescr       from WOKUnix,
+    TimeStat     from WOKUnix,
+    StatBuf      from WOKUnix,
+    Extension    from WOKUnix
+
+is
+
+    Create returns mutable Path from WOKUnix;
+    ---Purpose: Instantiates Path from WOKUnix    
+
+    Create(apath : CString from Standard) 
+       returns mutable Path from WOKUnix;
+    
+    Create(apath : HAsciiString from TCollection) 
+    ---Purpose: Instantiates Path from WOKUnix using an asciistring
+       returns mutable Path from WOKUnix; 
+        
+    Create(adir,aname : HAsciiString from TCollection)  
+    ---Purpose: Instantiates Path from WOKUnix using an directory and
+    --          a name
+       returns mutable Path from WOKUnix; 
+    
+    Create(adir,aname : CString from Standard)  
+    ---Purpose: Instantiates Path from WOKUnix using an directory and
+    --          a name
+       returns mutable Path from WOKUnix; 
+    
+    CheckStats(me:mutable)
+    ---C++: inline
+       returns Boolean from Standard;
+
+    GetStats(me:mutable)
+       returns Boolean from Standard;
+    
+    Name(me) 
+    ---C++: return const &
+    ---C++: inline
+    ---Purpose: returns PathName    
+       returns HAsciiString from TCollection;
+       
+    SetName(me:mutable; apath : HAsciiString from TCollection);
+    ---Purpose: sets path
+    
+    BuildFDescr(me) 
+    ---Purpose: Builds a WOKUnix_FDescr to manipulate Path
+       returns FDescr from WOKUnix;
+    
+    Exists(me) returns Boolean;
+    ---Purpose: Tests existency of path on disk    
+
+    CreateDirectory(me:mutable; CreateParents : Boolean from Standard = Standard_False) 
+    ---Purpose: Creates path as a directory
+       returns Boolean;
+       
+    CreateFile(me:mutable; CreateParents : Boolean from Standard = Standard_False) 
+    ---Purpose: Creates path as a file on disk  
+       returns Boolean;
+
+    IsSymLink(me:mutable)
+       returns Boolean from Standard;
+       
+    IsFile(me:mutable)
+       returns Boolean from Standard;
+
+    IsDirectory(me:mutable)
+       returns Boolean from Standard;
+
+    CreateSymLinkTo(me:mutable; apath : Path from WOKUnix)
+       returns Boolean from Standard;
+
+    RemoveDirectory(me:mutable; RemoveChilds : Boolean from Standard = Standard_False)
+       returns Boolean from Standard;
+
+    RemoveFile(me:mutable) 
+       returns Boolean from Standard;
+
+    MoveTo(me:mutable; adestpath : Path from WOKUnix)
+    ---Purpose: Renames file to destpath Failes if mypath and dest
+    --          path are not on the same file system
+    --          mypath is changed to which of adestpath
+       returns Boolean from Standard;
+
+    ReducedPath(me)
+    ---Purpose: reduces Path as much as possible (reads links)
+       returns Path from WOKUnix;
+
+    IsSamePath(me; another : Path from WOKUnix)
+    ---Purpose: Tests is me corresponds to the same 
+    --          file as <another> (reads links)
+       returns Boolean from Standard;
+
+    IsSameFile(me; another : Path from WOKUnix)
+    ---Purpose: Teste si deux fichiers ont le meme     
+    --          contenu (typiquement utilise a l'extraction)
+       returns Boolean from Standard;
+
+    MDate(me:mutable)
+    ---C++: inline
+    ---Purpose: returns known date of path   
+       returns TimeStat from WOKUnix;
+
+    ResetMDate(me:mutable);
+    ---C++: inline
+
+    IsOlder(me:mutable; another : Path from WOKUnix)
+       returns Boolean from Standard;
+    IsNewer(me:mutable; another : Path from WOKUnix)
+       returns Boolean from Standard;
+       
+    IsWriteAble(me)
+       returns Boolean from Standard;
+    
+    Extension(me)
+    ---Purpose: extracts Extension of file    
+       returns Extension from WOKUnix;
+
+    ExtensionName(me)
+    ---Purpose: extracts Extension of file    
+       returns HAsciiString from TCollection;
+
+    BaseName(me)
+    ---Purpose: returns the basename of File
+       returns HAsciiString from TCollection;
+       
+    DirName(me)
+    ---Purpose: returns the dirname of file
+       returns HAsciiString from TCollection;
+       
+    FileName(me)
+    ---Purpose: returns the filename (<BaseName>.<Extension>) of path
+       returns HAsciiString from TCollection;
+
+fields
+    mypath  : HAsciiString from TCollection;
+    myacces : Boolean      from Standard;
+    mystats : StatBuf      from WOKUnix;
+end;
+
+   
diff --git a/src/WOKUnix/WOKUnix_Path.cxx b/src/WOKUnix/WOKUnix_Path.cxx
new file mode 100755 (executable)
index 0000000..13765da
--- /dev/null
@@ -0,0 +1,770 @@
+// File:       WOKUnix_Path.cxx
+// Created:    Tue May 30 09:17:00 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#include <WOKUnix_Path.ixx>
+
+#include <WOKTools_Messages.hxx>
+
+#include <TCollection_AsciiString.hxx>
+
+#include <WOKUnix.hxx>
+
+#include <WOKUnix_PathIterator.hxx>
+
+//=======================================================================
+//function : WOKUnix_Path
+//purpose  : Empty Contructor
+//=======================================================================
+WOKUnix_Path::WOKUnix_Path()
+{
+  mystats.st_mtime = -1;
+  myacces = Standard_False;
+}
+
+//=======================================================================
+//function : WOKUnix_Path
+//purpose  : Instantiates using a TCollection_AsciiString
+//=======================================================================
+WOKUnix_Path::WOKUnix_Path(const Standard_CString apath)
+{
+  mypath = new TCollection_HAsciiString(apath);
+  mystats.st_mtime = -1;
+  myacces = Standard_False;
+}
+
+//=======================================================================
+//function : WOKUnix_Path
+//purpose  : Instantiates using a TCollection_AsciiString
+//=======================================================================
+WOKUnix_Path::WOKUnix_Path(const Handle(TCollection_HAsciiString)& apath)
+{
+  mypath = apath;
+  mystats.st_mtime = -1;
+  myacces = Standard_False;
+}
+
+//=======================================================================
+//function : WOKUnix_Path
+//purpose  : Instantiates using a TCollection_AsciiString
+//=======================================================================
+WOKUnix_Path::WOKUnix_Path(const Handle(TCollection_HAsciiString)& adir, const Handle(TCollection_HAsciiString)& aname)
+{
+  Handle(TCollection_HAsciiString) astr = new TCollection_HAsciiString;
+
+  astr->AssignCat(adir);
+  astr->AssignCat("/");
+  astr->AssignCat(aname);
+  mypath = astr;
+  mystats.st_mtime = -1;
+  myacces = Standard_False;
+}
+
+//=======================================================================
+//function : WOKUnix_Path
+//purpose  : Instantiates using a TCollection_AsciiString
+//=======================================================================
+WOKUnix_Path::WOKUnix_Path(const Standard_CString adir, const Standard_CString aname)
+{
+  Handle(TCollection_HAsciiString) astr = new TCollection_HAsciiString;
+
+  astr->AssignCat(adir);
+  astr->AssignCat("/");
+  astr->AssignCat(aname);
+  mypath = astr;
+  mystats.st_mtime = -1;
+  myacces = Standard_False;
+}
+
+//=======================================================================
+//function : SetName
+//purpose  : set path
+//=======================================================================
+void WOKUnix_Path::SetName(const Handle(TCollection_HAsciiString)& apath)
+{
+  mypath = apath;
+}
+
+//=======================================================================
+//function : BuildFDescr
+//purpose  : build WOKUnix_FDescr
+//=======================================================================
+WOKUnix_FDescr WOKUnix_Path::BuildFDescr() const 
+{
+  WOKUnix_FDescr afd;
+  OSD_Path        apath(mypath->String());
+
+
+  afd.SetPath(apath);
+
+  return afd;
+}
+
+//=======================================================================
+//function : Exists
+//purpose  : Test existency of path on FS
+//=======================================================================
+Standard_Boolean WOKUnix_Path::Exists() const 
+{
+  if(mypath.IsNull())
+    {
+      return Standard_False;
+    }
+  if(myacces) return  Standard_True;
+  
+  if(access(mypath->ToCString(), F_OK))  {return Standard_False;}
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : CreateDirectory
+//purpose  : Creates path as a directory
+//=======================================================================
+Standard_Boolean WOKUnix_Path::CreateDirectory(const Standard_Boolean CreateParents) 
+{
+  TCollection_AsciiString afullname;
+  
+  if(Exists())
+    {
+      // l'inode existe deja
+      if(!IsDirectory())
+       {
+         ErrorMsg << "WOKUnix_Path::CreateDirectory" 
+           << mypath << " exists and is not a directory" << endm; 
+         return Standard_False;
+       }
+      return Standard_True;
+    }
+  
+  Handle(WOKUnix_Path) parent = new WOKUnix_Path(DirName());
+
+  if(parent->Exists())
+    {
+      if(!parent->IsDirectory())
+       {
+         ErrorMsg << "WOKUnix_Path::CreateDirectory" 
+           << "Parent Directory " << parent->Name() << " exists and is not a directory" << endm; 
+         return Standard_False;
+       }
+
+     if(mkdir(mypath->ToCString(), 0777))
+       {
+         ErrorMsg << "WOKUnix_Path::CreateDirectory" 
+           << WOKUnix::LastSystemMessage() << endm;
+         ErrorMsg << "WOKUnix_Path::CreateDirectory" 
+           << "Could not create directory : " << mypath << endm;
+         return Standard_False;
+       }
+      return Standard_True;
+    }
+  
+  if(CreateParents == Standard_False)
+    {
+      ErrorMsg << "WOKUnix_Path::CreateDirectory" 
+       << "Parent Directory " << parent->Name() << " does not exist" << endm;
+      return Standard_False;
+    }
+
+  // j'ai le droit de creer les parents
+  // ADN - attention, creation de path sur un disque invisible (bouclage !)
+  if (!strcmp(parent->Name()->ToCString(),Name()->ToCString())) {
+    return Standard_False;
+  }
+
+  if (parent->CreateDirectory(Standard_True)) {
+    return CreateDirectory(Standard_False);
+  }
+  return Standard_False;
+}
+
+//=======================================================================
+//function : CreateFile
+//purpose  : Creates path as a file
+//=======================================================================
+Standard_Boolean WOKUnix_Path::CreateFile(const Standard_Boolean CreateParents) 
+{
+  TCollection_AsciiString afullname;
+  Handle(WOKUnix_Path) parent = new WOKUnix_Path;
+
+  if(Exists())
+    {
+      // l'inode existe deja
+      if(!IsFile())
+       {
+         ErrorMsg << "WOKUnix_Path::CreateFile" 
+           << mypath << " exists and is not a file" << endm; 
+         return Standard_False;
+       }
+      else return Standard_True;
+    }
+
+  //if(apath.IsValid(mypath->ToCString()) == Standard_False) 
+  //  {
+  //    ErrorMsg << "WOKUnix_Path::CreateFile" 
+  //          << mypath << " is invalid" << endm; 
+  //    return Standard_False;
+  //  }
+  
+  parent->SetName(DirName());
+  
+  if(parent->Exists())
+    {
+      if(!parent->IsDirectory())
+       {
+         ErrorMsg << "WOKUnix_Path::CreateFile" 
+           << "Parent Directory " << parent->Name() << " exists and is not a directory" << endm; 
+         return Standard_False;
+       }
+
+      Standard_Integer fd;
+      
+      if((fd=creat(mypath->ToCString(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) < 0)
+       {
+         ErrorMsg << "WOKUnix_Path::CreateFile" << WOKUnix::LastSystemMessage() << endm;
+         ErrorMsg << "WOKUnix_Path::CreateFile" << "Could not create " << mypath << endm; 
+         return Standard_False;
+       }
+      close(fd);
+      return Standard_True;
+    }
+  else if(CreateParents == Standard_False)
+    {
+      ErrorMsg << "WOKUnix_Path::CreateFile" 
+       << "Parent Directory " 
+         << parent->Name()
+           << " does not exist" << endm;
+      return Standard_False;
+    }
+  if (parent->CreateDirectory(Standard_True)) {
+    return CreateFile(Standard_False);
+  }
+  return Standard_False;
+}
+
+//=======================================================================
+//function : IsSymLink
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsSymLink()  
+{
+  if(mypath.IsNull()) return Standard_False;
+  if(!CheckStats())     return Standard_False;
+
+  struct stat statbuf;
+  if(lstat(mypath->ToCString(), &statbuf))
+    {
+      return Standard_False;
+    }
+  return  S_ISLNK(statbuf.st_mode);
+}
+
+//=======================================================================
+//function : IsFile
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsFile()  
+{
+  if(mypath.IsNull()) return Standard_False;
+  if(!CheckStats())     return Standard_False;
+  return  S_ISREG(mystats.st_mode);
+}
+
+//=======================================================================
+//function : IsDirectory
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsDirectory()  
+{
+  if(mypath.IsNull()) return Standard_False;
+  if(!CheckStats())     return Standard_False;
+
+  return  S_ISDIR(mystats.st_mode);
+}
+
+//=======================================================================
+//function : CreateSymLinkTo
+//purpose  : 
+//=======================================================================
+Standard_Boolean  WOKUnix_Path::CreateSymLinkTo(const Handle(WOKUnix_Path)& apath) 
+{
+  if(apath.IsNull() || Name().IsNull())
+    {
+      ErrorMsg << "WOKUnix_Path::CreateSymLinkTo" 
+       << "Unable to create symlink : Invalid arguments" << endm;
+      return Standard_False;
+    }
+
+  if(symlink(apath->Name()->ToCString(), Name()->ToCString()))
+    {
+      ErrorMsg << "WOKUnix_Path::CreateSymLinkTo" 
+       << WOKUnix::LastSystemMessage() << endm;
+      ErrorMsg << "WOKUnix_Path::CreateSymLinkTo" 
+       << "Unable to create " << Name() << " -> " << apath->Name() << endm;
+      return Standard_False;      
+    }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : RemoveDirectory
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::RemoveDirectory(const Standard_Boolean RemoveChilds)
+{
+  if(Name().IsNull())
+    {
+      ErrorMsg << "WOKUnix_Path::RemoveDirectory" 
+       << "Invalid null name" << endm;
+      return Standard_False;
+    }
+
+  if(!RemoveChilds)
+    {
+      if(rmdir(Name()->ToCString()) != 0)
+       {
+         ErrorMsg << "WOKUnix_Path::RemoveDirectory" 
+           << WOKUnix::LastSystemMessage() << endm;
+         ErrorMsg << "WOKUnix_Path::RemoveDirectory" 
+           << "Could not remove : " << Name() << endm;
+         return Standard_False;
+       }
+    }
+  else
+    {
+      // WOKUtils_PathIterator ....
+    }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : RemoveFile
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::RemoveFile()
+{
+  if(Name().IsNull())
+    {
+      ErrorMsg << "WOKUnix_Path::RemoveFile" 
+       << "Invalid null name" << endm;
+      return Standard_False;
+    }
+  if(unlink(Name()->ToCString()))
+    {
+      ErrorMsg << "WOKUnix_Path::RemoveFile" 
+       << WOKUnix::LastSystemMessage() << endm;
+      ErrorMsg << "WOKUnix_Path::RemoveFile" 
+       << "Failed to Remove : " << Name() << endm;
+      return Standard_False;
+    }
+  return Standard_True;
+}
+
+//=======================================================================
+//function : MoveTo
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::MoveTo(const Handle(WOKUnix_Path)& adestpath) 
+{
+  if(rename(mypath->ToCString(), adestpath->Name()->ToCString()))
+    {
+      ErrorMsg << "WOKUnix_Path::MoveTo" 
+       << WOKUnix::LastSystemMessage() << endm;
+      ErrorMsg << "WOKUnix_Path::MoveTo" 
+       << "Failed to Move " << mypath->ToCString() << " to " << adestpath->Name()->ToCString()<< endm;
+      return Standard_False;
+    }
+  else
+    {
+      mypath = adestpath->Name();
+      return Standard_True;
+    }
+}
+
+//=======================================================================
+//function : ReducedPath
+//purpose  : 
+//=======================================================================
+Handle(WOKUnix_Path) WOKUnix_Path::ReducedPath() const
+{
+  Handle(WOKUnix_Path) areduced;
+  Handle(TCollection_HAsciiString) astr;
+
+  if(Exists())
+    {
+#if !defined(DECOSF1) && !defined(HPUX)
+
+      char abuffer[PATH_MAX];
+
+      *abuffer = '\0';
+
+      if(realpath(mypath->ToCString(), abuffer) == NULL)
+       {
+         ErrorMsg << "WOKUnix_Path::ReducedPath" << WOKUnix::LastSystemMessage() << endm;
+         return this;
+       }
+
+      astr = new TCollection_HAsciiString(abuffer);
+
+      areduced = new WOKUnix_Path(astr);
+      return areduced;
+#else
+
+      astr = new TCollection_HAsciiString(mypath);
+      areduced = new WOKUnix_Path(astr);
+
+      return areduced;
+
+#endif
+
+    }
+  else
+    {
+      astr = new TCollection_HAsciiString(Name());
+      areduced = new WOKUnix_Path(Name());
+      return areduced;
+    }
+}
+
+//=======================================================================
+//function : IsSamePath
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsSamePath(const Handle(WOKUnix_Path)& another) const 
+{
+  Handle(WOKUnix_Path) mereduced = ReducedPath();
+  Handle(WOKUnix_Path) otherreduced = another->ReducedPath();
+
+  if(mereduced->Name()->IsSameString(otherreduced->Name())) return Standard_True;
+  return Standard_False;
+}
+
+//=======================================================================
+//function : IsSameFile
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsSameFile(const Handle(WOKUnix_Path)& another) const 
+{
+  int fd1, fd2;
+  long lg1, lg2;
+  long nb;
+  static char buf1[4096], buf2[4096];
+  struct stat buf_stat;
+
+  if((fd1 = open(Name()->ToCString(), O_RDONLY, 0)) < 0)
+    {
+      ErrorMsg << "WOKUnix_Path::IsSameFile" << WOKUnix::LastSystemMessage() << endm;
+      ErrorMsg << "WOKUnix_Path::IsSameFile" << "Can't open " << Name() << endm;
+      return Standard_False;
+    }
+  if((fd2 = open(another->Name()->ToCString(), O_RDONLY, 0)) < 0)
+    {
+      ErrorMsg << "WOKUnix_Path::IsSameFile" << WOKUnix::LastSystemMessage() << endm;
+      ErrorMsg << "WOKUnix_Path::IsSameFile" << "Can't open " << another->Name() << endm;
+      return Standard_False;
+    }
+
+  /* longueurs differentes ? */
+  if(fstat(fd1, &buf_stat)) {close(fd1); close(fd2); return Standard_False;}
+  lg1 = buf_stat.st_size;
+  if(fstat(fd2, &buf_stat)) {close(fd1); close(fd2); return Standard_False;}
+  lg2 = buf_stat.st_size;
+  if(lg1 != lg2) {close(fd1); close(fd2); return Standard_False;}
+
+  while(lg1 > 0)
+    {
+      if (lg1 > 4096)
+       {nb = 4096; lg1 -= 4096;}
+      else
+       {nb = lg1;  lg1 = -1;}
+      if((read(fd1, buf1, nb)) < 0) {close(fd1); close(fd2); return Standard_False;}
+      if((read(fd2, buf2, nb)) < 0) {close(fd1); close(fd2); return Standard_False;}
+      /* fichiers differents */
+      if(memcmp(buf1, buf2, nb)) {close(fd1); close(fd2); return Standard_False;}
+    }
+  
+  /* fichiers identiques */
+  close(fd1);
+  close(fd2);
+  return Standard_True;  
+}
+
+//=======================================================================
+//function : GetStats
+//purpose  : Obtain file stats
+//=======================================================================
+Standard_Boolean WOKUnix_Path::GetStats()
+{
+  if(mystats.st_mtime != -1) return Standard_True;
+
+  if(!Exists()) return Standard_False;
+  else if(stat(mypath->ToCString(), &mystats))
+    {
+      ErrorMsg << "WOKUnix_Path::GetStats" 
+       << WOKUnix::LastSystemMessage() << endm;
+      return Standard_False;
+    }
+  else return Standard_True;
+}
+
+//=======================================================================
+//function : IsOlder
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsOlder(const Handle(WOKUnix_Path)& another) 
+{
+  if(MDate() < another->MDate()) return Standard_True;
+  return Standard_False;
+}
+
+
+//=======================================================================
+//function : IsNewer
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsNewer(const Handle(WOKUnix_Path)& another) 
+{
+  if(MDate() > another->MDate()) return Standard_True;
+  return Standard_False;
+}
+
+//=======================================================================
+//function : IsWriteAble
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Path::IsWriteAble() const
+{
+  
+  if(mypath.IsNull())
+    {
+      return Standard_False;
+    }
+  
+  if(access(mypath->ToCString(), R_OK | W_OK ))
+    {
+      return Standard_False;
+    }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : Extension
+//purpose  : 
+//=======================================================================
+WOKUnix_Extension WOKUnix_Path::Extension() const
+{
+  Standard_CString ptr = strrchr(mypath->ToCString(), '.');
+
+  if(ptr)
+    {
+      ptr++;
+
+      // Specification Files
+      if(!strcmp(ptr, "cdl"))       return WOKUnix_CDLFile;
+      if(!strcmp(ptr, "odl"))       return WOKUnix_ODLFile;
+      if(!strcmp(ptr, "idl"))       return WOKUnix_IDLFile;
+
+      // Includes
+      if(!strcmp(ptr, "hxx"))       return WOKUnix_HXXFile;
+      if(!strcmp(ptr, "ixx"))       return WOKUnix_IXXFile;
+      if(!strcmp(ptr, "jxx"))       return WOKUnix_JXXFile;
+      if(!strcmp(ptr, "lxx"))       return WOKUnix_LXXFile;
+      if(!strcmp(ptr, "gxx"))       return WOKUnix_GXXFile;
+      if(!strcmp(ptr, "h"))         return WOKUnix_HFile;
+      if(!strcmp(ptr, "pxx"))       return WOKUnix_PXXFile;
+      if(!strcmp(ptr, "inc"))       return WOKUnix_INCFile;
+      if(!strcmp(ptr, "INC"))       return WOKUnix_INCFile;
+
+      // DBMS Files
+      if(!strcmp(ptr, "ddl"))       return WOKUnix_DDLFile;
+      if(!strcmp(ptr, "DB"))        return WOKUnix_DBFile;
+      if(!strcmp(ptr, "FDDB"))      return WOKUnix_FDDBFile;
+      if(!strcmp(ptr, "libschema")) return WOKUnix_LibSchemaFile;
+      if(!strcmp(ptr, "asdb"))      return WOKUnix_AppSchemaFile;
+      if(!strcmp(ptr, "ho2"))       return WOKUnix_HO2File;
+
+      // Code Generators
+      if(!strcmp(ptr, "lex"))       return WOKUnix_LexFile;
+      if(!strcmp(ptr, "yacc"))      return WOKUnix_YaccFile;
+      if(!strcmp(ptr, "lws"))       return WOKUnix_LWSFile;      
+      if(!strcmp(ptr, "psw"))       return WOKUnix_PSWFile;
+
+      // Compilable
+      if(!strcmp(ptr, "cxx"))       return WOKUnix_CXXFile;
+      if(!strcmp(ptr, "C"))         return WOKUnix_CXXFile;      
+      if(!strcmp(ptr, "c"))         return WOKUnix_CFile;
+      if(!strcmp(ptr, "f"))         return WOKUnix_F77File;
+
+      // Machine Files
+      if(!strcmp(ptr, "o"))         return WOKUnix_ObjectFile;
+      if(!strcmp(ptr, "m"))         return WOKUnix_MFile;
+      if(!strcmp(ptr, "a"))         return WOKUnix_ArchiveFile;
+
+      if(!strcmp(ptr, "so"))        return WOKUnix_DSOFile;
+      if(!strcmp(ptr, "sl"))        return WOKUnix_DSOFile;
+      
+      // WNT Externsions
+      if(!strcmp(ptr, "lib"))       return WOKUnix_LIBFile;
+      if(!strcmp(ptr, "imp"))       return WOKUnix_IMPFile;
+      if(!strcmp(ptr, "def"))       return WOKUnix_DEFile;
+      if(!strcmp(ptr, "exp"))       return WOKUnix_EXPFile;
+
+      if(!strcmp(ptr, "rc"))        return WOKUnix_RCFile;
+      if(!strcmp(ptr, "res"))       return WOKUnix_RESFile;
+
+      // Miscellaneous
+      if(!strcmp(ptr, "Z"))         return WOKUnix_CompressedFile;
+      if(!strcmp(ptr, "gz"))        return WOKUnix_CompressedFile;
+      if(!strcmp(ptr, "dat"))       return WOKUnix_DATFile;
+      if(!strcmp(ptr, "ll"))        return WOKUnix_LispFile;
+      if(!strcmp(ptr, "ccl"))       return WOKUnix_LispFile;
+      if(!strcmp(ptr, "xwd"))       return WOKUnix_IconFile;
+      if(!strcmp(ptr, "txt"))       return WOKUnix_TextFile;
+      if(!strcmp(ptr, "tar"))       return WOKUnix_TarFile;
+      if(!strcmp(ptr, "csh"))       return WOKUnix_CSHFile;
+
+      if(!strcmp(ptr, "template"))  return WOKUnix_TemplateFile;
+      return WOKUnix_UnknownFile;
+    }
+  
+  return WOKUnix_NoExtFile;
+}
+
+
+//=======================================================================
+//function : ExtensionName
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_Path::ExtensionName() const
+{
+  Standard_Integer                   pos;
+  Handle(TCollection_HAsciiString)   retVal = new TCollection_HAsciiString(mypath);
+  
+  pos = retVal->Length();
+  while(pos != 0)
+    {
+      Standard_Character chr = retVal -> Value(pos);
+      if( chr ==  '.') break;
+      --pos;
+    }
+  
+  if(pos)
+    retVal = retVal->SubString(pos, retVal->Length());
+  return retVal;
+}
+
+//=======================================================================
+//function : BaseName
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_Path::BaseName() const
+{
+  Standard_Integer                   pos;
+  Handle(TCollection_HAsciiString)   retVal = new TCollection_HAsciiString(mypath);
+  
+  pos = retVal->Length();
+  
+  while(pos != 0)
+    {
+      Standard_Character chr = retVal -> Value(pos);
+      
+      if( chr ==  '/' ) break;
+      --pos;
+    }
+  
+  if(pos)
+    retVal = retVal->SubString(pos+1, retVal->Length());
+
+  pos = retVal->Length();
+  while(pos != 0)
+    {
+      Standard_Character chr = retVal -> Value(pos);
+      if( chr == '.') break;
+      --pos;
+    }
+  
+  if(pos)
+    retVal = retVal->SubString(1, pos-1);
+  return retVal;
+}
+
+//=======================================================================
+//function : DirName
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_Path::DirName() const
+{
+
+  Standard_Integer                   pos, len;
+  Standard_Character                 chr;
+  Standard_Boolean                   fRetry;
+  Handle(TCollection_HAsciiString)   retVal = new TCollection_HAsciiString(mypath);
+
+  fRetry = Standard_False;
+  pos    = len = retVal->Length();
+
+  while(pos != 0)
+    {
+      chr = retVal -> Value(pos );
+      
+      if( chr == '/' )
+       {
+         if(fRetry || pos != len) break;
+         
+         retVal -> Trunc(pos - 1 );
+         fRetry = Standard_True;
+       }
+      --pos;
+    }
+
+  if(pos > 1 )
+    retVal -> Trunc(pos - 1 );
+  return retVal;
+}
+
+//=======================================================================
+//function : DirName
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_Path::FileName() const
+{
+  Standard_Integer                   pos;
+  Handle(TCollection_HAsciiString)   retVal = new TCollection_HAsciiString(mypath);
+  
+  pos = retVal->Length();
+  
+  while(pos != 0)
+    {
+      Standard_Character chr = retVal -> Value(pos);
+      
+      if( chr ==  '/' )
+       {
+         if(pos == retVal->Length())
+           {
+             retVal->Trunc(retVal->Length()-1);
+           }
+         else
+           break;
+       }
+      --pos;
+    }
+  
+  if(pos)
+    retVal = retVal->SubString(pos+1, retVal->Length());
+  return retVal;
+}
+
diff --git a/src/WOKUnix/WOKUnix_Path.lxx b/src/WOKUnix/WOKUnix_Path.lxx
new file mode 100755 (executable)
index 0000000..f8afa87
--- /dev/null
@@ -0,0 +1,45 @@
+// File:       WOKUnix_Path.lxx
+// Created:    Thu Jul 27 19:46:43 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+#include <TCollection_HAsciiString.hxx>
+
+//=======================================================================
+//Author   : Jean Gautier (jga)
+//function : Name
+//purpose  : returns PathName    
+//=======================================================================
+const Handle(TCollection_HAsciiString)& WOKUnix_Path::Name() const 
+{
+  return mypath;
+}
+
+Standard_Boolean WOKUnix_Path::CheckStats()
+{
+  if(mystats.st_mtime == -1) 
+    return GetStats();
+  else return Standard_True;
+}
+
+//=======================================================================
+//Author   : Jean Gautier (jga)
+//function : MDate
+//purpose  : returns known date of path
+//=======================================================================
+WOKUnix_TimeStat WOKUnix_Path::MDate()
+{
+  if(mystats.st_mtime == -1) 
+    GetStats();
+  return mystats.st_mtime;
+}
+
+//=======================================================================
+//Author   : Jean Gautier (jga)
+//function : ResetMDate
+//purpose  : 
+//=======================================================================
+void WOKUnix_Path::ResetMDate()
+{
+  mystats.st_mtime = -1;
+}
diff --git a/src/WOKUnix/WOKUnix_PathIterator.cdl b/src/WOKUnix/WOKUnix_PathIterator.cdl
new file mode 100755 (executable)
index 0000000..5c76fac
--- /dev/null
@@ -0,0 +1,66 @@
+-- File:       WOKUnix_PathIterator.cdl
+-- Created:    Mon Aug 03 15:37:45 1998
+-- Author:     
+--             <jga@GROMINEX>
+---Copyright:   Matra Datavision 1998
+
+
+class PathIterator from WOKUnix
+
+
+uses 
+    Boolean from Standard,
+    HAsciiString from TCollection,
+    AsciiString from TCollection,
+    StackOfDir from WOKUnix,
+    Dir from WOKUnix,
+    DirEnt from WOKUnix,
+    Path from WOKUnix
+    
+is
+
+
+    Create(apath : Path from WOKUnix; recursive : Boolean from Standard = Standard_False; mask : CString from Standard = "*")
+       returns PathIterator from WOKUnix;
+
+    SkipDots(me:out) is private;
+       
+    IsDots(myclass; aname : CString from Standard)
+       returns Boolean from Standard is private;
+
+    Push(me:out; apath : Path from WOKUnix; adir : Dir from WOKUnix) is private;
+    Pop(me:out) is private;
+    
+    Next(me:out);
+    
+    
+    PathValue(me)
+       returns Path from WOKUnix;
+    
+    LevelValue(me)
+       returns Integer from Standard;
+       
+    NameValue(me)
+       returns HAsciiString from TCollection;
+
+    BrowsedPath(me)
+       returns Path from WOKUnix;      
+               
+    More(me)
+       returns Boolean from Standard;
+
+    Destroy(me:in out);
+    ---C++: alias ~
+
+fields
+
+    mymask      : AsciiString from TCollection;
+    mypath      : Path from WOKUnix;
+    mydata      : DirEnt from WOKUnix;
+    mystack     : StackOfDir from WOKUnix;
+    mymore      : Boolean from Standard;
+    myrecflag   : Boolean from Standard;
+
+end;
+
+
diff --git a/src/WOKUnix/WOKUnix_PathIterator.cxx b/src/WOKUnix/WOKUnix_PathIterator.cxx
new file mode 100755 (executable)
index 0000000..3614f25
--- /dev/null
@@ -0,0 +1,187 @@
+
+
+#include <WOKUnix_PathIterator.ixx>
+
+
+#include <WOKUnix.hxx>
+#include <WOKUnix_Path.hxx>
+
+#include <WOKTools_Messages.hxx>
+
+#include <stream.h>
+
+#include <stdio.h>
+//#include <sys/types.h>
+//#include <sys/stat.h>
+#include <dirent.h>
+
+
+WOKUnix_PathIterator::WOKUnix_PathIterator(const Handle(WOKUnix_Path)& apath, const Standard_Boolean abool, const Standard_CString amask) 
+: mypath(apath), myrecflag(abool), mymask(amask)
+{
+  TCollection_HAsciiString mask;
+  mask.AssignCat(apath->Name()->ToCString());
+  mask.AssignCat("/");
+  mask.AssignCat(mymask.ToCString());
+
+  
+  WOKUnix_Dir adir = opendir(apath->Name()->ToCString());
+
+  if(!adir) 
+    {
+      ErrorMsg << "WOKUnix_PathIterator::WOKUnix_PathIterator" 
+       << WOKUnix::LastSystemMessage() << endm;
+      ErrorMsg << "WOKUnix_PathIterator::WOKUnix_PathIterator" 
+       << "Could not open directory " << apath->Name() << endm;
+      mymore = Standard_False;
+      return;
+    }
+
+  mystack.Push(adir);
+  mydata = readdir(mystack.Top());
+  mymore = Standard_True;
+  
+  SkipDots();
+}
+
+
+Standard_Boolean WOKUnix_PathIterator::IsDots(const Standard_CString astr)
+{
+  if(astr[0] == '.')
+    {
+      if(!astr[1])
+       return Standard_True;
+      else
+       if(astr[1] == '.' )
+         if(!astr[2])
+           return Standard_True;
+    }
+  return Standard_False;
+}
+
+void WOKUnix_PathIterator::SkipDots() 
+{
+  if(!mydata) return;
+  while(IsDots((Standard_CString)mydata->d_name) && !mystack.IsEmpty())
+    {
+      mydata = readdir(mystack.Top());
+      if(!mydata)
+       {
+         if(!mystack.IsEmpty())
+            {
+               Pop();
+               if(!mymore) return;
+           }
+         else
+           {
+               mymore = Standard_False;
+               return;
+           }
+       }
+    }
+}
+
+
+void WOKUnix_PathIterator::Push(const Handle(WOKUnix_Path)& apath,  const WOKUnix_Dir& data)
+{
+  if(!IsDots(mydata->d_name) && myrecflag)
+    {
+      mypath = apath;
+      
+      WOKUnix_Dir nextone = opendir(mypath->Name()->ToCString());
+      mystack.Push(nextone);
+      mydata = readdir(mystack.Top());
+      SkipDots();
+      
+      if(!mystack.IsEmpty())
+       {
+         if(!mystack.Top()) 
+           mymore = Standard_False;
+         else
+           mymore = Standard_True;
+       }
+      else
+       mymore = Standard_False;
+    }
+}
+
+void WOKUnix_PathIterator::Pop()
+{
+  if(!mystack.IsEmpty())
+    {
+      closedir(mystack.Top());
+      mystack.Pop();
+      if(!mystack.IsEmpty()) 
+       {
+         mydata = readdir(mystack.Top());
+         if(!mydata)
+           {
+             if(mystack.IsEmpty())
+               mymore = Standard_False;
+             else
+               Pop();
+           }
+         else
+           SkipDots();
+         mypath = new WOKUnix_Path(mypath->DirName());
+       }
+      else 
+       mymore = Standard_False;
+    }
+}
+
+
+void WOKUnix_PathIterator::Next()
+{
+  Handle(WOKUnix_Path) apath =  new WOKUnix_Path(mypath->Name(), new TCollection_HAsciiString(mydata->d_name));
+  if(!IsDots(mydata->d_name) && myrecflag && apath->IsDirectory()) 
+    Push(apath, mystack.Top());
+  else
+    {
+      mydata = readdir(mystack.Top());
+      if(!mydata)
+       {
+         if(!mystack.IsEmpty())
+           Pop();
+         
+         if(mystack.IsEmpty())
+           mymore = Standard_False;
+       }
+    }
+}
+
+Handle(WOKUnix_Path) WOKUnix_PathIterator::PathValue()  const
+{
+  if(mydata) return new WOKUnix_Path(mypath->Name(), new TCollection_HAsciiString(mydata->d_name));
+  return Handle(WOKUnix_Path)();
+}
+
+Handle(TCollection_HAsciiString) WOKUnix_PathIterator::NameValue()  const
+{
+  
+  if(mydata) return new TCollection_HAsciiString(mydata->d_name);
+  return Handle(TCollection_HAsciiString)();
+  
+}
+
+Standard_Integer WOKUnix_PathIterator::LevelValue() const
+{
+  return mystack.Depth();
+}
+
+Standard_Boolean WOKUnix_PathIterator::More() const
+{
+  return mymore;
+}
+
+void WOKUnix_PathIterator::Destroy() 
+{
+  while(!mystack.IsEmpty())
+    {
+      if(mystack.Top()) closedir(mystack.Top());
+      mystack.Pop();
+    }
+}
+
+
+
diff --git a/src/WOKUnix/WOKUnix_Process.cdl b/src/WOKUnix/WOKUnix_Process.cdl
new file mode 100755 (executable)
index 0000000..9bad083
--- /dev/null
@@ -0,0 +1,89 @@
+-- File:       WOKUnix_Process.cdl
+-- Created:    Tue May  9 14:18:26 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class Process from WOKUnix
+inherits TShared from MMgt
+
+
+       ---Purpose: 
+
+
+uses
+    HAsciiString    from TCollection,
+    ProcessOutput   from WOKUnix,
+    Timeval         from WOKUnix,
+    FDSet           from WOKUnix,
+    ArgTable        from WOKTools,
+    FDescr          from WOKUnix,
+    PopenOutputMode from WOKUnix,
+    PopenBufferMode from WOKUnix
+raises 
+    --ProgramError from Standard, 
+    OSDError     from OSD
+is
+    
+    Create(argcount : Integer; cmdline: ArgTable from WOKTools;
+          anoutputmode : PopenOutputMode from WOKUnix = WOKUnix_POPEN_MIX_OUT_ERR; 
+           abuffermode  : PopenBufferMode from WOKUnix = WOKUnix_POPEN_BUFFERED;
+          atimeout     : Integer from Standard = -1) 
+       returns mutable Process;
+            
+    Create(cmdline : HAsciiString from TCollection;
+          anoutputmode : PopenOutputMode from WOKUnix = WOKUnix_POPEN_MIX_OUT_ERR; 
+           abuffermode  : PopenBufferMode from WOKUnix = WOKUnix_POPEN_BUFFERED;
+          atimeout     : Integer from Standard = -1) 
+       returns mutable Process;
+
+    --Command(me) returns ProgramError from Standard;
+    SetCommand(me:mutable;argcount : Integer; cmdline: ArgTable from WOKTools);
+    --SetCommand(me : mutable; cmdline: ArgTable from WOKTools)
+    --                     raises ProgramError from Standard;
+    Launch(me : mutable);
+    IsLaunched(me) returns Boolean;    
+
+    Pid(me) returns Integer;
+    
+    Output(me : mutable) 
+    ---C++: return &
+       returns mutable ProcessOutput from WOKUnix
+       is protected;
+    
+    Timeout(me) returns Integer from Standard;
+    SetTimeout(me : mutable;atimeout : Integer);
+    
+    Select(me; afdmax : out Integer from Standard; 
+              atimeout : in out Timeval from WOKUnix;
+               aset :  out FDSet from WOKUnix) 
+       is protected;
+    
+    Acquit(me; selectstatus : Integer from Standard ; aset : FDSet from WOKUnix)  
+       is protected;
+   
+    SelectAndAcquit(me) is protected;
+
+    Send(me : mutable; astring : HAsciiString from TCollection) 
+       raises  OSDError from OSD is virtual; 
+
+    Kill(me:mutable);
+    Destroy(me:mutable);
+    ---C++: alias ~
+
+
+
+fields 
+    myargv       : ArgTable        from WOKTools;
+    mymode       : PopenOutputMode from WOKUnix;
+    mybuffermode : PopenBufferMode from WOKUnix;
+    myinput      : FDescr          from WOKUnix;
+    myoutput     : ProcessOutput   from WOKUnix;
+    mylaunched   : Boolean         from Standard;
+    mytimeout    : Integer         from Standard;
+    mychildpid   : Integer         from Standard;
+end Process;
+
+
diff --git a/src/WOKUnix/WOKUnix_Process.cxx b/src/WOKUnix/WOKUnix_Process.cxx
new file mode 100755 (executable)
index 0000000..0308f80
--- /dev/null
@@ -0,0 +1,355 @@
+
+#ifdef IRIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <bstring.h>
+#include <sys/time.h>
+#endif
+
+#ifdef HPUX
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#endif
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+#include <Standard_ProgramError.hxx>
+
+#include <WOKUnix_Process.ixx>
+#include <WOKUnix_OutErrOutput.hxx>
+#include <WOKUnix_MixedOutput.hxx>
+#include <WOKUnix_Signal.hxx>
+#include <WOKUnix_FDescr.hxx>
+#include <WOKUnix_ProcessManager.hxx>
+#include <WOKTools_Messages.hxx>
+#include <WOKTools_ArgTable.hxx>
+
+
+//=======================================================================
+//function : WOKUnix_Process
+//purpose  : constructs a process
+//=======================================================================
+ WOKUnix_Process::WOKUnix_Process(const Standard_Integer argcount, 
+                                   const WOKTools_ArgTable& cmdline, 
+                                   const WOKUnix_PopenOutputMode anoutputmode, 
+                                   const WOKUnix_PopenBufferMode abuffermode, 
+                                   const Standard_Integer atimeout)
+{
+  Standard_Integer i = 0;
+
+  myargv = new char * [argcount];
+
+  while(i < argcount)
+    {
+      myargv[i] =cmdline [i];
+      i++;
+    }
+
+  mymode       = anoutputmode;
+  mybuffermode = abuffermode;
+  mylaunched   = Standard_False;
+  mytimeout    = atimeout;
+
+  WOKUnix_ProcessManager::AddProcess(this);
+}
+
+//=======================================================================
+//function : SetCommand
+//purpose  : 
+//=======================================================================
+void WOKUnix_Process::SetCommand(const Standard_Integer argcount, 
+                                 const WOKTools_ArgTable& cmdline)
+{
+  Standard_Integer i = 0;
+
+  myargv = new char * [argcount];
+
+  while(i < argcount)
+    {
+      if(cmdline [i])
+       myargv[i] = strdup(cmdline [i]);
+      else
+       myargv[i] = NULL;
+      i++;
+    }
+}
+
+//=======================================================================
+//function : SetTimeout
+//purpose  : 
+//=======================================================================
+void WOKUnix_Process::SetTimeout(const Standard_Integer atimeout)
+{
+  mytimeout = atimeout;
+}
+
+//=======================================================================
+//function : Launch
+//purpose  : launches subprocess (uses fork+exec)
+//=======================================================================
+void WOKUnix_Process::Launch()  
+{
+  if (mylaunched) return;
+  else
+    {
+      WOKUnix_FDescr Pin;  WOKUnix_FDescr Sin;
+      WOKUnix_FDescr Pout; WOKUnix_FDescr Sout;
+      WOKUnix_FDescr Perr; WOKUnix_FDescr Serr;
+
+      /* ouverture des pipes */
+      WOKUnix_FDescr::Pipe(Pin, Sin);
+      WOKUnix_FDescr::Pipe(Sout, Pout);
+
+      switch(mymode)
+       {
+       case WOKUnix_POPEN_MIX_OUT_ERR: 
+         break;
+       case WOKUnix_POPEN_OUT_ERR:
+         WOKUnix_FDescr::Pipe(Serr, Perr);
+         break;
+       default:
+         Standard_ProgramError::Raise("WOKUnix_Process::Launch : Unknown mode");
+       }
+  
+      WOKUnix_FDescr Stdin(0);  WOKUnix_FDescr Stdout(1);  WOKUnix_FDescr Stderr(2);
+  
+      /* on cree le processus fils */
+      mychildpid = fork();
+  
+      if(mychildpid < 0)
+       {
+         Standard_ProgramError::Raise("WOKUnix_Process::Launch : Could not fork");
+       }
+  
+      switch(mychildpid)
+       {
+       case 0:
+         /* dans le fils */  
+         /* fermeture des pipes inutiles */
+         /* redirection de stdin, stdout, stderr */
+       
+         /* redirection stdin */
+         Stdin.Close();Sin.Dup();  Stdin = WOKUnix_FDescr(0);  Sin.Close(); Pin.Close();
+         Stdin.SetUnBuffered();
+         /* redirection stdout */
+         Stdout.Close();Sout.Dup();Stdout = WOKUnix_FDescr(1);  Sout.Close(); Pout.Close();
+         Stdout.SetUnBuffered();
+         switch(mymode)
+           {
+           case  WOKUnix_POPEN_MIX_OUT_ERR: 
+             /* redirection stderr */
+             Stderr.Close(); Stdout.Dup();
+             break;
+           case  WOKUnix_POPEN_OUT_ERR: 
+             /* redirection stderr */
+             Stderr.Close();     Sout.Dup(); Stdout = WOKUnix_FDescr(2);Sout.Close();Pout.Close();
+             Stderr.SetUnBuffered();
+             break;
+           }
+      
+         /* exec de la commande */
+         if(execvp(myargv[0], (char **) myargv)) 
+           {
+             perror("execvp");
+             exit(1);
+           }
+         break;
+       default:
+         /* dans le pere */
+      
+         /* fermeture des pipes inutiles */
+         /* ouverture des fstream su le processus fils */
+         Sin.Close();  
+         Pin.SetUnBuffered();
+         Pin.SetNonBlock();
+         myinput=Pin;
+      
+         Sout.Close(); Pout.SetUnBuffered();
+         switch(mymode)
+           {
+           case  WOKUnix_POPEN_MIX_OUT_ERR: 
+             myoutput = new WOKUnix_MixedOutput(Pout, mybuffermode);
+             break;
+           case  WOKUnix_POPEN_OUT_ERR: 
+             Serr.Close(); Perr.SetUnBuffered();
+             myoutput = new WOKUnix_OutErrOutput(Pout, Perr, mybuffermode);
+             break;
+           }
+         break;
+       }
+
+      WOK_TRACE {
+       VerboseMsg("WOK_PROCESS") << "WOKUnix_Process::Launch" << "Process " << mychildpid << " launched" << endm;
+      }
+
+      mylaunched = Standard_True;
+      return;
+    }
+}
+
+//=======================================================================
+//function : IsLaunched
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Process::IsLaunched() const
+{
+  return mylaunched;
+}
+
+//=======================================================================
+//function : Pid
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_Process::Pid() const
+{
+  return mychildpid;
+}
+
+//=======================================================================
+//function : Output
+//purpose  : 
+//=======================================================================
+Handle(WOKUnix_ProcessOutput)& WOKUnix_Process::Output() 
+{
+  return myoutput;
+}
+
+//=======================================================================
+//function : Timeout
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_Process::Timeout() const
+{
+  return mytimeout;
+}
+
+
+//=======================================================================
+//function : Select
+//purpose  : select() on the output of subprocess
+//=======================================================================
+void WOKUnix_Process::Select(Standard_Integer& afdmax, WOKUnix_Timeval& atimeout,  WOKUnix_FDSet& aset) const 
+{
+  myoutput->Select(afdmax, atimeout, aset);
+}
+
+//=======================================================================
+//function : Acquit
+//purpose  : select() acquitment
+//=======================================================================
+void WOKUnix_Process::Acquit(const Standard_Integer selectstatus, const WOKUnix_FDSet& aset) const 
+{
+  myoutput->Acquit(selectstatus, aset);
+}
+
+//=======================================================================
+//function : SelectAndAcquit
+//purpose  : selects and acquit
+//=======================================================================
+void WOKUnix_Process::SelectAndAcquit() const 
+{
+  WOKUnix_FDSet readfds;
+  WOKUnix_Timeval s_timeout;
+  Standard_Integer selectstatus;
+  Standard_Integer fdmax = 0;
+
+
+  FD_ZERO(&readfds);
+
+  s_timeout.tv_sec = mytimeout;
+
+  myoutput->Select(fdmax, s_timeout, readfds);
+  
+  if((selectstatus=select(fdmax, (WOKUnix_FDSet_CAST)&readfds, NULL, NULL , &s_timeout)) < 0)
+    {
+      perror("select");
+      return ;
+    }
+  myoutput->Acquit(selectstatus, readfds);
+  return ;
+}
+
+//=======================================================================
+//function : Send
+//purpose  : 
+//=======================================================================
+void WOKUnix_Process::Send(const Handle(TCollection_HAsciiString)& astring) 
+{
+  Standard_Integer nbwritten, nbwrite;
+  Standard_CString ptr = astring->ToCString();
+
+  WOK_TRACE {
+    VerboseMsg("WOK_PROCESS") << "WOKUnix_Process::Send" 
+                             << "Writing : " << astring->ToCString() << "to file id : " << myinput.FileNo() << endm;
+  }
+
+  if(!IsLaunched())
+    {
+      ErrorMsg << "WOKUnix_Process::Send" << "Trying to perform send to dead or unlaunched process" << endm;
+      Standard_ProgramError::Raise("WOKUnix_Process::Send");
+    }
+
+  nbwritten=0;
+  
+  while(nbwritten!=astring->Length())
+    {
+      while((nbwrite = write(myinput.FileNo(), ptr, astring->Length()-nbwritten)) == -1)
+       {
+         // write failed ... is 
+         if(errno == EAGAIN)
+           {
+             // le write aurait ete bloquant : Acquit 
+             // if(Select(shell, NULL)) return 1;
+             // il faut laisser le temps au temps 
+             
+             WOK_TRACE {
+               VerboseMsg("WOK_PROCESS") << "WOKUnix_Process::Send" 
+                                         << "Write failed : Acquit output" << endm;
+             }
+
+             SelectAndAcquit();
+             sleep(1);
+           }
+         else
+           {
+             // write failed 
+             perror("shell input:");
+             OSD_OSDError::Raise("Process::Send : Write to process failed\n");
+           }
+       }
+      ptr += nbwrite;
+      nbwritten += nbwrite;
+    }
+  return;
+}
+
+//=======================================================================
+//function : Kill
+//purpose  : 
+//=======================================================================
+void WOKUnix_Process::Kill() 
+{
+  if(mylaunched == Standard_True)
+    {
+      kill(mychildpid, SIGTERM);
+      
+      if(myinput.FileNo() >= 0) myinput.Close();
+      myoutput->Close();
+      
+      mylaunched = Standard_False;
+    }
+}
+
+//=======================================================================
+//function : Destroy
+//purpose  : 
+//=======================================================================
+void WOKUnix_Process::Destroy()
+{
+ Kill();
+ delete myargv;
+}
diff --git a/src/WOKUnix/WOKUnix_ProcessManager.cdl b/src/WOKUnix/WOKUnix_ProcessManager.cdl
new file mode 100755 (executable)
index 0000000..e1dbde7
--- /dev/null
@@ -0,0 +1,41 @@
+-- File:       WOKUnix_ProcessManager.cdl
+-- Created:    Tue Jun  6 14:02:25 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+class ProcessManager from WOKUnix
+uses
+    Process from WOKUnix,
+    SequenceOfProcess from WOKUnix
+is
+    
+    Arm(myclass);
+
+    UnArm(myclass);
+
+    Processes(myclass) returns SequenceOfProcess from WOKUnix is  private;
+    ---C++: return  &
+
+    InteruptHandler(myclass);
+    
+    ChildDeathHandler(myclass);
+    
+    PipeHandler(myclass);
+
+    KillAll(myclass);
+
+    SetCriticalPid(myclass; apid : Integer);
+    
+    AddProcess(myclass; aprocess : Process from WOKUnix) is private;
+     
+    RemoveProcess(myclass; aprocess : Process from WOKUnix) is private;
+    
+    WaitProcess(myclass; aprocess : Process from WOKUnix) is private;
+
+friends
+
+    class Process      from WOKUnix,
+    class ShellManager from WOKUnix
+    
+end;
diff --git a/src/WOKUnix/WOKUnix_ProcessManager.cxx b/src/WOKUnix/WOKUnix_ProcessManager.cxx
new file mode 100755 (executable)
index 0000000..ade5501
--- /dev/null
@@ -0,0 +1,197 @@
+
+#include <sys/wait.h>
+
+#include <OSD_SIGINT.hxx>
+
+#include <WOKUnix_Signal.hxx>
+
+#include <WOKUnix_ProcessManager.ixx>
+
+#include <Standard_ProgramError.hxx>
+
+#include <WOKTools_Messages.hxx>
+
+static Standard_Integer CriticPid = 0;
+
+//=======================================================================
+//function : Arm
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::Arm()
+{
+  WOKUnix_Signal::Arm(WOKUnix_SIGINT,   (WOKUnix_SigHandler) WOKUnix_ProcessManager::InteruptHandler);
+  WOKUnix_Signal::Arm(WOKUnix_SIGCHILD, (WOKUnix_SigHandler) WOKUnix_ProcessManager::ChildDeathHandler);
+  WOKUnix_Signal::Arm(WOKUnix_SIGPIPE,  (WOKUnix_SigHandler) WOKUnix_ProcessManager::PipeHandler);
+}
+
+
+//=======================================================================
+//function : UnArm
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::UnArm()
+{
+  WOKUnix_Signal::Arm(WOKUnix_SIGINT,   (WOKUnix_SigHandler) NULL);
+  WOKUnix_Signal::Arm(WOKUnix_SIGCHILD, (WOKUnix_SigHandler) NULL);
+  WOKUnix_Signal::Arm(WOKUnix_SIGPIPE,  (WOKUnix_SigHandler) NULL);
+}
+
+//=======================================================================
+//function : Processes
+//purpose  : 
+//=======================================================================
+WOKUnix_SequenceOfProcess  &WOKUnix_ProcessManager::Processes()
+{
+  static WOKUnix_SequenceOfProcess processes;
+  
+  return processes;
+}
+
+//=======================================================================
+//function : InteruptHandler
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::InteruptHandler()
+{
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_ProcessManager::InteruptHandler" 
+                           << "Interupt Signal Launched !!" << endm;
+#endif
+
+  WOKUnix_ProcessManager::KillAll();
+  OSD_SIGINT::Raise("SIGINT 'interrupt' detected.");
+  return;
+}
+
+//=======================================================================
+//function : ChildDeathHandler
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::ChildDeathHandler()
+{
+  int  pid, status;
+
+  pid  = wait(&status);
+
+  if(pid == CriticPid)
+    {
+      ErrorMsg << "WOKUnix_ProcessManager::ChildDeathHandler"
+              << "Child " << pid << " died" << endm;
+      Standard_ProgramError::Raise("unexpected child shell death");
+    }
+
+  for(Standard_Integer ind = 1; ind <= Processes().Length(); ind ++)
+    {
+      if(Processes().Value(ind)->Pid() == pid)
+       {
+#ifdef WOK_VERBOSE
+         VerboseMsg("WOK_PROCESS") << "WOKUnix_ProcessManager::ChildDeathHandler"
+                                   << "Process " << pid << " died" << endm;
+#endif
+         Processes().Value(ind)->Kill();
+         Processes().Remove(ind);
+         return;
+       }
+    }
+  return;
+}
+
+//=======================================================================
+//function : PipeHandler
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::PipeHandler()
+{
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_ProcessManager::PipeHandler" << "SIGPIPE received" << endm;
+#endif
+  return;
+}
+
+//=======================================================================
+//function : KillAll
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::KillAll()
+{
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_ProcessManager::PipeHandler" << "Killing all sub proccesses" << endm;
+#endif
+
+  for(Standard_Integer ind = 1; ind <= Processes().Length(); ind ++)
+    {
+#ifdef WOK_VERBOSE
+      VerboseMsg("WOK_PROCESS") << "WOKUnix_ProcessManager::KillAll"
+                               << "Process " << Processes().Value(ind)->Pid() << " requested to die (interrupt)" << endm;
+#endif
+      Processes().Value(ind)->Kill();
+    }
+  Processes().Clear();
+}
+
+//=======================================================================
+//function : SetCriticPid
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::SetCriticalPid(const Standard_Integer pid)
+{
+  CriticPid = pid;
+}
+
+//=======================================================================
+//function : AddProcess
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::AddProcess(const Handle(WOKUnix_Process)& aprocess)
+{
+  Processes().Append(aprocess);
+}
+
+//=======================================================================
+//function : RemoveProcess
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::RemoveProcess(const Handle(WOKUnix_Process)& aprocess)
+{
+  
+  for(Standard_Integer ind = 1; ind <= Processes().Length(); ind ++)
+    {
+      if(Processes().Value(ind)->Pid() == aprocess->Pid())
+       {
+         Processes().Remove(ind);
+         break;
+       }
+    }
+}
+
+//=======================================================================
+//function : WaitProcess
+//purpose  : 
+//=======================================================================
+void WOKUnix_ProcessManager::WaitProcess(const Handle(WOKUnix_Process)& aprocess)
+{
+  Standard_Integer status, pid;
+  // ignore SIGCHILD for a while
+  WOKUnix_Signal::Arm(WOKUnix_SIGCHILD, (WOKUnix_SigHandler)NULL);
+
+  
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_ProcessManager::WaitProcess"
+                           << "Waiting for process " << aprocess->Pid() << " to die" << endm;
+#endif
+  pid = waitpid(aprocess->Pid(), &status, 0);
+
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_ProcessManager::WaitProcess"
+                           << "Process " << aprocess->Pid() << " died" << endm;
+#endif
+
+  if(pid == aprocess->Pid()) 
+    {
+      WOKUnix_ProcessManager::RemoveProcess(aprocess);
+    }
+
+  WOKUnix_Signal::Arm(WOKUnix_SIGCHILD, (WOKUnix_SigHandler) WOKUnix_ProcessManager::ChildDeathHandler);
+  return;
+}
diff --git a/src/WOKUnix/WOKUnix_ProcessOutput.cdl b/src/WOKUnix/WOKUnix_ProcessOutput.cdl
new file mode 100755 (executable)
index 0000000..ecedd59
--- /dev/null
@@ -0,0 +1,27 @@
+-- File:       WOKUnix_ProcessOutput.cdl
+-- Created:    Thu May  4 16:23:17 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+private deferred class ProcessOutput from WOKUnix
+inherits TShared from MMgt
+uses
+    Timeval from WOKUnix,
+    FDSet   from WOKUnix,
+    FDescr  from WOKUnix,
+    HSequenceOfHAsciiString from TColStd
+is
+    Initialize;
+    
+    Clear(me) is deferred;
+    Echo(me)   returns HSequenceOfHAsciiString from TColStd is deferred;
+    Errors(me) returns HSequenceOfHAsciiString from TColStd is deferred;
+
+    Select(me; afdmax : out Integer; atimeout : in out Timeval from WOKUnix; aset : out FDSet from WOKUnix) is deferred;
+    
+    Acquit(me; selectstatus : Integer; aset : FDSet from WOKUnix) is deferred;
+
+    Close(me:mutable) is deferred;
+
+end;
diff --git a/src/WOKUnix/WOKUnix_ProcessOutput.cxx b/src/WOKUnix/WOKUnix_ProcessOutput.cxx
new file mode 100755 (executable)
index 0000000..307ab20
--- /dev/null
@@ -0,0 +1,6 @@
+#include <WOKUnix_ProcessOutput.ixx>
+
+ WOKUnix_ProcessOutput::WOKUnix_ProcessOutput()
+{
+}
+
diff --git a/src/WOKUnix/WOKUnix_RegExp.cdl b/src/WOKUnix/WOKUnix_RegExp.cdl
new file mode 100755 (executable)
index 0000000..55d5ff4
--- /dev/null
@@ -0,0 +1,88 @@
+-- File:       WOKUnix_RegExp.cdl
+-- Created:    Fri Aug  2 09:43:37 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+class RegExp from WOKUnix inherits TShared from MMgt
+
+    ---Purpose: provides regular expression matching and searching
+
+ uses
+  RESyntax     from WOKUnix,
+  HAsciiString from TCollection
+
+ raises
+  ProgramError from Standard
+
+ is
+  Create returns mutable RegExp from WOKUnix;
+    ---Purpose: creates a class instance
+
+  Create (
+   aPattern  : HAsciiString from TCollection;
+   aSyntax   : RESyntax     from WOKUnix = WOKUnix_RESyntaxAWK;
+   aTransTbl : Address      from Standard = NULL;
+   aTblLen   : Integer      from Standard = 0
+  ) returns mutable RegExp  from WOKUnix
+    raises ProgramError     from Standard;
+       ---Purpose: creates a class instance with given pattern that denotes a set
+       --          of strings. Defines a translation table <aTransTbl> and
+       --          its length <aTblLen> to perform character translation.
+       --          Supply NULL for <aTransTbl> and zero value for <aTblLen>
+       --          if no translation necessary. It is possible to set
+       --          syntax of the regular expression by meaning <aSyntax>
+       --          parameter.
+       ---Warning: raises if syntax of the regular expression given is incorrect
+
+  Destroy ( me : mutable );
+       ---Purpose: destroys all resources attached to the class instanse
+       ---C++:     alias ~
+    
+  SetPattern (
+   me        : mutable;
+   aPattern  : HAsciiString from TCollection;
+   aSyntax   : RESyntax     from WOKUnix = WOKUnix_RESyntaxAWK;
+   aTransTbl : Address      from Standard = NULL;
+   aTblLen   : Integer      from Standard = 0
+  ) raises ProgramError from Standard;
+       ---Purpose: sets a new match pattern and possibly a new pattern syntax
+       ---Warning: raises if the syntax given is incorrect
+
+  Search (
+   me;
+   aString   : HAsciiString from TCollection;
+   aStartPos : Integer      from Standard = 1
+  ) returns Integer      from Standard
+    raises  ProgramError from Standard;
+       ---Purpose: searches a sub-string in the <aString> which matches
+        --          the specified pattern starting at index <aStartPos>.
+        --          Returns an index of the match position on success.
+        --          Returns -1 if no match was found.
+       --          Returns -2 if error was occur.
+       ---Warning: raises if no search pattern was set
+
+  Match (
+   me;
+   aString   : HAsciiString from TCollection;
+   aStartPos : Integer      from Standard = 1;
+   aStopPos  : Integer      from Standard = 1
+  ) returns Integer     from Standard
+    raises ProgramError from Standard;
+       ---Purpose: match the pattern given against the string <aString>
+       --          starting at index <aStartPos>. Do not consider matching
+       --          past the position <aStopPos>.
+       --          Returns the length of the string matched on success.
+       --          Returns -1 if no match was found.
+       --          Returns -2 if error was occur.
+       ---Warning: raises if no search pattern was set
+
+ fields
+  
+  myBuffer : Address from Standard;     
+  myAlloc  : Boolean from Standard;
+                           
+end RegExp;
diff --git a/src/WOKUnix/WOKUnix_RegExp.cxx b/src/WOKUnix/WOKUnix_RegExp.cxx
new file mode 100755 (executable)
index 0000000..6573d66
--- /dev/null
@@ -0,0 +1,160 @@
+
+#include <WOKUnix_RegExp.ixx>
+
+#include <WOKUnix_regexp.h>
+
+#define BUFFER (  ( PRE_PATTERN_BUFFER )myBuffer  )
+#define RAISE( str ) Standard_ProgramError :: Raise (   _TEXT(  ( str )  )   );
+
+static _TCHAR errBuff[ 128 ];
+
+#ifndef WNT
+# define _tcscpy strcpy
+# define _tcscat strcat
+#endif //WNT
+
+WOKUnix_RegExp :: WOKUnix_RegExp () {
+
+ myBuffer = NULL;
+
+}  // end constructor ( 1 )
+
+WOKUnix_RegExp :: WOKUnix_RegExp (
+                    const Handle( TCollection_HAsciiString )& aPattern,
+                    const WOKUnix_RESyntax                   aSyntax,
+                    const Standard_Address                    aTransTbl,
+                    const Standard_Integer                    aTblLen
+                   ) {
+
+ SetPattern ( aPattern, aSyntax, aTransTbl, aTblLen );
+
+}  // end constructro ( 2 )
+
+void WOKUnix_RegExp :: Destroy () {
+
+ if ( myBuffer != NULL ) {
+
+  if ( myAlloc )
+
+   delete [] BUFFER -> translate;
+  if (  BUFFER -> fastmap   != NULL  ) delete [] BUFFER -> fastmap;
+  if (  BUFFER -> buffer    != NULL  ) free (  ( void* )( BUFFER -> buffer )  );
+  
+  delete myBuffer;
+
+  myBuffer = NULL;
+ }  // end if
+
+}  // end WOKUnix_RegExp :: Destroy
+
+void WOKUnix_RegExp :: SetPattern (
+                         const Handle( TCollection_HAsciiString )& aPattern,
+                         const WOKUnix_RESyntax aSyntax,
+                         const Standard_Address aTransTbl,
+                         const Standard_Integer aTblLen
+                        ) {
+
+ int     syntax;
+ _TCHAR* errMsg;
+
+ Destroy ();
+
+ myBuffer = new RE_PATTERN_BUFFER;
+ memset (  BUFFER, 0, sizeof ( RE_PATTERN_BUFFER )  );
+ BUFFER -> fastmap = new _TCHAR[ ( 1 << BYTEWIDTH ) ];
+
+ if ( aTransTbl != NULL ) {
+
+  if ( aTblLen != 0 ) {
+
+   BUFFER -> translate = new Standard_Character[ aTblLen ];
+   memcpy ( BUFFER -> translate, aTransTbl, aTblLen );
+   myAlloc = Standard_True;
+
+  } else {
+   BUFFER -> translate = ( _TCHAR* )aTransTbl;
+   myAlloc = Standard_False;
+
+  }  // end else
+ }  // end if
+
+ switch ( aSyntax ) {
+  case WOKUnix_RESyntaxAWK:
+   syntax = RE_SYNTAX_AWK;
+  break;
+
+  case WOKUnix_RESyntaxEGREP:
+   syntax = RE_SYNTAX_EGREP;
+  break;
+
+  case WOKUnix_RESyntaxGREP:
+   syntax = RE_SYNTAX_GREP;
+  break;
+
+  case WOKUnix_RESyntaxEMACS:
+   syntax = RE_SYNTAX_EMACS;
+  break;
+
+  default:
+   RAISE( "WOKUnix_RegExp (): incorrect parameter value ( syntax )" );
+ }  // end switch
+
+ re_set_syntax ( syntax );
+
+ errMsg = re_compile_pattern (
+           aPattern -> ToCString (), aPattern -> Length (), BUFFER
+          );
+
+ if ( errMsg != NULL ) {
+  _tcscpy (  errBuff, _TEXT( "WOKUnix_RegExp (): error parsing specified pattern - " )  );
+  _tcscat (  errBuff, errMsg );
+
+  Standard_ProgramError :: Raise ( errBuff );
+ }  // end if
+
+ re_compile_fastmap ( BUFFER );
+
+}  // end WOKUnix_RegExp :: SetPattern
+
+Standard_Integer WOKUnix_RegExp :: Search (
+                                     const Handle( TCollection_HAsciiString )& aString,
+                                     const Standard_Integer                    aStartPos
+                                    ) const {
+
+ Standard_Integer retVal;
+ retVal = re_search (
+           BUFFER, aString -> ToCString (), aString -> Length (),
+           aStartPos - 1, 0, NULL
+          );
+
+ if ( retVal >= 0 ) ++retVal;
+
+ return retVal;
+
+}  // end WOKUnix_RegExp :: Search
+
+Standard_Integer WOKUnix_RegExp :: Match (
+                                     const Handle( TCollection_HAsciiString )& aString,
+                                     const Standard_Integer aStartPos,
+                                     const Standard_Integer aStopPos
+                                    ) const {
+
+ Standard_Integer len = aString -> Length ();
+
+ return re_match_2 (
+         BUFFER, NULL, 0,
+         ( _TUCHAR* )(  aString -> ToCString ()  ), len,
+         aStartPos - 1, NULL, ( aStopPos == 1 ? len : aStopPos - 1 )
+        );
+
+}  // end WOKUnix_RegExp :: Match
+
diff --git a/src/WOKUnix/WOKUnix_RemoteShell.cdl b/src/WOKUnix/WOKUnix_RemoteShell.cdl
new file mode 100755 (executable)
index 0000000..955839d
--- /dev/null
@@ -0,0 +1,45 @@
+-- File:       WOKUnix_RemoteShell.cdl
+-- Created:    Mon Nov  6 14:29:52 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+class RemoteShell from WOKUnix 
+inherits Shell from WOKUnix
+
+       ---Purpose: 
+
+uses
+    ShellMode        from WOKUnix,
+    PopenOutputMode  from WOKUnix,
+    PopenBufferMode  from WOKUnix,
+    HAsciiString     from TCollection,
+    AsciiString      from TCollection
+is
+
+
+    Create(ahost    : HAsciiString     from TCollection;
+          apath    : AsciiString      from TCollection;
+          amode    : ShellMode        from WOKUnix = WOKUnix_AsynchronousMode; 
+          outmode  : PopenOutputMode  from WOKUnix = WOKUnix_POPEN_MIX_OUT_ERR;
+          bufmode  : PopenBufferMode  from WOKUnix = WOKUnix_POPEN_BUFFERED)  
+       returns mutable RemoteShell from WOKUnix;
+
+    SyncAndStatus(me : mutable) returns Integer is redefined;
+    
+    SetUser(me:mutable; auser : HAsciiString from TCollection);
+    User(me) returns HAsciiString from TCollection;
+    
+    SetPassword(me:mutable; auser : HAsciiString from TCollection);
+    Password(me) returns HAsciiString from TCollection;
+    
+fields
+
+    myuser     : HAsciiString from TCollection;
+    mypassword : HAsciiString from TCollection;
+
+end RemoteShell;
+
+
+
diff --git a/src/WOKUnix/WOKUnix_RemoteShell.cxx b/src/WOKUnix/WOKUnix_RemoteShell.cxx
new file mode 100755 (executable)
index 0000000..ddd5c0c
--- /dev/null
@@ -0,0 +1,160 @@
+// File:       WOKUnix_RemoteShell.cxx
+// Created:    Mon Nov  6 14:55:55 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+#ifdef IRIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <bstring.h>
+#include <sys/time.h>
+#endif
+
+#ifdef HPUX
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#endif
+#include <Standard_ProgramError.hxx>
+#include <WOKTools_Messages.hxx>
+#include <OSD_Protection.hxx>
+
+#include <WOKUnix_ShellStatus.hxx>
+#include <WOKUnix_ProcessManager.hxx>
+#include <TCollection_HAsciiString.hxx>
+#include <TCollection_AsciiString.hxx>
+
+#include <WOKUnix_RemoteShell.ixx>
+
+
+//=======================================================================
+//function : WOKUnix_RemoteShell
+//purpose  : 
+//=======================================================================
+ WOKUnix_RemoteShell::WOKUnix_RemoteShell(const Handle(TCollection_HAsciiString)& ahost, 
+                                           const TCollection_AsciiString & apath,
+                                           const WOKUnix_ShellMode amode, 
+                                           const WOKUnix_PopenOutputMode outmode, 
+                                           const WOKUnix_PopenBufferMode bufmode) 
+: WOKUnix_Shell(apath, amode, outmode, bufmode)
+{ 
+
+  char *rshellargv[]={"rsh" , ahost->ToCString(), "exec","/bin/csh", "-fs", NULL};
+  SetCommand(6,rshellargv);
+}
+
+//=======================================================================
+//function : SyncAndStatus
+//purpose  : 
+//=======================================================================
+ Standard_Integer WOKUnix_RemoteShell::SyncAndStatus()
+{
+  WOKUnix_FDSet readfds;
+  WOKUnix_Timeval s_timeout;
+  Standard_Integer selectstatus;
+  Standard_Integer fdmax;
+
+
+  if(!IsLaunched())
+    {
+      ErrorMsg << "WOKUnix_RemoteShell::SyncAndStatus()" << "Trying to perform sync to dead or unlaunched process" << endm;
+      Standard_ProgramError::Raise("WOKUnix_RemoteShell::SyncAndStatus()");
+    }
+
+  // beginning of the critical section
+  WOKUnix_ProcessManager::SetCriticalPid(Pid());
+
+  while(1)
+    {
+      FD_ZERO(&readfds);
+      
+      //FD_SET(mystatus->No(), &readfds);
+
+      fdmax = 0;
+
+      // wait a moment ....
+      Select(fdmax, s_timeout, readfds);
+
+      
+      s_timeout.tv_sec  = 0;
+      s_timeout.tv_usec = 100000;
+
+      if((selectstatus=select(fdmax, (WOKUnix_FDSet_CAST)&readfds, NULL, NULL ,&s_timeout ) < 0))
+       {
+         perror("select");
+         WOKUnix_ProcessManager::SetCriticalPid(-1);
+         return 1;
+       }
+
+      mystatus->StatusFile().Close();
+      mystatus->StatusFile().Open(OSD_ReadWrite, OSD_Protection());
+      mystatus->StatusFile().Flush();
+
+      if(mystatus->StatusFile().GetSize()) // le status file n'est pas vide
+       {
+         //mystatus->StatusFile().Flush();
+
+         //lire le status file
+         mystatus->GetRemote();
+
+         Acquit(selectstatus, readfds); // Process output acquit
+
+         // vider le status file
+         mystatus->StatusFile().EmptyAndOpen();
+         
+         //end of the critical section
+         WOKUnix_ProcessManager::SetCriticalPid(-1);
+         return mystatus->Status();
+       }
+
+      Acquit(selectstatus, readfds); // Process output acquit
+
+    }
+}
+
+//=======================================================================
+//function : SetUser
+//purpose  : 
+//=======================================================================
+void WOKUnix_RemoteShell::SetUser(const Handle(TCollection_HAsciiString)& auser)
+{
+  myuser = auser;
+}
+
+//=======================================================================
+//function : User
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_RemoteShell::User() const 
+{
+  return myuser;
+}
+
+//=======================================================================
+//function : SetPassword
+//purpose  : 
+//=======================================================================
+void WOKUnix_RemoteShell::SetPassword(const Handle(TCollection_HAsciiString)& apassword)
+{
+  mypassword = apassword;
+}
+
+//=======================================================================
+//function : Password
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_RemoteShell::Password() const 
+{
+  return mypassword;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/WOKUnix/WOKUnix_Shell.cdl b/src/WOKUnix/WOKUnix_Shell.cdl
new file mode 100755 (executable)
index 0000000..140d2f5
--- /dev/null
@@ -0,0 +1,81 @@
+-- File:       WOKUnix_Shell.cdl
+-- Created:    Thu Jun  8 17:31:30 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+class Shell from WOKUnix 
+inherits Process from WOKUnix
+
+       ---Purpose: 
+
+uses
+    Path                    from WOKUnix,
+    ShellMode               from WOKUnix,
+    ShellStatus             from WOKUnix,
+    PopenOutputMode         from WOKUnix,
+    PopenBufferMode         from WOKUnix,
+    HAsciiString            from TCollection,
+    AsciiString            from TCollection,    
+    HSequenceOfHAsciiString from TColStd
+    
+is
+    Create(amode    : ShellMode        from WOKUnix = WOKUnix_AsynchronousMode; 
+          outmode  : PopenOutputMode  from WOKUnix = WOKUnix_POPEN_MIX_OUT_ERR;
+          bufmode  : PopenBufferMode  from WOKUnix = WOKUnix_POPEN_BUFFERED) 
+       returns mutable Shell from WOKUnix; 
+       
+    Create(apath    : AsciiString      from TCollection;
+          amode    : ShellMode        from WOKUnix = WOKUnix_AsynchronousMode; 
+          outmode  : PopenOutputMode  from WOKUnix = WOKUnix_POPEN_MIX_OUT_ERR;
+          bufmode  : PopenBufferMode  from WOKUnix = WOKUnix_POPEN_BUFFERED) 
+       returns mutable Shell from WOKUnix; 
+  
+    SetEcho(me:mutable);
+    UnsetEcho(me:mutable);
+    IsEchoed(me)
+       returns Boolean from Standard;
+    
+    Echo(me; astr : HAsciiString from TCollection);
+    
+    Lock(me:mutable);
+    UnLock(me:mutable);
+    IsLocked(me)
+       returns Boolean from Standard;
+     
+    LogInFile(me:mutable; apath : Path from WOKUnix);
+    NoLog(me:mutable);
+    LogFile(me)
+       returns Path from WOKUnix;
+    
+    Log(me; astr : HAsciiString from TCollection);
+
+    SetSynchronous(me:mutable);
+    SetASynchronous(me:mutable);
+    
+    SyncAndStatus(me : mutable) returns Integer is virtual;
+    
+    Status(me) returns Integer;  
+
+    Errors(me : mutable) returns HSequenceOfHAsciiString from TColStd;
+    ClearOutput(me : mutable);
+    
+    Send(me : mutable; astring : HAsciiString from TCollection) is redefined; 
+    
+    Execute(me:mutable; astring : HAsciiString from TCollection) returns Integer from Standard; 
+    Execute(me:mutable; somestrings : HSequenceOfHAsciiString from TColStd)  returns Integer  from  Standard;
+
+    SetHost(me:mutable; ahost : HAsciiString from TCollection);
+    Host(me) returns HAsciiString from TCollection;
+    
+fields
+
+    mystatus  : ShellStatus  from WOKUnix is protected;
+    mymode    : ShellMode    from WOKUnix;
+    myname    : HAsciiString from TCollection;
+    mylocked  : Boolean      from Standard;
+    myecho    : Boolean      from Standard;
+    mylogfile : Path         from WOKUnix;
+    myhost    : HAsciiString from TCollection;
+end Shell;
diff --git a/src/WOKUnix/WOKUnix_Shell.cxx b/src/WOKUnix/WOKUnix_Shell.cxx
new file mode 100755 (executable)
index 0000000..6e762c0
--- /dev/null
@@ -0,0 +1,440 @@
+
+#ifdef IRIX
+#include <unistd.h>
+#include <sys/types.h>
+#include <bstring.h>
+#include <sys/time.h>
+#endif
+
+#ifdef HPUX
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#endif
+
+#include <fstream.h>
+
+#include <WOKTools_Messages.hxx>
+
+#include <WOKUnix_ASyncStatus.hxx>
+#include <WOKUnix_SyncStatus.hxx>
+#include <WOKUnix_DumpScript.hxx>
+#include <WOKUnix_ProcessOutput.hxx>
+#include <WOKUnix_ProcessManager.hxx>
+
+#include <WOKUnix_Shell.ixx>
+
+#ifndef WOK_IDLE_TRIGGER
+#define WOK_IDLE_TRIGGER 1
+#endif
+
+#ifdef WOK_IDLE_TRIGGER
+#include <WOKUtils_Triggers.hxx>
+#endif
+
+static  char *ShellArgv[] = {"/bin/csh", "-f", NULL};
+
+//=======================================================================
+//function : WOKUnix_Shell
+//purpose  : 
+//=======================================================================
+WOKUnix_Shell::WOKUnix_Shell(const WOKUnix_ShellMode amode,
+                              const WOKUnix_PopenOutputMode outmode, 
+                              const WOKUnix_PopenBufferMode bufmode) 
+:  WOKUnix_Process(3, ShellArgv, outmode, bufmode, -1),  mymode(amode), myecho(Standard_False), mylocked(Standard_False)
+{
+  switch(amode)
+    {
+    case WOKUnix_SynchronousMode:
+      mystatus = new WOKUnix_SyncStatus;
+      break;
+    case WOKUnix_AsynchronousMode:
+      mystatus = new WOKUnix_ASyncStatus;
+      break;
+    case WOKUnix_DumpScriptMode:
+      mystatus = new WOKUnix_DumpScript;
+      break;
+    }
+  
+}
+
+//=======================================================================
+//function : WOKUnix_Shell
+//purpose  : 
+//=======================================================================
+WOKUnix_Shell::WOKUnix_Shell(const TCollection_AsciiString& apath,
+                              const WOKUnix_ShellMode       amode,
+                              const WOKUnix_PopenOutputMode outmode, 
+                              const WOKUnix_PopenBufferMode bufmode) 
+:  WOKUnix_Process(3, ShellArgv, outmode, bufmode, -1),  mymode(amode), myecho(Standard_False), mylocked(Standard_False)
+{
+  switch(amode)
+    {
+    case WOKUnix_SynchronousMode:
+      mystatus = new WOKUnix_SyncStatus(apath);
+      break;
+    case WOKUnix_AsynchronousMode:
+      mystatus = new WOKUnix_ASyncStatus(apath);
+      break;
+    case WOKUnix_DumpScriptMode:
+      mystatus = new WOKUnix_DumpScript(apath);
+      break;
+    }
+  
+}
+
+
+//=======================================================================
+//function : SetSynchronous
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::SetSynchronous()
+{
+  // si deja en synchrone : ne rien faire
+  if(mymode ==  WOKUnix_SynchronousMode) return;
+  if(IsLaunched() == Standard_True) 
+    {
+      // i have to forget what has be done before
+      mystatus->Reset(this);
+
+      // le nouveau est un synchrone
+      mystatus = new WOKUnix_SyncStatus();
+      mystatus->Reset(this);
+    }
+  mymode = WOKUnix_SynchronousMode;
+}
+
+//=======================================================================
+//function : SetEcho
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::SetEcho() 
+{
+  myecho = Standard_True;
+}
+
+//=======================================================================
+//function : UnsetEcho
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::UnsetEcho() 
+{
+  myecho = Standard_False;
+}
+
+//=======================================================================
+//function : IsEchoed
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Shell::IsEchoed() const
+{
+  return myecho;
+}
+
+//=======================================================================
+//function : Echo
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::Echo(const Handle(TCollection_HAsciiString)& astr) const
+{
+  if(myecho)
+    {
+      WOKTools_Info shellinfo = InfoMsg;
+      shellinfo.Init();
+      shellinfo.DontPrintHeader();
+      shellinfo.DontPrintContext();
+      
+      shellinfo << "WOKUnix_Shell::Echo" << astr << endm;
+    }
+}
+
+//=======================================================================
+//function : Lock
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::Lock()
+{
+  mylocked = Standard_True;
+}
+
+//=======================================================================
+//function : UnLock
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::UnLock()
+{
+  mylocked = Standard_False;
+}
+
+//=======================================================================
+//function : IsLocked
+//purpose  : 
+//=======================================================================
+Standard_Boolean WOKUnix_Shell::IsLocked() const
+{ 
+  return mylocked;
+}
+
+//=======================================================================
+//function : LogInFile
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::LogInFile(const Handle(WOKUnix_Path)& apath)
+{
+  if(apath.IsNull()) return;
+
+  if(!apath->Exists())
+    {
+      apath->CreateFile(Standard_True);
+      if(!apath->Exists()) return;
+    }
+
+  mylogfile = apath;
+}
+
+//=======================================================================
+//function : NoLog
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::NoLog()
+{
+  mylogfile.Nullify();
+}
+
+//=======================================================================
+//function : LogFile
+//purpose  : 
+//=======================================================================
+Handle(WOKUnix_Path) WOKUnix_Shell::LogFile() const
+{
+  return mylogfile;
+}
+
+//=======================================================================
+//function : Log
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::Log(const Handle(TCollection_HAsciiString)& astr) const
+{
+  if(!mylogfile.IsNull())
+    {
+      ofstream logfile(mylogfile->Name()->ToCString(), ios::app);
+      if(!logfile.bad())
+       {
+         logfile << astr->ToCString();
+         logfile.close();
+       }
+    }
+}
+
+//=======================================================================
+//function : SetASynchronous
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::SetASynchronous()
+{
+  // si deja en synchrone : ne rien faire
+  if(mymode == WOKUnix_AsynchronousMode) return;
+  if(IsLaunched() == Standard_True) 
+    {
+      // i have to forget what has be done before
+      mystatus->Reset(this);
+
+      // le nouveau est un asynchrone
+      mystatus = new WOKUnix_ASyncStatus();
+      mystatus->Reset(this);
+    }
+  mymode = WOKUnix_AsynchronousMode;
+}
+
+//=======================================================================
+//function : SyncAndStatus
+//purpose  : 
+//=======================================================================
+ Standard_Integer WOKUnix_Shell::SyncAndStatus()
+{
+  WOKUnix_FDSet readfds;
+  WOKUnix_Timeval s_timeout;
+  WOKUnix_Timeval* p_timeout;
+  Standard_Integer selectstatus;
+  Standard_Integer fdmax;
+  
+  WOKUnix_ProcessManager::SetCriticalPid(Pid());
+
+  WOK_TRACE {
+    VerboseMsg("WOK_PROCESS") << "WOKUnix_Shell::SyncAndStatus"
+                             << "Entering SyncAndStatus" << endm;
+  }
+
+  while(1)
+    {
+      FD_ZERO(&readfds);
+
+      FD_SET(mystatus->No(), &readfds);
+
+      fdmax = mystatus->No();
+
+      if(Timeout() > 0)
+       {
+         s_timeout.tv_sec = Timeout();
+         p_timeout = &s_timeout;
+       }
+      else
+       {
+         p_timeout = NULL;
+       }
+      
+
+      Select(fdmax, s_timeout, readfds); // process output Select
+      
+#ifdef WOK_VERBOSE
+      if(VerboseMsg("WOK_PROCESS").IsSet()) {
+       Standard_Integer i;
+
+       if(p_timeout) {
+         VerboseMsg("WOK_PROCESS") << "WOKUnix_Shell::SyncAndStatus"
+           << "Entering select : timeout : " << (const int) s_timeout.tv_sec << "s " << (const int) s_timeout.tv_usec << "ms" << endm;
+       } else {
+         VerboseMsg("WOK_PROCESS") << "WOKUnix_Shell::SyncAndStatus"
+           << "Entering select : infinite wait" << endm;
+       }
+       
+
+       for(i=0; i<fdmax; i++) {
+         if(FD_ISSET(i,&readfds)) {
+           VerboseMsg("WOK_PROCESS") << "WOKUnix_Shell::SyncAndStatus" << "FD " << (const int) i << " is setted" << endm;
+         }
+       }
+      }
+
+#endif
+
+      if((selectstatus=select(fdmax, (WOKUnix_FDSet_CAST) &readfds, NULL, NULL , &s_timeout)) < 0)
+       {
+         perror("select");
+         WOKUnix_ProcessManager::SetCriticalPid(-1);
+         return 1;
+       }
+      
+#ifdef WOK_IDLE_TRIGGER
+      
+      WOKUtils_Trigger idle;
+
+      idle("WOK_DoWhenIdle") << endt;
+
+#endif
+      
+      if(FD_ISSET(mystatus->No(), &readfds))
+       {
+         // le status pipe est en select ---> ca m'interesse avant tout 
+         mystatus->Get();
+         Acquit(selectstatus, readfds); // Process output acquit
+         WOKUnix_ProcessManager::SetCriticalPid(-1);
+         return mystatus->Status();
+       }
+
+#ifdef WOK_VERBOSE
+      VerboseMsg("WOK_PROCESS") << "WOKUnix_Shell::SyncAndStatus"
+       << "Aquit output" << endm;
+#endif
+
+      Acquit(selectstatus, readfds); // Process output acquit
+    }
+}
+
+//=======================================================================
+//function : Status
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_Shell::Status() const 
+{
+  return mystatus->Status();
+}
+
+//=======================================================================
+//function : Errors
+//purpose  : 
+//=======================================================================
+Handle(TColStd_HSequenceOfHAsciiString) WOKUnix_Shell::Errors()
+{
+  return Output()->Errors();
+}
+
+//=======================================================================
+//function : ClearOutput
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::ClearOutput() 
+{
+  Output()->Clear();
+}
+
+//=======================================================================
+//function : Send
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::Send(const Handle(TCollection_HAsciiString)& astring)
+{
+  Log(astring);
+  Echo(astring);
+  WOKUnix_Process::Send(astring);
+  return;
+}
+
+//=======================================================================
+//function : Execute
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_Shell::Execute(const Handle(TCollection_HAsciiString)& astring)
+{
+  Log(astring);
+  Echo(astring);
+  WOKUnix_Process::Send(astring);
+  mystatus->EndCmd(this);
+  mystatus->Sync(this);
+  return mystatus->Status();
+}
+
+
+//=======================================================================
+//function : Execute
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_Shell::Execute(const Handle(TColStd_HSequenceOfHAsciiString)& somestrings)
+{
+  Handle(TCollection_HAsciiString) astring;
+  
+  for(Standard_Integer i = 1; i <= somestrings->Length(); i++)
+    {
+      astring = somestrings->Value(i);
+
+      Log(astring);
+      Echo(astring);
+
+      WOKUnix_Process::Send(astring);
+      mystatus->EndCmd(this);
+    }
+  mystatus->Sync(this);
+  return mystatus->Status();
+}
+
+//=======================================================================
+//function : SetHost
+//purpose  : 
+//=======================================================================
+void WOKUnix_Shell::SetHost(const Handle(TCollection_HAsciiString)& ahost)
+{
+
+  myhost = ahost;
+}
+
+//=======================================================================
+//function : Host
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_Shell::Host() const 
+{
+  return myhost;
+}
+
+
diff --git a/src/WOKUnix/WOKUnix_ShellManager.cdl b/src/WOKUnix/WOKUnix_ShellManager.cdl
new file mode 100755 (executable)
index 0000000..c08317b
--- /dev/null
@@ -0,0 +1,36 @@
+-- File:       WOKUnix_ShellManager.cdl
+-- Created:    Thu Apr  4 22:55:35 1996
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1996
+
+
+class ShellManager from WOKUnix 
+
+       ---Purpose: 
+
+uses
+
+    Shell from WOKUnix,
+    RemoteShell from WOKUnix,
+    HAsciiString from TCollection,
+    AsciiString from TCollection
+    
+is
+
+    GetShell(myclass)
+    ---Purpose: returns one unlocked shell of processes list    
+       returns Shell from WOKUnix;
+    
+    GetShell(myclass; apid : Integer from Standard)
+    ---Purpose: get a precise shell     
+       returns Shell from WOKUnix;
+
+    GetRemoteShell(myclass; 
+                  ahost : HAsciiString from TCollection;
+                  apath : AsciiString from TCollection)
+    ---Purpose: returns a host's unlocked remote shell of processes list  
+       returns RemoteShell from WOKUnix;
+
+end ShellManager;
+
diff --git a/src/WOKUnix/WOKUnix_ShellManager.cxx b/src/WOKUnix/WOKUnix_ShellManager.cxx
new file mode 100755 (executable)
index 0000000..c1d4fa0
--- /dev/null
@@ -0,0 +1,100 @@
+// File:       WOKUnix_ShellManager.cxx
+// Created:    Thu Apr  4 23:21:02 1996
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+#include <WOKUnix_ShellManager.ixx>
+
+#include <WOKUnix_ProcessManager.hxx>
+#include <WOKUnix_SequenceOfProcess.hxx>
+#include <WOKUnix_Shell.hxx>
+#include <WOKUnix_RemoteShell.hxx>
+
+//=======================================================================
+//function : GetShell
+//purpose  : 
+//=======================================================================
+Handle(WOKUnix_Shell) WOKUnix_ShellManager::GetShell()
+{
+  Standard_Integer i;
+  WOKUnix_SequenceOfProcess& procseq = WOKUnix_ProcessManager::Processes();
+  Handle(WOKUnix_Shell) ashell;
+
+  for(i=1; i<=procseq.Length(); i++)
+    {
+      ashell = Handle(WOKUnix_Shell)::DownCast(procseq.Value(i));
+      if(!ashell.IsNull()) 
+       {
+
+         if(!ashell->IsLocked())
+           {
+             return ashell;
+           }
+       }
+    }
+  ashell = new WOKUnix_Shell;
+
+  return ashell;
+}
+
+//=======================================================================
+//function : GetShell
+//purpose  : 
+//=======================================================================
+Handle(WOKUnix_Shell) WOKUnix_ShellManager::GetShell(const Standard_Integer apid)
+{
+  Standard_Integer i;
+  WOKUnix_SequenceOfProcess& procseq = WOKUnix_ProcessManager::Processes();
+  Handle(WOKUnix_Shell) ashell;
+  
+  for(i=1; i<=procseq.Length(); i++)
+    {
+      if(procseq.Value(i)->IsKind(STANDARD_TYPE(WOKUnix_Shell)))
+       {
+         ashell = Handle(WOKUnix_Shell)::DownCast(procseq.Value(i));
+         
+         if(!ashell->Pid() == apid)
+           {
+             return ashell;
+           }
+         else ashell.Nullify();
+       }
+    }
+  return ashell;
+}
+
+//=======================================================================
+//function : GetRemoteShell
+//purpose  : 
+//=======================================================================
+Handle(WOKUnix_RemoteShell) WOKUnix_ShellManager::GetRemoteShell(const Handle(TCollection_HAsciiString) & ahost,
+                                                                  const TCollection_AsciiString & apath)
+{
+  Standard_Integer i;
+  WOKUnix_SequenceOfProcess& procseq = WOKUnix_ProcessManager::Processes();
+  Handle(WOKUnix_RemoteShell) aremoteshell;
+
+  for(i=1; i<=procseq.Length(); i++)
+    {
+      if(procseq.Value(i)->IsKind(STANDARD_TYPE(WOKUnix_RemoteShell)))
+       {
+       
+         aremoteshell = Handle(WOKUnix_RemoteShell)::DownCast(procseq.Value(i));
+
+         if( (!aremoteshell->IsLocked()) && (!strcmp(aremoteshell->Host()->ToCString(),ahost->ToCString()) ))
+           {
+             return aremoteshell;
+           }
+       }
+    }
+  aremoteshell = new WOKUnix_RemoteShell(ahost,apath);
+
+  return aremoteshell;
+}
+
+
+
+
+
+
+
diff --git a/src/WOKUnix/WOKUnix_ShellStatus.cdl b/src/WOKUnix/WOKUnix_ShellStatus.cdl
new file mode 100755 (executable)
index 0000000..4e7f3cf
--- /dev/null
@@ -0,0 +1,55 @@
+
+-- -- File:    WOKUnix_ShellStatus.cdl
+-- Created:    Thu Jun  8 18:22:21 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private deferred class ShellStatus from WOKUnix 
+inherits TShared from MMgt
+       ---Purpose: 
+
+uses
+    FDescr from WOKUnix,
+    Shell  from WOKUnix,
+    HAsciiString from TCollection,
+    AsciiString from TCollection,
+    File from OSD
+    
+raises
+
+    ProgramError from Standard
+is
+    Initialize;
+    Initialize(apath : AsciiString from TCollection); 
+    
+    StatusFile(me:mutable) returns FDescr from WOKUnix;
+    ---C++:return &
+
+
+    No(me)   returns Integer is static;
+    Name(me) returns HAsciiString from TCollection is static;
+       
+    Status(me) returns Integer is static;
+       
+    EndCmd(me:mutable; ashell : Shell from WOKUnix) is deferred;
+    Sync(me:mutable;   ashell : Shell from WOKUnix) is deferred;
+    Reset(me:mutable;  ashell : Shell from WOKUnix) is deferred;
+    
+    Get(me:mutable)  returns Integer raises ProgramError from Standard is virtual;
+    GetRemote(me:mutable)  returns Integer raises ProgramError from Standard is virtual;
+
+    Destroy(me:mutable)
+    ---C++: alias ~
+     is virtual;
+    
+fields
+    mystatus : Integer is protected;
+    myfile   : FDescr from WOKUnix;
+    
+end ShellStatus;
+
+
+
+
diff --git a/src/WOKUnix/WOKUnix_ShellStatus.cxx b/src/WOKUnix/WOKUnix_ShellStatus.cxx
new file mode 100755 (executable)
index 0000000..48fb864
--- /dev/null
@@ -0,0 +1,131 @@
+
+#include <WOKUnix_ShellStatus.ixx>
+
+#include <TCollection_AsciiString.hxx>
+
+//=======================================================================
+//function : WOKUnix_ShellStatus
+//purpose  : 
+//=======================================================================
+ WOKUnix_ShellStatus::WOKUnix_ShellStatus()
+{
+  myfile.BuildNamedPipe();
+}
+
+//=======================================================================
+//function : WOKUnix_ShellStatus
+//purpose  : 
+//=======================================================================
+ WOKUnix_ShellStatus::WOKUnix_ShellStatus(const TCollection_AsciiString& apath)
+{
+  myfile.BuildTemporary(apath);
+}
+
+//=======================================================================
+//function : StatusFile
+//purpose   :
+//=======================================================================
+ WOKUnix_FDescr &  WOKUnix_ShellStatus::StatusFile() 
+{
+  return myfile;
+}
+
+//=======================================================================
+//function : No
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_ShellStatus::No() const 
+{
+  return myfile.FileNo();
+}
+
+
+//=======================================================================
+//function : Name
+//purpose  : 
+//=======================================================================
+Handle(TCollection_HAsciiString) WOKUnix_ShellStatus::Name() const 
+{
+  return myfile.Name();
+}
+
+//=======================================================================
+//function : Status
+//purpose  : 
+//=======================================================================
+Standard_Integer WOKUnix_ShellStatus::Status() const 
+{
+  return mystatus;
+}
+
+//=======================================================================
+//function : Get
+//purpose  : Reads on a pipe the status of a shell command 
+//=======================================================================
+Standard_Integer WOKUnix_ShellStatus::Get()
+{
+  myfile.Flush();
+
+  Standard_Integer nbtoread = myfile.GetNbToRead();
+  if(nbtoread == 0) 
+    {
+      Standard_ProgramError::Raise("ShellStatus::Get : Nothing to read on status pipe\n");
+      return 1;
+    }
+
+  TCollection_AsciiString buf;
+  
+  myfile.Read(buf, nbtoread);
+  if(nbtoread != buf.Length())
+    {
+      perror(Name()->ToCString());
+      Standard_ProgramError::Raise("ShellStatus::Get : Could not read from status pipe\n");
+      return 1;
+    }
+  buf.Trunc(nbtoread);
+  mystatus = buf.IntegerValue();
+
+  return mystatus;
+}
+//=======================================================================
+//function : GetRemote
+//purpose  : Reads in a file the status of a remote shell command
+//=======================================================================
+Standard_Integer WOKUnix_ShellStatus::GetRemote()
+{
+  myfile.Flush();
+
+  Standard_Integer nbtoread = myfile.GetSize();
+  if(nbtoread == 0) 
+    {
+      Standard_ProgramError::Raise("ShellStatus::GetRemote : Nothing to read on status file\n");
+      return 1;
+    }
+
+  TCollection_AsciiString buf;
+  
+  myfile.Read(buf, nbtoread);
+  if(nbtoread != buf.Length())
+    {
+      perror(Name()->ToCString());
+      Standard_ProgramError::Raise("ShellStatus::GetRemote : Could not read from status file\n");
+      return 1;
+    }
+  buf.Trunc(nbtoread);
+  mystatus = buf.IntegerValue();
+
+  return mystatus;
+}
+
+//=======================================================================
+//function : Destroy
+//purpose  : 
+//=======================================================================
+void WOKUnix_ShellStatus::Destroy()
+{
+  myfile.Remove();
+}
+
+
+
+
diff --git a/src/WOKUnix/WOKUnix_SigHandler.hxx b/src/WOKUnix/WOKUnix_SigHandler.hxx
new file mode 100755 (executable)
index 0000000..aa8dfa3
--- /dev/null
@@ -0,0 +1,39 @@
+// File:       WOKUnix_SigHandler.hxx
+// Created:    Wed May 24 18:35:36 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_SigHandler_HeaderFile
+#define WOKUnix_SigHandler_HeaderFile
+
+
+#ifdef SUN
+#include <floatingpoint.h>
+#endif
+
+#ifdef SOLARIS
+#include <floatingpoint.h>
+#include <sys/machsig.h>
+
+#define FPE_FLTDIV_TRAP FPE_FLTDIV 
+#define FPE_INTDIV_TRAP FPE_INTDIV 
+#define FPE_FLTOVF_TRAP FPE_FLTOVF 
+#define FPE_INTOVF_TRAP FPE_INTOVF
+#define FPE_FLTUND_TRAP FPE_FLTUND 
+extern "C" {int ieee_handler(char *,char *, sigfpe_handler_type&);};
+#endif
+
+
+#ifdef IRIX
+#include <sys/siginfo.h>
+#define FPE_FLTDIV_TRAP FPE_FLTDIV 
+#define FPE_INTDIV_TRAP FPE_INTDIV 
+#define FPE_FLTOVF_TRAP FPE_FLTOVF 
+#define FPE_INTOVF_TRAP FPE_INTOVF
+#define FPE_FLTUND_TRAP FPE_FLTUND 
+#endif 
+
+typedef void (* WOKUnix_SigHandler) (int);
+
+#endif
diff --git a/src/WOKUnix/WOKUnix_Signal.cdl b/src/WOKUnix/WOKUnix_Signal.cdl
new file mode 100755 (executable)
index 0000000..aed35ea
--- /dev/null
@@ -0,0 +1,26 @@
+-- File:       WOKUnix_Signal.cdl
+-- Created:    Wed May 24 17:32:41 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+class Signal from WOKUnix
+uses
+    Signals from WOKUnix,
+    SigHandler from WOKUnix
+is
+    Create                               returns Signal from WOKUnix;
+    Create(asig : Signals from WOKUnix) returns Signal from WOKUnix;
+    
+    Set(me : in out; asig : Signals from WOKUnix);
+    
+    Arm(me : in out; ahandler : SigHandler from WOKUnix);
+    Arm(myclass; asig : Signals from WOKUnix; ahandler : SigHandler from WOKUnix);
+
+    GetSig(myclass; asig : Signals from WOKUnix) returns Integer from Standard is  private;
+
+fields
+    mysig   : Signals from WOKUnix;
+    isarmed : Boolean from Standard;
+end;
+
diff --git a/src/WOKUnix/WOKUnix_Signal.cxx b/src/WOKUnix/WOKUnix_Signal.cxx
new file mode 100755 (executable)
index 0000000..752375b
--- /dev/null
@@ -0,0 +1,120 @@
+
+#include <WOKUnix_Signal.ixx>
+
+
+#include <stdlib.h>
+#include <signal.h>
+
+#ifndef HPUX
+#include <siginfo.h>
+#endif
+
+//=======================================================================
+//function : WOKUnix_Signal
+//purpose  : 
+//=======================================================================
+ WOKUnix_Signal::WOKUnix_Signal()
+{
+  isarmed = Standard_False;
+}
+
+//=======================================================================
+//function : WOKUnix_Signal
+//purpose  : 
+//=======================================================================
+ WOKUnix_Signal::WOKUnix_Signal(const WOKUnix_Signals asig)
+{
+  mysig = asig;
+  isarmed = Standard_False;
+}
+
+//=======================================================================
+//function : Set
+//purpose  : 
+//=======================================================================
+void WOKUnix_Signal::Set(const WOKUnix_Signals asig)
+{
+  mysig = asig;
+  isarmed = Standard_False;
+}
+
+//=======================================================================
+//function : Arm
+//purpose  : 
+//=======================================================================
+void WOKUnix_Signal::Arm(const WOKUnix_SigHandler& ahandler)
+{
+  struct sigaction act, oact;
+  int              stat;
+
+  //==== Save the old Signale Handler, and set the new one ===================
+
+  if(ahandler == NULL)
+    {
+      act.sa_handler =  (WOKUnix_SigHandler) SIG_DFL;
+    }
+  else
+    {
+      act.sa_handler =  (WOKUnix_SigHandler) ahandler;
+    }
+#ifdef SOLARIS
+  act.sa_mask.__sigbits[0]    = 0;
+  act.sa_mask.__sigbits[1]    = 0;
+  act.sa_mask.__sigbits[2]    = 0;
+  act.sa_mask.__sigbits[3]    = 0;
+  act.sa_flags                = SA_RESTART;
+#elif HPUX
+  act.sa_mask.sigset[0]    = 0;
+  act.sa_mask.sigset[1]    = 0;
+  act.sa_mask.sigset[2]    = 0;
+  act.sa_mask.sigset[3]    = 0;
+  act.sa_mask.sigset[4]    = 0;
+  act.sa_mask.sigset[5]    = 0;
+  act.sa_mask.sigset[6]    = 0;
+  act.sa_mask.sigset[7]    = 0;
+  act.sa_flags   = 0;
+#elif IRIX
+  act.sa_mask.__sigbits[0]      = 0;
+  act.sa_mask.__sigbits[1]      = 0;
+  act.sa_mask.__sigbits[2]      = 0;
+  act.sa_mask.__sigbits[3]      = 0;
+  act.sa_flags             = 0;
+#else
+  act.sa_mask    = 0;
+  act.sa_flags   = 0;
+#endif
+
+  //==== Always detected the signal "SIGFPE" =================================
+  stat = sigaction(WOKUnix_Signal::GetSig(mysig),&act,&oact);   // ...... floating point exception 
+  if (stat) {
+     cerr << "sigaction does not work !!! KO " << endl;
+     perror("sigaction ");
+  }
+}
+
+//=======================================================================
+//function : Arm
+//purpose  : 
+//=======================================================================
+void WOKUnix_Signal::Arm(const WOKUnix_Signals asig, const WOKUnix_SigHandler& ahandler)
+{
+  WOKUnix_Signal thesig(asig);
+
+  thesig.Arm(ahandler);
+}
+
+int WOKUnix_Signal::GetSig(const WOKUnix_Signals asig) 
+{
+  switch (asig)
+    {
+    case WOKUnix_SIGPIPE  : return SIGPIPE;
+    case WOKUnix_SIGHUP   : return SIGHUP;
+    case WOKUnix_SIGINT   : return SIGINT;
+    case WOKUnix_SIGQUIT  : return SIGQUIT;
+    case WOKUnix_SIGILL   : return SIGILL;
+    case WOKUnix_SIGKILL  : return SIGKILL;
+    case WOKUnix_SIGBUS   : return SIGBUS;
+    case WOKUnix_SIGSEGV  : return SIGSEGV;
+    case WOKUnix_SIGCHILD : return SIGCLD;
+    }
+}
diff --git a/src/WOKUnix/WOKUnix_StatBuf.hxx b/src/WOKUnix/WOKUnix_StatBuf.hxx
new file mode 100755 (executable)
index 0000000..4270909
--- /dev/null
@@ -0,0 +1,22 @@
+// File:       WOKUnix_StatBuf.hxx
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_StatBuf_HeaderFile
+#define WOKUnix_StatBuf_HeaderFile
+
+#ifndef WNT 
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+typedef struct stat WOKUnix_StatBuf;
+
+#else
+
+#error "Type StatBuf does not exist on WNT"
+
+#endif
+
+#endif
diff --git a/src/WOKUnix/WOKUnix_SyncStatus.cdl b/src/WOKUnix/WOKUnix_SyncStatus.cdl
new file mode 100755 (executable)
index 0000000..db882f5
--- /dev/null
@@ -0,0 +1,24 @@
+-- File:       WOKUnix_SyncStatus.cdl
+-- Created:    Thu Jun  8 20:07:25 1995
+-- Author:     Jean GAUTIER
+--             <jga@cobrax>
+---Copyright:   Matra Datavision 1995
+
+
+private class SyncStatus from WOKUnix 
+inherits ShellStatus from WOKUnix
+       ---Purpose: 
+
+uses
+    AsciiString from TCollection,
+    Shell  from WOKUnix
+is
+    Create returns mutable SyncStatus from WOKUnix;
+    Create(apath    : AsciiString      from TCollection)
+                        returns mutable SyncStatus from WOKUnix;
+    EndCmd(me:mutable; ashell : Shell from WOKUnix) is redefined;
+    Sync(me:mutable;   ashell : Shell from WOKUnix) is redefined;
+    Reset(me:mutable;  ashell : Shell from WOKUnix) is redefined;
+    
+end SyncStatus;
diff --git a/src/WOKUnix/WOKUnix_SyncStatus.cxx b/src/WOKUnix/WOKUnix_SyncStatus.cxx
new file mode 100755 (executable)
index 0000000..1cf1dfd
--- /dev/null
@@ -0,0 +1,67 @@
+
+
+#include <WOKTools_Messages.hxx>
+
+#include <TCollection_HAsciiString.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <WOKUnix_SyncStatus.ixx>
+
+
+//=======================================================================
+//function : WOKUnix_SyncStatus
+//purpose  : 
+//=======================================================================
+ WOKUnix_SyncStatus::WOKUnix_SyncStatus()
+{
+}
+
+//=======================================================================
+//function : WOKUnix_SyncStatus
+//purpose  : 
+//=======================================================================
+ WOKUnix_SyncStatus::WOKUnix_SyncStatus(const TCollection_AsciiString & apath)
+                     :WOKUnix_ShellStatus(apath)
+{
+}
+
+//=======================================================================
+//function : EndCmd
+//purpose  : 
+//=======================================================================
+void WOKUnix_SyncStatus::EndCmd(const Handle(WOKUnix_Shell)& ashell)
+{
+#ifdef USE_SYNCHRO
+  Handle(TCollection_HAsciiString) abuf = new TCollection_HAsciiString("\n/tmp/synchro ");
+  abuf->AssignCat(Name());
+  abuf->AssignCat(" $status\n");
+#else
+  Handle(TCollection_HAsciiString) abuf = new TCollection_HAsciiString("\necho $status > ");
+  abuf->AssignCat(Name());
+  abuf->AssignCat("\n");
+#endif
+  ashell->WOKUnix_Process::Send(abuf);
+
+  mystatus = ashell->SyncAndStatus();
+
+#ifdef WOK_VERBOSE
+  VerboseMsg("WOK_PROCESS") << "WOKUnix_SyncStatus::EndCmd" << "Command ended with status : " << mystatus << endm;
+#endif
+}
+
+//=======================================================================
+//function : Sync
+//purpose  : 
+//=======================================================================
+void WOKUnix_SyncStatus::Sync(const Handle(WOKUnix_Shell)& )
+{
+  
+}
+
+//=======================================================================
+//function : Reset
+//purpose  : 
+//=======================================================================
+void WOKUnix_SyncStatus::Reset(const Handle(WOKUnix_Shell)& )
+{
+}
+
diff --git a/src/WOKUnix/WOKUnix_TimeStat.hxx b/src/WOKUnix/WOKUnix_TimeStat.hxx
new file mode 100755 (executable)
index 0000000..64f1c10
--- /dev/null
@@ -0,0 +1,18 @@
+// File:       WOKUnix_TimeStat.hxx
+// Created:    Mon Jun 26 15:46:11 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_TimeStat_HeaderFile
+#define WOKUnix_TimeStat_HeaderFile
+
+#include <sys/types.h>
+
+
+// time time in return of stat system call 
+
+typedef time_t WOKUnix_TimeStat;
+
+
+#endif
diff --git a/src/WOKUnix/WOKUnix_Timeval.hxx b/src/WOKUnix/WOKUnix_Timeval.hxx
new file mode 100755 (executable)
index 0000000..6e32290
--- /dev/null
@@ -0,0 +1,14 @@
+// File:       WOKUnix_Timeval.hxx
+// Created:    Tue May  9 15:24:00 1995
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKUnix_Timeval_HeaderFile
+#define WOKUnix_Timeval_HeaderFile
+
+#include <sys/time.h>
+
+typedef struct timeval WOKUnix_Timeval ;
+
+#endif
diff --git a/src/WOKUnix/WOKUnix_WOKSteps.edl b/src/WOKUnix/WOKUnix_WOKSteps.edl
new file mode 100755 (executable)
index 0000000..81e7c50
--- /dev/null
@@ -0,0 +1,21 @@
+-- File:       WOKUnix_WOKSteps.edl
+-- Author:     Jean GAUTIER
+-- History:    Tue Aug 12 17:19:49 1997        Jean GAUTIER    Creation
+-- Copyright:   Matra Datavision 1997
+
+@ifnotdefined ( %WOKUnix_WOKSteps_EDL) then
+@set %WOKUnix_WOKSteps_EDL = "";
+
+@if ( %Station == "wnt" ) then
+
+       @set %WOKSteps_ObjGroup = "obj.nocompil";
+       @set %WOKSteps_LibGroup = "";
+
+       @set %WOKSteps_obj_nocompil = "WOKStep_Compile";
+       
+       @set %WOKSteps_toolkit_ListWith  = "obj.nocompil";
+       @set %WOKSteps_toolkit_LinksWith = "obj.nocompil";
+
+@endif;
+
+@endif;
diff --git a/src/WOKUnix/WOKUnix_regexp.h b/src/WOKUnix/WOKUnix_regexp.h
new file mode 100755 (executable)
index 0000000..a025578
--- /dev/null
@@ -0,0 +1,283 @@
+
+#ifndef __REGEXP_H
+# define __REGEXP_H
+/***/
+# ifdef WNT
+#  ifdef UNICODE_API
+#   ifndef _UNICODE
+#    define _UNICODE
+#   endif  /* _UNICODE */
+#  endif  /* UNICODE_API */
+/***/
+#  ifndef _INC_TCHAR
+#   include <tchar.h>
+#  endif  /* _INC_TCHAR */
+/***/
+#  ifndef _INC_STDLIB
+#   include <stdlib.h>
+#  endif  /* _INC_STDLIB */
+/***/
+#  ifndef _INC_MALLOC
+#   include <malloc.h>
+#  endif  /* _INC_MALLOC */
+/***/
+#  ifndef _INC_LIMITS
+#   include <limits.h>
+#  endif  /* _INC_LIMITS */
+#  ifndef _INC_STRING
+#   include <string.h>
+#  endif  /* _INC_STRING */
+/***/
+#  ifdef __WOKUnix_DLL
+#   define REGEXP_API __declspec( dllexport )
+#  else
+#   define REGEXP_API __declspec( dllimport )
+#  endif  /* __OSD_DLL */
+# else
+#  define _TEXT( arg ) arg
+#  define REGEXP_API
+#  include <stdio.h>
+#  include <limits.h>
+typedef char          _TCHAR;
+typedef char          TCHAR;
+typedef unsigned char _TUCHAR;
+# endif  /* WNT */
+/***/
+/******************************************************************************/
+/* Definitions for data structures callers pass the regex library.            */
+/*   Copyright (C) 1985 Free Software Foundation, Inc.                        */
+/*                                                                            */
+/*    This program is free software; you can redistribute it and/or modify    */
+/*    it under the terms of the GNU General Public License as published by    */
+/*    the Free Software Foundation; either version 1, or (at your option)     */
+/*    any later version.                                                      */
+/*                                                                            */
+/*    This program is distributed in the hope that it will be useful,         */
+/*    but WITHOUT ANY WARRANTY; without even the implied warranty of          */
+/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
+/*    GNU General Public License for more details.                            */
+/*                                                                            */
+/*    You should have received a copy of the GNU General Public License       */
+/*    along with this program; if not, write to the Free Software             */
+/*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
+/*                                                                            */
+/* In other words, you are welcome to use, share and improve this program.    */
+/* You are forbidden to forbid anyone else to use, share and improve          */
+/* what you give them.   Help stamp out software-hoarding!                    */
+/******************************************************************************/
+/******************************************************************************/
+/* Modified by EUG ( MATRA Datavision ) for Windows NT and UNICODE ( 1996 )   */
+/******************************************************************************/
+/***/
+/******************************************************************************/
+/* Define number of parens for which we record the beginnings and ends.       */
+/* This affects how much space the `struct re_registers' type takes up.       */
+/******************************************************************************/
+#ifndef RE_NREGS
+# define RE_NREGS 10
+#endif
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* width of a byte in bits                                                    */
+/*                                                                            */
+/******************************************************************************/
+/***/
+#ifdef _UNICODE
+# define BYTEWIDTH (  CHAR_BIT * sizeof ( TCHAR )  )
+# define CHAR_MASK USHRT_MAX
+#else
+# define BYTEWIDTH CHAR_BIT
+# define CHAR_MASK UCHAR_MAX
+#endif  /* _UNICODE */
+/***/
+/******************************************************************************/
+/* These bits are used in the obscure_syntax variable to choose among         */
+/* alternative regexp syntaxes.                                               */
+/*                                                                            */
+/* 1 means plain parentheses serve as grouping, and backslash                 */
+/*   parentheses are needed for literal searching.                            */
+/* 0 means backslash-parentheses are grouping, and plain parentheses          */
+/*   are for literal searching.                                               */
+/******************************************************************************/
+#define RE_NO_BK_PARENS 1
+/******************************************************************************/
+/* 1 means plain | serves as the "or"-operator, and \| is a literal.          */
+/* 0 means \| serves as the "or"-operator, and | is a literal.                */
+/******************************************************************************/
+#define RE_NO_BK_VBAR 2
+/******************************************************************************/
+/* 0 means plain + or ? serves as an operator, and \+, \? are literals.       */
+/*   1 means \+, \? are operators and plain +, ? are literals.                */
+/******************************************************************************/
+#define RE_BK_PLUS_QM 4
+/******************************************************************************/
+/* 1 means | binds tighter than ^ or $.                                       */
+/* 0 means the contrary.                                                      */
+/******************************************************************************/
+#define RE_TIGHT_VBAR 8
+/******************************************************************************/
+/* 1 means treat \n as an _OR operator                                        */
+/* 0 means treat it as a normal character                                     */
+/******************************************************************************/
+#define RE_NEWLINE_OR 16
+/******************************************************************************/
+/* 0 means that a special characters (such as *, ^, and $) always have        */
+/*   their special meaning regardless of the surrounding context.             */
+/* 1 means that special characters may act as normal characters in some       */
+/*   contexts.  Specifically, this applies to:                                */
+/*      ^ - only special at the beginning, or after ( or |                        */
+/*  $ - only special at the end, or before ) or |                             */
+/*  *, +, ? - only special when not after the beginning, (, or |              */
+/******************************************************************************/
+#define RE_CONTEXT_INDEP_OPS 32
+/******************************************************************************/
+/* Now define combinations of bits for the standard possibilities.            */
+/******************************************************************************/
+#define RE_SYNTAX_AWK   ( RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS )
+#define RE_SYNTAX_EGREP ( RE_SYNTAX_AWK   | RE_NEWLINE_OR                        )
+#define RE_SYNTAX_GREP  ( RE_BK_PLUS_QM   | RE_NEWLINE_OR                        )
+#define RE_SYNTAX_EMACS 0
+/******************************************************************************/
+/* This data structure is used to represent a compiled pattern.               */
+/******************************************************************************/
+typedef struct re_pattern_buffer {
+
+ _TCHAR* buffer;    /* Space holding the compiled pattern commands.           */
+ int     allocated; /* Size of space that  buffer  points to                  */
+ int     used;      /* Length of portion of buffer actually occupied          */
+ _TCHAR* fastmap;   /* Pointer to fastmap, if any, or zero if none.           */
+                    /* re_search uses the fastmap, if there is one,           */
+                    /* to skip quickly over totally implausible characters    */
+ _TCHAR* translate;     /* Translate table to apply to all characters before      */
+                    /* comparing. Or zero for no translation. The translation */
+                    /* is applied to a pattern when it is compiled and to     */
+                    /* data when it is matched.                               */
+ _TCHAR  fastmap_accurate; /* Set to zero when a new pattern is stored,       */
+                                       /* set to one when the fastmap is updated from it. */
+ _TCHAR  can_be_null; /* Set to one by compiling fastmap                      */
+                                  /* if this pattern might match the null string.         */
+                                  /* It does not necessarily match the null string        */
+                                  /* in that case, but if this is zero, it cannot.        */
+                                  /* 2 as value means can match null string               */
+                                  /* but at end of range or before a character            */
+                                  /* listed in the fastmap.                               */
+
+} RE_PATTERN_BUFFER, *PRE_PATTERN_BUFFER;
+/******************************************************************************/
+/* Structure to store "register" contents data in.                            */
+/*   Pass the address of such a structure as an argument to re_match, etc.,   */
+/*   if you want this information back.                                       */
+/*                                                                            */
+/*   start[i] and end[i] record the string matched by \( ... \) grouping i,   */
+/*   for i from 1 to RE_NREGS - 1.                                            */
+/*   start[0] and end[0] record the entire string matched.                    */
+/******************************************************************************/
+typedef struct re_registers {
+
+ int start[ RE_NREGS ];
+ int end[ RE_NREGS ];
+  
+} RE_REGISTERS, *PRE_REGISTERS;
+/******************************************************************************/
+/* These are the command codes that appear in compiled regular expressions,   */
+/* one per byte. Some command codes are followed by argument bytes.           */
+/* A command code can specify any interpretation whatever for its arguments.  */
+/* Zero-bytes may appear in the compiled regular expression.                  */
+/******************************************************************************/
+enum regexpcode {
+
+ unused,
+ exactn,        /* followed by one byte giving n, and then by n literal bytes */
+ begline,       /* fails unless at beginning of line                          */
+ endline,       /* fails unless at end of line                                */
+ jump,          /* followed by two bytes giving relative address to jump to   */
+ on_failure_jump, /* followed by two bytes giving relative address of place   */
+                  /* to resume at in case of failure.                         */
+ finalize_jump, /* Throw away latest failure point and then jump to address.  */
+ maybe_finalize_jump, /* Like jump but finalize if safe to do so.             */
+                      /* This is used to jump back to the beginning           */
+                      /* of a repeat.  If the command that follows            */
+                      /* this jump is clearly incompatible with the           */
+                          /* one at the beginning of the repeat, such that        */
+                      /* we can be sure that there is no use backtracking     */
+                      /* out of repetitions already completed,                */
+                      /* then we finalize.                                    */
+ dummy_failure_jump,  /* jump, and push a dummy failure point.                */
+                      /* This failure point will be thrown away               */
+                      /* if an attempt is made to use it for a failure.       */
+                      /* A + construct makes this before the first repeat.    */
+ anychar,             /* matches any one character                            */
+ charset,             /* matches any one char belonging to specified set.     */
+                      /* First following byte is # bitmap bytes.              */
+                      /* Then come bytes for a bit-map saying which chars     */
+                      /* are in.                                              */
+                      /* Bits in each byte are ordered low-bit-first.         */
+                      /* A character is in the set if its bit is 1.           */
+                      /* A character too large to have a bit in the map       */
+                      /* is automatically not in the set                      */
+ charset_not,         /* similar but match any character that is NOT one of   */
+                      /* those specified                                      */
+ start_memory,        /* starts remembering the text that is matched          */
+                      /* and stores it in a memory register.                  */
+                      /* followed by one byte containing the register number. */
+                      /* Register numbers must be in the range 0 through      */
+                      /* NREGS.                                               */
+ stop_memory,         /* stops remembering the text that is matched           */
+                      /* and stores it in a memory register.                  */
+                      /* followed by one byte containing the register number. */
+                      /* Register numbers must be in the range 0 through      */
+                      /* NREGS.                                               */
+ duplicate,           /* match a duplicate of something remembered.           */
+                              /* Followed by one byte containing the index of the     */
+                      /* memory register.                                     */
+ before_dot,          /* Succeeds if before dot                               */
+ at_dot,              /* Succeeds if at dot                                   */
+ after_dot,           /* Succeeds if after dot                                */
+ begbuf,              /* Succeeds if at beginning of buffer                   */
+ endbuf,              /* Succeeds if at end of buffer                         */
+ wordchar,            /* Matches any word-constituent character               */
+ notwordchar,         /* Matches any char that is not a word-constituent      */
+ wordbeg,             /* Succeeds if at word beginning                        */
+ wordend,             /* Succeeds if at word end                              */
+ wordbound,           /* Succeeds if at a word boundary                       */
+ notwordbound,        /* Succeeds if not at a word boundary                   */
+ syntaxspec,          /* Matches any character whose syntax is specified.     */
+                      /* followed by a byte which contains a syntax code,     */
+                      /* Sword or such like                                   */
+ notsyntaxspec        /* Matches any character whose syntax differs from the  */
+                      /* specified.                                           */
+  
+};
+/******************************************************************************/
+/* Function prototypes                                                        */
+/******************************************************************************/
+/***/
+# ifdef __cplusplus
+extern "C" {
+# endif  /* __cplusplus */
+/***/
+REGEXP_API _TCHAR* re_compile_pattern ( _TCHAR*, int, PRE_PATTERN_BUFFER );
+REGEXP_API void    re_compile_fastmap ( PRE_PATTERN_BUFFER );
+REGEXP_API int     re_search (
+                    PRE_PATTERN_BUFFER, _TCHAR*, int, int, int, PRE_REGISTERS
+                   );
+REGEXP_API int     re_search_2 (
+                    PRE_PATTERN_BUFFER, _TCHAR*, int,_TCHAR*, int, int, int,
+                    PRE_REGISTERS, int
+                   );
+REGEXP_API int     re_match (
+                    PRE_PATTERN_BUFFER, _TCHAR*, int, int, PRE_REGISTERS
+                   );
+REGEXP_API int     re_match_2 (
+                    PRE_PATTERN_BUFFER, _TUCHAR*, int, _TUCHAR*, int,
+                    int, PRE_REGISTERS, int
+                   );
+REGEXP_API int     re_set_syntax ( int );
+/***/
+# ifdef __cplusplus
+}
+# endif  /* __cplusplus */
+/***/
+/******************************************************************************/
+#endif  /* __REGEXP_H */
diff --git a/src/WOKUnix/WOKUnix_regexp_1.c b/src/WOKUnix/WOKUnix_regexp_1.c
new file mode 100755 (executable)
index 0000000..178fe4f
--- /dev/null
@@ -0,0 +1,1735 @@
+/******************************************************************************/
+/* Extended regular expression matching and search.                           */
+/* Copyright (C) 1985 Free Software Foundation, Inc.                          */
+/*                                                                            */
+/* This program is free software; you can redistribute it and/or modify       */
+/*  it under the terms of the GNU General Public License as published by      */
+/*  the Free Software Foundation; either version 1, or (at your option)       */
+/*  any later version.                                                        */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/*  GNU General Public License for more details.                              */
+/*                                                                            */
+/*  You should have received a copy of the GNU General Public License         */
+/*   along with this program; if not, write to the Free Software              */
+/*   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                */
+/*                                                                            */
+/* In other words, you are welcome to use, share and improve this program.    */
+/* You are forbidden to forbid anyone else to use, share and improve          */
+/* what you give them.   Help stamp out software-hoarding!                    */
+/******************************************************************************/
+/******************************************************************************/
+/* Modified by EUG ( MATRA Datavision ) for Windows NT and UNICODE ( 1996 )   */
+/******************************************************************************/
+/***/
+
+/* JGA : to compile on Solaris */
+
+#if !defined(HPUX) && !defined (WNT)
+#include <alloca.h>
+
+#else
+/* alloca() non disponible sur HPUX 9.07 */
+# ifdef __cplusplus
+extern "C" {
+# endif  
+void *alloca(unsigned int);
+# ifdef __cplusplus
+}
+#endif
+void *alloca(unsigned int size){return (void *)0L;}
+#endif
+
+
+#include <WOKUnix_regexp.h>
+
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Define the syntax stuff, so we can do the \<...\> things.                  */
+/*                                                                            */
+/******************************************************************************/
+/***/
+#ifndef Sword   /* must be non-zero in some of the tests below...             */
+# define Sword 1
+#endif  /* Sword */
+
+#define SYNTAX( c ) re_syntax_table[ ( c ) ]
+
+TCHAR* re_syntax_table;
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Number of failure points to allocate space for initially,                  */
+/* when matching.  If this number is exceeded, more space is allocated,       */
+/* so it is not a hard limit.                                                 */
+/*                                                                            */
+/******************************************************************************/
+/***/
+#ifndef NFAILURES
+# define NFAILURES 80
+#endif  /* NFAILURES */
+/***/
+#ifndef SIGN_EXTEND_CHAR
+# define SIGN_EXTEND_CHAR( x ) ( x )
+#endif  /* SIGN_EXTEND_CHAR */
+/***/
+static int obscure_syntax;
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Specify the precise syntax of regexp for compilation.                      */
+/* This provides for compatibility for various utilities                      */
+/* which historically have different, incompatible syntaxes.                  */
+/*                                                                            */
+/* The argument SYNTAX is a bit-mask containing the two bits                  */
+/* RE_NO_BK_PARENS and RE_NO_BK_VBAR.                                         */
+/*                                                                            */
+/******************************************************************************/
+/***/
+int re_set_syntax ( int syntax ) {
+
+ int ret;
+
+ ret = obscure_syntax;
+ obscure_syntax = syntax;
+
+ return ret;
+
+}  /* end re_set_syntax */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* re_compile_pattern takes a regular-expression string                       */
+/*  and converts it into a buffer full of byte commands for matching.         */
+/*                                                                            */
+/* PATTERN   is the address of the pattern string                             */
+/* SIZE      is the length of it.                                             */
+/* BUFP             is a  struct re_pattern_buffer *  which points to the info       */
+/*           on where to store the byte commands.                             */
+/*           This structure contains a  char *  which points to the           */
+/*           actual space, which should have been obtained with malloc.       */
+/*           re_compile_pattern may use  realloc  to grow the buffer space.   */
+/*                                                                            */
+/*  The number of bytes of commands can be found out by looking in            */
+/*  the  struct re_pattern_buffer  that bufp pointed to,                      */
+/*  after re_compile_pattern returns.                                         */
+/*                                                                            */
+/******************************************************************************/
+/***/
+#define PATPUSH( ch ) (  *b++ = ( _TCHAR )( ch )  )
+
+#define PATFETCH( c ) { if ( p == pend ) goto end_of_pattern;        \
+                        ( c ) = *( _TUCHAR* )p++;                    \
+                        if ( translate ) ( c ) = translate[ ( c ) ]; \
+                      }
+
+#define PATFETCH_RAW( c ) { if ( p == pend ) goto end_of_pattern; \
+                            ( c ) = *( _TUCHAR* )p++;             \
+                          }
+
+#define PATUNFETCH p--
+
+#define EXTEND_BUFFER { _TCHAR* old_buffer = bufp -> buffer;      \
+                        if (  bufp -> allocated == ( 1 << 16 )  ) \
+                         goto too_big;                            \
+                        bufp -> allocated *= 2;                   \
+                        if (  bufp -> allocated > ( 1 << 16 )  )  \
+                         bufp -> allocated = ( 1 << 16 );         \
+                        if (   !(  bufp -> buffer =               \
+                                    ( _TCHAR* )realloc (          \
+                                                bufp -> buffer,   \
+                                                bufp -> allocated \
+                                               )                  \
+                                )                                 \
+                        ) goto memory_exhausted;                  \
+                        c = bufp -> buffer - old_buffer;          \
+                        b += c;                                   \
+                        if ( fixup_jump ) fixup_jump += c;        \
+                        if ( laststart ) laststart += c;          \
+                        begalt += c;                              \
+                        if ( pending_exact )                      \
+                         pending_exact += ( long )c;              \
+                      }
+
+static void store_jump  ( _TCHAR*, _TCHAR, _TCHAR* );
+static void insert_jump ( _TCHAR, _TCHAR*, _TCHAR*, _TCHAR* );
+
+_TCHAR* re_compile_pattern (
+         _TCHAR* pattern, int size, PRE_PATTERN_BUFFER bufp
+        ) {
+
+ _TCHAR*  b = bufp -> buffer;
+ _TCHAR*  p = pattern;
+ _TCHAR*  pend = pattern + size;
+ _TCHAR*  p1;
+ _TUCHAR* translate = ( _TUCHAR* )bufp -> translate;
+
+ unsigned long c, c1;
+
+/* address of the count-byte of the most recently inserted "exactn" command.  */
+/*  This makes it possible to tell whether a new exact-match character        */
+/*  can be added to that command or requires a new "exactn" command.          */
+     
+ _TCHAR* pending_exact = NULL;
+
+/* address of the place where a forward-jump should go                        */
+/*  to the end of the containing expression.                                  */
+/*  Each alternative of an "or", except the last, ends with a forward-jump    */
+/*  of this sort.                                                             */
+
+ _TCHAR* fixup_jump = NULL;
+
+/* address of start of the most recently finished expression.                 */
+/*  This tells postfix * where to find the start of its operand.              */
+
+ _TCHAR* laststart = NULL;
+
+/* In processing a repeat, 1 means zero matches is allowed                    */
+
+ _TCHAR zero_times_ok;
+
+/* In processing a repeat, 1 means many matches is allowed                    */
+
+ _TCHAR many_times_ok;
+
+/* address of beginning of regexp, or inside of last \(                       */
+
+ _TCHAR* begalt = b;
+
+/* Stack of information saved by \( and restored by \).                       */
+/*   Four stack elements are pushed by each \(:                               */
+/*     First, the value of b.                                                 */
+/*     Second, the value of fixup_jump.                                       */
+/*     Third, the value of regnum.                                            */
+/*     Fourth, the value of begalt.                                           */
+
+ long  stackb[ 40 ];
+ long* stackp = stackb;
+ long* stacke = stackb + 40;
+ long* stackt;
+
+/* Counts \('s as they are encountered.  Remembered for the matching \),      */
+/*   where it becomes the "register number" to put in the stop_memory command */
+
+ int regnum = 1;
+
+ bufp -> fastmap_accurate = 0;
+
+ if ( bufp -> allocated == 0 ) {
+
+  bufp -> allocated = 28;
+      
+  if ( bufp -> buffer )
+       /* EXTEND_BUFFER loses when bufp->allocated is 0 */
+   bufp -> buffer = ( _TCHAR* )realloc (  bufp -> buffer, 28 * sizeof ( _TCHAR )  );
+  
+  else
+       /* Caller did not allocate a buffer.  Do it for him */
+   bufp -> buffer = ( _TCHAR* ) malloc (  28 * sizeof ( _TCHAR )  );
+
+  if ( !bufp -> buffer ) goto memory_exhausted;
+
+  begalt = b = bufp -> buffer;
+    
+ }  /* end if */
+
+ while ( p != pend ) {
+
+  if (  ( int )( b - bufp -> buffer ) >
+        ( int )(  bufp -> allocated - 10 * sizeof ( _TCHAR )  )
+  )
+       
+   EXTEND_BUFFER; /* Note that EXTEND_BUFFER clobbers c */
+
+  PATFETCH( c );
+
+  switch ( c ) {
+
+   case _TEXT( '$' ):
+
+    if ( obscure_syntax & RE_TIGHT_VBAR ) {
+
+        if (  !( obscure_syntax & RE_CONTEXT_INDEP_OPS ) && p != pend  ) goto normal_char;
+             /* Make operand of last vbar end before this `$'.  */
+        if ( fixup_jump ) store_jump ( fixup_jump, jump, b );
+             
+      fixup_jump = NULL;
+     PATPUSH( endline );
+             
+     break;
+    
+    }  /* end if */
+
+       /* $ means succeed if at end of line, but only in special contexts.    */
+       /*   If randomly in the middle of a pattern, it is a normal character. */
+       if (  p == pend                                ||
+         *p == _TEXT( '\n' )                       ||
+         ( obscure_syntax & RE_CONTEXT_INDEP_OPS ) ||
+         ( obscure_syntax & RE_NO_BK_PARENS ?
+            *p == _TEXT( ')'  )             :
+            *p == _TEXT( '\\' ) &&
+             p[ 1 ] == _TEXT( ')' )
+         )                                         ||
+            ( obscure_syntax & RE_NO_BK_VBAR ?
+          *p == _TEXT( '|'  )             :
+          *p == _TEXT( '\\' ) &&
+           p[ 1 ] == _TEXT( '|' )
+         )
+    ) {
+
+     PATPUSH( endline );
+
+     break;
+
+       }  /* end if */
+
+       goto normal_char;
+
+   case _TEXT( '^' ):
+         /* ^ means succeed if at beg of line, but only if no preceding pattern. */
+
+    if (  laststart && p[ -2 ] != _TEXT( '\n' )      &&
+          !( obscure_syntax & RE_CONTEXT_INDEP_OPS )
+    ) goto normal_char;
+
+    if ( obscure_syntax & RE_TIGHT_VBAR ) {
+
+     if ( p != pattern + 1                           &&
+          !( obscure_syntax & RE_CONTEXT_INDEP_OPS )
+     ) goto normal_char;
+
+        PATPUSH( begline );
+        begalt = b;
+
+           
+    } else PATPUSH( begline );
+
+   break;
+
+   case _TEXT( '+' ):
+   case _TEXT( '?' ):
+
+    if ( obscure_syntax & RE_BK_PLUS_QM ) goto normal_char;
+
+handle_plus:
+
+   case _TEXT( '*' ):
+         /* If there is no previous pattern, char not special. */
+
+    if (  !laststart && !( obscure_syntax & RE_CONTEXT_INDEP_OPS )  ) goto normal_char;
+
+         /* If there is a sequence of repetition chars,  */
+         /*  collapse it down to equivalent to just one. */
+       zero_times_ok = 0;
+       many_times_ok = 0;
+
+       while ( 1 ) {
+
+        zero_times_ok |= c != _TEXT( '+' );
+        many_times_ok |= c != _TEXT( '?' );
+
+        if ( p == pend ) break;
+
+        PATFETCH( c );
+
+        if (  c == _TEXT( '*' )  )
+         ;
+        else if (  !( obscure_syntax & RE_BK_PLUS_QM )           &&
+                 (  c == _TEXT( '+' ) || c == _TEXT( '?' )  )
+          );
+     else if (  ( obscure_syntax & RE_BK_PLUS_QM ) && c == _TEXT( '\\' )  ) {
+
+      long c1;
+
+      PATFETCH( c1 );
+
+      if (   !(  c1 == _TEXT( '+' ) || c1 == _TEXT( '?' )  )   ) {
+
+       PATUNFETCH;
+       PATUNFETCH;
+
+       break;
+                   
+      }  /* end if */
+
+      c = c1;
+
+     } else {
+
+      PATUNFETCH;
+
+      break;
+
+     }  /* end else */
+
+       }  /* end while */
+
+       /* Star, etc. applied to an empty pattern is equivalent */
+       /*   to an empty pattern.                               */
+         
+    if ( !laststart ) break;
+
+       /* Now we know whether 0 matches is allowed,   */
+       /*   and whether 2 or more matches is allowed. */
+
+       if ( many_times_ok ) {
+     /* If more than one repetition is allowed, */
+        /*  put in a backward jump at the end.     */
+
+        store_jump ( b, maybe_finalize_jump, laststart - 3L );
+     b += 3;
+
+       }  /* end if */
+
+       insert_jump ( on_failure_jump, laststart, b + 3, b );
+    pending_exact = NULL;
+    b += 3;
+
+    if ( !zero_times_ok ) {
+        /* At least one repetition required: insert before the loop */
+        /*  a skip over the initial on-failure-jump instruction     */
+
+     insert_jump ( dummy_failure_jump, laststart, laststart + 6L, b );
+        b += 3;
+           
+    }  /* end if */
+
+   break;
+
+   case _TEXT( '.' ):
+
+    laststart = b;
+    PATPUSH( anychar );
+
+   break;
+
+   case _TEXT( '[' ):
+
+    while (  b - bufp -> buffer  >
+                    ( int )( bufp->allocated - 3 - ( 1 << BYTEWIDTH ) / BYTEWIDTH )
+    ) /* Note that EXTEND_BUFFER clobbers c */ EXTEND_BUFFER;
+
+    laststart = b;
+         
+    if (  *p == _TEXT( '^' )  )
+
+     PATPUSH( charset_not ), p++;
+         
+    else
+
+        PATPUSH( charset );
+
+    p1 = p;
+    PATPUSH(  ( 1 << BYTEWIDTH ) / BYTEWIDTH  );
+       /* Clear the whole map */
+       memset (  b, 0, ( 1 << BYTEWIDTH ) / BYTEWIDTH * sizeof ( TCHAR )  );
+
+       /* Read in characters and ranges, setting map bits */
+    while ( 1 ) {
+
+        PATFETCH( c );
+
+        if (  c == _TEXT( ']' ) && p != p1 + 1  ) break;
+
+        if (  *p == _TEXT( '-' ) && p[ 1 ] != _TEXT( ']' )  ) {
+
+      PATFETCH( c1 );
+      PATFETCH( c1 );
+
+      if ( translate )
+
+       while ( c <= c1 ) {
+
+        _TUCHAR mapped_c = translate[ c ];
+        b[ mapped_c / BYTEWIDTH ] |= 1 << ( mapped_c % BYTEWIDTH );
+        ++c;
+
+       }  /* end while */
+
+         else
+
+       while ( c <= c1 ) b[ c / BYTEWIDTH ] |= 1 << ( c % BYTEWIDTH ), c++;
+               
+     } else {
+
+      if ( translate ) c = translate[ c ];
+
+      b[ c / BYTEWIDTH ] |= 1 << ( c % BYTEWIDTH );
+               
+     }  /* end else */
+
+    }  /* end while */
+
+       /* Discard any bitmap bytes that are all 0 at the end of the map. */
+       /*  Decrement the map-length byte too.                            */
+       while (  ( int )b[ -1 ] > 0 && b[  b[ -1 ] - 1  ] == 0  ) b[ -1 ]--;
+
+    b += b[ -1 ];
+
+   break;
+
+   case _TEXT( '(' ):
+
+    if (  !( obscure_syntax & RE_NO_BK_PARENS )  )
+        goto normal_char;
+       else
+        goto handle_open;
+
+   case _TEXT( ')' ):
+    if (  !( obscure_syntax & RE_NO_BK_PARENS )  )
+     goto normal_char;
+    else
+     goto handle_close;
+
+   case '\n':
+    if (  !( obscure_syntax & RE_NEWLINE_OR )  )
+     goto normal_char;
+    else
+     goto handle_bar;
+
+   case _TEXT( '|' ):
+    if (  !( obscure_syntax & RE_NO_BK_VBAR )  )
+     goto normal_char;
+    else
+     goto handle_bar;
+
+   case _TEXT( '\\' ):
+
+    if ( p == pend ) goto invalid_pattern;
+
+    PATFETCH_RAW( c );
+
+    switch ( c ) {
+
+     case _TEXT( '(' ):
+
+         if ( obscure_syntax & RE_NO_BK_PARENS ) goto normal_backsl;
+
+handle_open:
+
+      if ( stackp == stacke ) goto nesting_too_deep;
+
+         if ( regnum < RE_NREGS ) {
+
+       PATPUSH( start_memory );
+       PATPUSH( regnum );
+               
+      }  /* end if */
+
+      *stackp++  = b - bufp -> buffer;
+      *stackp++  = fixup_jump ? fixup_jump - bufp -> buffer + 1L : 0L;
+      *stackp++  = regnum++;
+      *stackp++  = begalt - bufp -> buffer;
+         fixup_jump = NULL;
+         laststart  = NULL;
+         begalt     = b;
+
+     break;
+
+     case _TEXT( ')' ):
+
+      if ( obscure_syntax & RE_NO_BK_PARENS ) goto normal_backsl;
+
+handle_close:
+
+      if ( stackp == stackb ) goto unmatched_close;
+
+      begalt = *--stackp + bufp -> buffer;
+
+      if ( fixup_jump ) store_jump ( fixup_jump, jump, b );
+             
+      if ( stackp[ -1 ] < RE_NREGS ) {
+
+       PATPUSH( stop_memory );
+       PATPUSH( stackp[ -1 ] );
+               
+      }  /* end if */
+
+      stackp -= 2;
+      fixup_jump = NULL;
+
+      if ( *stackp ) fixup_jump = *stackp + bufp -> buffer - 1L;
+
+      laststart = *--stackp + bufp -> buffer;
+
+        break;
+
+     case _TEXT( '|' ):
+
+      if ( obscure_syntax & RE_NO_BK_VBAR ) goto normal_backsl;
+
+handle_bar:
+
+      insert_jump ( on_failure_jump, begalt, b + 6, b );
+      pending_exact = NULL;
+      b += 3;
+
+      if ( fixup_jump ) store_jump ( fixup_jump, jump, b );
+             
+      fixup_jump = b;
+      b += 3;
+      laststart = 0;
+      begalt = b;
+
+     break;
+
+        case _TEXT( 'w' ):
+
+         laststart = b;
+         PATPUSH( wordchar );
+
+        break;
+
+     case _TEXT( 'W' ):
+
+      laststart = b;
+      PATPUSH( notwordchar );
+
+     break;
+
+     case _TEXT( '<' ):
+
+      PATPUSH( wordbeg );
+
+     break;
+
+     case _TEXT( '>' ):
+
+      PATPUSH( wordend );
+
+     break;
+
+     case _TEXT( 'b' ):
+
+      PATPUSH( wordbound );
+
+     break;
+
+     case _TEXT( 'B' ):
+
+      PATPUSH( notwordbound );
+     
+     break;
+
+     case _TEXT( '`' ):
+
+      PATPUSH( begbuf );
+
+     break;
+
+     case _TEXT( '\'' ):
+
+      PATPUSH( endbuf );
+
+     break;
+
+     case _TEXT( '1' ):
+     case _TEXT( '2' ):
+     case _TEXT( '3' ):
+     case _TEXT( '4' ):
+     case _TEXT( '5' ):
+     case _TEXT( '6' ):
+     case _TEXT( '7' ):
+     case _TEXT( '8' ):
+     case _TEXT( '9' ):
+
+      c1 = c - _TEXT( '0' );
+
+      if (  ( int )c1 >= regnum  ) goto normal_char;
+
+      for ( stackt = stackp - 2;  stackt > stackb;  stackt -= 4 )
+               
+       if (  *stackt == ( long )c1  ) goto normal_char;
+
+         laststart = b;
+         PATPUSH( duplicate );
+         PATPUSH( c1 );
+
+        break;
+
+        case _TEXT( '+' ):
+     case _TEXT( '?' ):
+
+         if ( obscure_syntax & RE_BK_PLUS_QM ) goto handle_plus;
+
+        default:
+
+normal_backsl:
+
+        /* You might think it would be useful for \ to mean */
+     /* not to translate; but if we don't translate it   */
+     /* it will never match anything.                    */
+         if ( translate ) c = translate[ c ];
+      
+      goto normal_char;
+
+       }  /* end switch */
+
+   break;
+
+   default:
+
+normal_char:
+
+    if (  !pending_exact                            ||
+           pending_exact + *pending_exact + 1L != b ||
+             *pending_exact == 0177                    ||
+          *p == _TEXT( '*' )                        ||
+          *p == _TEXT( '^' )                        ||
+             (  ( obscure_syntax & RE_BK_PLUS_QM ) ?
+              *p == _TEXT( '\\' ) &&
+              (  p[ 1 ] == _TEXT( '+' ) ||
+                 p[ 1]  == _TEXT( '?' )
+              )                                 :
+              ( *p == _TEXT( '+' ) ||
+                *p == _TEXT( '?' )
+              )
+          )
+    ) {
+
+        laststart = b;
+        PATPUSH( exactn );
+        pending_exact = b;
+        PATPUSH( 0 );
+
+       }  /* end if */
+
+    PATPUSH( c );
+    ( *pending_exact )++;
+
+  }  /* end switch */
+
+ }  /* end while */
+
+ if ( fixup_jump ) store_jump ( fixup_jump, jump, b );
+
+ if ( stackp != stackb ) goto unmatched_open;
+
+ bufp -> used = b - bufp -> buffer;
+
+ return NULL;
+
+invalid_pattern:  return _TEXT( "invalid regular expression" );
+
+unmatched_open:   return _TEXT( "unmatched \\(" );
+
+unmatched_close:  return _TEXT( "unmatched \\)" );
+
+end_of_pattern:   return _TEXT( "premature end of regular expression" );
+
+nesting_too_deep: return _TEXT( "nesting too deep" );
+
+too_big:          return _TEXT( "regular expression too big" );
+
+memory_exhausted: return _TEXT( "Memory exhausted" );
+
+}  /* end re_compile_pattern */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Store where `from' points a jump operation to jump to where `to' points.   */
+/* `opcode' is the opcode to store.                                           */
+/*                                                                            */
+/******************************************************************************/
+/***/
+static void store_jump ( _TCHAR* from, _TCHAR opcode, _TCHAR* to ) {
+
+ from[ 0 ] = opcode;
+ from[ 1 ] = (  to - ( from + 3 )  ) &  CHAR_MASK;
+ from[ 2 ] = (  to - ( from + 3 )  ) >> BYTEWIDTH;
+
+}  /* end store_jump */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Open up space at char FROM, and insert there a jump to TO.                 */
+/* CURRENT_END gives te end of the storage no in use,                         */
+/* so we know how much data to copy up.                                       */
+/* OP is the opcode of the jump to insert.                                    */
+/*                                                                            */
+/* If you call this function, you must zero out pending_exact.                */
+/*                                                                            */
+/******************************************************************************/
+/***/
+static void insert_jump (
+             _TCHAR op, _TCHAR* from, _TCHAR* to, _TCHAR* current_end
+            ) {
+
+  _TCHAR* pto = current_end + 3;
+  _TCHAR* pfrom = current_end;
+
+  while ( pfrom != from ) *--pto = *--pfrom;
+
+  store_jump ( from, op, to );
+
+}  /* end insert_jump */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Given a pattern, compute a fastmap from it.                                */
+/* The fastmap records which of the (1 << BYTEWIDTH) possible characters      */
+/* can start a string that matches the pattern.                               */
+/* This fastmap is used by re_search to skip quickly over totally implausible */
+/* text.                                                                      */
+/* The caller must supply the address of a (1 << BYTEWIDTH)-byte data area    */
+/* as bufp->fastmap.                                                          */
+/* The other components of bufp describe the pattern to be used.              */
+/*                                                                            */
+/******************************************************************************/
+/***/
+void re_compile_fastmap ( PRE_PATTERN_BUFFER bufp ) {
+
+ int j, size = bufp -> used;
+
+ _TUCHAR*  pattern   = (_TUCHAR* )bufp -> buffer;
+ _TUCHAR*  p         = pattern;
+ _TUCHAR*  pend      = pattern + size;
+ _TUCHAR*  translate = (_TUCHAR* )bufp -> translate;
+ _TCHAR*   fastmap   = bufp -> fastmap;
+ _TUCHAR*  stackb[ NFAILURES ];
+ _TUCHAR** stackp = stackb;
+
+ memset (  fastmap, 0, ( 1 << BYTEWIDTH ) * sizeof ( TCHAR )  );
+ bufp -> fastmap_accurate = 1;
+ bufp -> can_be_null = 0;
+      
+ while ( p ) {
+
+  if ( p == pend ) {
+
+   bufp -> can_be_null = 1;
+
+   break;
+
+  }  /* end if */
+
+  switch (  ( enum regexpcode )*p++  ) {
+
+   case exactn:
+
+    if ( translate )
+     fastmap[   translate[  p[ 1 ]  ]   ] = 1;
+    else
+     fastmap[  p[ 1 ]  ] = 1;
+         
+   break;
+
+   case begline:
+   case before_dot:
+   case at_dot:
+   case after_dot:
+   case begbuf:
+   case endbuf:
+   case wordbound:
+   case notwordbound:
+   case wordbeg:
+   case wordend:
+
+    continue;
+
+   case endline:
+
+    if ( translate )
+     fastmap[  translate[ _TEXT( '\n' ) ]  ] = 1;
+    else
+     fastmap[ _TEXT( '\n' ) ] = 1;
+
+    if ( bufp -> can_be_null != 1 )
+     bufp -> can_be_null = 2;
+         
+   break;
+
+   case finalize_jump:
+   case maybe_finalize_jump:
+   case jump:
+   case dummy_failure_jump:
+
+    bufp -> can_be_null = 1;
+    j = *p++ & CHAR_MASK;
+    j += SIGN_EXTEND_CHAR(  *( char* )p  ) << BYTEWIDTH;
+    p += j + 1;  /* The 1 compensates for missing ++ above */
+         
+    if ( j > 0 ) continue;
+
+    /* Jump backward reached implies we just went through      */
+    /*  the body of a loop and matched nothing.                */
+    /*  Opcode jumped to should be an on_failure_jump.         */
+    /*  Just treat it like an ordinary jump.                   */
+    /*  For a * loop, it has pushed its failure point already; */
+    /*    if so, discard that as redundant.                    */
+    if (  ( enum regexpcode )*p != on_failure_jump  ) continue;
+
+    ++p;
+    j = *p++ & CHAR_MASK;
+    j += SIGN_EXTEND_CHAR(  *( char* )p  ) << BYTEWIDTH;
+    p += j + 1;  /* The 1 compensates for missing ++ above */
+
+    if ( stackp != stackb && *stackp == p ) stackp--;
+
+    continue;
+         
+   case on_failure_jump:
+
+    j = *p++ & CHAR_MASK;
+    j += SIGN_EXTEND_CHAR(  *( char* )p  ) << BYTEWIDTH;
+    p++;
+    *++stackp = p + j;
+
+    continue;
+
+   case start_memory:
+   case stop_memory:
+
+    ++p;
+
+    continue;
+
+   case duplicate:
+
+    bufp -> can_be_null = 1;
+    fastmap[ _TEXT( '\n' )] = 1;
+
+   case anychar:
+
+    for (  j = 0; j < ( 1 << BYTEWIDTH ); j++  )
+           
+     if (  j != _TEXT( '\n' )  ) fastmap[ j ] = 1;
+
+    if ( bufp -> can_be_null ) return;
+
+    /* Don't return; check the alternative paths  */
+    /*  so we can set can_be_null if appropriate. */
+   break;
+
+   case wordchar:
+
+    for (  j = 0; j < ( 1 << BYTEWIDTH ); j++  )
+
+     if (  SYNTAX( j ) == Sword  ) fastmap[ j ] = 1;
+         
+   break;
+
+   case notwordchar:
+
+    for (  j = 0; j < ( 1 << BYTEWIDTH ); j++  )
+
+     if (  SYNTAX( j ) != Sword  ) fastmap[ j ] = 1;
+
+   break;
+
+   case charset:
+
+    for ( j = *p++ * BYTEWIDTH - 1; j >= 0; j-- )
+
+     if (   p[ j / BYTEWIDTH ] & (  1 << ( j % BYTEWIDTH )  )   ) {
+
+      if ( translate )
+       fastmap[  translate[ j ]  ] = 1;
+      else
+       fastmap[ j ] = 1;
+
+     }  /* end if */
+
+   break;
+
+   case charset_not:
+    /* Chars beyond end of map must be allowed */
+    for (  j = *p * BYTEWIDTH; j < ( 1 << BYTEWIDTH ); j++  )
+           
+     if ( translate )
+      fastmap[  translate[ j ]  ] = 1;
+     else
+      fastmap[ j ] = 1;
+
+    for ( j = *p++ * BYTEWIDTH - 1; j >= 0; j-- )
+
+     if (    !(  p[ j / BYTEWIDTH ] & (  1 << ( j % BYTEWIDTH )  )   )    ) {
+
+      if ( translate )
+       fastmap[  translate[ j ]  ] = 1;
+      else
+       fastmap[ j ] = 1;
+
+     }  /* end if */
+         
+   break;
+       
+  }  /* end switch */
+
+   /* Get here means we have successfully found the possible starting    */
+   /* characters of one path of the pattern.  We need not follow this    */
+   /* path any farther. Instead, look at the next alternative remembered */
+   /* in the stack.                                                      */
+  if ( stackp != stackb )
+   p = *stackp--;
+  else
+   break;
+    
+ }  /* end while */
+
+}  /* end re_compile_fastmap */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Like re_search_2, below, but only one string is specified.                 */
+/*                                                                            */
+/******************************************************************************/
+/***/
+int re_search (
+     PRE_PATTERN_BUFFER pbufp, _TCHAR* string, int size, int startpos,
+     int range, PRE_REGISTERS regs
+    ) {
+
+ return re_search_2 (
+         pbufp, NULL, 0, string, size, startpos, range, regs, size
+        );
+
+}  /* end re_search */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Like re_match_2 but tries first a match starting at index STARTPOS,        */
+/* then at STARTPOS + 1, and so on.                                           */
+/* RANGE is the number of places to try before giving up.                     */
+/* If RANGE is negative, the starting positions tried are                     */
+/*  STARTPOS, STARTPOS - 1, etc.                                              */
+/* It is up to the caller to make sure that range is not so large             */
+/*  as to take the starting position outside of the input strings.            */
+/*                                                                            */
+/* The value returned is the position at which the match was found,           */
+/* or -1 if no match was found,                                               */
+/* or -2 if error (such as failure stack overflow).                           */
+/*                                                                            */
+/******************************************************************************/
+/***/
+int re_search_2 (
+     PRE_PATTERN_BUFFER pbufp,
+     _TCHAR* string1, int size1, _TCHAR* string2, int size2,
+     int startpos, int range, PRE_REGISTERS regs, int mstop
+    ) {
+
+ _TCHAR*  fastmap   = pbufp -> fastmap;
+ _TUCHAR* translate = (_TUCHAR* )pbufp -> translate;
+
+ int total = size1 + size2;
+ int val;
+
+ /* Update the fastmap now if not correct already */
+ if ( fastmap && !pbufp -> fastmap_accurate ) re_compile_fastmap ( pbufp );
+  
+ /* Don't waste time in a long search for a pattern */
+ /*  that says it is anchored.                      */
+ if ( pbufp -> used > 0                                 &&
+      ( enum regexpcode )pbufp -> buffer[ 0 ] == begbuf &&
+      range > 0
+ ) {
+
+  if ( startpos > 0 )
+   return -1;
+  else
+   range = 1;
+    
+ }  /* end if */
+
+ while ( 1 ) {
+
+  /* If a fastmap is supplied, skip quickly over characters  */
+  /* that cannot possibly be the start of a match.           */
+  /* Note, however, that if the pattern can possibly match   */
+  /* the null string, we must test it at each starting point */
+  /* so that we take the first null string we get.           */
+  if ( fastmap && startpos < total && pbufp -> can_be_null != 1 ) {
+
+   if ( range > 0 ) {
+
+       int lim    = 0;
+    int irange = range;
+
+       _TUCHAR* p;
+
+       if ( startpos < size1 && startpos + range >= size1 )
+               
+     lim = range - ( size1 - startpos );
+
+       p = (  ( _TUCHAR * )
+                   &( startpos >= size1 ? string2 - size1 : string1 )[ startpos ]
+        );
+
+       if ( translate )
+
+     while ( range > lim && !fastmap[  translate[ *p++ ]  ] ) range--;
+
+    else
+                 
+     while ( range > lim && !fastmap[ *p++ ] ) range--;
+
+    startpos += irange - range;
+
+   } else {
+
+       _TUCHAR c;
+
+       if ( startpos >= size1 )
+     c = string2[ startpos - size1 ];
+       else
+     c = string1[ startpos ];
+
+       c &= CHAR_MASK;
+
+       if ( translate ? !fastmap[  translate[ c ]  ] : !fastmap[ c ] ) goto advance;
+
+   }  /* end else */
+
+  }  /* end if */
+
+  if ( range >= 0           &&
+       startpos == total    &&
+          fastmap              &&
+       pbufp -> can_be_null == 0
+  ) return -1;
+
+  val = re_match_2 ( pbufp, string1, size1, string2, size2, startpos, regs, mstop );
+
+  /* Propagate error indication if worse than mere failure.  */
+  if ( val == -2 ) return -2;
+
+  /* Return position on success.  */
+  if ( 0 <= val ) return startpos;
+
+advance:
+
+  if ( !range ) break;
+
+  if ( range > 0 )
+   range--, startpos++;
+  else
+   range++, startpos--;
+    
+ }  /* end while */
+
+  return -1;
+
+}  /* end int re_search_2 */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+/***/
+int re_match (
+     PRE_PATTERN_BUFFER pbufp, _TCHAR* string, int size, int pos,
+     PRE_REGISTERS regs
+    ) {
+
+ return re_match_2 ( pbufp, NULL, 0, string, size, pos, regs, size );
+
+}  /* end re_match */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Maximum size of failure stack.  Beyond this, overflow is an error.         */
+/*                                                                            */
+/******************************************************************************/
+/***/
+#define RE_MAX_FAILURES 65536
+/***/
+static int bcmp_translate();
+/***/
+/******************************************************************************/
+/*                                                                            */
+/* Match the pattern described by PBUFP                                       */
+/*   against data which is the virtual concatenation of STRING1 and STRING2.  */
+/*   SIZE1 and SIZE2 are the sizes of the two data strings.                   */
+/*   Start the match at position POS.                                         */
+/*   Do not consider matching past the position MSTOP.                        */
+/*                                                                            */
+/*   If pbufp->fastmap is nonzero, then it had better be up to date.          */
+/*                                                                            */
+/*   The reason that the data to match are specified as two components        */
+/*   which are to be regarded as concatenated                                 */
+/*   is so this function can be used directly on the contents of an Emacs     */
+/*   buffer.                                                                  */
+/*                                                                            */
+/*   -1 is returned if there is no match.  -2 is returned if there is         */
+/*   an error (such as match stack overflow).  Otherwise the value is the     */
+/*   length of the substring which was matched.                               */
+/*                                                                            */
+/******************************************************************************/
+/***/
+int re_match_2 (
+     PRE_PATTERN_BUFFER pbufp,
+     _TUCHAR* string1, int size1, _TUCHAR* string2, int size2,
+     int pos, PRE_REGISTERS regs, int mstop
+    ) {
+
+ _TUCHAR* p    = ( _TUCHAR* )pbufp -> buffer;
+ _TUCHAR* pend = p + pbufp -> used;
+ /* End of first string */
+ _TUCHAR* end1;
+ /* End of second string */
+ _TUCHAR* end2;
+ /* Pointer just past last char to consider matching */
+ _TUCHAR* end_match_1, *end_match_2;
+ _TUCHAR* d, *dend;
+ _TUCHAR* translate = ( _TUCHAR* ) pbufp -> translate;
+ int mcnt;
+ /* Failure point stack.  Each place that can handle a failure       */
+ /* further down the line pushes a failure point on this stack.      */
+ /* It consists of two char *'s.                                     */
+ /* The first one pushed is where to resume scanning the pattern;    */
+ /* the second pushed is where to resume scanning the strings.       */
+ /* If the latter is zero, the failure point is a "dummy".           */
+ /* If a failure happens and the innermost failure point is dormant, */
+ /* it discards that failure point and tries the next one.           */
+
+ _TUCHAR*  initial_stack[ 2 * NFAILURES ];
+ _TUCHAR** stackb = initial_stack;
+ _TUCHAR** stackp = stackb, **stacke = &stackb[ 2 * NFAILURES ];
+
+ /* Information on the "contents" of registers.                              */
+ /*  These are pointers into the input strings; they record                  */
+ /*  just what was matched (on this attempt) by some part of the pattern.    */
+ /*  The start_memory command stores the start of a register's contents      */
+ /*  and the stop_memory command stores the end.                             */
+ /*                                                                          */
+ /*  At that point, regstart[regnum] points to the first character in        */
+ /*  the register,                                                           */
+ /*  regend[regnum] points to the first character beyond the end of          */
+ /*  the register,                                                           */
+ /*  regstart_seg1[regnum] is true iff regstart[regnum] points into string1, */
+ /*  and regend_seg1[regnum] is true iff regend[regnum] points into string1. */
+
+  _TUCHAR* regstart[ RE_NREGS ];
+  _TUCHAR* regend[ RE_NREGS ];
+  _TUCHAR  regstart_seg1[ RE_NREGS ], regend_seg1[ RE_NREGS ];
+
+ /* Set up pointers to ends of strings.                               */
+ /*  Don't allow the second string to be empty unless both are empty. */
+ if ( !size2 ) {
+
+  string2 = string1;
+  size2 = size1;
+  string1 = NULL;
+  size1 = 0;
+    
+ }  /* end if */
+
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings */
+ if ( mstop <= size1 ) {
+
+  end_match_1 = string1 + mstop;
+  end_match_2 = string2;
+
+ } else {
+
+  end_match_1 = end1;
+  end_match_2 = string2 + mstop - size1;
+
+ }  /* end else */
+
+ /* Initialize \) text positions to -1                */
+ /*  to mark ones that no \( or \) has been seen for. */
+
+ for (  mcnt = 0; mcnt < sizeof ( regend ) / sizeof( *regend ); mcnt++ )
+
+  regend[ mcnt ] = ( _TUCHAR* )-1;
+
+ /* `p' scans through the pattern as `d' scans through the data.         */
+ /*  `dend' is the end of the input string that `d' points within.       */
+ /*  `d' is advanced into the following input string whenever necessary, */
+ /*  but this happens before fetching;                                   */
+ /*  therefore, at the beginning of the loop,                            */
+ /*  `d' can be pointing at the end of a string,                         */
+ /*  but it cannot equal string2.                                        */
+ if ( pos <= size1 )
+  d = string1 + pos, dend = end_match_1;
+ else
+  d = string2 + pos - size1, dend = end_match_2;
+
+/* Write PREFETCH; just before fetching a character with *d. */
+#define PREFETCH while ( d == dend ) {                                                  \
+                  if ( dend == end_match_2 ) goto fail; /* end of string2 => failure */ \
+                  d = string2; /* end of string1 => advance to string2. */              \
+                  dend = end_match_2;                                                   \
+                 }
+
+ /* This loop loops over pattern commands.                                        */
+ /*  It exits by returning from the function if match is complete,                */
+ /*  or it drops through if match fails at this starting point in the input data. */
+ while ( 1 ) {
+
+  if (p == pend) {  /* End of pattern means we have succeeded! */
+         
+   if ( regs ) { /* If caller wants register contents data back, convert it to indices */
+
+       regs -> start[ 0 ] = pos;
+             
+    if ( dend == end_match_1 )
+     regs -> end[ 0 ] = d - string1;
+    else
+     regs->end[ 0 ] = d - string2 + size1;
+
+       for ( mcnt = 1; mcnt < RE_NREGS; mcnt++ ) {
+
+     if (  regend[ mcnt ] == ( _TUCHAR* )-1  ) {
+
+      regs -> start[ mcnt ] = -1;
+      regs -> end[ mcnt ]   = -1;
+                     
+      continue;
+                   
+     }  /* end if */
+
+     if ( regstart_seg1[ mcnt ] )
+      regs -> start[ mcnt ] = regstart[ mcnt ] - string1;
+     else
+      regs -> start[ mcnt ] = regstart[ mcnt ] - string2 + size1;
+                 
+     if ( regend_seg1[ mcnt ] )
+      regs -> end[ mcnt ] = regend[ mcnt ] - string1;
+     else
+      regs -> end[ mcnt ] = regend[ mcnt ] - string2 + size1;
+               
+    }  /* end for */
+           
+   }  /* end if */
+
+   if ( dend == end_match_1 )
+    return ( d - string1 - pos );
+   else
+       return d - string2 + size1 - pos;
+
+  }  /* end if */
+
+  /* Otherwise match next pattern command */
+  switch (  ( enum regexpcode )*p++  ) {
+
+   /* \( is represented by a start_memory, \) by a stop_memory.              */
+   /*   Both of those commands contain a "register number" argument.         */
+   /*   The text matched within the \( and \) is recorded under that number. */
+   /*   Then, \<digit> turns into a `duplicate' command which                */
+   /*   is followed by the numeric value of <digit> as the register number.  */
+   case start_memory:
+
+    regstart[ *p ] = d;
+    regstart_seg1[ *p++ ] = ( dend == end_match_1 );
+        
+   break;
+
+   case stop_memory:
+
+    regend[ *p ] = d;
+    regend_seg1[ *p++ ] = ( dend == end_match_1 );
+        
+   break;
+
+   case duplicate: {
+
+    int     regno = *p++;  /* Get which register to match against */
+    _TUCHAR *d2, *dend2;
+
+    /* Don't allow matching a register that hasn't been used. */
+    /*     This isn't fully reliable in the current version,  */
+    /*     but it is better than crashing.                    */
+    if (  ( int )regend[ regno ] == -1  ) goto fail;
+
+    d2 = regstart[ regno ];
+    dend2 = (  ( regstart_seg1[ regno ] == regend_seg1[ regno]  ) ?
+             regend[regno]                                        :
+             end_match_1
+            );
+
+    while ( 1 ) {
+
+     /* Advance to next segment in register contents, if necessary */
+     while ( d2 == dend2 ) {
+
+      if ( dend2 == end_match_2     ) break;
+      if ( dend2 == regend[ regno ] ) break;
+
+      d2 = string2, dend2 = regend[ regno ];  /* end of string1 => advance to string2. */
+                 
+     }  /* end while
+       
+     /* At end of register contents => success */
+     if ( d2 == dend2 ) break;
+
+     /* Advance to next segment in data being matched, if necessary */
+     PREFETCH;
+
+     /* mcnt gets # consecutive chars to compare */
+     mcnt = dend - d;
+
+     if ( mcnt > dend2 - d2 ) mcnt = dend2 - d2;
+
+     /* Compare that many; failure if mismatch, else skip them. */
+     if ( translate                                 ?
+          bcmp_translate ( d, d2, mcnt, translate ) :
+          memcmp ( d, d2, mcnt )
+     ) goto fail;
+
+     d += mcnt, d2 += mcnt;
+             
+    }  /* end while */
+
+   }  /* duplicate */
+
+   break;
+
+   case anychar:
+
+    /* fetch a data character */
+    PREFETCH;
+    /* Match anything but a newline.  */
+    if (  ( translate ? translate[ *d++ ] : *d++ ) == _TEXT( '\n' )  ) goto fail;
+
+   break;
+
+   case charset:
+   case charset_not: {
+
+    /* Nonzero for charset_not */
+    int not = 0;
+    int c;
+
+    if (  *( p - 1 ) == ( _TUCHAR ) charset_not  ) not = 1;
+
+    /* fetch a data character */
+    PREFETCH;
+
+    if ( translate )
+     c = translate [ *d ];
+    else
+     c = *d;
+
+    if (  c < ( int )( *p * BYTEWIDTH ) &&
+         p[ 1 + c / BYTEWIDTH ] & (  1 << ( c % BYTEWIDTH ) )
+    ) not = !not;
+
+    p += 1 + *p;
+
+    if ( !not ) goto fail;
+
+    ++d;
+
+   }  /* charset & charset_not */
+
+   break;
+
+   case begline:
+
+    if (  d == string1 || d[ -1 ] == _TEXT( '\n' )  ) break;
+
+    goto fail;
+
+   case endline:
+
+    if ( d == end2 ||
+         ( d == end1 ? ( size2 == 0 ||
+                         *string2 == _TEXT( '\n' )
+                       )
+                     : *d == _TEXT( '\n' )
+         )
+    ) break;
+
+    goto fail;
+
+   /* "or" constructs ("|") are handled by starting each alternative             */
+   /*  with an on_failure_jump that points to the start of the next alternative. */
+   /*  Each alternative except the last ends with a jump to the joining point.   */
+   /*  (Actually, each jump except for the last one really jumps                 */
+   /*   to the following jump, because tensioning the jumps is a hassle.)        */
+   /*                                                                            */
+   /* The start of a stupid repeat has an on_failure_jump that points            */
+   /* past the end of the repeat text.                                           */
+   /* This makes a failure point so that, on failure to match a repetition,      */
+   /* matching restarts past as many repetitions have been found                 */
+   /* with no way to fail and look for another one.                              */
+   /*                                                                            */
+   /* A smart repeat is similar but loops back to the on_failure_jump            */
+   /* so that each repetition makes another failure point.                       */
+
+   case on_failure_jump:
+
+    if ( stackp == stacke ) {
+
+     _TUCHAR** stackx;
+
+     if ( stacke - stackb > RE_MAX_FAILURES ) return -2;
+
+     stackx = ( _TUCHAR** ) alloca (  2 * ( stacke - stackb ) * sizeof ( _TCHAR* )  );
+     memcpy (  stackx, stackb, ( stacke - stackb ) * sizeof ( _TCHAR* )  );
+     stackp = stackx + ( stackp - stackb );
+     stacke = stackx + 2 * ( stacke - stackb );
+     stackb = stackx;
+           
+    }  /* end if */
+
+    mcnt = *p++ & CHAR_MASK;
+    mcnt += SIGN_EXTEND_CHAR(  *( _TCHAR* )p  ) << BYTEWIDTH;
+    ++p;
+    *stackp++ = mcnt + p;
+    *stackp++ = d;
+         
+   break;
+
+   /* The end of a smart repeat has an maybe_finalize_jump back. */
+   /* Change it either to a finalize_jump or an ordinary jump.   */
+   case maybe_finalize_jump:
+
+    mcnt = *p++ & CHAR_MASK;
+    mcnt += SIGN_EXTEND_CHAR(  *( _TCHAR* )p  ) << BYTEWIDTH;
+    ++p;
+
+    /* Compare what follows with the begining of the repeat.      */
+    /*  If we can establish that there is nothing that they would */
+    /*  both match, we can change to finalize_jump                */
+    if ( p == pend )
+     p[ -3 ] = ( _TUCHAR )finalize_jump;
+    else if ( *p == ( _TUCHAR )exactn  || 
+              *p == ( _TUCHAR )endline
+    ) {
+             
+     int      c  = *p == ( _TUCHAR ) endline ? _TEXT( '\n' ) : p[ 2 ];
+     _TUCHAR* p1 = p + mcnt;
+             
+     /* p1[0] ... p1[2] are an on_failure_jump. */
+     /* Examine what follows that               */
+     if (  p1[ 3 ] == ( _TUCHAR )exactn && p1[ 5 ] != c  )
+      p[ -3 ] = ( _TUCHAR )finalize_jump;
+     else if (  p1[ 3 ] == ( _TUCHAR )charset     ||
+                p1[ 3 ] == ( _TUCHAR )charset_not
+     ) {
+
+      int not = p1[ 3 ] == ( _TCHAR )charset_not;
+                 
+      if ( c < ( int )( p1[ 4 ] * BYTEWIDTH  ) &&
+           p1[ 5 + c / BYTEWIDTH ] & (  1 << ( c % BYTEWIDTH )  )
+      ) not = !not;
+
+      /* not is 1 if c would match             */
+      /* That means it is not safe to finalize */
+      if ( !not ) p[ -3 ] = ( _TUCHAR )finalize_jump;
+
+     }  /* end if */
+
+    }  /* end if */
+
+    p -= 2;
+
+    if ( p[ -1 ] != ( _TUCHAR )finalize_jump ) {
+
+     p[ -1 ] = ( _TUCHAR ) jump;
+     goto nofinalize;
+
+    }  /* end if */
+
+   /* The end of a stupid repeat has a finalize-jump              */
+   /* back to the start, where another failure point will be made */
+   /* which will point after all the repetitions found so far.    */
+
+   case finalize_jump:
+
+    stackp -= 2;
+
+   case jump:
+
+nofinalize:
+
+    mcnt = *p++ & CHAR_MASK;
+    mcnt += SIGN_EXTEND_CHAR(  *( _TCHAR* )p  ) << BYTEWIDTH;
+    p += mcnt + 1; /* The 1 compensates for missing ++ above */
+
+   break;
+
+   case dummy_failure_jump:
+
+    if ( stackp == stacke ) {
+
+     _TUCHAR** stackx =
+      ( _TUCHAR** ) alloca (  2 * ( stacke - stackb ) * sizeof ( _TUCHAR* )  );
+             
+     memcpy (  stackx, stackb, (stacke - stackb) * sizeof ( _TCHAR* )  );
+     stackp = stackx + ( stackp - stackb );
+     stacke = stackx + 2 * ( stacke - stackb );
+     stackb = stackx;
+           
+    }  /* end if */
+
+    *stackp++ = 0;
+    *stackp++ = 0;
+        
+    goto nofinalize;
+
+   case wordbound:
+
+    if ( d == string1  ||             /* Points to first char */
+         d == end2     ||             /* Points to end        */
+         ( d == end1 && size2 == 0 )  /* Points to end        */
+    ) break;
+
+    if (   (  SYNTAX( d[ -1 ]                   ) == Sword  ) !=
+           (  SYNTAX( d == end1 ? *string2 : *d ) == Sword  )
+    ) break;
+
+    goto fail;
+
+   case notwordbound:
+
+    if ( d == string1  ||             /* Points to first char */
+         d == end2     ||             /* Points to end        */
+         ( d == end1 && size2 == 0 )  /* Points to end        */
+    ) goto fail;
+
+    if (   (  SYNTAX( d[ -1 ]                   ) == Sword  ) !=
+           (  SYNTAX( d == end1 ? *string2 : *d ) == Sword  )
+    ) goto fail;
+
+    break;
+
+   case wordbeg:
+
+    if ( d == end2                  ||                      /* Points to end          */
+         ( d == end1 && size2 == 0) ||                      /* Points to end          */
+         SYNTAX(  *( d == end1 ? string2 : d )  ) != Sword  /* Next char not a letter */
+    ) goto fail;
+
+    if ( d == string1 ||             /* Points to first char */
+         SYNTAX( d[ -1 ] ) != Sword  /* prev char not letter */
+    ) break;
+
+    goto fail;
+
+   case wordend:
+
+    if ( d == string1 ||           /* Points to first char */
+         SYNTAX( d[-1] ) != Sword  /* prev char not letter */
+    ) goto fail;
+
+    if ( d == end2                 ||                   /* Points to end          */
+         (d == end1 && size2 == 0) ||                   /* Points to end          */
+         SYNTAX( d == end1 ? *string2 : *d ) != Sword   /* Next char not a letter */
+    ) break;
+
+    goto fail;
+
+   case wordchar:
+
+    PREFETCH;
+
+    if (  SYNTAX ( *d++ ) == 0  ) goto fail;
+
+   break;
+         
+   case notwordchar:
+
+    PREFETCH;
+
+    if (  SYNTAX ( *d++ ) != 0  ) goto fail;
+         
+   break;
+
+   case begbuf:
+
+    if ( d == string1 ) /* Note, d cannot equal string2 */
+     break;                 /* unless string1 == string2.  */
+
+    goto fail;
+
+   case endbuf:
+
+    if (  d == end2 || ( d == end1 && size2 == 0 )  ) break;
+
+    goto fail;
+
+   case exactn:
+    /* Match the next few pattern characters exactly. */
+    /*  mcnt is how many characters to match.         */
+    mcnt = *p++;
+
+    if ( translate ) {
+
+     do {
+
+      PREFETCH;
+
+      if ( translate[ *d++ ] != *p++ ) goto fail;
+               
+     } while ( --mcnt );
+           
+    } else {
+
+     do {
+
+      PREFETCH;
+
+      if ( *d++ != *p++ ) goto fail;
+               
+     } while ( --mcnt );
+           
+    }  /* end else */
+
+   break;
+
+  }  /* end switch */
+
+  continue; /* Successfully matched one pattern command; keep matching */
+
+  /* Jump here if any matching operation fails. */
+fail:
+
+  if ( stackp != stackb ) { /* A restart point is known.  Restart there and pop it. */
+
+   if ( !stackp[ -2 ] ) {   /* If innermost failure point is dormant, */
+                               /* flush it and keep looking              */
+    stackp -= 2;      
+
+       goto fail;
+           
+   }  /* end if */
+
+   d = *--stackp;
+   p = *--stackp;
+         
+   if ( d >= string1 && d <= end1 ) dend = end_match_1;
+
+  } else break;   /* Matching at this starting point really fails! */
+
+ }  /* end while */
+
+ return -1; /* Failure to match */
+
+}  /* end re_search_2 */
+/***/
+/******************************************************************************/
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+/***/
+static int bcmp_translate (
+            _TUCHAR* s1, _TUCHAR* s2, int len, _TUCHAR* translate
+           ) {
+
+  _TUCHAR *p1 = s1, *p2 = s2;
+
+  while ( len ) {
+
+   if ( translate [ *p1++ ] != translate [ *p2++] ) return 1;
+
+   --len;
+    
+  }  /* end while */
+
+  return 0;
+
+}  /* end bcmp_translate */
+/***/
+/******************************************************************************/