]> 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)
42 files changed:
src/WOKNT/FILES [new file with mode: 0755]
src/WOKNT/WOKNT.cdl [new file with mode: 0755]
src/WOKNT/WOKNT.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_AdmFile.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_AdmFile.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_CompareOfString.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_CompareOfString.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_CopyIfCh.c [new file with mode: 0755]
src/WOKNT/WOKNT_Dword.hxx [new file with mode: 0755]
src/WOKNT/WOKNT_FindData.hxx [new file with mode: 0755]
src/WOKNT/WOKNT_Handle.hxx [new file with mode: 0755]
src/WOKNT/WOKNT_MixedOutput.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_MixedOutput.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_OutErrOutput.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_OutErrOutput.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_Path.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_Path.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_Path.lxx [new file with mode: 0755]
src/WOKNT/WOKNT_PathIterator.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_PathIterator.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_RegExp.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_RegExp.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_ReplIfCh.c [new file with mode: 0755]
src/WOKNT/WOKNT_ReplIfChWith.c [new file with mode: 0755]
src/WOKNT/WOKNT_Shell.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_Shell.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_Shell.lxx [new file with mode: 0755]
src/WOKNT/WOKNT_ShellManager.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_ShellManager.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_ShellOutput.cdl [new file with mode: 0755]
src/WOKNT/WOKNT_ShellOutput.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_Shell_1.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_TimeStat.hxx [new file with mode: 0755]
src/WOKNT/WOKNT_WNT_BREAK.hxx [new file with mode: 0755]
src/WOKNT/WOKNT_WOKSteps.edl [new file with mode: 0755]
src/WOKNT/WOKNT_chmod.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_cmp.c [new file with mode: 0755]
src/WOKNT/WOKNT_cp.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_mv.cxx [new file with mode: 0755]
src/WOKNT/WOKNT_regexp.h [new file with mode: 0755]
src/WOKNT/WOKNT_regexp_1.c [new file with mode: 0755]
src/WOKNT/WOKNT_rm.cxx [new file with mode: 0755]

diff --git a/src/WOKNT/FILES b/src/WOKNT/FILES
new file mode 100755 (executable)
index 0000000..e1fe42b
--- /dev/null
@@ -0,0 +1,17 @@
+WOKNT_regexp.h
+WOKNT_regexp_1.c
+WOKNT_TimeStat.hxx
+WOKNT_Shell_1.cxx
+WOKNT_WNT_BREAK.hxx
+WOKNT_ReplIfChWith.c
+WOKNT_ReplIfCh.c
+WOKNT_cmp.c
+WOKNT_CopyIfCh.c
+WOKNT_chmod.cxx
+WOKNT_rm.cxx
+WOKNT_mv.cxx
+WOKNT_cp.cxx
+WOKNT_WOKSteps.edl
+WOKNT_Handle.hxx
+WOKNT_FindData.hxx
+WOKNT_Dword.hxx
diff --git a/src/WOKNT/WOKNT.cdl b/src/WOKNT/WOKNT.cdl
new file mode 100755 (executable)
index 0000000..866a3ec
--- /dev/null
@@ -0,0 +1,110 @@
+-- File:       WOKNT.cdl
+-- Created:    Mon Jul 22 15:58:28 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+package WOKNT
+
+    ---Purpose: This package defines utility classes for
+    --          WOK++ for Windows NT.
+
+ uses
+  MMgt, 
+  OSD, 
+  TCollection,
+  TColStd,
+  SortTools,
+  EDL,
+  WOKTools
+
+ is
+
+
+    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, PDBFile, DLLFile, EXEFile, 
+                                  UnknownFile, NoExtFile;
+
+   enumeration RESyntax        is RESyntaxAWK, RESyntaxEGREP, RESyntaxGREP, RESyntaxEMACS;
+
+    -----------------------
+    ---Category: classes---
+    -----------------------
+
+  ---class FDescr;
+  class AdmFile; 
+  class Path;
+  class PathIterator;
+
+  class Shell;
+  class ShellManager;
+
+  class RegExp;
+
+  private deferred class ShellOutput;
+  private          class MixedOutput;
+  private          class OutErrOutput;
+
+
+  private class CompareOfString;
+
+  private class StackOfHandle
+       instantiates    Stack  from TCollection ( Handle from WOKNT );
+
+  private class SequenceOfShell 
+       instantiates  Sequence from TCollection ( Shell from  WOKNT);
+
+       
+  private deferred class PrivCompareOfString 
+       instantiates   Compare from TCollection ( HAsciiString from TCollection );
+
+  private class Array1OfString 
+       instantiates    Array1 from TCollection ( HAsciiString from TCollection );
+
+  private class QuickSortOfString 
+       instantiates QuickSort from SortTools (
+                                HAsciiString    from TCollection,
+                                Array1OfString  from WOKNT,
+                                CompareOfString from WOKNT );
+
+  private class Array1OfRegExp 
+       instantiates    Array1 from TCollection ( RegExp from WOKNT );
+
+
+    ------------------------------
+    ---Category: imported types---
+    ------------------------------
+
+ imported TimeStat;
+
+ private imported FindData;
+ private imported Handle;
+ private imported Dword;
+    ----------------------------
+    ---Category: enumerations---
+    ----------------------------
+
+ enumeration ExecutionMode is
+   SynchronousMode, AsynchronousMode;
+  
+ enumeration OutputMode is
+   OutErrMixed, OutErrSeparated;
+
+ SystemLastError returns Integer from Standard;
+ SystemMessage(i : Integer from Standard) 
+    returns CString from Standard;
+
+ LastSystemMessage
+       returns CString from Standard;
+
+end WOKNT;
diff --git a/src/WOKNT/WOKNT.cxx b/src/WOKNT/WOKNT.cxx
new file mode 100755 (executable)
index 0000000..d42030c
--- /dev/null
@@ -0,0 +1,49 @@
+
+
+
+#ifdef WNT
+
+#include <windows.h>
+
+#ifdef CreateFile
+# undef CreateFile
+#endif  // CreateFile
+
+#ifdef CreateDirectory
+# undef CreateDirectory
+#endif  // CreateFile
+
+#ifdef RemoveDirectory
+# undef RemoveDirectory
+#endif  // CreateFile
+
+#include <WOKNT.hxx>
+
+
+Standard_Integer WOKNT::SystemLastError() 
+{
+  return GetLastError();
+}
+
+Standard_CString WOKNT::SystemMessage(const Standard_Integer errCode) 
+{
+  static Standard_Character buffer[ 1024 ];
+  
+  if(!FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                    0, errCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
+                    buffer, 2048, NULL)) 
+    { 
+      wsprintf ( buffer, "error code %d", errCode );
+      SetLastError ( errCode );
+    }
+  return buffer;
+}
+Standard_CString WOKNT::LastSystemMessage() 
+{
+  return SystemMessage(SystemLastError());
+}
+
+
+
+
+#endif
diff --git a/src/WOKNT/WOKNT_AdmFile.cdl b/src/WOKNT/WOKNT_AdmFile.cdl
new file mode 100755 (executable)
index 0000000..b0ce3f1
--- /dev/null
@@ -0,0 +1,36 @@
+-- File:       WOKNT_AdmFile.cdl
+-- Created:    Wed Jul 24 12:59:45 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+class AdmFile from WOKNT inherits File from OSD
+
+    ---Purpose: reads file in WOK format
+    --          - lines beginning by '#' are ignored
+    --          - lines terminating by '\' are continued
+    --          - empty lines are ignored
+
+ uses
+    AsciiString             from TCollection,
+    HAsciiString            from TCollection,
+    HSequenceOfHAsciiString from TColStd,
+    Path                    from WOKNT
+    
+ raises
+    ProgramError from Standard
+    
+ is
+    Create ( aPath : Path from WOKNT ) returns AdmFile from WOKNT;
+       ---Purpose: creates a class instance
+
+    Read ( me : out )
+     returns HSequenceOfHAsciiString from TColStd
+     raises  ProgramError            from Standard;
+       ---Purpose: reads a file in WOK format
+
+    Name ( me ) returns AsciiString from TCollection;
+end AdmFile;
diff --git a/src/WOKNT/WOKNT_AdmFile.cxx b/src/WOKNT/WOKNT_AdmFile.cxx
new file mode 100755 (executable)
index 0000000..6c14fae
--- /dev/null
@@ -0,0 +1,103 @@
+#define STRICT
+#include <windows.h>
+
+#include <WOKNT_AdmFile.ixx>
+
+#include <WOKTools_Messages.hxx>
+#include <OSD_Protection.hxx>
+
+#define MAX_LINE_LENGTH 1024
+
+#define RAISE() Standard_ProgramError :: Raise (  TEXT( "WOKNT_AdmFile :: Read () failed" )  );
+
+WOKNT_AdmFile :: WOKNT_AdmFile ( const Handle( WOKNT_Path )& aPath ) :
+                    OSD_File (   OSD_Path (  aPath -> Name () -> String ()  )   ) {
+
+}  // end constructor
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_AdmFile :: Read () {
+
+ TCollection_AsciiString                   str;
+ Handle( TColStd_HSequenceOfHAsciiString ) retVal = new TColStd_HSequenceOfHAsciiString;
+
+ if (  !Exists ()  ) {
+   
+  ErrorMsg << TEXT( "WOKNT_AdmFile :: Read (): " << "file '" ) << Name ().ToCString ()
+           << TEXT( "' does not exists" ) << endm;
+  RAISE();
+ } else if (  KindOfFile () != OSD_FILE  ) {
+  ErrorMsg << TEXT( "WOKNT_AdmFile :: Read (): " << "file '" ) << Name ().ToCString ()
+           << TEXT( "' is not a file" ) << endm;
+  RAISE();
+  
+ } else {
+  Standard_Boolean fNext = Standard_False;
+  Standard_Boolean isNext;
+  Standard_Integer nRead;
+
+  Open (  OSD_ReadOnly, OSD_Protection ()  );
+
+  while ( 1 ) {
+  
+   ReadLine ( str, MAX_LINE_LENGTH, nRead );
+
+   if (  IsAtEnd () || Failed ()  ) break;
+
+   str.LeftAdjust ();
+
+   if (  !str.IsEmpty () && str.Value ( 1 ) != TEXT( '#' )  ) {
+   
+    if (   str.Value (  str.Length ()  ) == TEXT( '\\' )   ) {
+    
+     str.Trunc (  str.Length () - 1  );
+     isNext = Standard_True;
+    
+    } else
+
+     isNext = Standard_False;
+
+    if ( fNext )
+
+     retVal -> Value (  retVal -> Length ()  ) -> AssignCat (  str.ToCString ()  );
+
+    else
+
+     retVal -> Append (   new TCollection_HAsciiString (  str.ToCString ()  )   );
+
+    fNext = isNext;
+   
+   } else
+
+    fNext = Standard_False;
+  
+  }  // end while
+ }  // end else
+
+ Close ();
+
+ if (  Failed ()  ) {
+  Perror ();
+  RAISE();
+ }  // end if
+
+ return retVal;
+
+}  // end WOKNT_AdmFile :: Read
+
+TCollection_AsciiString WOKNT_AdmFile :: Name () const {
+
+ TCollection_AsciiString retVal;
+ OSD_Path                path;
+
+ Path ( path );
+ path.SystemName ( retVal );
+
+ return retVal;
+
+}  // end WOKNT_AdmFile :: Name
diff --git a/src/WOKNT/WOKNT_CompareOfString.cdl b/src/WOKNT/WOKNT_CompareOfString.cdl
new file mode 100755 (executable)
index 0000000..ef3540f
--- /dev/null
@@ -0,0 +1,33 @@
+-- File:       WOKNT_CompareOfString.cdl
+-- Created:    Wed Jul 31 11:31:03 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+private class CompareOfString from WOKNT inherits
+              PrivCompareOfString from WOKNT
+
+    ---Purpose: defines string comparator class
+
+ uses
+  HAsciiString from TCollection
+
+ is
+  Create;
+    ---Purpose: creates a class instance
+
+  IsLower ( me; Left, Right : HAsciiString from TCollection )
+   returns Boolean from Standard is redefined;
+    ---Purpose: returns True if <Left> is lower than <Right>
+
+  IsGreater ( me; Left, Right : HAsciiString from TCollection )
+   returns Boolean from Standard is redefined;
+    ---Purpose: returns True if <Left> is greater than <Right>.
+
+  IsEqual ( me; Left, Right : HAsciiString from TCollection )
+   returns Boolean from Standard is redefined;
+    ---Purpose: returns True when <Right> and <Left> are equal.
+
+end CompareOfString;         
diff --git a/src/WOKNT/WOKNT_CompareOfString.cxx b/src/WOKNT/WOKNT_CompareOfString.cxx
new file mode 100755 (executable)
index 0000000..a64a07a
--- /dev/null
@@ -0,0 +1,36 @@
+#include <WOKNT_CompareOfString.ixx>
+
+WOKNT_CompareOfString :: WOKNT_CompareOfString () {
+
+}  // end constructor
+
+Standard_Boolean WOKNT_CompareOfString ::
+                  IsLower (
+                   const Handle( TCollection_HAsciiString )& Left,
+                   const Handle( TCollection_HAsciiString )& Right
+                  ) const {
+
+ return Left -> IsLess ( Right );
+
+}  // end WOKNT_CompareOfString :: IsLower
+
+Standard_Boolean WOKNT_CompareOfString ::
+                  IsGreater (
+                   const Handle( TCollection_HAsciiString )& Left,
+                   const Handle( TCollection_HAsciiString )& Right
+                  ) const {
+
+ return Left -> IsGreater ( Right );
+
+}  // end WOKNT_CompareOfString :: IsGreater
+
+Standard_Boolean WOKNT_CompareOfString ::
+                  IsEqual (
+                   const Handle( TCollection_HAsciiString )& Left,
+                   const Handle( TCollection_HAsciiString )& Right
+                  ) const {
+
+ return Left -> IsSameString ( Right );
+
+}  // end WOKNT_CompareOfString :: IsEqual
+
diff --git a/src/WOKNT/WOKNT_CopyIfCh.c b/src/WOKNT/WOKNT_CopyIfCh.c
new file mode 100755 (executable)
index 0000000..029fbe9
--- /dev/null
@@ -0,0 +1,25 @@
+#define STRICT
+#include <windows.h>
+
+extern int wokCMP ( int, char** );
+
+__declspec( dllexport ) int wokCopyIfCh ( int argc, char** argv ) {
+
+ int    status;
+ char*  newArgs[ 3 ];
+
+ if ( argc != 3 ) return 2;
+
+ newArgs[ 0 ] = "wokCMP";
+ newArgs[ 1 ] = argv[ 1 ];
+ newArgs[ 2 ] = argv[ 2 ];
+
+ status = wokCMP ( 3, newArgs ); 
+
+ if ( status )
+
+  status = CopyFile ( argv[ 1 ], argv[ 2 ],FALSE ) ? 0 : 2;
+
+ return status;
+
+}  /* end main */
diff --git a/src/WOKNT/WOKNT_Dword.hxx b/src/WOKNT/WOKNT_Dword.hxx
new file mode 100755 (executable)
index 0000000..0faaa5e
--- /dev/null
@@ -0,0 +1,11 @@
+// File:       WOKNT_Dword.hxx
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKNT_Dword_HeaderFile
+#define WOKNT_Dword_HeaderFile
+
+typedef unsigned long WOKNT_Dword;
+
+#endif
diff --git a/src/WOKNT/WOKNT_FindData.hxx b/src/WOKNT/WOKNT_FindData.hxx
new file mode 100755 (executable)
index 0000000..440ca4c
--- /dev/null
@@ -0,0 +1,37 @@
+// File:       WOKUtils_Timeval.hxx
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKNT_FindData_HeaderFile
+#define WOKNT_FindData_HeaderFile
+
+#ifdef WNT
+#include <windows.h>
+
+typedef WIN32_FIND_DATA WOKNT_FindData;
+
+#ifdef CreateFile
+# undef CreateFile
+#endif  // CreateFile
+
+#ifdef CreateDirectory
+# undef CreateDirectory
+#endif  // CreateFile
+
+#ifdef RemoveDirectory
+# undef RemoveDirectory
+#endif  // CreateFile
+
+
+
+
+#else
+
+
+typedef int WOKNT_FindData ;
+
+
+#endif
+
+#endif
diff --git a/src/WOKNT/WOKNT_Handle.hxx b/src/WOKNT/WOKNT_Handle.hxx
new file mode 100755 (executable)
index 0000000..b4bf39b
--- /dev/null
@@ -0,0 +1,35 @@
+// File:       WOKNT_Handle.hxx
+// Author:     Jean GAUTIER
+//             <jga@cobrax>
+
+
+#ifndef WOKNT_Handle_HeaderFile
+#define WOKNT_Handle_HeaderFile
+
+#ifdef WNT
+#include <windows.h>
+
+typedef HANDLE WOKNT_Handle ;
+
+#ifdef CreateFile
+# undef CreateFile
+#endif  // CreateFile
+
+#ifdef CreateDirectory
+# undef CreateDirectory
+#endif  // CreateFile
+
+#ifdef RemoveDirectory
+# undef RemoveDirectory
+#endif  // CreateFile
+
+
+#else
+
+
+typedef int WOKNT_Handle ;
+
+
+#endif
+
+#endif
diff --git a/src/WOKNT/WOKNT_MixedOutput.cdl b/src/WOKNT/WOKNT_MixedOutput.cdl
new file mode 100755 (executable)
index 0000000..5588047
--- /dev/null
@@ -0,0 +1,69 @@
+-- File:       WOKNT_MixedOutput.cdl
+-- Created:    Tue Jul 30 10:19:51 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+private class MixedOutput from WOKNT inherits ShellOutput from WOKNT
+
+    ---Purpose: manages output of sub-process ( creates a pipe ).
+    --          Standard output stream and standard error stream are MIXED.
+
+ uses
+  HSequenceOfHAsciiString from TColStd
+  
+ is
+  Create returns MixedOutput from WOKNT;
+    ---Purpose: creates a class instance
+
+  Cleanup ( me : out ) is redefined virtual;
+    ---Purpose: dummy method to be used in derived class
+    ---C++:     alias ~
+
+  OpenStdOut ( me : out ) returns Integer from Standard is redefined static;
+    ---Purpose: creates a pipe for reading a standard output of sub-process
+    --          and returns a pipe handle.
+    ---Warning: returns INVALID_HANDLE_VALUE in case of failure
+
+  CloseStdOut ( me : out ) is redefined static;
+    ---Purpose: closes write end of the 'STDOUT' pipe
+
+  OpenStdErr ( me : out ) returns Integer from Standard is virtual;
+    ---Purpose: creates a pipe for reading a standard error output of sub-process
+    --          and returns a pipe handle
+    ---Warning: this method is simply calling 'OpenStdOut' method
+
+  CloseStdErr ( me : out ) is redefined virtual;
+    ---Purpose: closes write end of the 'STDERR' pipe
+    ---Warning: this method is simply calling 'CloseStdOut' method
+
+  Clear ( me : out ) is redefined virtual;
+    ---Purpose: clears output buffer of sub-process
+
+  Echo ( me : out ) returns HSequenceOfHAsciiString from TColStd is redefined static;
+    ---Purpose: returns standard output of sub-process
+    ---Warning: returns NULL object if there is nothing to read
+
+  Errors ( me : out ) returns HSequenceOfHAsciiString from TColStd is redefined virtual;
+    ---Purpose: returns standard error output of sub-process
+    ---Warning: this method is simply calling 'Echo' method
+
+  SyncStdOut ( me : out ) returns HSequenceOfHAsciiString from TColStd is redefined static;
+    ---Purpose: waits for sub-process termination ( until the write end of pipe
+    --          will be closed ).
+    ---Warning: write end of pipe MUST BE CLOSED by parent process immediately
+    --          after creation of the child process else this method will
+    --          NEVER return. Use ONLY 'CloseStdOut' method for this purpose.
+
+  SyncStdErr ( me : out ) returns HSequenceOfHAsciiString from TColStd is redefined virtual;
+    ---Purpose: same as 'SyncStdOut' method
+    ---Warning: use 'CloseStdErr' method to close write end of pipe
+
+ fields
+  myOutHandle : Integer                 from Standard is protected;
+  myStdOut    : HSequenceOfHAsciiString from TColStd  is protected;
+  
+end MixedOutput;
diff --git a/src/WOKNT/WOKNT_MixedOutput.cxx b/src/WOKNT/WOKNT_MixedOutput.cxx
new file mode 100755 (executable)
index 0000000..1a87e19
--- /dev/null
@@ -0,0 +1,190 @@
+#define STRICT
+#include <windows.h>
+
+#include <WOKNT_MixedOutput.ixx>
+
+#include <TCollection_HAsciiString.hxx>
+#include <OSD_WNT.h>
+
+#define MAX_LINE_LENGTH 2048
+
+void                                      __fastcall _WOKNT_clear_pipe ( HANDLE );
+DWORD                                     __fastcall _WOKNT_nb_to_read ( HANDLE );
+Handle( TColStd_HSequenceOfHAsciiString ) __fastcall _WOKNT_read_pipe ( OSD_File*, HANDLE );
+void                                      __fastcall _WOKNT_create_pipe (
+                                                      Standard_Integer*, Standard_Integer*
+                                                     );
+
+WOKNT_MixedOutput :: WOKNT_MixedOutput () {
+
+}  // end constructor
+
+void WOKNT_MixedOutput :: Cleanup () {
+
+ CloseStdOut ();
+ WOKNT_ShellOutput :: Cleanup ();
+
+}  // end WOKNT_MixedOutput :: Cleanup
+
+Standard_Integer WOKNT_MixedOutput :: OpenStdOut () {
+
+ _WOKNT_create_pipe ( &myFileChannel, &myOutHandle );
+ myIO |= ( FLAG_PIPE | FLAG_READ_PIPE );
+
+ return myOutHandle;
+
+}  // end WOKNT_MixedOutput :: OpenStdOut
+
+void WOKNT_MixedOutput :: CloseStdOut () {
+
+ if (  ( HANDLE )myOutHandle != INVALID_HANDLE_VALUE  ) {
+  CloseHandle (  ( HANDLE )myOutHandle  );
+  myOutHandle = ( Standard_Integer )INVALID_HANDLE_VALUE;
+
+ }  // end if
+
+}  // end WOKNT_MixedOutput :: CloseStdOut
+
+Standard_Integer WOKNT_MixedOutput :: OpenStdErr () {
+
+ return (  ( HANDLE )myOutHandle == INVALID_HANDLE_VALUE  ) ?
+         OpenStdOut () : myOutHandle;
+
+}  // end WOKNT_MixedOutput :: OpenStdErr
+
+void WOKNT_MixedOutput :: CloseStdErr () {
+
+ CloseStdOut ();
+
+}  // end WOKNT_MixedOutput :: CloseStdErr
+
+void WOKNT_MixedOutput :: Clear () {
+
+ _WOKNT_clear_pipe (  ( HANDLE )myFileChannel  );
+
+}  // end WOKNT_MixedOutput :: Clear
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_MixedOutput :: Echo () {
+
+ return _WOKNT_read_pipe (  this, ( HANDLE )myFileChannel  );
+
+}  // end WOKNT_MixedOutput :: Echo
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_MixedOutput :: Errors () {
+
+ return Echo ();
+
+}  // end WOKNT_MixedOutput :: Errors
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_MixedOutput :: SyncStdOut () {
+
+ DWORD                                     dummy;
+ Handle( TColStd_HSequenceOfHAsciiString ) retVal;
+
+ if (  ( HANDLE )myFileChannel != INVALID_HANDLE_VALUE  ) {
+  while (  ReadFile (  ( HANDLE )myFileChannel, NULL, 0, ( LPDWORD )&dummy, NULL )  ) {
+  
+   if (  retVal.IsNull ()  )
+
+    retVal = new TColStd_HSequenceOfHAsciiString ();
+
+   retVal -> Append (  Echo ()  );
+
+  }  // end while
+
+  CloseStdOut ();
+ }  // end if
+
+ return retVal;
+
+}  // end WOKNT_MixedOutput :: SyncStdOut
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_MixedOutput :: SyncStdErr () {
+
+ return SyncStdOut ();
+
+}  // end WOKNT_MixedOutput :: SyncStdErr
+
+DWORD __fastcall _WOKNT_nb_to_read ( HANDLE hPipe ) {
+
+ DWORD retVal = 0;
+
+ PeekNamedPipe ( hPipe, NULL, 0, NULL, &retVal, NULL );
+
+ return retVal;
+
+}  // end _WOKNT_nb_to_read
+
+void __fastcall _WOKNT_clear_pipe ( HANDLE hPipe ) {
+
+ PBYTE buffer = NULL;
+ DWORD dwBytesToRead;
+ DWORD dwBuffSize = 0;
+
+ while (  dwBytesToRead = _WOKNT_nb_to_read ( hPipe )  ) {
+  if ( dwBytesToRead > dwBuffSize ) {
+  
+   if ( buffer != NULL ) delete [] buffer;
+
+   buffer = new BYTE[ dwBuffSize = dwBytesToRead ];
+  
+  }  // end if
+
+  ReadFile ( hPipe, buffer, dwBuffSize, &dwBytesToRead, NULL );
+ }  // end while
+
+ if ( buffer != NULL ) delete [] buffer;
+
+}  // end _WOKNT_clear_pipe
+
+Handle( TColStd_HSequenceOfHAsciiString ) __fastcall _WOKNT_read_pipe (
+                                                      OSD_File* aFile, HANDLE hPipe
+                                                     ) {
+
+ DWORD                                     dwBytes;
+ DWORD                                     dwBytesRead = 0;
+ Standard_Integer                          dummy;
+ TCollection_AsciiString                   aLine;
+ Handle( TColStd_HSequenceOfHAsciiString ) retVal =
+  new TColStd_HSequenceOfHAsciiString ();
+
+ while (  dwBytes = _WOKNT_nb_to_read ( hPipe )  ) {
+  dwBytesRead += dwBytes;
+
+  aFile -> ReadLine ( aLine, MAX_LINE_LENGTH, dummy );
+
+  retVal -> Append (  new TCollection_HAsciiString ( aLine )  );
+
+ }  // end while
+
+ if ( dwBytesRead == 0 ) retVal.Nullify ();
+
+ return retVal;
+
+}  // end _WOKNT_read_pipe
+
+void __fastcall _WOKNT_create_pipe (
+                 Standard_Integer* readPipe, Standard_Integer* writePipe
+                ) {
+                
+ SECURITY_ATTRIBUTES sa;
+
+ sa.nLength              = sizeof ( SECURITY_DESCRIPTOR );  // structure size
+ sa.lpSecurityDescriptor = NULL;                            // default protection
+ sa.bInheritHandle       = TRUE;                            // inheritable handle
+
+ if (  !CreatePipe (
+         ( PHANDLE )readPipe,   // read end of the pipe
+         ( PHANDLE )writePipe,  // write end of the pipe
+         &sa,                   // protection/inheritance
+         4096                   // buffer size
+        )
+ ) *writePipe = ( Standard_Integer )INVALID_HANDLE_VALUE;
+                
+}  // end _WOKNT_create_pipe
diff --git a/src/WOKNT/WOKNT_OutErrOutput.cdl b/src/WOKNT/WOKNT_OutErrOutput.cdl
new file mode 100755 (executable)
index 0000000..0a49abc
--- /dev/null
@@ -0,0 +1,53 @@
+-- File:       WOKNT_OutErrOutput.cdl
+-- Created:    Tue Jul 30 10:53:50 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+private class OutErrOutput from WOKNT inherits MixedOutput from WOKNT
+
+    ---Purpose: manages output of sub-process ( creates a pipe ).
+    --          Standard output stream and standard error stream are MIXED.
+
+ uses
+  HSequenceOfHAsciiString from TColStd
+  
+ is
+  Create returns OutErrOutput from WOKNT;
+    ---Purpose: creates a class instance
+
+  Cleanup ( me : out ) is redefined static;
+    ---Purpose: closes read end of the 'STDERR' handle
+    ---C++:     alias ~
+
+  OpenStdErr ( me : out ) returns Integer from Standard is redefined static;
+    ---Purpose: creates a pipe for reading a standard error output of sub-process
+    --          and returns a pipe handle
+    ---Warning: returns INVALID_HANDLE_VALUE in case of failure 
+
+  CloseStdErr ( me : out ) is redefined static;
+    ---Purpose: closes write end of the 'STDERR' pipe
+
+  Clear ( me : out ) is redefined static;
+    ---Purpose: clears output buffer of sub-process
+
+  Errors ( me : out ) returns HSequenceOfHAsciiString from TColStd is redefined static;
+    ---Purpose: returns standard error output of sub-process
+    ---Warning: returns NULL object if there is nothing to read
+
+  SyncStdErr ( me : out ) returns HSequenceOfHAsciiString from TColStd is redefined static;
+    ---Purpose: waits for sub-process termination ( until the write end of pipe
+    --          will be closed ).
+    ---Warning: write end of pipe MUST BE CLOSED by parent process immediately
+    --          after creation of the child process else this method will
+    --          NEVER return. Use ONLY 'CloseStdErr' method for this purpose.
+
+ fields
+  myErrHandleR : Integer                 from Standard;
+  myErrHandleW : Integer                 from Standard;
+  myStdErr     : HSequenceOfHAsciiString from TColStd;
+
+end OutErrOutput;
diff --git a/src/WOKNT/WOKNT_OutErrOutput.cxx b/src/WOKNT/WOKNT_OutErrOutput.cxx
new file mode 100755 (executable)
index 0000000..051176e
--- /dev/null
@@ -0,0 +1,103 @@
+#define STRICT
+#include <windows.h>
+
+#include <WOKNT_OutErrOutput.ixx>
+
+#include <OSD_WNT.h>
+
+void                                      __fastcall _WOKNT_clear_pipe ( HANDLE );
+DWORD                                     __fastcall _WOKNT_nb_to_read ( HANDLE );
+Handle( TColStd_HSequenceOfHAsciiString ) __fastcall _WOKNT_read_pipe ( OSD_File*, HANDLE );
+void                                      __fastcall _WOKNT_create_pipe (
+                                                      Standard_Integer*, Standard_Integer*
+                                                     );
+
+WOKNT_OutErrOutput :: WOKNT_OutErrOutput () {
+
+}  // end constructor
+
+void WOKNT_OutErrOutput :: Cleanup () {
+
+ CloseStdOut ();
+ CloseStdErr ();
+
+ if (  ( HANDLE )myErrHandleR != INVALID_HANDLE_VALUE  ) {
+  CloseHandle (  ( HANDLE )myErrHandleR  );
+  myErrHandleR = ( Standard_Integer )INVALID_HANDLE_VALUE;
+
+ }  // end if
+
+ WOKNT_ShellOutput :: Cleanup ();
+
+}  // end WOKNT_OutErrOutput :: Cleanup
+
+Standard_Integer WOKNT_OutErrOutput :: OpenStdErr () {
+
+ _WOKNT_create_pipe ( &myErrHandleR, &myErrHandleW );
+ myIO |= ( FLAG_PIPE | FLAG_READ_PIPE );
+
+ return myErrHandleW;
+
+}  // end WOKNT_OutErrOutput :: OpenStdErr
+
+void WOKNT_OutErrOutput :: CloseStdErr () {
+
+ if (  ( HANDLE )myErrHandleW != INVALID_HANDLE_VALUE  ) {
+  CloseHandle (  ( HANDLE )myErrHandleW  );
+  myErrHandleW = ( Standard_Integer )INVALID_HANDLE_VALUE;
+
+ }  // end if
+
+}  // end WOKNT_OutErrOutput :: CloseStdErr
+
+void WOKNT_OutErrOutput :: Clear () {
+
+ WOKNT_MixedOutput :: Clear ();
+
+ _WOKNT_clear_pipe (  ( HANDLE )myErrHandleR  );
+
+}  // end WOKNT_OutErrOutput :: Clear
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_OutErrOutput :: Errors () {
+
+ Handle( TColStd_HSequenceOfHAsciiString ) retVal;
+ Standard_Integer                          handle;
+
+ handle        = myFileChannel;
+ myFileChannel = myErrHandleR;
+
+ retVal = _WOKNT_read_pipe (  this, ( HANDLE )myFileChannel  );
+
+ myFileChannel = handle;
+
+ return retVal;
+
+}  // end WOKNT_OutErrOutput :: Errors
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_OutErrOutput :: SyncStdErr () {
+
+ DWORD                                     dummy;
+ Handle( TColStd_HSequenceOfHAsciiString ) retVal;
+
+ if (  ( HANDLE )myErrHandleR != INVALID_HANDLE_VALUE  ) {
+  while (  ReadFile (  ( HANDLE )myErrHandleR, NULL, 0, ( LPDWORD )&dummy, NULL )  ) {
+  
+   if (  retVal.IsNull ()  )
+
+    retVal = new TColStd_HSequenceOfHAsciiString ();
+
+   retVal -> Append (  Errors ()  );
+
+  }  // end while
+
+  CloseStdErr ();
+  CloseHandle (  ( HANDLE )myErrHandleR  );
+ }  // end if
+
+ return retVal;
+
+}  // end WOKNT_OutErrOutput :: SyncStdErr
diff --git a/src/WOKNT/WOKNT_Path.cdl b/src/WOKNT/WOKNT_Path.cdl
new file mode 100755 (executable)
index 0000000..cc0dbb7
--- /dev/null
@@ -0,0 +1,130 @@
+-- File:       WOKNT_Path.cdl
+-- Created:    Mon Jul 22 17:17:38 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+class Path from WOKNT
+inherits TShared from MMgt
+
+ uses
+    Path         from OSD,
+    TimeStat     from WOKNT,
+    Extension    from WOKNT,
+    Dword        from WOKNT,
+    HAsciiString from TCollection
+    
+ raises
+    OSDError from OSD
+    
+ is
+    Create returns mutable Path from WOKNT;
+       ---Purpose: creates a class instance
+
+    Create( aPath : HAsciiString from TCollection )
+     returns mutable Path from WOKNT;
+       ---Purpose: creates a class instance
+
+    Create( aDir, aName : HAsciiString from TCollection )
+     returns mutable Path from WOKNT;
+       ---Purpose: creates a class instance
+
+    Create( aDir, aName : CString from Standard )
+     returns mutable Path from WOKNT;
+       ---Purpose: creates a class instance
+
+    CheckAttr(me:mutable) returns Boolean from Standard is private;
+    ---C++:     inline
+   
+    GetAttr(me:mutable) 
+     returns Boolean from Standard is private;
+
+    Exists(me:mutable) returns Boolean from Standard;
+       ---Purpose: tests whether specified entity exists or not
+
+    CreateDirectory(me:mutable; fCreateParents : Boolean from Standard = Standard_False)
+     returns Boolean from Standard;
+       ---Purpose: creates a directory
+
+    CreateFile(me:mutable; fCreateParents : Boolean from Standard = Standard_False)
+     returns Boolean from Standard;
+       ---Purpose: creates a file
+
+    RemoveDirectory(me:mutable; fRemoveChilds : Boolean from Standard = Standard_False)
+     returns Boolean from Standard;
+       ---Purpose: removes a directory
+
+    RemoveFile(me:mutable)
+     returns Boolean from Standard;
+       ---Purpose: removes a file
+
+    MoveTo(me: mutable; aDestPath : Path from WOKNT )
+     returns Boolean from Standard;
+       ---Purpose: moves a file/directory to the new location
+       ---Warning: raises if the operation was failed
+
+    GetMDate(me: mutable ) returns TimeStat from WOKNT;
+       ---Purpose: returns last modification date of the file
+
+    Extension(me) returns Extension from WOKNT;
+       ---Purpose: returns a file extension
+
+    BaseName(me) returns HAsciiString from TCollection;
+       ---Purpose: returns a base name of full file name
+
+    DirName(me) returns HAsciiString from TCollection;
+       ---Purpose: returns path component of full file name
+
+    FileName(me) returns HAsciiString from TCollection;
+       ---Purpose: returns file name ( name.ext )
+
+    Name(me) returns HAsciiString from TCollection;
+       ---Purpose: returns full name
+       ---C++:     return const &
+       ---C++:     inline
+
+    MDate(me:mutable) returns TimeStat from WOKNT;
+       ---Purpose: returns known modification date of path
+       ---C++:     inline
+
+    ResetMDate(me: mutable );
+       ---Purpose: resets modification date
+       ---C++:     inline
+
+    IsOlder(me: mutable; aName : Path from WOKNT ) returns Boolean from Standard;
+       ---Purpose: compares last modification time of the file
+
+    IsNewer(me: mutable; aName : Path from WOKNT ) returns Boolean from Standard;
+       ---Purpose: compares last modification time of the file
+
+    IsDirectory(me:mutable)
+       returns Boolean from Standard;
+
+    IsFile(me:mutable) returns Boolean from Standard;
+       ---Purpose: checks whether 'myPath' is a file or not
+
+    IsSymLink(me:mutable) returns Boolean from Standard;
+       ---Purpose: checks whether specified file a symbolic link or not
+
+    ReducedPath(me)
+     returns Path from WOKNT;
+        ---Purpose: reduces Path as much as possible (reads links)
+
+    IsSameFile(me ; aPath : Path from WOKNT) returns Boolean from Standard;
+       ---Purpose:
+
+    IsWriteAble(me:mutable) returns Boolean from Standard;
+
+    ExtensionName(me) returns HAsciiString from TCollection;
+
+
+ fields
+    myPath    : HAsciiString from TCollection;
+    myDate    : TimeStat     from WOKNT;
+    myAttr    : Dword        from WOKNT;
+    myAttrGet : Boolean      from Standard;
+end Path;
diff --git a/src/WOKNT/WOKNT_Path.cxx b/src/WOKNT/WOKNT_Path.cxx
new file mode 100755 (executable)
index 0000000..98ba8f5
--- /dev/null
@@ -0,0 +1,617 @@
+#define STRICT
+#include <windows.h>
+
+#ifdef THIS
+# undef THIS
+#endif 
+
+#ifdef CreateFile
+# undef CreateFile
+#endif 
+
+#ifdef CreateDirectory
+# undef CreateDirectory
+#endif  
+
+#ifdef RemoveDirectory
+# undef RemoveDirectory
+#endif 
+
+#include <WOKNT_Path.ixx>
+
+#include <WOKNT.hxx>
+#include <WOKNT_PathIterator.hxx>
+
+#include <WOKTools_Messages.hxx>
+//#include <OSD_File.hxx>
+//#include <OSD_Directory.hxx>
+//#include <OSD_Protection.hxx>
+
+#ifndef _INC_TCHAR
+# include <tchar.h>
+#endif  // _INC_TCHAR
+
+#include <io.h>
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <share.h>
+
+extern "C" int wokCMP(int, char** );
+
+//static int _writeable(OSD_SingleProtection );
+
+WOKNT_Path::WOKNT_Path()
+: myAttrGet(Standard_False), myDate(-1)
+{
+}  
+
+WOKNT_Path::WOKNT_Path(const Handle(TCollection_HAsciiString)& aPath)
+: myPath(aPath), myDate(-1), myAttrGet(Standard_False)
+{
+  myPath = aPath;
+  myDate = -1;
+}  
+
+WOKNT_Path::WOKNT_Path(const Handle(TCollection_HAsciiString)& aDir, const Handle(TCollection_HAsciiString)& aName) 
+: myDate(-1), myAttrGet(Standard_False)
+{
+  Handle(TCollection_HAsciiString) str = new TCollection_HAsciiString;
+  
+  str->AssignCat(aDir);
+  str->AssignCat(TEXT("/"));
+  str->AssignCat(aName);
+  
+  myPath = str;
+}
+
+WOKNT_Path::WOKNT_Path(const Standard_CString aDir, const Standard_CString aName) 
+: myDate(-1), myAttrGet(Standard_False)
+{
+  Handle( TCollection_HAsciiString)str = new TCollection_HAsciiString;
+  
+  str -> AssignCat(aDir );
+  str -> AssignCat( TEXT( "/") );
+  str -> AssignCat(aName );
+  
+  myPath = str;
+} 
+
+
+Standard_Boolean WOKNT_Path::GetAttr() 
+{
+  if(myAttrGet) return Standard_True;
+  if(myPath.IsNull()) return Standard_False;
+  myAttrGet = Standard_True;
+  if((myAttr = GetFileAttributes( myPath -> ToCString())) != 0xFFFFFFFF)
+    return Standard_True;
+  else
+    return Standard_False;
+}
+
+Standard_Boolean WOKNT_Path::Exists()
+{
+  if(myPath.IsNull()) return Standard_False;
+  CheckAttr();
+  if(myAttr != 0xFFFFFFFF )
+    return Standard_True;
+  else
+    return Standard_False;
+} 
+
+Standard_Boolean WOKNT_Path::CreateDirectory(const Standard_Boolean fCreateParents) 
+{
+  if(Exists())
+    {
+      if(!IsDirectory())
+       {
+         ErrorMsg << TEXT( "WOKNT_Path::CreateDirectory (): ")<< myPath
+           << TEXT( " exists and is not a directory"       )<< endm;
+         return Standard_False;
+       }
+      return Standard_True;
+    }
+  
+  Handle(WOKNT_Path) aParent = new WOKNT_Path(DirName());
+  
+  if(!aParent->Exists()) 
+    {  
+      if(fCreateParents) 
+       {
+         if(!aParent->CreateDirectory(fCreateParents)) 
+           return Standard_False;
+       }
+      else
+       {
+         ErrorMsg << TEXT( "WOKNT_Path::CreateDirectory") 
+           << "Parent directory " << aParent->Name() << TEXT(" does not exist")<< endm;
+         return Standard_False;
+       }
+    }
+  else
+    {
+      if(!aParent->IsDirectory())
+       {
+         ErrorMsg << TEXT( "WOKNT_Path::CreateDirectory") 
+           << "Parent  " << aParent->Name() << TEXT(" exists and is not a directory")<< endm;
+         return Standard_False;
+       }
+    }
+  
+#ifdef UNICODE
+# define CreateDirectory CreateDirectoryW
+#else
+# define CreateDirectory CreateDirectoryA
+#endif 
+  
+  if(CreateDirectory(myPath->ToCString(), NULL))
+    return Standard_True;
+  return Standard_False;
+
+#ifdef CreateFile
+# undef CreateFile
+#endif  // CreateFile
+  
+#ifdef CreateDirectory
+# undef CreateDirectory
+#endif  // CreateFile
+  
+#ifdef RemoveDirectory
+# undef RemoveDirectory
+#endif  // CreateFile
+  
+}
+
+Standard_Boolean WOKNT_Path::CreateFile(const Standard_Boolean fCreateParents) 
+{
+  if(Exists())
+    {
+      if(IsDirectory()) 
+       {
+         ErrorMsg << TEXT( "WOKNT_Path::CreateFile" )
+           << myPath << TEXT( " exists and is a directory")<< endm;
+         return Standard_False;
+       }
+      return Standard_True;
+    } 
+
+  Handle(WOKNT_Path) aParent = new WOKNT_Path(DirName());
+  
+  if(aParent->Exists())
+    {
+      if(!aParent->IsDirectory()) 
+       {
+         ErrorMsg << TEXT( "WOKNT_Path::CreateFile" )
+           << TEXT("Parent diectory ")<< aParent->Name() << TEXT(" exists and is not a directory")<< endm;
+         return Standard_False;
+       }
+    }
+  else
+    {
+      aParent->CreateDirectory(fCreateParents);
+    }
+
+#ifdef UNICODE
+# define CreateFile CreateFileW
+#else
+# define CreateFile CreateFileA
+#endif 
+
+  HANDLE theFile = CreateFile(myPath->ToCString(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  
+#ifdef CreateFile
+# undef CreateFile
+#endif  // CreateFile
+  
+  
+  if(theFile == INVALID_HANDLE_VALUE) 
+    {
+      ErrorMsg << TEXT( "WOKNT_Path::CreateFile")
+       << TEXT( "Creation of ") << myPath << " failed" << endm;
+      return Standard_False;
+    }
+  else
+    {
+      CloseHandle(theFile);
+      return Standard_True;
+    }
+}
+  
+
+Standard_Boolean WOKNT_Path::RemoveDirectory(const Standard_Boolean fRemoveChilds) 
+{
+
+  if( myPath.IsNull () )
+    { 
+      ErrorMsg << TEXT( "WOKNT_Path    ::RemoveDirectory (): " )
+       << TEXT( " invalid directory name(null )")<< endm;
+      return Standard_False;
+    }
+  
+  Standard_Boolean isempty = Standard_True;
+
+  if(!fRemoveChilds)
+    {
+      WOKNT_PathIterator anit(this);
+      
+      if(anit.More())
+       {
+         ErrorMsg << TEXT( "WOKNT_Path::RemoveDirectory" )
+           << TEXT( "Could not remove ")<< myPath  << ": directory is not empty" << endm;
+         return Standard_False;
+       }
+    } else {
+
+      WOKNT_PathIterator anit(this);
+      
+      while(anit.More())
+       {
+         Handle(WOKNT_Path) apath = anit.PathValue();
+
+         if(apath->IsDirectory())
+           {
+             if(!apath->RemoveDirectory(Standard_True)) isempty = Standard_False;
+           }
+         else
+           {
+             if(apath->RemoveFile()) isempty = Standard_False;
+           }
+         anit.Next();
+       }
+
+    }  // end if    
+
+  if(isempty)
+    {
+
+#ifdef UNICODE
+# define RemoveDirectory RemoveDirectoryW
+#else
+# define RemoveDirectory RemoveDirectoryA
+#endif
+      if(!RemoveDirectory(myPath->ToCString()))
+       {
+         ErrorMsg << TEXT( "WOKNT_Path::RemoveDirectory" )
+           << TEXT( "could not remove ") << myPath << ": " << WOKNT::SystemMessage(GetLastError()) << endm;
+         return Standard_False;
+       }   
+#ifdef RemoveDirectory
+# undef RemoveDirectory
+#endif
+    }
+  else
+    {
+      ErrorMsg << TEXT( "WOKNT_Path::RemoveDirectory" )
+           << TEXT( "Could not empty ") << myPath  << endm;
+      return Standard_False;
+    }
+  return Standard_True;
+}
+
+Standard_Boolean WOKNT_Path::RemoveFile()
+{
+  if( myPath.IsNull())
+    {
+      ErrorMsg << TEXT( "WOKNT_Path::RemoveFile" )
+       << TEXT( "Invalid file name(null )")<< endm;
+      return Standard_False;
+    }
+
+  if(!DeleteFile(myPath->ToCString()))
+    {
+      ErrorMsg << TEXT( "WOKNT::RemoveFile" )
+       << TEXT( "Failed to remove ") << myPath << ": " << WOKNT::SystemMessage(GetLastError()) << endm;
+      return Standard_False;
+    }
+  return Standard_True;
+}
+
+WOKNT_TimeStat WOKNT_Path::GetMDate () {
+
+  int          fd;
+  struct _stat buffer;
+  BOOL         fOK = FALSE;
+
+  __try {
+
+    if( ( fd = _sopen (
+                      myPath -> ToCString (), _O_RDONLY, _SH_DENYNO
+                      )
+        )== -1
+       ){
+      
+      fOK = TRUE;
+      __leave;
+
+    }  // end if
+
+    if( _fstat(fd, &buffer)== -1 )__leave;
+
+    fOK = TRUE;
+
+  }  // end __try
+
+  __finally {
+    
+    if(fd != -1)close(fd );
+
+  }  // end __finally
+
+  if(!fOK )
+
+    OSD_OSDError::Raise( TEXT( "WOKNT_Path::GetMDate () failed") );
+
+  return myDate = buffer.st_mtime;
+
+}  // end WOKNT_Path::GetMDate
+
+WOKNT_Extension WOKNT_Path::Extension () const {
+
+  Standard_CString ptr = _tcsrchr( myPath -> ToCString (), TEXT( '.') );
+
+  myPath -> RightAdjust ();
+
+  if(ptr++ != NULL){
+    
+    if(  _tcscmp( ptr, TEXT( "cdl"     ))== 0  )return WOKNT_CDLFile;
+    if(  _tcscmp( ptr, TEXT( "odl"     ))== 0  )return WOKNT_ODLFile;
+    if(  _tcscmp( ptr, TEXT( "idl"     ))== 0  )return WOKNT_IDLFile;
+
+    if(  _tcscmp( ptr, TEXT( "hxx"     ))== 0  )return WOKNT_HXXFile;
+    if(  _tcscmp( ptr, TEXT( "ixx"     ))== 0  )return WOKNT_IXXFile;
+    if(  _tcscmp( ptr, TEXT( "jxx"     ))== 0  )return WOKNT_JXXFile;
+    if(  _tcscmp( ptr, TEXT( "lxx"     ))== 0  )return WOKNT_LXXFile;
+    if(  _tcscmp( ptr, TEXT( "gxx"     ))== 0  )return WOKNT_GXXFile;
+    if(  _tcscmp( ptr, TEXT( "pxx"     ))== 0  )return WOKNT_PXXFile;
+    if(  _tcscmp( ptr, TEXT( "h"       ))== 0  )return WOKNT_HFile;
+    if(  _tcscmp( ptr, TEXT( "inc"     ))== 0  )return WOKNT_INCFile;
+
+    if(  _tcscmp( ptr, TEXT( "template"))== 0  )return WOKNT_TemplateFile;
+    
+    if(  _tcscmp( ptr, TEXT( "ddl"     ))== 0  )return WOKNT_DDLFile;
+    if(  _tcscmp( ptr, TEXT( "DB"      ))== 0  )return WOKNT_DBFile;
+    if(  _tcscmp( ptr, TEXT( "FDDB"    ))== 0  )return WOKNT_FDDBFile;
+    if(  _tcscmp( ptr, TEXT( "libshema"))== 0  )return WOKNT_LibSchemaFile;
+    if(  _tcscmp( ptr, TEXT( "asdb"    ))== 0  )return WOKNT_AppSchemaFile;
+    if(  _tcscmp( ptr, TEXT( "ho2"     ))== 0  )return WOKNT_HO2File;
+
+    if(  _tcscmp( ptr, TEXT( "lex"     ))== 0  )return WOKNT_LexFile;
+    if(  _tcscmp( ptr, TEXT( "yacc"    ))== 0  )return WOKNT_YaccFile;
+    if(  _tcscmp( ptr, TEXT( "lws"     ))== 0  )return WOKNT_LWSFile;
+    if(  _tcscmp( ptr, TEXT( "psw"     ))== 0  )return WOKNT_PSWFile;
+
+    if(  _tcscmp( ptr, TEXT( "cxx"     ))== 0  )return WOKNT_CXXFile;
+    if(  _tcscmp( ptr, TEXT( "cpp"     ))== 0  )return WOKNT_CXXFile;
+    if(  _tcscmp( ptr, TEXT( "c"       ))== 0  )return WOKNT_CFile;
+    if(  _tcscmp( ptr, TEXT( "f"       ))== 0  )return WOKNT_F77File;
+
+    if(  _tcscmp( ptr, TEXT( "obj"     ))== 0  )return WOKNT_ObjectFile;
+    if(  _tcscmp( ptr, TEXT( "lib"     ))== 0  )return WOKNT_LIBFile;
+    if(  _tcscmp( ptr, TEXT( "imp"     ))== 0  )return WOKNT_IMPFile;
+    if(  _tcscmp( ptr, TEXT( "def"     ))== 0  )return WOKNT_DEFile;
+    if(  _tcscmp( ptr, TEXT( "pdb"     ))== 0  )return WOKNT_PDBFile;
+    if(  _tcscmp( ptr, TEXT( "dll"     ))== 0  )return WOKNT_DLLFile;
+    if(  _tcscmp( ptr, TEXT( "exe"     ))== 0  )return WOKNT_EXEFile;
+    if(  _tcscmp( ptr, TEXT( "exp"     ))== 0  )return WOKNT_EXPFile;
+
+    if(  _tcscmp( ptr, TEXT( "rc"      ))== 0  )return WOKNT_RCFile;
+    if(  _tcscmp( ptr, TEXT( "res"     ))== 0  )return WOKNT_RESFile;
+
+    if(  _tcscmp( ptr, TEXT( "dat"     ))== 0  )return WOKNT_DATFile;
+    if(  _tcscmp( ptr, TEXT( "xwd"     ))== 0  )return WOKNT_IconFile;
+    if(  _tcscmp( ptr, TEXT( "txt"     ))== 0  )return WOKNT_TextFile;
+
+
+    if(  _tcscmp( ptr, TEXT( "ll"       ))== 0  )return WOKNT_LispFile;
+    if(  _tcscmp( ptr, TEXT( "m"       ))== 0  ) return WOKNT_MFile;
+
+    return WOKNT_UnknownFile;
+
+  } else
+
+    return WOKNT_NoExtFile;
+
+}  
+
+Handle(TCollection_HAsciiString) WOKNT_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 == TEXT( '\\') || chr == TEXT( '/')) 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 == TEXT( '.')) break;
+      --pos;
+    }
+  
+  if(pos)
+    retVal = retVal->SubString(1, pos-1);
+  return retVal;
+}
+
+Handle(TCollection_HAsciiString) WOKNT_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 == TEXT( '\\')|| chr == TEXT( '/'))
+       {
+         if(fRetry || pos != len) break;
+       
+         retVal -> Trunc(pos - 1 );
+         fRetry = Standard_True;
+       }
+      --pos;
+    }
+
+  if(pos > 1 )
+    retVal -> Trunc(pos - 1 );
+  return retVal;
+}
+
+Handle( TCollection_HAsciiString)WOKNT_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 == TEXT( '\\') || chr == TEXT( '/'))
+       {
+         if(pos == retVal->Length())
+           {
+             retVal->Trunc(retVal->Length()-1);
+           }
+         else
+           break;
+       }
+      --pos;
+    }
+  
+  if(pos)
+    retVal = retVal->SubString(pos+1, retVal->Length());
+  return retVal;
+}
+
+Handle( TCollection_HAsciiString)WOKNT_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 == TEXT( '.')) break;
+      --pos;
+    }
+  
+  if(pos)
+    retVal = retVal->SubString(pos, retVal->Length());
+  return retVal;
+}
+
+Standard_Boolean WOKNT_Path::MoveTo(const Handle(WOKNT_Path)& aDestPath) 
+{
+  if(!CheckAttr()) return Standard_False;
+
+  if(!(myAttr&FILE_ATTRIBUTE_DIRECTORY)) 
+    {
+      if (!MoveFileEx(myPath->ToCString (), aDestPath->Name()->ToCString (), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
+       {
+         ErrorMsg << TEXT("WOKNT_Path::MoveTo")
+           << WOKNT::SystemMessage(GetLastError()) << endm;
+         ErrorMsg << TEXT("WOKNT_Path::MoveTo")
+           << TEXT("Failed to move ") << myPath << " to " << aDestPath->Name() << endm;
+         return Standard_False;
+       }
+    }
+  else
+    {
+      if (!MoveFileEx(myPath->ToCString (), aDestPath->Name()->ToCString (), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
+       {
+           ErrorMsg << TEXT("WOKNT_Path::MoveTo")
+             << WOKNT::SystemMessage(GetLastError()) << endm;
+           ErrorMsg << TEXT("WOKNT_Path::MoveTo")
+             << TEXT("Failed to move ") << myPath << " to " << aDestPath->Name() << endm;
+           return Standard_False;
+       }
+    }
+  return Standard_True;
+} 
+
+//=======================================================================
+//function : ReducedPath
+//purpose  : 
+//=======================================================================
+Handle(WOKNT_Path) WOKNT_Path::ReducedPath() const
+{
+  Handle(WOKNT_Path) areduced;
+  Handle(TCollection_HAsciiString) astr;
+
+  astr = new TCollection_HAsciiString(Name());
+  areduced = new WOKNT_Path(astr);
+  return areduced;
+}
+
+Standard_Boolean WOKNT_Path::IsSymLink ()  
+{
+  // stupid question on NT
+  return Standard_False;
+}
+
+Standard_Boolean WOKNT_Path::IsOlder(const Handle(WOKNT_Path)& aName)
+{
+  return aName->MDate() > MDate();
+} 
+
+Standard_Boolean WOKNT_Path::IsNewer(const Handle(WOKNT_Path)& aName) 
+{
+  return aName -> MDate () < MDate ();
+}
+
+Standard_Boolean WOKNT_Path::IsSameFile(const Handle( WOKNT_Path )& aPath)const {
+
+  Standard_CString newArgs[ 3 ];
+
+  if(myPath.IsNull()) return Standard_False;
+  if(aPath.IsNull())  return Standard_False;
+  if(aPath->Name().IsNull()) return Standard_False;
+  
+  newArgs[ 0 ] = "wokCMP";
+  newArgs[ 1 ] = myPath -> ToCString ();
+  newArgs[ 2 ] = aPath  -> Name () -> ToCString ();
+
+  return !wokCMP(3, newArgs)? Standard_True : Standard_False;
+
+
+}
+
+Standard_Boolean WOKNT_Path::IsWriteAble ()  {
+  CheckAttr();
+  if(myAttr == 0xffffffff || myAttr & FILE_ATTRIBUTE_READONLY) return Standard_False;
+  return Standard_True;
+}
+
+Standard_Boolean  WOKNT_Path::IsDirectory () 
+{
+  if(!CheckAttr())  return Standard_False;
+  if(myAttr & FILE_ATTRIBUTE_DIRECTORY) return Standard_True;
+  return Standard_False;
+}
+
+Standard_Boolean WOKNT_Path::IsFile () 
+{
+  if(!CheckAttr())             return Standard_False;
+  if(myAttr & FILE_ATTRIBUTE_DIRECTORY) return Standard_False; 
+  return Standard_True;
+}
diff --git a/src/WOKNT/WOKNT_Path.lxx b/src/WOKNT/WOKNT_Path.lxx
new file mode 100755 (executable)
index 0000000..17fe433
--- /dev/null
@@ -0,0 +1,24 @@
+#include <TCollection_HAsciiString.hxx>
+#include <WOKNT_TimeStat.hxx>
+
+inline const Handle(TCollection_HAsciiString)& WOKNT_Path::Name() const
+{
+  return myPath;
+}
+
+inline WOKNT_TimeStat WOKNT_Path :: MDate() 
+{
+ if(myDate == -1) GetMDate();
+ return myDate;
+}
+
+inline void WOKNT_Path::ResetMDate()
+{
+ myDate = -1;
+}
+
+inline Standard_Boolean WOKNT_Path::CheckAttr ()  
+{
+  if(myAttrGet) return Standard_True;
+  return GetAttr();
+}
diff --git a/src/WOKNT/WOKNT_PathIterator.cdl b/src/WOKNT/WOKNT_PathIterator.cdl
new file mode 100755 (executable)
index 0000000..a710be2
--- /dev/null
@@ -0,0 +1,65 @@
+-- File:       WOKNT_PathIterator.cdl
+-- Created:    Mon Aug 03 15:37:45 1998
+-- Author:     
+--             <jga@GROMINEX>
+---Copyright:   Matra Datavision 1998
+
+
+class PathIterator from WOKNT
+
+
+uses 
+    Boolean from Standard,
+    HAsciiString from TCollection,
+    AsciiString from TCollection,
+    FindData from WOKNT,
+    Handle from WOKNT,
+    StackOfHandle   from WOKNT,
+    Path from WOKNT
+    
+is
+
+
+    Create(apath : Path from WOKNT; recursive : Boolean from Standard = Standard_False; mask : CString from Standard = "*")
+       returns PathIterator from WOKNT;
+
+    SkipDots(me:out) is private;
+       
+    Push(me:out; data : FindData from WOKNT; handle : Handle from WOKNT) is private;
+    Pop(me:out) is private;
+    
+    IsDots(myclass; aname : CString from Standard)
+       returns Boolean from Standard is private;
+    
+    Next(me:out);
+    
+    
+    PathValue(me)
+       returns Path from WOKNT;
+    
+    LevelValue(me)
+       returns Integer from Standard;
+       
+    NameValue(me)
+       returns HAsciiString from TCollection;
+
+    BrowsedPath(me)
+       returns Path from WOKNT;        
+               
+    More(me)
+       returns Boolean from Standard;
+
+    Destroy(me);
+    ---C++: alias operator~
+
+fields
+
+    mymask      : AsciiString from TCollection;
+    mypath      : Path from WOKNT;
+    mydata      : FindData from WOKNT;
+    myStack     : StackOfHandle from WOKNT;
+    mymore      : Boolean from Standard;
+    myrecflag   : Boolean from Standard;
+
+end;
+
diff --git a/src/WOKNT/WOKNT_PathIterator.cxx b/src/WOKNT/WOKNT_PathIterator.cxx
new file mode 100755 (executable)
index 0000000..fd8ddd5
--- /dev/null
@@ -0,0 +1,185 @@
+
+
+#include <WOKNT_PathIterator.ixx>
+#include <WOKNT_Path.hxx>
+
+#include <WOKTools_Messages.hxx>
+
+#include <stream.h>
+
+WOKNT_PathIterator::WOKNT_PathIterator(const Handle(WOKNT_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());
+
+  myStack.Push(FindFirstFile(mask.ToCString(), &mydata));
+  if(myStack.Top() == INVALID_HANDLE_VALUE ) 
+    mymore = Standard_False;
+  else
+    mymore = Standard_True;
+
+  SkipDots();
+}
+
+
+Standard_Boolean WOKNT_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 WOKNT_PathIterator::SkipDots() 
+{
+  while(IsDots((Standard_CString)mydata.cFileName) && !myStack.IsEmpty())
+    {
+      if(!FindNextFile(myStack.Top(), &mydata))
+       {
+         if(GetLastError() == ERROR_NO_MORE_FILES) 
+           {
+             if(!myStack.IsEmpty())
+               Pop();
+             else
+               mymore = Standard_False;
+           }
+         else 
+           {
+             ErrorMsg << "WOKNT_PathIterator::Next" 
+               << "Error occured in directory lookup : " << (int)GetLastError() << endm;
+             mymore = Standard_False;
+           }
+       }
+    }
+}
+
+
+void WOKNT_PathIterator::Push(const WOKNT_FindData& data, const WOKNT_Handle& handle)
+{
+  if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && myrecflag)
+    {
+      if(!IsDots(mydata.cFileName) && myrecflag)
+       {
+         mypath = new WOKNT_Path(mypath->Name(), new TCollection_HAsciiString(mydata.cFileName));
+         TCollection_AsciiString mask;
+         mask = mypath->Name()->String();
+         mask.AssignCat("/");
+         mask.AssignCat(mymask);
+
+         WOKNT_Handle nextone = FindFirstFile(mask.ToCString(), &mydata);
+         myStack.Push(nextone);
+         SkipDots();
+
+         if(!myStack.IsEmpty())
+           {
+             if(myStack.Top() == INVALID_HANDLE_VALUE ) 
+               mymore = Standard_False;
+             else
+               mymore = Standard_True;
+           }
+         else
+           mymore = Standard_False;
+       }
+    }
+  else
+    {
+      ErrorMsg << "WOKNT_PathIterator::Push"
+       << "Only a directory can be pushed in PathIterator" << endm;
+    }
+}
+
+void WOKNT_PathIterator::Pop()
+{
+  if(!myStack.IsEmpty())
+    {
+      FindClose(myStack.Top());
+      myStack.Pop();
+      if(!myStack.IsEmpty()) 
+       {
+         if(!FindNextFile(myStack.Top(), &mydata))
+           {
+             if(GetLastError() == ERROR_NO_MORE_FILES) 
+               {
+                 if(myStack.IsEmpty())
+                   mymore = Standard_False;
+                 else
+                   Pop();
+               }
+           }
+         else
+           SkipDots();
+         mypath = new WOKNT_Path(mypath->DirName());
+       }
+      else 
+       mymore = Standard_False;
+    }
+}
+
+
+void WOKNT_PathIterator::Next()
+{
+  if(myStack.Top()!=INVALID_HANDLE_VALUE && mymore) 
+    {
+      if(!IsDots(mydata.cFileName) && mydata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY && myrecflag) 
+       Push(mydata, myStack.Top());
+      else
+       {
+         if(!FindNextFile(myStack.Top(), &mydata))
+           {
+             if(GetLastError() == ERROR_NO_MORE_FILES) 
+               {
+                 if(!myStack.IsEmpty())
+                   Pop();
+
+                 if(myStack.IsEmpty())
+                   mymore = Standard_False;
+               }
+             else 
+               {
+                 ErrorMsg << "WOKNT_PathIterator::Next" 
+                   << "Error occured in directory lookup : " << (int)GetLastError() << endm;
+                 mymore = Standard_False;
+               }
+           }
+       }
+    }
+}
+
+Handle(WOKNT_Path) WOKNT_PathIterator::PathValue()  const
+{
+  if(mydata.cFileName) return new WOKNT_Path(mypath->Name(), new TCollection_HAsciiString((char * const)mydata.cFileName));
+  return Handle(WOKNT_Path)();
+}
+
+Handle(TCollection_HAsciiString) WOKNT_PathIterator::NameValue()  const
+{
+
+  if(mydata.cFileName) return new TCollection_HAsciiString((char * const)mydata.cFileName);
+  return Handle(TCollection_HAsciiString)();
+  
+}
+
+Standard_Integer WOKNT_PathIterator::LevelValue() const
+{
+  return myStack.Depth();
+}
+
+Standard_Boolean WOKNT_PathIterator::More() const
+{
+  return mymore;
+}
+
+void WOKNT_PathIterator::Destroy() const
+{
+  if(myStack.Top() != INVALID_HANDLE_VALUE) FindClose(myStack.Top());
+}
+
diff --git a/src/WOKNT/WOKNT_RegExp.cdl b/src/WOKNT/WOKNT_RegExp.cdl
new file mode 100755 (executable)
index 0000000..af5a2ae
--- /dev/null
@@ -0,0 +1,88 @@
+-- File:       WOKNT_RegExp.cdl
+-- Created:    Fri Aug  2 09:43:37 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+class RegExp from WOKNT inherits TShared from MMgt
+
+    ---Purpose: provides regular expression matching and searching
+
+ uses
+  RESyntax     from WOKNT,
+  HAsciiString from TCollection
+
+ raises
+  ProgramError from Standard
+
+ is
+  Create returns mutable RegExp from WOKNT;
+    ---Purpose: creates a class instance
+
+  Create (
+   aPattern  : HAsciiString from TCollection;
+   aSyntax   : RESyntax     from WOKNT = WOKNT_RESyntaxAWK;
+   aTransTbl : Address      from Standard = NULL;
+   aTblLen   : Integer      from Standard = 0
+  ) returns mutable RegExp  from WOKNT
+    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 WOKNT = WOKNT_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/WOKNT/WOKNT_RegExp.cxx b/src/WOKNT/WOKNT_RegExp.cxx
new file mode 100755 (executable)
index 0000000..ad71db2
--- /dev/null
@@ -0,0 +1,159 @@
+
+#include <WOKNT_RegExp.ixx>
+
+#include <WOKNT_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
+
+WOKNT_RegExp :: WOKNT_RegExp () 
+: myBuffer(NULL), myAlloc(Standard_False)
+{
+}  // end constructor ( 1 )
+
+WOKNT_RegExp :: WOKNT_RegExp (
+                    const Handle( TCollection_HAsciiString )& aPattern,
+                    const WOKNT_RESyntax                   aSyntax,
+                    const Standard_Address                    aTransTbl,
+                    const Standard_Integer                    aTblLen
+                   ) 
+: myBuffer(NULL), myAlloc(Standard_False)
+{
+ SetPattern ( aPattern, aSyntax, aTransTbl, aTblLen );
+}  // end constructro ( 2 )
+
+void WOKNT_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 WOKNT_RegExp :: Destroy
+
+void WOKNT_RegExp :: SetPattern (
+                         const Handle( TCollection_HAsciiString )& aPattern,
+                         const WOKNT_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 WOKNT_RESyntaxAWK:
+   syntax = RE_SYNTAX_AWK;
+  break;
+
+  case WOKNT_RESyntaxEGREP:
+   syntax = RE_SYNTAX_EGREP;
+  break;
+
+  case WOKNT_RESyntaxGREP:
+   syntax = RE_SYNTAX_GREP;
+  break;
+
+  case WOKNT_RESyntaxEMACS:
+   syntax = RE_SYNTAX_EMACS;
+  break;
+
+  default:
+   RAISE( "WOKNT_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( "WOKNT_RegExp (): error parsing specified pattern - " )  );
+  _tcscat (  errBuff, errMsg );
+
+  Standard_ProgramError :: Raise ( errBuff );
+ }  // end if
+
+ re_compile_fastmap ( BUFFER );
+
+}  // end WOKNT_RegExp :: SetPattern
+
+Standard_Integer WOKNT_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 WOKNT_RegExp :: Search
+
+Standard_Integer WOKNT_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 WOKNT_RegExp :: Match
+
diff --git a/src/WOKNT/WOKNT_ReplIfCh.c b/src/WOKNT/WOKNT_ReplIfCh.c
new file mode 100755 (executable)
index 0000000..500404a
--- /dev/null
@@ -0,0 +1,30 @@
+#define STRICT
+#include <process.h>
+#include <windows.h>
+
+extern int wokCMP ( int, char** );
+
+__declspec( dllexport ) int wokReplIfCh ( int argc, char** argv ) {
+
+ int    status;
+ char*  newArgs[ 3 ];
+
+ if ( argc != 3 ) return 2;
+
+ newArgs[ 0 ] = "wokCMP";
+ newArgs[ 1 ] = argv[ 1 ];
+ newArgs[ 2 ] = argv[ 2 ];
+
+ status = wokCMP ( 3, newArgs );
+
+ if ( status == 1 )
+
+  status = MoveFileEx (
+               argv[ 1 ], argv[ 2 ], MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING
+                  ) ? 1 : 2;
+
+ DeleteFile ( argv[ 1 ] ) ? 0 : 2;
+
+ return status;
+
+}  /* end main */
diff --git a/src/WOKNT/WOKNT_ReplIfChWith.c b/src/WOKNT/WOKNT_ReplIfChWith.c
new file mode 100755 (executable)
index 0000000..b83c4b2
--- /dev/null
@@ -0,0 +1,30 @@
+#define STRICT
+#include <process.h>
+#include <windows.h>
+
+extern int wokCMP ( int, char** );
+
+__declspec( dllexport ) int wokReplIfChWith ( int argc, char** argv ) {
+
+ int    status;
+ char*  newArgs[ 3 ];
+
+ if ( argc != 4 ) return 2;
+
+ newArgs[ 0 ] = "wokCMP";
+ newArgs[ 1 ] = argv[ 1 ];
+ newArgs[ 2 ] = argv[ 2 ];
+
+ status = wokCMP ( 3, newArgs );
+
+ if ( status == 1 )
+
+  status = MoveFileEx (
+               argv[ 1 ], argv[ 3 ], MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING
+                  ) ? 1 : 2;
+
+ DeleteFile ( argv[ 1 ] ) ? 0 : 2;
+
+ return status;
+
+}  /* end main */
diff --git a/src/WOKNT/WOKNT_Shell.cdl b/src/WOKNT/WOKNT_Shell.cdl
new file mode 100755 (executable)
index 0000000..16c2a5c
--- /dev/null
@@ -0,0 +1,142 @@
+-- File:       WOKNT_Shell.cdl
+-- Created:    Thu Jul 25 12:42:56 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+class Shell from WOKNT inherits TShared from MMgt
+
+    ---Purpose: creates and manages processes
+
+ uses
+  ExecutionMode           from WOKNT,
+  OutputMode              from WOKNT,
+  Path                    from WOKNT,
+  Array1OfString          from WOKNT,
+  HSequenceOfHAsciiString from TColStd,
+  HAsciiString            from TCollection
+  
+ is
+  Create (
+   anExecMode : ExecutionMode from WOKNT = WOKNT_SynchronousMode;
+   anOutMode  : OutputMode    from WOKNT = WOKNT_OutErrMixed
+  ) returns mutable Shell from WOKNT;
+    ---Purpose: creates a class instance
+
+  Destroy ( me : mutable );
+    ---Purpose: destrouys all resources attached to the Shell
+    ---C++:     alias ~
+
+  Launch ( me : mutable );
+    ---Purpose: launches a process
+
+  IsLaunched ( me ) returns Boolean from Standard;
+    ---Purpose: checks whether a process launched or not
+    ---C++:     inline
+
+  Kill ( me : mutable );
+    ---Purpose: terminates a process
+
+  Lock ( me : mutable );
+  
+  UnLock ( me : mutable );
+
+  IsLocked ( me ) returns Boolean from Standard;
+    ---C++:     inline
+  
+  Status ( me ) returns Integer from Standard;
+    ---Purpose: returns process's exit status
+    ---C++:     inline
+
+  Errors ( me : mutable ) returns HSequenceOfHAsciiString from TColStd;
+    ---Purpose: returns process output
+
+  ClearOutput ( me : mutable );
+    ---Purpose: clears process's output
+
+  Send ( me : mutable; aString : HAsciiString from TCollection );
+    ---Purpose: sends a string to the shell
+
+  Execute ( me : mutable; aCmdLine : HAsciiString from TCollection );
+    ---Purpose: executes a shell command
+
+  SyncAndStatus ( me : mutable ) returns Integer from Standard;
+    ---Purpose: waits for process termination and returns its exit status
+
+  BuiltInCommand (
+   me      : mutable;
+   aCmd    : in out HAsciiString from TCollection;
+   doParse : Boolean from Standard = Standard_True 
+  ) returns Boolean from Standard is protected;
+    ---Purpose: checks whether a specified command built-in or not.
+    --          Also provides primary parsing of the commend line
+    --          ( extraction of the environment variables ).
+
+  BuildEnvironment ( me : mutable; aRebuildFlag : Boolean from Standard = Standard_False )
+   returns Address from Standard is protected;
+    ---Purpose: builds environment block for sub-process
+
+  AddEnvironmentVariable (
+   me     : mutable;
+   aName  : HAsciiString from TCollection;
+   aValue : HAsciiString from TCollection
+  );
+    ---Purpose: adds environment variable to the shell's environment block
+
+  RemoveEnvironmentVariable (
+   me    : mutable;
+   aName : HAsciiString from TCollection
+  ); 
+    ---Purpose: removes specified variable from the shell's environment block
+
+  EnvironmentVariable ( me; aName : HAsciiString from TCollection )
+   returns HAsciiString from TCollection;
+    ---Purpose: returns a value for a given environment variable
+    ---Warning: returns a null string if specified variable does not exists
+
+  Echo ( me; aStr : HAsciiString from TCollection );
+    ---Purpose: echoes a string
+
+  SetEcho ( me : mutable );
+    ---Purpose: turns echo on
+    ---C++:     inline
+  
+  UnsetEcho ( me : mutable );
+    ---Purpose: turns echo off
+    ---C++:     inline
+
+  Log ( me; aStr : HAsciiString from TCollection );
+    ---Purpose: logs a string to the file
+  
+  LogInFile ( me : mutable; aPath : Path from WOKNT );
+    ---Purpose: creates log file and turns on logging to the file
+  
+  NoLog ( me : mutable );
+    ---Purpose: turns off logging to file  
+
+ fields
+
+  myOutMode     : OutputMode              from WOKNT;
+  myExecMode    : ExecutionMode           from WOKNT;
+  myStatus      : Integer                 from Standard;
+  myLocked      : Boolean                 from Standard;
+  myEcho        : Boolean                 from Standard;
+  myExeFlag     : Boolean                 from Standard;
+  myKillFlag    : Boolean                 from Standard;
+  myOutput      : Address                 from Standard;
+  myProcess     : Integer                 from Standard;
+  myCmdLine     : HAsciiString            from TCollection;
+  myStdOut      : HSequenceOfHAsciiString from TColStd;
+  myStdErr      : HSequenceOfHAsciiString from TColStd;
+  myEnvironment : HSequenceOfHAsciiString from TColStd;
+  myChannel     : Integer                 from Standard;
+  myDirectory   : HAsciiString            from TCollection;
+  myLogFile     : Path                    from WOKNT;
+
+ friends
+  class ShellManager from WOKNT
+
+end Shell;
diff --git a/src/WOKNT/WOKNT_Shell.cxx b/src/WOKNT/WOKNT_Shell.cxx
new file mode 100755 (executable)
index 0000000..ec3fd20
--- /dev/null
@@ -0,0 +1,610 @@
+#define STRICT
+#include <windows.h>
+#include <tchar.h>
+
+#ifdef CreateFile
+# undef CreateFile
+#endif  // CreateFile
+
+#ifdef CreateDirectory
+# undef CreateDirectory
+#endif  // CreateFile
+
+#ifdef RemoveDirectory
+# undef RemoveDirectory
+#endif  // CreateFile
+
+#include <WOKNT_Shell.ixx>
+
+#include <WOKNT_OutErrOutput.hxx>
+#include <WOKTools_Messages.hxx>
+#include <OSD_Environment.hxx>
+#include <WOKNT_Array1OfString.hxx>
+#include <WOKNT_CompareOfString.hxx>
+#include <WOKNT_QuickSortOfString.hxx>
+
+#include <OSD_Exception_CTRL_BREAK.hxx>
+
+#pragma comment( lib, "user32.lib" )
+
+Standard_CString _WOKNT_get_last_error_text ( void );
+
+Standard_Integer __fastcall _WOKNT_find_environment_variable (
+                             const Handle( TColStd_HSequenceOfHAsciiString )&,
+                             const Handle( TCollection_HAsciiString )&
+                            );
+
+static void _WOKNT_get_env (  Handle( TColStd_HSequenceOfHAsciiString )&  );
+
+WOKNT_Shell :: WOKNT_Shell (
+                   const WOKNT_ExecutionMode anExecMode,
+                   const WOKNT_OutputMode    anOutMode
+                  ) {
+
+ char aDir[1024];\r
+\r
+ GetCurrentDirectory(1024, aDir);\r
+
+ myDirectory = new TCollection_HAsciiString ( aDir );
+
+ myOutput      = ( anOutMode == WOKNT_OutErrMixed ) ?
+                  new WOKNT_MixedOutput () :
+                  new WOKNT_OutErrOutput ();
+ myCmdLine     = new TCollection_HAsciiString ();
+ myProcess     = ( Standard_Integer )INVALID_HANDLE_VALUE;
+ myLocked      = Standard_False;
+ myExecMode    = anExecMode;
+ myOutMode     = anOutMode;
+ myEcho        = Standard_False;
+
+ _WOKNT_get_env ( myEnvironment );
+
+}  // end constructor
+
+void WOKNT_Shell :: Destroy () {
+
+ Kill ();
+
+ delete myOutput;
+
+}  // end WOKNT_Shell :: Destroy
+
+void WOKNT_Shell :: Launch () {
+
+}  // end WOKNT_Shell :: Launch
+
+void WOKNT_Shell :: Kill () {
+
+ if (  ( HANDLE )myProcess != INVALID_HANDLE_VALUE  ) {
+
+  TerminateProcess (  ( HANDLE )myProcess, ( UINT )-1  );
+
+  if (  ( HANDLE )myChannel != INVALID_HANDLE_VALUE  ) {
+  
+   CloseHandle (  ( HANDLE )myChannel  );
+   myChannel = ( Standard_Integer )INVALID_HANDLE_VALUE;
+  
+  }  // end if
+
+  myKillFlag = Standard_True;
+
+ }  // end if
+
+}  // end WOKNT_Shell :: Kill
+
+void WOKNT_Shell :: Lock () {
+
+ myLocked = Standard_True;
+
+}  // end WOKNT_Shell :: Lock
+
+void WOKNT_Shell :: UnLock () {
+
+ myLocked = Standard_False;
+
+}  // end WOKNT_Shell :: UnLock
+
+void WOKNT_Shell :: ClearOutput () {
+
+ (  ( WOKNT_ShellOutput* )myOutput  ) -> Clear ();
+
+if (  !myStdOut.IsNull ()  ) myStdOut.Nullify ();
+if (  !myStdErr.IsNull ()  ) myStdErr.Nullify ();
+
+}  // end WOKNT_Shell :: ClearOutput
+
+void WOKNT_Shell :: Execute (  const Handle( TCollection_HAsciiString )& aCmdLine  ) {
+
+ int i, numCmd;
+
+ if (  !myExeFlag  ) {
+  Echo ( aCmdLine );
+  Log  ( aCmdLine );
+ } else
+
+
+#ifdef WOK_VERBOSE
+   VerboseMsg("WOK_COMMAND") << "WOKNT_Shell::Execute" << aCmdLine << endm;
+#endif
+
+
+  myExeFlag = Standard_False;
+
+ myKillFlag = Standard_False;
+
+ Handle( TCollection_HAsciiString ) aCommandLine = new TCollection_HAsciiString ();
+
+ if (  !myCmdLine.IsNull ()  ) aCommandLine = myCmdLine;
+
+ aCommandLine -> AssignCat ( aCmdLine );
+
+ if (  !aCmdLine.IsNull ()                         &&
+       !aCmdLine -> IsEmpty ()                     &&
+       !BuiltInCommand ( aCommandLine )            &&
+       ( HANDLE )myProcess == INVALID_HANDLE_VALUE
+ ) {
+
+  PROCESS_INFORMATION                pi;
+  STARTUPINFO                        si;
+  HANDLE                             hStdInput;
+  BOOL                               fRetry;
+  HANDLE                             hStdOut;
+  HANDLE                             hStdErr;
+  SECURITY_ATTRIBUTES                sa;
+  LPVOID                             env;
+  Handle( TCollection_HAsciiString ) cmd = new TCollection_HAsciiString (
+                                                aCommandLine -> String ()
+                                               );
+
+  sa.nLength              = sizeof ( SECURITY_ATTRIBUTES );
+  sa.lpSecurityDescriptor = NULL;
+  sa.bInheritHandle       = TRUE;
+
+  if (  !CreatePipe (
+          &hStdInput, ( PHANDLE )&myChannel, &sa, 0
+         )
+  ) {
+  
+   hStdInput = INVALID_HANDLE_VALUE;
+   myChannel = ( Standard_Integer )INVALID_HANDLE_VALUE;
+  
+  }  // end if
+
+  Handle( TColStd_HSequenceOfHAsciiString ) cmdSeq = new TColStd_HSequenceOfHAsciiString ();
+
+  i = 1;
+
+  while ( TRUE ) {
+
+   aCommandLine = cmd -> Token (  _TEXT( "\x01" ), i++  );
+
+   if (  aCommandLine -> IsEmpty ()  ) break;
+
+   cmdSeq -> Append ( aCommandLine );
+
+  }  // end while
+
+  numCmd = cmdSeq -> Length ();
+
+  if (  myStdOut.IsNull ()  ) myStdOut = new TColStd_HSequenceOfHAsciiString ();
+  if (  myStdErr.IsNull ()  ) myStdErr = new TColStd_HSequenceOfHAsciiString ();
+
+  env = BuildEnvironment ();
+
+  for ( i = 1; i <= numCmd; ++i ) {
+
+   cmd = new TCollection_HAsciiString (  cmdSeq -> Value ( i )  );
+
+   if (
+    BuiltInCommand (  cmd, Standard_False  ) ||
+    cmd -> Value ( 1 ) == TEXT( '@' ) && myStatus
+   ) continue;
+
+   if (  cmd -> Value ( 1 ) == TEXT( '@' )  ) cmd -> Remove ( 1 );
+
+   hStdOut = ( HANDLE )(  ( WOKNT_ShellOutput* )myOutput  ) -> OpenStdOut ();
+   hStdErr = ( HANDLE )(  ( WOKNT_ShellOutput* )myOutput  ) -> OpenStdErr ();
+
+   ZeroMemory (  &si, sizeof ( STARTUPINFO )  );
+   si.cb          = sizeof ( STARTUPINFO );
+   si.dwFlags     = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+   si.wShowWindow = SW_HIDE;
+   si.hStdInput   = hStdInput;
+   si.hStdOutput  = hStdOut;
+   si.hStdError   = hStdErr;
+
+   fRetry = FALSE;
+
+   while ( TRUE ) {
+
+    if (  !CreateProcess (
+            NULL,                        // image name
+            cmd -> ToCString (),         // command line
+            NULL,                        // security attributes for process ( default )
+            NULL,                        // security attributes for primary thread ( default )
+            TRUE,                        // handle inheritance
+            NORMAL_PRIORITY_CLASS,       // normal process with no special scheduling needs
+            env,                         // environment
+            myDirectory -> ToCString (), // current directory
+            &si,                         // startup information
+            &pi                          // process information
+           )
+    ) {
+
+     if (  fRetry || GetLastError () != ERROR_FILE_NOT_FOUND  ) {
+
+      ErrorMsg << TEXT( "WOKNT_Shell :: Execute (): can not execute " )
+               << TEXT( "'" ) << cmd -> ToCString () << TEXT( "' - " )
+               << _WOKNT_get_last_error_text () << endm;
+
+      myProcess = ( Standard_Integer )INVALID_HANDLE_VALUE;
+      (  ( WOKNT_ShellOutput* )myOutput  ) -> Cleanup ();
+      myStatus = -1;
+
+      break;
+
+     } else {
+
+      OSD_Environment comSpec (  TEXT( "ComSpec" )  );
+
+      aCommandLine = cmdSeq -> Value ( i );
+      cmd -> Clear ();
+
+      if (  comSpec.Failed ()  )
+     
+       cmd -> AssignCat (  TEXT( "cmd.exe" )  );
+
+      else
+         
+       cmd -> AssignCat(  comSpec.Value ().ToCString ()  );
+
+      cmd -> AssignCat (  TEXT( " /C " )  );
+      cmd -> AssignCat (  aCommandLine -> ToCString ()  );
+      fRetry = TRUE;
+
+     }  // end else
+
+    } else {
+
+     CloseHandle ( pi.hThread );
+     myProcess = ( Standard_Integer )pi.hProcess;
+
+     if ( myExecMode == WOKNT_SynchronousMode ||
+          numCmd > 1 && i < numCmd
+     ) SyncAndStatus ();
+
+     break;
+
+    }  // end else
+   
+   }  // end while
+
+  }  // end for
+
+  CloseHandle ( hStdInput );
+  delete [] env;
+
+ }  // end if
+
+ if ( myKillFlag && myStatus == -1 )
+  OSD_Exception_CTRL_BREAK :: Raise (  TEXT( "*** INTERRUPT ***" )  );
+
+ myCmdLine -> Clear ();
+
+}  // end WOKNT_Shell :: Execute
+
+void WOKNT_Shell :: Send ( const Handle(TCollection_HAsciiString)& aString ) {
+
+ Standard_Integer i;
+ DWORD            dwBytesWritten;
+
+
+#ifdef WOK_VERBOSE
+   VerboseMsg("WOK_COMMAND") << "WOKNT_Shell::Send" << aString << endm;
+#endif
+
+ myCmdLine -> AssignCat ( aString );
+
+ if (  !myCmdLine.IsNull () &&
+        myCmdLine -> Value (  myCmdLine -> Length ()     ) == TEXT( '\n' ) &&
+               myCmdLine -> Value (  myCmdLine -> Length () - 1 ) != TEXT( '\\' )
+ ) {
+
+  Echo ( myCmdLine );
+  Log  ( myCmdLine );
+
+  myCmdLine -> Trunc (  myCmdLine -> Length () - 1  );
+
+  if (  ( HANDLE )myProcess == INVALID_HANDLE_VALUE ) {
+
+   i         = 1;
+   myExeFlag = Standard_True;
+   Handle( TCollection_HAsciiString ) cmd;
+
+   while ( TRUE ) {
+
+    cmd = myCmdLine -> Token (  _TEXT( "\n" ), i++  );
+
+    if (  cmd -> IsEmpty ()  ) break;
+
+    Execute ( cmd );
+
+   }  // end while
+
+  } else
+   
+   WriteFile (  // send a string to the sub-process
+    ( HANDLE )myChannel, myCmdLine -> ToCString (), myCmdLine -> Length (),
+    &dwBytesWritten, NULL
+   ); 
+  myCmdLine -> Clear ();
+
+ }  // end if
+
+}  // end WOKNT_Shell :: Send
+
+Standard_Integer WOKNT_Shell :: SyncAndStatus () {
+
+ Handle( TColStd_HSequenceOfHAsciiString ) stdOut;
+ Handle( TColStd_HSequenceOfHAsciiString ) stdErr;
+
+ if (  ( HANDLE )myProcess != INVALID_HANDLE_VALUE  ) {
+
+  (  ( WOKNT_ShellOutput* )myOutput  ) -> CloseStdOut ();
+  (  ( WOKNT_ShellOutput* )myOutput  ) -> CloseStdErr ();
+
+  if (  myStdOut.IsNull ()  ) myStdOut = new TColStd_HSequenceOfHAsciiString ();
+  if (  myStdErr.IsNull ()  ) myStdErr = new TColStd_HSequenceOfHAsciiString ();
+
+  stdOut = (  ( WOKNT_ShellOutput* )myOutput  ) -> SyncStdOut ();
+  stdErr = myOutMode == WOKNT_OutErrMixed ?
+            stdOut                           :
+            (  ( WOKNT_ShellOutput* )myOutput  ) -> SyncStdErr ();
+
+  if (  !stdOut.IsNull ()  ) myStdOut -> Append ( stdOut );
+  if (  !stdErr.IsNull ()  ) myStdErr -> Append ( stdErr );
+
+  (  ( WOKNT_ShellOutput* )myOutput  ) -> Cleanup ();
+
+  WaitForSingleObject (  ( HANDLE )myProcess, INFINITE  );
+
+  GetExitCodeProcess (  ( HANDLE )myProcess, ( LPDWORD )&myStatus  );
+  CloseHandle (  ( HANDLE )myProcess  );
+  CloseHandle (  ( HANDLE )myChannel  );
+  myProcess = ( Standard_Integer )INVALID_HANDLE_VALUE;
+  myChannel = ( Standard_Integer )INVALID_HANDLE_VALUE;
+
+ }  // end if
+
+ return myStatus;
+
+}  // end WOKNT_Shell :: SyncAndStatus
+
+Handle( TColStd_HSequenceOfHAsciiString ) WOKNT_Shell :: Errors () {
+
+ Handle( TColStd_HSequenceOfHAsciiString ) retVal =
+  myStdErr.IsNull () ? (  ( WOKNT_ShellOutput* )myOutput  ) -> Errors () : myStdErr;
+
+ return retVal.IsNull () ? new TColStd_HSequenceOfHAsciiString () : retVal;
+
+}  // end WOKNT_Shell :: Errors
+
+Standard_Address WOKNT_Shell :: BuildEnvironment (
+                                    const Standard_Boolean aRebuildFlag
+                                   ) {
+
+ if ( aRebuildFlag ) {
+  myEnvironment.Nullify ();
+
+  _WOKNT_get_env ( myEnvironment );
+
+  return NULL;
+ } else {
+
+  int                      i;
+  Standard_CString         retVal;
+  Standard_CString         ptr;
+  Standard_Integer         len = 0;
+  WOKNT_CompareOfString comp;
+  WOKNT_Array1OfString  env (  1, myEnvironment -> Length ()  );
+
+  for ( i = 1; i <= myEnvironment -> Length (); ++i ) {
+   len += (  lstrlen (  myEnvironment -> Value ( i ) -> ToCString ()  ) + 1  );
+   env.SetValue (  i, myEnvironment -> Value ( i )  );
+  }  // end for
+
+  WOKNT_QuickSortOfString :: Sort ( env, comp );
+
+  retVal = ptr = new Standard_Character[ ++len ];
+
+  for ( i = env.Lower (); i <= env.Upper (); ++i ) {
+   lstrcpy (  ptr, env.Value ( i ) -> ToCString ()  );
+   ptr += (  lstrlen ( ptr ) + 1  );
+  }  // end for
+
+  *ptr = TEXT( '\x00' );
+
+  return retVal;
+
+ }  // end else
+
+}  // end WOKNT_Shell :: BuildEnvironment
+
+void WOKNT_Shell :: AddEnvironmentVariable (
+                        const Handle_TCollection_HAsciiString& aName,
+                        const Handle_TCollection_HAsciiString& aValue
+                       ) {
+
+ Handle( TCollection_HAsciiString ) str = new TCollection_HAsciiString ();
+
+ str -> AssignCat (  aName -> String ().ToCString ()   );
+
+ RemoveEnvironmentVariable ( str );
+
+ str -> AssignCat (  TEXT( "=" )  );
+ str -> AssignCat ( aValue        );
+ myEnvironment -> Prepend ( str );
+
+}  // end WOKNT_Shell :: AddEnvironmentVariable
+
+void WOKNT_Shell :: RemoveEnvironmentVariable (
+                        const Handle_TCollection_HAsciiString& aName
+                       ) {
+
+ Standard_Integer i;
+
+ if (  i = _WOKNT_find_environment_variable ( myEnvironment, aName )  )
+
+  myEnvironment -> Remove ( i );
+
+}  // end WOKNT_Shell :: RemoveEnvironmentVariabl
+
+Handle( TCollection_HAsciiString )
+ WOKNT_Shell :: EnvironmentVariable ( const Handle_TCollection_HAsciiString& aName ) const {
+ Standard_Integer                   i;
+ Handle( TCollection_HAsciiString ) retVal;
+
+ if (  i = _WOKNT_find_environment_variable ( myEnvironment, aName )  )
+
+  retVal = myEnvironment -> Value ( i ) -> Token (  _TEXT( "=" ), 2  );
+
+ return retVal;
+}  // end WOKNT_Shell :: EnvironmentVariable
+
+void WOKNT_Shell :: Echo ( const Handle_TCollection_HAsciiString& aStr ) const {
+
+ if ( myEcho ) {
+  WOKTools_Info shellInfo = InfoMsg;
+
+  shellInfo.Init             ();
+  shellInfo.DontPrintHeader  ();
+  shellInfo.DontPrintContext ();
+
+  shellInfo << TEXT( "WOKNT_Shell :: Echo ()" ) << aStr << endm;
+ }  // end if
+
+}  // end WOKNT_Shell :: Echo
+
+void WOKNT_Shell :: Log ( const Handle_TCollection_HAsciiString& aStr ) const {
+
+ if (  !myLogFile.IsNull ()  ) {
+  ofstream logFile (  myLogFile -> Name () -> ToCString (), ios :: app  );
+
+  if (  logFile.good ()  ) {
+
+   logFile << aStr -> ToCString ();
+   logFile.close ();
+
+  }  // end if
+ }  // end if
+
+}  // end WOKNT_Shell :: Log
+
+void WOKNT_Shell :: LogInFile ( const Handle_WOKNT_Path& aPath ) {
+
+ if (  !aPath.IsNull ()  ) {
+  if (  !aPath -> Exists ()  ) {
+  
+   aPath -> CreateFile ( Standard_True );
+
+   if (  aPath -> Exists ()  )
+
+    myLogFile = aPath;
+  
+  }  // end if
+ }  // end if
+
+}  // end WOKNT_Shell :: LogInFile
+
+void WOKNT_Shell :: NoLog () {
+
+ myLogFile.Nullify ();
+
+}  // end WOKNT_Shell :: NoLog
+
+Standard_CString _WOKNT_get_last_error_text ( void ) {
+
+ static Standard_Character buffer[ 2048 ];
+
+ DWORD errCode = GetLastError ();
+
+ if (  !FormatMessage (
+         FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+         0, errCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
+         buffer, 2048, NULL
+        )
+ ) {
+
+  wsprintf (  buffer, TEXT( "error code %d" ), errCode  );
+  SetLastError ( errCode );
+
+ }  // end if
+
+ return buffer;
+
+}  // end _get_last_error_text
+
+Standard_Integer __fastcall _WOKNT_find_environment_variable (
+                             const Handle( TColStd_HSequenceOfHAsciiString )& envBlock,
+                             const Handle( TCollection_HAsciiString )&        envVar
+                            ) {
+                            
+ Standard_Integer retVal = 0;          
+                            
+ Handle( TCollection_HAsciiString ) str = new TCollection_HAsciiString ();
+
+ str -> AssignCat  (  envVar -> String ().ToCString ()  );
+ str -> AssignCat  (  TEXT( "=" )                       );
+ str -> LeftAdjust ();
+
+ for ( int i = 1; i <= envBlock -> Length (); ++i )
+
+  if (   envBlock -> Value ( i ) -> Search ( str ) == 1   ) {
+  
+   retVal = i;
+   break;
+  
+  }  // end if
+
+ return retVal;
+
+}  // end _WOKNT_find_environment_variable
+
+static void _WOKNT_get_env (  Handle( TColStd_HSequenceOfHAsciiString )& seq  ) {
+
+ Standard_CString ptr, env;
+
+ seq = new TColStd_HSequenceOfHAsciiString ();
+
+ env = ptr = ( Standard_CString )GetEnvironmentStrings ();
+
+  if (  *ptr != TEXT( '\x00' )  )
+
+   do {
+
+    seq -> Append (  new TCollection_HAsciiString ( ptr )  );
+    ptr += (  lstrlen ( ptr ) + 1  );
+
+   } while (  *ptr != TEXT( '\x00' )  );
+
+ FreeEnvironmentStrings ( env );
+
+}  // end _WOKNT_get_env
diff --git a/src/WOKNT/WOKNT_Shell.lxx b/src/WOKNT/WOKNT_Shell.lxx
new file mode 100755 (executable)
index 0000000..1cd4a8f
--- /dev/null
@@ -0,0 +1,31 @@
+#include <WOKNT_ShellOutput.hxx>
+
+inline Standard_Boolean WOKNT_Shell :: IsLaunched () const {
+
+ return Standard_True;
+
+}  // end WOKNT_Shell :: IsLaunched
+
+inline Standard_Integer WOKNT_Shell :: Status () const {
+
+ return myStatus;
+
+}  // end WOKNT_Shell :: Status
+
+inline Standard_Boolean WOKNT_Shell :: IsLocked () const {
+
+ return myLocked;
+
+}  // end WOKNT_Shell :: IsLocked
+
+inline void WOKNT_Shell :: SetEcho () {
+
+ myEcho = Standard_True;
+
+}  // end WOKNT_Shell :: SetEcho
+
+inline void WOKNT_Shell :: UnsetEcho () {
+
+ myEcho = Standard_False;
+
+}  // end WOKNT_Shell :: UnsetEcho
diff --git a/src/WOKNT/WOKNT_ShellManager.cdl b/src/WOKNT/WOKNT_ShellManager.cdl
new file mode 100755 (executable)
index 0000000..6a98ff8
--- /dev/null
@@ -0,0 +1,38 @@
+-- File:       WOKNT_ShellManager.cdl
+-- Created:    Fri Jul 26 17:33:13 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+class ShellManager from WOKNT 
+
+        ---Purpose: shell management
+
+ uses
+  Shell           from WOKNT,
+  SequenceOfShell from WOKNT
+    
+ ---raises
+ --- Exception_CTRL_BREAK from OSD
+ is
+
+  GetShell ( myclass ) returns Shell from WOKNT;
+    ---Purpose: returns one unlocked shell of processes list    
+
+  Arm ( myclass );
+    ---Purpose: sets signal handlers
+
+  UnArm ( myclass );
+    ---Purpose: unsets signal handlers
+
+  KillAll ( myclass );
+    ---Purpose: Terminates all active sub-processes
+
+  Break ( myclass ) ;
+    ---raises OSD_Exception_CTRL_BREAK from OSD;
+    ---Purpose: Checks whethes CTRL-BREAK keystroke was or not.
+    --          if yes then raises
+
+end ShellManager;
diff --git a/src/WOKNT/WOKNT_ShellManager.cxx b/src/WOKNT/WOKNT_ShellManager.cxx
new file mode 100755 (executable)
index 0000000..20896cd
--- /dev/null
@@ -0,0 +1,98 @@
+#define STRICT
+#include <windows.h>
+#include <tchar.h>
+
+
+#include <OSD_Exception_CTRL_BREAK.hxx>
+
+#include <WOKNT_ShellManager.ixx>
+
+#include <WOKNT_Shell.hxx>
+#include <WOKNT_SequenceOfShell.hxx>
+
+static BOOL s_fCtrlBreak;
+
+static WOKNT_SequenceOfShell shells;
+
+static BOOL CALLBACK interruptHandler ( DWORD );
+
+Handle( WOKNT_Shell ) WOKNT_ShellManager :: GetShell () {
+
+ Standard_Integer         i;
+ Handle( WOKNT_Shell ) aShell;
+
+ for ( i = 1; i <= shells.Length (); i++ ) {
+
+  aShell = shells.Value ( i );
+
+  if (  !aShell -> IsLocked ()  ) {
+  
+   aShell -> BuildEnvironment ( Standard_True );
+  
+   return aShell;
+
+  }  // end if
+ }  // end for
+
+ aShell = new WOKNT_Shell ();
+
+ shells.Append ( aShell );
+
+ aShell -> BuildEnvironment ( Standard_True );
+
+ return aShell;
+
+}  // end WOKNT_ShellManager :: GetShell
+
+void WOKNT_ShellManager :: Arm () {
+
+ s_fCtrlBreak = FALSE;
+ SetConsoleCtrlHandler ( &interruptHandler, TRUE );
+
+}  // end WOKNT_ShellManager :: Arm
+
+void WOKNT_ShellManager :: UnArm () {
+
+ SetConsoleCtrlHandler ( &interruptHandler, FALSE );
+
+}  // end WOKNT_ShellManager :: UnArm
+
+void WOKNT_ShellManager :: KillAll () {
+
+ for ( Standard_Integer i = 1; i <= shells.Length (); ++i )
+  shells.Value ( i ) -> Kill ();
+
+ shells.Clear ();
+
+}  // end WOKNT_ShellManager :: KillAll
+
+void WOKNT_ShellManager :: Break () {
+
+ if ( s_fCtrlBreak ) {
+
+  s_fCtrlBreak = FALSE;
+  
+  OSD_Exception_CTRL_BREAK :: Raise (  TEXT( "*** INTERRUPT ***" )  ); 
+ }  // end if
+
+}  // end WOKNT_ShellManager :: Break
+
+static BOOL CALLBACK interruptHandler ( DWORD dwCode ) {
+
+ WOKNT_ShellManager :: KillAll ();
+ if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
+  MessageBeep ( MB_ICONEXCLAMATION );
+  return s_fCtrlBreak = TRUE;
+
+ }  // end if
+
+ exit ( 254 );
+
+ return TRUE;
+
+}  // end interruptHandler
diff --git a/src/WOKNT/WOKNT_ShellOutput.cdl b/src/WOKNT/WOKNT_ShellOutput.cdl
new file mode 100755 (executable)
index 0000000..a48bc11
--- /dev/null
@@ -0,0 +1,55 @@
+-- File:       WOKNT_ShellOutput.cdl
+-- Created:    Tue Jul 30 10:10:37 1996
+-- Author:     PLOTNIKOV Eugeny
+--             <eugeny@maniax>
+---Copyright:   Matra Datavision 1996
+
+private deferred class ShellOutput from WOKNT inherits File from OSD
+
+    ---Purpose: defines root class to manage output of sub-process
+
+ uses
+  HSequenceOfHAsciiString from TColStd
+  
+ is
+  Initialize;
+    ---Purpose: protected constructor
+
+  Cleanup ( me : out ) is virtual;
+    ---Purpose: provides 'cleanup' functionality
+    ---C++:     alias ~
+
+  Clear ( me : out ) is deferred;
+    ---Purpose: clears output buffer(s) of sub-process
+
+  Echo ( me : out ) returns HSequenceOfHAsciiString from TColStd is deferred;
+    ---Purpose: returns standard output of sub-process
+
+  Errors ( me : out ) returns HSequenceOfHAsciiString from TColStd is deferred;
+    ---Purpose: returns standard error output of sub-process
+
+  OpenStdOut ( me : out ) returns Integer from Standard is deferred;
+    ---Purpose: creates an I/O object for reading a standard output of sub-process
+    --          and returns this object handle.
+    ---Warning: returns INVALID_HANDLE_VALUE in case of failure
+
+  CloseStdOut ( me : out ) is deferred;
+    ---Purpose: closes an I/O object's handle opened by 'OpenStdOut' method
+
+  OpenStdErr ( me : out ) returns Integer from Standard is deferred;
+    ---Purpose: creates an I/O object for reading a standard error output of sub-process
+    --          and returns this object handle
+    ---Warning: returns INVALID_HANDLE_VALUE in case of failure
+
+  CloseStdErr ( me : out ) is deferred;
+    ---Purpose: closes an I/O object's handle opened by 'OpenStdErr' method
+
+  SyncStdOut ( me : out ) returns HSequenceOfHAsciiString from TColStd is deferred;
+    ---Purpose: waits for sub-process termination
+
+  SyncStdErr ( me : out ) returns HSequenceOfHAsciiString from TColStd is deferred;
+    ---Purpose: same as 'SyncStdOut' method
+
+end ShellOutput;  
diff --git a/src/WOKNT/WOKNT_ShellOutput.cxx b/src/WOKNT/WOKNT_ShellOutput.cxx
new file mode 100755 (executable)
index 0000000..90c4664
--- /dev/null
@@ -0,0 +1,14 @@
+#define STRICT
+#include <windows.h>
+
+#include <WOKNT_ShellOutput.ixx>
+
+WOKNT_ShellOutput :: WOKNT_ShellOutput () {
+
+}  // end constructor
+
+void WOKNT_ShellOutput :: Cleanup () {
+
+ if (  ( HANDLE )myFileChannel != INVALID_HANDLE_VALUE  ) Close ();
+
+}  // end WOKNT_ShellOutput :: Cleanup
diff --git a/src/WOKNT/WOKNT_Shell_1.cxx b/src/WOKNT/WOKNT_Shell_1.cxx
new file mode 100755 (executable)
index 0000000..32afbef
--- /dev/null
@@ -0,0 +1,435 @@
+#define STRICT
+#include <windows.h>
+
+#include <WOKNT_Shell.hxx>
+#include <TCollection_HAsciiString.hxx>
+#include <TColStd_HSequenceOfHAsciiString.hxx>
+#include <WOKNT_Array1OfRegExp.hxx>
+#include <WOKTools_Messages.hxx>
+#include <OSD_Environment.hxx>
+#include <OSD_Path.hxx>
+#include <OSD_SharedLibrary.hxx>
+
+#include <regexp.h>
+#include <stdio.h>
+
+typedef int ( *EXT_FUNC ) ( int, TCHAR** );
+
+#define PATTERN_CHAR_STRING        1
+#define PATTERN_ENV_VARIABLE       2
+#define PATTERN_WORD               3
+#define PATTERN_SET_COMMAND        4
+#define PATTERN_SETENV_COMMAND     5
+#define PATTERN_UNSETENV_COMMAND   6
+#define PATTERN_CD_COMMAND         7
+#define PATTERN_CHAR_STRING_1      8
+#define PATTERN_COMMAND_SEPARATOR  9
+#define PATTERN_CONTINUE          10
+
+const Standard_CString patterns[] = {
+
+ _TEXT( "\"(\"\"|[^\"])*\"" ), // character string pattern
+ _TEXT( "%[^%]+%" ),           // Windows NT environment variable syntax
+ _TEXT( "*.[^ \t\"%;]*" ),     // string quoted by whitespaces, '"' or '%' or ';'
+ _TEXT( "set .+=.*" ),         // 'set' command syntax ( 'set var=val' )
+ _TEXT( "setenv .+ .+" ),      // 'setenv' command syntax ( 'setenv var val' )
+ _TEXT( "unsetenv .+" ),       // 'unsetenv' command syntax ( 'unsetenv ver' )
+ _TEXT( "cd$|cd .+" ),         // 'cd' command syntax
+ _TEXT( "'(''|[^\'])*'" ),     // character string pattern
+ _TEXT( "[ \t]*;" ),           // command separator ( semicolon )
+ _TEXT( "[ \t]*\\\\" )         // continuation line ( backslash )
+
+};  // end patterns
+
+#define NUM_PATTERNS (  sizeof ( patterns ) / sizeof ( Standard_CString )  )
+
+static _TUCHAR caseTrans[ ( 1 << BYTEWIDTH ) ] = {  // translation table to perform
+                                                    // character case translation
+    000, 001, 002, 003, 004, 005, 006, 007,
+    010, 011, 012, 013, 014, 015, 016, 017,
+    020, 021, 022, 023, 024, 025, 026, 027,
+    030, 031, 032, 033, 034, 035, 036, 037,
+    040, 041, 042, 043, 044, 045, 046, 047,
+    050, 051, 052, 053, 054, 055, 056, 057,
+    060, 061, 062, 063, 064, 065, 066, 067,
+    070, 071, 072, 073, 074, 075, 076, 077,
+    0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+    0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+    0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+    0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+    0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+    0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+    0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+    0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+    0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+    0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+    0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+    0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+    0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+    0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+    0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+    0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+    0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+    0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+    0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+    0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+    0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+    0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+    0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+    0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+  
+};
+
+static WOKNT_Array1OfRegExp _shellRegExp ( 1, NUM_PATTERNS );
+static OSD_SharedLibrary       _extLib;
+static HMODULE                 _hWOKCXModule;
+
+extern "C" __declspec( dllexport ) int __fastcall __WOKNT_INIT__ ( 
+                                                   unsigned hInstance, unsigned long reason_for_call
+                                                  ) {
+
+ if ( reason_for_call == DLL_PROCESS_ATTACH ) _hWOKCXModule = ( HMODULE )hInstance;
+
+ return 1;
+
+}  // end __WOKNT_INIT__
+
+extern "C" __declspec( dllexport ) int __fastcall __TKWOK_INIT__ (
+                                                   unsigned hInstance, unsigned long reason_for_call
+                                                  ) {
+
+ if ( reason_for_call == DLL_PROCESS_ATTACH ) _hWOKCXModule = ( HMODULE )hInstance;
+
+ return 1;
+
+}  // end __TKWOK_INIT__
+
+class _regExpInit {  // provides initialisation in case of UNICODE environment
+
+ public:
+
+  _regExpInit () {
+
+   for (  int i = ( 1 << CHAR_BIT ); i < ( 1 << BYTEWIDTH ); ++i  )
+
+    caseTrans[ i ] = ( _TUCHAR )i;
+
+   for ( i = 1; i <= NUM_PATTERNS; ++i )
+
+    _shellRegExp.SetValue ( i, new WOKNT_RegExp (
+                                    new TCollection_HAsciiString ( patterns[ i - 1 ] ),
+                                    WOKNT_RESyntaxAWK, caseTrans
+                                   )
+                 );
+
+  }  // end constructor
+
+};  // end _regExpInit
+
+static _regExpInit initializeShellRegExp;
+
+Standard_Integer __fastcall _WOKNT_find_environment_variable (
+                             const Handle( TColStd_HSequenceOfHAsciiString )&,
+                             const Handle( TCollection_HAsciiString )&
+                            );
+Standard_CString _WOKNT_get_last_error_text ( void );
+Standard_Integer _rm_command ( Standard_CString );
+Standard_Integer _chmod_command ( Standard_CString );
+
+static void __fastcall _WOKNT_strip_string (  Handle( TCollection_HAsciiString )&  );
+
+#define MATCH( i ) (  _shellRegExp.Value (  ( i )  ) ->          \
+                      Match (  tmpStr, 1, len+1  ) \
+                   )
+
+#define C_MATCH( i ) (  _shellRegExp.Value (  ( i )  ) ->        \
+                        Match (  aCmd,1 ,len+1  ) \
+                     )
+
+Standard_Boolean WOKNT_Shell :: BuiltInCommand (
+                                    Handle_TCollection_HAsciiString& aCmd,
+                                    const Standard_Boolean           doParse
+                                   ) {
+
+ Handle( TCollection_HAsciiString )tmpStr =
+  new TCollection_HAsciiString (  aCmd -> String ()  );
+ Standard_Integer                  len;
+ Standard_Integer                  envIdx;
+ Standard_Integer                  pos = 1;
+ EXT_FUNC                          xFunc;
+
+ aCmd   -> Clear ();
+ tmpStr -> RightAdjust ();
+ len = tmpStr -> Length ();
+
+ while ( len ) {
+
+  if (   (  pos = MATCH( PATTERN_CHAR_STRING   )   ) > 0  ||
+         (  pos = MATCH( PATTERN_CHAR_STRING_1 )   ) > 0
+  ) {
+  
+   aCmd -> AssignCat (  tmpStr -> SubString ( 1, pos )  );
+   len -= pos;
+  
+  } else if (   (  pos = MATCH( PATTERN_ENV_VARIABLE )  ) > 0   ) {
+
+   envIdx = 0;
+
+   if ( !doParse ) {
+
+    Handle( TCollection_HAsciiString ) envVar = tmpStr -> SubString ( 2, pos - 1 );
+
+    if (   !_tcscmp (  envVar -> ToCString (), _TEXT( "status" )  )   ) {
+    
+     TCHAR buff[ 20 ];
+
+     envIdx = 1;
+     aCmd -> AssignCat (
+              new TCollection_HAsciiString (  _ltot ( myStatus, buff, 10 )  )
+             );
+    
+    } else if (  envIdx = _WOKNT_find_environment_variable (
+                           myEnvironment,
+                           tmpStr -> SubString ( 2, pos - 1 )
+                          )
+           ) aCmd -> AssignCat (
+                      myEnvironment -> Value ( envIdx ) -> Token (  _TEXT( "=" ), 2  )
+                     );
+
+   }  // end if
+   
+   if ( doParse || !envIdx ) aCmd -> AssignCat (  tmpStr -> SubString ( 1, pos )  );
+
+  } else if (   ( pos = MATCH( PATTERN_COMMAND_SEPARATOR )  ) > 0   ) {
+
+   aCmd -> AssignCat (  _TEXT( "\x01" )  );
+
+  } else if (   ( pos = MATCH( PATTERN_CONTINUE )  ) > 0   ) {
+
+   aCmd -> AssignCat (  _TEXT( " " )  );
+
+  } else if (   (  pos = MATCH( PATTERN_WORD )  ) > 0   ) {
+
+   aCmd -> AssignCat (  tmpStr -> SubString ( 1, pos )  );
+
+  } else break;
+  
+  tmpStr -> Remove ( 1, pos );
+
+  if (   tmpStr -> Length () > 0 && _istspace (  tmpStr -> Value ( 1 )  )   )
+
+   aCmd -> AssignCat (  _TEXT( " " )  );
+
+  tmpStr -> LeftAdjust ();
+  len = tmpStr -> Length ();
+
+ }  // end while
+
+ if ( doParse ) return Standard_False;
+
+ aCmd -> LeftAdjust ();
+ len = aCmd -> Length ();
+
+ if (  C_MATCH( PATTERN_SET_COMMAND ) > 0  ) {
+
+  Standard_Integer                   valLen;
+  Handle( TCollection_HAsciiString ) name, value;
+
+  name   = aCmd -> Token (  _TEXT( "=" ), 1  );
+  value  = aCmd -> Token (  _TEXT( "=" ), 2  );
+  valLen = value -> Length ();
+
+  name -> Remove ( 1, 3 );
+  name -> LeftAdjust ();
+
+  if (   !_tcscmp (  name -> ToCString (), _TEXT( "status" )  )   ) {
+  
+   if (  !value -> IsEmpty ()  ) myStatus = _ttoi (  value -> ToCString ()  );
+
+   return Standard_True;
+  
+  } else if (  value -> IsEmpty ()  ) {
+  
+   RemoveEnvironmentVariable ( name );
+
+  } else
+  
+   AddEnvironmentVariable ( name, value );
+
+ } else if (  C_MATCH( PATTERN_SETENV_COMMAND ) > 0  ) {
+
+  Handle( TCollection_HAsciiString ) name, value;
+
+  name  = aCmd -> Token (  _TEXT( " " ), 2  );
+  value = aCmd -> Token (  _TEXT( " " ), 3  );
+
+  _WOKNT_strip_string ( name  );
+  _WOKNT_strip_string ( value );
+
+  AddEnvironmentVariable ( name, value );
+
+ } else if (  C_MATCH( PATTERN_UNSETENV_COMMAND ) > 0  ) {
+  Handle( TCollection_HAsciiString ) name = aCmd -> Token (  _TEXT( " " ), 2  );
+
+  _WOKNT_strip_string ( name );
+
+  RemoveEnvironmentVariable ( name );
+
+ } else if (  C_MATCH( PATTERN_CD_COMMAND ) > 0  ) {
+  aCmd -> AssignCat (  _TEXT( " " )  );
+
+  Handle ( TCollection_HAsciiString ) newDir = aCmd -> SubString (  3, aCmd -> Length ()  );
+
+  newDir -> LeftAdjust ();
+  
+  if ( newDir -> IsEmpty ()  ) {
+
+   Handle( TCollection_HAsciiString ) homeDir = new TCollection_HAsciiString ();
+   OSD_Environment                    homeDrive (  _TEXT( "HOMEDRIVE" )  );
+   OSD_Environment                    homePath  (  _TEXT( "HOMEPATH"  )  );
+
+   homeDir -> AssignCat (  homeDrive.Value ().ToCString ()  );
+   homeDir -> AssignCat (  homePath.Value  ().ToCString ()  );
+
+   myDirectory = homeDir;
+
+  } else {\r
+         char aDir[1024];\r
+\r
+        GetCurrentDirectory(1024, aDir);\r
+
+        TCollection_AsciiString str = aDir;
+
+    if (   !SetCurrentDirectory (  newDir -> ToCString ()  )   ) {
+   
+    Handle( TCollection_HAsciiString ) errMsg = new TCollection_HAsciiString ();
+
+    errMsg -> Cat (  _TEXT( "'" )  );
+    errMsg -> Cat ( newDir );
+    errMsg -> Cat (  _TEXT( "' - " )  );
+    errMsg -> Cat (  _WOKNT_get_last_error_text ()  );
+
+    if (  myStdErr.IsNull ()  ) myStdErr = new TColStd_HSequenceOfHAsciiString ();
+
+    myStdErr -> Append ( errMsg );
+
+   } else {
+
+    SetCurrentDirectory (  str.ToCString ()  );
+    myDirectory = newDir;
+   }  // end else
+  
+  }  // end else
+
+ } else {
+
+  Standard_Boolean                   fCond = Standard_False; 
+  Standard_Integer                   cLen;
+  Handle( TCollection_HAsciiString ) command = aCmd -> Token ( " \t", 1 );
+
+  cLen = command -> Length ();
+
+  if (  command -> Value ( 1 ) == _TEXT( '@' )  ) {
+  
+   fCond = Standard_True;
+   command -> Remove ( 1 );
+
+  }  // end if
+
+  if (    (   xFunc = ( EXT_FUNC )GetProcAddress (
+                                   _hWOKCXModule, command -> ToCString ()
+                                  )
+          ) != NULL
+  ) {
+
+   if (  fCond && !myStatus  ) return Standard_True;
+
+   TCHAR** argv;
+
+   Handle( TCollection_HAsciiString        ) item;
+   Handle( TColStd_HSequenceOfHAsciiString ) args =
+    new TColStd_HSequenceOfHAsciiString ();
+
+   aCmd -> Remove ( 1, cLen );
+   aCmd -> LeftAdjust ();
+
+   args -> Append ( command );
+
+   tmpStr = aCmd;
+   len = tmpStr -> Length ();
+
+   while ( len ) {
+  
+    if (   (  pos = MATCH( PATTERN_CHAR_STRING   )   ) > 0  ||
+           (  pos = MATCH( PATTERN_CHAR_STRING_1 )   ) > 0
+    ) {
+  
+     item = tmpStr -> SubString ( 1, pos );
+     len -= pos;
+  
+     _WOKNT_strip_string ( item );
+
+    } else if (   (  pos = MATCH( PATTERN_WORD )  ) > 0   ) {
+
+     item = tmpStr -> SubString ( 1, pos );
+
+    } else break;
+
+    tmpStr -> Remove ( 1, pos );
+    tmpStr -> LeftAdjust ();
+    len = tmpStr -> Length ();
+    args -> Append ( item );
+   }  // end while
+
+   argv = new TCHAR*[ args -> Length () ];
+
+   for ( int i = 1; i <= args -> Length (); ++i )
+
+    argv[ i - 1 ] = args -> Value ( i ) -> ToCString ();
+
+   myStatus = ( *xFunc ) (  args -> Length (), argv  );
+
+   delete [] argv;
+
+  } else
+
+   return Standard_False;
+
+ }  // end else
+
+ return Standard_True;
+
+}  //end WOKNT_Shell :: BuiltInCommand
+
+static void __fastcall _WOKNT_strip_string (  Handle( TCollection_HAsciiString )& str ) {
+
+ Standard_Integer len = str -> Length ();
+
+ if (  str -> Value ( 1 )   == _TEXT( '"' ) &&
+       str -> Value ( len ) == _TEXT( '"' )
+ ) {
+  str -> Remove ( 1 );
+  str -> Remove ( len - 1 );
+
+  while (    (   len = str -> Search (  _TEXT( "\"\"" )  )   )!= -1    )
+
+   str -> Remove ( len );
+ } else if (  str -> Value ( 1 )   == _TEXT( '\'' ) &&
+              str -> Value ( len ) == _TEXT( '\'' )
+        ) {
+  str -> Remove ( 1 );
+  str -> Remove ( len - 1 );
+
+  while (    (   len = str -> Search (  _TEXT( "\'\'" )  )   )!= -1    )
+
+   str -> Remove ( len );
+
+ }  // end else
+
+}  // end _WOKNT_strip_string
diff --git a/src/WOKNT/WOKNT_TimeStat.hxx b/src/WOKNT/WOKNT_TimeStat.hxx
new file mode 100755 (executable)
index 0000000..618780f
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __WOKNT_FILETIME_HXX
+# define __WOKNT_FILETIME_HXX
+
+# ifndef STRICT
+#  define STRICT
+# endif  // STRICT
+
+# ifndef _INC_TIME
+#  include <time.h>
+# endif  // _INC_TIME
+
+typedef time_t WOKNT_TimeStat;
+
+#endif  // __WOKNT_FILETIME_HXX
diff --git a/src/WOKNT/WOKNT_WNT_BREAK.hxx b/src/WOKNT/WOKNT_WNT_BREAK.hxx
new file mode 100755 (executable)
index 0000000..b0cb211
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __WOKNT_WNT_BREAK__HXX
+# define __WOKNT_WNT_BREAK__HXX
+
+# ifdef WNT
+#  include <WOKNT_ShellManager.hxx>
+#  define _TEST_BREAK() WOKNT_ShellManager :: Break ()
+# endif  // WNT
+
+#endif  // __WOKNT_WNT_BREAK__HXX
diff --git a/src/WOKNT/WOKNT_WOKSteps.edl b/src/WOKNT/WOKNT_WOKSteps.edl
new file mode 100755 (executable)
index 0000000..4a8c2a1
--- /dev/null
@@ -0,0 +1,21 @@
+-- File:       WOKNT_WOKSteps.edl
+-- Author:     Jean GAUTIER
+-- History:    Tue Aug 12 17:21:24 1997        Jean GAUTIER    Creation
+-- Copyright:   Matra Datavision 1997
+
+@ifnotdefined ( %WOKNT_WOKSteps_EDL) then
+@set %WOKNT_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/WOKNT/WOKNT_chmod.cxx b/src/WOKNT/WOKNT_chmod.cxx
new file mode 100755 (executable)
index 0000000..1994b45
--- /dev/null
@@ -0,0 +1,268 @@
+#define EXPORT
+#include <iostream.h>
+#include <stdlib.h>
+
+#include <OSD_WNT.h>
+#include <OSD_File.hxx>
+#include <OSD_Path.hxx>
+#include <OSD_Protection.hxx>
+
+#define FLAG_SYSTEM  0x01
+#define FLAG_OWNER   0x02
+#define FLAG_GROUP   0x04
+#define FLAG_WORLD   0x08
+
+#define OPER_GRANT   0
+#define OPER_DENY    1
+
+#define PROT_READ    0x01
+#define PROT_WRITE   0x02
+#define PROT_EXECUTE 0x04
+#define PROT_DELETE  0x08
+
+#define I_SYSTEM 0
+#define I_OWNER  1
+#define I_GROUP  2
+#define I_WORLD  3
+
+typedef struct _prt_data {
+
+                BYTE fUser;
+                BYTE fProt;
+                BOOL fGrant;
+                BOOL fRecurse;
+
+               } PRT_DATA, *PPRT_DATA;
+
+typedef BOOL ( *CHMOD_FUNC ) ( LPCTSTR, BOOL, void* );
+
+static BOOL _chmod_func ( LPTSTR, BOOL, void* );
+
+#define USAGE() { cerr << "Usage: wokCHMOD [-R] [sugoa]{+|-}[rwxd] file(s)\n"; return 1; }
+
+static int nFiles;
+
+extern "C" __declspec( dllexport ) wokCHMOD ( int, char** );
+
+int wokCHMOD ( int argc, char** argv ) {
+
+ int      i, retVal = 0;
+ char*    ptr;
+ PRT_DATA pd = { 0, 0, 0 };
+ BOOL     fRecurse;
+ char     path[ _MAX_PATH ];
+ char     name[ _MAX_FNAME + _MAX_EXT ];
+ char     drive[ _MAX_DRIVE ];
+ char     dir[ _MAX_DIR ];
+ char     fname[ _MAX_FNAME ];
+ char     ext[ _MAX_EXT ];
+
+ if ( argc < 3 ) USAGE();
+
+ if (  *argv[ 1 ] == '-' && ( argv[ 1 ][ 1 ] == 'r' || argv[ 1 ][ 1 ] == 'R' )  ) {
+  fRecurse = pd.fRecurse = TRUE;
+  ptr      = argv[ 2 ];
+  i        = 3;
+ } else {
+  fRecurse = pd.fRecurse = FALSE;
+  ptr      = argv[ 1 ];
+  i        = 2;
+ }  // end else
+ while ( *ptr != '+' && *ptr != '-' ) {
+  if ( *ptr == 0 ) USAGE();
+
+  switch ( *ptr ) {
+  
+   case 's':
+   case 'S':
+
+    pd.fUser |= FLAG_SYSTEM;
+
+   break;
+
+   case 'o':
+   case 'O':
+   case 'u':
+   case 'U':
+
+    pd.fUser |= FLAG_OWNER;
+
+   break;
+
+   case 'g':
+   case 'G':
+
+    pd.fUser |= FLAG_GROUP;
+
+   break;
+
+   case 'a':
+   case 'A':
+
+    pd.fUser |= FLAG_WORLD;
+
+   break;
+
+   default:
+
+    USAGE();
+
+  }  // end switch
+
+  ++ptr;
+ }  // end while
+
+ pd.fGrant = ( *ptr++ == '+' ) ? TRUE : FALSE;
+
+ while ( *ptr != 0 ) {
+
+  switch ( *ptr ) {
+  
+   case 'r':
+   case 'R':
+
+    pd.fProt |= PROT_READ;
+
+   break;
+
+   case 'w':
+   case 'W':
+
+    pd.fProt |= PROT_WRITE;
+
+   break;
+
+   case 'x':
+   case 'X':
+
+    pd.fProt |= PROT_EXECUTE;
+
+   break;
+
+   case 'd':
+   case 'D':
+
+    pd.fProt |= PROT_DELETE;
+
+   break;
+
+   default:
+
+    USAGE();
+  
+  }  // end switch
+  ++ptr;
+ }  // end while
+
+ for ( ; i < argc; ++i ) {
+
+  nFiles = 0;
+  _splitpath ( argv[ i ], drive, dir, fname, ext );
+  _makepath  ( path, drive, dir, NULL, NULL );
+  _makepath  ( name, NULL, NULL, fname, ext );
+
+  if (  !DirWalk ( path, name, ( CHMOD_FUNC )_chmod_func, fRecurse, &pd )  ) retVal = 1;
+  if ( nFiles == 0 ) {
+   cerr << "wokCHMOD: could not find " << argv[ i ] << endl << flush;
+   retVal = 1;
+  }   // end if
+
+ }  // end for
+
+ return retVal;
+
+}  // end main
+
+static BOOL _chmod_func ( LPTSTR fName, BOOL fDir, void* data ) {
+
+ int                  i, j;
+ OSD_Protection       prot;
+ OSD_File             file;
+ OSD_SingleProtection pArr[ 4 ];
+ OSD_SingleProtection pDef[ 4 ] = { OSD_R, OSD_W, OSD_X, OSD_D };
+ unsigned char        flags[ 4 ] = { 0, 0, 0, 0 };
+ unsigned char        prt[ 4 ] = { 0, 0, 0, 0 };
+ PPRT_DATA            pData = ( PPRT_DATA )data;
+
+ ++nFiles;
+
+ if ( fDir && !pData -> fRecurse ) return TRUE;
+
+ file.SetPath (  OSD_Path ( fName )  );
+ prot = file.Protection ();
+
+ if (  file.Failed ()  ) {
+  cerr << "wokCHMOD: ";
+  file.Perror ();
+  return FALSE;
+ }  // end if
+
+ pArr[ I_SYSTEM ] = prot.System ();
+ pArr[ I_OWNER  ] = prot.User ();
+ pArr[ I_GROUP  ] = prot.Group ();
+ pArr[ I_WORLD  ] = prot.World ();
+
+ if ( pData -> fUser & FLAG_SYSTEM ) flags[ I_SYSTEM ] = 1;
+ if ( pData -> fUser & FLAG_OWNER  ) flags[ I_OWNER  ] = 1;
+ if ( pData -> fUser & FLAG_GROUP  ) flags[ I_GROUP  ] = 1;
+ if ( pData -> fUser & FLAG_WORLD  ) flags[ I_WORLD  ] = 1;
+
+ if ( pData -> fProt & PROT_READ    ) prt[ 0 ] = 1;
+ if ( pData -> fProt & PROT_WRITE   ) prt[ 1 ] = 1;
+ if ( pData -> fProt & PROT_EXECUTE ) prt[ 2 ] = 1;
+ if ( pData -> fProt & PROT_DELETE  ) prt[ 3 ] = 1;
+
+ if ( flags[ I_SYSTEM ] == 0 &&
+      flags[ I_OWNER  ] == 0 &&
+      flags[ I_GROUP  ] == 0 &&
+      flags[ I_WORLD  ] == 0
+ ) flags[ I_OWNER ] = 1;
+
+ for ( i = 0; i < 4; ++i )
+
+  for ( j = 0; j < 4; ++j )
+   if ( prt[ j ] )
+
+    if ( flags[ i ] )
+
+     if ( !pData -> fGrant )
+
+      prot.Sub ( pArr[ i ], pDef[ j ] );
+
+     else
+
+      prot.Add ( pArr[ i ], pDef[ j ] );
+
+ prot.SetSystem ( pArr[ I_SYSTEM ] );
+ prot.SetUser   ( pArr[ I_OWNER  ] );
+ prot.SetGroup  ( pArr[ I_GROUP  ] );
+ prot.SetWorld  ( pArr[ I_WORLD  ] );
+
+ file.SetProtection ( prot );
+
+ if (  file.Failed ()  ) {
+  cerr << "wokCHMOD: ";
+  file.Perror ();
+  return FALSE;
+ }  // end if
+
+ return TRUE;
+
+}  // end _chmod_func
diff --git a/src/WOKNT/WOKNT_cmp.c b/src/WOKNT/WOKNT_cmp.c
new file mode 100755 (executable)
index 0000000..ef31294
--- /dev/null
@@ -0,0 +1,67 @@
+#define STRICT
+#include <windows.h>
+
+#include <stdlib.h>
+#include <memory.h>
+
+__declspec( dllexport ) int wokCMP ( int argc, char** argv ) 
+{
+  
+  HANDLE hFile1,  hFile2;
+  HANDLE hMap1,   hMap2;
+  DWORD  dwSize1, dwSize2;
+  PVOID  pvAddr1, pvAddr2;
+  
+  int retVal = 2;
+  
+  hFile1 = hFile2 = INVALID_HANDLE_VALUE;
+  
+  pvAddr1 = pvAddr2 = hMap1 = hMap2 = NULL;
+  if( argc != 3 ) return 2;
+
+  if((hFile1 = CreateFile(argv[ 1 ],             /* file name   */
+                         GENERIC_READ,          /* access      */
+                         FILE_SHARE_READ,       /* sharing     */
+                         NULL,                  /* security    */
+                         OPEN_EXISTING,         /* disposition */
+                         FILE_ATTRIBUTE_NORMAL, /* attributes  */
+                         NULL                   /* template    */
+                         )) == INVALID_HANDLE_VALUE )
+    retVal = 2;
+  else if((hFile2 = CreateFile(argv[ 2 ],             /* file name   */
+                         GENERIC_READ,          /* access      */
+                         FILE_SHARE_READ,       /* sharing     */
+                         NULL,                  /* security    */
+                         OPEN_EXISTING,         /* disposition */
+                         FILE_ATTRIBUTE_NORMAL, /* attributes  */
+                         NULL                   /* template    */
+                         )) == INVALID_HANDLE_VALUE)
+    retVal = 2;
+  else
+    {
+      dwSize1 = GetFileSize ( hFile1, NULL );
+      dwSize2 = GetFileSize ( hFile2, NULL );
+      
+      if ( dwSize1 != dwSize2 ) retVal = 1;
+      else if(( hMap1 = CreateFileMapping(hFile1, NULL, PAGE_READONLY, 0, dwSize1, NULL)) == NULL) retVal = 2;
+      else if((hMap2 = CreateFileMapping(hFile2, NULL, PAGE_READONLY, 0, dwSize2, NULL)) == NULL)  retVal = 2;
+      else if((pvAddr1 = MapViewOfFile(hMap1, FILE_MAP_READ, 0, 0, dwSize1)) == NULL)  retVal = 2;
+      else if((pvAddr2 = MapViewOfFile(hMap2, FILE_MAP_READ, 0, 0, dwSize2)) == NULL)  retVal = 2;
+      else 
+       retVal = memcmp ( pvAddr1, pvAddr2, dwSize1 );
+      
+      if ( retVal ) retVal = 1;
+    }    
+  
+  if ( pvAddr2 != NULL ) UnmapViewOfFile ( pvAddr2 );
+  if ( pvAddr1 != NULL ) UnmapViewOfFile ( pvAddr1 );
+  
+  if ( hMap2 != NULL ) CloseHandle ( hMap2 );
+  if ( hMap1 != NULL ) CloseHandle ( hMap1 );
+  
+  if ( hFile2 != INVALID_HANDLE_VALUE ) CloseHandle ( hFile2 );
+  if ( hFile1 != INVALID_HANDLE_VALUE ) CloseHandle ( hFile1 );
+  
+  return retVal;
+}
diff --git a/src/WOKNT/WOKNT_cp.cxx b/src/WOKNT/WOKNT_cp.cxx
new file mode 100755 (executable)
index 0000000..d90796a
--- /dev/null
@@ -0,0 +1,124 @@
+#define STRICT
+#include <windows.h>
+#include <string.h>
+
+#include <OSD_Path.hxx>
+#include <OSD_File.hxx>
+#include <WOKNT_Path.hxx>
+
+#define BUFFER_SIZE 4096
+
+#define USAGE() { cerr << "Usage: wokCP [-pr] source destination\n"; return ( 1 ); }
+
+extern "C" int __declspec( dllexport ) wokCP ( int, char** );
+
+int wokCP( int argc, char** argv ) 
+{
+  int   i, retVal = 1;
+  char* src = NULL, *dst = NULL, *ptr;
+  BOOL  fPreserve = FALSE, fRecurse = FALSE;
+  
+  DWORD dwBytesRead, dwBytesWritten;
+  BYTE  buffer[ BUFFER_SIZE ];
+  
+  if ( argc < 3 ) USAGE();
+  
+  for( i=1; i<argc; ++i) 
+    {
+      if( argv[i][0] == '-' ) 
+       {
+         ptr=argv[i];
+
+         while( *++ptr != 0 ) 
+           {
+             switch ( *ptr ) 
+               {
+               case 'p':
+               case 'P':
+                 fPreserve=TRUE;
+                 break;
+               case 'r':
+               case 'R':
+                 fRecurse=TRUE;
+                 break;
+               default:
+                 USAGE();
+               }
+           }
+       }
+      else 
+       break;
+    }
+
+  if( i==argc ) USAGE();
+  
+  src=argv[i++];
+
+  if( i==argc) USAGE();
+
+  dst=argv[i];
+
+  if(lstrcmp(src,dst)==0) return 0;
+
+  if ( src && dst ) 
+    {
+      Handle(WOKNT_Path) woksrc = new WOKNT_Path(new TCollection_HAsciiString(src));
+      Handle(WOKNT_Path) wokdst = new WOKNT_Path(new TCollection_HAsciiString(dst));
+      Handle(WOKNT_Path) newdst;
+
+      if(woksrc->IsFile() && wokdst->IsDirectory())
+       {
+         newdst = new WOKNT_Path(wokdst->Name()->ToCString(), woksrc->FileName()->ToCString());
+         dst = newdst->Name()->ToCString();
+       }
+      
+      if(fRecurse) 
+       {
+         OSD_Path pathSrc(src);
+         OSD_Path pathDst(dst);
+
+         OSD_File source( pathSrc );
+
+         source.Copy(pathDst);
+
+         if(source.Failed())
+           source.Perror ();
+         else
+           retVal = 0;
+       }
+      else
+       {
+         if(fPreserve)
+           {
+             if(!CopyFile(src,dst,FALSE))
+               return retVal;
+             retVal = 0;
+           }
+         else 
+           {
+             HANDLE hFileSrc, hFileDst;
+             
+             hFileSrc = CreateFile ( src, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+             hFileDst = CreateFile ( dst, GENERIC_WRITE, 0,              NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
+
+             if ( hFileSrc == INVALID_HANDLE_VALUE || hFileDst == INVALID_HANDLE_VALUE )
+               return retVal;
+
+             while(TRUE) 
+               {
+                 if( !ReadFile( hFileSrc, buffer, BUFFER_SIZE, &dwBytesRead, NULL)) return retVal;
+                 if( dwBytesRead == 0 ) break;
+                 
+                 if( !WriteFile ( hFileDst, buffer, dwBytesRead, &dwBytesWritten, NULL ) ||
+                     dwBytesWritten != dwBytesRead ) return retVal;
+   } 
+    CloseHandle ( hFileDst );
+    CloseHandle ( hFileSrc );
+
+    retVal = 0;
+  
+   } 
+  }  
+ }
+ return retVal;
+} 
diff --git a/src/WOKNT/WOKNT_mv.cxx b/src/WOKNT/WOKNT_mv.cxx
new file mode 100755 (executable)
index 0000000..1c6e77e
--- /dev/null
@@ -0,0 +1,36 @@
+#define EXPORT
+#define STRICT
+#include <windows.h>
+#include <iostream.h>
+
+extern "C" __declspec( dllexport ) int wokMV ( int, char** );
+
+int wokMV ( int argc, char** argv ) {
+
+ if (  argc != 3 ) {
+  cerr << "Usage: wokMV src dst\n" << flush;
+  return 1;
+ }  // end if
+
+ if (  !MoveFileEx ( argv[ 1 ], argv[ 2 ], MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING)  ) {
+  char  buffer[ 2048 ];
+  DWORD dwCode = GetLastError ();
+
+  if (  !FormatMessage (
+          FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+          0, dwCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
+          buffer, 2048, NULL
+         )
+  ) wsprintf ( buffer, "Error code %d", dwCode );
+
+  cerr << "wokMV: could not move - " << buffer << endl << flush;
+  return 2;
+
+ }  // end if
+
+ return 0;
+
+}  // end main
diff --git a/src/WOKNT/WOKNT_regexp.h b/src/WOKNT/WOKNT_regexp.h
new file mode 100755 (executable)
index 0000000..690539a
--- /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 __WOKNT_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/WOKNT/WOKNT_regexp_1.c b/src/WOKNT/WOKNT_regexp_1.c
new file mode 100755 (executable)
index 0000000..8305a0f
--- /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 <WOKNT_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 */
+/***/
+/******************************************************************************/
diff --git a/src/WOKNT/WOKNT_rm.cxx b/src/WOKNT/WOKNT_rm.cxx
new file mode 100755 (executable)
index 0000000..a81d56a
--- /dev/null
@@ -0,0 +1,196 @@
+#define EXPORT
+#include <iostream.h>
+#include <stdlib.h>
+#include <io.h>
+#include <sys/stat.h>
+
+#include <OSD_WNT.h>
+#include <OSD_File.hxx>
+#include <OSD_Path.hxx>
+#include <OSD_Protection.hxx>
+
+typedef struct _delete_data {
+
+                BOOL forceReadOnly;
+                BOOL fRecurse;
+
+               } DELETE_DATA, *PDELETE_DATA;
+
+typedef BOOL ( *RM_FUNC ) ( LPCTSTR, BOOL, void* );
+
+static BOOL _rm_func     ( LPTSTR, BOOL, void* );
+static void _print_error ( LPCTSTR );
+
+static int nFiles;
+
+#define USAGE() { cerr << "Usage: wokRM [-rfq] file(s)\n"; return ( 1 ); }
+
+extern "C" __declspec( dllexport ) int wokRM ( int, char** );
+
+int wokRM ( int argc, char** argv ) {
+
+ int         i, retVal = 0;
+ char*       ptr;
+ DELETE_DATA dd = { FALSE, FALSE };
+ char        buff[ _MAX_PATH ];
+ char        path[ _MAX_PATH ];
+ char        name[ _MAX_FNAME + _MAX_EXT ];
+ char        drive[ _MAX_DRIVE ];
+ char        dir[ _MAX_DIR ];
+ char        fname[ _MAX_FNAME ];
+ char        ext[ _MAX_EXT ];
+ BOOL        fQuiet = FALSE;
+
+ if ( argc < 2 ) USAGE();
+
+ for ( i = 1; i < argc; ++i ) {
+  if ( argv[ i ][ 0 ] == '-' ) {
+  
+   ptr = argv[ i ];
+
+   while ( *++ptr != 0 ) {
+   
+    switch ( *ptr ) {
+    
+     case 'f':
+     case 'F':
+
+      dd.forceReadOnly = TRUE;
+
+     break;
+
+     case 'r':
+     case 'R':
+
+      dd.fRecurse = TRUE;
+
+     break;
+
+     case 'q':
+     case 'Q':
+
+      fQuiet = TRUE;
+
+     break;
+
+     default:
+
+      USAGE();
+
+    }  // end switch
+   
+   }  // end while
+  
+  } else 
+
+   break;
+ }  // end for
+
+ if ( i == argc ) USAGE();
+
+ for ( ; i < argc; ++i ) {
+  nFiles = 0;
+
+  strcpy ( buff, argv[ i ] );
+
+  if (
+   GetFileAttributes ( buff ) == FILE_ATTRIBUTE_DIRECTORY &&
+   dd.fRecurse
+  ) strcat ( buff, "/*.*" );
+
+  _splitpath ( buff, drive, dir, fname, ext );
+  _makepath  ( path, drive, dir, NULL, NULL );
+  _makepath  ( name, NULL, NULL, fname, ext );
+
+  if (  !DirWalk ( path, name, ( RM_FUNC )_rm_func, dd.fRecurse, &dd )  ) retVal = 1;
+  if ( nFiles == 0 && !fQuiet ) {
+  
+   cerr << "wokRM: could not find " << argv[ i ] << endl << flush;
+   retVal = 1;
+  
+  }  // end if
+
+ }  // end for
+
+ return retVal;
+}  // end main
+
+static BOOL _rm_func ( LPTSTR fileName, BOOL fDir, void* data ) {
+ BOOL         fRetry = FALSE;
+ BOOL         status;
+ PDELETE_DATA pData = ( PDELETE_DATA )data;
+
+ ++nFiles;
+
+ if ( pData -> forceReadOnly ) _chmod ( fileName, _S_IREAD | _S_IWRITE );
+retry:
+ if ( !fDir )
+
+  status = DeleteFile ( fileName );
+
+ else if ( pData -> fRecurse ) {
+
+  cerr << fileName << endl;
+  status = RemoveDirectory ( fileName );
+
+ }
+
+ if ( !status )
+
+  if (  GetLastError () == ERROR_ACCESS_DENIED &&
+        pData -> forceReadOnly                 &&
+        !fRetry
+  ) {
+   OSD_File             aFile;
+   OSD_Protection       aProt;
+   OSD_SingleProtection aPrt;
+
+   aFile.SetPath (  OSD_Path ( fileName )  );
+   aProt = aFile.Protection ();
+   aPrt  = aProt.User ();
+   aProt.Add ( aPrt, OSD_RWXD );
+   aProt.SetUser ( aPrt );
+   aFile.SetProtection ( aProt );
+   _chmod ( fileName, _S_IREAD | _S_IWRITE );
+
+   fRetry = TRUE;
+  
+   goto retry;
+  } else
+   _print_error ( fileName );
+
+ return status;
+
+}  // end _deletreProc
+
+static void _print_error ( LPCTSTR fName ) {
+
+ DWORD              errCode;
+ Standard_Character buffer[ 2048 ];
+
+ errCode = GetLastError ();
+
+ if (  !FormatMessage (
+         FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+         0, errCode, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ),
+         buffer, 2048, NULL
+        )
+ ) {
+  wsprintf ( buffer, "error code %d", errCode );
+  SetLastError ( errCode );
+
+ }  // end if
+
+ cerr << "wokRM: could not remove " << fName << " - " << buffer << endl << flush;
+
+}  // end _set_error