From db3d6e2886ba043b9b30f6448ca0bcf92e58e039 Mon Sep 17 00:00:00 2001 From: David Leal Date: Fri, 8 Sep 2023 15:38:14 -0600 Subject: [PATCH] feat: add Windows CI back (#1290) Signed-off-by: realstealthninja Co-authored-by: github-actions[bot] Co-authored-by: realstealthninja <68815218+realstealthninja@users.noreply.github.com> --- .github/workflows/awesome_workflow.yml | 4 +- CMakeLists.txt | 13 +- DIRECTORY.md | 2 + client_server/CMakeLists.txt | 24 +- client_server/bool.h | 55 ++++ client_server/fork.h | 298 ++++++++++++++++++ .../remote_command_exec_udp_client.c | 19 +- .../remote_command_exec_udp_server.c | 19 +- client_server/tcp_full_duplex_client.c | 22 +- client_server/tcp_full_duplex_server.c | 31 +- client_server/tcp_half_duplex_client.c | 19 +- client_server/tcp_half_duplex_server.c | 19 +- developer_tools/min_printf.h | 6 +- dynamic_programming/matrix_chain_order.c | 88 ++++-- graphics/CMakeLists.txt | 2 +- searching/exponential_search.c | 7 +- 16 files changed, 547 insertions(+), 81 deletions(-) create mode 100644 client_server/bool.h create mode 100644 client_server/fork.h diff --git a/.github/workflows/awesome_workflow.yml b/.github/workflows/awesome_workflow.yml index dc3c8532..728238e8 100644 --- a/.github/workflows/awesome_workflow.yml +++ b/.github/workflows/awesome_workflow.yml @@ -57,14 +57,14 @@ jobs: needs: [MainSequence] strategy: matrix: - os: [ubuntu-latest, macOS-latest] + os: [windows-latest, ubuntu-latest, macOS-latest] steps: - uses: actions/checkout@v3 with: submodules: true - run: | cmake -B ./build -S . - cmake --build build + cmake --build build --config Release - name: Label on PR fail uses: actions/github-script@v6 if: ${{ failure() && matrix.os == 'ubuntu-latest' && github.event_name == 'pull_request' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index f85692ad..01a43e66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,17 @@ cmake_minimum_required(VERSION 3.22) project(Algorithms_in_C - LANGUAGES C - VERSION 1.0.0 - DESCRIPTION "Set of algorithms implemented in C." -) + LANGUAGES C + VERSION 1.0.0 + DESCRIPTION "Set of algorithms implemented in C." + ) # Set compilation standards set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED YES) - -if(MSVC) +if (MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) # add_compile_options(/Za) -endif(MSVC) +endif (MSVC) # check for math library # addresses a bug when linking on OSX diff --git a/DIRECTORY.md b/DIRECTORY.md index 1493a480..1339bc6f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -7,7 +7,9 @@ * [Rot13](https://github.com/TheAlgorithms/C/blob/HEAD/cipher/rot13.c) ## Client Server + * [Bool](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/bool.h) * [Client](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/client.c) + * [Fork](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/fork.h) * [Remote Command Exec Udp Client](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/remote_command_exec_udp_client.c) * [Remote Command Exec Udp Server](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/remote_command_exec_udp_server.c) * [Server](https://github.com/TheAlgorithms/C/blob/HEAD/client_server/server.c) diff --git a/client_server/CMakeLists.txt b/client_server/CMakeLists.txt index c02e6185..58d0aeb8 100644 --- a/client_server/CMakeLists.txt +++ b/client_server/CMakeLists.txt @@ -6,6 +6,7 @@ else() CHECK_INCLUDE_FILE(arpa/inet.h ARPA_HEADERS) endif() +include(CheckSymbolExists) if(ARPA_HEADERS OR WINSOCK_HEADER) # If necessary, use the RELATIVE flag, otherwise each source file may be listed # with full pathname. RELATIVE may makes it easier to extract an executable name @@ -15,16 +16,21 @@ if(ARPA_HEADERS OR WINSOCK_HEADER) # AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_SOURCES) foreach( testsourcefile ${APP_SOURCES} ) # I used a simple string replace, to cut off .cpp. - string( REPLACE ".c" "" testname ${testsourcefile} ) - add_executable( ${testname} ${testsourcefile} ) - - if(OpenMP_C_FOUND) + string(REPLACE ".c" "" testname ${testsourcefile}) + + if(NOT WIN32) + if(${testname} STREQUAL "fork" OR ${testname} STREQUAL "bool") + continue() + endif() + endif() + add_executable(${testname} ${testsourcefile}) + + if (OpenMP_C_FOUND) target_link_libraries(${testname} PRIVATE OpenMP::OpenMP_C) - endif() - if(MATH_LIBRARY) + endif () + if (MATH_LIBRARY) target_link_libraries(${testname} PRIVATE ${MATH_LIBRARY}) - endif() - + endif () # if(HAS_UNISTD) # target_compile_definitions(${testname} PRIVATE HAS_UNISTD) # endif() @@ -34,7 +40,7 @@ if(ARPA_HEADERS OR WINSOCK_HEADER) # target_compile_definitions(${testname} PRIVATE WINSOCK_HEADER) # endif() - if(WINSOCK_HEADER) + if (WINSOCK_HEADER) target_link_libraries(${testname} PRIVATE ws2_32) # link winsock library on windows endif() diff --git a/client_server/bool.h b/client_server/bool.h new file mode 100644 index 00000000..25cc9a72 --- /dev/null +++ b/client_server/bool.h @@ -0,0 +1,55 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2007 - INRIA + * + * Copyright (C) 2012 - 2016 - Scilab Enterprises + * + * This file is hereby licensed under the terms of the GNU GPL v2.0, + * pursuant to article 5.3.4 of the CeCILL v.2.1. + * This file was originally licensed under the terms of the CeCILL v2.1, + * and continues to be available under such terms. + * For more information, see the COPYING file which you should have received + * along with this program. + * + */ +#ifndef __BOOL_H__ +#define __BOOL_H__ + +/* define boolean type */ +#ifdef BOOL +#undef BOOL +#endif + +#ifdef TRUE +#undef TRUE +#endif + +#ifdef FALSE +#undef FALSE +#endif + + +#ifndef _MSC_VER +typedef enum +{ + FALSE = 0, + TRUE = 1 +} BOOL; + +#else +/* Please notice that BOOL is defined in */ +/* BUT windef.h includes all others windows include */ +/* it is better to redefine as */ +typedef int BOOL; +#define FALSE 0 +#define TRUE 1 + +#endif +/* converts BOOL to bool */ +#define BOOLtobool(w) ((w != FALSE) ? true : false) + +/* converts bool to BOOL */ +#define booltoBOOL(w) ((w == true) ? TRUE : FALSE) + +#endif /* __BOOL_H__ */ +/*--------------------------------------------------------------------------*/ diff --git a/client_server/fork.h b/client_server/fork.h new file mode 100644 index 00000000..3221d204 --- /dev/null +++ b/client_server/fork.h @@ -0,0 +1,298 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) DIGITEO - 2010 - Allan CORNET + * + * Copyright (C) 2012 - 2016 - Scilab Enterprises + * + * This file is hereby licensed under the terms of the GNU GPL v2.0, + * pursuant to article 5.3.4 of the CeCILL v.2.1. + * This file was originally licensed under the terms of the CeCILL v2.1, + * and continues to be available under such terms. + * For more information, see the COPYING file which you should have received + * along with this program. + * + */ +/*--------------------------------------------------------------------------*/ +#ifndef __FORK_H__ +#define __FORK_H__ + +/* http://technet.microsoft.com/en-us/library/bb497007.aspx */ +/* http://undocumented.ntinternals.net/ */ + +#include +#include + +#include "bool.h" + +/** + * simulate fork on Windows + */ +int fork(void); + +/** + * check if symbols to simulate fork are present + * and load these symbols + */ +BOOL haveLoadedFunctionsForFork(void); + +/*--------------------------------------------------------------------------*/ +typedef LONG NTSTATUS; +/*--------------------------------------------------------------------------*/ +typedef struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG ProcessId; + UCHAR ObjectTypeNumber; + UCHAR Flags; + USHORT Handle; + PVOID Object; + ACCESS_MASK GrantedAccess; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; +/*--------------------------------------------------------------------------*/ +typedef struct _OBJECT_ATTRIBUTES +{ + ULONG Length; + HANDLE RootDirectory; + PVOID /* really PUNICODE_STRING */ ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; /* type SECURITY_DESCRIPTOR */ + PVOID SecurityQualityOfService; /* type SECURITY_QUALITY_OF_SERVICE */ +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; +/*--------------------------------------------------------------------------*/ +typedef enum _MEMORY_INFORMATION_ +{ + MemoryBasicInformation, + MemoryWorkingSetList, + MemorySectionName, + MemoryBasicVlmInformation +} MEMORY_INFORMATION_CLASS; +/*--------------------------------------------------------------------------*/ +typedef struct _CLIENT_ID +{ + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID, *PCLIENT_ID; +/*--------------------------------------------------------------------------*/ +typedef struct _USER_STACK +{ + PVOID FixedStackBase; + PVOID FixedStackLimit; + PVOID ExpandableStackBase; + PVOID ExpandableStackLimit; + PVOID ExpandableStackBottom; +} USER_STACK, *PUSER_STACK; +/*--------------------------------------------------------------------------*/ +typedef LONG KPRIORITY; +typedef ULONG_PTR KAFFINITY; +typedef KAFFINITY *PKAFFINITY; +/*--------------------------------------------------------------------------*/ +typedef struct _THREAD_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PVOID TebBaseAddress; + CLIENT_ID ClientId; + KAFFINITY AffinityMask; + KPRIORITY Priority; + KPRIORITY BasePriority; +} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; +/*--------------------------------------------------------------------------*/ +typedef enum _SYSTEM_INFORMATION_CLASS +{ + SystemHandleInformation = 0x10 +} SYSTEM_INFORMATION_CLASS; +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwWriteVirtualMemory_t)( + IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN PVOID Buffer, + IN ULONG NumberOfBytesToWrite, OUT PULONG NumberOfBytesWritten OPTIONAL); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwCreateProcess_t)( + OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE InheriteFromProcessHandle, + IN BOOLEAN InheritHandles, IN HANDLE SectionHandle OPTIONAL, + IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(WINAPI *ZwQuerySystemInformation_t)( + SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, + ULONG SystemInformationLength, PULONG ReturnLength); +typedef NTSTATUS(NTAPI *ZwQueryVirtualMemory_t)( + IN HANDLE ProcessHandle, IN PVOID BaseAddress, + IN MEMORY_INFORMATION_CLASS MemoryInformationClass, + OUT PVOID MemoryInformation, IN ULONG MemoryInformationLength, + OUT PULONG ReturnLength OPTIONAL); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwGetContextThread_t)(IN HANDLE ThreadHandle, + OUT PCONTEXT Context); +typedef NTSTATUS(NTAPI *ZwCreateThread_t)( + OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, + IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, + OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, + IN PUSER_STACK UserStack, IN BOOLEAN CreateSuspended); +/*--------------------------------------------------------------------------*/ +typedef NTSTATUS(NTAPI *ZwResumeThread_t)(IN HANDLE ThreadHandle, + OUT PULONG SuspendCount OPTIONAL); +typedef NTSTATUS(NTAPI *ZwClose_t)(IN HANDLE ObjectHandle); +typedef NTSTATUS(NTAPI *ZwQueryInformationThread_t)( + IN HANDLE ThreadHandle, IN THREAD_INFORMATION_CLASS ThreadInformationClass, + OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, + OUT PULONG ReturnLength OPTIONAL); +/*--------------------------------------------------------------------------*/ +static ZwCreateProcess_t ZwCreateProcess = NULL; +static ZwQuerySystemInformation_t ZwQuerySystemInformation = NULL; +static ZwQueryVirtualMemory_t ZwQueryVirtualMemory = NULL; +static ZwCreateThread_t ZwCreateThread = NULL; +static ZwGetContextThread_t ZwGetContextThread = NULL; +static ZwResumeThread_t ZwResumeThread = NULL; +static ZwClose_t ZwClose = NULL; +static ZwQueryInformationThread_t ZwQueryInformationThread = NULL; +static ZwWriteVirtualMemory_t ZwWriteVirtualMemory = NULL; +/*--------------------------------------------------------------------------*/ +#define NtCurrentProcess() ((HANDLE)-1) +#define NtCurrentThread() ((HANDLE)-2) +/* we use really the Nt versions - so the following is just for completeness */ +#define ZwCurrentProcess() NtCurrentProcess() +#define ZwCurrentThread() NtCurrentThread() +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) +/*--------------------------------------------------------------------------*/ +/* setjmp env for the jump back into the fork() function */ +static jmp_buf jenv; +/*--------------------------------------------------------------------------*/ +/* entry point for our child thread process - just longjmp into fork */ +static int child_entry(void) +{ + longjmp(jenv, 1); + return 0; +} +/*--------------------------------------------------------------------------*/ +static BOOL haveLoadedFunctionsForFork(void) +{ + HMODULE ntdll = GetModuleHandle("ntdll"); + if (ntdll == NULL) + { + return FALSE; + } + + if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory && + ZwCreateThread && ZwGetContextThread && ZwResumeThread && + ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose) + { + return TRUE; + } + + ZwCreateProcess = + (ZwCreateProcess_t)GetProcAddress(ntdll, "ZwCreateProcess"); + ZwQuerySystemInformation = (ZwQuerySystemInformation_t)GetProcAddress( + ntdll, "ZwQuerySystemInformation"); + ZwQueryVirtualMemory = + (ZwQueryVirtualMemory_t)GetProcAddress(ntdll, "ZwQueryVirtualMemory"); + ZwCreateThread = (ZwCreateThread_t)GetProcAddress(ntdll, "ZwCreateThread"); + ZwGetContextThread = + (ZwGetContextThread_t)GetProcAddress(ntdll, "ZwGetContextThread"); + ZwResumeThread = (ZwResumeThread_t)GetProcAddress(ntdll, "ZwResumeThread"); + ZwQueryInformationThread = (ZwQueryInformationThread_t)GetProcAddress( + ntdll, "ZwQueryInformationThread"); + ZwWriteVirtualMemory = + (ZwWriteVirtualMemory_t)GetProcAddress(ntdll, "ZwWriteVirtualMemory"); + ZwClose = (ZwClose_t)GetProcAddress(ntdll, "ZwClose"); + + if (ZwCreateProcess && ZwQuerySystemInformation && ZwQueryVirtualMemory && + ZwCreateThread && ZwGetContextThread && ZwResumeThread && + ZwQueryInformationThread && ZwWriteVirtualMemory && ZwClose) + { + return TRUE; + } + else + { + ZwCreateProcess = NULL; + ZwQuerySystemInformation = NULL; + ZwQueryVirtualMemory = NULL; + ZwCreateThread = NULL; + ZwGetContextThread = NULL; + ZwResumeThread = NULL; + ZwQueryInformationThread = NULL; + ZwWriteVirtualMemory = NULL; + ZwClose = NULL; + } + return FALSE; +} +/*--------------------------------------------------------------------------*/ +int fork(void) +{ + HANDLE hProcess = 0, hThread = 0; + OBJECT_ATTRIBUTES oa = {sizeof(oa)}; + MEMORY_BASIC_INFORMATION mbi; + CLIENT_ID cid; + USER_STACK stack; + PNT_TIB tib; + THREAD_BASIC_INFORMATION tbi; + + CONTEXT context = {CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | + CONTEXT_FLOATING_POINT}; + + if (setjmp(jenv) != 0) + { + return 0; /* return as a child */ + } + + /* check whether the entry points are initilized and get them if necessary + */ + if (!ZwCreateProcess && !haveLoadedFunctionsForFork()) + { + return -1; + } + + /* create forked process */ + ZwCreateProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, NtCurrentProcess(), + TRUE, 0, 0, 0); + + /* set the Eip for the child process to our child function */ + ZwGetContextThread(NtCurrentThread(), &context); + + /* In x64 the Eip and Esp are not present, their x64 counterparts are Rip + and Rsp respectively. + */ +#if _WIN64 + context.Rip = (ULONG)child_entry; +#else + context.Eip = (ULONG)child_entry; +#endif + +#if _WIN64 + ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Rsp, + MemoryBasicInformation, &mbi, sizeof mbi, 0); +#else + ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Esp, + MemoryBasicInformation, &mbi, sizeof mbi, 0); +#endif + + stack.FixedStackBase = 0; + stack.FixedStackLimit = 0; + stack.ExpandableStackBase = (PCHAR)mbi.BaseAddress + mbi.RegionSize; + stack.ExpandableStackLimit = mbi.BaseAddress; + stack.ExpandableStackBottom = mbi.AllocationBase; + + /* create thread using the modified context and stack */ + ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa, hProcess, &cid, &context, + &stack, TRUE); + + /* copy exception table */ + ZwQueryInformationThread(NtCurrentThread(), ThreadMemoryPriority, &tbi, + sizeof tbi, 0); + tib = (PNT_TIB)tbi.TebBaseAddress; + ZwQueryInformationThread(hThread, ThreadMemoryPriority, &tbi, sizeof tbi, + 0); + ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress, &tib->ExceptionList, + sizeof tib->ExceptionList, 0); + + /* start (resume really) the child */ + ZwResumeThread(hThread, 0); + + /* clean up */ + ZwClose(hThread); + ZwClose(hProcess); + + /* exit with child's pid */ + return (int)cid.UniqueProcess; +} + +#endif /* __FORK_H__ */ +/*--------------------------------------------------------------------------*/ diff --git a/client_server/remote_command_exec_udp_client.c b/client_server/remote_command_exec_udp_client.c index 8a2afa0c..6669919f 100644 --- a/client_server/remote_command_exec_udp_client.c +++ b/client_server/remote_command_exec_udp_client.c @@ -14,17 +14,26 @@ * using UDP is shown using the server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include /// For the type in_addr_t and in_port_t +#else #include /// For the type in_addr_t and in_port_t -#include /// To indicate what went wrong if an error occurs #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// To indicate what went wrong if an error occurs +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place diff --git a/client_server/remote_command_exec_udp_server.c b/client_server/remote_command_exec_udp_server.c index 619c116c..67d62390 100644 --- a/client_server/remote_command_exec_udp_server.c +++ b/client_server/remote_command_exec_udp_server.c @@ -14,17 +14,26 @@ * using UDP is shown using the server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include /// For the type in_addr_t and in_port_t +#else #include /// For the type in_addr_t and in_port_t -#include /// To indicate what went wrong if an error occurs #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// To indicate what went wrong if an error occurs +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place diff --git a/client_server/tcp_full_duplex_client.c b/client_server/tcp_full_duplex_client.c index 25c21b46..12836c59 100644 --- a/client_server/tcp_full_duplex_client.c +++ b/client_server/tcp_full_duplex_client.c @@ -17,16 +17,29 @@ * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define pid_t int +#define close _close +#include +#include +#include +#include +#include "fork.h" +#define sleep(a) Sleep(a * 1000) +#else #include /// For the type in_addr_t and in_port_t #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place @@ -141,6 +154,7 @@ int main() */ pid_t pid; pid = fork(); + if (pid == 0) /// Value of 0 is for child process { while (1) diff --git a/client_server/tcp_full_duplex_server.c b/client_server/tcp_full_duplex_server.c index da3635c6..aab2ea8d 100644 --- a/client_server/tcp_full_duplex_server.c +++ b/client_server/tcp_full_duplex_server.c @@ -3,7 +3,7 @@ * @author [NVombat](https://github.com/NVombat) * @brief Server-side implementation of [TCP Full Duplex * Communication](http://www.tcpipguide.com/free/t_SimplexFullDuplexandHalfDuplexOperation.htm) - * @see tcp_full_duplex_server.c + * @see tcp_full_duplex_client.c * * @details * The algorithm is based on the simple TCP client and server model. However, @@ -17,16 +17,29 @@ * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define pid_t int +#define close _close +#include +#include +#include +#include +#include "fork.h" +#define sleep(a) Sleep(a * 1000) +#else #include /// For the type in_addr_t and in_port_t #include /// For structures returned by the network database library - formatted internet addresses and port numbers #include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 10000 /// Define port over which communication will take place @@ -162,7 +175,15 @@ int main() * place simultaneously this represents FULL DUPLEX COMMUNICATION */ pid_t pid; + + #ifdef _WIN32 + #ifdef FORK_WINDOWS pid = fork(); + #endif + #else + pid = fork(); + #endif + if (pid == 0) /// Value of 0 is for child process { while (1) diff --git a/client_server/tcp_half_duplex_client.c b/client_server/tcp_half_duplex_client.c index 51cc98b9..0d77dedc 100644 --- a/client_server/tcp_half_duplex_client.c +++ b/client_server/tcp_half_duplex_client.c @@ -15,15 +15,24 @@ * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include +#else #include /// For structures returned by the network database library - formatted internet addresses and port numbers -#include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +// #include /// For in_addr and sockaddr_in structures +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 8100 /// Define port over which communication will take place diff --git a/client_server/tcp_half_duplex_server.c b/client_server/tcp_half_duplex_server.c index 9a1a7c1d..266d9896 100644 --- a/client_server/tcp_half_duplex_server.c +++ b/client_server/tcp_half_duplex_server.c @@ -15,15 +15,24 @@ * can be represented using the TCP server-client model & socket programming */ +#ifdef _WIN32 +#define bzero(b, len) \ + (memset((b), '\0', (len)), (void)0) /**< BSD name not in windows */ +#define close _close +#include +#include +#include +#else #include /// For structures returned by the network database library - formatted internet addresses and port numbers -#include /// For in_addr and sockaddr_in structures -#include /// For specific bit size values of variables +#include /// For macro definitions related to the creation of sockets +#include /// For definitions to allow for the porting of BSD programs +#include +#endif +// #include /// For in_addr and sockaddr_in structures +#include /// For specific bit size values of variables #include /// Variable types, several macros, and various functions for performing input and output #include /// Variable types, several macros, and various functions for performing general functions #include /// Various functions for manipulating arrays of characters -#include /// For macro definitions related to the creation of sockets -#include /// For definitions to allow for the porting of BSD programs -#include /// For miscellaneous symbolic constants and types, and miscellaneous functions #define PORT 8100 /// Define port over which communication will take place diff --git a/developer_tools/min_printf.h b/developer_tools/min_printf.h index b58db13d..395331c1 100644 --- a/developer_tools/min_printf.h +++ b/developer_tools/min_printf.h @@ -19,7 +19,11 @@ #define MIN_PRINTF_H #include /// for `malloc` and `free` functions -#include /// for `write` function +#ifdef _WIN32 + #include /// for `write` function +#else + #include /// for `write` function +#endif #include /// for `va_start` and `va_arg` functions #define INT_MAX_LENGTH 10 /// used as standard length of string to store integers diff --git a/dynamic_programming/matrix_chain_order.c b/dynamic_programming/matrix_chain_order.c index d0ee8cac..7b48f4ca 100644 --- a/dynamic_programming/matrix_chain_order.c +++ b/dynamic_programming/matrix_chain_order.c @@ -1,18 +1,20 @@ /** * @file - * @brief [Matrix Chain Order](https://en.wikipedia.org/wiki/Matrix_chain_multiplication) + * @brief [Matrix Chain + * Order](https://en.wikipedia.org/wiki/Matrix_chain_multiplication) * @details - * From Wikipedia: Matrix chain multiplication (or the matrix chain ordering problem) - * is an optimization problem concerning the most efficient way to multiply a given sequence of matrices. - * The problem is not actually to perform the multiplications, - * but merely to decide the sequence of the matrix multiplications involved. + * From Wikipedia: Matrix chain multiplication (or the matrix chain ordering + * problem) is an optimization problem concerning the most efficient way to + * multiply a given sequence of matrices. The problem is not actually to perform + * the multiplications, but merely to decide the sequence of the matrix + * multiplications involved. * @author [CascadingCascade](https://github.com/CascadingCascade) */ -#include /// for assert -#include /// for IO operations -#include /// for INT_MAX macro -#include /// for malloc() and free() +#include /// for assert +#include /// for INT_MAX macro +#include /// for IO operations +#include /// for malloc() and free() /** * @brief Finds the optimal sequence using the classic O(n^3) algorithm. @@ -21,27 +23,49 @@ * @param s location to store results * @returns number of operations */ -int matrixChainOrder(int l,const int *p, int *s) { - // mat stores the cost for a chain that starts at i and ends on j (inclusive on both ends) - int mat[l][l]; - for (int i = 0; i < l; ++i) { +int matrixChainOrder(int l, const int *p, int *s) +{ + // mat stores the cost for a chain that starts at i and ends on j (inclusive + // on both ends) + int **mat = malloc(l * sizeof(int *)); + for (int i = 0; i < l; ++i) + { + mat[i] = malloc(l * sizeof(int)); + } + + for (int i = 0; i < l; ++i) + { mat[i][i] = 0; } - // cl denotes the difference between start / end indices, cl + 1 would be chain length. - for (int cl = 1; cl < l; ++cl) { - for (int i = 0; i < l - cl; ++i) { + // cl denotes the difference between start / end indices, cl + 1 would be + // chain length. + for (int cl = 1; cl < l; ++cl) + { + for (int i = 0; i < l - cl; ++i) + { int j = i + cl; mat[i][j] = INT_MAX; - for (int div = i; div < j; ++div) { + for (int div = i; div < j; ++div) + { int q = mat[i][div] + mat[div + 1][j] + p[i] * p[div] * p[j]; - if (q < mat[i][j]) { + if (q < mat[i][j]) + { mat[i][j] = q; s[i * l + j] = div; } } } } - return mat[0][l - 1]; + int result = mat[0][l - 1]; + + // Free dynamically allocated memory + for (int i = 0; i < l; ++i) + { + free(mat[i]); + } + free(mat); + + return result; } /** @@ -52,14 +76,16 @@ int matrixChainOrder(int l,const int *p, int *s) { * @param j ending index * @returns void */ -void printSolution(int l,int *s,int i,int j) { - if(i == j) { - printf("A%d",i); +void printSolution(int l, int *s, int i, int j) +{ + if (i == j) + { + printf("A%d", i); return; } putchar('('); - printSolution(l,s,i,s[i * l + j]); - printSolution(l,s,s[i * l + j] + 1,j); + printSolution(l, s, i, s[i * l + j]); + printSolution(l, s, s[i * l + j] + 1, j); putchar(')'); } @@ -67,15 +93,16 @@ void printSolution(int l,int *s,int i,int j) { * @brief Self-test implementations * @returns void */ -static void test() { - int sizes[] = {35,15,5,10,20,25}; +static void test() +{ + int sizes[] = {35, 15, 5, 10, 20, 25}; int len = 6; int *sol = malloc(len * len * sizeof(int)); - int r = matrixChainOrder(len,sizes,sol); + int r = matrixChainOrder(len, sizes, sol); assert(r == 18625); - printf("Result : %d\n",r); + printf("Result : %d\n", r); printf("Optimal ordering : "); - printSolution(len,sol,0,5); + printSolution(len, sol, 0, 5); free(sol); printf("\n"); @@ -85,7 +112,8 @@ static void test() { * @brief Main function * @returns 0 */ -int main() { +int main() +{ test(); // run self-test implementations return 0; } diff --git a/graphics/CMakeLists.txt b/graphics/CMakeLists.txt index 6bb38bc2..89fc6565 100644 --- a/graphics/CMakeLists.txt +++ b/graphics/CMakeLists.txt @@ -8,7 +8,7 @@ if(OpenGL_FOUND) FREEGLUT-PRJ URL https://github.com/FreeGLUTProject/freeglut/releases/download/v3.2.1/freeglut-3.2.1.tar.gz URL_MD5 cd5c670c1086358598a6d4a9d166949d - CMAKE_GENERATOR ${CMAKE_GENERATOR} --config Release + CMAKE_GENERATOR ${CMAKE_GENERATOR} CMAKE_GENERATOR_TOOLSET ${CMAKE_GENERATOR_TOOLSET} CMAKE_GENERATOR_PLATFORM ${CMAKE_GENERATOR_PLATFORM} CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release diff --git a/searching/exponential_search.c b/searching/exponential_search.c index 7f30b443..efb1ec71 100644 --- a/searching/exponential_search.c +++ b/searching/exponential_search.c @@ -3,8 +3,9 @@ * \brief [Exponential Search](https://github.com/TheAlgorithms/Algorithms-Explanation/blob/master/en/Search%20Algorithms/Exponential%20Search.md) * \author [Alessio Farinelli](https://github.com/faridevnz) */ -#include /// for assert +#include /// for assert #include /// for int64_t, uint16_t +#include /// for printf #define ELEMENT -10 @@ -81,7 +82,7 @@ int main() static void test() { // empty array - int64_t arr_empty[] = {}; + int64_t arr_empty[] = { 0 }; assert(exponential_search(arr_empty, 0, 10) == -1); // elent not found int64_t arr_found[] = {1, 2, 3}; @@ -104,4 +105,6 @@ static void test() // find an element in an array of length n int64_t arr_middle[] = {-1, 2, 4, 6, 8}; assert(exponential_search(arr_middle, 5, 6) == 3); + + printf("All tests have successfully passed!\n"); }