diff options
Diffstat (limited to 'converter/other/fiasco/params.c')
-rw-r--r-- | converter/other/fiasco/params.c | 1139 |
1 files changed, 540 insertions, 599 deletions
diff --git a/converter/other/fiasco/params.c b/converter/other/fiasco/params.c index 32145fc3..042a14e2 100644 --- a/converter/other/fiasco/params.c +++ b/converter/other/fiasco/params.c @@ -22,6 +22,7 @@ #include "config.h" +#include <assert.h> #include <stdio.h> #include <ctype.h> #include <math.h> /* strtod() on SUN sparc */ @@ -32,6 +33,7 @@ #include <getopt.h> /* system or ../lib */ #include "pm_c_util.h" +#include "mallocvar.h" #include "nstring.h" #include "types.h" @@ -40,626 +42,181 @@ #include "misc.h" #include "fiasco.h" -#include "binerror.h" - #include "params.h" -/***************************************************************************** - - prototypes - -*****************************************************************************/ static void -read_parameter_file (param_t *params, FILE *file); -static int -get_parameter_index (const param_t *params, const char *search_string); -static void -set_parameter (param_t *parameter, const char *value); -static void -usage (const param_t *params, const char *progname, const char *synopsis, - const char *comment, const char *non_opt_string, - bool_t show_all_options, const char *sys_file_name, - const char *usr_file_name); +setParameter(param_t * const parameter, + const char * const value) { +/*---------------------------------------------------------------------------- -/***************************************************************************** + Set value of 'parameter' to 'value'. - public code + No return value. -*****************************************************************************/ + Side effects: + 'parameter.value' is changed accordingly -int -parseargs (param_t *usr_params, - int argc, char **argv, - const char *synopsis, - const char *comment, - const char *non_opt_string, - const char *path, - const char *sys_file_name, - const char *usr_file_name) -/* - * Perform the command line parsing. - * List of allowed parameters is given by 'usr_params'. - * Command line and number of parameters are given by 'argv' and 'argc'. - * 'synopsis' contains a brief description of the program and - * 'comment' may contain some additional advice. - * Initialization order of parameters: - * 1.) Default values given by the param_t struct - * 2.) System parameter-file ('path'/'sys_file_name') - * 3.) User parameter-file ($HOME/'usr_file_name') - * 4.) Command line parameters - * 5.) Parameter-file forced by option -f (--config-file) - * - * Return value: - * index in ARGV of the first ARGV-element that is not an option. - * - * Side effects: - * the elements of ARGV are permuted - * usr_params [].value is modified - */ -{ - extern int optind; /* index in ARGV of the 1st element - that is not an option */ - bool_t detailed_help = NO; /* NO if all parameters can be modified - with short options too */ - unsigned n1; /* number of user parameters */ - unsigned n2; /* number of system parameters */ - bool_t read_config_file = NO; /* will override command line */ - param_t *params; /* array of user and system params */ - param_t *sys_params; /* array of system parameters */ - param_t detailed_sys_params [] = /* detailed system parameters */ - { - {"version", NULL, 'v', PFLAG, {0}, NULL, - "Print program version number, then exit."}, - {"verbose", "NUM", 'V', PINT, {0}, "1", - "Set level of verbosity to `%s'."}, - {"config", "FILE", 'f', PSTR, {0}, NULL, - "Load `%s' to initialize parameters."}, - {"info", NULL, 'h', PFLAG, {0}, NULL, - "Print brief help, then exit."}, - {"help", NULL, 'H', PFLAG, {0}, NULL, - "Print detailed help, then exit."}, - {NULL, NULL, 0, PSTR, {0}, NULL, NULL } - }; - param_t short_sys_params [] = /* short system parameters */ - { - {"version", NULL, 'v', PFLAG, {0}, NULL, - "Print program version number, then exit."}, - {"verbose", "NUM", 'V', PINT, {0}, "1", - "Set level of verbosity to `%s'."}, - {"config", "FILE", 'f', PSTR, {0}, NULL, - "Load `%s' to initialize parameters."}, - {"help", NULL, 'h', PFLAG, {0}, NULL, - "Print this help, then exit."}, - {NULL, NULL, 0, PSTR, {0}, NULL, NULL } - }; - char *sys_path; /* path to system config file */ - - sys_path = calloc (strlen (path) + strlen (sys_file_name) + 2, - sizeof (char)); - if (!sys_path) - error ("Out of memory."); - sprintf (sys_path, "%s/%s", path, sys_file_name); - - /* - * Set parameters defaults - */ - { - param_t *p; - - for (p = usr_params; p->name != NULL; p++) - { - set_parameter (p, p->default_value); - if (p->optchar == '\0') - detailed_help = YES; - } - - sys_params = detailed_help ? detailed_sys_params : short_sys_params; - - for (p = sys_params; p->name != NULL; p++) - set_parameter (p, p->default_value); - } - /* - * Append system command line option to user parameters - */ - for (n1 = 0; usr_params [n1].name != NULL; n1++) - ; - for (n2 = 0; sys_params [n2].name != NULL; n2++) - ; - params = calloc (n1 + n2 + 1, sizeof (param_t)); - if (!params) - error ("Out of memory."); - - memcpy (params, usr_params, n1 * sizeof (param_t)); - memcpy (params + n1, sys_params, (n2 + 1) * sizeof (param_t)); - /* - * Try to open the system resource file 'path'/'sys_file_name' - */ - { - FILE *parameter_file = open_file (sys_path, NULL, READ_ACCESS); - if (parameter_file == NULL) -/* - warning ("No system resource file found."); -*/ {} - else - { - read_parameter_file (params, parameter_file); - fclose (parameter_file); - } - } - /* - * Try to read user resource file $HOME/'usr_file_name' - */ - { - FILE *parameter_file = open_file (usr_file_name, "HOME", READ_ACCESS); - if (parameter_file != NULL) - { - read_parameter_file (params, parameter_file); - fclose (parameter_file); - } - } - /* - * Parse command line options - */ - { - extern char *optarg; /* argument of current option */ - struct option *long_options; /* array of long options */ - int option_index = 0; - char optstr [MAXSTRLEN]; /* string containing the legitimate - option characters */ - int optchar; /* found option character */ - - /* - * Build short option string for getopt_long (). - */ - { - param_t *p; /* counter */ - char *ptr_optstr; /* pointer to position in string */ - - ptr_optstr = optstr; - for (p = params; p->name != NULL; p++) - if (p->optchar != '\0') - { - *ptr_optstr++ = p->optchar; - if (p->type == POSTR) - { - *ptr_optstr++ = ':'; - *ptr_optstr++ = ':'; - } - else if (p->type != PFLAG) - *ptr_optstr++ = ':'; - } - *ptr_optstr = '\0'; - } - - /* - * Build long option string for getopt_long (). - */ - { - int i; - - long_options = calloc (n1 + n2 + 1, sizeof (struct option)); - if (!long_options) - error ("Out of memory."); - for (i = 0; params [i].name != NULL; i++) - { - long_options [i].name = params [i].name; - switch (params [i].type) - { - case PFLAG: - long_options [i].has_arg = 0; - break; - case POSTR: - long_options [i].has_arg = 2; - break; - case PINT: - case PSTR: - case PFLOAT: - default: - long_options [i].has_arg = 1; - break; - } - long_options [i].has_arg = params [i].type != PFLAG; - long_options [i].flag = NULL; - long_options [i].val = 0; - } - } - - /* - * Parse command line - */ - while ((optchar = getopt_long (argc, argv, optstr, long_options, - &option_index)) != EOF) - { - int param_index = -1; - - switch (optchar) - { - case 0: - param_index = option_index; - break; - case ':': - if (detailed_help) - fprintf (stderr, - "Try `%s -h' or `%s --help' for " - "more information.\n", - argv [0], argv [0]); - else - fprintf (stderr, "Try `%s --help' for more information.\n", - argv [0]); - exit (2); - break; - case '?': - if (detailed_help) - fprintf (stderr, - "Try `%s -h' or `%s --help' " - "for more information.\n", - argv [0], argv [0]); - else - fprintf (stderr, "Try `%s --help' for more information.\n", - argv [0]); - exit (2); - break; - default: - { - int i; +-----------------------------------------------------------------------------*/ + assert (parameter); - for (i = 0; params [i].name != NULL; i++) - if (params [i].optchar == optchar) - { - param_index = i; - break; - } - } - } - /* - * Check for system options - */ - if (param_index >= 0) - { - set_parameter (params + param_index, optarg ? optarg : ""); - if (streq (params [param_index].name, "help")) - usage (params, argv [0], synopsis, comment, non_opt_string, - YES, sys_path, usr_file_name); - else if (streq (params [param_index].name, "info")) - usage (params, argv [0], synopsis, comment, non_opt_string, - NO, sys_path, usr_file_name); - else if (streq (params [param_index].name, "version")) - { - fprintf (stderr, "%s " VERSION "\n", argv [0]); - { - /* Kludge for standard Netpbm version announcement */ - char * modified_argv[2]; - int argc; - modified_argv[0] = argv[0]; - modified_argv[1] = (char *) "--version"; - argc = 2; - pm_proginit(&argc, (const char **) modified_argv); - } - exit (2); + switch (parameter->type) { + case PFLAG: + if (value != NULL && *value != '\0') { + if (strcaseeq (value, "TRUE")) + parameter->value.b = YES; + else if (strcaseeq (value, "FALSE")) + parameter->value.b = NO; + else if (strcaseeq (value, "YES")) + parameter->value.b = YES; + else if (strcaseeq (value, "NO")) + parameter->value.b = NO; + else { + long int data; + char *endptr; + + data = strtol (value, &endptr, 0); + if (*endptr != '\0' || endptr == value) + pm_message("Invalid value `%s' converted to %d", + value, (int) data); + parameter->value.b = data ? YES : NO; } - else if (streq (params [param_index].name, "verbose")) - fiasco_set_verbosity ( - * (fiasco_verbosity_e *) parameter_value (params, - "verbose")); - else if (streq (params [param_index].name, "config")) - read_config_file = YES; - param_index = -1; /* clear index flag */ - } - } - - free (long_options); - } - - /* - * Read config-file if specified by option -f - */ - if (read_config_file) - { - char *filename; - - if ((filename = (char *) parameter_value (params, "config")) != NULL) - { - FILE *parameter_file; /* input file */ - - warning ("Options set in file `%s' will override" - " command line options.", filename); - parameter_file = open_file (filename, NULL, READ_ACCESS); - if (parameter_file != NULL) - { - read_parameter_file (params, parameter_file); - fclose (parameter_file); - } - else - file_error (filename); - } - else - error ("Invalid config filename."); - } - - memcpy (usr_params, params, n1 * sizeof (param_t)); /* fill user struct */ - free (sys_path); - - return optind; + } else + parameter->value.b = !parameter->value.b; + break; + case PINT: { + long int data; + char *endptr; + + data = strtol (value, &endptr, 0); + if (*endptr != '\0' || endptr == value) + pm_message("Invalid value `%s' converted to %d", + value, (int) data); + parameter->value.i = data; + } break; + case PFLOAT: { + double data; + char *endptr; + + data = strtod (value, &endptr); + if (*endptr != '\0' || endptr == value) + pm_message("Invalid value `%s' converted to %f", + value, (double) data); + parameter->value.f = data; + } break; + case PSTR: + case POSTR: + parameter->value.s = value ? strdup (value) : NULL; + break; + default: + pm_error("Invalid parameter type for %s", parameter->name); + } } -void * -parameter_value (const param_t *params, const char *name) -/* - * Extract value of parameter 'name.' of the given parameters 'params'. - * - * Return value: - * value of given parameter - */ -{ - int pind = get_parameter_index (params, name); - if (pind < 0) - error ("Invalid parameter `%s'.", name); - if (params [pind].type == PSTR || params [pind].type == POSTR) - return (void *) params [pind].value.s; +static int +getParameterIndex(const param_t * const params, + const char * const search_string) { +/*---------------------------------------------------------------------------- + Search for parameter with name 'search_string' in parameter struct. + + Return value: index of parameter or -1 if no matching parameter has been + found +-----------------------------------------------------------------------------*/ + int n; + int index = -1; + + assert (params && search_string); + + for (n = 0; params [n].name != NULL; n++) { + if (strcaseeq (params [n].name, search_string)) { + index = n; + break; + } + } - return (void *) &(params [pind].value); + return index; } -void -ask_and_set (param_t *params, const char *name, const char *msg) -/* - * Ask user (print given message 'msg') for missing mandatory - * parameter 'name' of the given parameters 'params'. - * - * No return value. - * - * Side effects: - * 'params ['name'].value' is changed - */ -{ - char answer [MAXSTRLEN]; - int index = get_parameter_index (params, name); - - if (index < 0) - error ("Invalid parameter %s.", name); - - if (msg) - fprintf (stderr, "%s\n", msg); - - switch (params [index].type) - { - case PFLAG: /* Unusual, at least. */ - warning ("Flags should be initialized and set on demand, " - "not request"); - case PINT: - case PSTR: - case POSTR: - case PFLOAT: - scanf (MAXSTRLEN_SCANF, answer); - set_parameter (¶ms [index], answer); - break; - default: - error ("Invalid parameter type for %s", name); - } -} -void -write_parameters (const param_t *params, FILE *output) -/* - * Write all parameter settings to 'output'. - * - * No return value. - */ -{ - int pind; - - if (!params || !output) - error ("Parameters must be not NULL."); - - for (pind = 0; params [pind].name != NULL; pind++) - { - fprintf (output, "# %s = ", params [pind].name); - switch (params [pind].type) - { - case PFLAG: - fprintf (output, "%s\n", params [pind].value.b ? "TRUE" : "FALSE"); - break; - case PINT: - fprintf (output, "%d\n", params [pind].value.i); - break; - case PFLOAT: - fprintf (output, "%.4f\n", (double) params [pind].value.f); - break; - case PSTR: - case POSTR: - fprintf (output, "%s\n", params [pind].value.s); - break; - default: - error ("Invalid type %d for parameter %s", - params [pind].type, params [pind].name); - } - } - fputc ('\n', output); -} -/***************************************************************************** +static void +readParameterFile(param_t * const params, + FILE * const file) { +/*---------------------------------------------------------------------------- - private code + Read parameter settings from 'file'. -*****************************************************************************/ + No return value. -static void -set_parameter (param_t *parameter, const char *value) -/* - * Set value of 'parameter' to 'value'. - * - * No return value. - * - * Side effects: - * 'parameter.value' is changed accordingly - */ -{ - assert (parameter); - - switch (parameter->type) - { - case PFLAG: - if (value != NULL && *value != '\0') - { - if (strcaseeq (value, "TRUE")) - parameter->value.b = YES; - else if (strcaseeq (value, "FALSE")) - parameter->value.b = NO; - else if (strcaseeq (value, "YES")) - parameter->value.b = YES; - else if (strcaseeq (value, "NO")) - parameter->value.b = NO; - else - { - long int data; - char *endptr; - - data = strtol (value, &endptr, 0); - if (*endptr != '\0' || endptr == value) - warning ("Invalid value `%s' converted to %d", - value, (int) data); - parameter->value.b = data ? YES : NO; - } - } - else - parameter->value.b = !parameter->value.b; - break; - case PINT: - { - long int data; - char *endptr; - - data = strtol (value, &endptr, 0); - if (*endptr != '\0' || endptr == value) - warning ("Invalid value `%s' converted to %d", - value, (int) data); - parameter->value.i = data; - } - break; - case PFLOAT: - { - double data; - char *endptr; - - data = strtod (value, &endptr); - if (*endptr != '\0' || endptr == value) - warning ("Invalid value `%s' converted to %f", - value, (double) data); - parameter->value.f = data; - } - break; - case PSTR: - case POSTR: - parameter->value.s = value ? strdup (value) : NULL; - break; - default: - error ("Invalid parameter type for %s", parameter->name); - } -} + Side effects: + 'params [].value' are changed if specified in 'file' +-----------------------------------------------------------------------------*/ + char buffer [MAXSTRLEN]; + int n = 0; -static int -get_parameter_index (const param_t *params, const char *search_string) -/* - * Search for parameter with name 'search_string' in parameter struct. - * - * Return value: - * index of parameter or -1 if no matching parameter has been found - */ -{ - int n; - int index = -1; + assert (params && file); - assert (params && search_string); + while (fgets (buffer, MAXSTRLEN, file) != NULL) { + char *b; /* temporary variable */ + char *name; /* parameter name */ + char *value; /* parameter value */ + int pind; /* current argument number */ - for (n = 0; params [n].name != NULL; n++) - if (strcaseeq (params [n].name, search_string)) - { - index = n; - break; - } + b = strchr (buffer, '#'); + if (b != NULL) /* Strip comments. */ + *b = '\0'; - return index; -} + b = strchr (buffer, '='); + if (b == NULL) /* Strip lines that contain no '=' */ + continue; + *b = '\0'; /* Replace '=' by string terminator */ -static void -read_parameter_file (param_t *params, FILE *file) -/* - * Read parameter settings from 'file'. - * - * No return value. - * - * Side effects: - * 'params [].value' are changed if specified in 'file' - */ -{ - char buffer [MAXSTRLEN]; - int n = 0; - - assert (params && file); - - while (fgets (buffer, MAXSTRLEN, file) != NULL) - { - char *b; /* temporary variable */ - char *name; /* parameter name */ - char *value; /* parameter value */ - int pind; /* current argument number */ - - b = strchr (buffer, '#'); - if (b != NULL) /* Strip comments. */ - *b = '\0'; - - b = strchr (buffer, '='); - if (b == NULL) /* Strip lines that contain no '=' */ - continue; - *b = '\0'; /* Replace '=' by string terminator */ - - /* - * Extract value of parameter - */ - for (value = b + 1; ISSPACE (*value); value++) - ; /* Delete leading spaces */ - - for (b = value + strlen (value) - 1; b >= value && ISSPACE (*b); b--) - *b = '\0'; /* Delete trailing spaces. */ - - /* - * Extract parameter name - */ - for (name = buffer; ISSPACE (*name); name++) - ; /* Delete leading spaces */ - - for (b = name + strlen (name) - 1; b >= name && ISSPACE (*b); b--) - *b = '\0'; /* Delete trailing spaces. */ - - pind = get_parameter_index (params, name); - if (pind >= 0) - set_parameter (¶ms [pind], value); - - n++; - } + /* Extract value of parameter */ + for (value = b + 1; ISSPACE (*value); value++) + ; /* Delete leading spaces */ + + for (b = value + strlen (value) - 1; b >= value && ISSPACE (*b); b--) + *b = '\0'; /* Delete trailing spaces. */ + + /* Extract parameter name */ + for (name = buffer; ISSPACE (*name); name++) + ; /* Delete leading spaces */ + + for (b = name + strlen (name) - 1; b >= name && ISSPACE (*b); b--) + *b = '\0'; /* Delete trailing spaces. */ + + pind = getParameterIndex(params, name); + if (pind >= 0) + setParameter(¶ms[pind], value); + + ++n; + } } static void -usage (const param_t *params, const char *progname, const char *synopsis, - const char *comment, const char *non_opt_string, - bool_t show_all_options, const char *sys_file_name, - const char *usr_file_name) -/* - * Generates and prints command line description from param_t struct 'params'. - * 'progname' is the name of the executable, 'synopsis' a short program - * description, and 'comment' some more advice. - * If flag 'show_all_options' is set then print also options that are not - * associated with a short option character. - * 'sys_file_name' and 'usr_file_name' are filenames to parameter files. - * - * No return value. - */ -{ +usage(const param_t * const params, + const char * const progname, + const char * const synopsis, + const char * const comment, + const char * const non_opt_string, + bool_t const show_all_options, + const char * const sys_file_name, + const char * const usr_file_name) { +/*---------------------------------------------------------------------------- + + Generates and prints command line description from param_t struct 'params'. + 'progname' is the name of the executable, 'synopsis' a short program + description, and 'comment' some more advice. + If flag 'show_all_options' is set then print also options that are not + associated with a short option character. + 'sys_file_name' and 'usr_file_name' are filenames to parameter files. + + No return value. +-----------------------------------------------------------------------------*/ int i; size_t width = 0; @@ -671,9 +228,8 @@ usage (const param_t *params, const char *progname, const char *synopsis, fprintf (stderr, "Mandatory or optional arguments to long options " "are mandatory or optional\nfor short options too. " "Default values are surrounded by {}.\n"); - for (i = 0; params [i].name != NULL; i++) - if (params [i].optchar != '\0' || show_all_options) - { + for (i = 0; params [i].name != NULL; i++) { + if (params [i].optchar != '\0' || show_all_options) { if (params [i].type == POSTR) width = MAX(width, (strlen (params [i].name) + strlen (params [i].argument_name) + 2)); @@ -683,10 +239,9 @@ usage (const param_t *params, const char *progname, const char *synopsis, else width = MAX(width, (strlen (params [i].name)) - 1); } - - for (i = 0; params [i].name != NULL; i++) - if (params [i].optchar != '\0' || show_all_options) - { + } + for (i = 0; params [i].name != NULL; i++) { + if (params [i].optchar != '\0' || show_all_options) { if (params [i].optchar != '\0') fprintf (stderr, " -%c, --", params [i].optchar); else @@ -708,8 +263,7 @@ usage (const param_t *params, const char *progname, const char *synopsis, fprintf (stderr, params [i].use, params [i].argument_name); - switch (params [i].type) - { + switch (params [i].type) { case PFLAG: break; case PINT: @@ -724,20 +278,407 @@ usage (const param_t *params, const char *progname, const char *synopsis, fprintf (stderr, "{%s}", params [i].value.s); break; default: - error ("type %d for %s invalid", - params [i].type, params [i].name); + pm_error("type %d for %s invalid", + params [i].type, params [i].name); } fprintf (stderr, "\n"); } + } fprintf (stderr, "\n"); + fprintf (stderr, "Parameter initialization order:\n"); fprintf (stderr, "1.) %s\n2.) $HOME/%s\t 3.) command line\t 4.) --config=file", sys_file_name, usr_file_name); fprintf (stderr, "\n\n"); + if (comment != NULL) fprintf (stderr, "%s\n", comment); exit (1); } + + +const void * +parameter_value(const param_t * const params, + const char * const name) { +/*---------------------------------------------------------------------------- + Extract value of parameter 'name.' of the given parameters 'params'. + + Return value: value of given parameter + +-----------------------------------------------------------------------------*/ + int pind = getParameterIndex(params, name); + + if (pind < 0) + pm_error("Invalid parameter '%s'.", name); + + if (params[pind].type == PSTR || params[pind].type == POSTR) + return params[pind].value.s; + + return &(params[pind].value); +} + + + +int +parseargs(param_t * const usr_params, + int argc, + const char ** const argv, + const char * const synopsis, + const char * const comment, + const char * const non_opt_string, + const char * const path, + const char * const sys_file_name, + const char * const usr_file_name) { +/*---------------------------------------------------------------------------- + Perform the command line parsing. + List of allowed parameters is given by 'usr_params'. + Command line and number of parameters are given by 'argv' and 'argc'. + 'synopsis' contains a brief description of the program and + 'comment' may contain some additional advice. + Initialization order of parameters: + 1.) Default values given by the param_t struct + 2.) System parameter-file ('path'/'sys_file_name') + 3.) User parameter-file ($HOME/'usr_file_name') + 4.) Command line parameters + 5.) Parameter-file forced by option -f (--config-file) + + Return value: + index in ARGV of the first ARGV-element that is not an option. + + Side effects: + the elements of ARGV are permuted + usr_params [].value is modified +-----------------------------------------------------------------------------*/ + extern int optind; /* index in ARGV of the 1st element + that is not an option */ + bool_t detailed_help = NO; /* NO if all parameters can be modified + with short options too */ + unsigned n1; /* number of user parameters */ + unsigned n2; /* number of system parameters */ + bool_t read_config_file = NO; /* will override command line */ + param_t *params; /* array of user and system params */ + param_t *sys_params; /* array of system parameters */ + param_t detailed_sys_params [] = /* detailed system parameters */ + { + {"version", NULL, 'v', PFLAG, {0}, NULL, + "Print program version number, then exit."}, + {"verbose", "NUM", 'V', PINT, {0}, "1", + "Set level of verbosity to `%s'."}, + {"config", "FILE", 'f', PSTR, {0}, NULL, + "Load `%s' to initialize parameters."}, + {"info", NULL, 'h', PFLAG, {0}, NULL, + "Print brief help, then exit."}, + {"help", NULL, 'H', PFLAG, {0}, NULL, + "Print detailed help, then exit."}, + {NULL, NULL, 0, PSTR, {0}, NULL, NULL } + }; + param_t short_sys_params [] = /* short system parameters */ + { + {"version", NULL, 'v', PFLAG, {0}, NULL, + "Print program version number, then exit."}, + {"verbose", "NUM", 'V', PINT, {0}, "1", + "Set level of verbosity to `%s'."}, + {"config", "FILE", 'f', PSTR, {0}, NULL, + "Load `%s' to initialize parameters."}, + {"help", NULL, 'h', PFLAG, {0}, NULL, + "Print this help, then exit."}, + {NULL, NULL, 0, PSTR, {0}, NULL, NULL } + }; + const char * sys_path; /* path to system config file */ + + pm_asprintf(&sys_path, "%s/%s", path, sys_file_name); + + /* Set parameters defaults */ + { + param_t *p; + + for (p = usr_params; p->name != NULL; p++) + { + setParameter(p, p->default_value); + if (p->optchar == '\0') + detailed_help = YES; + } + + sys_params = detailed_help ? detailed_sys_params : short_sys_params; + + for (p = sys_params; p->name != NULL; p++) + setParameter(p, p->default_value); + } + /* Append system command line option to user parameters */ + for (n1 = 0; usr_params [n1].name != NULL; n1++) + ; + for (n2 = 0; sys_params [n2].name != NULL; n2++) + ; + MALLOCARRAY_NOFAIL(params, n1 + n2 + 1); + + memcpy(params, usr_params, n1 * sizeof(param_t)); + memcpy(params + n1, sys_params, (n2 + 1) * sizeof(param_t)); + + { + /* Try to open the system resource file 'path'/'sys_file_name' */ + + FILE *parameter_file = open_file(sys_path, NULL, READ_ACCESS); + + if (parameter_file) { + readParameterFile(params, parameter_file); + fclose(parameter_file); + } + } + { + /* Try to read user resource file $HOME/'usr_file_name' */ + + FILE *parameter_file = open_file(usr_file_name, "HOME", READ_ACCESS); + + if (parameter_file) { + readParameterFile(params, parameter_file); + fclose(parameter_file); + } + } + { + /* Parse command line options */ + + extern char *optarg; /* argument of current option */ + struct option *long_options; /* array of long options */ + int option_index = 0; + char optstr [MAXSTRLEN]; /* string containing the legitimate + option characters */ + int optchar; /* found option character */ + + { + /* Build short option string for getopt_long (). */ + param_t *p; /* counter */ + char *ptr_optstr; /* pointer to position in string */ + + ptr_optstr = optstr; + for (p = params; p->name != NULL; p++) + if (p->optchar != '\0') + { + *ptr_optstr++ = p->optchar; + if (p->type == POSTR) + { + *ptr_optstr++ = ':'; + *ptr_optstr++ = ':'; + } + else if (p->type != PFLAG) + *ptr_optstr++ = ':'; + } + *ptr_optstr = '\0'; + } + + { + /* Build long option string for getopt_long (). */ + + int i; + + MALLOCARRAY_NOFAIL(long_options, n1 + n2 + 1); + + for (i = 0; params [i].name != NULL; i++) { + long_options [i].name = params [i].name; + switch (params [i].type) + { + case PFLAG: + long_options [i].has_arg = 0; + break; + case POSTR: + long_options [i].has_arg = 2; + break; + case PINT: + case PSTR: + case PFLOAT: + default: + long_options [i].has_arg = 1; + break; + } + long_options [i].has_arg = params [i].type != PFLAG; + long_options [i].flag = NULL; + long_options [i].val = 0; + } + } + + /* Parse command line */ + + while ((optchar = getopt_long(argc, (char **)argv, optstr, + long_options, + &option_index)) != EOF) { + int param_index = -1; + + switch (optchar) { + case 0: + param_index = option_index; + break; + case ':': + if (detailed_help) + fprintf (stderr, + "Try `%s -h' or `%s --help' for " + "more information.\n", + argv [0], argv [0]); + else + fprintf (stderr, "Try `%s --help' for more information.\n", + argv [0]); + exit (2); + break; + case '?': + if (detailed_help) + fprintf (stderr, + "Try `%s -h' or `%s --help' " + "for more information.\n", + argv [0], argv [0]); + else + fprintf (stderr, "Try `%s --help' for more information.\n", + argv [0]); + exit (2); + break; + default: { + int i; + + for (i = 0; params [i].name != NULL; i++) { + if (params [i].optchar == optchar) { + param_index = i; + break; + } + } + } + } + /* Check for system options */ + + if (param_index >= 0) { + setParameter(params + param_index, optarg ? optarg : ""); + if (streq(params[param_index].name, "help")) + usage(params, argv [0], synopsis, comment, non_opt_string, + YES, sys_path, usr_file_name); + else if (streq(params[param_index].name, "info")) + usage(params, argv [0], synopsis, comment, non_opt_string, + NO, sys_path, usr_file_name); + else if (streq(params[param_index].name, "version")) { + fprintf(stderr, "%s " VERSION "\n", argv [0]); + { + /* Kludge for standard Netpbm version announcement */ + const char * modifiedArgv[2]; + int argc; + modifiedArgv[0] = argv[0]; + modifiedArgv[1] = (char *) "--version"; + argc = 2; + pm_proginit(&argc, modifiedArgv); + } + exit (2); + } else if (streq(params[param_index].name, "verbose")) + fiasco_set_verbosity( + * (fiasco_verbosity_e *) parameter_value(params, + "verbose")); + else if (streq(params[param_index].name, "config")) + read_config_file = YES; + param_index = -1; /* clear index flag */ + } + } + free(long_options); + } + + /* Read config-file if specified by option -f */ + if (read_config_file) { + char * filename; + + if ((filename = (char *) parameter_value(params, "config")) != NULL) { + FILE * parameter_file; /* input file */ + + pm_message("Options set in file `%s' will override" + " command line options.", filename); + parameter_file = open_file(filename, NULL, READ_ACCESS); + if (parameter_file != NULL) { + readParameterFile(params, parameter_file); + fclose(parameter_file); + } else + pm_error("Failed to open config file '%s'", filename); + } else + pm_error("Invalid config filename."); + } + + memcpy(usr_params, params, n1 * sizeof (param_t)); /* fill user struct */ + pm_strfree(sys_path); + + return optind; +} + + + +void +ask_and_set(param_t * const params, + const char * const name, + const char * const msg) { +/*---------------------------------------------------------------------------- + Ask user (print given message 'msg') for missing mandatory + parameter 'name' of the given parameters 'params'. + + No return value. + + Side effects: + 'params ['name'].value' is changed +-----------------------------------------------------------------------------*/ + char answer[MAXSTRLEN]; + int index = getParameterIndex(params, name); + + if (index < 0) + pm_error("Invalid parameter '%s'.", name); + + if (msg) + pm_message("%s", msg); + + switch (params[index].type) { + case PFLAG: /* Unusual, at least. */ + pm_message("Flags should be initialized and set on demand, " + "not request"); + case PINT: + case PSTR: + case POSTR: + case PFLOAT: + scanf(MAXSTRLEN_SCANF, answer); + setParameter(¶ms [index], answer); + break; + default: + pm_error("Invalid parameter type for %s", name); + } +} + + + +void +write_parameters(const param_t * const params, + FILE * const output) { +/*---------------------------------------------------------------------------- + Write all parameter settings to 'output'. + + No return value. +-----------------------------------------------------------------------------*/ + unsigned int pind; + + if (!params || !output) + pm_error("Parameters must be not NULL."); + + for (pind = 0; params[pind].name != NULL; pind++) { + fprintf(output, "# %s = ", params[pind].name); + switch(params[pind].type) { + case PFLAG: + fprintf(output, "%s\n", params[pind].value.b ? "TRUE" : "FALSE"); + break; + case PINT: + fprintf(output, "%d\n", params[pind].value.i); + break; + case PFLOAT: + fprintf(output, "%.4f\n", (double) params[pind].value.f); + break; + case PSTR: + case POSTR: + fprintf(output, "%s\n", params[pind].value.s); + break; + default: + pm_error("Invalid type %d for parameter %s", + params[pind].type, params[pind].name); + } + } + fputc ('\n', output); +} + + + |