summaryrefslogtreecommitdiff
path: root/src/settingsgen
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-03-01 13:12:17 +0100
committerPatric Stout <github@truebrain.nl>2021-03-01 23:17:47 +0100
commit74aa934441351334e40d8963900b8a2fbc9bc9cd (patch)
tree1257efebb69111b35c5026d59c0504088faff0d8 /src/settingsgen
parentd7a70c67bacef7453ae56e9136c9c16e4b19c314 (diff)
downloadopenttd-74aa934441351334e40d8963900b8a2fbc9bc9cd.tar.xz
Codechange: validate that "max" value of settings fit in their storage
This is an easy mistake to make, so protect us against making such mistakes, by validating it doesn't happen.
Diffstat (limited to 'src/settingsgen')
-rw-r--r--src/settingsgen/settingsgen.cpp139
1 files changed, 82 insertions, 57 deletions
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);