Replace getopt with ketopt
parent
cfa6a1df53
commit
153ae78ab5
|
@ -145,7 +145,6 @@ if(ENABLE_REDIS OR ENABLE_ANY_DATABASE OR ENABLE_ALL_DATABASES)
|
|||
endif(ENABLE_REDIS OR ENABLE_ANY_DATABASE OR ENABLE_ALL_DATABASES)
|
||||
|
||||
# Schließen Sie Unterprojekte ein.
|
||||
#add_subdirectory ("wingetopt")
|
||||
add_subdirectory ("Minetestmapper")
|
||||
|
||||
message(STATUS "VCPKG_APPLOCAL_DEPS: ${VCPKG_APPLOCAL_DEPS}")
|
||||
|
|
|
@ -45,6 +45,7 @@ set(sources
|
|||
db-redis.h
|
||||
db-sqlite3.cpp
|
||||
db-sqlite3.h
|
||||
ketopt.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
|
@ -59,16 +60,8 @@ find_library(LIBGD_LIBRARY NAMES gd libgd libgd_static)
|
|||
find_path(LIBGD_INCLUDE_DIR NAMES gd.h)
|
||||
|
||||
if(WIN32)
|
||||
include_directories(../wingetopt/src/)
|
||||
find_path(SYSTEM_INCLUDE_DIR dirent.h)
|
||||
include_directories(${SYSTEM_INCLUDE_DIR})
|
||||
|
||||
add_library (wingetopt STATIC ../wingetopt/src/getopt.c)
|
||||
endif()
|
||||
|
||||
set(wingetopt_lib "")
|
||||
if(WIN32)
|
||||
set(wingetopt_lib wingetopt)
|
||||
endif()
|
||||
|
||||
set(leveldb_lib "")
|
||||
|
@ -95,11 +88,10 @@ if(USE_REDIS)
|
|||
endif()
|
||||
|
||||
|
||||
#link_directories (../wingetopt)
|
||||
# Fügen Sie der ausführbaren Datei für dieses Projekt eine Quelle hinzu.
|
||||
add_executable (Minetestmapper ${sources})
|
||||
set_target_properties(Minetestmapper PROPERTIES COMPILE_FLAGS -DBUILDER_STATIC_DEFINE)
|
||||
target_link_libraries(Minetestmapper ${wingetopt_lib} ${LIBGD_LIBRARY} ${ZLIB_LIBRARY} ${SQLITE3_LIBRARY} ${leveldb_lib} ${postgresql_lib} ${redis_lib})
|
||||
target_link_libraries(Minetestmapper ${LIBGD_LIBRARY} ${ZLIB_LIBRARY} ${SQLITE3_LIBRARY} ${leveldb_lib} ${postgresql_lib} ${redis_lib})
|
||||
# TODO: Fügen Sie bei Bedarf Tests und Installationsziele hinzu.
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <getopt.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
@ -30,6 +29,7 @@
|
|||
#include "porting.h"
|
||||
#include "util.h"
|
||||
#include "version.h"
|
||||
#include "ketopt.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
@ -50,79 +50,80 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
auto begin = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// TODO: Get rid of getopt and use a proper cmdarg parsing lib or write something own.
|
||||
static struct option long_options[] =
|
||||
static ko_longopt_t long_options[] =
|
||||
{
|
||||
{ "help", no_argument, nullptr, 'h' },
|
||||
{ "version", no_argument, nullptr, 'V' },
|
||||
{ "input", required_argument, nullptr, 'i' },
|
||||
{ "output", required_argument, nullptr, 'o' },
|
||||
{ "colors", required_argument, nullptr, 'C' },
|
||||
{ "heightmap-nodes", required_argument, nullptr, OPT_HEIGHTMAPNODESFILE },
|
||||
{ "heightmap-colors", required_argument, nullptr, OPT_HEIGHTMAPCOLORSFILE },
|
||||
{ "heightmap", optional_argument, nullptr, OPT_HEIGHTMAP },
|
||||
{ "heightmap-yscale", required_argument, nullptr, OPT_HEIGHTMAPYSCALE },
|
||||
{ "height-level-0", required_argument, nullptr, OPT_HEIGHT_LEVEL0 },
|
||||
{ "bgcolor", required_argument, nullptr, 'b' },
|
||||
{ "blockcolor", required_argument, nullptr, OPT_BLOCKCOLOR },
|
||||
{ "scalecolor", required_argument, nullptr, 's' },
|
||||
{ "origincolor", required_argument, nullptr, 'r' },
|
||||
{ "playercolor", required_argument, nullptr, 'p' },
|
||||
{ "draworigin", no_argument, nullptr, 'R' },
|
||||
{ "drawplayers", no_argument, nullptr, 'P' },
|
||||
{ "drawscale", optional_argument, nullptr, 'S' },
|
||||
{ "sidescale-interval", required_argument, nullptr, OPT_SCALEINTERVAL },
|
||||
{ "drawheightscale", no_argument, nullptr, OPT_DRAWHEIGHTSCALE },
|
||||
{ "heightscale-interval", required_argument, nullptr, OPT_SCALEINTERVAL },
|
||||
{ "drawalpha", optional_argument, nullptr, 'e' },
|
||||
{ "drawair", no_argument, nullptr, OPT_DRAWAIR },
|
||||
{ "drawnodes", required_argument, nullptr, OPT_DRAWNODES },
|
||||
{ "ignorenodes", required_argument, nullptr, OPT_DRAWNODES },
|
||||
{ "drawpoint", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawline", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawcircle", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawellipse", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawrectangle", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawarrow", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawtext", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawmappoint", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawmapline", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawmapcircle", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawmapellipse", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawmaprectangle", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawmaparrow", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "drawmaptext", required_argument, nullptr, OPT_DRAW_OBJECT },
|
||||
{ "noshading", no_argument, nullptr, 'H' },
|
||||
{ "geometry", required_argument, nullptr, 'g' },
|
||||
{ "cornergeometry", required_argument, nullptr, 'g' },
|
||||
{ "centergeometry", required_argument, nullptr, 'g' },
|
||||
{ "geometrymode", required_argument, nullptr, 'G' },
|
||||
{ "forcegeometry", no_argument, nullptr, 'G' },
|
||||
{ "min-y", required_argument, nullptr, 'a' },
|
||||
{ "max-y", required_argument, nullptr, 'c' },
|
||||
{ "backend", required_argument, nullptr, 'd' },
|
||||
{ "disable-blocklist-prefetch", optional_argument, nullptr, OPT_NO_BLOCKLIST_PREFETCH },
|
||||
{ "database-format", required_argument, nullptr, OPT_DATABASE_FORMAT },
|
||||
{ "prescan-world", required_argument, nullptr, OPT_PRESCAN_WORLD },
|
||||
{ "sqlite-cacheworldrow", no_argument, nullptr, OPT_SQLITE_CACHEWORLDROW },
|
||||
{ "sqlite3-limit-prescan-query-size", optional_argument, nullptr, OPT_SQLITE_LIMIT_PRESCAN_QUERY },
|
||||
{ "tiles", required_argument, nullptr, 't' },
|
||||
{ "tileorigin", required_argument, nullptr, 'T' },
|
||||
{ "tilecenter", required_argument, nullptr, 'T' },
|
||||
{ "tilebordercolor", required_argument, nullptr, 'B' },
|
||||
{ "scalefactor", required_argument, nullptr, OPT_SCALEFACTOR },
|
||||
{ "chunksize", required_argument, nullptr, OPT_CHUNKSIZE },
|
||||
{ "silence-suggestions", required_argument, nullptr, OPT_SILENCE_SUGGESTIONS },
|
||||
{ "verbose", optional_argument, nullptr, 'v' },
|
||||
{ "verbose-search-colors", optional_argument, nullptr, OPT_VERBOSE_SEARCH_COLORS },
|
||||
{ "progress", no_argument, nullptr, OPT_PROGRESS_INDICATOR },
|
||||
{ nullptr, 0, nullptr, 0 }
|
||||
{ "help", ko_no_argument, 'h' },
|
||||
{ "version", ko_no_argument, 'V' },
|
||||
{ "input", ko_required_argument, 'i' },
|
||||
{ "output", ko_required_argument, 'o' },
|
||||
{ "colors", ko_required_argument, 'C' },
|
||||
{ "heightmap-nodes", ko_required_argument, OPT_HEIGHTMAPNODESFILE },
|
||||
{ "heightmap-colors", ko_required_argument, OPT_HEIGHTMAPCOLORSFILE },
|
||||
{ "heightmap", ko_optional_argument, OPT_HEIGHTMAP },
|
||||
{ "heightmap-yscale", ko_required_argument, OPT_HEIGHTMAPYSCALE },
|
||||
{ "height-level-0", ko_required_argument, OPT_HEIGHT_LEVEL0 },
|
||||
{ "bgcolor", ko_required_argument, 'b' },
|
||||
{ "blockcolor", ko_required_argument, OPT_BLOCKCOLOR },
|
||||
{ "scalecolor", ko_required_argument, 's' },
|
||||
{ "origincolor", ko_required_argument, 'r' },
|
||||
{ "playercolor", ko_required_argument, 'p' },
|
||||
{ "draworigin", ko_no_argument, 'R' },
|
||||
{ "drawplayers", ko_no_argument, 'P' },
|
||||
{ "drawscale", ko_optional_argument, 'S' },
|
||||
{ "sidescale-interval", ko_required_argument, OPT_SCALEINTERVAL },
|
||||
{ "drawheightscale", ko_no_argument, OPT_DRAWHEIGHTSCALE },
|
||||
{ "heightscale-interval", ko_required_argument, OPT_SCALEINTERVAL },
|
||||
{ "drawalpha", ko_optional_argument, 'e' },
|
||||
{ "drawair", ko_no_argument, OPT_DRAWAIR },
|
||||
{ "drawnodes", ko_required_argument, OPT_DRAWNODES },
|
||||
{ "ignorenodes", ko_required_argument, OPT_DRAWNODES },
|
||||
{ "drawpoint", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawline", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawcircle", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawellipse", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawrectangle", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawarrow", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawtext", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawmappoint", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawmapline", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawmapcircle", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawmapellipse", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawmaprectangle", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawmaparrow", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "drawmaptext", ko_required_argument, OPT_DRAW_OBJECT },
|
||||
{ "noshading", ko_no_argument, 'H' },
|
||||
{ "geometry", ko_required_argument, 'g' },
|
||||
{ "cornergeometry", ko_required_argument, 'g' },
|
||||
{ "centergeometry", ko_required_argument, 'g' },
|
||||
{ "geometrymode", ko_required_argument, 'G' },
|
||||
{ "forcegeometry", ko_no_argument, 'G' },
|
||||
{ "min-y", ko_required_argument, 'a' },
|
||||
{ "max-y", ko_required_argument, 'c' },
|
||||
{ "backend", ko_required_argument, 'd' },
|
||||
{ "disable-blocklist-prefetch", ko_optional_argument, OPT_NO_BLOCKLIST_PREFETCH },
|
||||
{ "database-format", ko_required_argument, OPT_DATABASE_FORMAT },
|
||||
{ "prescan-world", ko_required_argument, OPT_PRESCAN_WORLD },
|
||||
{ "sqlite-cacheworldrow", ko_no_argument, OPT_SQLITE_CACHEWORLDROW },
|
||||
{ "sqlite3-limit-prescan-query-size", ko_optional_argument, OPT_SQLITE_LIMIT_PRESCAN_QUERY },
|
||||
{ "tiles", ko_required_argument, 't' },
|
||||
{ "tileorigin", ko_required_argument, 'T' },
|
||||
{ "tilecenter", ko_required_argument, 'T' },
|
||||
{ "tilebordercolor", ko_required_argument, 'B' },
|
||||
{ "scalefactor", ko_required_argument, OPT_SCALEFACTOR },
|
||||
{ "chunksize", ko_required_argument, OPT_CHUNKSIZE },
|
||||
{ "silence-suggestions", ko_required_argument, OPT_SILENCE_SUGGESTIONS },
|
||||
{ "verbose", ko_optional_argument, 'v' },
|
||||
{ "verbose-search-colors", ko_optional_argument, OPT_VERBOSE_SEARCH_COLORS },
|
||||
{ "progress", ko_no_argument, OPT_PROGRESS_INDICATOR },
|
||||
{ nullptr, 0, 0 }
|
||||
};
|
||||
|
||||
try {
|
||||
int option_index = 0;
|
||||
//int option_index = 0;
|
||||
ketopt_t opt = KETOPT_INIT;
|
||||
int c = 0;
|
||||
while (true) {
|
||||
c = getopt_long(argc, argv, "hi:o:", long_options, &option_index);
|
||||
c = ketopt(&opt, argc, argv, 0, "hi:o:", long_options);
|
||||
if (c == -1) {
|
||||
if (input.empty() || output.empty()) {
|
||||
std::cerr << "Input (world directory) or output (PNG filename) missing" << std::endl;
|
||||
|
@ -132,6 +133,22 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
break;
|
||||
}
|
||||
switch (c) {
|
||||
case '?':
|
||||
if (opt.opt == 0) // Unknown long option
|
||||
std::cerr << "Unknown Option: '" << argv[opt.ind - 1] << "'." << std::endl;
|
||||
else
|
||||
std::cerr << "Unknown Option: '-" << static_cast<char>(opt.opt) << "'." << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
case ':':
|
||||
if (opt.longidx != -1)
|
||||
std::cerr << "Missing Argument: --'" << long_options[opt.longidx].name << "'." << std::endl;
|
||||
else
|
||||
std::cerr << "Missing Argument: -'" << opt.opt << "'." << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
|
@ -141,29 +158,29 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
return 0;
|
||||
break;
|
||||
case 'i':
|
||||
input = optarg;
|
||||
input = opt.arg;
|
||||
break;
|
||||
case 'o':
|
||||
output = optarg;
|
||||
output = opt.arg;
|
||||
break;
|
||||
case 'C':
|
||||
nodeColorsFile = optarg;
|
||||
nodeColorsFile = opt.arg;
|
||||
break;
|
||||
case OPT_HEIGHTMAPNODESFILE:
|
||||
heightMapNodesFile = optarg;
|
||||
heightMapNodesFile = opt.arg;
|
||||
break;
|
||||
case OPT_HEIGHTMAPCOLORSFILE:
|
||||
heightMapColorsFile = optarg;
|
||||
heightMapColorsFile = opt.arg;
|
||||
break;
|
||||
case 'b':
|
||||
generator.setBgColor(Color(optarg, 0));
|
||||
generator.setBgColor(Color(opt.arg, 0));
|
||||
break;
|
||||
case OPT_NO_BLOCKLIST_PREFETCH:
|
||||
if (optarg && *optarg) {
|
||||
if (strlower(optarg) == "force")
|
||||
if (opt.arg && *opt.arg) {
|
||||
if (strlower(opt.arg) == "force")
|
||||
generator.setGenerateNoPrefetch(TileGenerator::BlockListPrefetch::NoPrefetchForced);
|
||||
else {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "'; expected 'force' or nothing." << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name << "'; expected 'force' or nothing." << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -173,54 +190,54 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
break;
|
||||
case OPT_DATABASE_FORMAT: {
|
||||
std::string opt = strlower(optarg);
|
||||
if (opt == "minetest-i64")
|
||||
std::string option = strlower(opt.arg);
|
||||
if (option == "minetest-i64")
|
||||
generator.setDBFormat(BlockPos::I64, false);
|
||||
else if (opt == "freeminer-axyz")
|
||||
else if (option == "freeminer-axyz")
|
||||
generator.setDBFormat(BlockPos::AXYZ, false);
|
||||
else if (opt == "mixed")
|
||||
else if (option == "mixed")
|
||||
generator.setDBFormat(BlockPos::Unknown, false);
|
||||
else if (opt == "query")
|
||||
else if (option == "query")
|
||||
generator.setDBFormat(BlockPos::Unknown, true);
|
||||
else {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': '" << optarg << "'" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name << "': '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case OPT_PRESCAN_WORLD: {
|
||||
std::string opt = strlower(optarg);
|
||||
std::string option = strlower(opt.arg);
|
||||
generator.setGenerateNoPrefetch(TileGenerator::BlockListPrefetch::Prefetch);
|
||||
if (opt == "disabled-force")
|
||||
if (option == "disabled-force")
|
||||
generator.setGenerateNoPrefetch(TileGenerator::BlockListPrefetch::NoPrefetchForced);
|
||||
else if (opt == "disabled")
|
||||
else if (option == "disabled")
|
||||
generator.setGenerateNoPrefetch(TileGenerator::BlockListPrefetch::NoPrefetch);
|
||||
else if (opt == "auto")
|
||||
else if (option == "auto")
|
||||
generator.setScanEntireWorld(false);
|
||||
else if (opt == "full")
|
||||
else if (option == "full")
|
||||
generator.setScanEntireWorld(true);
|
||||
else {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': '" << optarg << "'" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name << "': '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case OPT_SQLITE_LIMIT_PRESCAN_QUERY:
|
||||
if (!optarg || !*optarg) {
|
||||
if (!opt.arg || !*opt.arg) {
|
||||
#ifdef USE_SQLITE3
|
||||
DBSQLite3::setLimitBlockListQuerySize();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (!isdigit(optarg[0])) {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': must be a positive number" << std::endl;
|
||||
if (!isdigit(opt.arg[0])) {
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name << "': must be a positive number" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
#ifdef USE_SQLITE3
|
||||
int size = atoi(optarg);
|
||||
int size = atoi(opt.arg);
|
||||
DBSQLite3::setLimitBlockListQuerySize(size);
|
||||
#endif
|
||||
}
|
||||
|
@ -228,9 +245,9 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
case OPT_HEIGHTMAP:
|
||||
generator.setHeightMap(true);
|
||||
heightMap = true;
|
||||
if (optarg && *optarg) {
|
||||
if (opt.arg && *opt.arg) {
|
||||
loadHeightMapColorsFile = false;
|
||||
std::string color = strlower(optarg);
|
||||
std::string color = strlower(opt.arg);
|
||||
if (color == "grey" || color == "gray")
|
||||
generator.setHeightMapColor(Color(0, 0, 0), Color(255, 255, 255));
|
||||
else if (color == "black")
|
||||
|
@ -246,41 +263,41 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
break;
|
||||
case OPT_HEIGHTMAPYSCALE:
|
||||
if (isdigit(optarg[0]) || ((optarg[0] == '-' || optarg[0] == '+') && isdigit(optarg[1]))) {
|
||||
float scale = static_cast<float>(atof(optarg));
|
||||
if (isdigit(opt.arg[0]) || ((opt.arg[0] == '-' || opt.arg[0] == '+') && isdigit(opt.arg[1]))) {
|
||||
float scale = static_cast<float>(atof(opt.arg));
|
||||
generator.setHeightMapYScale(scale);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': '" << optarg << "'" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name << "': '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case OPT_HEIGHT_LEVEL0:
|
||||
if (isdigit(optarg[0]) || ((optarg[0] == '-' || optarg[0] == '+') && isdigit(optarg[1]))) {
|
||||
int level = atoi(optarg);
|
||||
if (isdigit(opt.arg[0]) || ((opt.arg[0] == '-' || opt.arg[0] == '+') && isdigit(opt.arg[1]))) {
|
||||
int level = atoi(opt.arg);
|
||||
generator.setSeaLevel(level);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': '" << optarg << "'" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name << "': '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
case OPT_BLOCKCOLOR:
|
||||
generator.setBlockDefaultColor(Color(optarg, 0));
|
||||
generator.setBlockDefaultColor(Color(opt.arg, 0));
|
||||
break;
|
||||
case 's':
|
||||
generator.setScaleColor(Color(optarg, 0));
|
||||
generator.setScaleColor(Color(opt.arg, 0));
|
||||
break;
|
||||
case 'r':
|
||||
generator.setOriginColor(Color(optarg, 1));
|
||||
generator.setOriginColor(Color(opt.arg, 1));
|
||||
break;
|
||||
case 'p':
|
||||
generator.setPlayerColor(Color(optarg, 1));
|
||||
generator.setPlayerColor(Color(opt.arg, 1));
|
||||
break;
|
||||
case 'B':
|
||||
generator.setTileBorderColor(Color(optarg, 0));
|
||||
generator.setTileBorderColor(Color(opt.arg, 0));
|
||||
break;
|
||||
case 'R':
|
||||
generator.setDrawOrigin(true);
|
||||
|
@ -289,19 +306,19 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
generator.setDrawPlayers(true);
|
||||
break;
|
||||
case 'S':
|
||||
if (optarg && *optarg) {
|
||||
std::string opt = strlower(optarg);
|
||||
if (opt == "left")
|
||||
if (opt.arg && *opt.arg) {
|
||||
std::string option = strlower(opt.arg);
|
||||
if (option == "left")
|
||||
generator.setDrawScale(DRAWSCALE_LEFT);
|
||||
else if (opt == "top")
|
||||
else if (option == "top")
|
||||
generator.setDrawScale(DRAWSCALE_TOP);
|
||||
else if (opt == "left,top")
|
||||
else if (option == "left,top")
|
||||
generator.setDrawScale(DRAWSCALE_LEFT | DRAWSCALE_TOP);
|
||||
else if (opt == "top,left")
|
||||
else if (option == "top,left")
|
||||
generator.setDrawScale(DRAWSCALE_LEFT | DRAWSCALE_TOP);
|
||||
else {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name
|
||||
<< "': '" << optarg << "' (expected: left,top)" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name
|
||||
<< "': '" << opt.arg << "' (expected: left,top)" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -315,29 +332,29 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
break;
|
||||
case OPT_SCALEINTERVAL: {
|
||||
istringstream arg;
|
||||
arg.str(optarg);
|
||||
arg.str(opt.arg);
|
||||
int major;
|
||||
int minor;
|
||||
char sep;
|
||||
arg >> major;
|
||||
if (major < 0 || !isdigit(*optarg) || arg.fail()) {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name
|
||||
<< "': '" << optarg << "' (expected: <major>[,<minor>]" << std::endl;
|
||||
if (major < 0 || !isdigit(*opt.arg) || arg.fail()) {
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name
|
||||
<< "': '" << opt.arg << "' (expected: <major>[,<minor>]" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
arg >> std::ws >> sep >> std::ws;
|
||||
if (!arg.fail()) {
|
||||
if ((sep != ',' && sep != ':') || !isdigit(arg.peek())) {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name
|
||||
<< "': '" << optarg << "' (expected: <major>[,<minor>]" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name
|
||||
<< "': '" << opt.arg << "' (expected: <major>[,<minor>]" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
arg >> minor;
|
||||
if (minor < 0) {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name
|
||||
<< "': '" << optarg << "' (expected: <major>[,<minor>]" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name
|
||||
<< "': '" << opt.arg << "' (expected: <major>[,<minor>]" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -347,7 +364,7 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
if (minor && sep == ':') {
|
||||
if (major % minor) {
|
||||
std::cerr << long_options[option_index].name << ": Cannot divide major interval in "
|
||||
std::cerr << long_options[opt.ind].name << ": Cannot divide major interval in "
|
||||
<< minor << " subintervals (not divisible)" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -355,25 +372,25 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
if ((minor % major) == 0)
|
||||
minor = 0;
|
||||
if (long_options[option_index].name[0] == 's') {
|
||||
if (long_options[opt.ind].name[0] == 's') {
|
||||
generator.setSideScaleInterval(major, minor);
|
||||
}
|
||||
else if (long_options[option_index].name[0] == 'h') {
|
||||
else if (long_options[opt.ind].name[0] == 'h') {
|
||||
generator.setHeightScaleInterval(major, minor);
|
||||
}
|
||||
else {
|
||||
std::cerr << "Internal error: option " << long_options[option_index].name << " not handled" << std::endl;
|
||||
std::cerr << "Internal error: option " << long_options[opt.ind].name << " not handled" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case OPT_SILENCE_SUGGESTIONS: {
|
||||
for (size_t i = 0; i < strlen(optarg); i++) {
|
||||
optarg[i] = tolower(optarg[i]);
|
||||
if (optarg[i] == ',')
|
||||
optarg[i] = ' ';
|
||||
for (size_t i = 0; i < strlen(opt.arg); i++) {
|
||||
opt.arg[i] = tolower(opt.arg[i]);
|
||||
if (opt.arg[i] == ',')
|
||||
opt.arg[i] = ' ';
|
||||
}
|
||||
std::istringstream iss(optarg);
|
||||
std::istringstream iss(opt.arg);
|
||||
std::string flag;
|
||||
iss >> std::skipws >> flag;
|
||||
while (!iss.fail()) {
|
||||
|
@ -390,18 +407,18 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
#endif
|
||||
}
|
||||
else {
|
||||
std::cerr << "Invalid flag to '" << long_options[option_index].name << "': '" << flag << "'" << std::endl;
|
||||
std::cerr << "Invalid flag to '" << long_options[opt.ind].name << "': '" << flag << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
iss >> flag;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'v':
|
||||
if (optarg && isdigit(optarg[0]) && optarg[1] == '\0') {
|
||||
generator.verboseStatistics = optarg[0] - '0';
|
||||
generator.verboseCoordinates = optarg[0] - '0';
|
||||
if (opt.arg && isdigit(opt.arg[0]) && opt.arg[1] == '\0') {
|
||||
generator.verboseStatistics = opt.arg[0] - '0';
|
||||
generator.verboseCoordinates = opt.arg[0] - '0';
|
||||
}
|
||||
else {
|
||||
generator.verboseStatistics = 1;
|
||||
|
@ -409,8 +426,8 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
break;
|
||||
case OPT_VERBOSE_SEARCH_COLORS:
|
||||
if (optarg && isdigit(optarg[0]) && optarg[1] == '\0') {
|
||||
generator.verboseReadColors = optarg[0] - '0';
|
||||
if (opt.arg && isdigit(opt.arg[0]) && opt.arg[1] == '\0') {
|
||||
generator.verboseReadColors = opt.arg[0] - '0';
|
||||
}
|
||||
else {
|
||||
generator.verboseReadColors++;
|
||||
|
@ -418,20 +435,20 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
break;
|
||||
case 'e':
|
||||
generator.setDrawAlpha(true);
|
||||
if (!optarg || !*optarg)
|
||||
if (!opt.arg || !*opt.arg)
|
||||
PixelAttribute::setMixMode(PixelAttribute::AlphaMixAverage);
|
||||
else if (string(optarg) == "cumulative" || strlower(optarg) == "nodarken")
|
||||
else if (string(opt.arg) == "cumulative" || strlower(opt.arg) == "nodarken")
|
||||
// "nodarken" is supported for backwards compatibility
|
||||
PixelAttribute::setMixMode(PixelAttribute::AlphaMixCumulative);
|
||||
else if (string(optarg) == "darken" || strlower(optarg) == "cumulative-darken")
|
||||
else if (string(opt.arg) == "darken" || strlower(opt.arg) == "cumulative-darken")
|
||||
// "darken" is supported for backwards compatibility
|
||||
PixelAttribute::setMixMode(PixelAttribute::AlphaMixCumulativeDarken);
|
||||
else if (strlower(optarg) == "average")
|
||||
else if (strlower(opt.arg) == "average")
|
||||
PixelAttribute::setMixMode(PixelAttribute::AlphaMixAverage);
|
||||
else if (strlower(optarg) == "none")
|
||||
else if (strlower(opt.arg) == "none")
|
||||
generator.setDrawAlpha(false);
|
||||
else {
|
||||
std::cerr << "Invalid parameter to '" << long_options[option_index].name << "': '" << optarg << "'" << std::endl;
|
||||
std::cerr << "Invalid parameter to '" << long_options[opt.ind].name << "': '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -440,12 +457,12 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
generator.setDrawAir(true);
|
||||
break;
|
||||
case OPT_DRAWNODES: {
|
||||
bool draw = long_options[option_index].name[0] == 'd';
|
||||
for (char *c = optarg; *c; c++) {
|
||||
bool draw = long_options[opt.ind].name[0] == 'd';
|
||||
for (char *c = opt.arg; *c; c++) {
|
||||
*c = tolower(*c);
|
||||
if (*c == ',') *c = ' ';
|
||||
}
|
||||
istringstream iss(optarg);
|
||||
istringstream iss(opt.arg);
|
||||
string flag;
|
||||
iss >> std::skipws >> flag;
|
||||
while (!iss.fail()) {
|
||||
|
@ -461,14 +478,14 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
else if (flag == "air")
|
||||
generator.setDrawAir(enable);
|
||||
else {
|
||||
std::cerr << "Invalid " << long_options[option_index].name << " flag '" << flag << "'" << std::endl;
|
||||
std::cerr << "Invalid " << long_options[opt.ind].name << " flag '" << flag << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
iss >> flag;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'H':
|
||||
generator.setShading(false);
|
||||
break;
|
||||
|
@ -484,48 +501,48 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
break;
|
||||
case 'a': {
|
||||
istringstream iss;
|
||||
iss.str(optarg);
|
||||
iss.str(opt.arg);
|
||||
int miny;
|
||||
iss >> miny;
|
||||
generator.setMinY(miny);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'c': {
|
||||
istringstream iss;
|
||||
iss.str(optarg);
|
||||
iss.str(opt.arg);
|
||||
int maxy;
|
||||
iss >> maxy;
|
||||
generator.setMaxY(maxy);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case OPT_CHUNKSIZE: {
|
||||
istringstream iss;
|
||||
iss.str(optarg);
|
||||
iss.str(opt.arg);
|
||||
int size;
|
||||
iss >> size;
|
||||
if (iss.fail() || size < 0) {
|
||||
std::cerr << "Invalid chunk size (" << optarg << ")" << std::endl;
|
||||
std::cerr << "Invalid chunk size (" << opt.arg << ")" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
generator.setChunkSize(size);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case OPT_SCALEFACTOR: {
|
||||
istringstream arg;
|
||||
arg.str(optarg);
|
||||
arg.str(opt.arg);
|
||||
int one;
|
||||
char colon;
|
||||
int factor = 1;
|
||||
arg >> one >> std::ws;
|
||||
if (arg.fail() || one != 1) {
|
||||
std::cerr << "Invalid scale factor specification (" << optarg << ") - expected: 1:<n>" << std::endl;
|
||||
std::cerr << "Invalid scale factor specification (" << opt.arg << ") - expected: 1:<n>" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!arg.eof()) {
|
||||
arg >> colon >> factor >> std::ws;
|
||||
if (arg.fail() || colon != ':' || factor<0 || !arg.eof()) {
|
||||
std::cerr << "Invalid scale factor specification (" << optarg << ") - expected: 1:<n>" << std::endl;
|
||||
std::cerr << "Invalid scale factor specification (" << opt.arg << ") - expected: 1:<n>" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -536,10 +553,10 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
generator.setScaleFactor(factor);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 't': {
|
||||
istringstream tilesize;
|
||||
tilesize.str(strlower(optarg));
|
||||
tilesize.str(strlower(opt.arg));
|
||||
if (tilesize.str() == "block") {
|
||||
generator.setTileSize(BLOCK_SIZE, BLOCK_SIZE);
|
||||
generator.setTileOrigin(TILECORNER_AT_WORLDCENTER, TILECORNER_AT_WORLDCENTER);
|
||||
|
@ -553,7 +570,7 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
char c;
|
||||
tilesize >> size;
|
||||
if (tilesize.fail() || size<0) {
|
||||
std::cerr << "Invalid tile size specification (" << optarg << ")" << std::endl;
|
||||
std::cerr << "Invalid tile size specification (" << opt.arg << ")" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -561,7 +578,7 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
tilesize >> c >> border;
|
||||
if (!tilesize.fail()) {
|
||||
if (c != '+' || border < 1) {
|
||||
std::cerr << "Invalid tile border size specification (" << optarg << ")" << std::endl;
|
||||
std::cerr << "Invalid tile border size specification (" << opt.arg << ")" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -569,11 +586,11 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'T': {
|
||||
bool origin = long_options[option_index].name[4] == 'o';
|
||||
bool origin = long_options[opt.ind].name[4] == 'o';
|
||||
istringstream iss;
|
||||
iss.str(strlower(optarg));
|
||||
iss.str(strlower(opt.arg));
|
||||
NodeCoord coord;
|
||||
if (iss.str() == "world") {
|
||||
if (origin)
|
||||
|
@ -590,7 +607,7 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
else {
|
||||
bool result = true;
|
||||
if (!parseCoordinates(iss, coord, 2, 0, ',')) {
|
||||
iss.str(optarg);
|
||||
iss.str(opt.arg);
|
||||
result = parseCoordinates(iss, coord, 2, 0, ':');
|
||||
}
|
||||
if (result) {
|
||||
|
@ -604,15 +621,15 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
else {
|
||||
std::cerr << "Invalid " << long_options[option_index].name << " parameter (" << optarg << ")" << std::endl;
|
||||
std::cerr << "Invalid " << long_options[opt.ind].name << " parameter (" << opt.arg << ")" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'G':
|
||||
if (long_options[option_index].name[0] == 'f') {
|
||||
if (long_options[opt.ind].name[0] == 'f') {
|
||||
// '--forcegeometry'
|
||||
// Old behavior - for compatibility.
|
||||
generator.setShrinkGeometry(false);
|
||||
|
@ -620,13 +637,13 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
if (!foundGeometrySpec)
|
||||
generator.setBlockGeometry(true);
|
||||
}
|
||||
else if (optarg && *optarg) {
|
||||
for (char *c = optarg; *c; c++) {
|
||||
else if (opt.arg && *opt.arg) {
|
||||
for (char *c = opt.arg; *c; c++) {
|
||||
*c = tolower(*c);
|
||||
if (*c == ',') *c = ' ';
|
||||
}
|
||||
istringstream iss;
|
||||
iss.str(optarg);
|
||||
iss.str(opt.arg);
|
||||
string flag;
|
||||
iss >> std::skipws >> flag;
|
||||
while (!iss.fail()) {
|
||||
|
@ -654,23 +671,23 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
break;
|
||||
case 'g': {
|
||||
istringstream iss;
|
||||
iss.str(optarg);
|
||||
iss.str(opt.arg);
|
||||
NodeCoord coord1;
|
||||
NodeCoord coord2;
|
||||
bool legacy;
|
||||
FuzzyBool center = FuzzyBool::Maybe;
|
||||
if (long_options[option_index].name[0] == 'c' && long_options[option_index].name[1] == 'e')
|
||||
if (long_options[opt.ind].name[0] == 'c' && long_options[opt.ind].name[1] == 'e')
|
||||
center = FuzzyBool::Yes;
|
||||
if (long_options[option_index].name[0] == 'c' && long_options[option_index].name[1] == 'o')
|
||||
if (long_options[opt.ind].name[0] == 'c' && long_options[opt.ind].name[1] == 'o')
|
||||
center = FuzzyBool::No;
|
||||
if (!parseMapGeometry(iss, coord1, coord2, legacy, center)) {
|
||||
std::cerr << "Invalid geometry specification '" << optarg << "'" << std::endl;
|
||||
std::cerr << "Invalid geometry specification '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// Set defaults
|
||||
if (!foundGeometrySpec) {
|
||||
if (long_options[option_index].name[0] == 'g' && legacy) {
|
||||
if (long_options[opt.ind].name[0] == 'g' && legacy) {
|
||||
// Compatibility when using the option 'geometry'
|
||||
generator.setBlockGeometry(true);
|
||||
generator.setShrinkGeometry(true);
|
||||
|
@ -691,11 +708,11 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
generator.setGeometry(coord1, coord2);
|
||||
foundGeometrySpec = true;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case OPT_DRAW_OBJECT: {
|
||||
TileGenerator::DrawObject drawObject;
|
||||
drawObject.world = long_options[option_index].name[4] != 'm';
|
||||
char object = long_options[option_index].name[4 + (drawObject.world ? 0 : 3)];
|
||||
drawObject.world = long_options[opt.ind].name[4] != 'm';
|
||||
char object = long_options[opt.ind].name[4 + (drawObject.world ? 0 : 3)];
|
||||
switch (object) {
|
||||
case 'p':
|
||||
drawObject.type = TileGenerator::DrawObject::Point;
|
||||
|
@ -718,14 +735,14 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
break;
|
||||
default:
|
||||
std::cerr << "Internal error: unrecognised object ("
|
||||
<< long_options[option_index].name
|
||||
<< long_options[opt.ind].name
|
||||
<< ")" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
istringstream iss;
|
||||
iss.str(optarg);
|
||||
iss.str(opt.arg);
|
||||
NodeCoord coord1;
|
||||
NodeCoord coord2;
|
||||
NodeCoord dimensions;
|
||||
|
@ -739,8 +756,8 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
needDimensions = FuzzyBool::Yes;
|
||||
if (!parseGeometry(iss, coord1, coord2, dimensions, legacy, centered, 2, needDimensions)) {
|
||||
std::cerr << "Invalid drawing geometry specification for "
|
||||
<< long_options[option_index].name
|
||||
<< " '" << optarg << "'" << std::endl;
|
||||
<< long_options[opt.ind].name
|
||||
<< " '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -783,8 +800,8 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
iss >> std::ws >> colorStr;
|
||||
if (iss.fail()) {
|
||||
std::cerr << "Missing color for "
|
||||
<< long_options[option_index].name
|
||||
<< " '" << optarg << "'" << std::endl;
|
||||
<< long_options[opt.ind].name
|
||||
<< " '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -796,8 +813,8 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
std::getline(iss, localizedText);
|
||||
if (localizedText.empty() || iss.fail()) {
|
||||
std::cerr << "Invalid or missing text for "
|
||||
<< long_options[option_index].name
|
||||
<< " '" << optarg << "'" << std::endl;
|
||||
<< long_options[opt.ind].name
|
||||
<< " '" << opt.arg << "'" << std::endl;
|
||||
usage();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
@ -831,9 +848,9 @@ int Mapper::start(int argc, char *argv[]) {
|
|||
generator.drawObject(drawObject);
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'd':
|
||||
generator.setBackend(strlower(optarg));
|
||||
generator.setBackend(strlower(opt.arg));
|
||||
break;
|
||||
default:
|
||||
return EXIT_FAILURE;
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
This File was taken from https://github.com/attractivechaos/klib/blob/master/ketopt.h and is licensed under MIT license.
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h> /* for strchr() and strncmp() */
|
||||
|
||||
#define ko_no_argument 0
|
||||
#define ko_required_argument 1
|
||||
#define ko_optional_argument 2
|
||||
|
||||
typedef struct {
|
||||
int ind; /* equivalent to optind */
|
||||
int opt; /* equivalent to optopt */
|
||||
char *arg; /* equivalent to optarg */
|
||||
int longidx; /* index of a long option; or -1 if short */
|
||||
/* private variables not intended for external uses */
|
||||
int i, pos, n_args;
|
||||
} ketopt_t;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int has_arg;
|
||||
int val;
|
||||
} ko_longopt_t;
|
||||
|
||||
static ketopt_t KETOPT_INIT = { 1, 0, 0, -1, 1, 0, 0 };
|
||||
|
||||
static void ketopt_permute(char *argv[], int j, int n) /* move argv[j] over n elements to the left */
|
||||
{
|
||||
int k;
|
||||
char *p = argv[j];
|
||||
for (k = 0; k < n; ++k)
|
||||
argv[j - k] = argv[j - k - 1];
|
||||
argv[j - k] = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse command-line options and arguments
|
||||
*
|
||||
* This fuction has a similar interface to GNU's getopt_long(). Each call
|
||||
* parses one option and returns the option name. s->arg points to the option
|
||||
* argument if present. The function returns -1 when all command-line arguments
|
||||
* are parsed. In this case, s->ind is the index of the first non-option
|
||||
* argument.
|
||||
*
|
||||
* @param s status; shall be initialized to KETOPT_INIT on the first call
|
||||
* @param argc length of argv[]
|
||||
* @param argv list of command-line arguments; argv[0] is ignored
|
||||
* @param permute non-zero to move options ahead of non-option arguments
|
||||
* @param ostr option string
|
||||
* @param longopts long options
|
||||
*
|
||||
* @return ASCII for a short option; ko_longopt_t::val for a long option; -1 if
|
||||
* argv[] is fully processed; '?' for an unknown option or an ambiguous
|
||||
* long option; ':' if an option argument is missing
|
||||
*/
|
||||
static int ketopt(ketopt_t *s, int argc, char *argv[], int permute, const char *ostr, const ko_longopt_t *longopts)
|
||||
{
|
||||
int opt = -1, i0, j;
|
||||
if (permute) {
|
||||
while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0'))
|
||||
++s->i, ++s->n_args;
|
||||
}
|
||||
s->arg = 0, s->longidx = -1, i0 = s->i;
|
||||
if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') {
|
||||
s->ind = s->i - s->n_args;
|
||||
return -1;
|
||||
}
|
||||
if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */
|
||||
if (argv[s->i][2] == '\0') { /* a bare "--" */
|
||||
ketopt_permute(argv, s->i, s->n_args);
|
||||
++s->i, s->ind = s->i - s->n_args;
|
||||
return -1;
|
||||
}
|
||||
s->opt = 0, opt = '?', s->pos = -1;
|
||||
if (longopts) { /* parse long options */
|
||||
int k, n_matches = 0;
|
||||
const ko_longopt_t *o = 0;
|
||||
for (j = 2; argv[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */
|
||||
for (k = 0; longopts[k].name != 0; ++k)
|
||||
if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0)
|
||||
++n_matches, o = &longopts[k];
|
||||
if (n_matches == 1) {
|
||||
s->opt = opt = o->val, s->longidx = (int)(o - longopts);
|
||||
if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1];
|
||||
if (o->has_arg == 1 && argv[s->i][j] == '\0') {
|
||||
if (s->i < argc - 1) s->arg = argv[++s->i];
|
||||
else opt = ':'; /* missing option argument */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* a short option */
|
||||
const char *p;
|
||||
if (s->pos == 0) s->pos = 1;
|
||||
opt = s->opt = argv[s->i][s->pos++];
|
||||
p = strchr(ostr, opt);
|
||||
if (p == 0) {
|
||||
opt = '?'; /* unknown option */
|
||||
}
|
||||
else if (p[1] == ':') {
|
||||
if (argv[s->i][s->pos] == 0) {
|
||||
if (s->i < argc - 1) s->arg = argv[++s->i];
|
||||
else opt = ':'; /* missing option argument */
|
||||
}
|
||||
else s->arg = &argv[s->i][s->pos];
|
||||
s->pos = -1;
|
||||
}
|
||||
}
|
||||
if (s->pos < 0 || argv[s->i][s->pos] == 0) {
|
||||
++s->i, s->pos = 0;
|
||||
if (s->n_args > 0) /* permute */
|
||||
for (j = i0; j < s->i; ++j)
|
||||
ketopt_permute(argv, j, s->n_args);
|
||||
}
|
||||
s->ind = s->i - s->n_args;
|
||||
return opt;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
build
|
||||
*.lib
|
||||
*.pdb
|
|
@ -1,23 +0,0 @@
|
|||
PROJECT(wingetopt)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build the shared library" OFF)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
add_definitions(-DBUILDING_WINGETOPT_DLL -DWINGETOPT_SHARED_LIB)
|
||||
endif()
|
||||
|
||||
add_library(wingetopt src/getopt.c src/getopt.h)
|
||||
|
||||
install(FILES src/getopt.h DESTINATION include)
|
||||
|
||||
install(TARGETS wingetopt
|
||||
RUNTIME DESTINATION bin
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib)
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
#### AUTHORS:
|
||||
|
||||
* Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* The NetBSD Foundation, Inc.
|
||||
* Alexei Kasatkin is the author of trivial CMakeLists.txt, build script itself is Public Domain
|
||||
|
||||
#### LICENSE
|
||||
|
||||
Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Sponsored in part by the Defense Advanced Research Projects
|
||||
Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
|
||||
***
|
||||
|
||||
Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This code is derived from software contributed to The NetBSD Foundation
|
||||
by Dieter Baron and Thomas Klausner.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,63 +0,0 @@
|
|||
# wingetopt
|
||||
|
||||
getopt library for Windows compilers
|
||||
|
||||
|
||||
This library was created to allow compilation linux-based software on Windows.
|
||||
http://en.wikipedia.org/wiki/Getopt
|
||||
|
||||
The sources were taken from MinGW-runtime project.
|
||||
|
||||
#### AUTHORS:
|
||||
|
||||
* Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* The NetBSD Foundation, Inc.
|
||||
|
||||
#### LICENSE
|
||||
|
||||
Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Sponsored in part by the Defense Advanced Research Projects
|
||||
Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
|
||||
***
|
||||
|
||||
Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
All rights reserved.
|
||||
|
||||
This code is derived from software contributed to The NetBSD Foundation
|
||||
by Dieter Baron and Thomas Klausner.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,562 +0,0 @@
|
|||
/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */
|
||||
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Sponsored in part by the Defense Advanced Research Projects
|
||||
* Agency (DARPA) and Air Force Research Laboratory, Air Force
|
||||
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
|
||||
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
int opterr = 1; /* if error message should be printed */
|
||||
int optind = 1; /* index into parent argv vector */
|
||||
int optopt = '?'; /* character checked for validity */
|
||||
#undef optreset /* see getopt.h */
|
||||
#define optreset __mingw_optreset
|
||||
int optreset; /* reset getopt */
|
||||
char *optarg; /* argument associated with option */
|
||||
#endif
|
||||
|
||||
#define PRINT_ERROR ((opterr) && (*options != ':'))
|
||||
|
||||
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
|
||||
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
|
||||
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
|
||||
|
||||
/* return values */
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
|
||||
#define INORDER (int)1
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
#define __progname __argv[0]
|
||||
#else
|
||||
extern char __declspec(dllimport) *__progname;
|
||||
#endif
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
static char EMSG[] = "";
|
||||
#else
|
||||
#define EMSG ""
|
||||
#endif
|
||||
|
||||
static int getopt_internal(int, char * const *, const char *,
|
||||
const struct option *, int *, int);
|
||||
static int parse_long_options(char * const *, const char *,
|
||||
const struct option *, int *, int);
|
||||
static int gcd(int, int);
|
||||
static void permute_args(int, int, int, char * const *);
|
||||
|
||||
static char *place = EMSG; /* option letter processing */
|
||||
|
||||
/* XXX: set optreset to 1 rather than these two */
|
||||
static int nonopt_start = -1; /* first non option argument (for permute) */
|
||||
static int nonopt_end = -1; /* first option after non options (for permute) */
|
||||
|
||||
/* Error messages */
|
||||
static const char recargchar[] = "option requires an argument -- %c";
|
||||
static const char recargstring[] = "option requires an argument -- %s";
|
||||
static const char ambig[] = "ambiguous option -- %.*s";
|
||||
static const char noarg[] = "option doesn't take an argument -- %.*s";
|
||||
static const char illoptchar[] = "unknown option -- %c";
|
||||
static const char illoptstring[] = "unknown option -- %s";
|
||||
|
||||
static void
|
||||
_vwarnx(const char *fmt,va_list ap)
|
||||
{
|
||||
(void)fprintf(stderr,"%s: ",__progname);
|
||||
if (fmt != NULL)
|
||||
(void)vfprintf(stderr,fmt,ap);
|
||||
(void)fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
static void
|
||||
warnx(const char *fmt,...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,fmt);
|
||||
_vwarnx(fmt,ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the greatest common divisor of a and b.
|
||||
*/
|
||||
static int
|
||||
gcd(int a, int b)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = a % b;
|
||||
while (c != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
}
|
||||
|
||||
return (b);
|
||||
}
|
||||
|
||||
/*
|
||||
* Exchange the block from nonopt_start to nonopt_end with the block
|
||||
* from nonopt_end to opt_end (keeping the same order of arguments
|
||||
* in each block).
|
||||
*/
|
||||
static void
|
||||
permute_args(int panonopt_start, int panonopt_end, int opt_end,
|
||||
char * const *nargv)
|
||||
{
|
||||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||
char *swap;
|
||||
|
||||
/*
|
||||
* compute lengths of blocks and number and size of cycles
|
||||
*/
|
||||
nnonopts = panonopt_end - panonopt_start;
|
||||
nopts = opt_end - panonopt_end;
|
||||
ncycle = gcd(nnonopts, nopts);
|
||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||
|
||||
for (i = 0; i < ncycle; i++) {
|
||||
cstart = panonopt_end+i;
|
||||
pos = cstart;
|
||||
for (j = 0; j < cyclelen; j++) {
|
||||
if (pos >= panonopt_end)
|
||||
pos -= nnonopts;
|
||||
else
|
||||
pos += nopts;
|
||||
swap = nargv[pos];
|
||||
/* LINTED const cast */
|
||||
((char **) nargv)[pos] = nargv[cstart];
|
||||
/* LINTED const cast */
|
||||
((char **)nargv)[cstart] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse_long_options --
|
||||
* Parse long options in argc/argv argument vector.
|
||||
* Returns -1 if short_too is set and the option does not match long_options.
|
||||
*/
|
||||
static int
|
||||
parse_long_options(char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx, int short_too)
|
||||
{
|
||||
char *current_argv, *has_equal;
|
||||
size_t current_argv_len;
|
||||
int i, ambiguous, match;
|
||||
|
||||
#define IDENTICAL_INTERPRETATION(_x, _y) \
|
||||
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
|
||||
long_options[(_x)].flag == long_options[(_y)].flag && \
|
||||
long_options[(_x)].val == long_options[(_y)].val)
|
||||
|
||||
current_argv = place;
|
||||
match = -1;
|
||||
ambiguous = 0;
|
||||
|
||||
optind++;
|
||||
|
||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||
/* argument found (--option=arg) */
|
||||
current_argv_len = has_equal - current_argv;
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = strlen(current_argv);
|
||||
|
||||
for (i = 0; long_options[i].name; i++) {
|
||||
/* find matching long option */
|
||||
if (strncmp(current_argv, long_options[i].name,
|
||||
current_argv_len))
|
||||
continue;
|
||||
|
||||
if (strlen(long_options[i].name) == current_argv_len) {
|
||||
/* exact match */
|
||||
match = i;
|
||||
ambiguous = 0;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If this is a known short option, don't allow
|
||||
* a partial match of a single character.
|
||||
*/
|
||||
if (short_too && current_argv_len == 1)
|
||||
continue;
|
||||
|
||||
if (match == -1) /* partial match */
|
||||
match = i;
|
||||
else if (!IDENTICAL_INTERPRETATION(i, match))
|
||||
ambiguous = 1;
|
||||
}
|
||||
if (ambiguous) {
|
||||
/* ambiguous abbreviation */
|
||||
if (PRINT_ERROR)
|
||||
warnx(ambig, (int)current_argv_len,
|
||||
current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (match != -1) { /* option found */
|
||||
if (long_options[match].has_arg == no_argument
|
||||
&& has_equal) {
|
||||
if (PRINT_ERROR)
|
||||
warnx(noarg, (int)current_argv_len,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
return (BADARG);
|
||||
}
|
||||
if (long_options[match].has_arg == required_argument ||
|
||||
long_options[match].has_arg == optional_argument) {
|
||||
if (has_equal)
|
||||
optarg = has_equal;
|
||||
else if (long_options[match].has_arg ==
|
||||
required_argument) {
|
||||
/*
|
||||
* optional argument doesn't use next nargv
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
}
|
||||
}
|
||||
if ((long_options[match].has_arg == required_argument)
|
||||
&& (optarg == NULL)) {
|
||||
/*
|
||||
* Missing argument; leading ':' indicates no error
|
||||
* should be generated.
|
||||
*/
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargstring,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
--optind;
|
||||
return (BADARG);
|
||||
}
|
||||
} else { /* unknown option */
|
||||
if (short_too) {
|
||||
--optind;
|
||||
return (-1);
|
||||
}
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptstring, current_argv);
|
||||
optopt = 0;
|
||||
return (BADCH);
|
||||
}
|
||||
if (idx)
|
||||
*idx = match;
|
||||
if (long_options[match].flag) {
|
||||
*long_options[match].flag = long_options[match].val;
|
||||
return (0);
|
||||
} else
|
||||
return (long_options[match].val);
|
||||
#undef IDENTICAL_INTERPRETATION
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_internal --
|
||||
* Parse argc/argv argument vector. Called by user level routines.
|
||||
*/
|
||||
static int
|
||||
getopt_internal(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx, int flags)
|
||||
{
|
||||
const char *oli; /* option letter list index */
|
||||
int optchar, short_too;
|
||||
static int posixly_correct = -1;
|
||||
|
||||
if (options == NULL)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* XXX Some GNU programs (like cvs) set optind to 0 instead of
|
||||
* XXX using optreset. Work around this braindamage.
|
||||
*/
|
||||
if (optind == 0)
|
||||
optind = optreset = 1;
|
||||
|
||||
/*
|
||||
* Disable GNU extensions if POSIXLY_CORRECT is set or options
|
||||
* string begins with a '+'.
|
||||
*
|
||||
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
|
||||
* optreset != 0 for GNU compatibility.
|
||||
*/
|
||||
if (posixly_correct == -1 || optreset != 0)
|
||||
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
|
||||
if (*options == '-')
|
||||
flags |= FLAG_ALLARGS;
|
||||
else if (posixly_correct || *options == '+')
|
||||
flags &= ~FLAG_PERMUTE;
|
||||
if (*options == '+' || *options == '-')
|
||||
options++;
|
||||
|
||||
optarg = NULL;
|
||||
if (optreset)
|
||||
nonopt_start = nonopt_end = -1;
|
||||
start:
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc) { /* end of argument vector */
|
||||
place = EMSG;
|
||||
if (nonopt_end != -1) {
|
||||
/* do permutation, if we have to */
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
else if (nonopt_start != -1) {
|
||||
/*
|
||||
* If we skipped non-options, set optind
|
||||
* to the first of them.
|
||||
*/
|
||||
optind = nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
if (*(place = nargv[optind]) != '-' ||
|
||||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
|
||||
place = EMSG; /* found non-option */
|
||||
if (flags & FLAG_ALLARGS) {
|
||||
/*
|
||||
* GNU extension:
|
||||
* return non-option as argument to option 1
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
return (INORDER);
|
||||
}
|
||||
if (!(flags & FLAG_PERMUTE)) {
|
||||
/*
|
||||
* If no permutation wanted, stop parsing
|
||||
* at first non-option.
|
||||
*/
|
||||
return (-1);
|
||||
}
|
||||
/* do permutation */
|
||||
if (nonopt_start == -1)
|
||||
nonopt_start = optind;
|
||||
else if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
nonopt_start = optind -
|
||||
(nonopt_end - nonopt_start);
|
||||
nonopt_end = -1;
|
||||
}
|
||||
optind++;
|
||||
/* process next argument */
|
||||
goto start;
|
||||
}
|
||||
if (nonopt_start != -1 && nonopt_end == -1)
|
||||
nonopt_end = optind;
|
||||
|
||||
/*
|
||||
* If we have "-" do nothing, if "--" we are done.
|
||||
*/
|
||||
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
|
||||
optind++;
|
||||
place = EMSG;
|
||||
/*
|
||||
* We found an option (--), so if we skipped
|
||||
* non-options, we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check long options if:
|
||||
* 1) we were passed some
|
||||
* 2) the arg is not just "-"
|
||||
* 3) either the arg starts with -- we are getopt_long_only()
|
||||
*/
|
||||
if (long_options != NULL && place != nargv[optind] &&
|
||||
(*place == '-' || (flags & FLAG_LONGONLY))) {
|
||||
short_too = 0;
|
||||
if (*place == '-')
|
||||
place++; /* --foo long option */
|
||||
else if (*place != ':' && strchr(options, *place) != NULL)
|
||||
short_too = 1; /* could be short option too */
|
||||
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, short_too);
|
||||
if (optchar != -1) {
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
}
|
||||
|
||||
if ((optchar = (int)*place++) == (int)':' ||
|
||||
(optchar == (int)'-' && *place != '\0') ||
|
||||
(oli = strchr(options, optchar)) == NULL) {
|
||||
/*
|
||||
* If the user specified "-" and '-' isn't listed in
|
||||
* options, return -1 (non-option) as per POSIX.
|
||||
* Otherwise, it is an unknown option character (or ':').
|
||||
*/
|
||||
if (optchar == (int)'-' && *place == '\0')
|
||||
return (-1);
|
||||
if (!*place)
|
||||
++optind;
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADCH);
|
||||
}
|
||||
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
|
||||
/* -W long-option */
|
||||
if (*place) /* no space */
|
||||
/* NOTHING */;
|
||||
else if (++optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else /* white space */
|
||||
place = nargv[optind];
|
||||
optchar = parse_long_options(nargv, options, long_options,
|
||||
idx, 0);
|
||||
place = EMSG;
|
||||
return (optchar);
|
||||
}
|
||||
if (*++oli != ':') { /* doesn't take argument */
|
||||
if (!*place)
|
||||
++optind;
|
||||
} else { /* takes (optional) argument */
|
||||
optarg = NULL;
|
||||
if (*place) /* no white space */
|
||||
optarg = place;
|
||||
else if (oli[1] != ':') { /* arg not optional */
|
||||
if (++optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return (BADARG);
|
||||
} else
|
||||
optarg = nargv[optind];
|
||||
}
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
/* dump back option letter */
|
||||
return (optchar);
|
||||
}
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*
|
||||
* [eventually this will replace the BSD getopt]
|
||||
*/
|
||||
int
|
||||
getopt(int nargc, char * const *nargv, const char *options)
|
||||
{
|
||||
|
||||
/*
|
||||
* We don't pass FLAG_PERMUTE to getopt_internal() since
|
||||
* the BSD getopt(3) (unlike GNU) has never done this.
|
||||
*
|
||||
* Furthermore, since many privileged programs call getopt()
|
||||
* before dropping privileges it makes sense to keep things
|
||||
* as simple (and bug-free) as possible.
|
||||
*/
|
||||
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
|
||||
}
|
||||
#endif /* REPLACE_GETOPT */
|
||||
|
||||
/*
|
||||
* getopt_long --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE));
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_long_only --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx)
|
||||
{
|
||||
|
||||
return (getopt_internal(nargc, nargv, options, long_options, idx,
|
||||
FLAG_PERMUTE|FLAG_LONGONLY));
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
#ifndef __GETOPT_H__
|
||||
/**
|
||||
* DISCLAIMER
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is a part of the w64 mingw-runtime package.
|
||||
*
|
||||
* The w64 mingw-runtime package and its code is distributed in the hope that it
|
||||
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
|
||||
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
|
||||
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define __GETOPT_H__
|
||||
|
||||
/* All the headers include this file. */
|
||||
#include <crtdefs.h>
|
||||
|
||||
#if defined( WINGETOPT_SHARED_LIB )
|
||||
# if defined( BUILDING_WINGETOPT_DLL )
|
||||
# define WINGETOPT_API __declspec(dllexport)
|
||||
# else
|
||||
# define WINGETOPT_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define WINGETOPT_API
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WINGETOPT_API extern int optind; /* index of first non-option in argv */
|
||||
WINGETOPT_API extern int optopt; /* single option character, as parsed */
|
||||
WINGETOPT_API extern int opterr; /* flag to enable built-in diagnostics... */
|
||||
/* (user may set to zero, to suppress) */
|
||||
|
||||
WINGETOPT_API extern char *optarg; /* pointer to argument of current option */
|
||||
|
||||
extern int getopt(int nargc, char * const *nargv, const char *options);
|
||||
|
||||
#ifdef _BSD_SOURCE
|
||||
/*
|
||||
* BSD adds the non-standard `optreset' feature, for reinitialisation
|
||||
* of `getopt' parsing. We support this feature, for applications which
|
||||
* proclaim their BSD heritage, before including this header; however,
|
||||
* to maintain portability, developers are advised to avoid it.
|
||||
*/
|
||||
# define optreset __mingw_optreset
|
||||
extern int optreset;
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* POSIX requires the `getopt' API to be specified in `unistd.h';
|
||||
* thus, `unistd.h' includes this header. However, we do not want
|
||||
* to expose the `getopt_long' or `getopt_long_only' APIs, when
|
||||
* included in this manner. Thus, close the standard __GETOPT_H__
|
||||
* declarations block, and open an additional __GETOPT_LONG_H__
|
||||
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
|
||||
* to declare the extended API.
|
||||
*/
|
||||
#endif /* !defined(__GETOPT_H__) */
|
||||
|
||||
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
|
||||
#define __GETOPT_LONG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct option /* specification for a long form option... */
|
||||
{
|
||||
const char *name; /* option name, without leading hyphens */
|
||||
int has_arg; /* does it take an argument? */
|
||||
int *flag; /* where to save its status, or NULL */
|
||||
int val; /* its associated status value */
|
||||
};
|
||||
|
||||
enum /* permitted values for its `has_arg' field... */
|
||||
{
|
||||
no_argument = 0, /* option never takes an argument */
|
||||
required_argument, /* option always requires an argument */
|
||||
optional_argument /* option may take an argument */
|
||||
};
|
||||
|
||||
extern int getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx);
|
||||
extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx);
|
||||
/*
|
||||
* Previous MinGW implementation had...
|
||||
*/
|
||||
#ifndef HAVE_DECL_GETOPT
|
||||
/*
|
||||
* ...for the long form API only; keep this for compatibility.
|
||||
*/
|
||||
# define HAVE_DECL_GETOPT 1
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
|
Loading…
Reference in New Issue