|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* params.c: Parameter file and command line parsing
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Written by: Stefan Frank
|
|
Packit |
78deda |
* Ullrich Hafner
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* This file is part of FIASCO (Fractal Image And Sequence COdec)
|
|
Packit |
78deda |
* Copyright (C) 1994-2000 Ullrich Hafner
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* $Date: 2000/07/15 17:24:21 $
|
|
Packit |
78deda |
* $Author: hafner $
|
|
Packit |
78deda |
* $Revision: 5.2 $
|
|
Packit |
78deda |
* $State: Exp $
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#define _DEFAULT_SOURCE 1 /* New name for SVID & BSD source defines */
|
|
Packit |
78deda |
#define _BSD_SOURCE 1
|
|
Packit |
78deda |
/* Make sure strdup() is in string.h and strcaseeq() is in nstring.h */
|
|
Packit |
78deda |
#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "config.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <stdio.h>
|
|
Packit |
78deda |
#include <ctype.h>
|
|
Packit |
78deda |
#include <math.h> /* strtod() on SUN sparc */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <stdlib.h>
|
|
Packit |
78deda |
#include <string.h>
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include <getopt.h> /* system or ../lib */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_c_util.h"
|
|
Packit |
78deda |
#include "nstring.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "types.h"
|
|
Packit |
78deda |
#include "macros.h"
|
|
Packit |
78deda |
#include "bit-io.h"
|
|
Packit |
78deda |
#include "misc.h"
|
|
Packit |
78deda |
#include "fiasco.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "binerror.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "params.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*****************************************************************************
|
|
Packit |
78deda |
|
|
Packit |
78deda |
prototypes
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_parameter_file (param_t *params, FILE *file);
|
|
Packit |
78deda |
static int
|
|
Packit |
78deda |
get_parameter_index (const param_t *params, const char *search_string);
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
set_parameter (param_t *parameter, const char *value);
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
usage (const param_t *params, const char *progname, const char *synopsis,
|
|
Packit |
78deda |
const char *comment, const char *non_opt_string,
|
|
Packit |
78deda |
bool_t show_all_options, const char *sys_file_name,
|
|
Packit |
78deda |
const char *usr_file_name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*****************************************************************************
|
|
Packit |
78deda |
|
|
Packit |
78deda |
public code
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
parseargs (param_t *usr_params,
|
|
Packit |
78deda |
int argc, char **argv,
|
|
Packit |
78deda |
const char *synopsis,
|
|
Packit |
78deda |
const char *comment,
|
|
Packit |
78deda |
const char *non_opt_string,
|
|
Packit |
78deda |
const char *path,
|
|
Packit |
78deda |
const char *sys_file_name,
|
|
Packit |
78deda |
const char *usr_file_name)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Perform the command line parsing.
|
|
Packit |
78deda |
* List of allowed parameters is given by 'usr_params'.
|
|
Packit |
78deda |
* Command line and number of parameters are given by 'argv' and 'argc'.
|
|
Packit |
78deda |
* 'synopsis' contains a brief description of the program and
|
|
Packit |
78deda |
* 'comment' may contain some additional advice.
|
|
Packit |
78deda |
* Initialization order of parameters:
|
|
Packit |
78deda |
* 1.) Default values given by the param_t struct
|
|
Packit |
78deda |
* 2.) System parameter-file ('path'/'sys_file_name')
|
|
Packit |
78deda |
* 3.) User parameter-file ($HOME/'usr_file_name')
|
|
Packit |
78deda |
* 4.) Command line parameters
|
|
Packit |
78deda |
* 5.) Parameter-file forced by option -f (--config-file)
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Return value:
|
|
Packit |
78deda |
* index in ARGV of the first ARGV-element that is not an option.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Side effects:
|
|
Packit |
78deda |
* the elements of ARGV are permuted
|
|
Packit |
78deda |
* usr_params [].value is modified
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
extern int optind; /* index in ARGV of the 1st element
|
|
Packit |
78deda |
that is not an option */
|
|
Packit |
78deda |
bool_t detailed_help = NO; /* NO if all parameters can be modified
|
|
Packit |
78deda |
with short options too */
|
|
Packit |
78deda |
unsigned n1; /* number of user parameters */
|
|
Packit |
78deda |
unsigned n2; /* number of system parameters */
|
|
Packit |
78deda |
bool_t read_config_file = NO; /* will override command line */
|
|
Packit |
78deda |
param_t *params; /* array of user and system params */
|
|
Packit |
78deda |
param_t *sys_params; /* array of system parameters */
|
|
Packit |
78deda |
param_t detailed_sys_params [] = /* detailed system parameters */
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
{"version", NULL, 'v', PFLAG, {0}, NULL,
|
|
Packit |
78deda |
"Print program version number, then exit."},
|
|
Packit |
78deda |
{"verbose", "NUM", 'V', PINT, {0}, "1",
|
|
Packit |
78deda |
"Set level of verbosity to `%s'."},
|
|
Packit |
78deda |
{"config", "FILE", 'f', PSTR, {0}, NULL,
|
|
Packit |
78deda |
"Load `%s' to initialize parameters."},
|
|
Packit |
78deda |
{"info", NULL, 'h', PFLAG, {0}, NULL,
|
|
Packit |
78deda |
"Print brief help, then exit."},
|
|
Packit |
78deda |
{"help", NULL, 'H', PFLAG, {0}, NULL,
|
|
Packit |
78deda |
"Print detailed help, then exit."},
|
|
Packit |
78deda |
{NULL, NULL, 0, PSTR, {0}, NULL, NULL }
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
param_t short_sys_params [] = /* short system parameters */
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
{"version", NULL, 'v', PFLAG, {0}, NULL,
|
|
Packit |
78deda |
"Print program version number, then exit."},
|
|
Packit |
78deda |
{"verbose", "NUM", 'V', PINT, {0}, "1",
|
|
Packit |
78deda |
"Set level of verbosity to `%s'."},
|
|
Packit |
78deda |
{"config", "FILE", 'f', PSTR, {0}, NULL,
|
|
Packit |
78deda |
"Load `%s' to initialize parameters."},
|
|
Packit |
78deda |
{"help", NULL, 'h', PFLAG, {0}, NULL,
|
|
Packit |
78deda |
"Print this help, then exit."},
|
|
Packit |
78deda |
{NULL, NULL, 0, PSTR, {0}, NULL, NULL }
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
char *sys_path; /* path to system config file */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
sys_path = calloc (strlen (path) + strlen (sys_file_name) + 2,
|
|
Packit |
78deda |
sizeof (char));
|
|
Packit |
78deda |
if (!sys_path)
|
|
Packit |
78deda |
error ("Out of memory.");
|
|
Packit |
78deda |
sprintf (sys_path, "%s/%s", path, sys_file_name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Set parameters defaults
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
param_t *p;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (p = usr_params; p->name != NULL; p++)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
set_parameter (p, p->default_value);
|
|
Packit |
78deda |
if (p->optchar == '\0')
|
|
Packit |
78deda |
detailed_help = YES;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
sys_params = detailed_help ? detailed_sys_params : short_sys_params;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (p = sys_params; p->name != NULL; p++)
|
|
Packit |
78deda |
set_parameter (p, p->default_value);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Append system command line option to user parameters
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
for (n1 = 0; usr_params [n1].name != NULL; n1++)
|
|
Packit |
78deda |
;
|
|
Packit |
78deda |
for (n2 = 0; sys_params [n2].name != NULL; n2++)
|
|
Packit |
78deda |
;
|
|
Packit |
78deda |
params = calloc (n1 + n2 + 1, sizeof (param_t));
|
|
Packit |
78deda |
if (!params)
|
|
Packit |
78deda |
error ("Out of memory.");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
memcpy (params, usr_params, n1 * sizeof (param_t));
|
|
Packit |
78deda |
memcpy (params + n1, sys_params, (n2 + 1) * sizeof (param_t));
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Try to open the system resource file 'path'/'sys_file_name'
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
FILE *parameter_file = open_file (sys_path, NULL, READ_ACCESS);
|
|
Packit |
78deda |
if (parameter_file == NULL)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
warning ("No system resource file found.");
|
|
Packit |
78deda |
*/ {}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
read_parameter_file (params, parameter_file);
|
|
Packit |
78deda |
fclose (parameter_file);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Try to read user resource file $HOME/'usr_file_name'
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
FILE *parameter_file = open_file (usr_file_name, "HOME", READ_ACCESS);
|
|
Packit |
78deda |
if (parameter_file != NULL)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
read_parameter_file (params, parameter_file);
|
|
Packit |
78deda |
fclose (parameter_file);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Parse command line options
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
extern char *optarg; /* argument of current option */
|
|
Packit |
78deda |
struct option *long_options; /* array of long options */
|
|
Packit |
78deda |
int option_index = 0;
|
|
Packit |
78deda |
char optstr [MAXSTRLEN]; /* string containing the legitimate
|
|
Packit |
78deda |
option characters */
|
|
Packit |
78deda |
int optchar; /* found option character */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Build short option string for getopt_long ().
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
param_t *p; /* counter */
|
|
Packit |
78deda |
char *ptr_optstr; /* pointer to position in string */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ptr_optstr = optstr;
|
|
Packit |
78deda |
for (p = params; p->name != NULL; p++)
|
|
Packit |
78deda |
if (p->optchar != '\0')
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
*ptr_optstr++ = p->optchar;
|
|
Packit |
78deda |
if (p->type == POSTR)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
*ptr_optstr++ = ':';
|
|
Packit |
78deda |
*ptr_optstr++ = ':';
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else if (p->type != PFLAG)
|
|
Packit |
78deda |
*ptr_optstr++ = ':';
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
*ptr_optstr = '\0';
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Build long option string for getopt_long ().
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
long_options = calloc (n1 + n2 + 1, sizeof (struct option));
|
|
Packit |
78deda |
if (!long_options)
|
|
Packit |
78deda |
error ("Out of memory.");
|
|
Packit |
78deda |
for (i = 0; params [i].name != NULL; i++)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
long_options [i].name = params [i].name;
|
|
Packit |
78deda |
switch (params [i].type)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
case PFLAG:
|
|
Packit |
78deda |
long_options [i].has_arg = 0;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case POSTR:
|
|
Packit |
78deda |
long_options [i].has_arg = 2;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PINT:
|
|
Packit |
78deda |
case PSTR:
|
|
Packit |
78deda |
case PFLOAT:
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
long_options [i].has_arg = 1;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
long_options [i].has_arg = params [i].type != PFLAG;
|
|
Packit |
78deda |
long_options [i].flag = NULL;
|
|
Packit |
78deda |
long_options [i].val = 0;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Parse comand line
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
while ((optchar = getopt_long (argc, argv, optstr, long_options,
|
|
Packit |
78deda |
&option_index)) != EOF)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int param_index = -1;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (optchar)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
case 0:
|
|
Packit |
78deda |
param_index = option_index;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case ':':
|
|
Packit |
78deda |
if (detailed_help)
|
|
Packit |
78deda |
fprintf (stderr,
|
|
Packit |
78deda |
"Try `%s -h' or `%s --help' for "
|
|
Packit |
78deda |
"more information.\n",
|
|
Packit |
78deda |
argv [0], argv [0]);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
fprintf (stderr, "Try `%s --help' for more information.\n",
|
|
Packit |
78deda |
argv [0]);
|
|
Packit |
78deda |
exit (2);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case '?':
|
|
Packit |
78deda |
if (detailed_help)
|
|
Packit |
78deda |
fprintf (stderr,
|
|
Packit |
78deda |
"Try `%s -h' or `%s --help' "
|
|
Packit |
78deda |
"for more information.\n",
|
|
Packit |
78deda |
argv [0], argv [0]);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
fprintf (stderr, "Try `%s --help' for more information.\n",
|
|
Packit |
78deda |
argv [0]);
|
|
Packit |
78deda |
exit (2);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int i;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; params [i].name != NULL; i++)
|
|
Packit |
78deda |
if (params [i].optchar == optchar)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
param_index = i;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Check for system options
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (param_index >= 0)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
set_parameter (params + param_index, optarg ? optarg : "");
|
|
Packit |
78deda |
if (streq (params [param_index].name, "help"))
|
|
Packit |
78deda |
usage (params, argv [0], synopsis, comment, non_opt_string,
|
|
Packit |
78deda |
YES, sys_path, usr_file_name);
|
|
Packit |
78deda |
else if (streq (params [param_index].name, "info"))
|
|
Packit |
78deda |
usage (params, argv [0], synopsis, comment, non_opt_string,
|
|
Packit |
78deda |
NO, sys_path, usr_file_name);
|
|
Packit |
78deda |
else if (streq (params [param_index].name, "version"))
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
fprintf (stderr, "%s " VERSION "\n", argv [0]);
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
/* Kludge for standard Netpbm version announcement */
|
|
Packit |
78deda |
char * modified_argv[2];
|
|
Packit |
78deda |
int argc;
|
|
Packit |
78deda |
modified_argv[0] = argv[0];
|
|
Packit |
78deda |
modified_argv[1] = (char *) "--version";
|
|
Packit |
78deda |
argc = 2;
|
|
Packit |
78deda |
pm_proginit(&argc, (const char **) modified_argv);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
exit (2);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else if (streq (params [param_index].name, "verbose"))
|
|
Packit |
78deda |
fiasco_set_verbosity (
|
|
Packit |
78deda |
* (fiasco_verbosity_e *) parameter_value (params,
|
|
Packit |
78deda |
"verbose"));
|
|
Packit |
78deda |
else if (streq (params [param_index].name, "config"))
|
|
Packit |
78deda |
read_config_file = YES;
|
|
Packit |
78deda |
param_index = -1; /* clear index flag */
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free (long_options);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Read config-file if specified by option -f
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
if (read_config_file)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
char *filename;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if ((filename = (char *) parameter_value (params, "config")) != NULL)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
FILE *parameter_file; /* input file */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
warning ("Options set in file `%s' will override"
|
|
Packit |
78deda |
" command line options.", filename);
|
|
Packit |
78deda |
parameter_file = open_file (filename, NULL, READ_ACCESS);
|
|
Packit |
78deda |
if (parameter_file != NULL)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
read_parameter_file (params, parameter_file);
|
|
Packit |
78deda |
fclose (parameter_file);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
file_error (filename);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
error ("Invalid config filename.");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
memcpy (usr_params, params, n1 * sizeof (param_t)); /* fill user struct */
|
|
Packit |
78deda |
free (sys_path);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return optind;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
void *
|
|
Packit |
78deda |
parameter_value (const param_t *params, const char *name)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Extract value of parameter 'name.' of the given parameters 'params'.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Return value:
|
|
Packit |
78deda |
* value of given parameter
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int pind = get_parameter_index (params, name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (pind < 0)
|
|
Packit |
78deda |
error ("Invalid parameter `%s'.", name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (params [pind].type == PSTR || params [pind].type == POSTR)
|
|
Packit |
78deda |
return (void *) params [pind].value.s;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return (void *) &(params [pind].value);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
void
|
|
Packit |
78deda |
ask_and_set (param_t *params, const char *name, const char *msg)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Ask user (print given message 'msg') for missing mandatory
|
|
Packit |
78deda |
* parameter 'name' of the given parameters 'params'.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* No return value.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Side effects:
|
|
Packit |
78deda |
* 'params ['name'].value' is changed
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
char answer [MAXSTRLEN];
|
|
Packit |
78deda |
int index = get_parameter_index (params, name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (index < 0)
|
|
Packit |
78deda |
error ("Invalid parameter %s.", name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (msg)
|
|
Packit |
78deda |
fprintf (stderr, "%s\n", msg);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (params [index].type)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
case PFLAG: /* Unusual, at least. */
|
|
Packit |
78deda |
warning ("Flags should be initialized and set on demand, "
|
|
Packit |
78deda |
"not request");
|
|
Packit |
78deda |
case PINT:
|
|
Packit |
78deda |
case PSTR:
|
|
Packit |
78deda |
case POSTR:
|
|
Packit |
78deda |
case PFLOAT:
|
|
Packit |
78deda |
scanf (MAXSTRLEN_SCANF, answer);
|
|
Packit |
78deda |
set_parameter (¶ms [index], answer);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
error ("Invalid parameter type for %s", name);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
void
|
|
Packit |
78deda |
write_parameters (const param_t *params, FILE *output)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Write all parameter settings to 'output'.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* No return value.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int pind;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (!params || !output)
|
|
Packit |
78deda |
error ("Parameters must be not NULL.");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (pind = 0; params [pind].name != NULL; pind++)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
fprintf (output, "# %s = ", params [pind].name);
|
|
Packit |
78deda |
switch (params [pind].type)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
case PFLAG:
|
|
Packit |
78deda |
fprintf (output, "%s\n", params [pind].value.b ? "TRUE" : "FALSE");
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PINT:
|
|
Packit |
78deda |
fprintf (output, "%d\n", params [pind].value.i);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PFLOAT:
|
|
Packit |
78deda |
fprintf (output, "%.4f\n", (double) params [pind].value.f);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PSTR:
|
|
Packit |
78deda |
case POSTR:
|
|
Packit |
78deda |
fprintf (output, "%s\n", params [pind].value.s);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
error ("Invalid type %d for parameter %s",
|
|
Packit |
78deda |
params [pind].type, params [pind].name);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
fputc ('\n', output);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*****************************************************************************
|
|
Packit |
78deda |
|
|
Packit |
78deda |
private code
|
|
Packit |
78deda |
|
|
Packit |
78deda |
*****************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
set_parameter (param_t *parameter, const char *value)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Set value of 'parameter' to 'value'.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* No return value.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Side effects:
|
|
Packit |
78deda |
* 'parameter.value' is changed accordingly
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
assert (parameter);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (parameter->type)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
case PFLAG:
|
|
Packit |
78deda |
if (value != NULL && *value != '\0')
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if (strcaseeq (value, "TRUE"))
|
|
Packit |
78deda |
parameter->value.b = YES;
|
|
Packit |
78deda |
else if (strcaseeq (value, "FALSE"))
|
|
Packit |
78deda |
parameter->value.b = NO;
|
|
Packit |
78deda |
else if (strcaseeq (value, "YES"))
|
|
Packit |
78deda |
parameter->value.b = YES;
|
|
Packit |
78deda |
else if (strcaseeq (value, "NO"))
|
|
Packit |
78deda |
parameter->value.b = NO;
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
long int data;
|
|
Packit |
78deda |
char *endptr;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
data = strtol (value, &endptr, 0);
|
|
Packit |
78deda |
if (*endptr != '\0' || endptr == value)
|
|
Packit |
78deda |
warning ("Invalid value `%s' converted to %d",
|
|
Packit |
78deda |
value, (int) data);
|
|
Packit |
78deda |
parameter->value.b = data ? YES : NO;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
parameter->value.b = !parameter->value.b;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PINT:
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
long int data;
|
|
Packit |
78deda |
char *endptr;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
data = strtol (value, &endptr, 0);
|
|
Packit |
78deda |
if (*endptr != '\0' || endptr == value)
|
|
Packit |
78deda |
warning ("Invalid value `%s' converted to %d",
|
|
Packit |
78deda |
value, (int) data);
|
|
Packit |
78deda |
parameter->value.i = data;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PFLOAT:
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
double data;
|
|
Packit |
78deda |
char *endptr;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
data = strtod (value, &endptr);
|
|
Packit |
78deda |
if (*endptr != '\0' || endptr == value)
|
|
Packit |
78deda |
warning ("Invalid value `%s' converted to %f",
|
|
Packit |
78deda |
value, (double) data);
|
|
Packit |
78deda |
parameter->value.f = data;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PSTR:
|
|
Packit |
78deda |
case POSTR:
|
|
Packit |
78deda |
parameter->value.s = value ? strdup (value) : NULL;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
error ("Invalid parameter type for %s", parameter->name);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static int
|
|
Packit |
78deda |
get_parameter_index (const param_t *params, const char *search_string)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Search for parameter with name 'search_string' in parameter struct.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Return value:
|
|
Packit |
78deda |
* index of parameter or -1 if no matching parameter has been found
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int n;
|
|
Packit |
78deda |
int index = -1;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
assert (params && search_string);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (n = 0; params [n].name != NULL; n++)
|
|
Packit |
78deda |
if (strcaseeq (params [n].name, search_string))
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
index = n;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return index;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
read_parameter_file (param_t *params, FILE *file)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Read parameter settings from 'file'.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* No return value.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* Side effects:
|
|
Packit |
78deda |
* 'params [].value' are changed if specified in 'file'
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
char buffer [MAXSTRLEN];
|
|
Packit |
78deda |
int n = 0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
assert (params && file);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
while (fgets (buffer, MAXSTRLEN, file) != NULL)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
char *b; /* temporary variable */
|
|
Packit |
78deda |
char *name; /* parameter name */
|
|
Packit |
78deda |
char *value; /* parameter value */
|
|
Packit |
78deda |
int pind; /* current argument number */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
b = strchr (buffer, '#');
|
|
Packit |
78deda |
if (b != NULL) /* Strip comments. */
|
|
Packit |
78deda |
*b = '\0';
|
|
Packit |
78deda |
|
|
Packit |
78deda |
b = strchr (buffer, '=');
|
|
Packit |
78deda |
if (b == NULL) /* Strip lines that contain no '=' */
|
|
Packit |
78deda |
continue;
|
|
Packit |
78deda |
*b = '\0'; /* Replace '=' by string terminator */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Extract value of parameter
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
for (value = b + 1; ISSPACE (*value); value++)
|
|
Packit |
78deda |
; /* Delete leading spaces */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (b = value + strlen (value) - 1; b >= value && ISSPACE (*b); b--)
|
|
Packit |
78deda |
*b = '\0'; /* Delete trailing spaces. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Extract parameter name
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
for (name = buffer; ISSPACE (*name); name++)
|
|
Packit |
78deda |
; /* Delete leading spaces */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (b = name + strlen (name) - 1; b >= name && ISSPACE (*b); b--)
|
|
Packit |
78deda |
*b = '\0'; /* Delete trailing spaces. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pind = get_parameter_index (params, name);
|
|
Packit |
78deda |
if (pind >= 0)
|
|
Packit |
78deda |
set_parameter (¶ms [pind], value);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
n++;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
usage (const param_t *params, const char *progname, const char *synopsis,
|
|
Packit |
78deda |
const char *comment, const char *non_opt_string,
|
|
Packit |
78deda |
bool_t show_all_options, const char *sys_file_name,
|
|
Packit |
78deda |
const char *usr_file_name)
|
|
Packit |
78deda |
/*
|
|
Packit |
78deda |
* Generates and prints command line description from param_t struct 'params'.
|
|
Packit |
78deda |
* 'progname' is the name of the excecutable, 'synopsis' a short program
|
|
Packit |
78deda |
* description, and 'comment' some more advice.
|
|
Packit |
78deda |
* If flag 'show_all_options' is set then print also options that are not
|
|
Packit |
78deda |
* associated with a short option character.
|
|
Packit |
78deda |
* 'sys_file_name' and 'usr_file_name' are filenames to parameter files.
|
|
Packit |
78deda |
*
|
|
Packit |
78deda |
* No return value.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
int i;
|
|
Packit |
78deda |
size_t width = 0;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
fprintf (stderr, "Usage: %s [OPTION]...%s\n", progname,
|
|
Packit |
78deda |
non_opt_string ? non_opt_string : " ");
|
|
Packit |
78deda |
if (synopsis != NULL)
|
|
Packit |
78deda |
fprintf (stderr, "%s", synopsis);
|
|
Packit |
78deda |
fprintf (stderr, "\n\n");
|
|
Packit |
78deda |
fprintf (stderr, "Mandatory or optional arguments to long options "
|
|
Packit |
78deda |
"are mandatory or optional\nfor short options too. "
|
|
Packit |
78deda |
"Default values are surrounded by {}.\n");
|
|
Packit |
78deda |
for (i = 0; params [i].name != NULL; i++)
|
|
Packit |
78deda |
if (params [i].optchar != '\0' || show_all_options)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if (params [i].type == POSTR)
|
|
Packit |
78deda |
width = MAX(width, (strlen (params [i].name)
|
|
Packit |
78deda |
+ strlen (params [i].argument_name) + 2));
|
|
Packit |
78deda |
else if (params [i].type != PFLAG)
|
|
Packit |
78deda |
width = MAX(width, (strlen (params [i].name)
|
|
Packit |
78deda |
+ strlen (params [i].argument_name)));
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
width = MAX(width, (strlen (params [i].name)) - 1);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (i = 0; params [i].name != NULL; i++)
|
|
Packit |
78deda |
if (params [i].optchar != '\0' || show_all_options)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
if (params [i].optchar != '\0')
|
|
Packit |
78deda |
fprintf (stderr, " -%c, --", params [i].optchar);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
fprintf (stderr, " --");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (params [i].type == POSTR)
|
|
Packit |
78deda |
fprintf (stderr, "%s=[%s]%-*s ", params [i].name,
|
|
Packit |
78deda |
params [i].argument_name,
|
|
Packit |
78deda |
(unsigned)
|
|
Packit |
78deda |
MAX(0, (width - 2 - strlen (params [i].name)
|
|
Packit |
78deda |
- strlen (params [i].argument_name))), "");
|
|
Packit |
78deda |
else if (params [i].type != PFLAG)
|
|
Packit |
78deda |
fprintf (stderr, "%s=%-*s ", params [i].name,
|
|
Packit |
78deda |
(unsigned)(width - strlen (params [i].name)),
|
|
Packit |
78deda |
params [i].argument_name);
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
fprintf (stderr, "%-*s ",
|
|
Packit |
78deda |
(unsigned)(width + 1), params [i].name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
fprintf (stderr, params [i].use, params [i].argument_name);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
switch (params [i].type)
|
|
Packit |
78deda |
{
|
|
Packit |
78deda |
case PFLAG:
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PINT:
|
|
Packit |
78deda |
fprintf (stderr, "{%d}", params [i].value.i);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PFLOAT:
|
|
Packit |
78deda |
fprintf (stderr, "{%.2f}", (double) params [i].value.f);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case PSTR:
|
|
Packit |
78deda |
case POSTR:
|
|
Packit |
78deda |
if (params [i].value.s)
|
|
Packit |
78deda |
fprintf (stderr, "{%s}", params [i].value.s);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
default:
|
|
Packit |
78deda |
error ("type %d for %s invalid",
|
|
Packit |
78deda |
params [i].type, params [i].name);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
fprintf (stderr, "\n");
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
fprintf (stderr, "\n");
|
|
Packit |
78deda |
fprintf (stderr, "Parameter initialization order:\n");
|
|
Packit |
78deda |
fprintf (stderr,
|
|
Packit |
78deda |
"1.) %s\n2.) $HOME/%s\t 3.) command line\t 4.) --config=file",
|
|
Packit |
78deda |
sys_file_name, usr_file_name);
|
|
Packit |
78deda |
fprintf (stderr, "\n\n");
|
|
Packit |
78deda |
if (comment != NULL)
|
|
Packit |
78deda |
fprintf (stderr, "%s\n", comment);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
exit (1);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|