diff options
| author | Aiden Woodruff <aiden.woodruff@gmail.com> | 2019-09-18 22:51:25 -0500 |
|---|---|---|
| committer | Aiden Woodruff <aiden.woodruff@gmail.com> | 2019-09-18 22:51:25 -0500 |
| commit | f64ebb50da3a74b9060f1616d05b1e25e0503798 (patch) | |
| tree | 7c2a843291308ea3466ae4e970d01b6817e5ce23 | |
| parent | 176647fc5eb719953aa3961f39b3311e3368ce6a (diff) | |
| download | life-f64ebb50da3a74b9060f1616d05b1e25e0503798.tar.gz life-f64ebb50da3a74b9060f1616d05b1e25e0503798.tar.bz2 life-f64ebb50da3a74b9060f1616d05b1e25e0503798.zip | |
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).
| -rw-r--r-- | .gitignore | 7 | ||||
| -rw-r--r-- | CMakeLists.txt | 133 | ||||
| -rw-r--r-- | cmakeconfig.h.in | 131 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/correct_curses.h | 24 | ||||
| -rw-r--r-- | src/foreach.h | 37 | ||||
| -rw-r--r-- | src/getopt.c | 51 | ||||
| -rw-r--r-- | src/getopt.h | 85 |
8 files changed, 466 insertions, 8 deletions
| @@ -1,3 +1,10 @@ | |||
| 1 | # Ignore backups | 1 | # Ignore backups |
| 2 | *~ | 2 | *~ |
| 3 | \#*# | 3 | \#*# |
| 4 | |||
| 5 | # cmake build dir | ||
| 6 | out/ | ||
| 7 | build/ | ||
| 8 | |||
| 9 | # Visual Studio | ||
| 10 | .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 @@ | |||
| 1 | cmake_minimum_required(VERSION 3.8) | ||
| 2 | project(life VERSION 0.0 LANGUAGES C) | ||
| 3 | set(CMAKE_C_STANDARD 99) | ||
| 4 | set(CMAKE_C_STANDARD_REQUIRED YES) | ||
| 5 | # cmake_policy(SET CMP0067 NEW) # Use c++ standard in try_compile checks | ||
| 6 | |||
| 7 | # Macros and stuff | ||
| 8 | include(CheckIncludeFile) | ||
| 9 | include(CheckCCompilerFlag) | ||
| 10 | include(CheckSymbolExists) | ||
| 11 | include(CheckTypeSize) | ||
| 12 | include(CMakePushCheckState) | ||
| 13 | |||
| 14 | # CXX Compile Features options | ||
| 15 | if ($<COMPILE_FEATURES:c_function_prototypes>) | ||
| 16 | set(HAVE_AUTO_RETURN YES) | ||
| 17 | endif() | ||
| 18 | |||
| 19 | # Settable options, i.e. to fix issues on VisualStudio | ||
| 20 | set(EXTRA_GLOBAL_OPTIONS "" CACHE STRING "Extra options to set") | ||
| 21 | set(EXTRA_LINKER_OPTIONS "" CACHE STRING "Extra linker options to set") | ||
| 22 | add_compile_options(${EXTRA_GLOBAL_OPTIONS}) | ||
| 23 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${EXTRA_LINKER_OPTIONS}") | ||
| 24 | |||
| 25 | option(USE_PDCURSES "Use PDCurses") | ||
| 26 | if (USE_PDCURSES) | ||
| 27 | set(PDCURSES_SRCDIR "C:/PDCurses" CACHE FILEPATH "PDCurses' Source Directory") | ||
| 28 | set(PDCURSES_LIBRARIES "C:/PDCurses/wincon/pdcurses.lib" CACHE FILEPATH "PDCurses Library") | ||
| 29 | else() | ||
| 30 | find_package(Curses REQUIRED) | ||
| 31 | endif() | ||
| 32 | |||
| 33 | # Large number of compiler flags (but not unreasonable, i.e. not VS's -Wall) | ||
| 34 | check_c_compiler_flag(-W4 HAVE_W4) | ||
| 35 | if (HAVE_W4) | ||
| 36 | add_compile_options(-W4) | ||
| 37 | else() | ||
| 38 | check_c_compiler_flag(-Wall HAVE_WALL) | ||
| 39 | check_c_compiler_flag(-Wextra HAVE_WEXTRA) | ||
| 40 | check_c_compiler_flag(-pedantic HAVE_PEDANTIC) | ||
| 41 | endif() | ||
| 42 | if ("$<CONFIG:Debug>" OR "$<CONFIG:x64-Debug>" OR "$<CONFIG:x86-Debug>") | ||
| 43 | add_compile_options("$<$<BOOL:${HAVE_WALL}>:-Wall>" "$<$<BOOL:${HAVE_WEXTRA}>:-Wextra>" "$<$<BOOL:${HAVE_PEDANTIC}>:-pedantic>") | ||
| 44 | # else() | ||
| 45 | # set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") | ||
| 46 | endif() | ||
| 47 | |||
| 48 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||
| 49 | |||
| 50 | # Set some variables to match autoconf ones | ||
| 51 | set(PACKAGE_NAME ${PROJECT_NAME}) | ||
| 52 | string(TOLOWER ${PACKAGE_NAME} PACKAGE) | ||
| 53 | set(PACKAGE_VERSION ${PROJECT_VERSION}) | ||
| 54 | string(CONCAT PACKAGE_STRING ${PACKAGE_NAME} " " ${VERSION}) | ||
| 55 | set(PACKAGE_BUGREPORT aiden.woodruff@gmail.com) | ||
| 56 | set(PACKAGE_URL ${HOMEPAGE_URL}) | ||
| 57 | |||
| 58 | # Check for headers | ||
| 59 | check_include_file(inttypes.h HAVE_INTTYPES_H) | ||
| 60 | check_include_file(memory.h HAVE_MEMORY_H) | ||
| 61 | check_include_file(stdint.h HAVE_STDINT_H) | ||
| 62 | check_include_file(stdlib.h HAVE_STDLIB_H) | ||
| 63 | check_include_file(string.h HAVE_STRING_H) | ||
| 64 | check_include_file(strings.h HAVE_STRINGS_H) | ||
| 65 | check_include_file(sys/stat.h HAVE_SYS_STAT_H) | ||
| 66 | check_include_file(sys/types.h HAVE_SYS_TYPES_H) | ||
| 67 | check_include_file(unistd.h HAVE_UNISTD_H) | ||
| 68 | |||
| 69 | # Check for libraries | ||
| 70 | |||
| 71 | |||
| 72 | # Set options similar to autoconf ones based off FindCurses's flags | ||
| 73 | if (USE_PDCURSES) | ||
| 74 | # Change PDCurses options to match FindCurses ones | ||
| 75 | message(STATUS "Using PDCurses") | ||
| 76 | set(CURSES_INCLUDE_DIRS ${PDCURSES_SRCDIR}) | ||
| 77 | set(CURSES_LIBRARIES ${PDCURSES_LIBRARIES}) | ||
| 78 | set(HAVE_CURSES YES) | ||
| 79 | set(HAVE_CURSES_H YES) | ||
| 80 | else () | ||
| 81 | find_package(Curses) | ||
| 82 | if (CURSES_FOUND) | ||
| 83 | set(HAVE_CURSES ${CURSES_FOUND}) | ||
| 84 | set(HAVE_CURSES_H ${CURSES_HAVE_CURSES_H}) | ||
| 85 | set(HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H}) | ||
| 86 | set(HAVE_NCURSES_CURSES_H ${CURSES_HAVE_NCURSES_CURSES_H}) | ||
| 87 | else() | ||
| 88 | message(FATAL_ERROR "No type of curses has been found. One fix might be to run cmake with the USE_PDCURSES option.") | ||
| 89 | endif () | ||
| 90 | endif () | ||
| 91 | |||
| 92 | # Set the header to include | ||
| 93 | # NOTE: There are a number of other weird ones FindCurses has, but we'll ignore those | ||
| 94 | if (HAVE_NCURSES_CURSES_H) | ||
| 95 | set(CURSES_HEADER "ncurses/curses.h") | ||
| 96 | set(HAVE_NCURSES YES) | ||
| 97 | elseif (HAVE_NCURSES_H) | ||
| 98 | set(CURSES_HEADER "ncurses.h") | ||
| 99 | set(HAVE_NCURSES YES) | ||
| 100 | elseif (HAVE_CURSES_H) | ||
| 101 | set(CURSES_HEADER "curses.h") | ||
| 102 | endif() | ||
| 103 | |||
| 104 | # Check for color support in curses, based off existence of the start_color function | ||
| 105 | if (HAVE_CURSES) | ||
| 106 | set(CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_DIRS}) | ||
| 107 | set(CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARIES}) | ||
| 108 | check_symbol_exists(start_color ${CURSES_HEADER} HAVE_CURSES_COLOR) | ||
| 109 | if (HAVE_CURSES_COLOR) | ||
| 110 | message(STATUS "Found color support for curses") | ||
| 111 | else() | ||
| 112 | message(STATUS "Did NOT find color support for curses") | ||
| 113 | endif() | ||
| 114 | endif() | ||
| 115 | |||
| 116 | find_library(HAVE_MATH m) | ||
| 117 | |||
| 118 | # Check for types | ||
| 119 | cmake_reset_check_state() | ||
| 120 | set(CMAKE_EXTRA_INCLUDE_FILES cstdint) | ||
| 121 | set(CMAKE) | ||
| 122 | check_type_size(int32_t SIZEOF_INT32_T) | ||
| 123 | |||
| 124 | if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.12") | ||
| 125 | add_compile_definitions(HAVE_CMAKECONFIG_H) | ||
| 126 | else() | ||
| 127 | add_compile_options(-DHAVE_CMAKECONFIG_H) | ||
| 128 | endif() | ||
| 129 | configure_file(cmakeconfig.h.in cmakeconfig.h ESCAPE_QUOTES @ONLY) | ||
| 130 | |||
| 131 | add_subdirectory(src) | ||
| 132 | # add_subdirectory(test) | ||
| 133 | |||
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 @@ | |||
| 1 | /* Define to 1 if you have the <cmath> header file. */ | ||
| 2 | #cmakedefine HAVE_CMATH | ||
| 3 | |||
| 4 | /* Define to 1 if you have the <cstdint> header file. */ | ||
| 5 | #cmakedefine HAVE_CSTDINT | ||
| 6 | |||
| 7 | /* Define to 1 if a SysV or X/Open compatible Curses library is present */ | ||
| 8 | #cmakedefine HAVE_CURSES | ||
| 9 | |||
| 10 | /* Define to 1 if library supports color (enhanced functions) */ | ||
| 11 | #cmakedefine HAVE_CURSES_COLOR | ||
| 12 | |||
| 13 | /* Define to 1 if library supports X/Open Enhanced functions */ | ||
| 14 | #undef HAVE_CURSES_ENHANCED | ||
| 15 | |||
| 16 | /* Define to 1 if <curses.h> is present */ | ||
| 17 | #cmakedefine HAVE_CURSES_H | ||
| 18 | |||
| 19 | /* Define to 1 if library supports certain obsolete features */ | ||
| 20 | #undef HAVE_CURSES_OBSOLETE | ||
| 21 | |||
| 22 | /* define if the compiler supports auto return type */ | ||
| 23 | #cmakedefine HAVE_AUTO_RETURN | ||
| 24 | |||
| 25 | /* Define if the compiler supports trailing return type */ | ||
| 26 | #cmakedefine HAVE_TRAILING_RETURN | ||
| 27 | |||
| 28 | #cmakedefine HAVE_NOEXCEPT | ||
| 29 | // My use of 201003 as the date is based off of N3050's date. | ||
| 30 | #if defined(HAVE_NOEXCEPT) || __cplusplus >= 201003L | ||
| 31 | #define my_noexcept noexcept | ||
| 32 | #else | ||
| 33 | #define my_noexcept throw() | ||
| 34 | #endif | ||
| 35 | |||
| 36 | /* Define to 1 if you have the <functional> header file. */ | ||
| 37 | #cmakedefine HAVE_FUNCTIONAL | ||
| 38 | |||
| 39 | /* Define to 1 if you have the <inttypes.h> header file. */ | ||
| 40 | #cmakedefine HAVE_INTTYPES_H | ||
| 41 | |||
| 42 | /* Define to 1 if you have the <iostream> header file. */ | ||
| 43 | #cmakedefine HAVE_IOSTREAM | ||
| 44 | |||
| 45 | /* Define to 1 if you have the <memory.h> header file. */ | ||
| 46 | #cmakedefine HAVE_MEMORY_H | ||
| 47 | |||
| 48 | /* Define to 1 if the Ncurses library is present */ | ||
| 49 | #cmakedefine HAVE_NCURSES | ||
| 50 | |||
| 51 | /* Define to 1 if the NcursesW library is present */ | ||
| 52 | #undef HAVE_NCURSESW | ||
| 53 | |||
| 54 | /* Define to 1 if <ncursesw/curses.h> is present */ | ||
| 55 | #undef HAVE_NCURSESW_CURSES_H | ||
| 56 | |||
| 57 | /* Define to 1 if <ncursesw.h> is present */ | ||
| 58 | #undef HAVE_NCURSESW_H | ||
| 59 | |||
| 60 | /* Define to 1 if <ncurses/curses.h> is present */ | ||
| 61 | #cmakedefine HAVE_NCURSES_CURSES_H | ||
| 62 | |||
| 63 | /* Define to 1 if <ncurses.h> is present */ | ||
| 64 | #cmakedefine HAVE_NCURSES_H | ||
| 65 | |||
| 66 | /* Define to 1 if you have the <random> header file. */ | ||
| 67 | #cmakedefine HAVE_RANDOM | ||
| 68 | |||
| 69 | /* Define to 1 if you have the <stdint.h> header file. */ | ||
| 70 | #cmakedefine HAVE_STDINT_H | ||
| 71 | |||
| 72 | /* Define to 1 if you have the <stdlib.h> header file. */ | ||
| 73 | #cmakedefine HAVE_STDLIB_H | ||
| 74 | |||
| 75 | /* Define to 1 if you have the <string> header file. */ | ||
| 76 | #cmakedefine HAVE_STRING | ||
| 77 | |||
| 78 | /* Define to 1 if you have the <strings.h> header file. */ | ||
| 79 | #cmakedefine HAVE_STRINGS_H | ||
| 80 | |||
| 81 | /* Define to 1 if you have the <string.h> header file. */ | ||
| 82 | #cmakedefine HAVE_STRING_H | ||
| 83 | |||
| 84 | /* Define to 1 if you have the <sys/stat.h> header file. */ | ||
| 85 | #cmakedefine HAVE_SYS_STAT_H | ||
| 86 | |||
| 87 | /* Define to 1 if you have the <sys/types.h> header file. */ | ||
| 88 | #cmakedefine HAVE_SYS_TYPES_H | ||
| 89 | |||
| 90 | /* Define to 1 if you have the <unistd.h> header file. */ | ||
| 91 | #cmakedefine HAVE_UNISTD_H | ||
| 92 | |||
| 93 | /* Name of package */ | ||
| 94 | #cmakedefine PACKAGE | ||
| 95 | |||
| 96 | /* Define to the address where bug reports for this package should be sent. */ | ||
| 97 | #cmakedefine PACKAGE_BUGREPORT | ||
| 98 | |||
| 99 | /* Define to the full name of this package. */ | ||
| 100 | #cmakedefine PACKAGE_NAME | ||
| 101 | |||
| 102 | /* Define to the full name and version of this package. */ | ||
| 103 | #cmakedefine PACKAGE_STRING | ||
| 104 | |||
| 105 | /* Define to the one symbol short name of this package. */ | ||
| 106 | #undef PACKAGE_TARNAME | ||
| 107 | |||
| 108 | /* Define to the home page for this package. */ | ||
| 109 | #cmakedefine PACKAGE_URL | ||
| 110 | |||
| 111 | /* Define to the version of this package. */ | ||
| 112 | #cmakedefine PACKAGE_VERSION | ||
| 113 | |||
| 114 | /* Define to 1 if you have the ANSI C header files. */ | ||
| 115 | #undef STDC_HEADERS | ||
| 116 | |||
| 117 | /* Version number of package */ | ||
| 118 | #ifdef PACKAGE_VERSION | ||
| 119 | #define VERSION PACKAGE_VERSION | ||
| 120 | #else | ||
| 121 | #undef VERSION | ||
| 122 | #endif | ||
| 123 | |||
| 124 | #cmakedefine HAVE_SIZEOF_INT32_T | ||
| 125 | @SIZEOF_INT32_T_CODE@ | ||
| 126 | |||
| 127 | // Technically the standard doesn't require int32_t. But it does require int_fast32_t. We'll just prefer speed (over size). | ||
| 128 | #if !(defined(HAVE_SIZEOF_INT32_T) && SIZEOF_INT32_T == 4) | ||
| 129 | #define int32_t int_fast32_t | ||
| 130 | #endif | ||
| 131 | |||
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 @@ | |||
| 1 | # Makefile stuff | ||
| 2 | include_directories(.) | ||
| 3 | add_executable(life life.c life.h updatemap.c updatemap.h menus.c menus.h) | ||
| 4 | target_compile_features(life PUBLIC c_function_prototypes c_variadic_macros) | ||
| 5 | target_include_directories(life PRIVATE "${CURSES_INCLUDE_DIRS}") | ||
| 6 | 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 @@ | |||
| 1 | #ifndef GRAPH_CORRECT_CURSES_H | ||
| 2 | #define GRAPH_CORRECT_CURSES_H | ||
| 3 | #if defined(HAVE_CMAKECONFIG_H) | ||
| 4 | #include <cmakeconfig.h> | ||
| 5 | |||
| 6 | #if defined HAVE_NCURSESW_CURSES_H | ||
| 7 | # include <ncursesw/curses.h> | ||
| 8 | #elif defined HAVE_NCURSESW_H | ||
| 9 | # include <ncursesw.h> | ||
| 10 | #elif defined HAVE_NCURSES_CURSES_H | ||
| 11 | # include <ncurses/curses.h> | ||
| 12 | #elif defined HAVE_NCURSES_H | ||
| 13 | # include <ncurses.h> | ||
| 14 | #elif defined HAVE_CURSES_H | ||
| 15 | # include <curses.h> | ||
| 16 | #else | ||
| 17 | # error "SysV or X/Open-compatible Curses header file required" | ||
| 18 | #endif | ||
| 19 | #else | ||
| 20 | |||
| 21 | // Fingers-crossed | ||
| 22 | #include <curses.h> | ||
| 23 | #endif | ||
| 24 | #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 @@ | |||
| 1 | #ifndef NARG | 1 | #ifndef NARG |
| 2 | #define NARG(...) NARG_(__VA_ARGS__, RSEQ_N) | ||
| 3 | #define NARG_(...) NARG_N(__VA_ARGS__) | ||
| 4 | #define RSEQ_N 8, 7, 6, 5, 4, 3, 2, 1, 0 | ||
| 5 | #define NARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N | 2 | #define NARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N |
| 3 | #define RSEQ_N 8, 7, 6, 5, 4, 3, 2, 1, 0 | ||
| 4 | #if _MSC_VER && !__INTEL_COMPILER | ||
| 5 | #define EXPAND(...) __VA_ARGS__ | ||
| 6 | #define NARG_(...) EXPAND(EXPAND(NARG_N) (__VA_ARGS__)) | ||
| 7 | #else | ||
| 8 | #define NARG_(...) NARG_N(__VA_ARGS__) | ||
| 9 | #endif | ||
| 10 | #define NARG(...) NARG_(__VA_ARGS__, RSEQ_N) | ||
| 6 | #endif | 11 | #endif |
| 7 | 12 | ||
| 8 | #ifndef foreach | 13 | #ifndef foreach |
| 14 | |||
| 15 | #define CONCAT2(x, y) x##y | ||
| 16 | #define CONCAT1(x, y) CONCAT2(x,y) | ||
| 17 | #define CONCATENATE(x, y) CONCAT1(x, y) | ||
| 18 | |||
| 19 | #if _MSC_VER && !__INTEL_COMPILER | ||
| 20 | #undef EXPAND | ||
| 21 | #define EXPAND(...) __VA_ARGS__ | ||
| 22 | #define FOREACH_0(func) } while (0) | ||
| 23 | #define FOREACH_1(func, first) func(first); FOREACH_0(func) | ||
| 24 | #define FOREACH_2(func, first,...) func(first); EXPAND(EXPAND(FOREACH_1)(func, __VA_ARGS__)) | ||
| 25 | #define FOREACH_3(func, first,...) func(first); EXPAND(EXPAND(FOREACH_2)(func, __VA_ARGS__)) | ||
| 26 | #define FOREACH_4(func, first,...) func(first); EXPAND(EXPAND(FOREACH_3)(func, __VA_ARGS__)) | ||
| 27 | #define FOREACH_5(func, first,...) func(first); EXPAND(EXPAND(FOREACH_4)(func, __VA_ARGS__)) | ||
| 28 | #define FOREACH_6(func, first,...) func(first); EXPAND(EXPAND(FOREACH_5)(func, __VA_ARGS__)) | ||
| 29 | #define FOREACH_7(func, first,...) func(first); EXPAND(EXPAND(FOREACH_6)(func, __VA_ARGS__)) | ||
| 30 | #define FOREACH_8(func, first,...) func(first); EXPAND(EXPAND(FOREACH_7)(func, __VA_ARGS__)) | ||
| 31 | #define foreach(func, ...) do { EXPAND(CONCATENATE(FOREACH_, NARG(__VA_ARGS__))(func, __VA_ARGS__)) | ||
| 32 | #else | ||
| 9 | #define FOREACH_0(func) } while (0) | 33 | #define FOREACH_0(func) } while (0) |
| 10 | #define FOREACH_1(func, first) func(first); FOREACH_0(func) | 34 | #define FOREACH_1(func, first) func(first); FOREACH_0(func) |
| 11 | #define FOREACH_2(func, first,...) func(first); FOREACH_1(func, __VA_ARGS__) | 35 | #define FOREACH_2(func, first,...) func(first); FOREACH_1(func, __VA_ARGS__) |
| @@ -15,10 +39,7 @@ | |||
| 15 | #define FOREACH_6(func, first,...) func(first); FOREACH_5(func, __VA_ARGS__) | 39 | #define FOREACH_6(func, first,...) func(first); FOREACH_5(func, __VA_ARGS__) |
| 16 | #define FOREACH_7(func, first,...) func(first); FOREACH_6(func, __VA_ARGS__) | 40 | #define FOREACH_7(func, first,...) func(first); FOREACH_6(func, __VA_ARGS__) |
| 17 | #define FOREACH_8(func, first,...) func(first); FOREACH_7(func, __VA_ARGS__) | 41 | #define FOREACH_8(func, first,...) func(first); FOREACH_7(func, __VA_ARGS__) |
| 18 | 42 | #define foreach(func, ...) do { CONCATENATE(FOREACH_, NARG(__VA_ARGS__))(func, __VA_ARGS__) | |
| 19 | #define CONCAT1(x, y) x##y | 43 | #endif |
| 20 | #define CONCATENATE(x, y) CONCAT1(x, y) | ||
| 21 | |||
| 22 | #define foreach(func, ...) do { CONCATENATE(FOREACH_,NARG(__VA_ARGS__))(func, __VA_ARGS__) | ||
| 23 | #endif | 44 | #endif |
| 24 | 45 | ||
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 @@ | |||
| 1 | /* ***************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2016 Microsoft | ||
| 4 | * | ||
| 5 | * | ||
| 6 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 7 | * you may not use this file except in compliance with the License. | ||
| 8 | * You may obtain a copy of the License at | ||
| 9 | * | ||
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | * | ||
| 12 | * Unless required by applicable law or agreed to in writing, software | ||
| 13 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 15 | * See the License for the specific language governing permissions and | ||
| 16 | * limitations under the License. | ||
| 17 | * | ||
| 18 | ******************************************************************/ | ||
| 19 | |||
| 20 | #include "getopt.h" | ||
| 21 | #include <string.h> | ||
| 22 | |||
| 23 | char* optarg = NULL; | ||
| 24 | int optind = 1; | ||
| 25 | |||
| 26 | int getopt(int argc, char* const argv[], const char* optstring) | ||
| 27 | { | ||
| 28 | if ((optind >= argc) || (argv[optind][0] != '-') || (argv[optind][0] == 0)) | ||
| 29 | { | ||
| 30 | return -1; | ||
| 31 | } | ||
| 32 | |||
| 33 | int opt = argv[optind][1]; | ||
| 34 | const char* p = strchr(optstring, opt); | ||
| 35 | |||
| 36 | if (p == NULL) | ||
| 37 | { | ||
| 38 | return '?'; | ||
| 39 | } | ||
| 40 | if (p[1] == ':') | ||
| 41 | { | ||
| 42 | optind++; | ||
| 43 | if (optind >= argc) | ||
| 44 | { | ||
| 45 | return '?'; | ||
| 46 | } | ||
| 47 | optarg = argv[optind]; | ||
| 48 | optind++; | ||
| 49 | } | ||
| 50 | return opt; | ||
| 51 | } | ||
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 @@ | |||
| 1 | /* ***************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2016 Microsoft | ||
| 4 | * | ||
| 5 | * | ||
| 6 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 7 | * you may not use this file except in compliance with the License. | ||
| 8 | * You may obtain a copy of the License at | ||
| 9 | * | ||
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 11 | * | ||
| 12 | * Unless required by applicable law or agreed to in writing, software | ||
| 13 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 15 | * See the License for the specific language governing permissions and | ||
| 16 | * limitations under the License. | ||
| 17 | * | ||
| 18 | ******************************************************************/ | ||
| 19 | |||
| 20 | #include <string.h> | ||
| 21 | |||
| 22 | #ifndef GETOPT_H__ | ||
| 23 | #define GETOPT_H__ | ||
| 24 | |||
| 25 | #ifdef __cplusplus | ||
| 26 | extern "C" { | ||
| 27 | #endif | ||
| 28 | |||
| 29 | int getopt(int argc, char* const argv[], const char* optstring); | ||
| 30 | |||
| 31 | |||
| 32 | /* ***************************************************************** | ||
| 33 | * | ||
| 34 | * Copyright 2016 Microsoft | ||
| 35 | * | ||
| 36 | * | ||
| 37 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 38 | * you may not use this file except in compliance with the License. | ||
| 39 | * You may obtain a copy of the License at | ||
| 40 | * | ||
| 41 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 42 | * | ||
| 43 | * Unless required by applicable law or agreed to in writing, software | ||
| 44 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 45 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 46 | * See the License for the specific language governing permissions and | ||
| 47 | * limitations under the License. | ||
| 48 | * | ||
| 49 | ******************************************************************/ | ||
| 50 | |||
| 51 | char* optarg = NULL; | ||
| 52 | int optind = 1; | ||
| 53 | |||
| 54 | int getopt(int argc, char* const argv[], const char* optstring) | ||
| 55 | { | ||
| 56 | if ((optind >= argc) || (argv[optind][0] != '-') || (argv[optind][0] == 0)) | ||
| 57 | { | ||
| 58 | return -1; | ||
| 59 | } | ||
| 60 | |||
| 61 | int opt = argv[optind][1]; | ||
| 62 | const char* p = strchr(optstring, opt); | ||
| 63 | |||
| 64 | if (p == NULL) | ||
| 65 | { | ||
| 66 | return '?'; | ||
| 67 | } | ||
| 68 | if (p[1] == ':') | ||
| 69 | { | ||
| 70 | optind++; | ||
| 71 | if (optind >= argc) | ||
| 72 | { | ||
| 73 | return '?'; | ||
| 74 | } | ||
| 75 | optarg = argv[optind]; | ||
| 76 | optind++; | ||
| 77 | } | ||
| 78 | return opt; | ||
| 79 | } | ||
| 80 | |||
| 81 | #ifdef __cplusplus | ||
| 82 | } | ||
| 83 | #endif | ||
| 84 | |||
| 85 | #endif | ||
