diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/settings_type.h | 9 | ||||
-rw-r--r-- | src/settingsgen/settingsgen.cpp | 139 | ||||
-rw-r--r-- | src/table/company_settings.ini | 3 | ||||
-rw-r--r-- | src/table/currency_settings.ini | 3 | ||||
-rw-r--r-- | src/table/gameopt_settings.ini | 7 | ||||
-rw-r--r-- | src/table/misc_settings.ini | 4 | ||||
-rw-r--r-- | src/table/settings.ini | 8 | ||||
-rw-r--r-- | src/table/win32_settings.ini | 3 | ||||
-rw-r--r-- | src/table/window_settings.ini | 3 |
9 files changed, 122 insertions, 57 deletions
diff --git a/src/settings_type.h b/src/settings_type.h index f2c591f64..433e8d535 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -21,6 +21,15 @@ #include "zoom_type.h" #include "openttd.h" +/* Used to validate sizes of "max" value in settings. */ +const size_t MAX_SLE_UINT8 = UINT8_MAX; +const size_t MAX_SLE_UINT16 = UINT16_MAX; +const size_t MAX_SLE_UINT32 = UINT32_MAX; +const size_t MAX_SLE_UINT = UINT_MAX; +const size_t MAX_SLE_INT8 = INT8_MAX; +const size_t MAX_SLE_INT16 = INT16_MAX; +const size_t MAX_SLE_INT32 = INT32_MAX; +const size_t MAX_SLE_INT = INT_MAX; /** Settings profiles and highscore tables. */ enum SettingsProfile { diff --git a/src/settingsgen/settingsgen.cpp b/src/settingsgen/settingsgen.cpp index ac3a2a85a..8dd9ff6f4 100644 --- a/src/settingsgen/settingsgen.cpp +++ b/src/settingsgen/settingsgen.cpp @@ -186,11 +186,13 @@ struct SettingsIniFile : IniLoadFile { }; OutputStore _stored_output; ///< Temporary storage of the output, until all processing is done. +OutputStore _post_amble_output; ///< Similar to _stored_output, but for the post amble. -static const char *PREAMBLE_GROUP_NAME = "pre-amble"; ///< Name of the group containing the pre amble. +static const char *PREAMBLE_GROUP_NAME = "pre-amble"; ///< Name of the group containing the pre amble. static const char *POSTAMBLE_GROUP_NAME = "post-amble"; ///< Name of the group containing the post amble. -static const char *TEMPLATES_GROUP_NAME = "templates"; ///< Name of the group containing the templates. -static const char *DEFAULTS_GROUP_NAME = "defaults"; ///< Name of the group containing default values for the template variables. +static const char *TEMPLATES_GROUP_NAME = "templates"; ///< Name of the group containing the templates. +static const char *VALIDATION_GROUP_NAME = "validation"; ///< Name of the group containing the validation statements. +static const char *DEFAULTS_GROUP_NAME = "defaults"; ///< Name of the group containing default values for the template variables. /** * Load the INI file. @@ -240,16 +242,83 @@ static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defa } /** + * Parse a single entry via a template and output this. + * @param item The template to use for the output. + * @param grp Group current being used for template rendering. + * @param default_grp Default values for items not set in @grp. + * @param output Output to use for result. + */ +static void DumpLine(IniItem *item, IniGroup *grp, IniGroup *default_grp, OutputStore &output) +{ + static const int MAX_VAR_LENGTH = 64; + + /* Prefix with #if/#ifdef/#ifndef */ + static const char * const pp_lines[] = {"if", "ifdef", "ifndef", nullptr}; + int count = 0; + for (const char * const *name = pp_lines; *name != nullptr; name++) { + const char *condition = FindItemValue(*name, grp, default_grp); + if (condition != nullptr) { + output.Add("#", 1); + output.Add(*name); + output.Add(" ", 1); + output.Add(condition); + output.Add("\n", 1); + count++; + } + } + + /* Output text of the template, except template variables of the form '$[_a-z0-9]+' which get replaced by their value. */ + const char *txt = item->value->c_str(); + while (*txt != '\0') { + if (*txt != '$') { + output.Add(txt, 1); + txt++; + continue; + } + txt++; + if (*txt == '$') { // Literal $ + output.Add(txt, 1); + txt++; + continue; + } + + /* Read variable. */ + char variable[MAX_VAR_LENGTH]; + int i = 0; + while (i < MAX_VAR_LENGTH - 1) { + if (!(txt[i] == '_' || (txt[i] >= 'a' && txt[i] <= 'z') || (txt[i] >= '0' && txt[i] <= '9'))) break; + variable[i] = txt[i]; + i++; + } + variable[i] = '\0'; + txt += i; + + if (i > 0) { + /* Find the text to output. */ + const char *valitem = FindItemValue(variable, grp, default_grp); + if (valitem != nullptr) output.Add(valitem); + } else { + output.Add("$", 1); + } + } + output.Add("\n", 1); // \n after the expanded template. + while (count > 0) { + output.Add("#endif\n"); + count--; + } +} + +/** * Output all non-special sections through the template / template variable expansion system. * @param ifile Loaded INI data. */ static void DumpSections(IniLoadFile *ifile) { - static const int MAX_VAR_LENGTH = 64; - static const char * const special_group_names[] = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, nullptr}; + static const char * const special_group_names[] = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, VALIDATION_GROUP_NAME, nullptr}; IniGroup *default_grp = ifile->GetGroup(DEFAULTS_GROUP_NAME, false); IniGroup *templates_grp = ifile->GetGroup(TEMPLATES_GROUP_NAME, false); + IniGroup *validation_grp = ifile->GetGroup(VALIDATION_GROUP_NAME, false); if (templates_grp == nullptr) return; /* Output every group, using its name as template name. */ @@ -263,61 +332,14 @@ static void DumpSections(IniLoadFile *ifile) fprintf(stderr, "settingsgen: Warning: Cannot find template %s\n", grp->name.c_str()); continue; } + DumpLine(template_item, grp, default_grp, _stored_output); - /* Prefix with #if/#ifdef/#ifndef */ - static const char * const pp_lines[] = {"if", "ifdef", "ifndef", nullptr}; - int count = 0; - for (const char * const *name = pp_lines; *name != nullptr; name++) { - const char *condition = FindItemValue(*name, grp, default_grp); - if (condition != nullptr) { - _stored_output.Add("#", 1); - _stored_output.Add(*name); - _stored_output.Add(" ", 1); - _stored_output.Add(condition); - _stored_output.Add("\n", 1); - count++; + if (validation_grp != nullptr) { + IniItem *validation_item = validation_grp->GetItem(grp->name, false); // Find template value. + if (validation_item != nullptr && validation_item->value.has_value()) { + DumpLine(validation_item, grp, default_grp, _post_amble_output); } } - - /* Output text of the template, except template variables of the form '$[_a-z0-9]+' which get replaced by their value. */ - const char *txt = template_item->value->c_str(); - while (*txt != '\0') { - if (*txt != '$') { - _stored_output.Add(txt, 1); - txt++; - continue; - } - txt++; - if (*txt == '$') { // Literal $ - _stored_output.Add(txt, 1); - txt++; - continue; - } - - /* Read variable. */ - char variable[MAX_VAR_LENGTH]; - int i = 0; - while (i < MAX_VAR_LENGTH - 1) { - if (!(txt[i] == '_' || (txt[i] >= 'a' && txt[i] <= 'z') || (txt[i] >= '0' && txt[i] <= '9'))) break; - variable[i] = txt[i]; - i++; - } - variable[i] = '\0'; - txt += i; - - if (i > 0) { - /* Find the text to output. */ - const char *valitem = FindItemValue(variable, grp, default_grp); - if (valitem != nullptr) _stored_output.Add(valitem); - } else { - _stored_output.Add("$", 1); - } - } - _stored_output.Add("\n", 1); // \n after the expanded template. - while (count > 0) { - _stored_output.Add("#endif\n"); - count--; - } } } @@ -476,6 +498,7 @@ int CDECL main(int argc, char *argv[]) } _stored_output.Clear(); + _post_amble_output.Clear(); for (int i = 0; i < mgo.numleft; i++) ProcessIniFile(mgo.argv[i]); @@ -483,6 +506,7 @@ int CDECL main(int argc, char *argv[]) if (output_file == nullptr) { CopyFile(before_file, stdout); _stored_output.Write(stdout); + _post_amble_output.Write(stdout); CopyFile(after_file, stdout); } else { static const char * const tmp_output = "tmp2.xxx"; @@ -494,6 +518,7 @@ int CDECL main(int argc, char *argv[]) } CopyFile(before_file, fp); _stored_output.Write(fp); + _post_amble_output.Write(fp); CopyFile(after_file, fp); fclose(fp); diff --git a/src/table/company_settings.ini b/src/table/company_settings.ini index e685ff6dc..eea2371fc 100644 --- a/src/table/company_settings.ini +++ b/src/table/company_settings.ini @@ -20,6 +20,9 @@ SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_END = SDT_END() +[validation] +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); + [defaults] flags = 0 guiflags = SGF_PER_COMPANY diff --git a/src/table/currency_settings.ini b/src/table/currency_settings.ini index 7ff879964..c242c83a8 100644 --- a/src/table/currency_settings.ini +++ b/src/table/currency_settings.ini @@ -14,6 +14,9 @@ SDT_CHR = SDT_CHR($base, $var, $flags, $guiflags, $def, SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_END = SDT_END() +[validation] +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); + [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NONE diff --git a/src/table/gameopt_settings.ini b/src/table/gameopt_settings.ini index b85e11d9c..c4140f428 100644 --- a/src/table/gameopt_settings.ini +++ b/src/table/gameopt_settings.ini @@ -46,6 +46,13 @@ SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $ma SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_END = SDT_END() +[validation] +SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDTC_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); + [defaults] flags = 0 guiflags = SGF_NONE diff --git a/src/table/misc_settings.ini b/src/table/misc_settings.ini index 3add5148f..9d2f76cc0 100644 --- a/src/table/misc_settings.ini +++ b/src/table/misc_settings.ini @@ -26,6 +26,10 @@ SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_END = SDTG_END() +[validation] +SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); + [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NONE diff --git a/src/table/settings.ini b/src/table/settings.ini index dd0ecfee5..b48ac6cd6 100644 --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -77,6 +77,14 @@ SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, SDT_NULL = SDT_NULL($length, $from, $to), SDT_END = SDT_END() +[validation] +SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDTC_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDTC_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); +SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); + [defaults] flags = 0 guiflags = SGF_NONE diff --git a/src/table/win32_settings.ini b/src/table/win32_settings.ini index 406e8dd8f..c3cc45014 100644 --- a/src/table/win32_settings.ini +++ b/src/table/win32_settings.ini @@ -18,6 +18,9 @@ SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDTG_END = SDTG_END() +[validation] +SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size"); + [defaults] flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC guiflags = SGF_NONE diff --git a/src/table/window_settings.ini b/src/table/window_settings.ini index e336d6447..fb252076c 100644 --- a/src/table/window_settings.ini +++ b/src/table/window_settings.ini @@ -14,6 +14,9 @@ SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup), SDT_END = SDT_END() +[validation] +SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size"); + [defaults] base = WindowDesc flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC |