Blame converter/other/fiasco/params.c

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 (&params [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 (&params [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