Daniele Bartolini 11 anos atrás
pai
commit
2c74bc3ef0
1 arquivos alterados com 270 adições e 274 exclusões
  1. 270 274
      engine/core/os.h

+ 270 - 274
engine/core/os.h

@@ -31,10 +31,9 @@ OTHER DEALINGS IN THE SOFTWARE.
 #include "vector.h"
 #include "vector.h"
 #include "dynamic_string.h"
 #include "dynamic_string.h"
 #include "string_utils.h"
 #include "string_utils.h"
-#include "temp_allocator.h"
+#include "assert.h"
 
 
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	#include "assert.h"
 	#include <cstdarg>
 	#include <cstdarg>
 	#include <cstdio>
 	#include <cstdio>
 	#include <cstdlib>
 	#include <cstdlib>
@@ -51,7 +50,6 @@ OTHER DEALINGS IN THE SOFTWARE.
 	#include <win_headers.h>
 	#include <win_headers.h>
 	#include <io.h>
 	#include <io.h>
 #endif
 #endif
-
 #if CROWN_PLATFORM_ANDROID
 #if CROWN_PLATFORM_ANDROID
 	#include <android/log.h>
 	#include <android/log.h>
 #endif
 #endif
@@ -73,395 +71,393 @@ namespace crown
 
 
 namespace os
 namespace os
 {
 {
-
-//-----------------------------------------------------------------------------
-inline void log_debug(const char* string, va_list arg)
-{
+	//-----------------------------------------------------------------------------
+	inline void log_debug(const char* string, va_list arg)
+	{
 #if CROWN_PLATFORM_ANDROID
 #if CROWN_PLATFORM_ANDROID
-	__android_log_vprint(ANDROID_LOG_DEBUG, "crown", string, arg);
+		__android_log_vprint(ANDROID_LOG_DEBUG, "crown", string, arg);
 #else
 #else
-	vprintf(string, arg);
-	printf("\n");
+		vprintf(string, arg);
+		printf("\n");
 #endif
 #endif
-}
+	}
 
 
-//-----------------------------------------------------------------------------
-inline void log_error(const char* string, va_list arg)
-{
+	//-----------------------------------------------------------------------------
+	inline void log_error(const char* string, va_list arg)
+	{
 #if CROWN_PLATFORM_ANDROID
 #if CROWN_PLATFORM_ANDROID
-	__android_log_vprint(ANDROID_LOG_ERROR, "crown", string, arg);
+		__android_log_vprint(ANDROID_LOG_ERROR, "crown", string, arg);
 #else
 #else
-	vprintf(string, arg);
-	printf("\n");
+		vprintf(string, arg);
+		printf("\n");
 #endif
 #endif
-}
+	}
 
 
-//-----------------------------------------------------------------------------
-inline void log_warning(const char* string, va_list arg)
-{
+	//-----------------------------------------------------------------------------
+	inline void log_warning(const char* string, va_list arg)
+	{
 #if CROWN_PLATFORM_ANDROID
 #if CROWN_PLATFORM_ANDROID
-	__android_log_vprint(ANDROID_LOG_WARN, "crown", string, arg);
+		__android_log_vprint(ANDROID_LOG_WARN, "crown", string, arg);
 #else
 #else
-	vprintf(string, arg);
-	printf("\n");
+		vprintf(string, arg);
+		printf("\n");
 #endif
 #endif
-}
+	}
 
 
-//-----------------------------------------------------------------------------
-inline void log_info(const char* string, va_list arg)
-{
+	//-----------------------------------------------------------------------------
+	inline void log_info(const char* string, va_list arg)
+	{
 #if CROWN_PLATFORM_ANDROID
 #if CROWN_PLATFORM_ANDROID
-	__android_log_vprint(ANDROID_LOG_INFO, "crown", string, arg);
+		__android_log_vprint(ANDROID_LOG_INFO, "crown", string, arg);
 #else
 #else
-	vprintf(string, arg);
-	printf("\n");
+		vprintf(string, arg);
+		printf("\n");
 #endif
 #endif
-}
+	}
 
 
-//-----------------------------------------------------------------------------
-inline bool is_root_path(const char* path)
-{
+	//-----------------------------------------------------------------------------
+	inline bool is_root_path(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return (path != NULL && string::strlen(path) == 1 && path[0] == PATH_SEPARATOR);
+		return (path != NULL && string::strlen(path) == 1 && path[0] == PATH_SEPARATOR);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	return (path != NULL && string::strlen(path) == 3 && string::is_alpha(path[0]) &&
-		path[1] == ':' && path[2] == PATH_SEPARATOR);
+		return (path != NULL && string::strlen(path) == 3 && string::is_alpha(path[0]) &&
+			path[1] == ':' && path[2] == PATH_SEPARATOR);
 #endif
 #endif
-}
+	}
 
 
-//-----------------------------------------------------------------------------
-inline bool is_absolute_path(const char* path)
-{
+	//-----------------------------------------------------------------------------
+	inline bool is_absolute_path(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return (path != NULL && string::strlen(path) >= 1 && path[0] == PATH_SEPARATOR);
+		return (path != NULL && string::strlen(path) >= 1 && path[0] == PATH_SEPARATOR);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	return (path != NULL && string::strlen(path) >= 3 && string::is_alpha(path[0]) &&
-		path[1] == ':' && path[2] == PATH_SEPARATOR);
+		return (path != NULL && string::strlen(path) >= 3 && string::is_alpha(path[0]) &&
+			path[1] == ':' && path[2] == PATH_SEPARATOR);
 #endif
 #endif
-}
+	}
 
 
-inline bool exists(const char* path)
-{
+	inline bool exists(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return access(path, F_OK) != -1;
+		return access(path, F_OK) != -1;
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	return _access(path, 0) != -1;
+		return _access(path, 0) != -1;
 #endif
 #endif
-}
+	}
 
 
-/// Returns whether the path is a directory.
-inline bool is_directory(const char* path)
-{
+	/// Returns whether the path is a directory.
+	inline bool is_directory(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	struct stat info;
-	memset(&info, 0, sizeof(struct stat));
-	int err = lstat(path, &info);
-	CE_ASSERT(err == 0, "lstat: errno = %d", errno);
-	CE_UNUSED(err);
-	return ((S_ISDIR(info.st_mode) == 1) && (S_ISLNK(info.st_mode) == 0));
+		struct stat info;
+		memset(&info, 0, sizeof(struct stat));
+		int err = lstat(path, &info);
+		CE_ASSERT(err == 0, "lstat: errno = %d", errno);
+		CE_UNUSED(err);
+		return ((S_ISDIR(info.st_mode) == 1) && (S_ISLNK(info.st_mode) == 0));
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	DWORD fattr = GetFileAttributes(path);
-	return (fattr != INVALID_FILE_ATTRIBUTES && (fattr & FILE_ATTRIBUTE_DIRECTORY) != 0);
+		DWORD fattr = GetFileAttributes(path);
+		return (fattr != INVALID_FILE_ATTRIBUTES && (fattr & FILE_ATTRIBUTE_DIRECTORY) != 0);
 #endif
 #endif
-}
+	}
 
 
-/// Returns whether the path is a regular file.
-inline bool is_file(const char* path)
-{
+	/// Returns whether the path is a regular file.
+	inline bool is_file(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	struct stat info;
-	memset(&info, 0, sizeof(struct stat));
-	int err = lstat(path, &info);
-	CE_ASSERT(err == 0, "lstat: errno = %d", errno);
-	CE_UNUSED(err);
-	return ((S_ISREG(info.st_mode) == 1) && (S_ISLNK(info.st_mode) == 0));
+		struct stat info;
+		memset(&info, 0, sizeof(struct stat));
+		int err = lstat(path, &info);
+		CE_ASSERT(err == 0, "lstat: errno = %d", errno);
+		CE_UNUSED(err);
+		return ((S_ISREG(info.st_mode) == 1) && (S_ISLNK(info.st_mode) == 0));
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	DWORD fattr = GetFileAttributes(path);
-	return (fattr != INVALID_FILE_ATTRIBUTES && (fattr & FILE_ATTRIBUTE_DIRECTORY) == 0);
+		DWORD fattr = GetFileAttributes(path);
+		return (fattr != INVALID_FILE_ATTRIBUTES && (fattr & FILE_ATTRIBUTE_DIRECTORY) == 0);
 #endif
 #endif
-}
+	}
 
 
-/// Creates a regular file.
-inline void create_file(const char* path)
-{
+	/// Creates a regular file.
+	inline void create_file(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	// Permission mask: rw-r--r--
-	int err = ::mknod(path, S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0);
-	CE_ASSERT(err == 0, "mknod: errno = %d", errno);
-	CE_UNUSED(err);
+		// Permission mask: rw-r--r--
+		int err = ::mknod(path, S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0);
+		CE_ASSERT(err == 0, "mknod: errno = %d", errno);
+		CE_UNUSED(err);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	HANDLE hfile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-	CE_ASSERT(hfile != INVALID_HANDLE_VALUE, "CreateFile: GetLastError = %d", GetLastError());
-	CloseHandle(hfile);
+		HANDLE hfile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+		CE_ASSERT(hfile != INVALID_HANDLE_VALUE, "CreateFile: GetLastError = %d", GetLastError());
+		CloseHandle(hfile);
 #endif
 #endif
-}
+	}
 
 
-/// Deletes a regular file.
-inline void delete_file(const char* path)
-{
+	/// Deletes a regular file.
+	inline void delete_file(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	int err = ::unlink(path);
-	CE_ASSERT(err == 0, "unlink: errno = %d", errno);
-	CE_UNUSED(err);
+		int err = ::unlink(path);
+		CE_ASSERT(err == 0, "unlink: errno = %d", errno);
+		CE_UNUSED(err);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	BOOL err = DeleteFile(path);
-	CE_ASSERT(err != 0, "DeleteFile: GetLastError = %d", GetLastError());
-	CE_UNUSED(err);
+		BOOL err = DeleteFile(path);
+		CE_ASSERT(err != 0, "DeleteFile: GetLastError = %d", GetLastError());
+		CE_UNUSED(err);
 #endif
 #endif
-}
+	}
 
 
-/// Creates a directory.
-inline void create_directory(const char* path)
-{
+	/// Creates a directory.
+	inline void create_directory(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	// rwxr-xr-x
-	int err = ::mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
-	CE_ASSERT(err == 0, "mkdir: errno = %d", errno);
-	CE_UNUSED(err);
+		// rwxr-xr-x
+		int err = ::mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+		CE_ASSERT(err == 0, "mkdir: errno = %d", errno);
+		CE_UNUSED(err);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	BOOL err = CreateDirectory(path, NULL);
-	CE_ASSERT(err != 0, "CreateDirectory: GetLastError = %d", GetLastError());
-	CE_UNUSED(err);
+		BOOL err = CreateDirectory(path, NULL);
+		CE_ASSERT(err != 0, "CreateDirectory: GetLastError = %d", GetLastError());
+		CE_UNUSED(err);
 #endif
 #endif
-}
+	}
 
 
-/// Deletes a directory.
-inline void delete_directory(const char* path)
-{
+	/// Deletes a directory.
+	inline void delete_directory(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	int err = ::rmdir(path);
-	CE_ASSERT(err == 0, "rmdir: errno = %d", errno);
-	CE_UNUSED(err);
+		int err = ::rmdir(path);
+		CE_ASSERT(err == 0, "rmdir: errno = %d", errno);
+		CE_UNUSED(err);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	BOOL err = RemoveDirectory(path);
-	CE_ASSERT(err != 0, "RemoveDirectory: GetLastError = %d", GetLastError());
-	CE_UNUSED(err);
+		BOOL err = RemoveDirectory(path);
+		CE_ASSERT(err != 0, "RemoveDirectory: GetLastError = %d", GetLastError());
+		CE_UNUSED(err);
 #endif
 #endif
-}
-
-/// Returns the list of @a files in the given @a dir directory. Optionally walks into
-/// subdirectories whether @a recursive is true.
-/// @note
-/// Does not follow symbolic links.
-inline void list_files(const char* path, Vector<DynamicString>& files)
-{
-#if CROWN_PLATFORM_POSIX
-	DIR *dir;
-	struct dirent *entry;
-
-	if (!(dir = opendir(path)))
-	{
-		return;
 	}
 	}
 
 
-	while ((entry = readdir(dir)))
+	/// Returns the list of @a files in the given @a dir directory. Optionally walks into
+	/// subdirectories whether @a recursive is true.
+	/// @note
+	/// Does not follow symbolic links.
+	inline void list_files(const char* path, Vector<DynamicString>& files)
 	{
 	{
-		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+#if CROWN_PLATFORM_POSIX
+		DIR *dir;
+		struct dirent *entry;
+
+		if (!(dir = opendir(path)))
 		{
 		{
-			continue;
+			return;
 		}
 		}
 
 
-		DynamicString filename(default_allocator());
+		while ((entry = readdir(dir)))
+		{
+			if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+			{
+				continue;
+			}
 
 
-		filename = entry->d_name;
-		vector::push_back(files, filename);
-	}
+			DynamicString filename(default_allocator());
 
 
-	closedir(dir);
-#elif CROWN_PLATFORM_WINDOWS
-	HANDLE file = INVALID_HANDLE_VALUE;
-	WIN32_FIND_DATA ffd;
+			filename = entry->d_name;
+			vector::push_back(files, filename);
+		}
 
 
-	char cur_path[MAX_PATH_LENGTH];
+		closedir(dir);
+#elif CROWN_PLATFORM_WINDOWS
+		HANDLE file = INVALID_HANDLE_VALUE;
+		WIN32_FIND_DATA ffd;
 
 
-	string::strncpy(cur_path, path, string::strlen(path) + 1);
-	string::strncat(cur_path, "\\*", 2);
+		char cur_path[MAX_PATH_LENGTH];
 
 
-	file = FindFirstFile(cur_path, &ffd);
+		string::strncpy(cur_path, path, string::strlen(path) + 1);
+		string::strncat(cur_path, "\\*", 2);
 
 
-	do
-	{
-		CE_ASSERT(file != INVALID_HANDLE_VALUE, "Unable to list files. errono %d", GetLastError());
+		file = FindFirstFile(cur_path, &ffd);
 
 
-		if ((string::strcmp(ffd.cFileName, ".") == 0) || (string::strcmp(ffd.cFileName, "..") == 0))
+		do
 		{
 		{
-			continue;
-		}
+			CE_ASSERT(file != INVALID_HANDLE_VALUE, "Unable to list files. errono %d", GetLastError());
 
 
-		DynamicString filename(default_allocator());
+			if ((string::strcmp(ffd.cFileName, ".") == 0) || (string::strcmp(ffd.cFileName, "..") == 0))
+			{
+				continue;
+			}
 
 
-		filename = ffd.cFileName;
-		vector::push_back(files, filename);
-	}
-	while (FindNextFile(file, &ffd) != 0);
+			DynamicString filename(default_allocator());
 
 
-	FindClose(file);
+			filename = ffd.cFileName;
+			vector::push_back(files, filename);
+		}
+		while (FindNextFile(file, &ffd) != 0);
+
+		FindClose(file);
 #endif
 #endif
-}
+	}
 
 
-/// Returns os-dependent path from os-indipendent @a path
-inline const char* normalize_path(const char* path)
-{
+	/// Returns os-dependent path from os-indipendent @a path
+	inline const char* normalize_path(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	static char norm[MAX_PATH_LENGTH];
-	char* cur = norm;
+		static char norm[MAX_PATH_LENGTH];
+		char* cur = norm;
 
 
-	while ((*path) != '\0')
-	{
-		if ((*path) == '\\')
+		while ((*path) != '\0')
 		{
 		{
-			(*cur) = PATH_SEPARATOR;
+			if ((*path) == '\\')
+			{
+				(*cur) = PATH_SEPARATOR;
+			}
+			else
+			{
+				(*cur) = (*path);
+			}
+
+			path++;
+			cur++;
 		}
 		}
-		else
-		{
-			(*cur) = (*path);
-		}
-
-		path++;
-		cur++;
-	}
 
 
-	return norm;
+		return norm;
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	static char norm[MAX_PATH_LENGTH];
+		static char norm[MAX_PATH_LENGTH];
 
 
-	for (uint32_t i = 0; i < string::strlen(path)+1; i++)
-	{
-		if (path[i] == '/')
-		{
-			norm[i] = '\\';
-		}
-		else
+		for (uint32_t i = 0; i < string::strlen(path)+1; i++)
 		{
 		{
-			norm[i] = path[i];
+			if (path[i] == '/')
+			{
+				norm[i] = '\\';
+			}
+			else
+			{
+				norm[i] = path[i];
+			}
 		}
 		}
-	}
 
 
-	return norm;
+		return norm;
 #endif
 #endif
-}
+	}
 
 
-inline const char* getcwd(char* buf, size_t size)
-{
+	inline const char* getcwd(char* buf, size_t size)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return ::getcwd(buf, size);
+		return ::getcwd(buf, size);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	GetCurrentDirectory(size, buf);
-	return buf;
+		GetCurrentDirectory(size, buf);
+		return buf;
 #endif
 #endif
-}
+	}
 
 
-inline const char* getenv(const char* name)
-{
+	inline const char* getenv(const char* name)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return ::getenv(name);
+		return ::getenv(name);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	// GetEnvironmentVariable(name, buf, size);
+		// GetEnvironmentVariable(name, buf, size);
 #endif
 #endif
-}
+	}
 
 
-inline int64_t clocktime()
-{
+	inline int64_t clocktime()
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	timespec ttime;
-	clock_gettime(CLOCK_MONOTONIC, &ttime);
-	return ttime.tv_sec * int64_t(1000000000) + ttime.tv_nsec;
+		timespec ttime;
+		clock_gettime(CLOCK_MONOTONIC, &ttime);
+		return ttime.tv_sec * int64_t(1000000000) + ttime.tv_nsec;
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	LARGE_INTEGER ttime;
-	QueryPerformanceCounter(&ttime);
-	return (int64_t) ttime.QuadPart;
+		LARGE_INTEGER ttime;
+		QueryPerformanceCounter(&ttime);
+		return (int64_t) ttime.QuadPart;
 #endif
 #endif
-}
+	}
 
 
-inline int64_t clockfrequency()
-{
+	inline int64_t clockfrequency()
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return int32_t(1000000000);
+		return int32_t(1000000000);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	LARGE_INTEGER freq;
-	QueryPerformanceFrequency(&freq);
-	return (int64_t) freq.QuadPart;
+		LARGE_INTEGER freq;
+		QueryPerformanceFrequency(&freq);
+		return (int64_t) freq.QuadPart;
 #endif
 #endif
-}
+	}
 
 
-inline void* open_library(const char* path)
-{
+	inline void* open_library(const char* path)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return ::dlopen(path, RTLD_LAZY);
+		return ::dlopen(path, RTLD_LAZY);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	return (void*) LoadLibraryA(path);
+		return (void*) LoadLibraryA(path);
 #endif
 #endif
-}
+	}
 
 
-inline void close_library(void* library)
-{
+	inline void close_library(void* library)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	dlclose(library);
+		dlclose(library);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	FreeLibrary((HMODULE) library);
+		FreeLibrary((HMODULE) library);
 #endif
 #endif
-}
+	}
 
 
-inline void* lookup_symbol(void* library, const char* name)
-{
+	inline void* lookup_symbol(void* library, const char* name)
+	{
 #if CROWN_PLATFORM_POSIX
 #if CROWN_PLATFORM_POSIX
-	return ::dlsym(library, name);
+		return ::dlsym(library, name);
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	return (void*) GetProcAddress((HMODULE) library, name);
+		return (void*) GetProcAddress((HMODULE) library, name);
 #endif
 #endif
-}
-
-/// Executes a process.
-/// @a args is an array of arguments where:
-/// @a args[0] is the path to the program executable,
-/// @a args[1, 2, ..., n-1] is a list of arguments to pass to the executable,
-/// @a args[n] is NULL.
-inline void execute_process(const char* args[])
-{
-#if CROWN_PLATFORM_POSIX
-	pid_t pid = fork();
-	CE_ASSERT(pid != -1, "fork: errno = %d", errno);
-	if (pid)
-	{
-		int32_t dummy;
-		wait(&dummy);
 	}
 	}
-	else
+
+	/// Executes a process.
+	/// @a args is an array of arguments where:
+	/// @a args[0] is the path to the program executable,
+	/// @a args[1, 2, ..., n-1] is a list of arguments to pass to the executable,
+	/// @a args[n] is NULL.
+	inline void execute_process(const char* args[])
 	{
 	{
-		int err = execv(args[0], (char* const*)args);
-		CE_ASSERT(err != -1, "execv: errno = %d", errno);
-		CE_UNUSED(err);
-		exit(EXIT_SUCCESS);
-	}
+#if CROWN_PLATFORM_POSIX
+		pid_t pid = fork();
+		CE_ASSERT(pid != -1, "fork: errno = %d", errno);
+		if (pid)
+		{
+			int32_t dummy;
+			wait(&dummy);
+		}
+		else
+		{
+			int err = execv(args[0], (char* const*)args);
+			CE_ASSERT(err != -1, "execv: errno = %d", errno);
+			CE_UNUSED(err);
+			exit(EXIT_SUCCESS);
+		}
 #elif CROWN_PLATFORM_WINDOWS
 #elif CROWN_PLATFORM_WINDOWS
-	STARTUPINFO info;
-	memset(&info, 0, sizeof(info));
-	info.cb = sizeof(info);
+		STARTUPINFO info;
+		memset(&info, 0, sizeof(info));
+		info.cb = sizeof(info);
 
 
-	PROCESS_INFORMATION process;
-	memset(&process, 0, sizeof(process));
+		PROCESS_INFORMATION process;
+		memset(&process, 0, sizeof(process));
 
 
-	DynamicString cmds(default_allocator());
+		DynamicString cmds(default_allocator());
 
 
-	for (uint32_t i = 0; args[i] != NULL; i++)
-	{
-		cmds += args[i];
-		cmds += ' ';
-	}
+		for (uint32_t i = 0; args[i] != NULL; i++)
+		{
+			cmds += args[i];
+			cmds += ' ';
+		}
 
 
-	// Necessary because CreateProcess second argument must be non-const
-	char tmp[1024];
-	string::strncpy(tmp, normalize_path(cmds.c_str()), string::strlen(cmds.c_str()));
+		// Necessary because CreateProcess second argument must be non-const
+		char tmp[1024];
+		string::strncpy(tmp, normalize_path(cmds.c_str()), string::strlen(cmds.c_str()));
 
 
-	int err = CreateProcess(args[0], tmp, NULL, NULL, TRUE, 0, NULL, NULL, &info, &process);
-	CE_ASSERT(err != 0, "CreateProcess: GetLastError = %d", GetLastError());
-	CE_UNUSED(err);
+		int err = CreateProcess(args[0], tmp, NULL, NULL, TRUE, 0, NULL, NULL, &info, &process);
+		CE_ASSERT(err != 0, "CreateProcess: GetLastError = %d", GetLastError());
+		CE_UNUSED(err);
 
 
-	::WaitForSingleObject(process.hProcess, INFINITE);
-	CloseHandle(process.hProcess);
-	CloseHandle(process.hThread);
+		::WaitForSingleObject(process.hProcess, INFINITE);
+		CloseHandle(process.hProcess);
+		CloseHandle(process.hThread);
 #endif
 #endif
-}
-
+	}
 } // namespace os
 } // namespace os
 } // namespace crown
 } // namespace crown