[ros-diffs] [hyperion] 41235: added tools/msc_helper added tools/msc_helper/msc_helper.cpp added tools/msc_helper/msc_helper.rbuild Build tool to invoke Microsoft tools, overriding the %PATH% variable and optionally filtering out the name of the file being compiled Will be used by the Visual C++ support for rbuild

hyperion at svn.reactos.org hyperion at svn.reactos.org
Mon Jun 1 17:17:42 CEST 2009


Author: hyperion
Date: Mon Jun  1 19:17:41 2009
New Revision: 41235

URL: http://svn.reactos.org/svn/reactos?rev=41235&view=rev
Log:
added      tools/msc_helper
added      tools/msc_helper/msc_helper.cpp
added      tools/msc_helper/msc_helper.rbuild
   Build tool to invoke Microsoft tools, overriding the %PATH% variable and optionally filtering out the name of the file being compiled
   Will be used by the Visual C++ support for rbuild

Added:
    trunk/reactos/tools/msc_helper/   (with props)
    trunk/reactos/tools/msc_helper/msc_helper.cpp   (with props)
    trunk/reactos/tools/msc_helper/msc_helper.rbuild   (with props)

Propchange: trunk/reactos/tools/msc_helper/
------------------------------------------------------------------------------
--- bugtraq:logregex (added)
+++ bugtraq:logregex Mon Jun  1 19:17:41 2009
@@ -1,0 +1,2 @@
+([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))?
+(\d+)

Propchange: trunk/reactos/tools/msc_helper/
------------------------------------------------------------------------------
    bugtraq:message = See issue #%BUGID% for more details.

Propchange: trunk/reactos/tools/msc_helper/
------------------------------------------------------------------------------
    bugtraq:url = http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID%

Propchange: trunk/reactos/tools/msc_helper/
------------------------------------------------------------------------------
    tsvn:logminsize = 10

Added: trunk/reactos/tools/msc_helper/msc_helper.cpp
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/msc_helper/msc_helper.cpp?rev=41235&view=auto
==============================================================================
--- trunk/reactos/tools/msc_helper/msc_helper.cpp (added)
+++ trunk/reactos/tools/msc_helper/msc_helper.cpp [iso-8859-1] Mon Jun  1 19:17:41 2009
@@ -1,0 +1,475 @@
+/*
+	Copyright (c) 2009 KJK::Hyperion
+
+	Permission is hereby granted, free of charge, to any person obtaining a
+	copy of this software and associated documentation files (the "Software"),
+	to deal in the Software without restriction, including without limitation
+	the rights to use, copy, modify, merge, publish, distribute, sublicense,
+	and/or sell copies of the Software, and to permit persons to whom the
+	Software is furnished to do so, subject to the following conditions:
+
+	The above copyright notice and this permission notice shall be included in
+	all copies or substantial portions of the Software.
+
+	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+	DEALINGS IN THE SOFTWARE.
+*/
+
+#include <functional>
+#include <iterator>
+
+#include <tchar.h>
+#include <limits.h>
+
+#include <stdio.h>
+
+#define WIN32_LEAN_AND_MEAN
+#define STRICT
+#include <windows.h>
+
+#undef RtlMoveMemory
+extern "C" DECLSPEC_IMPORT void NTAPI RtlMoveMemory(void UNALIGNED *, const void UNALIGNED *, SIZE_T);
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(X_) (sizeof(X_) / sizeof((X_)[0]))
+#endif
+
+#include <kjk/argv_parser.h>
+#include <kjk/stringz_iterator.h>
+
+using namespace kjk;
+
+namespace
+{
+	bool WriteAll(HANDLE hFile, const void * p, size_t cb)
+	{
+		const char * pb = static_cast<const char *>(p);
+		bool ret = cb == 0;
+
+		while(cb)
+		{
+			DWORD cbToWrite;
+
+			if(cb > MAXLONG)
+				cbToWrite = MAXLONG;
+			else
+				cbToWrite = static_cast<DWORD>(cb);
+
+			DWORD cbWritten;
+			ret = !!WriteFile(hFile, pb, cbToWrite, &cbWritten, NULL);
+
+			if(!ret)
+				break;
+
+			cb -= cbWritten;
+			pb += cbWritten;
+		}
+
+		return ret;
+	}
+
+	DECLSPEC_NORETURN
+	void Exit(DWORD dwExitCode)
+	{
+		for(;;) TerminateProcess(GetCurrentProcess(), dwExitCode);
+	}
+
+	DECLSPEC_NORETURN
+	void Die(DWORD dwExitCode, const char * pszFunction, DWORD dwErrCode)
+	{
+		DWORD_PTR args[] = { (DWORD_PTR)pszFunction, dwErrCode };
+
+		char * pszMessage;
+		DWORD cchMessage = FormatMessageA
+		(
+			FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING,
+			"msc_helper: %1!s!() failed: error %2!lu!\n",
+			0,
+			0,
+			(LPSTR)&pszMessage,
+			0,
+			(va_list *)args
+		);
+
+		if(cchMessage)
+		{
+			(void)WriteAll(GetStdHandle(STD_ERROR_HANDLE), pszMessage, cchMessage);
+			LocalFree((HLOCAL)pszMessage);
+		}
+
+		Exit(dwExitCode);
+	}
+
+	DECLSPEC_NORETURN
+	void Die(const char * pszFunction)
+	{
+		Die(1, pszFunction, GetLastError());
+	}
+
+	DECLSPEC_NORETURN
+	void Die(const char * pszFunction, DWORD dwExitCode)
+	{
+		Die(1, pszFunction, dwExitCode);
+	}
+
+	template<size_t N>
+	DECLSPEC_NORETURN
+	void DieMessage(const char (& msg)[N])
+	{
+		(void)WriteAll(GetStdHandle(STD_ERROR_HANDLE), msg, (N) - 1);
+		Exit(1);
+	}
+
+	DECLSPEC_NORETURN
+	void OutOfMemory()
+	{
+		DieMessage("msc_helper: out of memory\n");
+	}
+
+	class store_argument
+	{
+	private:
+		char * m_arg;
+		size_t m_argLen;
+
+	public:
+		// Pretend we are an STL container
+		typedef TCHAR value_type;
+		typedef TCHAR * pointer;
+		typedef TCHAR& reference;
+		typedef const TCHAR * const_pointer;
+		typedef const TCHAR& const_reference;
+
+		void push_back(TCHAR x)
+		{
+#ifdef UNICODE
+			if(x > CHAR_MAX)
+				DieMessage("msc_helper: invalid character in command line\n");
+#endif
+			m_arg = static_cast<char *>(HeapReAlloc(GetProcessHeap(), 0, m_arg, m_argLen + 1));
+
+			if(m_arg == NULL)
+				OutOfMemory();
+
+			m_arg[m_argLen] = static_cast<char>(x);
+			++ m_argLen;
+		}
+
+	public:
+		store_argument(): m_arg(static_cast<char *>(HeapAlloc(GetProcessHeap(), 0, 1))), m_argLen(0)
+		{
+			if(m_arg == NULL)
+				OutOfMemory();
+		}
+
+		const char * get_arg() const { return m_arg; }
+		size_t get_arg_len() const { return m_argLen; }
+	};
+
+	class filter_output
+	{
+	private:
+		const char * m_pFilterLine;
+		size_t m_cbFilterLine;
+		HANDLE m_hOutput;
+		bool& m_fDone;
+
+		static DWORD s_cbDummy;
+		static DWORD s_pipeId;
+
+		char m_buffer[1024];
+		LPTSTR m_pszPipeName;
+		HANDLE m_hReadFrom;
+		OVERLAPPED m_asyncRead;
+		char * m_pLineBuffer;
+		size_t m_cbLineBuffer;
+
+		bool begin_read()
+		{
+			bool bRet = !!ReadFile(m_hReadFrom, m_buffer, sizeof(m_buffer), &s_cbDummy, &m_asyncRead);
+
+			if(!bRet)
+			{
+				bRet = GetLastError() != ERROR_BROKEN_PIPE;
+
+				if(bRet)
+				{
+					bRet = GetLastError() == ERROR_IO_PENDING;
+
+					if(!bRet)
+						Die("ReadFile");
+				}
+			}
+
+			return bRet;
+		}
+
+		void push_input(size_t cbBufferValid)
+		{
+			if(m_fDone)
+			{
+				if(!WriteAll(m_hOutput, m_buffer, cbBufferValid))
+					Die("WriteFile");
+
+				return;
+			}
+
+			// Add the data read from output to the line buffer
+			size_t cbLineBufferNew = m_cbLineBuffer + cbBufferValid;
+
+			if(m_pLineBuffer)
+				m_pLineBuffer = static_cast<char *>(HeapReAlloc(GetProcessHeap(), 0, m_pLineBuffer, cbLineBufferNew));
+			else
+				m_pLineBuffer = static_cast<char *>(HeapAlloc(GetProcessHeap(), 0, cbLineBufferNew));
+
+			if(m_pLineBuffer == NULL)
+				OutOfMemory();
+
+			RtlMoveMemory(m_pLineBuffer + m_cbLineBuffer, m_buffer, cbBufferValid);
+
+			// Parse all complete lines in the line buffer
+			size_t cbLineStart = 0;
+
+			for(size_t i = m_cbLineBuffer; i < cbLineBufferNew; ++ i)
+			{
+				// We have a complete line
+				if(m_pLineBuffer[i] == '\n' || m_pLineBuffer[i] == '\r')
+				{
+					size_t cbLine = i - cbLineStart;
+
+					++ i;
+
+					if(i < cbLineBufferNew && m_pLineBuffer[i - 1] == '\r' && m_pLineBuffer[i] == '\n')
+						++ i;
+
+					size_t cbLineFull = i - cbLineStart;
+
+					bool fMatched = cbLine == m_cbFilterLine && memcmp(m_pLineBuffer + cbLineStart, m_pFilterLine, m_cbFilterLine) == 0;
+
+					// The line doesn't match: dump it
+					if(!fMatched)
+					{
+						if(!WriteAll(m_hOutput, m_pLineBuffer + cbLineStart, cbLineFull))
+							Die("WriteFile");
+					}
+					// The line matches: we are done
+					else
+						m_fDone = fMatched;
+
+					cbLineStart = i;
+				}
+
+				// Filtering is complete: from now on, just dump everything
+				if(m_fDone)
+				{
+					if(!WriteAll(m_hOutput, m_buffer + i, cbLineBufferNew - i))
+						Die("WriteFile");
+
+					HeapFree(GetProcessHeap(), 0, m_pLineBuffer);
+					return;
+				}
+			}
+
+			// Re-buffer what's left
+			m_cbLineBuffer = cbLineBufferNew - cbLineStart;
+			RtlMoveMemory(m_pLineBuffer, m_pLineBuffer + cbLineStart, m_cbLineBuffer);
+		}
+
+	public:
+		filter_output(const char * pFilterLine, size_t cbFilterLine, HANDLE hOutput, bool * pfDone):
+			m_pFilterLine(pFilterLine),
+			m_cbFilterLine(cbFilterLine),
+			m_hOutput(hOutput),
+			m_fDone(*pfDone),
+			m_asyncRead(),
+			m_pLineBuffer(0),
+			m_cbLineBuffer(0)
+		{
+			for(;;)
+			{
+				DWORD_PTR args[] = { GetCurrentProcessId(), s_pipeId };
+
+				DWORD cchPipeName = FormatMessage
+				(
+					FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING,
+					TEXT("\\\\.\\pipe\\msc_helper-%1!08X!-%2!08X!"),
+					0,
+					0,
+					(LPTSTR)&m_pszPipeName,
+					0,
+					(va_list *)args
+				);
+
+				if(cchPipeName == 0)
+					Die("FormatMessage");
+
+				m_hReadFrom = CreateNamedPipe(m_pszPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 0, 0, 0, NULL);
+
+				++ s_pipeId;
+
+				if(m_hReadFrom != INVALID_HANDLE_VALUE)
+					break;
+
+				if(GetLastError() != ERROR_PIPE_BUSY)
+					Die("CreateNamedPipe");
+			}
+
+			// Just in case
+			bool fEmptyFilter = m_cbFilterLine == 0;
+
+			if(fEmptyFilter)
+				m_fDone = fEmptyFilter;
+		}
+
+		HANDLE open_write_end(LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
+		{
+			HANDLE hWritePipe = CreateFile(m_pszPipeName, GENERIC_WRITE, FILE_SHARE_READ, lpSecurityAttributes, OPEN_EXISTING, dwFlagsAndAttributes, hTemplateFile);
+
+			if(hWritePipe == INVALID_HANDLE_VALUE)
+				Die("CreateFile");
+
+			(void)begin_read();
+			return hWritePipe;
+		}
+
+		HANDLE get_read_completion() const
+		{
+			return m_hReadFrom;
+		}
+
+		bool operator()()
+		{
+			DWORD cbBufferValid;
+
+			if(!GetOverlappedResult(m_hReadFrom, &m_asyncRead, &cbBufferValid, TRUE))
+			{
+				bool b = GetLastError() != ERROR_BROKEN_PIPE;
+
+				if(!b)
+					return b;
+
+				Die("ReadFile");
+			}
+
+			push_input(cbBufferValid);
+			return begin_read();
+		}
+	};
+
+	DWORD filter_output::s_cbDummy = 0;
+	DWORD filter_output::s_pipeId = 0;
+}
+
+int main()
+{
+	DWORD dwExitCode = 1;
+
+	// Parse the command line
+	LPCTSTR pszCommandLine = GetCommandLine();
+
+	// Skip argv[0]
+	pszCommandLine = skip_argument(stringz_begin(pszCommandLine), stringz_end(pszCommandLine)).base();
+
+	// Get argv[1]: the line that should be filtered out of the output
+	// argv[2..N] will become argv[0..N-2] of the compiler
+	store_argument filterLine;
+	pszCommandLine = copy_argument(stringz_begin(pszCommandLine), stringz_end(pszCommandLine), std::back_inserter(filterLine)).base();
+
+	// Initialize the output filters
+	bool fDone = false;
+	filter_output filterStdOutput(filterLine.get_arg(), filterLine.get_arg_len(), GetStdHandle(STD_OUTPUT_HANDLE), &fDone);
+	filter_output filterStdError(filterLine.get_arg(), filterLine.get_arg_len(), GetStdHandle(STD_ERROR_HANDLE), &fDone);
+
+	// A handle that will never be signaled
+	HANDLE hNever;
+
+	if(!DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &hNever, SYNCHRONIZE, FALSE, 0))
+		Die("DuplicateHandle");
+
+	// Fix the environment
+	static TCHAR szPath[32768];
+	DWORD cchPath = GetEnvironmentVariable(TEXT("MSC_HELPER_PATH"), szPath, ARRAYSIZE(szPath));
+
+	if(cchPath > ARRAYSIZE(szPath))
+		DieMessage("msc_helper: %MSC_HELPER_PATH% variable too big\n");
+
+	if(cchPath > 0 && !SetEnvironmentVariable(TEXT("PATH"), szPath))
+		Die("SetEnvironmentVariable");
+
+	// Run the sub-process
+	STARTUPINFO si;
+	GetStartupInfo(&si);
+
+	si.dwFlags |= STARTF_USESTDHANDLES;
+
+	si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+
+	SECURITY_ATTRIBUTES pipeAttributes = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+	si.hStdOutput = filterStdOutput.open_write_end(&pipeAttributes, 0, NULL);
+	si.hStdError = filterStdError.open_write_end(&pipeAttributes, 0, NULL);
+
+	PROCESS_INFORMATION pi = {};
+
+	if(!CreateProcess(NULL, const_cast<LPTSTR>(pszCommandLine), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
+		Die("CreateProcess");
+
+	CloseHandle(pi.hThread);
+	CloseHandle(si.hStdOutput);
+	CloseHandle(si.hStdError);
+
+	(void)SetProcessWorkingSetSize(GetCurrentProcess(), (SIZE_T)-1, (SIZE_T)-1);
+
+	HANDLE waitHandles[3] =
+	{
+		pi.hProcess,
+		filterStdOutput.get_read_completion(),
+		filterStdError.get_read_completion()
+	};
+
+	unsigned done = 0;
+
+	char * pLineBuffer = NULL;
+	size_t cbLineBuffer = 0;
+
+	while(done < ARRAYSIZE(waitHandles))
+	{
+		switch(WaitForMultipleObjects(ARRAYSIZE(waitHandles), waitHandles, FALSE, INFINITE))
+		{
+		case WAIT_OBJECT_0:
+			GetExitCodeProcess(pi.hProcess, &dwExitCode);
+			waitHandles[WAIT_OBJECT_0] = hNever;
+			++ done;
+			break;
+
+		case WAIT_OBJECT_0 + 1:
+			if(!filterStdOutput())
+			{
+				waitHandles[WAIT_OBJECT_0 + 1] = hNever;
+				++ done;
+			}
+
+			break;
+
+		case WAIT_OBJECT_0 + 2:
+			if(!filterStdError())
+			{
+				waitHandles[WAIT_OBJECT_0 + 2] = hNever;
+				++ done;
+			}
+
+			break;
+
+		default:
+			Die("WaitForMultipleObjects");
+		}
+	}
+
+	Exit(dwExitCode);
+}
+
+// EOF

Propchange: trunk/reactos/tools/msc_helper/msc_helper.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/tools/msc_helper/msc_helper.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/tools/msc_helper/msc_helper.rbuild?rev=41235&view=auto
==============================================================================
--- trunk/reactos/tools/msc_helper/msc_helper.rbuild (added)
+++ trunk/reactos/tools/msc_helper/msc_helper.rbuild [iso-8859-1] Mon Jun  1 19:17:41 2009
@@ -1,0 +1,6 @@
+<?xml version="1.0"?>
+<module name="msc_helper" type="buildtool">
+	<define name="UNICODE" />
+	<define name="_UNICODE" />
+	<file>msc_helper.cpp</file>
+</module>

Propchange: trunk/reactos/tools/msc_helper/msc_helper.rbuild
------------------------------------------------------------------------------
    svn:eol-style = native



More information about the Ros-diffs mailing list