From e8a56db21dc00e09bff792a9c9fb66bcb51aa2cf Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 10 Apr 2024 21:49:39 +0200 Subject: [PATCH] Codechange: use designated initializers for OptionData and pass as span --- src/misc/getoptdata.cpp | 12 +++--- src/misc/getoptdata.h | 71 ++++----------------------------- src/openttd.cpp | 50 ++++++++++------------- src/settingsgen/settingsgen.cpp | 11 +++-- src/strgen/strgen.cpp | 19 +++++---- 5 files changed, 49 insertions(+), 114 deletions(-) diff --git a/src/misc/getoptdata.cpp b/src/misc/getoptdata.cpp index df54391232..b4cb5df3d1 100644 --- a/src/misc/getoptdata.cpp +++ b/src/misc/getoptdata.cpp @@ -21,7 +21,7 @@ */ int GetOptData::GetOpt() { - const OptionData *odata; + OptionSpan::iterator odata; char *s = this->cont; if (s == nullptr) { @@ -34,7 +34,7 @@ int GetOptData::GetOpt() this->numleft--; /* Is it a long option? */ - for (odata = this->options; odata->flags != ODF_END; odata++) { + for (odata = std::begin(this->options); odata != std::end(this->options); odata++) { if (odata->longname != nullptr && !strcmp(odata->longname, s)) { // Long options always use the entire argument. this->cont = nullptr; goto set_optval; @@ -45,13 +45,13 @@ int GetOptData::GetOpt() } /* Is it a short option? */ - for (odata = this->options; odata->flags != ODF_END; odata++) { + for (odata = std::begin(this->options); odata != std::end(this->options); odata++) { if (odata->shortname != '\0' && *s == odata->shortname) { this->cont = (s[1] != '\0') ? s + 1 : nullptr; set_optval: // Handle option value of *odata . this->opt = nullptr; - switch (odata->flags) { + switch (odata->type) { case ODF_NO_VALUE: return odata->id; @@ -63,10 +63,10 @@ set_optval: // Handle option value of *odata . return odata->id; } /* No more arguments, either return an error or a value-less option. */ - if (this->numleft == 0) return (odata->flags == ODF_HAS_VALUE) ? -2 : odata->id; + if (this->numleft == 0) return (odata->type == ODF_HAS_VALUE) ? -2 : odata->id; /* Next argument looks like another option, let's not return it as option value. */ - if (odata->flags == ODF_OPTIONAL_VALUE && this->argv[0][0] == '-') return odata->id; + if (odata->type == ODF_OPTIONAL_VALUE && this->argv[0][0] == '-') return odata->id; this->opt = this->argv[0]; // Next argument is the option value. this->argv++; diff --git a/src/misc/getoptdata.h b/src/misc/getoptdata.h index e9a8e824a2..d6df8f218e 100644 --- a/src/misc/getoptdata.h +++ b/src/misc/getoptdata.h @@ -11,27 +11,27 @@ #define GETOPTDATA_H /** Flags of an option. */ -enum OptionDataFlags { +enum OptionDataType : uint8_t { ODF_NO_VALUE, ///< A plain option (no value attached to it). ODF_HAS_VALUE, ///< An option with a value. ODF_OPTIONAL_VALUE, ///< An option with an optional value. - ODF_END, ///< Terminator (data is not parsed further). }; /** Data of an option. */ struct OptionData { - uint8_t id; ///< Unique identification of this option data, often the same as #shortname. - char shortname; ///< Short option letter if available, else use \c '\0'. - uint16_t flags; ///< Option data flags. @see OptionDataFlags - const char *longname; ///< Long option name including '-'/'--' prefix, use \c nullptr if not available. + OptionDataType type; ///< The type of option. + char id; ///< Unique identification of this option data, often the same as #shortname. + char shortname = '\0'; ///< Short option letter if available, else use \c '\0'. + const char *longname = nullptr; ///< Long option name including '-'/'--' prefix, use \c nullptr if not available. }; /** Data storage for parsing command line options. */ struct GetOptData { + using OptionSpan = std::span; char *opt; ///< Option value, if available (else \c nullptr). int numleft; ///< Number of arguments left in #argv. char **argv; ///< Remaining command line arguments. - const OptionData *options; ///< Command line option descriptions. + OptionSpan options; ///< Command line option descriptions. char *cont; ///< Next call to #GetOpt should start here (in the middle of an argument). /** @@ -40,7 +40,7 @@ struct GetOptData { * @param argv Command line arguments, excluding the program name. * @param options Command line option descriptions. */ - GetOptData(int argc, char **argv, const OptionData *options) : + GetOptData(int argc, char **argv, OptionSpan options) : opt(nullptr), numleft(argc), argv(argv), @@ -52,59 +52,4 @@ struct GetOptData { int GetOpt(); }; -/** - * General macro for creating an option. - * @param id Identification of the option. - * @param shortname Short option name. Use \c '\0' if not used. - * @param longname Long option name including leading '-' or '--'. Use \c nullptr if not used. - * @param flags Flags of the option. - */ -#define GETOPT_GENERAL(id, shortname, longname, flags) { id, shortname, flags, longname } - -/** - * Short option without value. - * @param shortname Short option name. Use \c '\0' if not used. - * @param longname Long option name including leading '-' or '--'. Use \c nullptr if not used. - */ -#define GETOPT_NOVAL(shortname, longname) GETOPT_GENERAL(shortname, shortname, longname, ODF_NO_VALUE) - -/** - * Short option with value. - * @param shortname Short option name. Use \c '\0' if not used. - * @param longname Long option name including leading '-' or '--'. Use \c nullptr if not used. - */ -#define GETOPT_VALUE(shortname, longname) GETOPT_GENERAL(shortname, shortname, longname, ODF_HAS_VALUE) - -/** - * Short option with optional value. - * @param shortname Short option name. Use \c '\0' if not used. - * @param longname Long option name including leading '-' or '--'. Use \c nullptr if not used. - * @note Options with optional values are hopelessly ambiguous, eg "-opt -value", avoid them. - */ -#define GETOPT_OPTVAL(shortname, longname) GETOPT_GENERAL(shortname, shortname, longname, ODF_OPTIONAL_VALUE) - - -/** - * Short option without value. - * @param shortname Short option name. Use \c '\0' if not used. - */ -#define GETOPT_SHORT_NOVAL(shortname) GETOPT_NOVAL(shortname, nullptr) - -/** - * Short option with value. - * @param shortname Short option name. Use \c '\0' if not used. - */ -#define GETOPT_SHORT_VALUE(shortname) GETOPT_VALUE(shortname, nullptr) - -/** - * Short option with optional value. - * @param shortname Short option name. Use \c '\0' if not used. - * @note Options with optional values are hopelessly ambiguous, eg "-opt -value", avoid them. - */ -#define GETOPT_SHORT_OPTVAL(shortname) GETOPT_OPTVAL(shortname, nullptr) - -/** Option terminator. */ -#define GETOPT_END() { '\0', '\0', ODF_END, nullptr} - - #endif /* GETOPTDATA_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index 7ae3cba92d..bece97833e 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -478,36 +478,27 @@ void PostMainLoop() extern void DedicatedFork(); #endif -/** Options of OpenTTD. */ -static const OptionData _options[] = { - GETOPT_SHORT_VALUE('I'), - GETOPT_SHORT_VALUE('S'), - GETOPT_SHORT_VALUE('M'), - GETOPT_SHORT_VALUE('m'), - GETOPT_SHORT_VALUE('s'), - GETOPT_SHORT_VALUE('v'), - GETOPT_SHORT_VALUE('b'), - GETOPT_SHORT_OPTVAL('D'), - GETOPT_SHORT_VALUE('n'), - GETOPT_SHORT_VALUE('p'), - GETOPT_SHORT_VALUE('P'), +/** + * Create all the options that OpenTTD supports. Each option is + * always a single character with no, an optional or a required value. + * @return The available options. + */ +static std::vector CreateOptions() +{ + std::vector options; + /* Options that require a parameter. */ + for (char c : "GIMPSbcmnpqrstv") options.push_back({ .type = ODF_HAS_VALUE, .id = c, .shortname = c }); #if !defined(_WIN32) - GETOPT_SHORT_NOVAL('f'), + options.push_back({ .type = ODF_HAS_VALUE, .id = 'f', .shortname = 'f' }); #endif - GETOPT_SHORT_VALUE('r'), - GETOPT_SHORT_VALUE('t'), - GETOPT_SHORT_OPTVAL('d'), - GETOPT_SHORT_NOVAL('e'), - GETOPT_SHORT_OPTVAL('g'), - GETOPT_SHORT_VALUE('G'), - GETOPT_SHORT_VALUE('c'), - GETOPT_SHORT_NOVAL('x'), - GETOPT_SHORT_NOVAL('X'), - GETOPT_SHORT_VALUE('q'), - GETOPT_SHORT_NOVAL('h'), - GETOPT_SHORT_NOVAL('Q'), - GETOPT_END() -}; + + /* Options with an optional parameter. */ + for (char c : "Ddg") options.push_back({ .type = ODF_OPTIONAL_VALUE, .id = c, .shortname = c }); + + /* Options without a parameter. */ + for (char c : "QXehx") options.push_back({ .type = ODF_NO_VALUE, .id = c, .shortname = c }); + return options; +} /** * Main entry point for this lovely game. @@ -538,7 +529,8 @@ int openttd_main(int argc, char *argv[]) _game_mode = GM_MENU; _switch_mode = SM_MENU; - GetOptData mgo(argc - 1, argv + 1, _options); + auto options = CreateOptions(); + GetOptData mgo(argc - 1, argv + 1, options); int ret = 0; int i; diff --git a/src/settingsgen/settingsgen.cpp b/src/settingsgen/settingsgen.cpp index 0ab4d5bd43..cb161033b8 100644 --- a/src/settingsgen/settingsgen.cpp +++ b/src/settingsgen/settingsgen.cpp @@ -385,12 +385,11 @@ static bool CompareFiles(const char *n1, const char *n2) /** Options of settingsgen. */ static const OptionData _opts[] = { - GETOPT_NOVAL( 'h', "--help"), - GETOPT_GENERAL('h', '?', nullptr, ODF_NO_VALUE), - GETOPT_VALUE( 'o', "--output"), - GETOPT_VALUE( 'b', "--before"), - GETOPT_VALUE( 'a', "--after"), - GETOPT_END(), + { .type = ODF_NO_VALUE, .id = 'h', .shortname = 'h', .longname = "--help" }, + { .type = ODF_NO_VALUE, .id = 'h', .shortname = '?' }, + { .type = ODF_HAS_VALUE, .id = 'o', .shortname = 'o', .longname = "--output" }, + { .type = ODF_HAS_VALUE, .id = 'b', .shortname = 'b', .longname = "--before" }, + { .type = ODF_HAS_VALUE, .id = 'a', .shortname = 'a', .longname = "--after" }, }; /** diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp index 63d52fb865..306a4f8c63 100644 --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -312,16 +312,15 @@ struct LanguageFileWriter : LanguageWriter, FileWriter { /** Options of strgen. */ static const OptionData _opts[] = { - GETOPT_GENERAL('C', '\0', "-export-commands", ODF_NO_VALUE), - GETOPT_GENERAL('L', '\0', "-export-plurals", ODF_NO_VALUE), - GETOPT_GENERAL('P', '\0', "-export-pragmas", ODF_NO_VALUE), - GETOPT_NOVAL( 't', "--todo"), - GETOPT_NOVAL( 'w', "--warning"), - GETOPT_NOVAL( 'h', "--help"), - GETOPT_GENERAL('h', '?', nullptr, ODF_NO_VALUE), - GETOPT_VALUE( 's', "--source_dir"), - GETOPT_VALUE( 'd', "--dest_dir"), - GETOPT_END(), + { .type = ODF_NO_VALUE, .id = 'C', .longname = "-export-commands" }, + { .type = ODF_NO_VALUE, .id = 'L', .longname = "-export-plurals" }, + { .type = ODF_NO_VALUE, .id = 'P', .longname = "-export-pragmas" }, + { .type = ODF_NO_VALUE, .id = 't', .shortname = 't', .longname = "--todo" }, + { .type = ODF_NO_VALUE, .id = 'w', .shortname = 'w', .longname = "--warning" }, + { .type = ODF_NO_VALUE, .id = 'h', .shortname = 'h', .longname = "--help" }, + { .type = ODF_NO_VALUE, .id = 'h', .shortname = '?' }, + { .type = ODF_HAS_VALUE, .id = 's', .shortname = 's', .longname = "--source_dir" }, + { .type = ODF_HAS_VALUE, .id = 'd', .shortname = 'd', .longname = "--dest_dir" }, }; int CDECL main(int argc, char *argv[])