fix(msvc): add a simple getopt() implementation
This commit is contained in:
parent
7f920d9d37
commit
93374bb2bc
2 changed files with 106 additions and 6 deletions
|
|
@ -170,7 +170,7 @@ if(VM_UNCHECKED)
|
|||
set(LEAN_EXTRA_CXX_FLAGS "${LEAN_EXTRA_CXX_FLAGS} -D LEAN_VM_UNCHECKED")
|
||||
endif()
|
||||
|
||||
if(AUTO_THREAD_FINALIZATION)
|
||||
if(AUTO_THREAD_FINALIZATION AND NOT MSVC)
|
||||
set(LEAN_EXTRA_CXX_FLAGS "${LEAN_EXTRA_CXX_FLAGS} -D LEAN_AUTO_THREAD_FINALIZATION")
|
||||
endif()
|
||||
|
||||
|
|
@ -241,9 +241,8 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
|||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
set(LEAN_EXTRA_LINKER_FLAGS "${LEAN_EXTRA_LINKER_FLAGS} -stdlib=libc++")
|
||||
endif ()
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
|
||||
elseif (MSVC)
|
||||
# All good. Maybe enforce a recent version?
|
||||
set(IS_MSVC 1)
|
||||
set(CMAKE_CXX_FLAGS "/GL /EHsc /W1 ${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "/Od ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "/Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
|
||||
|
|
@ -256,7 +255,7 @@ else()
|
|||
message(FATAL_ERROR "Unsupported compiler: ${CMAKE_CXX_COMPILER_ID}")
|
||||
endif ()
|
||||
|
||||
if (NOT DEFINED IS_MSVC)
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g3 ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os ${CMAKE_CXX_FLAGS_MINSIZEREL}")
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ Author: Leonardo de Moura
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <signal.h>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <getopt.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
|
@ -50,7 +50,11 @@ Author: Leonardo de Moura
|
|||
#include "init/init.h"
|
||||
#include "shell/simple_pos_info_provider.h"
|
||||
#include "shell/leandoc.h"
|
||||
#ifndef _MSC_VER
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#define STDOUT_FILENO 1
|
||||
#else
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined(LEAN_JSON)
|
||||
|
|
@ -61,6 +65,103 @@ Author: Leonardo de Moura
|
|||
#endif
|
||||
#include "githash.h" // NOLINT
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// extremely simple implementation of getopt.h
|
||||
enum arg_opt { no_argument, required_argument, optional_argument };
|
||||
|
||||
struct option {
|
||||
const char name[12];
|
||||
arg_opt has_arg;
|
||||
int *flag;
|
||||
char val;
|
||||
};
|
||||
|
||||
static char *optarg;
|
||||
static int optind = 1;
|
||||
|
||||
int getopt_long(int argc, char *in_argv[], const char *optstring, const option *opts, int *index) {
|
||||
optarg = nullptr;
|
||||
if (optind >= argc)
|
||||
return -1;
|
||||
|
||||
char *argv = in_argv[optind];
|
||||
if (argv[0] != '-') {
|
||||
// find first -opt if any
|
||||
int i = optind;
|
||||
bool found = false;
|
||||
for (; i < argc; ++i) {
|
||||
if (in_argv[i][0] == '-') {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return -1;
|
||||
auto next = in_argv[i];
|
||||
// FIXME: this doesn't account for long options with arguments like --foo arg
|
||||
memmove(&in_argv[optind + 1], &in_argv[optind], (i - optind) * sizeof(argv));
|
||||
argv = in_argv[optind] = next;
|
||||
}
|
||||
++optind;
|
||||
|
||||
// long option
|
||||
if (argv[1] == '-') {
|
||||
auto eq = strchr(argv, '=');
|
||||
size_t sz = (eq ? (eq - argv) : strlen(argv)) - 2;
|
||||
for (auto I = opts; *I->name; ++I) {
|
||||
if (!strncmp(I->name, argv + 2, sz) && I->name[sz] == '\0') {
|
||||
assert(!I->flag);
|
||||
switch (I->has_arg) {
|
||||
case no_argument:
|
||||
if (eq) {
|
||||
std::cerr << in_argv[0] << ": option doesn't take an argument -- " << I->name << std::endl;
|
||||
return '?';
|
||||
}
|
||||
break;
|
||||
case required_argument:
|
||||
if (eq) {
|
||||
optarg = eq + 1;
|
||||
} else {
|
||||
if (optind >= argc) {
|
||||
std::cerr << in_argv[0] << ": option requires an argument -- " << I->name << std::endl;
|
||||
return '?';
|
||||
}
|
||||
optarg = in_argv[optind++];
|
||||
}
|
||||
break;
|
||||
case optional_argument:
|
||||
if (eq) {
|
||||
optarg = eq + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*index = I - opts;
|
||||
return I->val;
|
||||
}
|
||||
}
|
||||
return '?';
|
||||
} else {
|
||||
auto opt = strchr(optstring, argv[1]);
|
||||
if (!opt)
|
||||
return '?';
|
||||
|
||||
if (opt[1] == ':') {
|
||||
if (argv[2] == '\0') {
|
||||
if (optind < argc) {
|
||||
optarg = in_argv[optind++];
|
||||
} else {
|
||||
std::cerr << in_argv[0] << ": option requires an argument -- " << *opt << std::endl;
|
||||
return '?';
|
||||
}
|
||||
} else {
|
||||
optarg = argv + 2;
|
||||
}
|
||||
}
|
||||
return *opt;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
using namespace lean; // NOLINT
|
||||
|
||||
#ifndef LEAN_SERVER_DEFAULT_MAX_MEMORY
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue