From f64ebb50da3a74b9060f1616d05b1e25e0503798 Mon Sep 17 00:00:00 2001 From: Aiden Woodruff Date: Wed, 18 Sep 2019 22:51:25 -0500 Subject: Use CMake instead of other stuff Add stuff to develop in Visual Studio (i.e. to gitignore) Add correct_curses.h Add MSVC fixes to foreach.h macros Add Windows getopt.c and getopt.h (for now). --- .gitignore | 7 +++ CMakeLists.txt | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++ cmakeconfig.h.in | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 6 +++ src/correct_curses.h | 24 ++++++++++ src/foreach.h | 37 ++++++++++---- src/getopt.c | 51 ++++++++++++++++++++ src/getopt.h | 85 ++++++++++++++++++++++++++++++++ 8 files changed, 466 insertions(+), 8 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 cmakeconfig.h.in create mode 100644 src/CMakeLists.txt create mode 100644 src/correct_curses.h create mode 100644 src/getopt.c create mode 100644 src/getopt.h diff --git a/.gitignore b/.gitignore index 5245f77..6cd9601 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ # Ignore backups *~ \#*# + +# cmake build dir +out/ +build/ + +# Visual Studio +.vs \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b6355f7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,133 @@ +cmake_minimum_required(VERSION 3.8) +project(life VERSION 0.0 LANGUAGES C) + set(CMAKE_C_STANDARD 99) + set(CMAKE_C_STANDARD_REQUIRED YES) +# cmake_policy(SET CMP0067 NEW) # Use c++ standard in try_compile checks + +# Macros and stuff +include(CheckIncludeFile) +include(CheckCCompilerFlag) +include(CheckSymbolExists) +include(CheckTypeSize) +include(CMakePushCheckState) + +# CXX Compile Features options +if ($) + set(HAVE_AUTO_RETURN YES) +endif() + +# Settable options, i.e. to fix issues on VisualStudio +set(EXTRA_GLOBAL_OPTIONS "" CACHE STRING "Extra options to set") +set(EXTRA_LINKER_OPTIONS "" CACHE STRING "Extra linker options to set") +add_compile_options(${EXTRA_GLOBAL_OPTIONS}) +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EXTRA_LINKER_OPTIONS}") + +option(USE_PDCURSES "Use PDCurses") +if (USE_PDCURSES) + set(PDCURSES_SRCDIR "C:/PDCurses" CACHE FILEPATH "PDCurses' Source Directory") + set(PDCURSES_LIBRARIES "C:/PDCurses/wincon/pdcurses.lib" CACHE FILEPATH "PDCurses Library") +else() + find_package(Curses REQUIRED) +endif() + +# Large number of compiler flags (but not unreasonable, i.e. not VS's -Wall) +check_c_compiler_flag(-W4 HAVE_W4) +if (HAVE_W4) + add_compile_options(-W4) +else() + check_c_compiler_flag(-Wall HAVE_WALL) + check_c_compiler_flag(-Wextra HAVE_WEXTRA) + check_c_compiler_flag(-pedantic HAVE_PEDANTIC) +endif() +if ("$" OR "$" OR "$") + add_compile_options("$<$:-Wall>" "$<$:-Wextra>" "$<$:-pedantic>") +# else() + # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") +endif() + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Set some variables to match autoconf ones +set(PACKAGE_NAME ${PROJECT_NAME}) +string(TOLOWER ${PACKAGE_NAME} PACKAGE) +set(PACKAGE_VERSION ${PROJECT_VERSION}) +string(CONCAT PACKAGE_STRING ${PACKAGE_NAME} " " ${VERSION}) +set(PACKAGE_BUGREPORT aiden.woodruff@gmail.com) +set(PACKAGE_URL ${HOMEPAGE_URL}) + +# Check for headers +check_include_file(inttypes.h HAVE_INTTYPES_H) +check_include_file(memory.h HAVE_MEMORY_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stdlib.h HAVE_STDLIB_H) +check_include_file(string.h HAVE_STRING_H) +check_include_file(strings.h HAVE_STRINGS_H) +check_include_file(sys/stat.h HAVE_SYS_STAT_H) +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(unistd.h HAVE_UNISTD_H) + +# Check for libraries + + +# Set options similar to autoconf ones based off FindCurses's flags +if (USE_PDCURSES) + # Change PDCurses options to match FindCurses ones + message(STATUS "Using PDCurses") + set(CURSES_INCLUDE_DIRS ${PDCURSES_SRCDIR}) + set(CURSES_LIBRARIES ${PDCURSES_LIBRARIES}) + set(HAVE_CURSES YES) + set(HAVE_CURSES_H YES) +else () + find_package(Curses) + if (CURSES_FOUND) + set(HAVE_CURSES ${CURSES_FOUND}) + set(HAVE_CURSES_H ${CURSES_HAVE_CURSES_H}) + set(HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H}) + set(HAVE_NCURSES_CURSES_H ${CURSES_HAVE_NCURSES_CURSES_H}) + else() + message(FATAL_ERROR "No type of curses has been found. One fix might be to run cmake with the USE_PDCURSES option.") + endif () +endif () + +# Set the header to include +# NOTE: There are a number of other weird ones FindCurses has, but we'll ignore those +if (HAVE_NCURSES_CURSES_H) + set(CURSES_HEADER "ncurses/curses.h") + set(HAVE_NCURSES YES) +elseif (HAVE_NCURSES_H) + set(CURSES_HEADER "ncurses.h") + set(HAVE_NCURSES YES) +elseif (HAVE_CURSES_H) + set(CURSES_HEADER "curses.h") +endif() + +# Check for color support in curses, based off existence of the start_color function +if (HAVE_CURSES) + set(CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARIES}) + check_symbol_exists(start_color ${CURSES_HEADER} HAVE_CURSES_COLOR) + if (HAVE_CURSES_COLOR) + message(STATUS "Found color support for curses") + else() + message(STATUS "Did NOT find color support for curses") + endif() +endif() + +find_library(HAVE_MATH m) + +# Check for types +cmake_reset_check_state() +set(CMAKE_EXTRA_INCLUDE_FILES cstdint) +set(CMAKE) +check_type_size(int32_t SIZEOF_INT32_T) + +if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.12") +add_compile_definitions(HAVE_CMAKECONFIG_H) +else() +add_compile_options(-DHAVE_CMAKECONFIG_H) +endif() +configure_file(cmakeconfig.h.in cmakeconfig.h ESCAPE_QUOTES @ONLY) + +add_subdirectory(src) +# add_subdirectory(test) + diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in new file mode 100644 index 0000000..6e620f2 --- /dev/null +++ b/cmakeconfig.h.in @@ -0,0 +1,131 @@ +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CMATH + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_CSTDINT + +/* Define to 1 if a SysV or X/Open compatible Curses library is present */ +#cmakedefine HAVE_CURSES + +/* Define to 1 if library supports color (enhanced functions) */ +#cmakedefine HAVE_CURSES_COLOR + +/* Define to 1 if library supports X/Open Enhanced functions */ +#undef HAVE_CURSES_ENHANCED + +/* Define to 1 if is present */ +#cmakedefine HAVE_CURSES_H + +/* Define to 1 if library supports certain obsolete features */ +#undef HAVE_CURSES_OBSOLETE + +/* define if the compiler supports auto return type */ +#cmakedefine HAVE_AUTO_RETURN + +/* Define if the compiler supports trailing return type */ +#cmakedefine HAVE_TRAILING_RETURN + +#cmakedefine HAVE_NOEXCEPT +// My use of 201003 as the date is based off of N3050's date. +#if defined(HAVE_NOEXCEPT) || __cplusplus >= 201003L +#define my_noexcept noexcept +#else +#define my_noexcept throw() +#endif + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_FUNCTIONAL + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_IOSTREAM + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H + +/* Define to 1 if the Ncurses library is present */ +#cmakedefine HAVE_NCURSES + +/* Define to 1 if the NcursesW library is present */ +#undef HAVE_NCURSESW + +/* Define to 1 if is present */ +#undef HAVE_NCURSESW_CURSES_H + +/* Define to 1 if is present */ +#undef HAVE_NCURSESW_H + +/* Define to 1 if is present */ +#cmakedefine HAVE_NCURSES_CURSES_H + +/* Define to 1 if is present */ +#cmakedefine HAVE_NCURSES_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_RANDOM + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H + +/* Name of package */ +#cmakedefine PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#cmakedefine PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#cmakedefine PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#cmakedefine PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#cmakedefine PACKAGE_URL + +/* Define to the version of this package. */ +#cmakedefine PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#ifdef PACKAGE_VERSION +#define VERSION PACKAGE_VERSION +#else +#undef VERSION +#endif + +#cmakedefine HAVE_SIZEOF_INT32_T +@SIZEOF_INT32_T_CODE@ + +// Technically the standard doesn't require int32_t. But it does require int_fast32_t. We'll just prefer speed (over size). +#if !(defined(HAVE_SIZEOF_INT32_T) && SIZEOF_INT32_T == 4) +#define int32_t int_fast32_t +#endif + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..3b216bf --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,6 @@ +# Makefile stuff +include_directories(.) +add_executable(life life.c life.h updatemap.c updatemap.h menus.c menus.h) +target_compile_features(life PUBLIC c_function_prototypes c_variadic_macros) +target_include_directories(life PRIVATE "${CURSES_INCLUDE_DIRS}") +target_link_libraries(life "${CURSES_LIBRARIES}") diff --git a/src/correct_curses.h b/src/correct_curses.h new file mode 100644 index 0000000..60bc2ba --- /dev/null +++ b/src/correct_curses.h @@ -0,0 +1,24 @@ +#ifndef GRAPH_CORRECT_CURSES_H +#define GRAPH_CORRECT_CURSES_H +#if defined(HAVE_CMAKECONFIG_H) +#include + +#if defined HAVE_NCURSESW_CURSES_H +# include +#elif defined HAVE_NCURSESW_H +# include +#elif defined HAVE_NCURSES_CURSES_H +# include +#elif defined HAVE_NCURSES_H +# include +#elif defined HAVE_CURSES_H +# include +#else +# error "SysV or X/Open-compatible Curses header file required" +#endif +#else + +// Fingers-crossed +#include +#endif +#endif // GRAPH_CORRECT_CURSES_H \ No newline at end of file diff --git a/src/foreach.h b/src/foreach.h index e684b93..9b20953 100644 --- a/src/foreach.h +++ b/src/foreach.h @@ -1,11 +1,35 @@ #ifndef NARG -#define NARG(...) NARG_(__VA_ARGS__, RSEQ_N) -#define NARG_(...) NARG_N(__VA_ARGS__) -#define RSEQ_N 8, 7, 6, 5, 4, 3, 2, 1, 0 #define NARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N +#define RSEQ_N 8, 7, 6, 5, 4, 3, 2, 1, 0 +#if _MSC_VER && !__INTEL_COMPILER +#define EXPAND(...) __VA_ARGS__ +#define NARG_(...) EXPAND(EXPAND(NARG_N) (__VA_ARGS__)) +#else +#define NARG_(...) NARG_N(__VA_ARGS__) +#endif +#define NARG(...) NARG_(__VA_ARGS__, RSEQ_N) #endif #ifndef foreach + +#define CONCAT2(x, y) x##y +#define CONCAT1(x, y) CONCAT2(x,y) +#define CONCATENATE(x, y) CONCAT1(x, y) + +#if _MSC_VER && !__INTEL_COMPILER +#undef EXPAND +#define EXPAND(...) __VA_ARGS__ +#define FOREACH_0(func) } while (0) +#define FOREACH_1(func, first) func(first); FOREACH_0(func) +#define FOREACH_2(func, first,...) func(first); EXPAND(EXPAND(FOREACH_1)(func, __VA_ARGS__)) +#define FOREACH_3(func, first,...) func(first); EXPAND(EXPAND(FOREACH_2)(func, __VA_ARGS__)) +#define FOREACH_4(func, first,...) func(first); EXPAND(EXPAND(FOREACH_3)(func, __VA_ARGS__)) +#define FOREACH_5(func, first,...) func(first); EXPAND(EXPAND(FOREACH_4)(func, __VA_ARGS__)) +#define FOREACH_6(func, first,...) func(first); EXPAND(EXPAND(FOREACH_5)(func, __VA_ARGS__)) +#define FOREACH_7(func, first,...) func(first); EXPAND(EXPAND(FOREACH_6)(func, __VA_ARGS__)) +#define FOREACH_8(func, first,...) func(first); EXPAND(EXPAND(FOREACH_7)(func, __VA_ARGS__)) +#define foreach(func, ...) do { EXPAND(CONCATENATE(FOREACH_, NARG(__VA_ARGS__))(func, __VA_ARGS__)) +#else #define FOREACH_0(func) } while (0) #define FOREACH_1(func, first) func(first); FOREACH_0(func) #define FOREACH_2(func, first,...) func(first); FOREACH_1(func, __VA_ARGS__) @@ -15,10 +39,7 @@ #define FOREACH_6(func, first,...) func(first); FOREACH_5(func, __VA_ARGS__) #define FOREACH_7(func, first,...) func(first); FOREACH_6(func, __VA_ARGS__) #define FOREACH_8(func, first,...) func(first); FOREACH_7(func, __VA_ARGS__) - -#define CONCAT1(x, y) x##y -#define CONCATENATE(x, y) CONCAT1(x, y) - -#define foreach(func, ...) do { CONCATENATE(FOREACH_,NARG(__VA_ARGS__))(func, __VA_ARGS__) +#define foreach(func, ...) do { CONCATENATE(FOREACH_, NARG(__VA_ARGS__))(func, __VA_ARGS__) +#endif #endif diff --git a/src/getopt.c b/src/getopt.c new file mode 100644 index 0000000..cb4f192 --- /dev/null +++ b/src/getopt.c @@ -0,0 +1,51 @@ +/* ***************************************************************** +* +* Copyright 2016 Microsoft +* +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************/ + +#include "getopt.h" +#include + +char* optarg = NULL; +int optind = 1; + +int getopt(int argc, char* const argv[], const char* optstring) +{ + if ((optind >= argc) || (argv[optind][0] != '-') || (argv[optind][0] == 0)) + { + return -1; + } + + int opt = argv[optind][1]; + const char* p = strchr(optstring, opt); + + if (p == NULL) + { + return '?'; + } + if (p[1] == ':') + { + optind++; + if (optind >= argc) + { + return '?'; + } + optarg = argv[optind]; + optind++; + } + return opt; +} diff --git a/src/getopt.h b/src/getopt.h new file mode 100644 index 0000000..b9a1e72 --- /dev/null +++ b/src/getopt.h @@ -0,0 +1,85 @@ +/* ***************************************************************** +* +* Copyright 2016 Microsoft +* +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************/ + +#include + +#ifndef GETOPT_H__ +#define GETOPT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + int getopt(int argc, char* const argv[], const char* optstring); + + + /* ***************************************************************** +* +* Copyright 2016 Microsoft +* +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************/ + + char* optarg = NULL; + int optind = 1; + + int getopt(int argc, char* const argv[], const char* optstring) + { + if ((optind >= argc) || (argv[optind][0] != '-') || (argv[optind][0] == 0)) + { + return -1; + } + + int opt = argv[optind][1]; + const char* p = strchr(optstring, opt); + + if (p == NULL) + { + return '?'; + } + if (p[1] == ':') + { + optind++; + if (optind >= argc) + { + return '?'; + } + optarg = argv[optind]; + optind++; + } + return opt; + } + +#ifdef __cplusplus +} +#endif + +#endif -- cgit