Merge branch 'upstream-kwsys' into update-kwsys

This commit is contained in:
Brad King 2012-12-19 08:09:36 -05:00
commit e33fa5b678
11 changed files with 119 additions and 1701 deletions

View File

@ -116,7 +116,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(KWSYS_USE_MD5 1)
SET(KWSYS_USE_Process 1)
SET(KWSYS_USE_RegularExpression 1)
SET(KWSYS_USE_Registry 1)
SET(KWSYS_USE_System 1)
SET(KWSYS_USE_SystemTools 1)
SET(KWSYS_USE_CommandLineArguments 1)
@ -762,7 +761,7 @@ SET(KWSYS_HXX_FILES Configure String
# Add selected C++ classes.
SET(cppclasses
Directory DynamicLoader Glob RegularExpression SystemTools
CommandLineArguments Registry IOStream SystemInformation
CommandLineArguments IOStream SystemInformation
)
FOREACH(cpp ${cppclasses})
IF(KWSYS_USE_${cpp})
@ -800,12 +799,8 @@ SET(KWSYS_CXX_SRCS)
# Add the proper sources for this platform's Process implementation.
IF(KWSYS_USE_Process)
IF(NOT UNIX)
# Use the Windows implementation. We need the encoded forwarding executable.
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c
${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c)
SET_SOURCE_FILES_PROPERTIES(
${PROJECT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
PROPERTIES GENERATED 1)
# Use the Windows implementation.
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessWin32.c)
ELSE(NOT UNIX)
# Use the UNIX implementation.
SET(KWSYS_C_SRCS ${KWSYS_C_SRCS} ProcessUNIX.c)
@ -937,43 +932,6 @@ IF(KWSYS_USE_String)
COMPILE_FLAGS "-DKWSYS_STRING_C")
ENDIF(KWSYS_USE_String)
#-----------------------------------------------------------------------------
# Process execution on windows needs to build a forwarding executable
# that works around a Win9x bug. We encode the executable into a C
# file and build it into the library. Win9x platforms reproduce the
# executable into a temporary directory when it is needed.
IF(KWSYS_USE_Process)
IF(NOT UNIX)
# Build the forwarding executable itself and a program that will
# encode it into a C file.
ADD_EXECUTABLE(${KWSYS_NAMESPACE}ProcessFwd9x ProcessFwd9x.c)
ADD_EXECUTABLE(${KWSYS_NAMESPACE}EncodeExecutable EncodeExecutable.c)
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}ProcessFwd9x PROPERTY LABELS ${KWSYS_LABELS_EXE})
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}EncodeExecutable PROPERTY LABELS ${KWSYS_LABELS_EXE})
SET(CFG_INTDIR "/${CMAKE_CFG_INTDIR}")
IF(CMAKE_BUILD_TOOL MATCHES "make")
SET(CFG_INTDIR "")
ENDIF(CMAKE_BUILD_TOOL MATCHES "make")
# Take advantage of a better custom command syntax if possible.
SET(CMD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}EncodeExecutable.exe)
SET(FWD ${CMAKE_CURRENT_BINARY_DIR}${CFG_INTDIR}/${KWSYS_NAMESPACE}ProcessFwd9x.exe)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
COMMAND ${CMD}
ARGS ${FWD} ${CMAKE_CURRENT_BINARY_DIR}/${KWSYS_NAMESPACE}ProcessFwd9xEnc.c
${KWSYS_NAMESPACE} ProcessFwd9x
DEPENDS ${CMD} ${FWD})
# Make sure build occurs in proper order.
ADD_DEPENDENCIES(${KWSYS_NAMESPACE} ${KWSYS_NAMESPACE}ProcessFwd9x
${KWSYS_NAMESPACE}EncodeExecutable)
ENDIF(NOT UNIX)
ENDIF(KWSYS_USE_Process)
#-----------------------------------------------------------------------------
# Setup testing if not being built as part of another project.
IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
@ -1012,7 +970,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
)
ENDIF(NOT WATCOM)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
testRegistry
testIOS
testSystemTools
testCommandLineArguments
@ -1116,8 +1073,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# We expect test to fail
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES WILL_FAIL ON)
GET_TEST_PROPERTY(kwsys.testFail WILL_FAIL wfv)
SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES FAIL_REGULAR_EXPRESSION "ERROR_NOT_VALGRIND;FAIL;Test failed")
SET_TESTS_PROPERTIES(kwsys.testRegistry PROPERTIES PASS_REGULAR_EXPRESSION "Test passed")
SET_TESTS_PROPERTIES(kwsys.testFail PROPERTIES MEASUREMENT "Some Key=Some Value")
MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
ENDIF()

View File

@ -1,114 +0,0 @@
/*============================================================================
KWSys - Kitware System Library
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include <stdio.h>
#ifdef __WATCOMC__
#define _unlink unlink
#endif
int main(int argc, char* argv[])
{
FILE* ifp;
FILE* ofp;
int i;
int n;
int count = 0;
unsigned char buffer[1024];
/* Check arguments. */
if(argc != 5)
{
fprintf(stderr, "Usage: %s <input> <output> <kwsys-name> <array>\n",
argv[0]);
return 1;
}
/* Open the input file. */
ifp = fopen(argv[1], "rb");
if(!ifp)
{
fprintf(stderr, "Cannot open input file: \"%s\"\n", argv[1]);
return 2;
}
ofp = fopen(argv[2], "w");
if(!ofp)
{
fprintf(stderr, "Cannot open output file: \"%s\"\n", argv[2]);
fclose(ifp);
return 2;
}
/* Prepend header comment. */
fprintf(ofp, "/*\n * DO NOT EDIT\n * This file is generated by:\n");
fprintf(ofp, " * %s\n */\n\n", argv[0]);
fprintf(ofp, "#include \"kwsysPrivate.h\"\n");
fprintf(ofp, "#include KWSYS_HEADER(Configure.h)\n\n");
fprintf(ofp, "#include <stdio.h>\n\n");
fprintf(ofp, "#if defined(_WIN32)\n");
fprintf(ofp, "# include <io.h>\n");
fprintf(ofp, "#else\n");
fprintf(ofp, "# include <unistd.h>\n");
fprintf(ofp, "#endif\n");
fprintf(ofp, "\n");
fprintf(ofp, "static void kwsys_unlink(const char* fname)\n");
fprintf(ofp, "{\n");
fprintf(ofp, "#if defined(__WATCOMC__)\n");
fprintf(ofp, " unlink(fname);\n");
fprintf(ofp, "#else\n");
fprintf(ofp, " _unlink(fname);\n");
fprintf(ofp, "#endif\n");
fprintf(ofp, "}\n");
fprintf(ofp, "\n");
/* Split file up in 1024-byte chunks. */
while((n = (int)fread(buffer, 1, 1024, ifp)) > 0)
{
fprintf(ofp, "static unsigned char kwsysEncodedArray%s_%d[%d] = {\n",
argv[4], count++, n);
for(i=0; i < n-1; ++i)
{
fprintf(ofp, "0x%02X", buffer[i]);
if(i%10 == 9)
{
fprintf(ofp, ",\n");
}
else
{
fprintf(ofp, ", ");
}
}
fprintf(ofp, "0x%02X};\n\n", buffer[n-1]);
}
fclose(ifp);
/* Provide a function to write the data to a file. */
fprintf(ofp, "extern %s_EXPORT int %sEncodedWriteArray%s(const char* fname)\n",
argv[3], argv[3], argv[4]);
fprintf(ofp, "{\n");
fprintf(ofp, " FILE* ofp = fopen(fname, \"wb\");\n");
fprintf(ofp, " if(!ofp) { return 0; }\n");
for(i=0; i < count; ++i)
{
fprintf(ofp, " if(fwrite(kwsysEncodedArray%s_%d, 1,\n"
" sizeof(kwsysEncodedArray%s_%d), ofp) !=\n"
" sizeof(kwsysEncodedArray%s_%d))\n",
argv[4], i, argv[4], i, argv[4], i);
fprintf(ofp, " {\n");
fprintf(ofp, " fclose(ofp);\n");
fprintf(ofp, " kwsys_unlink(fname);\n");
fprintf(ofp, " return 0;\n");
fprintf(ofp, " }\n");
}
fprintf(ofp, " fclose(ofp);\n");
fprintf(ofp, " return 1;\n");
fprintf(ofp, "}\n");
fclose(ofp);
return 0;
}

View File

@ -1,211 +0,0 @@
/*============================================================================
KWSys - Kitware System Library
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
/*
On Windows9x platforms, this executable is spawned between a parent
process and the child it is invoking to work around a bug. See the
Win32 implementation file for details.
Future Work: This executable must be linked statically against the C
runtime library before being encoded into the library. Building it
in this way may be hard because CMake has limited abilities to build
different targets with different configurations in the same
directory. We may just have to create and encode the executable
once instead of generating it during the build. This would be an
acceptable solution because the forwarding executable should not
change very often and is pretty simple.
*/
#ifdef _MSC_VER
#pragma warning (push, 1)
#endif
#include <windows.h>
#include <stdio.h>
void ReportLastError(HANDLE errorPipe);
int main()
{
/* Process startup information for the real child. */
STARTUPINFO si;
PROCESS_INFORMATION pi;
/* The result of waiting for the child to exit. */
DWORD waitResult;
/* The child's process return code. */
DWORD retVal;
/* The command line used to invoke this process. */
LPSTR commandLine = GetCommandLine();
/* Pointer that will be advanced to the beginning of the command
line of the real child process. */
LPSTR cmdLine = commandLine;
/* Handle to the error reporting pipe provided by the parent. This
is parsed off the command line. */
HANDLE errorPipe = 0;
HANDLE errorPipeOrig = 0;
/* Handle to the event the parent uses to tell us to resume the child.
This is parsed off the command line. */
HANDLE resumeEvent = 0;
/* Handle to the event the parent uses to tell us to kill the child.
This is parsed off the command line. */
HANDLE killEvent = 0;
/* Flag for whether to hide window of child process. */
int hideWindow = 0;
/* An array of the handles on which we wait when the child is
running. */
HANDLE waitHandles[2] = {0, 0};
/* Move the pointer past the name of this executable. */
if(*cmdLine == '"')
{
++cmdLine;
while(*cmdLine && *cmdLine != '"') { ++cmdLine; }
if(*cmdLine) { ++cmdLine; }
}
else
{
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
}
/* Parse the error pipe handle. */
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
sscanf(cmdLine, "%p", &errorPipeOrig);
/* Parse the resume event handle. */
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
sscanf(cmdLine, "%p", &resumeEvent);
/* Parse the kill event handle. */
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
sscanf(cmdLine, "%p", &killEvent);
/* Parse the hide window flag. */
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
sscanf(cmdLine, "%d", &hideWindow);
/* Skip to the beginning of the command line of the real child. */
while(*cmdLine && *cmdLine != ' ') { ++cmdLine; }
while(*cmdLine && *cmdLine == ' ') { ++cmdLine; }
/* Create a non-inherited copy of the error pipe. We do not want
the child to get it. */
if(DuplicateHandle(GetCurrentProcess(), errorPipeOrig,
GetCurrentProcess(), &errorPipe,
0, FALSE, DUPLICATE_SAME_ACCESS))
{
/* Have a non-inherited duplicate. Close the inherited one. */
CloseHandle(errorPipeOrig);
}
else
{
/* Could not duplicate handle. Report the error. */
ReportLastError(errorPipeOrig);
return 1;
}
/* Create the subprocess. */
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
si.wShowWindow = hideWindow?SW_HIDE:SW_SHOWDEFAULT;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if(CreateProcess(0, cmdLine, 0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &si, &pi))
{
/* Process created successfully. Close the error reporting pipe
to notify the parent of success. */
CloseHandle(errorPipe);
}
else
{
/* Error creating the process. Report the error to the parent
process through the special error reporting pipe. */
ReportLastError(errorPipe);
return 1;
}
/* Wait for resume or kill event from parent. */
waitHandles[0] = killEvent;
waitHandles[1] = resumeEvent;
waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
/* Check what happened. */
if(waitResult == WAIT_OBJECT_0)
{
/* We were asked to kill the child. */
TerminateProcess(pi.hProcess, 255);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 1;
}
else
{
/* We were asked to resume the child. */
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
}
/* Wait for subprocess to exit or for kill event from parent. */
waitHandles[0] = killEvent;
waitHandles[1] = pi.hProcess;
waitResult = WaitForMultipleObjects(2, waitHandles, 0, INFINITE);
/* Check what happened. */
if(waitResult == WAIT_OBJECT_0)
{
/* We were asked to kill the child. */
TerminateProcess(pi.hProcess, 255);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
return 1;
}
else
{
/* The child exited. Get the return code. */
GetExitCodeProcess(pi.hProcess, &retVal);
CloseHandle(pi.hProcess);
return retVal;
}
}
void ReportLastError(HANDLE errorPipe)
{
LPVOID lpMsgBuf;
DWORD n;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
WriteFile(errorPipe, lpMsgBuf, strlen(lpMsgBuf)+1, &n, 0);
LocalFree( lpMsgBuf );
}

View File

@ -28,14 +28,6 @@ On windows, a thread is created to wait for data on each pipe. The
threads are synchronized with the main thread to simulate the use of
a UNIX-style select system call.
On Windows9x platforms, a small WIN32 console application is spawned
in-between the calling process and the actual child to be executed.
This is to work-around a problem with connecting pipes from WIN16
console applications to WIN32 applications.
For more information, please check Microsoft Knowledge Base Articles
Q190351 and Q150956.
*/
#ifdef _MSC_VER
@ -91,18 +83,12 @@ Q190351 and Q150956.
# define KWSYSPE_DEBUG(x) (void)1
#endif
#define kwsysEncodedWriteArrayProcessFwd9x kwsys_ns(EncodedWriteArrayProcessFwd9x)
typedef LARGE_INTEGER kwsysProcessTime;
typedef struct kwsysProcessCreateInformation_s
{
/* Windows child startup control data. */
STARTUPINFO StartupInfo;
/* Special error reporting pipe for Win9x forwarding executable. */
HANDLE ErrorPipeRead;
HANDLE ErrorPipeWrite;
} kwsysProcessCreateInformation;
/*--------------------------------------------------------------------------*/
@ -146,7 +132,6 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
static void kwsysProcessKillTree(int pid);
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
/*--------------------------------------------------------------------------*/
/* A structure containing synchronization data for each thread. */
@ -233,15 +218,6 @@ struct kwsysProcess_s
/* Whether to treat command lines as verbatim. */
int Verbatim;
/* On Win9x platforms, the path to the forwarding executable. */
char* Win9x;
/* On Win9x platforms, the resume event for the forwarding executable. */
HANDLE Win9xResumeEvent;
/* On Win9x platforms, the kill event for the forwarding executable. */
HANDLE Win9xKillEvent;
/* Mutex to protect the shared index used by threads to report data. */
HANDLE SharedIndexMutex;
@ -269,9 +245,6 @@ struct kwsysProcess_s
HANDLE PipeNativeSTDOUT[2];
HANDLE PipeNativeSTDERR[2];
/* Handle to automatically delete the Win9x forwarding executable. */
HANDLE Win9xHandle;
/* ------------- Data managed per call to Execute ------------- */
/* The exceptional behavior that terminated the process, if any. */
@ -311,7 +284,7 @@ struct kwsysProcess_s
for pipes to close after process termination. */
int PipesLeft;
/* Buffer for error messages (possibly from Win9x child). */
/* Buffer for error messages. */
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
/* Description for the ExitException. */
@ -337,9 +310,6 @@ kwsysProcess* kwsysProcess_New(void)
/* Process control structure. */
kwsysProcess* cp;
/* Path to Win9x forwarding executable. */
char* win9x = 0;
/* Windows version number data. */
OSVERSIONINFO osv;
@ -365,73 +335,11 @@ kwsysProcess* kwsysProcess_New(void)
GetVersionEx(&osv);
if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
/* This is Win9x. We need the console forwarding executable to
work-around a Windows 9x bug. */
char fwdName[_MAX_FNAME+1] = "";
char tempDir[_MAX_PATH+1] = "";
/* We will try putting the executable in the system temp
directory. Note that the returned path already has a trailing
slash. */
DWORD length = GetTempPath(_MAX_PATH+1, tempDir);
/* Construct the executable name from the process id and kwsysProcess
instance. This should be unique. */
sprintf(fwdName, KWSYS_NAMESPACE_STRING "pew9xfwd_%ld_%p.exe",
GetCurrentProcessId(), cp);
/* If we have a temp directory, use it. */
if(length > 0 && length <= _MAX_PATH)
{
/* Allocate a buffer to hold the forwarding executable path. */
size_t tdlen = strlen(tempDir);
win9x = (char*)malloc(tdlen + strlen(fwdName) + 2);
if(!win9x)
{
kwsysProcess_Delete(cp);
return 0;
}
/* Construct the full path to the forwarding executable. */
sprintf(win9x, "%s%s", tempDir, fwdName);
}
/* If we found a place to put the forwarding executable, try to
write it. */
if(win9x)
{
if(!kwsysEncodedWriteArrayProcessFwd9x(win9x))
{
/* Failed to create forwarding executable. Give up. */
free(win9x);
kwsysProcess_Delete(cp);
return 0;
}
/* Get a handle to the file that will delete it when closed. */
cp->Win9xHandle = CreateFile(win9x, GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
if(cp->Win9xHandle == INVALID_HANDLE_VALUE)
{
/* We were not able to get a read handle for the forwarding
executable. It will not be deleted properly. Give up. */
_unlink(win9x);
free(win9x);
kwsysProcess_Delete(cp);
return 0;
}
}
else
{
/* Failed to find a place to put forwarding executable. */
kwsysProcess_Delete(cp);
return 0;
}
/* Win9x no longer supported. */
kwsysProcess_Delete(cp);
return 0;
}
/* Save the path to the forwarding executable. */
cp->Win9x = win9x;
/* Initially no thread owns the mutex. Initialize semaphore to 1. */
if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
{
@ -446,30 +354,6 @@ kwsysProcess* kwsysProcess_New(void)
return 0;
}
if(cp->Win9x)
{
SECURITY_ATTRIBUTES sa;
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
/* Create an event to tell the forwarding executable to resume the
child. */
if(!(cp->Win9xResumeEvent = CreateEvent(&sa, TRUE, 0, 0)))
{
kwsysProcess_Delete(cp);
return 0;
}
/* Create an event to tell the forwarding executable to kill the
child. */
if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0)))
{
kwsysProcess_Delete(cp);
return 0;
}
}
/* Create the thread to read each pipe. */
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
{
@ -620,13 +504,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
kwsysProcessCleanupHandle(&cp->Full);
/* Close the Win9x resume and kill event handles. */
if(cp->Win9x)
{
kwsysProcessCleanupHandle(&cp->Win9xResumeEvent);
kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
}
/* Free memory. */
kwsysProcess_SetCommand(cp, 0);
kwsysProcess_SetWorkingDirectory(cp, 0);
@ -637,12 +514,6 @@ void kwsysProcess_Delete(kwsysProcess* cp)
{
free(cp->CommandExitCodes);
}
if(cp->Win9x)
{
/* Close our handle to the forwarding executable file. This will
cause it to be deleted. */
kwsysProcessCleanupHandle(&cp->Win9xHandle);
}
free(cp);
}
@ -1017,21 +888,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
SetCurrentDirectory(cp->WorkingDirectory);
}
/* Reset the Win9x resume and kill events. */
if(cp->Win9x)
{
if(!ResetEvent(cp->Win9xResumeEvent))
{
kwsysProcessCleanup(cp, 1);
return;
}
if(!ResetEvent(cp->Win9xKillEvent))
{
kwsysProcessCleanup(cp, 1);
return;
}
}
/* Initialize startup info data. */
ZeroMemory(&si, sizeof(si));
si.StartupInfo.cb = sizeof(si.StartupInfo);
@ -1130,8 +986,6 @@ void kwsysProcess_Execute(kwsysProcess* cp)
STD_OUTPUT_HANDLE);
kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
STD_ERROR_HANDLE);
kwsysProcessCleanupHandle(&si.ErrorPipeRead);
kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
return;
}
}
@ -1160,16 +1014,9 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* All processes in the pipeline have been started in suspended
mode. Resume them all now. */
if(cp->Win9x)
for(i=0; i < cp->NumberOfCommands; ++i)
{
SetEvent(cp->Win9xResumeEvent);
}
else
{
for(i=0; i < cp->NumberOfCommands; ++i)
{
ResumeThread(cp->ProcessInformation[i].hThread);
}
ResumeThread(cp->ProcessInformation[i].hThread);
}
/* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
@ -1480,21 +1327,12 @@ void kwsysProcess_Kill(kwsysProcess* cp)
/* Kill the children. */
cp->Killed = 1;
if(cp->Win9x)
for(i=0; i < cp->NumberOfCommands; ++i)
{
/* Windows 9x. Tell the forwarding executable to kill the child. */
SetEvent(cp->Win9xKillEvent);
}
else
{
/* Not Windows 9x. Just terminate the children. */
for(i=0; i < cp->NumberOfCommands; ++i)
{
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
// close the handle if we kill it
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
}
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
// close the handle if we kill it
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
}
/* We are killing the children and ignoring all data. Do not wait
@ -1815,97 +1653,13 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
}
}
/* Create the child process. */
{
BOOL r;
char* realCommand;
if(cp->Win9x)
{
/* Create an error reporting pipe for the forwarding executable.
Neither end is directly inherited. */
if(!CreatePipe(&si->ErrorPipeRead, &si->ErrorPipeWrite, 0, 0))
{
return 0;
}
/* Create an inherited duplicate of the write end. This also closes
the non-inherited version. */
if(!DuplicateHandle(GetCurrentProcess(), si->ErrorPipeWrite,
GetCurrentProcess(), &si->ErrorPipeWrite,
0, TRUE, (DUPLICATE_CLOSE_SOURCE |
DUPLICATE_SAME_ACCESS)))
{
return 0;
}
/* The forwarding executable is given a handle to the error pipe
and resume and kill events. */
realCommand = (char*)malloc(strlen(cp->Win9x)+strlen(cp->Commands[index])+100);
if(!realCommand)
{
return 0;
}
sprintf(realCommand, "%s %p %p %p %d %s", cp->Win9x,
si->ErrorPipeWrite, cp->Win9xResumeEvent, cp->Win9xKillEvent,
cp->HideWindow, cp->Commands[index]);
}
else
{
realCommand = cp->Commands[index];
}
/* Create the child in a suspended state so we can wait until all
children have been created before running any one. */
r = CreateProcess(0, realCommand, 0, 0, TRUE,
cp->Win9x? 0 : CREATE_SUSPENDED, 0, 0,
&si->StartupInfo, &cp->ProcessInformation[index]);
if(cp->Win9x)
{
/* Free memory. */
free(realCommand);
/* Close the error pipe write end so we can detect when the
forwarding executable closes it. */
kwsysProcessCleanupHandle(&si->ErrorPipeWrite);
if(r)
{
/* Wait for the forwarding executable to report an error or
close the error pipe to report success. */
DWORD total = 0;
DWORD n = 1;
while(total < KWSYSPE_PIPE_BUFFER_SIZE && n > 0)
{
if(ReadFile(si->ErrorPipeRead, cp->ErrorMessage+total,
KWSYSPE_PIPE_BUFFER_SIZE-total, &n, 0))
{
total += n;
}
else
{
n = 0;
}
}
if(total > 0 || GetLastError() != ERROR_BROKEN_PIPE)
{
/* The forwarding executable could not run the process, or
there was an error reading from its error pipe. Preserve
the last error while cleaning up the forwarding executable
so the cleanup our caller does reports the proper error. */
DWORD error = GetLastError();
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread);
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
SetLastError(error);
return 0;
}
}
kwsysProcessCleanupHandle(&si->ErrorPipeRead);
}
if(!r)
if(!CreateProcess(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
0, &si->StartupInfo, &cp->ProcessInformation[index]))
{
return 0;
}
}
/* Successfully created this child process. Close the current
process's copies of the inherited stdout and stdin handles. The
@ -2152,19 +1906,12 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
/* Cleanup any processes already started in a suspended state. */
if(cp->ProcessInformation)
{
if(cp->Win9x)
for(i=0; i < cp->NumberOfCommands; ++i)
{
SetEvent(cp->Win9xKillEvent);
}
else
{
for(i=0; i < cp->NumberOfCommands; ++i)
if(cp->ProcessInformation[i].hProcess)
{
if(cp->ProcessInformation[i].hProcess)
{
TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
}
TerminateProcess(cp->ProcessInformation[i].hProcess, 255);
WaitForSingleObject(cp->ProcessInformation[i].hProcess, INFINITE);
}
}
for(i=0; i < cp->NumberOfCommands; ++i)

View File

@ -1,818 +0,0 @@
/*============================================================================
KWSys - Kitware System Library
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Registry.hxx)
#include KWSYS_HEADER(Configure.hxx)
#include KWSYS_HEADER(ios/iostream)
#include KWSYS_HEADER(stl/string)
#include KWSYS_HEADER(stl/map)
#include KWSYS_HEADER(ios/iostream)
#include KWSYS_HEADER(ios/fstream)
#include KWSYS_HEADER(ios/sstream)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
# include "Registry.hxx.in"
# include "Configure.hxx.in"
# include "kwsys_stl.hxx.in"
# include "kwsys_stl_string.hxx.in"
# include "kwsys_stl_map.hxx.in"
# include "kwsys_ios_iostream.h.in"
# include "kwsys_ios_fstream.h.in"
# include "kwsys_ios_sstream.h.in"
#endif
#include <ctype.h> // for isspace
#include <stdio.h>
#include <string.h> /* strlen, strncpy */
#include <stdlib.h> /* getenv */
#ifdef _WIN32
# include <windows.h>
#endif
namespace KWSYS_NAMESPACE
{
class RegistryHelper {
public:
RegistryHelper(Registry::RegistryType registryType);
virtual ~RegistryHelper();
// Read a value from the registry.
virtual bool ReadValue(const char *key, const char **value);
// Delete a key from the registry.
virtual bool DeleteKey(const char *key);
// Delete a value from a given key.
virtual bool DeleteValue(const char *key);
// Set value in a given key.
virtual bool SetValue(const char *key, const char *value);
// Open the registry at toplevel/subkey.
virtual bool Open(const char *toplevel, const char *subkey,
int readonly);
// Close the registry.
virtual bool Close();
// Set the value of changed
void SetChanged(bool b) { m_Changed = b; }
void SetTopLevel(const char* tl);
const char* GetTopLevel() { return m_TopLevel.c_str(); }
//! Read from local or global scope. On Windows this mean from local machine
// or local user. On unix this will read from $HOME/.Projectrc or
// /etc/Project
void SetGlobalScope(bool b);
bool GetGlobalScope();
kwsys_stl::string EncodeKey(const char* str);
kwsys_stl::string EncodeValue(const char* str);
kwsys_stl::string DecodeValue(const char* str);
protected:
bool m_Changed;
kwsys_stl::string m_TopLevel;
bool m_GlobalScope;
#ifdef _WIN32
HKEY HKey;
#endif
// Strip trailing and ending spaces.
char *Strip(char *str);
void SetSubKey(const char* sk);
kwsys_stl::string CreateKey(const char *key);
typedef kwsys_stl::map<kwsys_stl::string, kwsys_stl::string> StringToStringMap;
StringToStringMap EntriesMap;
kwsys_stl::string m_SubKey;
bool m_Empty;
bool m_SubKeySpecified;
kwsys_stl::string m_HomeDirectory;
Registry::RegistryType m_RegistryType;
};
//----------------------------------------------------------------------------
#define Registry_BUFFER_SIZE 8192
//----------------------------------------------------------------------------
Registry::Registry(Registry::RegistryType registryType)
{
m_Opened = false;
m_Locked = false;
this->Helper = 0;
this->Helper = new RegistryHelper(registryType);
}
//----------------------------------------------------------------------------
Registry::~Registry()
{
if ( m_Opened )
{
kwsys_ios::cerr << "Registry::Close should be "
"called here. The registry is not closed."
<< kwsys_ios::endl;
}
delete this->Helper;
}
//----------------------------------------------------------------------------
void Registry::SetGlobalScope(bool b)
{
this->Helper->SetGlobalScope(b);
}
//----------------------------------------------------------------------------
bool Registry::GetGlobalScope()
{
return this->Helper->GetGlobalScope();
}
//----------------------------------------------------------------------------
bool Registry::Open(const char *toplevel,
const char *subkey, int readonly)
{
bool res = false;
if ( m_Locked )
{
return res;
}
if ( m_Opened )
{
if ( !this->Close() )
{
return res;
}
}
if ( !toplevel || !*toplevel )
{
kwsys_ios::cerr << "Registry::Opened() Toplevel not defined"
<< kwsys_ios::endl;
return res;
}
if ( isspace(toplevel[0]) ||
isspace(toplevel[strlen(toplevel)-1]) )
{
kwsys_ios::cerr << "Toplevel has to start with letter or number and end"
" with one" << kwsys_ios::endl;
return res;
}
res = this->Helper->Open(toplevel, subkey, readonly);
if ( readonly != Registry::READONLY )
{
m_Locked = true;
}
if ( res )
{
m_Opened = true;
this->Helper->SetTopLevel(toplevel);
}
return res;
}
//----------------------------------------------------------------------------
bool Registry::Close()
{
bool res = false;
if ( m_Opened )
{
res = this->Helper->Close();
}
if ( res )
{
m_Opened = false;
m_Locked = false;
this->Helper->SetChanged(false);
}
return res;
}
//----------------------------------------------------------------------------
bool Registry::ReadValue(const char *subkey,
const char *key,
const char **value)
{
bool res = false;
bool open = false;
if ( ! value )
{
return res;
}
*value = 0;
if ( !m_Opened )
{
if ( !this->Open(this->GetTopLevel(), subkey,
Registry::READONLY) )
{
return res;
}
open = true;
}
res = this->Helper->ReadValue(key, value);
if ( open )
{
if ( !this->Close() )
{
res = false;
}
}
return res;
}
//----------------------------------------------------------------------------
bool Registry::DeleteKey(const char *subkey, const char *key)
{
bool res = false;
bool open = false;
if ( !m_Opened )
{
if ( !this->Open(this->GetTopLevel(), subkey,
Registry::READWRITE) )
{
return res;
}
open = true;
}
res = this->Helper->DeleteKey(key);
if ( res )
{
this->Helper->SetChanged(true);
}
if ( open )
{
if ( !this->Close() )
{
res = false;
}
}
return res;
}
//----------------------------------------------------------------------------
bool Registry::DeleteValue(const char *subkey, const char *key)
{
bool res = false;
bool open = false;
if ( !m_Opened )
{
if ( !this->Open(this->GetTopLevel(), subkey,
Registry::READWRITE) )
{
return res;
}
open = true;
}
res = this->Helper->DeleteValue(key);
if ( res )
{
this->Helper->SetChanged(true);
}
if ( open )
{
if ( !this->Close() )
{
res = false;
}
}
return res;
}
//----------------------------------------------------------------------------
bool Registry::SetValue(const char *subkey, const char *key,
const char *value)
{
bool res = false;
bool open = false;
if ( !m_Opened )
{
if ( !this->Open(this->GetTopLevel(), subkey,
Registry::READWRITE) )
{
return res;
}
open = true;
}
res = this->Helper->SetValue( key, value );
if ( res )
{
this->Helper->SetChanged(true);
}
if ( open )
{
if ( !this->Close() )
{
res = false;
}
}
return res;
}
//----------------------------------------------------------------------------
const char* Registry::GetTopLevel()
{
return this->Helper->GetTopLevel();
}
//----------------------------------------------------------------------------
void Registry::SetTopLevel(const char* tl)
{
this->Helper->SetTopLevel(tl);
}
//----------------------------------------------------------------------------
void RegistryHelper::SetTopLevel(const char* tl)
{
if ( tl )
{
m_TopLevel = tl;
}
else
{
m_TopLevel = "";
}
}
//----------------------------------------------------------------------------
RegistryHelper::RegistryHelper(Registry::RegistryType registryType)
{
m_Changed = false;
m_TopLevel = "";
m_SubKey = "";
m_SubKeySpecified = false;
m_Empty = true;
m_GlobalScope = false;
m_RegistryType = registryType;
}
//----------------------------------------------------------------------------
RegistryHelper::~RegistryHelper()
{
}
//----------------------------------------------------------------------------
bool RegistryHelper::Open(const char *toplevel, const char *subkey,
int readonly)
{
this->EntriesMap.clear();
m_Empty = 1;
#ifdef _WIN32
if ( m_RegistryType == Registry::WIN32_REGISTRY)
{
HKEY scope = HKEY_CURRENT_USER;
if ( this->GetGlobalScope() )
{
scope = HKEY_LOCAL_MACHINE;
}
int res = 0;
kwsys_ios::ostringstream str;
DWORD dwDummy;
str << "Software\\Kitware\\" << toplevel << "\\" << subkey;
if ( readonly == Registry::READONLY )
{
res = ( RegOpenKeyEx(scope, str.str().c_str(),
0, KEY_READ, &this->HKey) == ERROR_SUCCESS );
}
else
{
char lpClass[] = "";
res = ( RegCreateKeyEx(scope, str.str().c_str(),
0, lpClass, REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE,
NULL, &this->HKey, &dwDummy) == ERROR_SUCCESS );
}
if ( res != 0 )
{
this->SetSubKey( subkey );
}
return (res != 0);
}
#endif
if ( m_RegistryType == Registry::FILE_REGISTRY )
{
bool res = false;
int cc;
kwsys_ios::ostringstream str;
const char* homeDirectory;
if ( (homeDirectory = getenv("HOME")) == 0 )
{
if ( (homeDirectory = getenv("USERPROFILE")) == 0 )
{
return false;
}
}
m_HomeDirectory = homeDirectory;
str << m_HomeDirectory.c_str() << "/." << toplevel << "rc";
if ( readonly == Registry::READWRITE )
{
kwsys_ios::ofstream ofs( str.str().c_str(), kwsys_ios::ios::out|kwsys_ios::ios::app );
if ( ofs.fail() )
{
return false;
}
ofs.close();
}
kwsys_ios::ifstream *ifs = new kwsys_ios::ifstream(str.str().c_str(), kwsys_ios::ios::in
#ifndef KWSYS_IOS_USE_ANSI
| kwsys_ios::ios::nocreate
#endif
);
if ( !ifs )
{
return false;
}
if ( ifs->fail())
{
delete ifs;
return false;
}
res = true;
char buffer[Registry_BUFFER_SIZE];
while( !ifs->fail() )
{
ifs->getline(buffer, Registry_BUFFER_SIZE);
if ( ifs->fail() || ifs->eof() )
{
break;
}
char *line = this->Strip(buffer);
if ( *line == '#' || *line == 0 )
{
// Comment
continue;
}
int linelen = static_cast<int>(strlen(line));
for ( cc = 0; cc < linelen; cc++ )
{
if ( line[cc] == '=' )
{
char *key = new char[ cc+1 ];
strncpy( key, line, cc );
key[cc] = 0;
char *value = line + cc + 1;
char *nkey = this->Strip(key);
char *nvalue = this->Strip(value);
this->EntriesMap[nkey] = this->DecodeValue(nvalue);
m_Empty = 0;
delete [] key;
break;
}
}
}
ifs->close();
this->SetSubKey( subkey );
delete ifs;
return res;
}
return false;
}
//----------------------------------------------------------------------------
bool RegistryHelper::Close()
{
#ifdef _WIN32
if ( m_RegistryType == Registry::WIN32_REGISTRY)
{
int res;
res = ( RegCloseKey(this->HKey) == ERROR_SUCCESS );
return (res != 0);
}
#endif
if ( m_RegistryType == Registry::FILE_REGISTRY )
{
if ( !m_Changed )
{
this->SetSubKey(0);
return true;
}
kwsys_ios::ostringstream str;
str << m_HomeDirectory.c_str() << "/." << this->GetTopLevel() << "rc";
kwsys_ios::ofstream *ofs = new kwsys_ios::ofstream(str.str().c_str(), kwsys_ios::ios::out);
if ( !ofs )
{
return false;
}
if ( ofs->fail())
{
delete ofs;
return false;
}
*ofs << "# This file is automatically generated by the application" << kwsys_ios::endl
<< "# If you change any lines or add new lines, note that all" << kwsys_ios::endl
<< "# comments and empty lines will be deleted. Every line has" << kwsys_ios::endl
<< "# to be in format: " << kwsys_ios::endl
<< "# key = value" << kwsys_ios::endl
<< "#" << kwsys_ios::endl;
if ( !this->EntriesMap.empty() )
{
RegistryHelper::StringToStringMap::iterator it;
for ( it = this->EntriesMap.begin();
it != this->EntriesMap.end();
++ it )
{
*ofs << it->first.c_str() << " = " << this->EncodeValue(it->second.c_str()).c_str() << kwsys_ios::endl;
}
}
this->EntriesMap.clear();
ofs->close();
delete ofs;
this->SetSubKey(0);
m_Empty = 1;
return true;
}
return false;
}
//----------------------------------------------------------------------------
bool RegistryHelper::ReadValue(const char *skey, const char **value)
{
#ifdef _WIN32
if ( m_RegistryType == Registry::WIN32_REGISTRY)
{
kwsys_stl::string key = this->CreateKey( skey );
if ( key.empty() )
{
return false;
}
DWORD dwType, dwSize;
dwType = REG_SZ;
char buffer[1024]; // Replace with RegQueryInfoKey
dwSize = sizeof(buffer);
int res = ( RegQueryValueEx(this->HKey, skey, NULL, &dwType,
(BYTE *)buffer, &dwSize) == ERROR_SUCCESS );
if ( !res )
{
return false;
}
this->EntriesMap[key] = buffer;
RegistryHelper::StringToStringMap::iterator it
= this->EntriesMap.find(key);
*value = it->second.c_str();
return true;
}
#endif
if ( m_RegistryType == Registry::FILE_REGISTRY )
{
bool res = false;
kwsys_stl::string key = this->CreateKey( skey );
if ( key.empty() )
{
return false;
}
RegistryHelper::StringToStringMap::iterator it
= this->EntriesMap.find(key);
if ( it != this->EntriesMap.end() )
{
*value = it->second.c_str();
res = true;
}
return res;
}
return false;
}
//----------------------------------------------------------------------------
bool RegistryHelper::DeleteKey(const char* skey)
{
#ifdef _WIN32
if ( m_RegistryType == Registry::WIN32_REGISTRY)
{
int res = ( RegDeleteKey( this->HKey, skey ) == ERROR_SUCCESS );
return (res != 0);
}
#endif
if ( m_RegistryType == Registry::FILE_REGISTRY )
{
kwsys_stl::string key = this->CreateKey( skey );
if ( key.empty() )
{
return false;
}
this->EntriesMap.erase(key);
return true;
}
return false;
}
//----------------------------------------------------------------------------
bool RegistryHelper::DeleteValue(const char *skey)
{
#ifdef _WIN32
if ( m_RegistryType == Registry::WIN32_REGISTRY)
{
int res = ( RegDeleteValue( this->HKey, skey ) == ERROR_SUCCESS );
return (res != 0);
}
#endif
if ( m_RegistryType == Registry::FILE_REGISTRY )
{
kwsys_stl::string key = this->CreateKey( skey );
if ( key.empty() )
{
return false;
}
this->EntriesMap.erase(key);
return true;
}
return false;
}
//----------------------------------------------------------------------------
bool RegistryHelper::SetValue(const char *skey, const char *value)
{
#ifdef _WIN32
if ( m_RegistryType == Registry::WIN32_REGISTRY)
{
DWORD len = (DWORD)(value ? strlen(value) : 0);
int res = ( RegSetValueEx(this->HKey, skey, 0, REG_SZ,
(CONST BYTE *)(const char *)value,
len+1) == ERROR_SUCCESS );
return (res != 0);
}
#endif
if ( m_RegistryType == Registry::FILE_REGISTRY )
{
kwsys_stl::string key = this->CreateKey( skey );
if ( key.empty() )
{
return 0;
}
this->EntriesMap[key] = value;
return 1;
}
return false;
}
//----------------------------------------------------------------------------
kwsys_stl::string RegistryHelper::CreateKey( const char *key )
{
if ( !m_SubKeySpecified || m_SubKey.empty() || !key )
{
return "";
}
kwsys_ios::ostringstream ostr;
ostr << this->EncodeKey(this->m_SubKey.c_str()).c_str()
<< "\\" << this->EncodeKey(key).c_str();
return ostr.str();
}
//----------------------------------------------------------------------------
void RegistryHelper::SetSubKey(const char* sk)
{
if ( !sk )
{
m_SubKey = "";
m_SubKeySpecified = false;
}
else
{
m_SubKey = sk;
m_SubKeySpecified = true;
}
}
//----------------------------------------------------------------------------
char *RegistryHelper::Strip(char *str)
{
int cc;
size_t len;
char *nstr;
if ( !str )
{
return NULL;
}
len = strlen(str);
nstr = str;
for( cc=0; cc < static_cast<int>(len); cc++ )
{
if ( !isspace( *nstr ) )
{
break;
}
nstr ++;
}
for( cc= static_cast<int>(strlen(nstr))-1; cc>=0; cc-- )
{
if ( !isspace( nstr[cc] ) )
{
nstr[cc+1] = 0;
break;
}
}
return nstr;
}
//----------------------------------------------------------------------------
void RegistryHelper::SetGlobalScope(bool b)
{
m_GlobalScope = b;
}
//----------------------------------------------------------------------------
bool RegistryHelper::GetGlobalScope()
{
return m_GlobalScope;
}
//----------------------------------------------------------------------------
kwsys_stl::string RegistryHelper::EncodeKey(const char* str)
{
kwsys_ios::ostringstream ostr;
while ( *str )
{
switch ( *str )
{
case '%': case '=': case '\n': case '\r': case '\t':
char buffer[4];
sprintf(buffer, "%%%02X", *str);
ostr << buffer;
break;
default:
ostr << *str;
}
str ++;
}
return ostr.str();
}
//----------------------------------------------------------------------------
kwsys_stl::string RegistryHelper::EncodeValue(const char* str)
{
kwsys_ios::ostringstream ostr;
while ( *str )
{
switch ( *str )
{
case '%': case '=': case '\n': case '\r': case '\t':
char buffer[4];
sprintf(buffer, "%%%02X", *str);
ostr << buffer;
break;
default:
ostr << *str;
}
str ++;
}
return ostr.str();
}
//----------------------------------------------------------------------------
kwsys_stl::string RegistryHelper::DecodeValue(const char* str)
{
kwsys_ios::ostringstream ostr;
while ( *str )
{
unsigned int val;
switch ( *str )
{
case '%':
if ( *(str+1) && *(str+2) && sscanf(str+1, "%x", &val) == 1 )
{
ostr << static_cast<char>(val);
str += 2;
}
else
{
ostr << *str;
}
break;
default:
ostr << *str;
}
str ++;
}
return ostr.str();
}
} // namespace KWSYS_NAMESPACE

View File

@ -1,107 +0,0 @@
/*============================================================================
KWSys - Kitware System Library
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef @KWSYS_NAMESPACE@_Registry_hxx
#define @KWSYS_NAMESPACE@_Registry_hxx
#include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/stl/string>
namespace @KWSYS_NAMESPACE@
{
class RegistryHelper;
/** \class Registry
* \brief Portable registry class
*
* This class abstracts the storing of data that can be restored
* when the program executes again. On Win32 platform it is
* implemented using the registry and on unix as a file in
* the user's home directory.
*/
class @KWSYS_NAMESPACE@_EXPORT Registry
{
public:
enum RegistryType
{
#ifdef _WIN32
WIN32_REGISTRY,
#endif
FILE_REGISTRY
};
#ifdef _WIN32
Registry(RegistryType registryType = WIN32_REGISTRY);
#else
Registry(RegistryType registryType = FILE_REGISTRY);
#endif
virtual ~Registry();
//! Read a value from the registry.
bool ReadValue(const char *subkey, const char *key, const char **value);
//! Delete a key from the registry.
bool DeleteKey(const char *subkey, const char *key);
//! Delete a value from a given key.
bool DeleteValue(const char *subkey, const char *key);
//! Set value in a given key.
bool SetValue(const char *subkey, const char *key,
const char *value);
//! Open the registry at toplevel/subkey.
bool Open(const char *toplevel, const char *subkey,
int readonly);
//! Close the registry.
bool Close();
//! Read from local or global scope. On Windows this mean from local machine
// or local user. On unix this will read from $HOME/.Projectrc or
// /etc/Project
void GlobalScopeOn() { this->SetGlobalScope(1); }
void GlobalScopeOff() { this->SetGlobalScope(0); }
void SetGlobalScope(bool b);
bool GetGlobalScope();
// Set or get the toplevel registry key.
void SetTopLevel(const char* tl);
const char* GetTopLevel();
// Return true if registry opened
bool GetOpened() { return m_Opened; }
// Should the registry be locked?
bool GetLocked() { return m_Locked; }
enum {
READONLY,
READWRITE
};
// Return true if the character is space.
int IsSpace(char c);
private:
RegistryHelper* Helper;
bool m_Opened;
bool m_Locked;
}; // End Class: Registry
} // namespace @KWSYS_NAMESPACE@
#endif

View File

@ -307,7 +307,7 @@ public:
enum Manufacturer
{
AMD, Intel, NSC, UMC, Cyrix, NexGen, IDT, Rise, Transmeta, Sun, IBM,
Motorola, UnknownManufacturer
Motorola, HP, UnknownManufacturer
};
protected:
@ -346,7 +346,7 @@ protected:
static void Delay (unsigned int);
static void DelayOverhead (unsigned int);
void FindManufacturer();
void FindManufacturer(const kwsys_stl::string &family = "");
// For Mac
bool ParseSysCtl();
@ -1144,6 +1144,7 @@ void SystemInformationImplementation::RunCPUCheck()
{
// Retrieve the CPU details.
RetrieveCPUIdentity();
this->FindManufacturer();
RetrieveCPUFeatures();
}
@ -1415,6 +1416,8 @@ const char * SystemInformationImplementation::GetVendorID()
return "IBM";
case Motorola:
return "Motorola";
case HP:
return "Hewlett-Packard";
default:
return "Unknown Manufacturer";
}
@ -1670,7 +1673,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
#endif
; <<CPUID>>
; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
; edx: CPU feature flags
mov eax,1
CPUID_INSTRUCTION
@ -1755,7 +1758,7 @@ bool SystemInformationImplementation::RetrieveCPUFeatures()
/** Find the manufacturer given the vendor id */
void SystemInformationImplementation::FindManufacturer()
void SystemInformationImplementation::FindManufacturer(const kwsys_stl::string& family)
{
if (this->ChipID.Vendor == "GenuineIntel") this->ChipManufacturer = Intel; // Intel Corp.
else if (this->ChipID.Vendor == "UMC UMC UMC ") this->ChipManufacturer = UMC; // United Microelectronics Corp.
@ -1771,6 +1774,7 @@ void SystemInformationImplementation::FindManufacturer()
else if (this->ChipID.Vendor == "Sun") this->ChipManufacturer = Sun; // Sun Microelectronics
else if (this->ChipID.Vendor == "IBM") this->ChipManufacturer = IBM; // IBM Microelectronics
else if (this->ChipID.Vendor == "Motorola") this->ChipManufacturer = Motorola; // Motorola Microelectronics
else if (family.substr(0, 7) == "PA-RISC") this->ChipManufacturer = HP; // Hewlett-Packard
else this->ChipManufacturer = UnknownManufacturer; // Unknown manufacturer
}
@ -1809,7 +1813,7 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
; <<CPUID>>
; eax = 1 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
; edx: CPU feature flags
mov eax,1
CPUID_INSTRUCTION
@ -1836,8 +1840,6 @@ bool SystemInformationImplementation::RetrieveCPUIdentity()
vbuf[12] = '\0';
this->ChipID.Vendor = vbuf;
this->FindManufacturer();
// Retrieve the family of CPU present.
this->ChipID.ExtendedFamily = ((localCPUSignature & 0x0FF00000) >> 20); // Bits 27..20 Used
this->ChipID.ExtendedModel = ((localCPUSignature & 0x000F0000) >> 16); // Bits 19..16 Used
@ -2436,7 +2438,7 @@ bool SystemInformationImplementation::RetrieveExtendedCPUFeatures()
#endif
; <<CPUID>>
; eax = 0x80000001 --> eax: CPU ID - bits 31..16 - unused, bits 15..12 - type, bits 11..8 - family, bits 7..4 - model, bits 3..0 - mask revision
; ebx: 31..24 - default APIC ID, 23..16 - logical processsor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
; ebx: 31..24 - default APIC ID, 23..16 - logical processor ID, 15..8 - CFLUSH chunk size , 7..0 - brand ID
; edx: CPU feature flags
mov eax,0x80000001
CPUID_INSTRUCTION
@ -3002,6 +3004,16 @@ kwsys_stl::string SystemInformationImplementation::ExtractValueFromCpuInfoFile(k
size_t pos2 = buffer.find("\n",pos);
if(pos!=buffer.npos && pos2!=buffer.npos)
{
// It may happen that the beginning matches, but this is still not the requested key.
// An example is looking for "cpu" when "cpu family" comes first. So we check that
// we have only spaces from here to pos, otherwise we search again.
for(size_t i=this->CurrentPositionInFile+strlen(word); i < pos; ++i)
{
if(buffer[i] != ' ' && buffer[i] != '\t')
{
return this->ExtractValueFromCpuInfoFile(buffer, word, pos2);
}
}
return buffer.substr(pos+2,pos2-pos-2);
}
}
@ -3073,7 +3085,7 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
this->NumberOfLogicalCPU = atoi(cpucount.c_str());
#endif
// gotta have one, and if this is 0 then we get a / by 0n
// beter to have a bad answer than a crash
// better to have a bad answer than a crash
if(this->NumberOfPhysicalCPU <= 0)
{
this->NumberOfPhysicalCPU = 1;
@ -3082,32 +3094,83 @@ int SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical=
this->NumberOfLogicalCPU/this->NumberOfPhysicalCPU;
// CPU speed (checking only the first proc
// CPU speed (checking only the first processor)
kwsys_stl::string CPUSpeed = this->ExtractValueFromCpuInfoFile(buffer,"cpu MHz");
this->CPUSpeedInMHz = static_cast<float>(atof(CPUSpeed.c_str()));
// Chip family
this->ChipID.Family = atoi(this->ExtractValueFromCpuInfoFile(buffer,"cpu family").c_str());
kwsys_stl::string familyStr =
this->ExtractValueFromCpuInfoFile(buffer,"cpu family");
if(familyStr.empty())
{
familyStr = this->ExtractValueFromCpuInfoFile(buffer,"CPU architecture");
}
this->ChipID.Family = atoi(familyStr.c_str());
// Chip Vendor
this->ChipID.Vendor = this->ExtractValueFromCpuInfoFile(buffer,"vendor_id");
this->FindManufacturer();
this->FindManufacturer(familyStr);
// second try for setting family
if (this->ChipID.Family == 0 && this->ChipManufacturer == HP)
{
if (familyStr == "PA-RISC 1.1a")
this->ChipID.Family = 0x11a;
else if (familyStr == "PA-RISC 2.0")
this->ChipID.Family = 0x200;
// If you really get CMake to work on a machine not belonging to
// any of those families I owe you a dinner if you get it to
// contribute nightly builds regularly.
}
// Chip Model
this->ChipID.Model = atoi(this->ExtractValueFromCpuInfoFile(buffer,"model").c_str());
this->RetrieveClassicalCPUIdentity();
if(!this->RetrieveClassicalCPUIdentity())
{
// Some platforms (e.g. PA-RISC) tell us their CPU name here.
// Note: x86 does not.
kwsys_stl::string cpuname = this->ExtractValueFromCpuInfoFile(buffer,"cpu");
if(!cpuname.empty())
{
this->ChipID.ProcessorName = cpuname;
}
}
// Chip revision
kwsys_stl::string cpurev = this->ExtractValueFromCpuInfoFile(buffer,"stepping");
if(cpurev.empty())
{
cpurev = this->ExtractValueFromCpuInfoFile(buffer,"CPU revision");
}
this->ChipID.Revision = atoi(cpurev.c_str());
// Chip Model Name
this->ChipID.ModelName = this->ExtractValueFromCpuInfoFile(buffer,"model name").c_str();
// L1 Cache size
kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,"cache size");
pos = cacheSize.find(" KB");
if(pos!=cacheSize.npos)
// Different architectures may show different names for the caches.
// Sum up everything we find.
kwsys_stl::vector<const char*> cachename;
cachename.clear();
cachename.push_back("cache size"); // e.g. x86
cachename.push_back("I-cache"); // e.g. PA-RISC
cachename.push_back("D-cache"); // e.g. PA-RISC
this->Features.L1CacheSize = 0;
for (size_t index = 0; index < cachename.size(); index ++)
{
cacheSize = cacheSize.substr(0,pos);
kwsys_stl::string cacheSize = this->ExtractValueFromCpuInfoFile(buffer,cachename[index]);
if (!cacheSize.empty())
{
pos = cacheSize.find(" KB");
if(pos!=cacheSize.npos)
{
cacheSize = cacheSize.substr(0,pos);
}
this->Features.L1CacheSize += atoi(cacheSize.c_str());
}
}
this->Features.L1CacheSize = atoi(cacheSize.c_str());
return 1;
}

View File

@ -2754,9 +2754,15 @@ kwsys_stl::string SystemTools::GetRealPath(const char* path)
bool SystemTools::FileIsDirectory(const char* name)
{
size_t length = strlen(name);
if (length == 0)
{
return false;
}
// Remove any trailing slash from the name.
char buffer[KWSYS_SYSTEMTOOLS_MAXPATH];
size_t last = strlen(name)-1;
size_t last = length-1;
if(last > 0 && (name[last] == '/' || name[last] == '\\')
&& strcmp(name, "/") !=0)
{

View File

@ -82,6 +82,14 @@ int test3(int argc, const char* argv[])
int test4(int argc, const char* argv[])
{
/* Prepare a pointer to an invalid address. Don't use null, because
dereferencing null is undefined behaviour and compilers are free to
do whatever they want. ex: Clang will warn at compile time, or even
optimize away the write. We hope to 'outsmart' them by using
'volatile' and a slightly larger address, based on a runtime value. */
volatile int* invalidAddress = 0;
invalidAddress += argc?1:2;
#if defined(_WIN32)
/* Avoid error diagnostic popups since we are crashing on purpose. */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
@ -94,11 +102,8 @@ int test4(int argc, const char* argv[])
fprintf(stderr, "Output before crash on stderr from crash test.\n");
fflush(stdout);
fflush(stderr);
#if defined(__clang__)
*(int*)1 = 0; /* Clang warns about 0-ptr; undefined behavior. */
#else
*(int*)0 = 0;
#endif
/* Provoke deliberate crash by writing to the invalid address. */
*invalidAddress = 0;
fprintf(stdout, "Output after crash on stdout from crash test.\n");
fprintf(stderr, "Output after crash on stderr from crash test.\n");
return 0;

View File

@ -1,109 +0,0 @@
/*============================================================================
KWSys - Kitware System Library
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Registry.hxx)
#include KWSYS_HEADER(ios/iostream)
#include <string.h>
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
# include "Registry.hxx.in"
# include "kwsys_ios_iostream.h.in"
#endif
#define IFT(x,res) if ( !x ) \
{ \
res = 1; \
kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \
}
#define IFNT(x,res) if ( x ) \
{ \
res = 1; \
kwsys_ios::cout << "Error in: " << #x << kwsys_ios::endl; \
}
#define CHE(x,y,res) if ( x && strcmp(x,y) ) \
{ \
res = 1; \
kwsys_ios::cout << "Error, " << x << " != " << y << kwsys_ios::endl; \
}
int testRegistry(int, char*[])
{
int res = 0;
kwsys::Registry reg;
reg.SetTopLevel("TestRegistry");
IFT(reg.SetValue("TestSubkey", "TestKey1", "Test Value 1"), res);
IFT(reg.SetValue("TestSubkey1", "TestKey2", "Test Value 2"), res);
IFT(reg.SetValue("TestSubkey", "TestKey3", "Test Value 3"), res);
IFT(reg.SetValue("TestSubkey2", "TestKey4", "Test Value 4"), res);
const char *buffer;
IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res);
CHE(buffer, "Test Value 1", res);
IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res);
CHE(buffer, "Test Value 2", res);
IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res);
CHE(buffer, "Test Value 3", res);
IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res);
CHE(buffer, "Test Value 4", res);
IFT(reg.SetValue("TestSubkey", "TestKey1", "New Test Value 1"), res);
IFT(reg.SetValue("TestSubkey1", "TestKey2", "New Test Value 2"), res);
IFT(reg.SetValue("TestSubkey", "TestKey3", "New Test Value 3"), res);
IFT(reg.SetValue("TestSubkey2", "TestKey4", "New Test Value 4"), res);
IFT(reg.ReadValue("TestSubkey", "TestKey1", &buffer), res);
CHE(buffer, "New Test Value 1", res);
IFT(reg.ReadValue("TestSubkey1", "TestKey2", &buffer), res);
CHE(buffer, "New Test Value 2", res);
IFT(reg.ReadValue("TestSubkey", "TestKey3", &buffer), res);
CHE(buffer, "New Test Value 3", res);
IFT(reg.ReadValue("TestSubkey2", "TestKey4", &buffer), res);
CHE(buffer, "New Test Value 4", res);
IFT( reg.DeleteValue("TestSubkey", "TestKey1"), res);
IFNT(reg.ReadValue( "TestSubkey", "TestKey1", &buffer), res);
IFT( reg.DeleteValue("TestSubkey1", "TestKey2"), res);
IFNT(reg.ReadValue( "TestSubkey1", "TestKey2", &buffer), res);
IFT( reg.DeleteValue("TestSubkey", "TestKey3"), res);
IFNT(reg.ReadValue( "TestSubkey", "TestKey3", &buffer), res);
IFT( reg.DeleteValue("TestSubkey2", "TestKey4"), res);
IFNT(reg.ReadValue( "TestSubkey2", "TestKey5", &buffer), res);
const char* longStringWithNewLines = "Value with embedded CR and LF characters CR='\015' LF='\012' CRLF='\015\012'";
IFT(reg.SetValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", longStringWithNewLines), res);
IFT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res);
CHE(buffer, longStringWithNewLines, res);
IFT(reg.DeleteValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1"), res);
IFNT(reg.ReadValue("TestSubkeyWithVeryLongInFactSoLongItsHardToImagineAnybodyWouldReallyDoItLongName", "TestKey1", &buffer), res);
IFT(reg.SetValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", "Some value"), res);
IFT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res);
CHE(buffer, "Some value", res);
IFT(reg.DeleteValue("TestSubkeyWith = EqualSignChar", "TestKey = 1"), res);
IFNT(reg.ReadValue("TestSubkeyWith = EqualSignChar", "TestKey = 1", &buffer), res);
if ( res )
{
kwsys_ios::cout << "Test failed" << kwsys_ios::endl;
}
else
{
kwsys_ios::cout << "Test passed" << kwsys_ios::endl;
}
return res;
}

View File

@ -66,6 +66,7 @@ int testSystemInformation(int, char*[])
printMethod(info, GetFamilyID);
printMethod(info, GetModelID);
printMethod(info, GetExtendedProcessorName);
printMethod(info, GetSteppingCode);
printMethod(info, GetProcessorSerialNumber);
printMethod2(info, GetProcessorCacheSize, "KB");
printMethod(info, GetLogicalProcessorsPerPhysical);