1 /*
2  * Source file:
3  *       options.c
4  */
5 
6 #include "config.h"
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #ifdef HAVE_GETOPT_H
12 #include <getopt.h>
13 #else
14 #include "getopt.h"
15 #endif
16 
17 extern int optind;  /* undocumented variable used to reset getopt() */
18 
19 #include "trueprint.h" /* needed for boolean type */
20 #include "utils.h" /* needed for strdup */
21 #include "debug.h" /* needed for dm macro */
22 
23 #include "options.h"
24 
25 /******************************************************************************
26  * Macros
27  */
28 
29 /* If there are more than MAX_OPTIONS options then this must be increased */
30 #define MAX_OPTIONS 256
31 
32 /* This must specify a bit outside the range of MAX_OPTIONS */
33 #define OPT_FLAG 0x1000
34 
35 #define SHORT_OPTION(opt) (short_options[('A'<=opt&&opt<='Z')?(opt-'A')*2:\
36                       ('a'<=opt&&opt<='z')?(opt-'a')*2+1:\
37                       ('0'<=opt&&opt<='9')?opt-'0'+52:\
38                       62])
39 
40 #define PRINTUSAGE printf(gettext(" Usage: trueprint <options> <filename>\n   Use -H for details\n"))
41 
42 /******************************************************************************
43  * Typedefs
44  */
45 
46 typedef enum {
47   NOPARM,
48   OPTIONAL,
49   BOOLEAN,
50   CHAR,
51   CHOICE,
52   SHORT,
53   INT,
54   STRING,
55   FLAG_STRING
56 } option_types;
57 
58 typedef struct option_type{
59   char		letter;
60   option_types	type;
61   boolean	set;
62   char		need_string;
63   option_class	class;
64   union {
65     struct {
66       char *string;
67       boolean default_opt;
68       void (*handler)(const char *p, const char *s);
69       void (*set_default)(void);
70       char *help_string;
71     } onoparm;
72     struct {
73       char *string;
74       void (*handler)(const char *p, const char *s, char *value);
75       char *help_string;
76     } ooptional;
77     struct {
78       char *true_string;
79       char *false_string;
80       boolean *var;
81       boolean default_value;
82       void (*handler)(const char *p, const char *s, boolean value);
83       void (*set_default)(boolean value);
84       char *true_help_string;
85       char *false_help_string;
86     } obool;
87     struct {
88       char *string;
89       char *var;
90       char default_value;
91       char *valid_set;
92       void (*handler)(const char *p, const char *s, char value, char *valid_set);
93       void (*set_default)(char value);
94       char *help_string;
95     } ochar;
96     struct {
97       char *var;
98       char *choice1_string;
99       char *choice2_string;
100       char choice1; /* Also default */
101       char choice2;
102       void (*handler)(const char *p, const char *s, char value);
103       void (*set_default)(char value);
104       char *choice1_help_string;
105       char *choice2_help_string;
106     } ochoice;
107     struct {
108       char *string;
109       short *var;
110       short default_value;
111       char *special_string;
112       short special_value;
113       short  min;
114       short  max;
115       void (*handler)(const char *p, const char *s, short value, short min, short max);
116       void (*set_default)(short value);
117       char *help_string;
118       char *special_help_string;
119     } oshrt;
120     struct {
121       char *string;
122       int *var;
123       int default_value;
124       char *special_string;
125       short special_value;
126       int  min;
127       int  max;
128       void (*handler)(const char *p, const char *s, int value, int min, int max);
129       void (*set_default)(int value);
130       char *help_string;
131       char *special_help_string;
132     } oint;
133     struct {
134       char *string;
135       char **var;
136       char *default_value;
137       void (*handler)(const char *p, const char *s, char *value);
138       void (*set_default)(char *value);
139       char *help_string;
140     } ostrng;
141     struct {
142       char *set_string;
143       char *not_set_string;
144       boolean flag_var;
145       char **var;
146       boolean default_value;
147       char *true_value;
148       char *false_value;
149       void (*handler)(const char *p, const char *s, boolean value, char *true_value, char *false_value);
150       void (*set_default)(boolean value, char *string_value);
151       char *set_help_string;
152       char *not_set_help_string;
153     } oflg;
154   } t;
155 } option_type;
156 
157 /******************************************************************************
158  * Private functions
159  */
160 static void set_option(int option, char *prefix, const char *option_name, char *value);
161 static void set_option_default(int option);
162 
163 /******************************************************************************
164  * Constant variables and data structures
165  */
166 
167 static int short_options[62];
168 
169 static struct option_type option_list[MAX_OPTIONS+1];
170 static struct option long_options[MAX_OPTIONS+1];
171 static int next_option;
172 static int next_long_option;
173 static int this_option;
174 
175 /******************************************************************************
176  * Function:
177  *	setup_options
178  */
179 void
setup_options(void)180 setup_options(void)
181 {
182   next_option = 0;
183   next_long_option = 0;
184 }
185 
186 /******************************************************************************
187  * Function:
188  *	handle_string_options
189  *
190  * This function takes options as a single string, parses them into
191  * a char[][], and calls handle_options.
192  */
193 void
handle_string_options(char * options)194 handle_string_options(char *options)
195 
196 {
197   int	opt_argc = -1;
198   char	arguments[100][100];
199   char	*opt_argv[100];
200   int	options_index = -1;
201   int	argv_index = 0;
202   boolean	quoted = FALSE;
203   boolean ended = FALSE;
204 
205   if (options == (char *)0) return;
206   if (strlen(options) == 0) return;
207 
208   while (ended == FALSE)
209     {
210       switch (options[++options_index])
211 	{
212 	case ' ':
213 	case '	':
214 	  if (quoted)
215 	    {
216 	      if (argv_index == 0) opt_argc += 1;
217 	      arguments[opt_argc][argv_index++] = options[options_index];
218 	      continue;
219 	    }
220 	  if (argv_index > 0)
221 	    {
222 	      arguments[opt_argc][argv_index] = '\0';
223 	      argv_index = 0;
224 	    }
225 	  break;
226 
227 	case '\0':
228 	  if (argv_index > 0)
229 	    {
230 	      arguments[opt_argc][argv_index] = '\0';
231 	      argv_index = 0;
232 	    }
233 	  ended = TRUE;
234 	  break;
235 
236 	case '"':
237 	  if (quoted) quoted = FALSE;
238 	  else
239 	    quoted = TRUE;
240 	  break;
241 
242 	default:
243 	  if (argv_index == 0) opt_argc += 1;
244 	  arguments[opt_argc][argv_index++] = options[options_index];
245 	  break;
246 	}
247     }
248   opt_argc += 1;
249 
250   for (argv_index=0; argv_index < opt_argc; argv_index++)
251     opt_argv[argv_index+1] = arguments[argv_index];
252 
253   opt_argv[0] = opt_argv[1];
254   opt_argc += 1;
255 
256   handle_options(opt_argc, opt_argv);
257   return;
258 }
259 
260 /******************************************************************************
261  * Function:
262  *	handle_options
263  *
264  * This function handles the options passed to the program, and also
265  * the defaults for each language.  Since the options passed to the
266  * program gake priority and are also found first, this function
267  * will only assign a value to a flag if the flag has not previously
268  * been set.
269  */
270 unsigned int
handle_options(int argc,char ** argv)271 handle_options(int argc, char **argv)
272 
273 {
274   int option;
275   int option_index;
276   int short_option_index = 0;
277   int long_option_index;
278   char short_option_list[125]; /* 125 = (26+26+10)*2 + 1 */
279 
280   /*
281    * Since this function will be called twice, we need to initialise
282    * getopt_long() variables to make sure that it behaves properly during
283    * the second call.
284    */
285   optind = 1;
286 
287   /*
288    * Set up the string of single-letter options and set the last long_option
289    * to all zeros - this will be done multiple times each time trueprint
290    * is invoked, but it's quick so it shouldn't hurt.
291    */
292   for (option_index = 0; option_index < next_long_option; option_index++)
293     {
294       if (option_list[option_index].letter)
295 	{
296 	  short_option_list[short_option_index++] = option_list[option_index].letter;
297 	  if (option_list[option_index].need_string)
298 	    short_option_list[short_option_index++] = ':';
299 	}
300     }
301 
302   long_options[next_long_option].name = 0;
303   long_options[next_long_option].has_arg = 0;
304   long_options[next_long_option].flag = 0;
305   long_options[next_long_option].val = 0;
306 
307   /*
308    * Loop through the options.  This call will set this_option
309    * to the option number if it is looking at a long option.
310    */
311   while ((option =
312 	  getopt_long((unsigned int)argc, argv,
313 		      short_option_list, long_options, &long_option_index)
314 	  ) != EOF)
315     {
316       if (option == '?')
317 	{
318 	  fprintf(stderr, gettext(CMD_NAME ": failed to parse options\n"));
319 	  exit(1);
320 	}
321       else if (option != 0)
322 	{
323 	  char *option_name;
324 	  option_name = xmalloc(2);
325 	  option_name[0] = option;
326 	  option_name[1] = '\0';
327 	  option_index = SHORT_OPTION(option);
328 	  set_option(option_index,"-",option_name,optarg);
329 	}
330       else
331 	{
332 	  set_option(this_option, "--", long_options[long_option_index].name,optarg);
333 	}
334     }
335   return(optind);
336 }
337 
338 /******************************************************************************
339  * Option declaration functions
340  */
341 
342 /******************************************************************************
343  * noparm_option
344  * -c
345  * --s
346  * Calls handler if used.
347  * Uses either single-letter option or string long option or both
348  */
noparm_option(char * c,char * s,boolean default_opt,void (* handler)(const char * p,const char * s),void (* set_default)(void),option_class class,char * help_string)349 void noparm_option(char *c, char *s,
350 		   boolean default_opt,
351 		   void (*handler)(const char *p, const char *s),
352 		   void (*set_default)(void),
353 		   option_class class,
354 		   char *help_string)
355 {
356   int option_index = next_option++;
357 
358   if (s)
359     {
360       int long_option_index = next_long_option++;
361       long_options[long_option_index].name = s;
362       long_options[long_option_index].has_arg = 0;
363       long_options[long_option_index].flag = &this_option;
364       long_options[long_option_index].val = option_index;
365     }
366 
367   /*
368    * This checks for an internal error, so it is OK to
369    * risk an out-of-bounds access
370    * before checking for the bounds limit.
371    */
372   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
373     abort();
374 
375   if (handler == NULL)
376     abort();
377 
378   if (default_opt && set_default == NULL)
379     abort();
380 
381   if (c)
382     {
383       option_list[option_index].letter = *c;
384       SHORT_OPTION(*c) = option_index;
385     }
386   else
387     option_list[option_index].letter = 0;
388 
389   option_list[option_index].type = NOPARM;
390   option_list[option_index].class = class;
391   option_list[option_index].need_string = FALSE;
392   option_list[option_index].set = FALSE;
393   option_list[option_index].t.onoparm.string = s;
394   option_list[option_index].t.onoparm.default_opt = default_opt;
395   option_list[option_index].t.onoparm.handler = handler;
396   option_list[option_index].t.onoparm.set_default = set_default;
397   option_list[option_index].t.onoparm.help_string = help_string;
398 }
399 
400 /******************************************************************************
401  * optional_string_option
402  * -c
403  * --s
404  * --s=[string]
405  * Note that only the long option has the optional string.
406  * Calls handler if used.
407  * Uses either single-letter option or string long option or both
408  */
optional_string_option(char * c,char * s,void (* handler)(const char * p,const char * s,char * value),option_class class,char * help_string)409 void optional_string_option(char *c, char *s,
410 			    void (*handler)(const char *p, const char *s, char *value),
411 			    option_class class,
412 			    char *help_string)
413 {
414   int option_index = next_option++;
415 
416   if (s)
417     {
418       int long_option_index = next_long_option++;
419       long_options[long_option_index].name = s;
420       long_options[long_option_index].has_arg = 2;
421       long_options[long_option_index].flag = &this_option;
422       long_options[long_option_index].val = option_index;
423     }
424 
425   /*
426    * This checks for an internal error, so it is OK to
427    * risk an out-of-bounds access
428    * before checking for the bounds limit.
429    */
430   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
431     abort();
432 
433   if (handler == NULL)
434     abort();
435 
436   if (c)
437     {
438       option_list[option_index].letter = *c;
439       SHORT_OPTION(*c) = option_index;
440     }
441   else
442     option_list[option_index].letter = 0;
443 
444   option_list[option_index].type = OPTIONAL;
445   option_list[option_index].class = class;
446   option_list[option_index].need_string = FALSE;
447   option_list[option_index].set = FALSE;
448   option_list[option_index].t.ooptional.string = s;
449   option_list[option_index].t.ooptional.handler = handler;
450   option_list[option_index].t.ooptional.help_string = help_string;
451 }
452 
453 /******************************************************************************
454  * boolean_option
455  * -c = set option to TRUE
456  * --c = set option to FALSE
457  * --s1 = set option to TRUE
458  * --s2 = set option to FALSE
459  */
boolean_option(char * c,char * s1,char * s2,boolean default_value,boolean * var,void (* handler)(const char * p,const char * s,boolean value),void (* set_default)(boolean value),option_class class,char * true_help_string,char * false_help_string)460 void boolean_option(char *c, char *s1, char *s2,
461 		    boolean default_value,
462 		    boolean *var,
463 		    void (*handler)(const char *p, const char *s, boolean value),
464 		    void (*set_default)(boolean value),
465 		    option_class class,
466 		    char *true_help_string,
467 		    char *false_help_string)
468 {
469   int option_index = next_option++;
470 
471   if (c)
472     {
473       int long_option_index = next_long_option++;
474       option_list[option_index].letter = *c;
475       SHORT_OPTION(*c) = option_index;
476       long_options[long_option_index].name = c;
477       long_options[long_option_index].has_arg = 0;
478       long_options[long_option_index].flag = &this_option;
479       long_options[long_option_index].val = option_index | OPT_FLAG;
480     }
481   else
482     option_list[option_index].letter = 0;
483 
484   if (s1)
485     {
486       int long_option_index = next_long_option++;
487       long_options[long_option_index].name = s1;
488       long_options[long_option_index].has_arg = 0;
489       long_options[long_option_index].flag = &this_option;
490       long_options[long_option_index].val = option_index;
491     }
492   if (s2)
493     {
494       int long_option_index = next_long_option++;
495       long_options[long_option_index].name = s2;
496       long_options[long_option_index].has_arg = 0;
497       long_options[long_option_index].flag = &this_option;
498       long_options[long_option_index].val = option_index | OPT_FLAG;
499     }
500 
501   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
502     abort();
503   if ((var == NULL) && (handler == NULL))
504     abort();
505   if ((var != NULL) && (handler != NULL))
506     abort();
507   if ((handler == NULL) != (set_default == NULL))
508     abort();
509 
510   option_list[option_index].type = BOOLEAN;
511   option_list[option_index].class = class;
512   option_list[option_index].need_string = FALSE;
513   option_list[option_index].set = FALSE;
514   option_list[option_index].t.obool.true_string = s1;
515   option_list[option_index].t.obool.false_string = s2;
516   option_list[option_index].t.obool.var = var;
517   option_list[option_index].t.obool.default_value = default_value;
518   option_list[option_index].t.obool.handler = handler;
519   option_list[option_index].t.obool.set_default = set_default;
520   option_list[option_index].t.obool.true_help_string = true_help_string;
521   option_list[option_index].t.obool.false_help_string = false_help_string;
522 }
523 
524 /******************************************************************************
525  * choice_option
526  * -c <letter>
527  * --s1
528  * --s2
529  */
choice_option(char * c,char * s1,char * s2,char choice1,char choice2,char * var,void (* handler)(const char * p,const char * s,char value),void (* set_default)(char value),option_class class,char * choice1_help_string,char * choice2_help_string)530 void choice_option(char *c, char *s1, char *s2,
531 		   char choice1, char choice2,
532 		   char *var,
533 		   void (*handler)(const char *p, const char *s, char value),
534 		   void (*set_default)(char value),
535 		   option_class class,
536 		   char *choice1_help_string,
537 		   char *choice2_help_string)
538 {
539   int option_index = next_option++;
540 
541   if (c)
542     {
543       option_list[option_index].letter = *c;
544       SHORT_OPTION(*c) = option_index;
545     }
546   else
547     option_list[option_index].letter = 0;
548 
549   if (s1)
550     {
551       int long_option_index = next_long_option++;
552       long_options[long_option_index].name = s1;
553       long_options[long_option_index].has_arg = 0;
554       long_options[long_option_index].flag = &this_option;
555       long_options[long_option_index].val = option_index;
556     }
557 
558   if (s2)
559     {
560       int long_option_index = next_long_option++;
561       long_options[long_option_index].name = s2;
562       long_options[long_option_index].has_arg = 0;
563       long_options[long_option_index].flag = &this_option;
564       long_options[long_option_index].val = option_index | OPT_FLAG;
565     }
566 
567   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
568     abort();
569   if ((var == NULL) && (handler == NULL))
570     abort();
571   if ((var != NULL) && (handler != NULL))
572     abort();
573   if ((handler == NULL) != (set_default == NULL))
574     abort();
575 
576   option_list[option_index].type = CHOICE;
577   option_list[option_index].class = class;
578   option_list[option_index].need_string = TRUE;
579   option_list[option_index].set = FALSE;
580   option_list[option_index].t.ochoice.var = var;
581   option_list[option_index].t.ochoice.choice1_string = s1;
582   option_list[option_index].t.ochoice.choice2_string = s2;
583   option_list[option_index].t.ochoice.choice1 = choice1;
584   option_list[option_index].t.ochoice.choice2 = choice2;
585   option_list[option_index].t.ochoice.handler = handler;
586   option_list[option_index].t.ochoice.set_default = set_default;
587   option_list[option_index].t.ochoice.choice1_help_string = choice1_help_string;
588   option_list[option_index].t.ochoice.choice2_help_string = choice2_help_string;
589 }
590 
591 /******************************************************************************
592  * char_option
593  * -c <letter>
594  * --s <letter>
595  */
char_option(char * c,char * s,char default_value,char * valid_set,char * var,void (* handler)(const char * p,const char * s,char value,char * var),void (* set_default)(char value),option_class class,char * help_string)596 void char_option(char *c, char *s,
597 		 char default_value,
598 		 char *valid_set,
599 		 char *var,
600 		 void (*handler)(const char *p, const char *s, char value, char *var),
601 		 void (*set_default)(char value),
602 		 option_class class,
603 		 char *help_string)
604 {
605   int option_index = next_option++;
606 
607   if (c)
608     {
609       option_list[option_index].letter = *c;
610       SHORT_OPTION(*c) = option_index;
611     }
612   else
613     option_list[option_index].letter = 0;
614 
615   if (s)
616     {
617       int long_option_index = next_long_option++;
618       long_options[long_option_index].name = s;
619       long_options[long_option_index].has_arg = 1;
620       long_options[long_option_index].flag = &this_option;
621       long_options[long_option_index].val = option_index;
622     }
623 
624   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
625     abort();
626   if ((var == NULL) && (handler == NULL))
627     abort();
628   if ((var != NULL) && (handler != NULL))
629     abort();
630   if ((handler == NULL) != (set_default == NULL))
631     abort();
632 
633   option_list[option_index].type = CHAR;
634   option_list[option_index].class = class;
635   option_list[option_index].need_string = TRUE;
636   option_list[option_index].set = FALSE;
637   option_list[option_index].t.ochar.string = s;
638   option_list[option_index].t.ochar.var = var;
639   option_list[option_index].t.ochar.default_value = default_value;
640   option_list[option_index].t.ochar.valid_set = valid_set;
641   option_list[option_index].t.ochar.handler = handler;
642   option_list[option_index].t.ochar.set_default = set_default;
643   option_list[option_index].t.ochar.help_string = help_string;
644 }
645 
646 /******************************************************************************
647  * short_option
648  * -c <short>
649  * --s <short>
650  */
short_option(char * c,char * s,short default_value,char * special_string,short special_value,short min,short max,short * var,void (* handler)(const char * p,const char * s,short value,short min,short max),void (* set_default)(short value),option_class class,char * help_string,char * special_help_string)651 void short_option(char *c, char *s, short default_value,
652 		  char *special_string, short special_value,
653 		  short min, short max,
654 		  short *var,
655 		  void (*handler)(const char *p, const char *s, short value, short min, short max),
656 		  void (*set_default)(short value),
657 		  option_class class,
658 		  char *help_string,
659 		  char *special_help_string)
660 {
661   int option_index = next_option++;
662 
663   if (c)
664     {
665       option_list[option_index].letter = *c;
666       SHORT_OPTION(*c) = option_index;
667     }
668   else
669     option_list[option_index].letter = 0;
670 
671   if (s)
672     {
673       int long_option_index = next_long_option++;
674       long_options[long_option_index].name = s;
675       long_options[long_option_index].has_arg = 1;
676       long_options[long_option_index].flag = &this_option;
677       long_options[long_option_index].val = option_index;
678     }
679 
680   if (special_string)
681     {
682       int long_option_index = next_long_option++;
683       long_options[long_option_index].name = special_string;
684       long_options[long_option_index].has_arg = 0;
685       long_options[long_option_index].flag = &this_option;
686       long_options[long_option_index].val = option_index | OPT_FLAG;
687     }
688 
689   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
690     abort();
691   if ((var == NULL) && (handler == NULL))
692     abort();
693   if ((var != NULL) && (handler != NULL))
694     abort();
695   if ((handler == NULL) != (set_default == NULL))
696     abort();
697 
698   option_list[option_index].type = SHORT;
699   option_list[option_index].class = class;
700   option_list[option_index].need_string = TRUE;
701   option_list[option_index].set = FALSE;
702   option_list[option_index].t.oshrt.string = s;
703   option_list[option_index].t.oshrt.var = var;
704   option_list[option_index].t.oshrt.min = min;
705   option_list[option_index].t.oshrt.max = max;
706   option_list[option_index].t.oshrt.default_value = default_value;
707   option_list[option_index].t.oshrt.handler = handler;
708   option_list[option_index].t.oshrt.set_default = set_default;
709   option_list[option_index].t.oshrt.help_string = help_string;
710   option_list[option_index].t.oshrt.special_string = special_string;
711   option_list[option_index].t.oshrt.special_value = special_value;
712   option_list[option_index].t.oshrt.special_help_string = special_help_string;
713 }
714 
715 /******************************************************************************
716  * int_option
717  * -c <short>
718  * --s <short>
719  */
720 
int_option(char * c,char * s,int default_value,char * special_string,int special_value,int min,int max,int * var,void (* handler)(const char * p,const char * s,int value,int min,int max),void (* set_default)(int value),option_class class,char * help_string,char * special_help_string)721 void int_option(char *c, char *s, int default_value,
722 		char *special_string, int special_value,
723 		int min, int max,
724 		int *var,
725 		void (*handler)(const char *p, const char *s, int value, int min, int max),
726 		void (*set_default)(int value),
727 		option_class class,
728 		char *help_string,
729 		char *special_help_string)
730 {
731   int option_index = next_option++;
732 
733   if (c)
734     {
735       option_list[option_index].letter = *c;
736       SHORT_OPTION(*c) = option_index;
737     }
738   else
739     option_list[option_index].letter = 0;
740 
741   if (s)
742     {
743       int long_option_index = next_long_option++;
744       long_options[long_option_index].name = s;
745       long_options[long_option_index].has_arg = 1;
746       long_options[long_option_index].flag = &this_option;
747       long_options[long_option_index].val = option_index;
748     }
749 
750   if (special_string)
751     {
752       int long_option_index = next_long_option++;
753       long_options[long_option_index].name = special_string;
754       long_options[long_option_index].has_arg = 0;
755       long_options[long_option_index].flag = &this_option;
756       long_options[long_option_index].val = option_index | OPT_FLAG;
757     }
758 
759   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
760     abort();
761   if ((var == NULL) && (handler == NULL))
762     abort();
763   if ((var != NULL) && (handler != NULL))
764     abort();
765   if ((handler == NULL) != (set_default == NULL))
766     abort();
767 
768   option_list[option_index].type = INT;
769   option_list[option_index].class = class;
770   option_list[option_index].need_string = TRUE;
771   option_list[option_index].set = FALSE;
772   option_list[option_index].t.oint.string = s;
773   option_list[option_index].t.oint.var = var;
774   option_list[option_index].t.oint.min = min;
775   option_list[option_index].t.oint.max = max;
776   option_list[option_index].t.oint.default_value = default_value;
777   option_list[option_index].t.oint.handler = handler;
778   option_list[option_index].t.oint.set_default = set_default;
779   option_list[option_index].t.oint.help_string = help_string;
780   option_list[option_index].t.oint.special_string = special_string;
781   option_list[option_index].t.oint.special_value = special_value;
782   option_list[option_index].t.oint.special_help_string = special_help_string;
783 }
784 
785 /******************************************************************************
786  * string_option
787  * -c <string>
788  * --s <string>
789  */
string_option(char * c,char * s,char * default_value,char ** var,void (* handler)(const char * p,const char * s,char * value),void (* set_default)(char * value),option_class class,char * help_string)790 void string_option(char *c, char *s,
791 		   char *default_value,
792 		   char **var,
793 		   void (*handler)(const char *p, const char *s, char *value),
794 		   void (*set_default)(char *value),
795 		   option_class class,
796 		   char *help_string)
797 {
798   int option_index = next_option++;
799 
800   if (c)
801     {
802       option_list[option_index].letter = *c;
803       SHORT_OPTION(*c) = option_index;
804     }
805   else
806     option_list[option_index].letter = 0;
807 
808   if (s)
809     {
810       int long_option_index = next_long_option++;
811       long_options[long_option_index].name = s;
812       long_options[long_option_index].has_arg = 1;
813       long_options[long_option_index].flag = &this_option;
814       long_options[long_option_index].val = option_index;
815     }
816 
817   if ((var == NULL) && (handler == NULL))
818     abort();
819   if ((var != NULL) && (handler != NULL))
820     abort();
821   if ((handler == NULL) != (set_default == NULL))
822     abort();
823 
824   option_list[option_index].type = STRING;
825   option_list[option_index].class = class;
826   option_list[option_index].need_string = TRUE;
827   option_list[option_index].set = FALSE;
828   option_list[option_index].t.ostrng.string = s;
829   option_list[option_index].t.ostrng.var = var;
830   option_list[option_index].t.ostrng.default_value = default_value;
831   option_list[option_index].t.ostrng.handler = handler;
832   option_list[option_index].t.ostrng.set_default = set_default;
833   option_list[option_index].t.ostrng.help_string = help_string;
834 }
835 
836 /******************************************************************************
837  * flag_string_option
838  * -c <string>
839  * --c
840  * -s1 <string>
841  * --s2
842  */
flag_string_option(char * c,char * s1,char * s2,boolean default_value,char * true_value,char * false_value,char ** var,void (* handler)(const char * p,const char * s,boolean value,char * true_value,char * false_value),void (* set_default)(boolean value,char * string_value),option_class class,char * set_help_string,char * not_set_help_string)843 void flag_string_option(char *c, char *s1, char *s2,
844 			boolean default_value,
845 			char *true_value, char *false_value,
846 			char **var,
847 			void (*handler)(const char *p, const char *s, boolean value, char *true_value, char *false_value),
848 			void (*set_default)(boolean value, char *string_value),
849 			option_class class,
850 			char *set_help_string,
851 			char *not_set_help_string)
852 {
853   int option_index = next_option++;
854 
855   if (c)
856     {
857       option_list[option_index].letter = *c;
858       SHORT_OPTION(*c) = option_index;
859     }
860   else
861     option_list[option_index].letter = 0;
862 
863   if (s1)
864     {
865       int long_option_index = next_long_option++;
866       long_options[long_option_index].name = s1;
867       long_options[long_option_index].has_arg = 1;
868       long_options[long_option_index].flag = &this_option;
869       long_options[long_option_index].val = option_index;
870     }
871 
872   if (s2)
873     {
874       int long_option_index = next_long_option++;
875       long_options[long_option_index].name = s2;
876       long_options[long_option_index].has_arg = 0;
877       long_options[long_option_index].flag = &this_option;
878       long_options[long_option_index].val = option_index | OPT_FLAG;
879     }
880 
881   if ((next_option > MAX_OPTIONS) || (next_long_option > MAX_OPTIONS))
882     abort();
883   if ((var == NULL) && (handler == NULL))
884     abort();
885   if ((var != NULL) && (handler != NULL))
886     abort();
887   if ((handler == NULL) != (set_default == NULL))
888     abort();
889 
890   option_list[option_index].type = FLAG_STRING;
891   option_list[option_index].class = class;
892   option_list[option_index].need_string = FALSE;
893   option_list[option_index].set = FALSE;
894   option_list[option_index].t.oflg.var = var;
895   option_list[option_index].t.oflg.set_string = s1;
896   option_list[option_index].t.oflg.not_set_string = s2;
897   option_list[option_index].t.oflg.default_value = default_value;
898   option_list[option_index].t.oflg.true_value = true_value;
899   option_list[option_index].t.oflg.false_value = false_value;
900   option_list[option_index].t.oflg.handler = handler;
901   option_list[option_index].t.oflg.set_default = set_default;
902   option_list[option_index].t.oflg.set_help_string = set_help_string;
903   option_list[option_index].t.oflg.not_set_help_string = not_set_help_string;
904 }
905 
906 /******************************************************************************
907  * set_option - sets the option
908  */
909 
set_option(int index,char * prefix,const char * option_name,char * value)910 void set_option(int index, char *prefix, const char *option_name, char *value) {
911   boolean flag_set = ((index & OPT_FLAG) != 0);
912   struct option_type *op;
913 
914   if (flag_set)
915     op = &option_list[index-OPT_FLAG];
916   else
917     op = &option_list[index];
918 
919   if (value)
920     dm('o',3,"Trying to set option %s%s to %s\n", prefix, option_name, value);
921   else
922     dm('o',3,"Trying to set option %s%s\n", prefix, option_name);
923 
924   if (op->set)
925     {
926       dm('o',3,"Option %s%s already set\n", prefix, option_name);
927       return;
928     }
929 
930   switch (op->type)
931     {
932 
933     case NOPARM:
934       (*(op->t.onoparm.handler))(prefix, option_name);
935       break;
936 
937     case OPTIONAL:
938       (*(op->t.ooptional.handler))(prefix, option_name, value);
939       break;
940 
941     case BOOLEAN:
942       if (op->t.obool.var)
943 	{
944 	  *(op->t.obool.var) = (!flag_set);
945 	}
946       else
947 	{
948 	  (*(op->t.obool.handler))(prefix, option_name, !flag_set);
949 	}
950       break;
951 
952     case CHAR:
953       if (strlen(value) != 1)
954 	{
955 	  fprintf(stderr, gettext(CMD_NAME ": must have one character parameter for %s%s flag, but got '%s'\n"),prefix,option_name,value);
956 	  exit(1);
957 	}
958       /* TODO: Need to check that c is in valid_set */
959       if (op->t.ochar.var)
960 	{
961 	  *(op->t.ochar.var) = *value;
962 	}
963       else
964 	{
965 	  (*(op->t.ochar.handler))(prefix, option_name, *value, op->t.ochar.valid_set);
966 	}
967       break;
968 
969     case CHOICE:
970       if (strlen(prefix) == 1)
971 	{
972 	  /* This is a short option */
973 	  if (strlen(value) != 1)
974 	    {
975 	      fprintf(stderr, gettext(CMD_NAME ": must have one character parameter for %s%s flag, but got '%s'\n"),prefix,option_name,value);
976 	      exit(1);
977 	    }
978 
979 	  if ((*value != op->t.ochoice.choice1) && (*value != op->t.ochoice.choice2))
980 	    {
981 	      fprintf(stderr, gettext(CMD_NAME ": option %s%s can only take %c or %c, not %c\n"),prefix,option_name,op->t.ochoice.choice1,op->t.ochoice.choice2,*value);
982 	      exit(1);
983 	    }
984 
985 	  if (op->t.ochoice.var)
986 	    {
987 	      *(op->t.ochoice.var) = *value;
988 	    }
989 	  else
990 	    {
991 	      (*(op->t.ochoice.handler))(prefix, option_name, *value);
992 	    }
993 	}
994       else
995 	{
996 	  /* This is a long option */
997 	  char chosen_value;
998 	  if (strcmp(option_name,op->t.ochoice.choice1_string) == 0)
999 	    {
1000 	      /* First option selected */
1001 	      chosen_value = op->t.ochoice.choice1;
1002 	    }
1003 	  else
1004 	    {
1005 	      /* Second option selected */
1006 	      chosen_value = op->t.ochoice.choice2;
1007 	    }
1008 
1009 	  if (op->t.ochoice.var)
1010 	    {
1011 	      *(op->t.ochoice.var) = chosen_value;
1012 	    }
1013 	  else
1014 	    {
1015 	      (*(op->t.ochoice.handler))(prefix, option_name, chosen_value);
1016 	    }
1017 	}
1018 
1019       break;
1020 
1021     case SHORT:
1022       if (flag_set)
1023 	{
1024 	  if (op->t.oshrt.var)
1025 	    {
1026 	      *(op->t.oshrt.var) = op->t.oshrt.special_value;
1027 	    }
1028 	  else
1029 	    {
1030 	      (*(op->t.oshrt.handler))(prefix, option_name, op->t.oshrt.special_value, op->t.oshrt.min, op->t.oshrt.max);
1031 	    }
1032 	}
1033       else
1034 	{
1035 	  int intvalue = atoi(value);
1036 	  if ((intvalue > op->t.oshrt.max) || (intvalue < op->t.oshrt.min))
1037 	    {
1038 	      fprintf(stderr, gettext(CMD_NAME ": option %s%s not between %d and %d\n"),prefix,option_name,op->t.oshrt.min,op->t.oshrt.max);
1039 	      exit(1);
1040 	    }
1041 
1042 	  if (op->t.oshrt.var)
1043 	    {
1044 	      *(op->t.oshrt.var) = (short)intvalue;
1045 	    }
1046 	  else
1047 	    {
1048 	      (*(op->t.oshrt.handler))(prefix, option_name, (short)intvalue, op->t.oshrt.min, op->t.oshrt.max);
1049 	    }
1050 	}
1051       break;
1052 
1053     case INT:
1054       if (flag_set)
1055 	{
1056 	  if (op->t.oint.var)
1057 	    {
1058 	      *(op->t.oint.var) = op->t.oint.special_value;
1059 	    }
1060 	  else
1061 	    {
1062 	      (*(op->t.oint.handler))(prefix, option_name, op->t.oint.special_value, op->t.oint.min, op->t.oint.max);
1063 	    }
1064 	}
1065       else
1066 	{
1067 	  int intvalue = atoi(value);
1068 	  if ((intvalue > op->t.oint.max) || (intvalue < op->t.oint.min))
1069 	    {
1070 	      fprintf(stderr, gettext(CMD_NAME ": option %s%s not between %d and %d\n"),prefix,option_name,op->t.oint.min,op->t.oint.max);
1071 	      exit(1);
1072 	    }
1073 	  if (op->t.oint.var)
1074 	    {
1075 	      *(op->t.oint.var) = intvalue;
1076 	    }
1077 	  else
1078 	    {
1079 	      (*(op->t.oint.handler))(prefix, option_name, intvalue, op->t.oint.min, op->t.oint.max);
1080 	    }
1081 	}
1082       break;
1083 
1084     case STRING:
1085       if (op->t.ostrng.var)
1086 	{
1087 	  *(op->t.ostrng.var) = strdup(value);
1088 	}
1089       else
1090 	{
1091 	  (*(op->t.ostrng.handler))(prefix, option_name, value);
1092 	}
1093       break;
1094 
1095     case FLAG_STRING:
1096       if (op->t.oflg.var)
1097 	{
1098 	  if (flag_set)
1099 	    {
1100 	      if (op->t.oflg.true_value)
1101 		{
1102 		  *(op->t.oflg.var) = strdup(op->t.oflg.true_value);
1103 		}
1104 	      else
1105 		{
1106 		  *(op->t.oflg.var) = NULL;
1107 		}
1108 	    }
1109 	  else
1110 	    {
1111 	      if (op->t.oflg.false_value)
1112 		{
1113 		  *(op->t.oflg.var) = strdup(op->t.oflg.false_value);
1114 		}
1115 	      else
1116 		{
1117 		  *(op->t.oflg.var) = NULL;
1118 		}
1119 	    }
1120 	}
1121       else
1122 	{
1123 	  (*(op->t.oflg.handler))(prefix, option_name, !flag_set, op->t.oflg.true_value, op->t.oflg.false_value);
1124 	}
1125       break;
1126 
1127     default:
1128       abort();
1129     }
1130 
1131   op->set = TRUE;
1132 
1133   dm('o',3,"Succeeded - %s%s has not been set before\n",prefix,option_name);
1134 }
1135 
1136 /******************************************************************************
1137  * Function:
1138  *	set_option_default
1139  */
set_option_default(int index)1140 void set_option_default(int index)
1141 {
1142   option_type *op = &option_list[index];
1143 
1144   dm('o',3,"Trying to set option %d to default value\n", index);
1145 
1146   if (op->set)
1147     {
1148       dm('o',3,"Option %d already set\n", index);
1149       return;
1150     }
1151 
1152   switch (op->type)
1153     {
1154 
1155     case NOPARM:
1156       if (op->t.onoparm.default_opt)
1157 	(*(op->t.onoparm.set_default))();
1158       break;
1159 
1160     case OPTIONAL:
1161       break;
1162 
1163     case BOOLEAN:
1164       if (op->t.obool.var)
1165 	{
1166 	  *(op->t.obool.var) = op->t.obool.default_value;
1167 	}
1168       else
1169 	{
1170 	  (*(op->t.obool.set_default))(op->t.obool.default_value);
1171 	}
1172       break;
1173 
1174     case CHAR:
1175       if (op->t.ochar.var)
1176 	{
1177 	  *(op->t.ochar.var) = op->t.ochar.default_value;
1178 	}
1179       else
1180 	{
1181 	  (*(op->t.ochar.set_default))(op->t.ochar.default_value);
1182 	}
1183       break;
1184 
1185     case CHOICE:
1186       if (op->t.ochoice.var)
1187 	{
1188 	  *(op->t.ochoice.var) = op->t.ochoice.choice1;
1189 	}
1190       else
1191 	{
1192 	  (*(op->t.ochoice.set_default))(op->t.ochoice.choice1);
1193 	}
1194       break;
1195 
1196     case SHORT:
1197       if (op->t.oshrt.var)
1198 	{
1199 	  *(op->t.oshrt.var) = op->t.oshrt.default_value;
1200 	}
1201       else
1202 	{
1203 	  (*(op->t.oshrt.set_default))(op->t.oshrt.default_value);
1204 	}
1205       break;
1206 
1207     case INT:
1208       if (op->t.oint.var)
1209 	{
1210 	  *(op->t.oint.var) = op->t.oint.default_value;
1211 	}
1212       else
1213 	{
1214 	  (*(op->t.oint.set_default))(op->t.oint.default_value);
1215 	}
1216       break;
1217 
1218     case STRING:
1219       if (op->t.ostrng.var)
1220 	{
1221 	  if (op->t.ostrng.default_value)
1222 	    {
1223 	      *(op->t.ostrng.var) = strdup(op->t.ostrng.default_value);
1224 	    }
1225 	  else
1226 	    {
1227 	      *(op->t.ostrng.var) = NULL;
1228 	    }
1229 	}
1230       else
1231 	{
1232 	  if (op->t.ostrng.default_value)
1233 	    {
1234 	      (*(op->t.ostrng.set_default))(strdup(op->t.ostrng.default_value));
1235 	    }
1236 	  else
1237 	    {
1238 	      (*(op->t.ostrng.set_default))(NULL);
1239 	    }
1240 	}
1241       break;
1242 
1243     case FLAG_STRING:
1244       if (op->t.oflg.var)
1245 	{
1246 	  if (op->t.oflg.default_value)
1247 	    {
1248 	      if (op->t.oflg.true_value)
1249 		{
1250 		  *(op->t.oflg.var) = strdup(op->t.oflg.true_value);
1251 		}
1252 	      else
1253 		{
1254 		  *(op->t.oflg.var) = NULL;
1255 		}
1256 	    }
1257 	  else
1258 	    {
1259 	      if (op->t.oflg.false_value)
1260 		{
1261 		  *(op->t.oflg.var) = strdup(op->t.oflg.false_value);
1262 		}
1263 	      else
1264 		{
1265 		  *(op->t.oflg.var) = NULL;
1266 		}
1267 	    }
1268 	}
1269       else
1270 	{
1271 	  if (op->t.oflg.default_value)
1272 	    {
1273 	      if (op->t.oflg.true_value)
1274 		{
1275 		  (*(op->t.oflg.set_default))(1, strdup(op->t.oflg.true_value));
1276 		}
1277 	      else
1278 		{
1279 		  (*(op->t.oflg.set_default))(1, NULL);
1280 		}
1281 	    }
1282 	  else
1283 	    {
1284 	      if (op->t.oflg.false_value)
1285 		{
1286 		  (*(op->t.oflg.set_default))(0, strdup(op->t.oflg.false_value));
1287 		}
1288 	      else
1289 		{
1290 		  (*(op->t.oflg.set_default))(0, NULL);
1291 		}
1292 	    }
1293 	}
1294       break;
1295 
1296     default:
1297       abort();
1298     }
1299 
1300   dm('o',3,"Succeeded - option %d has not been set before\n",index);
1301 }
1302 
1303 /******************************************************************************
1304  * Function:
1305  *	print_usage_msgs
1306  */
print_usage_msgs(option_class class)1307 void print_usage_msgs(option_class class)
1308 {
1309   int option_index;
1310 
1311   switch (class){
1312   case OPT_MISC:
1313     printf(gettext("Miscellaneous options:\n"));
1314     break;
1315   case OPT_PAGE_FURNITURE:
1316     printf(gettext("Page furniture options:\n"));
1317     break;
1318   case OPT_TEXT_FORMAT:
1319     printf(gettext("Text formatting options:\n"));
1320     break;
1321   case OPT_PRINT:
1322     printf(gettext("Print selection options:\n"));
1323     break;
1324   case OPT_PAGE_FORMAT:
1325     printf(gettext("Page format options:\n"));
1326     break;
1327   case OPT_OUTPUT:
1328     printf(gettext("Output options:\n"));
1329     break;
1330   }
1331 
1332   for (option_index=0; option_index < next_option; option_index++)
1333     {
1334       option_type *op = &option_list[option_index];
1335       if (class == op->class)
1336 	{
1337 	  switch (op->type)
1338 	    {
1339 	    case NOPARM:
1340 	      if (op->letter)
1341 		printf("-%c  ",op->letter);
1342 	      if (op->t.onoparm.string)
1343 		printf("--%s",op->t.onoparm.string);
1344 	      printf("\n    %s\n",gettext(op->t.onoparm.help_string));
1345 	      break;
1346 
1347 	    case OPTIONAL:
1348 	      if (op->letter)
1349 		printf("-%c  ",op->letter);
1350 	      if (op->t.ooptional.string)
1351 		printf("--%s[=<string>]",op->t.ooptional.string);
1352 	      printf("\n    %s\n",gettext(op->t.ooptional.help_string));
1353 	      break;
1354 
1355 	    case BOOLEAN:
1356 	      if (op->letter)
1357 		printf("-%c  ",op->letter);
1358 	      if (op->t.obool.true_string)
1359 		printf("--%s",op->t.obool.true_string);
1360 	      printf("\n    %s\n",gettext(op->t.obool.true_help_string));
1361 	      if (op->letter)
1362 		printf("--%c  ",op->letter);
1363 	      if (op->t.obool.false_string)
1364 		printf("--%s",op->t.obool.false_string);
1365 	      printf("\n    %s\n",gettext(op->t.obool.false_help_string));
1366 	      break;
1367 
1368 	    case CHAR:
1369 	      if (op->letter)
1370 		printf("-%c <char>  ",op->letter);
1371 	      if (op->t.ochar.string)
1372 		printf("--%s <char>",op->t.ochar.string);
1373 	      printf("\n    %s\n",gettext(op->t.ochar.help_string));
1374 	      break;
1375 
1376 	    case CHOICE:
1377 	      if (op->letter)
1378 		printf("-%c %c  ",op->letter,op->t.ochoice.choice1);
1379 	      if (op->t.ochoice.choice1_string)
1380 		printf("--%s",op->t.ochoice.choice1_string);
1381 	      printf("\n    %s\n",gettext(op->t.ochoice.choice1_help_string));
1382 	      if (op->letter)
1383 		printf("-%c %c  ",op->letter,op->t.ochoice.choice2);
1384 	      if (op->t.ochoice.choice2_string)
1385 		printf("--%s",op->t.ochoice.choice2_string);
1386 	      printf("\n    %s\n",gettext(op->t.ochoice.choice2_help_string));
1387 	      break;
1388 
1389 	    case SHORT:
1390 	      if (op->letter)
1391 		printf("-%c <number>  ",op->letter);
1392 	      if (op->t.oshrt.string)
1393 		printf("--%s=<number>",op->t.oshrt.string);
1394 	      printf("\n    %s\n",gettext(op->t.oshrt.help_string));
1395 	      if (op->t.oshrt.special_string)
1396 		printf("--%s\n    %s\n", op->t.oshrt.special_string, gettext(op->t.oshrt.special_help_string));
1397 	      break;
1398 
1399 	    case INT:
1400 	      if (op->letter)
1401 		printf("-%c <number>  ",op->letter);
1402 	      if (op->t.oint.string)
1403 		printf("--%s=<number>",op->t.oint.string);
1404 	      printf("\n    %s\n",gettext(op->t.oint.help_string));
1405 	      if (op->t.oint.special_string)
1406 		printf("--%s\n    %s\n", op->t.oint.special_string, gettext(op->t.oint.special_help_string));
1407 	      break;
1408 
1409 	    case STRING:
1410 	      if (op->letter)
1411 		printf("-%c <string>  ",op->letter);
1412 	      if (op->t.ostrng.string)
1413 		printf("--%s=<string>",op->t.ostrng.string);
1414 	      printf("\n    %s\n",gettext(op->t.ostrng.help_string));
1415 	      break;
1416 
1417 	    case FLAG_STRING:
1418 	      if (op->letter)
1419 		printf("-%c <string>  ",op->letter);
1420 	      if (op->t.oflg.set_string)
1421 		printf("--%s=<string>",op->t.oflg.set_string);
1422 	      printf("\n    %s\n",gettext(op->t.oflg.set_help_string));
1423 	      if (op->letter)
1424 		printf("--%c  ",op->letter);
1425 	      if (op->t.oflg.set_string)
1426 		printf("--%s",op->t.oflg.not_set_string);
1427 	      printf("\n    %s\n",gettext(op->t.oflg.not_set_help_string));
1428 	    }
1429 	}
1430     }
1431 }
1432 
1433 /******************************************************************************
1434  * Function:
1435  *	set_option_defaults
1436  */
set_option_defaults(void)1437 void set_option_defaults(void)
1438 {
1439   int option_index;
1440 
1441   for (option_index=0; option_index < next_option; option_index++)
1442     {
1443       set_option_default(option_index);
1444     }
1445 }
1446