From: cas Date: Fri, 22 Oct 1999 18:05:40 +0000 (+0000) Subject: Initial revision X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=66835b720513e8f3cf1d1706ac1dcda54cbcc0b7;p=occt-wok.git Initial revision --- diff --git a/src/WOKNT/FILES b/src/WOKNT/FILES new file mode 100755 index 0000000..e1fe42b --- /dev/null +++ b/src/WOKNT/FILES @@ -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 index 0000000..866a3ec --- /dev/null +++ b/src/WOKNT/WOKNT.cdl @@ -0,0 +1,110 @@ +-- File: WOKNT.cdl +-- Created: Mon Jul 22 15:58:28 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..d42030c --- /dev/null +++ b/src/WOKNT/WOKNT.cxx @@ -0,0 +1,49 @@ + + + +#ifdef WNT + +#include + +#ifdef CreateFile +# undef CreateFile +#endif // CreateFile + +#ifdef CreateDirectory +# undef CreateDirectory +#endif // CreateFile + +#ifdef RemoveDirectory +# undef RemoveDirectory +#endif // CreateFile + +#include + + +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 index 0000000..b0ce3f1 --- /dev/null +++ b/src/WOKNT/WOKNT_AdmFile.cdl @@ -0,0 +1,36 @@ +-- File: WOKNT_AdmFile.cdl +-- Created: Wed Jul 24 12:59:45 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..6c14fae --- /dev/null +++ b/src/WOKNT/WOKNT_AdmFile.cxx @@ -0,0 +1,103 @@ +#define STRICT +#include + +#include + +#include +#include + +#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 index 0000000..ef3540f --- /dev/null +++ b/src/WOKNT/WOKNT_CompareOfString.cdl @@ -0,0 +1,33 @@ +-- File: WOKNT_CompareOfString.cdl +-- Created: Wed Jul 31 11:31:03 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 is lower than + + IsGreater ( me; Left, Right : HAsciiString from TCollection ) + returns Boolean from Standard is redefined; + ---Purpose: returns True if is greater than . + + IsEqual ( me; Left, Right : HAsciiString from TCollection ) + returns Boolean from Standard is redefined; + ---Purpose: returns True when and are equal. + +end CompareOfString; diff --git a/src/WOKNT/WOKNT_CompareOfString.cxx b/src/WOKNT/WOKNT_CompareOfString.cxx new file mode 100755 index 0000000..a64a07a --- /dev/null +++ b/src/WOKNT/WOKNT_CompareOfString.cxx @@ -0,0 +1,36 @@ +#include + +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 index 0000000..029fbe9 --- /dev/null +++ b/src/WOKNT/WOKNT_CopyIfCh.c @@ -0,0 +1,25 @@ +#define STRICT +#include + +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 index 0000000..0faaa5e --- /dev/null +++ b/src/WOKNT/WOKNT_Dword.hxx @@ -0,0 +1,11 @@ +// File: WOKNT_Dword.hxx +// Author: Jean GAUTIER +// + + +#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 index 0000000..440ca4c --- /dev/null +++ b/src/WOKNT/WOKNT_FindData.hxx @@ -0,0 +1,37 @@ +// File: WOKUtils_Timeval.hxx +// Author: Jean GAUTIER +// + + +#ifndef WOKNT_FindData_HeaderFile +#define WOKNT_FindData_HeaderFile + +#ifdef WNT +#include + +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 index 0000000..b4bf39b --- /dev/null +++ b/src/WOKNT/WOKNT_Handle.hxx @@ -0,0 +1,35 @@ +// File: WOKNT_Handle.hxx +// Author: Jean GAUTIER +// + + +#ifndef WOKNT_Handle_HeaderFile +#define WOKNT_Handle_HeaderFile + +#ifdef WNT +#include + +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 index 0000000..5588047 --- /dev/null +++ b/src/WOKNT/WOKNT_MixedOutput.cdl @@ -0,0 +1,69 @@ +-- File: WOKNT_MixedOutput.cdl +-- Created: Tue Jul 30 10:19:51 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..1a87e19 --- /dev/null +++ b/src/WOKNT/WOKNT_MixedOutput.cxx @@ -0,0 +1,190 @@ +#define STRICT +#include + +#include + +#include +#include + +#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 index 0000000..0a49abc --- /dev/null +++ b/src/WOKNT/WOKNT_OutErrOutput.cdl @@ -0,0 +1,53 @@ +-- File: WOKNT_OutErrOutput.cdl +-- Created: Tue Jul 30 10:53:50 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..051176e --- /dev/null +++ b/src/WOKNT/WOKNT_OutErrOutput.cxx @@ -0,0 +1,103 @@ +#define STRICT +#include + +#include + +#include + +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 index 0000000..cc0dbb7 --- /dev/null +++ b/src/WOKNT/WOKNT_Path.cdl @@ -0,0 +1,130 @@ +-- File: WOKNT_Path.cdl +-- Created: Mon Jul 22 17:17:38 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..98ba8f5 --- /dev/null +++ b/src/WOKNT/WOKNT_Path.cxx @@ -0,0 +1,617 @@ +#define STRICT +#include + +#ifdef THIS +# undef THIS +#endif + +#ifdef CreateFile +# undef CreateFile +#endif + +#ifdef CreateDirectory +# undef CreateDirectory +#endif + +#ifdef RemoveDirectory +# undef RemoveDirectory +#endif + +#include + +#include +#include + +#include +//#include +//#include +//#include + +#ifndef _INC_TCHAR +# include +#endif // _INC_TCHAR + +#include + +#include +#include +#include +#include + +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 index 0000000..17fe433 --- /dev/null +++ b/src/WOKNT/WOKNT_Path.lxx @@ -0,0 +1,24 @@ +#include +#include + +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 index 0000000..a710be2 --- /dev/null +++ b/src/WOKNT/WOKNT_PathIterator.cdl @@ -0,0 +1,65 @@ +-- File: WOKNT_PathIterator.cdl +-- Created: Mon Aug 03 15:37:45 1998 +-- Author: +-- +---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 index 0000000..fd8ddd5 --- /dev/null +++ b/src/WOKNT/WOKNT_PathIterator.cxx @@ -0,0 +1,185 @@ + + +#include +#include + +#include + +#include + +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 index 0000000..af5a2ae --- /dev/null +++ b/src/WOKNT/WOKNT_RegExp.cdl @@ -0,0 +1,88 @@ +-- File: WOKNT_RegExp.cdl +-- Created: Fri Aug 2 09:43:37 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 and + -- its length to perform character translation. + -- Supply NULL for and zero value for + -- if no translation necessary. It is possible to set + -- syntax of the regular expression by meaning + -- 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 which matches + -- the specified pattern starting at index . + -- 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 + -- starting at index . Do not consider matching + -- past the position . + -- 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 index 0000000..ad71db2 --- /dev/null +++ b/src/WOKNT/WOKNT_RegExp.cxx @@ -0,0 +1,159 @@ + +#include + +#include + +#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 index 0000000..500404a --- /dev/null +++ b/src/WOKNT/WOKNT_ReplIfCh.c @@ -0,0 +1,30 @@ +#define STRICT +#include +#include + +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 index 0000000..b83c4b2 --- /dev/null +++ b/src/WOKNT/WOKNT_ReplIfChWith.c @@ -0,0 +1,30 @@ +#define STRICT +#include +#include + +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 index 0000000..16c2a5c --- /dev/null +++ b/src/WOKNT/WOKNT_Shell.cdl @@ -0,0 +1,142 @@ +-- File: WOKNT_Shell.cdl +-- Created: Thu Jul 25 12:42:56 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..ec3fd20 --- /dev/null +++ b/src/WOKNT/WOKNT_Shell.cxx @@ -0,0 +1,610 @@ +#define STRICT +#include +#include + +#ifdef CreateFile +# undef CreateFile +#endif // CreateFile + +#ifdef CreateDirectory +# undef CreateDirectory +#endif // CreateFile + +#ifdef RemoveDirectory +# undef RemoveDirectory +#endif // CreateFile + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#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]; + + GetCurrentDirectory(1024, aDir); + + 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 index 0000000..1cd4a8f --- /dev/null +++ b/src/WOKNT/WOKNT_Shell.lxx @@ -0,0 +1,31 @@ +#include + +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 index 0000000..6a98ff8 --- /dev/null +++ b/src/WOKNT/WOKNT_ShellManager.cdl @@ -0,0 +1,38 @@ +-- File: WOKNT_ShellManager.cdl +-- Created: Fri Jul 26 17:33:13 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..20896cd --- /dev/null +++ b/src/WOKNT/WOKNT_ShellManager.cxx @@ -0,0 +1,98 @@ +#define STRICT +#include +#include + + +#include + +#include + +#include +#include + +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 index 0000000..a48bc11 --- /dev/null +++ b/src/WOKNT/WOKNT_ShellOutput.cdl @@ -0,0 +1,55 @@ +-- File: WOKNT_ShellOutput.cdl +-- Created: Tue Jul 30 10:10:37 1996 +-- Author: PLOTNIKOV Eugeny +-- +---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 index 0000000..90c4664 --- /dev/null +++ b/src/WOKNT/WOKNT_ShellOutput.cxx @@ -0,0 +1,14 @@ +#define STRICT +#include + +#include + +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 index 0000000..32afbef --- /dev/null +++ b/src/WOKNT/WOKNT_Shell_1.cxx @@ -0,0 +1,435 @@ +#define STRICT +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 { + char aDir[1024]; + + GetCurrentDirectory(1024, aDir); + + 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 index 0000000..618780f --- /dev/null +++ b/src/WOKNT/WOKNT_TimeStat.hxx @@ -0,0 +1,14 @@ +#ifndef __WOKNT_FILETIME_HXX +# define __WOKNT_FILETIME_HXX + +# ifndef STRICT +# define STRICT +# endif // STRICT + +# ifndef _INC_TIME +# include +# 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 index 0000000..b0cb211 --- /dev/null +++ b/src/WOKNT/WOKNT_WNT_BREAK.hxx @@ -0,0 +1,9 @@ +#ifndef __WOKNT_WNT_BREAK__HXX +# define __WOKNT_WNT_BREAK__HXX + +# ifdef WNT +# include +# 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 index 0000000..4a8c2a1 --- /dev/null +++ b/src/WOKNT/WOKNT_WOKSteps.edl @@ -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 index 0000000..1994b45 --- /dev/null +++ b/src/WOKNT/WOKNT_chmod.cxx @@ -0,0 +1,268 @@ +#define EXPORT +#include +#include + +#include +#include +#include +#include + +#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 index 0000000..ef31294 --- /dev/null +++ b/src/WOKNT/WOKNT_cmp.c @@ -0,0 +1,67 @@ +#define STRICT +#include + +#include +#include + +__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 index 0000000..d90796a --- /dev/null +++ b/src/WOKNT/WOKNT_cp.cxx @@ -0,0 +1,124 @@ +#define STRICT +#include +#include + +#include +#include +#include + +#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; iIsFile() && 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 index 0000000..1c6e77e --- /dev/null +++ b/src/WOKNT/WOKNT_mv.cxx @@ -0,0 +1,36 @@ +#define EXPORT +#define STRICT +#include +#include + +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 index 0000000..690539a --- /dev/null +++ b/src/WOKNT/WOKNT_regexp.h @@ -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 +# endif /* _INC_TCHAR */ +/***/ +# ifndef _INC_STDLIB +# include +# endif /* _INC_STDLIB */ +/***/ +# ifndef _INC_MALLOC +# include +# endif /* _INC_MALLOC */ +/***/ +# ifndef _INC_LIMITS +# include +# endif /* _INC_LIMITS */ +# ifndef _INC_STRING +# include +# 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 +# include +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 index 0000000..8305a0f --- /dev/null +++ b/src/WOKNT/WOKNT_regexp_1.c @@ -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 + +#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 + +/***/ +/******************************************************************************/ +/* */ +/* 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, \ turns into a `duplicate' command which */ + /* is followed by the numeric value of 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 index 0000000..a81d56a --- /dev/null +++ b/src/WOKNT/WOKNT_rm.cxx @@ -0,0 +1,196 @@ +#define EXPORT +#include +#include +#include +#include + +#include +#include +#include +#include + +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