From b10433715daca9eb11d3c383d8a473853d41aee2 Mon Sep 17 00:00:00 2001 From: frosch Date: Mon, 24 Mar 2025 19:16:02 +0100 Subject: [PATCH] Codechange: Turn out parameters into return values. --- src/strgen/strgen_base.cpp | 157 +++++++++++++++++------------------ src/table/strgen_tables.h | 162 ++++++++++++++++++------------------- 2 files changed, 156 insertions(+), 163 deletions(-) diff --git a/src/strgen/strgen_base.cpp b/src/strgen/strgen_base.cpp index 6a41455b8b..625b277607 100644 --- a/src/strgen/strgen_base.cpp +++ b/src/strgen/strgen_base.cpp @@ -31,7 +31,13 @@ static const char *_cur_ident; static ParsedCommandStruct _cur_pcs; static int _cur_argidx; -static const CmdStruct *ParseCommandString(const char **str, std::string ¶m, int *argno, int *casei); +struct ParsedCommandString { + const CmdStruct *cmd = nullptr; + std::string param; + std::optional argno; + std::optional casei; +}; +static ParsedCommandString ParseCommandString(const char **str); static int TranslateArgumentIdx(int arg, int offset = 0); /** @@ -133,22 +139,17 @@ uint StringData::Version() const const LangString *ls = this->strings[i].get(); if (ls != nullptr) { - const CmdStruct *cs; - const char *s; - std::string buf; - int argno; - int casei; - - s = ls->name.c_str(); + const char *s = ls->name.c_str(); hash ^= i * 0x717239; hash = (hash & 1 ? hash >> 1 ^ 0xDEADBEEF : hash >> 1); hash = VersionHashStr(hash, s + 1); s = ls->english.c_str(); - while ((cs = ParseCommandString(&s, buf, &argno, &casei)) != nullptr) { - if (cs->flags.Test(CmdFlag::DontCount)) continue; + ParsedCommandString cs; + while ((cs = ParseCommandString(&s)).cmd != nullptr) { + if (cs.cmd->flags.Test(CmdFlag::DontCount)) continue; - hash ^= (cs - _cmd_structs) * 0x1234567; + hash ^= (cs.cmd - _cmd_structs) * 0x1234567; hash = (hash & 1 ? hash >> 1 ^ 0xF00BAA4 : hash >> 1); } } @@ -237,23 +238,23 @@ void EmitSingleChar(Buffer *buffer, char *buf, int value) /* The plural specifier looks like * {NUM} {PLURAL passenger passengers} then it picks either passenger/passengers depending on the count in NUM */ -static bool ParseRelNum(char **buf, int *value, int *offset) +static std::pair, std::optional> ParseRelNum(char **buf) { const char *s = *buf; char *end; while (*s == ' ' || *s == '\t') s++; int v = std::strtol(s, &end, 0); - if (end == s) return false; - *value = v; - if (offset != nullptr && *end == ':') { + if (end == s) return {}; + std::optional offset; + if (*end == ':') { /* Take the Nth within */ s = end + 1; - *offset = std::strtol(s, &end, 0); - if (end == s) return false; + offset = std::strtol(s, &end, 0); + if (end == s) return {}; } *buf = end; - return true; + return {v, offset}; } /* Parse out the next word, or nullptr */ @@ -312,19 +313,21 @@ static void EmitWordList(Buffer *buffer, const std::vector &words, void EmitPlural(Buffer *buffer, char *buf, int) { - int argidx = _cur_argidx; - int offset = -1; int expected = _plural_forms[_lang.plural_form].plural_count; std::vector words(std::max(expected, MAX_PLURALS), nullptr); int nw = 0; /* Parse out the number, if one exists. Otherwise default to prev arg. */ - if (!ParseRelNum(&buf, &argidx, &offset)) argidx--; + auto [argidx, offset] = ParseRelNum(&buf); + if (!argidx.has_value()) { + if (_cur_argidx == 0) StrgenFatal("Plural choice needs positional reference"); + argidx = _cur_argidx - 1; + } - const CmdStruct *cmd = _cur_pcs.consuming_commands[argidx]; - if (offset == -1) { + const CmdStruct *cmd = _cur_pcs.consuming_commands[*argidx]; + if (!offset.has_value()) { /* Use default offset */ - if (cmd == nullptr || cmd->default_plural_offset < 0) { + if (cmd == nullptr || !cmd->default_plural_offset.has_value()) { StrgenFatal("Command '{}' has no (default) plural position", cmd == nullptr ? "" : cmd->cmd); } offset = cmd->default_plural_offset; @@ -358,21 +361,17 @@ void EmitPlural(Buffer *buffer, char *buf, int) buffer->AppendUtf8(SCC_PLURAL_LIST); buffer->AppendByte(_lang.plural_form); - buffer->AppendByte(TranslateArgumentIdx(argidx, offset)); + buffer->AppendByte(TranslateArgumentIdx(*argidx, *offset)); EmitWordList(buffer, words, nw); } void EmitGender(Buffer *buffer, char *buf, int) { - int argidx = _cur_argidx; - int offset = 0; - uint nw; - if (buf[0] == '=') { buf++; /* This is a {G=DER} command */ - nw = _lang.GetGenderIndex(buf); + uint nw = _lang.GetGenderIndex(buf); if (nw >= MAX_NUM_GENDERS) StrgenFatal("G argument '{}' invalid", buf); /* now nw contains the gender index */ @@ -383,13 +382,16 @@ void EmitGender(Buffer *buffer, char *buf, int) /* This is a {G 0 foo bar two} command. * If no relative number exists, default to +0 */ - ParseRelNum(&buf, &argidx, &offset); + auto [argidx, offset] = ParseRelNum(&buf); + if (!argidx.has_value()) argidx = _cur_argidx; + if (!offset.has_value()) offset = 0; - const CmdStruct *cmd = _cur_pcs.consuming_commands[argidx]; + const CmdStruct *cmd = _cur_pcs.consuming_commands[*argidx]; if (cmd == nullptr || !cmd->flags.Test(CmdFlag::Gender)) { StrgenFatal("Command '{}' can't have a gender", cmd == nullptr ? "" : cmd->cmd); } + uint nw; for (nw = 0; nw < MAX_NUM_GENDERS; nw++) { words[nw] = ParseWord(&buf); if (words[nw] == nullptr) break; @@ -398,7 +400,7 @@ void EmitGender(Buffer *buffer, char *buf, int) assert(IsInsideBS(cmd->value, SCC_CONTROL_START, UINT8_MAX)); buffer->AppendUtf8(SCC_GENDER_LIST); - buffer->AppendByte(TranslateArgumentIdx(argidx, offset)); + buffer->AppendByte(TranslateArgumentIdx(*argidx, *offset)); EmitWordList(buffer, words, nw); } } @@ -424,59 +426,56 @@ static uint ResolveCaseName(const char *str, size_t len) return case_idx + 1; } -/* returns nullptr on eof - * else returns command struct */ -static const CmdStruct *ParseCommandString(const char **str, std::string ¶m, int *argno, int *casei) +/* returns cmd == nullptr on eof */ +static ParsedCommandString ParseCommandString(const char **str) { - const char *s = *str, *start; - char c; - - *argno = -1; - *casei = -1; + ParsedCommandString result; + const char *s = *str; /* Scan to the next command, exit if there's no next command. */ for (; *s != '{'; s++) { - if (*s == '\0') return nullptr; + if (*s == '\0') return {}; } s++; // Skip past the { if (*s >= '0' && *s <= '9') { char *end; - *argno = std::strtoul(s, &end, 0); + result.argno = std::strtoul(s, &end, 0); if (*end != ':') StrgenFatal("missing arg #"); s = end + 1; } /* parse command name */ - start = s; + const char *start = s; + char c; do { c = *s++; } while (c != '}' && c != ' ' && c != '=' && c != '.' && c != 0); - const CmdStruct *cmd = FindCmd(start, s - start - 1); - if (cmd == nullptr) { + result.cmd = FindCmd(start, s - start - 1); + if (result.cmd == nullptr) { std::string command(start, s - start - 1); StrgenError("Undefined command '{}'", command); - return nullptr; + return {}; } if (c == '.') { const char *casep = s; - if (!cmd->flags.Test(CmdFlag::Case)) { - StrgenFatal("Command '{}' can't have a case", cmd->cmd); + if (!result.cmd->flags.Test(CmdFlag::Case)) { + StrgenFatal("Command '{}' can't have a case", result.cmd->cmd); } do { c = *s++; } while (c != '}' && c != ' ' && c != '\0'); - *casei = ResolveCaseName(casep, s - casep - 1); + result.casei = ResolveCaseName(casep, s - casep - 1); } if (c == '\0') { StrgenError("Missing }} from command '{}'", start); - return nullptr; + return {}; } if (c != '}') { @@ -488,15 +487,15 @@ static const CmdStruct *ParseCommandString(const char **str, std::string ¶m, if (c == '}') break; if (c == '\0') { StrgenError("Missing }} from command '{}'", start); - return nullptr; + return {}; } - param += c; + result.param += c; } } *str = s; - return cmd; + return result; } /** @@ -513,30 +512,26 @@ StringReader::StringReader(StringData &data, const std::string &file, bool maste ParsedCommandStruct ExtractCommandString(const char *s, bool) { - int argno; - int argidx = 0; - int casei; - ParsedCommandStruct p; + int argidx = 0; for (;;) { /* read until next command from a. */ - std::string param; - const CmdStruct *ar = ParseCommandString(&s, param, &argno, &casei); + auto cs = ParseCommandString(&s); - if (ar == nullptr) break; + if (cs.cmd == nullptr) break; /* Sanity checking */ - if (argno != -1 && ar->consumes == 0) StrgenFatal("Non consumer param can't have a paramindex"); + if (cs.argno.has_value() && cs.cmd->consumes == 0) StrgenFatal("Non consumer param can't have a paramindex"); - if (ar->consumes) { - if (argno != -1) argidx = argno; - if (argidx < 0 || (uint)argidx >= p.consuming_commands.max_size()) StrgenFatal("invalid param idx {}", argidx); - if (p.consuming_commands[argidx] != nullptr && p.consuming_commands[argidx] != ar) StrgenFatal("duplicate param idx {}", argidx); + if (cs.cmd->consumes > 0) { + if (cs.argno.has_value()) argidx = *cs.argno; + if ((uint)argidx >= p.consuming_commands.max_size()) StrgenFatal("invalid param idx {}", argidx); + if (p.consuming_commands[argidx] != nullptr && p.consuming_commands[argidx] != cs.cmd) StrgenFatal("duplicate param idx {}", argidx); - p.consuming_commands[argidx++] = ar; - } else if (!ar->flags.Test(CmdFlag::DontCount)) { // Ignore some of them - p.non_consuming_commands.emplace_back(ar, std::move(param)); + p.consuming_commands[argidx++] = cs.cmd; + } else if (!cs.cmd->flags.Test(CmdFlag::DontCount)) { // Ignore some of them + p.non_consuming_commands.emplace_back(cs.cmd, std::move(cs.param)); } } @@ -809,33 +804,31 @@ static void PutCommandString(Buffer *buffer, const char *str) continue; } - std::string param; - int argno; - int casei; - const CmdStruct *cs = ParseCommandString(&str, param, &argno, &casei); - if (cs == nullptr) break; + auto cs = ParseCommandString(&str); + auto *cmd = cs.cmd; + if (cmd == nullptr) break; - if (casei != -1) { + if (cs.casei.has_value()) { buffer->AppendUtf8(SCC_SET_CASE); // {SET_CASE} - buffer->AppendByte(casei); + buffer->AppendByte(*cs.casei); } /* For params that consume values, we need to handle the argindex properly */ - if (cs->consumes > 0) { + if (cmd->consumes > 0) { /* Check if we need to output a move-param command */ - if (argno != -1 && argno != _cur_argidx) { - _cur_argidx = argno; + if (cs.argno.has_value() && *cs.argno != _cur_argidx) { + _cur_argidx = *cs.argno; PutArgidxCommand(buffer); } /* Output the one from the master string... it's always accurate. */ - cs = _cur_pcs.consuming_commands[_cur_argidx++]; - if (cs == nullptr) { + cmd = _cur_pcs.consuming_commands[_cur_argidx++]; + if (cmd == nullptr) { StrgenFatal("{}: No argument exists at position {}", _cur_ident, _cur_argidx - 1); } } - cs->proc(buffer, param.data(), cs->value); + cmd->proc(buffer, cs.param.data(), cmd->value); } } diff --git a/src/table/strgen_tables.h b/src/table/strgen_tables.h index ca687c10b5..0c0c399f76 100644 --- a/src/table/strgen_tables.h +++ b/src/table/strgen_tables.h @@ -24,7 +24,7 @@ struct CmdStruct { ParseCmdProc proc; long value; uint8_t consumes; - int8_t default_plural_offset; + std::optional default_plural_offset; CmdFlags flags; }; @@ -34,49 +34,49 @@ extern void EmitGender(Buffer *buffer, char *buf, int value); static const CmdStruct _cmd_structs[] = { /* Font size */ - {"NORMAL_FONT", EmitSingleChar, SCC_NORMALFONT, 0, -1, {}}, - {"TINY_FONT", EmitSingleChar, SCC_TINYFONT, 0, -1, {}}, - {"BIG_FONT", EmitSingleChar, SCC_BIGFONT, 0, -1, {}}, - {"MONO_FONT", EmitSingleChar, SCC_MONOFONT, 0, -1, {}}, + {"NORMAL_FONT", EmitSingleChar, SCC_NORMALFONT, 0, std::nullopt, {}}, + {"TINY_FONT", EmitSingleChar, SCC_TINYFONT, 0, std::nullopt, {}}, + {"BIG_FONT", EmitSingleChar, SCC_BIGFONT, 0, std::nullopt, {}}, + {"MONO_FONT", EmitSingleChar, SCC_MONOFONT, 0, std::nullopt, {}}, /* Colours */ - {"BLUE", EmitSingleChar, SCC_BLUE, 0, -1, {CmdFlag::DontCount}}, - {"SILVER", EmitSingleChar, SCC_SILVER, 0, -1, {CmdFlag::DontCount}}, - {"GOLD", EmitSingleChar, SCC_GOLD, 0, -1, {CmdFlag::DontCount}}, - {"RED", EmitSingleChar, SCC_RED, 0, -1, {CmdFlag::DontCount}}, - {"PURPLE", EmitSingleChar, SCC_PURPLE, 0, -1, {CmdFlag::DontCount}}, - {"LTBROWN", EmitSingleChar, SCC_LTBROWN, 0, -1, {CmdFlag::DontCount}}, - {"ORANGE", EmitSingleChar, SCC_ORANGE, 0, -1, {CmdFlag::DontCount}}, - {"GREEN", EmitSingleChar, SCC_GREEN, 0, -1, {CmdFlag::DontCount}}, - {"YELLOW", EmitSingleChar, SCC_YELLOW, 0, -1, {CmdFlag::DontCount}}, - {"DKGREEN", EmitSingleChar, SCC_DKGREEN, 0, -1, {CmdFlag::DontCount}}, - {"CREAM", EmitSingleChar, SCC_CREAM, 0, -1, {CmdFlag::DontCount}}, - {"BROWN", EmitSingleChar, SCC_BROWN, 0, -1, {CmdFlag::DontCount}}, - {"WHITE", EmitSingleChar, SCC_WHITE, 0, -1, {CmdFlag::DontCount}}, - {"LTBLUE", EmitSingleChar, SCC_LTBLUE, 0, -1, {CmdFlag::DontCount}}, - {"GRAY", EmitSingleChar, SCC_GRAY, 0, -1, {CmdFlag::DontCount}}, - {"DKBLUE", EmitSingleChar, SCC_DKBLUE, 0, -1, {CmdFlag::DontCount}}, - {"BLACK", EmitSingleChar, SCC_BLACK, 0, -1, {CmdFlag::DontCount}}, - {"COLOUR", EmitSingleChar, SCC_COLOUR, 1, -1, {}}, - {"PUSH_COLOUR", EmitSingleChar, SCC_PUSH_COLOUR, 0, -1, {CmdFlag::DontCount}}, - {"POP_COLOUR", EmitSingleChar, SCC_POP_COLOUR, 0, -1, {CmdFlag::DontCount}}, + {"BLUE", EmitSingleChar, SCC_BLUE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"SILVER", EmitSingleChar, SCC_SILVER, 0, std::nullopt, {CmdFlag::DontCount}}, + {"GOLD", EmitSingleChar, SCC_GOLD, 0, std::nullopt, {CmdFlag::DontCount}}, + {"RED", EmitSingleChar, SCC_RED, 0, std::nullopt, {CmdFlag::DontCount}}, + {"PURPLE", EmitSingleChar, SCC_PURPLE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"LTBROWN", EmitSingleChar, SCC_LTBROWN, 0, std::nullopt, {CmdFlag::DontCount}}, + {"ORANGE", EmitSingleChar, SCC_ORANGE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"GREEN", EmitSingleChar, SCC_GREEN, 0, std::nullopt, {CmdFlag::DontCount}}, + {"YELLOW", EmitSingleChar, SCC_YELLOW, 0, std::nullopt, {CmdFlag::DontCount}}, + {"DKGREEN", EmitSingleChar, SCC_DKGREEN, 0, std::nullopt, {CmdFlag::DontCount}}, + {"CREAM", EmitSingleChar, SCC_CREAM, 0, std::nullopt, {CmdFlag::DontCount}}, + {"BROWN", EmitSingleChar, SCC_BROWN, 0, std::nullopt, {CmdFlag::DontCount}}, + {"WHITE", EmitSingleChar, SCC_WHITE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"LTBLUE", EmitSingleChar, SCC_LTBLUE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"GRAY", EmitSingleChar, SCC_GRAY, 0, std::nullopt, {CmdFlag::DontCount}}, + {"DKBLUE", EmitSingleChar, SCC_DKBLUE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"BLACK", EmitSingleChar, SCC_BLACK, 0, std::nullopt, {CmdFlag::DontCount}}, + {"COLOUR", EmitSingleChar, SCC_COLOUR, 1, std::nullopt, {}}, + {"PUSH_COLOUR", EmitSingleChar, SCC_PUSH_COLOUR, 0, std::nullopt, {CmdFlag::DontCount}}, + {"POP_COLOUR", EmitSingleChar, SCC_POP_COLOUR, 0, std::nullopt, {CmdFlag::DontCount}}, - {"REV", EmitSingleChar, SCC_REVISION, 0, -1, {}}, // openttd revision string + {"REV", EmitSingleChar, SCC_REVISION, 0, std::nullopt, {}}, // openttd revision string - {"STRING1", EmitSingleChar, SCC_STRING1, 2, -1, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and ONE argument - {"STRING2", EmitSingleChar, SCC_STRING2, 3, -1, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and TWO arguments - {"STRING3", EmitSingleChar, SCC_STRING3, 4, -1, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and THREE arguments - {"STRING4", EmitSingleChar, SCC_STRING4, 5, -1, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and FOUR arguments - {"STRING5", EmitSingleChar, SCC_STRING5, 6, -1, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and FIVE arguments - {"STRING6", EmitSingleChar, SCC_STRING6, 7, -1, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and SIX arguments - {"STRING7", EmitSingleChar, SCC_STRING7, 8, -1, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and SEVEN arguments + {"STRING1", EmitSingleChar, SCC_STRING1, 2, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and ONE argument + {"STRING2", EmitSingleChar, SCC_STRING2, 3, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and TWO arguments + {"STRING3", EmitSingleChar, SCC_STRING3, 4, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and THREE arguments + {"STRING4", EmitSingleChar, SCC_STRING4, 5, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and FOUR arguments + {"STRING5", EmitSingleChar, SCC_STRING5, 6, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and FIVE arguments + {"STRING6", EmitSingleChar, SCC_STRING6, 7, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and SIX arguments + {"STRING7", EmitSingleChar, SCC_STRING7, 8, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // included string that consumes the string id and SEVEN arguments - {"STATION_FEATURES", EmitSingleChar, SCC_STATION_FEATURES, 1, -1, {}}, // station features string, icons of the features - {"INDUSTRY", EmitSingleChar, SCC_INDUSTRY_NAME, 1, -1, {CmdFlag::Case, CmdFlag::Gender}}, // industry, takes an industry #, can have cases + {"STATION_FEATURES", EmitSingleChar, SCC_STATION_FEATURES, 1, std::nullopt, {}}, // station features string, icons of the features + {"INDUSTRY", EmitSingleChar, SCC_INDUSTRY_NAME, 1, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, // industry, takes an industry #, can have cases {"CARGO_LONG", EmitSingleChar, SCC_CARGO_LONG, 2, 1, {CmdFlag::Gender}}, {"CARGO_SHORT", EmitSingleChar, SCC_CARGO_SHORT, 2, 1, {CmdFlag::Gender}}, // short cargo description, only ### tons, or ### litres {"CARGO_TINY", EmitSingleChar, SCC_CARGO_TINY, 2, 1, {}}, // tiny cargo description with only the amount, not a specifier for the amount or the actual cargo name - {"CARGO_LIST", EmitSingleChar, SCC_CARGO_LIST, 1, -1, {CmdFlag::Case}}, + {"CARGO_LIST", EmitSingleChar, SCC_CARGO_LIST, 1, std::nullopt, {CmdFlag::Case}}, {"POWER", EmitSingleChar, SCC_POWER, 1, 0, {}}, {"POWER_TO_WEIGHT", EmitSingleChar, SCC_POWER_TO_WEIGHT, 1, 0, {}}, {"VOLUME_LONG", EmitSingleChar, SCC_VOLUME_LONG, 1, 0, {}}, @@ -92,16 +92,16 @@ static const CmdStruct _cmd_structs[] = { {"UNITS_YEARS_OR_PERIODS", EmitSingleChar, SCC_UNITS_YEARS_OR_PERIODS, 1, 0, {CmdFlag::Gender}}, {"UNITS_YEARS_OR_MINUTES", EmitSingleChar, SCC_UNITS_YEARS_OR_MINUTES, 1, 0, {CmdFlag::Gender}}, - {"P", EmitPlural, 0, 0, -1, {CmdFlag::DontCount}}, // plural specifier - {"G", EmitGender, 0, 0, -1, {CmdFlag::DontCount}}, // gender specifier + {"P", EmitPlural, 0, 0, std::nullopt, {CmdFlag::DontCount}}, // plural specifier + {"G", EmitGender, 0, 0, std::nullopt, {CmdFlag::DontCount}}, // gender specifier - {"DATE_TINY", EmitSingleChar, SCC_DATE_TINY, 1, -1, {}}, - {"DATE_SHORT", EmitSingleChar, SCC_DATE_SHORT, 1, -1, {CmdFlag::Case}}, - {"DATE_LONG", EmitSingleChar, SCC_DATE_LONG, 1, -1, {CmdFlag::Case}}, - {"DATE_ISO", EmitSingleChar, SCC_DATE_ISO, 1, -1, {}}, + {"DATE_TINY", EmitSingleChar, SCC_DATE_TINY, 1, std::nullopt, {}}, + {"DATE_SHORT", EmitSingleChar, SCC_DATE_SHORT, 1, std::nullopt, {CmdFlag::Case}}, + {"DATE_LONG", EmitSingleChar, SCC_DATE_LONG, 1, std::nullopt, {CmdFlag::Case}}, + {"DATE_ISO", EmitSingleChar, SCC_DATE_ISO, 1, std::nullopt, {}}, - {"STRING", EmitSingleChar, SCC_STRING, 1, -1, {CmdFlag::Case, CmdFlag::Gender}}, - {"RAW_STRING", EmitSingleChar, SCC_RAW_STRING_POINTER, 1, -1, {CmdFlag::Gender}}, + {"STRING", EmitSingleChar, SCC_STRING, 1, std::nullopt, {CmdFlag::Case, CmdFlag::Gender}}, + {"RAW_STRING", EmitSingleChar, SCC_RAW_STRING_POINTER, 1, std::nullopt, {CmdFlag::Gender}}, /* Numbers */ {"COMMA", EmitSingleChar, SCC_COMMA, 1, 0, {}}, // Number with comma @@ -114,47 +114,47 @@ static const CmdStruct _cmd_structs[] = { {"CURRENCY_LONG", EmitSingleChar, SCC_CURRENCY_LONG, 1, 0, {}}, {"CURRENCY_SHORT", EmitSingleChar, SCC_CURRENCY_SHORT, 1, 0, {}}, // compact currency - {"WAYPOINT", EmitSingleChar, SCC_WAYPOINT_NAME, 1, -1, {CmdFlag::Gender}}, // waypoint name - {"STATION", EmitSingleChar, SCC_STATION_NAME, 1, -1, {CmdFlag::Gender}}, - {"DEPOT", EmitSingleChar, SCC_DEPOT_NAME, 2, -1, {CmdFlag::Gender}}, - {"TOWN", EmitSingleChar, SCC_TOWN_NAME, 1, -1, {CmdFlag::Gender}}, - {"GROUP", EmitSingleChar, SCC_GROUP_NAME, 1, -1, {CmdFlag::Gender}}, - {"SIGN", EmitSingleChar, SCC_SIGN_NAME, 1, -1, {CmdFlag::Gender}}, - {"ENGINE", EmitSingleChar, SCC_ENGINE_NAME, 1, -1, {CmdFlag::Gender}}, - {"VEHICLE", EmitSingleChar, SCC_VEHICLE_NAME, 1, -1, {CmdFlag::Gender}}, - {"COMPANY", EmitSingleChar, SCC_COMPANY_NAME, 1, -1, {CmdFlag::Gender}}, - {"COMPANY_NUM", EmitSingleChar, SCC_COMPANY_NUM, 1, -1, {}}, - {"PRESIDENT_NAME", EmitSingleChar, SCC_PRESIDENT_NAME, 1, -1, {CmdFlag::Gender}}, + {"WAYPOINT", EmitSingleChar, SCC_WAYPOINT_NAME, 1, std::nullopt, {CmdFlag::Gender}}, // waypoint name + {"STATION", EmitSingleChar, SCC_STATION_NAME, 1, std::nullopt, {CmdFlag::Gender}}, + {"DEPOT", EmitSingleChar, SCC_DEPOT_NAME, 2, std::nullopt, {CmdFlag::Gender}}, + {"TOWN", EmitSingleChar, SCC_TOWN_NAME, 1, std::nullopt, {CmdFlag::Gender}}, + {"GROUP", EmitSingleChar, SCC_GROUP_NAME, 1, std::nullopt, {CmdFlag::Gender}}, + {"SIGN", EmitSingleChar, SCC_SIGN_NAME, 1, std::nullopt, {CmdFlag::Gender}}, + {"ENGINE", EmitSingleChar, SCC_ENGINE_NAME, 1, std::nullopt, {CmdFlag::Gender}}, + {"VEHICLE", EmitSingleChar, SCC_VEHICLE_NAME, 1, std::nullopt, {CmdFlag::Gender}}, + {"COMPANY", EmitSingleChar, SCC_COMPANY_NAME, 1, std::nullopt, {CmdFlag::Gender}}, + {"COMPANY_NUM", EmitSingleChar, SCC_COMPANY_NUM, 1, std::nullopt, {}}, + {"PRESIDENT_NAME", EmitSingleChar, SCC_PRESIDENT_NAME, 1, std::nullopt, {CmdFlag::Gender}}, - {"SPACE", EmitSingleChar, ' ', 0, -1, {CmdFlag::DontCount}}, - {"", EmitSingleChar, '\n', 0, -1, {CmdFlag::DontCount}}, - {"{", EmitSingleChar, '{', 0, -1, {CmdFlag::DontCount}}, - {"UP_ARROW", EmitSingleChar, SCC_UP_ARROW, 0, -1, {CmdFlag::DontCount}}, - {"SMALL_UP_ARROW", EmitSingleChar, SCC_SMALL_UP_ARROW, 0, -1, {CmdFlag::DontCount}}, - {"SMALL_DOWN_ARROW", EmitSingleChar, SCC_SMALL_DOWN_ARROW, 0, -1, {CmdFlag::DontCount}}, - {"TRAIN", EmitSingleChar, SCC_TRAIN, 0, -1, {CmdFlag::DontCount}}, - {"LORRY", EmitSingleChar, SCC_LORRY, 0, -1, {CmdFlag::DontCount}}, - {"BUS", EmitSingleChar, SCC_BUS, 0, -1, {CmdFlag::DontCount}}, - {"PLANE", EmitSingleChar, SCC_PLANE, 0, -1, {CmdFlag::DontCount}}, - {"SHIP", EmitSingleChar, SCC_SHIP, 0, -1, {CmdFlag::DontCount}}, - {"NBSP", EmitSingleChar, 0xA0, 0, -1, {CmdFlag::DontCount}}, - {"COPYRIGHT", EmitSingleChar, 0xA9, 0, -1, {CmdFlag::DontCount}}, - {"DOWN_ARROW", EmitSingleChar, SCC_DOWN_ARROW, 0, -1, {CmdFlag::DontCount}}, - {"CHECKMARK", EmitSingleChar, SCC_CHECKMARK, 0, -1, {CmdFlag::DontCount}}, - {"CROSS", EmitSingleChar, SCC_CROSS, 0, -1, {CmdFlag::DontCount}}, - {"RIGHT_ARROW", EmitSingleChar, SCC_RIGHT_ARROW, 0, -1, {CmdFlag::DontCount}}, - {"SMALL_LEFT_ARROW", EmitSingleChar, SCC_LESS_THAN, 0, -1, {CmdFlag::DontCount}}, - {"SMALL_RIGHT_ARROW", EmitSingleChar, SCC_GREATER_THAN, 0, -1, {CmdFlag::DontCount}}, + {"SPACE", EmitSingleChar, ' ', 0, std::nullopt, {CmdFlag::DontCount}}, + {"", EmitSingleChar, '\n', 0, std::nullopt, {CmdFlag::DontCount}}, + {"{", EmitSingleChar, '{', 0, std::nullopt, {CmdFlag::DontCount}}, + {"UP_ARROW", EmitSingleChar, SCC_UP_ARROW, 0, std::nullopt, {CmdFlag::DontCount}}, + {"SMALL_UP_ARROW", EmitSingleChar, SCC_SMALL_UP_ARROW, 0, std::nullopt, {CmdFlag::DontCount}}, + {"SMALL_DOWN_ARROW", EmitSingleChar, SCC_SMALL_DOWN_ARROW, 0, std::nullopt, {CmdFlag::DontCount}}, + {"TRAIN", EmitSingleChar, SCC_TRAIN, 0, std::nullopt, {CmdFlag::DontCount}}, + {"LORRY", EmitSingleChar, SCC_LORRY, 0, std::nullopt, {CmdFlag::DontCount}}, + {"BUS", EmitSingleChar, SCC_BUS, 0, std::nullopt, {CmdFlag::DontCount}}, + {"PLANE", EmitSingleChar, SCC_PLANE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"SHIP", EmitSingleChar, SCC_SHIP, 0, std::nullopt, {CmdFlag::DontCount}}, + {"NBSP", EmitSingleChar, 0xA0, 0, std::nullopt, {CmdFlag::DontCount}}, + {"COPYRIGHT", EmitSingleChar, 0xA9, 0, std::nullopt, {CmdFlag::DontCount}}, + {"DOWN_ARROW", EmitSingleChar, SCC_DOWN_ARROW, 0, std::nullopt, {CmdFlag::DontCount}}, + {"CHECKMARK", EmitSingleChar, SCC_CHECKMARK, 0, std::nullopt, {CmdFlag::DontCount}}, + {"CROSS", EmitSingleChar, SCC_CROSS, 0, std::nullopt, {CmdFlag::DontCount}}, + {"RIGHT_ARROW", EmitSingleChar, SCC_RIGHT_ARROW, 0, std::nullopt, {CmdFlag::DontCount}}, + {"SMALL_LEFT_ARROW", EmitSingleChar, SCC_LESS_THAN, 0, std::nullopt, {CmdFlag::DontCount}}, + {"SMALL_RIGHT_ARROW", EmitSingleChar, SCC_GREATER_THAN, 0, std::nullopt, {CmdFlag::DontCount}}, /* The following are directional formatting codes used to get the RTL strings right: * http://www.unicode.org/unicode/reports/tr9/#Directional_Formatting_Codes */ - {"LRM", EmitSingleChar, CHAR_TD_LRM, 0, -1, {CmdFlag::DontCount}}, - {"RLM", EmitSingleChar, CHAR_TD_RLM, 0, -1, {CmdFlag::DontCount}}, - {"LRE", EmitSingleChar, CHAR_TD_LRE, 0, -1, {CmdFlag::DontCount}}, - {"RLE", EmitSingleChar, CHAR_TD_RLE, 0, -1, {CmdFlag::DontCount}}, - {"LRO", EmitSingleChar, CHAR_TD_LRO, 0, -1, {CmdFlag::DontCount}}, - {"RLO", EmitSingleChar, CHAR_TD_RLO, 0, -1, {CmdFlag::DontCount}}, - {"PDF", EmitSingleChar, CHAR_TD_PDF, 0, -1, {CmdFlag::DontCount}}, + {"LRM", EmitSingleChar, CHAR_TD_LRM, 0, std::nullopt, {CmdFlag::DontCount}}, + {"RLM", EmitSingleChar, CHAR_TD_RLM, 0, std::nullopt, {CmdFlag::DontCount}}, + {"LRE", EmitSingleChar, CHAR_TD_LRE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"RLE", EmitSingleChar, CHAR_TD_RLE, 0, std::nullopt, {CmdFlag::DontCount}}, + {"LRO", EmitSingleChar, CHAR_TD_LRO, 0, std::nullopt, {CmdFlag::DontCount}}, + {"RLO", EmitSingleChar, CHAR_TD_RLO, 0, std::nullopt, {CmdFlag::DontCount}}, + {"PDF", EmitSingleChar, CHAR_TD_PDF, 0, std::nullopt, {CmdFlag::DontCount}}, }; /** Description of a plural form */