diff options
Diffstat (limited to 'reference_model/src/func_config.cc')
-rw-r--r-- | reference_model/src/func_config.cc | 663 |
1 files changed, 66 insertions, 597 deletions
diff --git a/reference_model/src/func_config.cc b/reference_model/src/func_config.cc index a17fdef..6bd809e 100644 --- a/reference_model/src/func_config.cc +++ b/reference_model/src/func_config.cc @@ -13,6 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include <cxxopts.hpp> #include <ctype.h> #include <signal.h> #include <stdarg.h> @@ -25,615 +26,83 @@ #include "func_config.h" #include "func_debug.h" -#define MAX_NAME_LEN 128 -#define MAX_DESC_LEN 128 - -#ifndef ARG_ERROR -#define ARG_ERROR(...) \ - fprintf(stderr, "ERROR: "); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - return 1; -#endif - -// Parameter base name string table -const char* config_base_name_table[] = { -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) #NAME, -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) #NAME, -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) #NAME, -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) #NAME, -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR -#undef DEF_UNIT_OPTION -}; - -// Parameter description table -const char* config_param_desc_table[] = { -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) #DESC, -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) #DESC, -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) #DESC, -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) #DESC, -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR -}; - -// String table and enum for the option hierarchy level/sub-levels -// (no leaf options). Attribute at the top level have "BASE" as their -// enum value and an empty string for the value. -const char* config_hier_str_table[] = { - "", -#define DEF_UNIT_START(UNIT) #UNIT, -#define DEF_UNIT_END(UNIT) /**/ -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) /**/ -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) /**/ -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) /**/ -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) /**/ -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR -}; - -typedef enum config_hier_enum_t -{ - BASE, -#define DEF_UNIT_START(UNIT) CURRENT_UNIT, -#define DEF_UNIT_END(UNIT) /**/ -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) /**/ -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) /**/ -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) /**/ -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) /**/ -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR - - MAX_CONFIG_HIER -} config_hier_enum_t; - -// Mapping from a leaf parameter index to the -// position in the hierarchy. -config_hier_enum_t config_hierarchy_map[] = { -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) BASE, -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) BASE, -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) CURRENT_UNIT, -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) CURRENT_UNIT, -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR -}; - -#define CONFIG_PARAMETER_COUNT (sizeof(config_hierarchy_map) / sizeof(config_hier_enum_t)) - -// Dynamically generated at initialization -char** config_param_str_table = nullptr; - -// Initialize the configuration data structures -int func_model_init_config() +// Read the command line arguments +int func_model_parse_cmd_line( + func_config_t& func_config, func_debug_t& func_debug, int argc, char** argv, const char* version) { - // Initialize string table (builds the hierarchical names) - config_param_str_table = (char**)calloc(CONFIG_PARAMETER_COUNT, sizeof(char*)); - ASSERT_MEM(config_param_str_table); - - for (uint32_t i = 0; i < CONFIG_PARAMETER_COUNT; i++) + try { - size_t len = strlen(config_base_name_table[i]) + 1; - if (config_hierarchy_map[i] != BASE) - { - ASSERT_MSG(config_hierarchy_map[i] <= MAX_CONFIG_HIER, - "Configuration parameter\'s hierarchy is out of bounds"); - len += strlen(config_hier_str_table[config_hierarchy_map[i]]) + 1; + cxxopts::Options options("tosa_reference_model", "The TOSA reference model"); + + // clang-format off + options.add_options() + ("operator_fbs", "Flat buffer schema file", cxxopts::value<std::string>(func_config.operator_fbs), "<schema>") + ("test_desc", "Json test descriptor", cxxopts::value<std::string>(func_config.test_desc), "<descriptor>") + ("flatbuffer_dir", "Flatbuffer directory to load. If not specified, it will be overwritten by dirname(test_desc)", + cxxopts::value<std::string>(func_config.flatbuffer_dir)) + ("output_dir", "Output directory to write. If not specified, it will be overwritten by dirname(test_desc)", + cxxopts::value<std::string>(func_config.output_dir)) + ("tosa_file", "Flatbuffer file. Support .json or .tosa. Specifying this will overwrite the one initialized by --test_desc.", + cxxopts::value<std::string>(func_config.tosa_file)) + ("ifm_name", "Input tensor name. Comma(,) separated. Specifying this will overwrite the one initialized by --test_desc.", + cxxopts::value<std::string>(func_config.ifm_name)) + ("ifm_file", "Input tensor numpy Comma(,) separated. file to initialize with placeholder. Specifying this will overwrite the one initialized by --test_desc.", + cxxopts::value<std::string>(func_config.ifm_file)) + ("ofm_name", "Output tensor name. Comma(,) seperated. Specifying this will overwrite the one initialized by --test_desc.", + cxxopts::value<std::string>(func_config.ofm_name)) + ("ofm_file", "Output tensor numpy file to be generated. Comma(,) seperated. Specifying this will overwrite the one initialized by --test_desc.", + cxxopts::value<std::string>(func_config.ofm_file)) + ("eval", "Evaluate the network (0/1)", cxxopts::value<uint32_t>(func_config.eval)) + ("fp_format", "Floating-point number dump format string (printf-style format, e.g. 0.5)", + cxxopts::value<std::string>(func_config.fp_format)) + ("validate_only", "Validate the network, but do not read inputs or evaluate (0/1)", + cxxopts::value<uint32_t>(func_config.validate_only)) + ("output_tensors", "Output tensors to a file (0/1)", cxxopts::value<uint32_t>(func_config.output_tensors)) + ("tosa_profile", "Set TOSA profile (0 = Base Inference, 1 = Main Inference, 2 = Main Training)", + cxxopts::value<uint32_t>(func_config.tosa_profile)) + ("dump_intermediates", "Dump intermediate tensors (0/1)", cxxopts::value<uint32_t>(func_config.dump_intermediates)) + ("v,version", "print model version") + ("i,input_tensor_file", "specify input tensor files", cxxopts::value<std::vector<std::string>>()) + ("l,loglevel", func_debug.get_debug_verbosity_help_string(), cxxopts::value<std::string>()) + ("o,logfile", "output log file", cxxopts::value<std::string>()) + ("d,debugmask", func_debug.get_debug_mask_help_string(), cxxopts::value<std::vector<std::string>>()) + ("h,help", "print help"); + // clang-format on + + auto result = options.parse(argc, argv); + if (result.count("help")) { + std::cout << options.help() << std::endl; + return 1; } - config_param_str_table[i] = (char*)calloc(len, 1); - ASSERT_MEM(config_param_str_table[i]); - ASSERT_MSG(len < MAX_NAME_LEN, "option expanded name is too long: %s", config_base_name_table[i]); - - if (config_hierarchy_map[i] != BASE) - { - snprintf(config_param_str_table[i], len, "%s.%s", config_hier_str_table[config_hierarchy_map[i]], - config_base_name_table[i]); + if (result.count("debugmask")) { + auto& v = result["debugmask"].as<std::vector<std::string>>(); + for (const std::string& s : v) + func_debug.set_mask(s); } - else - { - snprintf(config_param_str_table[i], len, "%s", config_base_name_table[i]); + if (result.count("loglevel")) { + const std::string& levelstr = result["loglevel"].as<std::string>(); + func_debug.set_verbosity(levelstr); } - } - - return 0; -} - -int func_model_set_default_config(func_config_t* func_config) -{ - // Set default values in the global configuration data structure - bzero(func_config, sizeof(*func_config)); - -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) func_config->NAME = (DEFAULT); -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) strncpy(func_config->NAME, (DEFAULT), (LEN)-1); -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) func_config->UNIT.NAME = (DEFAULT); -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) strncpy(func_config->UNIT.NAME, (DEFAULT), (LEN)-1); -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR - - return 0; -} - -int func_model_config_cleanup() -{ - uint32_t i; - - if (!config_param_str_table) - return 1; - - for (i = 0; i < CONFIG_PARAMETER_COUNT; i++) - { - free(config_param_str_table[i]); - } - - free(config_param_str_table); - config_param_str_table = nullptr; - - return 0; -} - -int func_model_config_set_option(func_config_t* func_config, const char* name, const char* value) -{ - // Increment an index variable on each parameter position - // so that we can index both the position struct through the macro and the - // array of parameter names through a simple array of strings. - int param_idx = 0; - char* endptr; - - // TODO: does not handle strings yet. Can set magic values on FMT to - // choose a string copy vs strtoull -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - func_config->NAME = (uint64_t)strtoll(value, &endptr, 0); \ - if (endptr == value) \ - { \ - ARG_ERROR("Cannot parse option: %s = %s", name, value); \ - } \ - return 0; \ - } \ - param_idx++; - -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - if (strlen(value) >= LEN) \ - { \ - ARG_ERROR("Option value is too long: %s = %s", name, value); \ - } \ - strncpy(func_config->NAME, value, (LEN)-1); \ - return 0; \ - } \ - param_idx++; - -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - func_config->UNIT.NAME = (uint64_t)strtoll(value, &endptr, 0); \ - if (endptr == value) \ - { \ - ARG_ERROR("Cannot parse option: %s = %s", name, value); \ - } \ - return 0; \ - } \ - param_idx++; - -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - if (strlen(value) >= LEN) \ - { \ - ARG_ERROR("Option value is too long: %s = %s", name, value); \ - } \ - strncpy(func_config->UNIT.NAME, value, (LEN)-1); \ - return 0; \ - } \ - param_idx++; - -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR - - // No match! - ARG_ERROR("Cannot find option: %s", name); - - return 1; -} - -int func_model_config_get_option_by_name(func_config_t* func_config, const char* name, uint64_t* val) -{ - // Increment an index variable on each parameter position - // so that we can index both the position struct through the macro and the - // array of parameter names through a simple array of strings. - int param_idx = 0; - -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) - -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) param_idx++; - -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, FMT, DEFAULT) param_idx++; - -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - *val = func_config->NAME; \ - return 0; \ - } \ - param_idx++; - -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - *val = func_config->UNIT.NAME; \ - return 0; \ - } \ - param_idx++; - -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR - // No match! - return 1; -} -int func_model_config_get_str_option_by_name(func_config_t* func_config, - const char* name, - char* value, - const uint32_t len) -{ - // Increment an index variable on each parameter position - // so that we can index both the position struct through the macro and the - // array of parameter names through a simple array of strings. - int param_idx = 0; - -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - strncpy(value, func_config->NAME, len - 1); \ - return 0; \ - } \ - param_idx++; - -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) \ - if (!strcmp(config_param_str_table[param_idx], name)) \ - { \ - strncpy(value, func_config->UNIT.NAME, len - 1); \ - return 0; \ - } \ - param_idx++; - -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) param_idx++; - -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) param_idx++; - -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR - // No match! - return 1; -} - -int func_config_print_config_help(FILE* out) -{ - fprintf(out, "%-40s %s\n", "Option", "Description"); - fprintf(out, "%-40s %s\n", "------", "-----------"); - - for (uint32_t i = 0; i < CONFIG_PARAMETER_COUNT; i++) - { - fprintf(out, "-C%-40s %s\n", config_param_str_table[i], config_param_desc_table[i]); - } - - fprintf(out, "\n"); - - return 0; -} - -int func_model_print_config(func_config_t* func_config, FILE* out) -{ -#define DEF_UNIT_START(UNIT) -#define DEF_UNIT_END(UNIT) -#define DEF_OPTION(NAME, DESC, TYPE, FMT, DEFAULT) fprintf(out, "%-40s = " FMT "\n", #NAME, func_config->NAME); -#define DEF_UNIT_OPTION(UNIT, NAME, DESC, TYPE, FMT, DEFAULT) \ - fprintf(out, "%-40s = " FMT "\n", #UNIT "." #NAME, func_config->UNIT.NAME); -#define DEF_OPTION_STR(NAME, DESC, LEN, DEFAULT) fprintf(out, "%-40s = %s\n", #NAME, func_config->NAME); -#define DEF_UNIT_OPTION_STR(UNIT, NAME, DESC, LEN, DEFAULT) \ - fprintf(out, "%-40s = %s\n", #UNIT "." #NAME, func_config->UNIT.NAME); - -#define FOF_HEX "0x%llx" -#define FOF_DEC "%" PRIu32 -#define FOF_DECU64 "%" PRIu64 - -#include "func_config.def" -#undef DEF_UNIT_START -#undef DEF_UNIT_END -#undef DEF_OPTION -#undef DEF_UNIT_OPTION -#undef DEF_OPTION_STR -#undef DEF_UNIT_OPTION_STR - - return 0; -} - -static const char* programname; - -void func_model_print_debug_masks(FILE* out) -{ - fprintf(out, "\t List of components:\n"); -#define DEBUG_MODE(string, value) fprintf(out, "\t\t" #string "\n"); -#include "debug_modes.def" -#undef DEBUG_MODE -} - -int func_model_print_help(FILE* out) -{ - fprintf(out, "TOSA Reference Model help\n\n"); - - fprintf(out, - "Usage: %s [-c] [-C <name=value>] [-d <Debug Mask>] [-h] [-l <verbosity>] [-F " - "<flatconfig>]\n", - programname); - fprintf(out, "\t-c - Print list of config options\n"); - fprintf(out, "\t-C <name=value> - modify config option <name> to <value>\n"); - fprintf(out, "\t-d <Debug Mask - set component debug mask\n"); - func_model_print_debug_masks(out); - fprintf(out, "\t-F <flatconfig> - parse <flatconfig> as file of config options\n"); - fprintf(out, "\t-v - Print refererence model version\n"); - fprintf(out, "\t-h - show this help message and exit\n"); - fprintf( - out, - "\t-i <input_tensor_name>,<filename> - set input tensor <input_tensor_name> to the values from <filename>\n"); - fprintf(out, "\t-l <verbosity> - set log verbosity\n"); - fprintf(out, "\t-o <debuglog> - set debug log file\n"); - fprintf(out, "\n"); - - func_config_print_config_help(stdout); - - return 0; -} - -static const char* get_arg_text(int& index, const int argc, const char** argv) -{ - if (strlen(argv[index]) > 2) - { - return argv[index] + 2; - } - - if ((index + 1 == argc) || (argv[index + 1][0] == '-')) - { - fprintf(stderr, "No option value found for option %s\n", argv[index]); - return ""; - } - - index++; - return argv[index]; -} - -// Read the command line arguments -int func_model_parse_cmd_line( - func_config_t* func_config, func_debug_t* func_debug, const int argc, const char** argv, const char* version) -{ - int i; - programname = argv[0]; - for (i = 1; i < argc; i++) - { - // All command line arguments must begin with -X where X is a recognized character - if (strlen(argv[i]) < 2 || argv[i][0] != '-') - { - func_model_print_help(stderr); - ARG_ERROR("Command line argument at position %d not valid: %s", i, argv[i]); + if (result.count("logfile")) { + func_debug.set_file(result["logfile"].as<std::string>()); } - - switch (argv[i][1]) - { - // Model parameters may be overridden with the -Cname=value switch - case 'c': - func_config_print_config_help(stderr); - return 1; - - case 'C': - { - const char *name = nullptr, *value = nullptr; - - // Break the string into name and value parts - name = get_arg_text(i, argc, argv); - value = strchr(name, '='); - - if (value == nullptr) - { - func_model_print_help(stderr); - ARG_ERROR("Cannot parse -C argument at position %d: %s", i, argv[i]); - } - - *const_cast<char*>(value) = 0; - - if (func_model_config_set_option(func_config, name, value + 1)) - { - func_model_print_help(stderr); - ARG_ERROR("Cannot parse -C argument at position %d: %s", i, argv[i]); - } - break; - } - - case 'd': - case 'D': - { - func_debug_set_mask(func_debug, get_arg_text(i, argc, argv)); - break; - } - case 'F': - { - // Read a flat configuration file - if (func_model_parse_flat_config_file(func_config, get_arg_text(i, argc, argv))) - return 1; - - break; - } - case 'h': - func_model_print_help(stderr); - return 1; - - case 'i': - { - // shortcut for '-Cinput_tensor=' - if (func_model_config_set_option(func_config, "input_tensor", get_arg_text(i, argc, argv))) - { - func_model_print_help(stderr); - ARG_ERROR("Cannot set input tensor config value"); - } - break; - } - case 'l': - { - // Debug verbosity/logging level - func_debug_set_verbosity(func_debug, get_arg_text(i, argc, argv)); - break; - } - case 'o': - { - func_debug_set_file(func_debug, get_arg_text(i, argc, argv)); - break; - } - case 'v': - { - fprintf(stdout, "Model Version %s\n", version); - return 1; - } - default: - func_model_print_help(stderr); - ARG_ERROR("Unrecognized argument at position %d: %s", i, argv[i]); + if (result.count("input_tensor_file")) { + func_config.ifm_name = result["input_tensor_file"].as<std::string>(); } + if (result.count("version")) { + std::cout << "Model version " << version << std::endl; + } + } + catch(const std::exception& e) + { + std::cerr << e.what() << '\n'; + return 1; } return 0; } -int func_model_parse_flat_config_file(func_config_t* func_config, const char* filename) +void func_model_print_help() { - const int MAX_LINE_LEN = 1024; - - FILE* infile = nullptr; - char line_buf[MAX_LINE_LEN]; - int line = 1; - - infile = fopen(filename, "r"); - - if (infile == nullptr) - { - ARG_ERROR("Cannot open config file: %s\n", filename); - } - - while (fgets(line_buf, MAX_LINE_LEN - 1, infile) != nullptr) - { - char *name = line_buf, *value = nullptr, *comment = nullptr, *ptr = nullptr; - - // Remove comments - comment = strchr(line_buf, '#'); - - if (comment) - *comment = 0; - // Break the string into name and value parts - name = line_buf; - - // Remove leading whitespace - while (*name && isspace(*name)) - name++; - - // Empty line? - if (*name == 0) - { - line++; - continue; - } - - value = strchr(name, '='); - - // Missing value - if (value == nullptr) - { - ARG_ERROR("Cannot parse parameter in %s at line %d: %s", filename, line, line_buf); - } - - // Remove the = - *value = 0; - value++; - - // Trim off any whitespace at the end of the value - ptr = value; - while (*ptr != 0 && !isspace(*ptr)) - ptr++; - *ptr = 0; - - // Include a nested file - if (!strcmp(name, "include")) - { - if (func_model_parse_flat_config_file(func_config, value)) - return 1; - line++; - continue; - } - - if (func_model_config_set_option(func_config, name, value)) - { - func_model_print_help(stderr); - ARG_ERROR("Cannot set parameter in %s at line %d: %s", filename, line, line_buf) - } - - line++; - } - - fclose(infile); - - return 0; } |