From: Alberto Leiva Popper Date: Sun, 24 Mar 2019 23:34:04 +0000 (-0600) Subject: Patch TOML parsing quirks found while documenting X-Git-Tag: v0.0.2~58 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9ddd7012809b0247f2415ece1c98a1145aa177ff;p=thirdparty%2FFORT-validator.git Patch TOML parsing quirks found while documenting - Was complaining about missing optional fields - Was freeing fields using the wrong function --- diff --git a/src/config/boolean.c b/src/config/boolean.c index c71e924b..0a6ceb2f 100644 --- a/src/config/boolean.c +++ b/src/config/boolean.c @@ -47,7 +47,7 @@ parse_toml_bool(struct option_field const *opt, struct toml_table_t *toml, raw = toml_raw_in(toml, opt->name); if (raw == NULL) - return pr_err("TOML boolean '%s' was not found.", opt->name); + return 0; if (toml_rtob(raw, &value) == -1) return pr_err("Cannot parse '%s' as a boolean.", raw); diff --git a/src/config/filename_format.c b/src/config/filename_format.c index a2fe2512..4bc805da 100644 --- a/src/config/filename_format.c +++ b/src/config/filename_format.c @@ -58,10 +58,11 @@ parse_toml_filename_format(struct option_field const *opt, char *string; int error; - string = NULL; - error = parse_toml_string(opt, toml, &string); + error = parse_toml_string(toml, opt->name, &string); if (error) return error; + if (string == NULL) + return 0; error = parse_argv_filename_format(opt, string, _result); diff --git a/src/config/out_file.c b/src/config/out_file.c index b701322c..008e26db 100644 --- a/src/config/out_file.c +++ b/src/config/out_file.c @@ -8,6 +8,18 @@ #include "log.h" #include "config/str.h" +static void +__free_out_file(struct config_out_file *file) +{ + if (file->fd != NULL) { + fclose(file->fd); + file->fd = NULL; + } + + free(file->file_name); + file->file_name = NULL; +} + static void print_out_file(struct group_fields const *group, struct option_field const *field, void *value) @@ -23,7 +35,7 @@ parse_argv_out_file(struct option_field const *field, char const *file_name, struct config_out_file *file = _result; int error; - field->type->free(file); + __free_out_file(file); file->file_name = strdup(file_name); if (file->file_name == NULL) @@ -47,10 +59,11 @@ parse_toml_out_file(struct option_field const *opt, struct toml_table_t *toml, char *file_name; int error; - file_name = NULL; - error = parse_toml_string(opt, toml, &file_name); + error = parse_toml_string(toml, opt->name, &file_name); if (error) return error; + if (file_name == NULL) + return 0; error = parse_argv_out_file(opt, file_name, _result); @@ -59,17 +72,9 @@ parse_toml_out_file(struct option_field const *opt, struct toml_table_t *toml, } static void -free_out_file(void *_file) +free_out_file(void *file) { - struct config_out_file *file = _file; - - if (file->fd != NULL) { - fclose(file->fd); - file->fd = NULL; - } - - free(file->file_name); - file->file_name = NULL; + __free_out_file(file); } const struct global_type gt_out_file = { diff --git a/src/config/str.c b/src/config/str.c index 6ed24674..4be654bd 100644 --- a/src/config/str.c +++ b/src/config/str.c @@ -6,67 +6,88 @@ #include "log.h" static void -print_string(struct group_fields const *group, struct option_field const *field, +__string_free(char **string) +{ + free(*string); + *string = NULL; +} + +static void +string_print(struct group_fields const *group, struct option_field const *field, void *value) { pr_info("%s.%s: %s", group->name, field->name, *((char **) value)); } static int -parse_argv_string(struct option_field const *field, char const *str, +string_parse_argv(struct option_field const *field, char const *str, void *_result) { char **result = _result; - /* Remove the previous value (usually the default). */ - field->type->free(result); - if (field->type->has_arg != required_argument || str == NULL) { return pr_err("String options ('%s' in this case) require an argument.", field->name); } + /* Remove the previous value (usually the default). */ + __string_free(result); + /* tomlc99 frees @str early, so work with a copy. */ *result = strdup(str); return ((*result) != NULL) ? 0 : pr_enomem(); } -int -parse_toml_string(struct option_field const *opt, struct toml_table_t *toml, +static int +string_parse_toml(struct option_field const *opt, struct toml_table_t *toml, void *_result) { - const char *raw; - char *value; + char *tmp; char **result; + int error; - /* Remove the previous value (usually the default). */ - opt->type->free(_result); - - raw = toml_raw_in(toml, opt->name); - if (raw == NULL) - return pr_err("TOML string '%s' was not found.", opt->name); - if (toml_rtos(raw, &value) == -1) - return pr_err("Cannot parse '%s' as a string.", raw); + error = parse_toml_string(toml, opt->name, &tmp); + if (error) + return error; + if (tmp == NULL) + return 0; result = _result; - *result = value; + __string_free(result); + *result = tmp; return 0; } static void -free_string(void *_string) +string_free(void *string) { - char **string = _string; - free(*string); - *string = NULL; + __string_free(string); } const struct global_type gt_string = { .has_arg = required_argument, .size = sizeof(char *), - .print = print_string, - .parse.argv = parse_argv_string, - .parse.toml = parse_toml_string, - .free = free_string, + .print = string_print, + .parse.argv = string_parse_argv, + .parse.toml = string_parse_toml, + .free = string_free, .arg_doc = "", }; + +int +parse_toml_string(struct toml_table_t *toml, char const *name, char **result) +{ + const char *raw; + char *value; + + raw = toml_raw_in(toml, name); + if (raw == NULL) { + *result = NULL; + return 0; + } + if (toml_rtos(raw, &value) == -1) + return pr_err("Cannot parse '%s' as a string.", raw); + + *result = value; + return 0; +} diff --git a/src/config/str.h b/src/config/str.h index f2cbfc4b..7cb592ed 100644 --- a/src/config/str.h +++ b/src/config/str.h @@ -5,7 +5,6 @@ extern const struct global_type gt_string; -int parse_toml_string(struct option_field const *, struct toml_table_t *, - void *); +int parse_toml_string(struct toml_table_t *, char const *, char **); #endif /* SRC_CONFIG_STR_H_ */ diff --git a/src/config/string_array.c b/src/config/string_array.c index 91a327cc..69f38415 100644 --- a/src/config/string_array.c +++ b/src/config/string_array.c @@ -38,6 +38,14 @@ string_array_cleanup(struct string_array *array) free(array->array); } +static void +__string_array_free(struct string_array *array) +{ + string_array_cleanup(array); + array->array = NULL; + array->length = 0; +} + static void string_array_print(struct group_fields const *group, struct option_field const *field, void *_value) @@ -67,14 +75,14 @@ string_array_parse_toml(struct option_field const *opt, struct string_array *result = _result; int error; - /* Remove the previous value (usually the default). */ - opt->type->free(_result); - array = toml_array_in(toml, opt->name); if (array == NULL) - return pr_err("TOML array '%s' was not found.", opt->name); + return 0; array_len = toml_array_nelem(array); + /* Remove the previous value (usually the default). */ + __string_array_free(result); + result->array = malloc(array_len * sizeof(char *)); if (result->array == NULL) return pr_enomem(); @@ -101,14 +109,9 @@ fail: } static void -string_array_free(void *_array) +string_array_free(void *array) { - struct string_array *array = _array; - - string_array_cleanup(array); - - array->array = NULL; - array->length = 0; + __string_array_free(array); } const struct global_type gt_string_array = { diff --git a/src/config/sync_strategy.c b/src/config/sync_strategy.c index 38e73550..d2522e18 100644 --- a/src/config/sync_strategy.c +++ b/src/config/sync_strategy.c @@ -64,10 +64,11 @@ parse_toml_sync_strategy(struct option_field const *opt, int error; char *string; - string = NULL; - error = parse_toml_string(opt, toml, &string); + error = parse_toml_string(toml, opt->name, &string); if (error) return error; + if (string == NULL) + return 0; error = parse_argv_sync_strategy(opt, string, _result); diff --git a/src/config/types.h b/src/config/types.h index c0b1e2fa..bdb5d7bf 100644 --- a/src/config/types.h +++ b/src/config/types.h @@ -110,6 +110,8 @@ struct global_type { argv_parse_function argv; /** * Converts from a TOML node to this data type. + * If the node is not present in the file, this function should + * do nothing. * Optional if there are no fields of this type that are read * from TOML files. */ diff --git a/src/config/uint.c b/src/config/uint.c index 702d652c..920bcf86 100644 --- a/src/config/uint.c +++ b/src/config/uint.c @@ -50,7 +50,7 @@ parse_toml_u_int(struct option_field const *opt, struct toml_table_t *toml, raw = toml_raw_in(toml, opt->name); if (raw == NULL) - return pr_err("TOML integer '%s' was not found.", opt->name); + return 0; if (toml_rtoi(raw, &value) == -1) return pr_err("Cannot parse '%s' as an integer.", raw);