1 /*
2  * Defines for a generic argv and argc processor...
3  *
4  * Copyright 2020 by Gray Watson
5  *
6  * This file is part of the argv library.
7  *
8  * Permission to use, copy, modify, and distribute this software for
9  * any purpose and without fee is hereby granted, provided that the
10  * above copyright notice and this permission notice appear in all
11  * copies, and that the name of Gray Watson not be used in advertising
12  * or publicity pertaining to distribution of the document or software
13  * without specific, written prior permission.
14  *
15  * Gray Watson makes no representations about the suitability of the
16  * software described herein for any purpose.  It is provided "as is"
17  * without express or implied warranty.
18  *
19  * The author may be contacted via http://dmalloc.com/
20  */
21 
22 #ifndef __ARGV_H__
23 #define __ARGV_H__
24 
25 /*
26  * Version string for the library
27  *
28  * NOTE to gray: whenever this is changed, corresponding Changlog and
29  * NEWS entries *must* be entered and 2 entries in argv.texi must be
30  * updated.
31  *
32  * ARGV LIBRARY VERSION -- 2.5.0
33  */
34 
35 /* produced by configure, inserted into argv.h */
36 /* used to handle the const operator */
37 /* const is available */
38 
39 /* NOTE: start of dmalloc_argv.h */
40 
41 /*
42  * Generic and standardized argument processor.  You describe the arguments
43  * that you are looking for along with their types and these routines do the
44  * work to convert them into values.
45  *
46  * These routines also provide standardized error and usage messages as well
47  * as good usage documentation and long and short options.
48  */
49 
50 #include <stdio.h>			/* have to for FILE * below */
51 
52 /* this defines what type the standard void memory-pointer is */
53 #if (defined(__STDC__) && __STDC__ == 1) || defined(__cplusplus)
54 #define ARGV_PNT	void *
55 #else
56 #define ARGV_PNT	char *
57 #endif
58 
59 /*
60  * argument information structure.  this specifies the allowable options
61  * and some information about each one.
62  *
63  * { 'O',  "optimize",  ARGV_BOOL,  &optimize,  NULL,  "turn on optimization" }
64  * { 'c',  "config",  ARGV_CHAR_P,  &config,  "file",  "configuration file" }
65  */
66 typedef struct {
67   char		ar_short_arg;		/* short argument, 'd' if '-d' */
68   char		*ar_long_arg;		/* long version of arg, '--delete' */
69   unsigned int	ar_type;		/* type of option, see values below */
70   ARGV_PNT	ar_variable;		/* address of associated variable */
71   char		*ar_var_label;		/* label for variable description */
72   char		*ar_comment;		/* comment for usage message */
73 } argv_t;
74 
75 /*
76  * Argument array type.  when ARGV_FLAG_ARRAY is |'d with the ar_type
77  * in the above structure then multiple instances of the option are
78  * allowed and each instance is stored into the following structure
79  * that MUST be in ar_variable in the above arg_t structure.
80  *
81  * NOTE: after the arguments have been processed, if aa_entryn is > 0
82  * then aa_entries needs to be free'd by user. argv_cleanup() can be
83  * used for this
84  */
85 typedef struct {
86   int		aa_entry_n;		/* number of elements in aa_entrees */
87   ARGV_PNT	aa_entries;		/* entry list specified */
88 } argv_array_t;
89 
90 /*  extract the count of the elements from an argv ARRAY */
91 #define ARGV_ARRAY_COUNT(array)		((array).aa_entry_n)
92 
93 /* extract WHICH entry of TYPE from an argv ARRAY */
94 #define ARGV_ARRAY_ENTRY(array, type, which)	\
95 	(((type *)(array).aa_entries)[which])
96 
97 /* extract a pointer to WHICH entry of TYPE from an argv ARRAY */
98 #define ARGV_ARRAY_ENTRY_P(array, type, which)	\
99 	(((type *)(array).aa_entries) + which)
100 
101 /* special ar_short_arg value to mark the last entry in the argument array */
102 #define ARGV_LAST	((char)255)
103 
104 /*
105  * special ar_short_arg value to mark mandatory arguments (i.e. arguments that
106  * *must* be specified.  for arguments that are not optional like [-b].
107  * to have a variable number of mandatory args then make the last MAND
108  * entry be a ARG_ARRAY type.
109  */
110 #define ARGV_MAND	((char)254)
111 
112 /*
113  * special ar_short_arg value to mark that there is the possibility of
114  * a mandatory argument here if one is specified.
115  */
116 #define ARGV_MAYBE	((char)253)
117 
118 /*
119  * special ar_short_arg value to say that the previous and next arguments in
120  * the list should not be used together.
121  * {'a'...}, {ARG_OR}, {'b'...}, {ARG_OR}, {'c'...} means
122  * the user should only specific -a or -b or -c but not 2 or more.
123  */
124 #define ARGV_OR		((char)252)
125 
126 /*
127  * special ar_short_arg value that is the same as ARGV_OR but one of the args
128  * must be used.
129  * {'a'...}, {ARG_ONE_OF}, {'b'...}, {ARG_ONE_OF}, {'c'...} means
130  * the user must specify one of -a or -b or -c but not 2 or more.
131  * ARGV_XOR is there for compatibility with older versions.
132  */
133 #define ARGV_ONE_OF	((char)251)
134 #define ARGV_XOR	((char)251)
135 
136 /*
137  * ar_type values of arg_t
138  * NOTE: if this list is changed, some defines in argv_loc need to be changed
139  */
140 #define ARGV_BOOL	1		/* boolean type, sets to ARGV_TRUE */
141 #define ARGV_BOOL_NEG	2		/* like bool but sets to ARGV_FALSE */
142 #define ARGV_BOOL_ARG	3		/* like bool but takes a yes/no arg */
143 #define ARGV_CHAR	4		/* single character */
144 #define ARGV_CHAR_P	5		/* same as STRING */
145 #define ARGV_SHORT	6		/* short integer number */
146 #define ARGV_U_SHORT	7		/* unsigned short integer number */
147 #define ARGV_INT	8		/* integer number */
148 #define ARGV_U_INT	9		/* unsigned integer number */
149 #define ARGV_LONG	10		/* long integer number */
150 #define ARGV_U_LONG	11		/* unsinged long integer number */
151 #define ARGV_FLOAT	12		/* floating pointer number */
152 #define ARGV_DOUBLE	13		/* double floating pointer number */
153 #define ARGV_BIN	14		/* binary number (0s and 1s) */
154 #define ARGV_OCT	15		/* octal number, (base 8) */
155 #define ARGV_HEX	16		/* hexadecimal number, (base 16) */
156 #define ARGV_INCR	17		/* int arg which gets ++ each time */
157 #define ARGV_SIZE	18		/* long arg which knows mMbBkKgG */
158 #define ARGV_U_SIZE	19		/* u_long arg which knows mMbBkKgG */
159 #define ARGV_BOOL_INT	20		/* like bool but takes an integer var*/
160 #define ARGV_BOOL_INT_NEG 21		/* like bool-neg but with an integer */
161 #define ARGV_BOOL_INT_ARG 22		/* like bool-arg but with an integer */
162 
163 #define ARGV_TYPE(t)	((t) & 0x3F)	/* strip off all but the var type */
164 #define ARGV_FLAG_ARRAY	(1 << 14)	/* OR with type to indicate array */
165 #define ARGV_FLAG_MAND	(1 << 13)	/* OR with type to mark mandatory */
166 /* NOTE: other internal flags defined in argv_loc.h */
167 
168 /* argv_usage which argument values */
169 #define ARGV_USAGE_NONE		0	/* no usage messages -- special */
170 #define ARGV_USAGE_SHORT	1	/* print short usage messages */
171 #define ARGV_USAGE_LONG		2	/* print long-format usage messages */
172 #define ARGV_USAGE_DEFAULT	3	/* default usage messages */
173 #define ARGV_USAGE_SEE		4	/* say see --usage for more info */
174 #define ARGV_USAGE_SHORT_REM	5	/* short + reminder how to get long */
175 #define ARGV_USAGE_ALL		6	/* all usage information */
176 
177 /* boolean type settings */
178 #define ARGV_FALSE		0
179 #define ARGV_TRUE		1
180 
181 /*<<<<<<<<<<  The below prototypes are auto-generated by fillproto */
182 
183 /* This is a processed version of argv[0], pre-path removed: /bin/ls -> ls */
184 extern
185 char	argv_program[/* PROGRAM_NAME + 1 */];
186 
187 /* A global value of argv from main after argv_process has been called */
188 extern
189 char	**argv_argv;
190 
191 /* A global value of argc from main after argv_process has been called */
192 extern
193 int	argv_argc;
194 
195 /* This should be set externally to provide general program help to user */
196 extern
197 char	*argv_help_string;
198 
199 /* This should be set externally to provide version information to the user */
200 extern
201 char	*argv_version_string;
202 
203 /*
204  * Are we running interactively?  This will exit on errors.  Set to
205  * false to return error codes instead.
206  */
207 extern
208 int 	argv_interactive;
209 
210 /*
211  * The FILE stream that argv out_puts all its errors.  Set to NULL to
212  * not dump any error messages.  Default is stderr.
213  */
214 extern
215 FILE 	*argv_error_stream;
216 
217 /*
218  * This is the error code to exit with when we have a usage error and
219  * we are in interactive mode.
220  */
221 extern
222 int	argv_error_code;
223 
224 /*
225  * Set to 1 (the default) to enable the handling of -l=foo or
226  * --logfile=foo type of arguments.  Set to 0 to disable.  This allows
227  * you to specifically assign a value to an argument.
228  */
229 extern
230 int	argv_close_enable_b;
231 
232 /*
233  * If the library sees a "--" argument, it will turn off further
234  * argument process.  Set to 1 to enable the ability of specifying
235  * additional "--" arguments to reenable (basically toggle on then
236  * off) argument processing.  Set to 0 (the default) to disable this
237  * behavior.
238  */
239 extern
240 int	argv_last_toggle_b;
241 
242 /*
243  * Set to 1 (the default) to have the library accept multiple usage of
244  * the same argument.  Set to 0 to have the library generate an error
245  * if you use an argument twice.
246  */
247 extern
248 int	argv_multi_accept_b;
249 
250 /*
251  * Set to one of the ARGV_USAGE_ defines in the argv.h file.  This
252  * tell the library what usage information to display when --usage is
253  * specified by the user.  Default is ARGV_USAGE_LONG.
254  */
255 extern
256 int	argv_usage_type;
257 
258 /*
259  * Set to one of the ARGV_USAGE_ defines in the argv.h file.  This
260  * tell the library what usage information to display when an error is
261  * encountered.  The usage information accompanies the error message.
262  * Default is ARGV_USAGE_SEE.
263  */
264 extern
265 int	argv_error_type;
266 
267 /*
268  * Set to 1 (the default) if you want the library look for associated
269  * arguments from the associated program's environmental variable.  If
270  * set the 0 then no environmental variable will be used.  If you are
271  * running program foo then the library will look for the
272  * environmental variable ARGV_foo and will add those to the argument
273  * list specified on the command line.  By default they will be
274  * inserted in front of those on the command line unless the
275  * argv_env_after_b is set to 1.
276  *
277  * NOTE: this is set by argv_process automatically.  If you do not
278  * want this behavior, you should use argv_process_no_env.
279  */
280 extern
281 int	argv_process_env_b;
282 
283 /*
284  * Set to 1 if you want the library to append the arguments from the
285  * program's environmental variable after those specified on the
286  * command line.  If set the 0 (the default) then they will be
287  * inserted before those specified on the command line.  See
288  * argv_process_env_b for more information.
289  */
290 extern
291 int	argv_env_after_b;
292 
293 /*
294  * int argv_process_no_env
295  *
296  * Process the user arguments with an argv_t structure array.  Like
297  * argv_process_args but without the processing of the argv
298  * environmental variables.
299  *
300  * Returns 0 on success and -1 on failure.
301  *
302  * ARGUMENTS:
303  *
304  * args - Array of argv_t structures.
305  *
306  * arg_n - Number of arguments in the argv array.
307  *
308  * argv - Array of character pointers terminated by 0L.
309  */
310 extern
311 int	argv_process_no_env(argv_t *args, const int arg_n, char **argv);
312 
313 /*
314  * int argv_process
315  *
316  * Processes a number of arguments depending on the argument array.
317  * This routine will not modify the argv array in any way.
318  *
319  * NOTE: it will modify the args array by setting various flags in the
320  * type field.  returns 0 if no error else -1.
321  *
322  * ARGUMENTS:
323  *
324  * args - Array of argv_t structures that we are using to process the
325  * user argument array.  If null then an empty array is used.
326  *
327  * argc - Number of arguments in the argv argument array.
328  *
329  * argv - Array of character pointer arguments terminated by a 0L.
330  */
331 extern
332 int	argv_process(argv_t *args, const int argc, char **argv);
333 
334 /*
335  * int argv_usage
336  *
337  * Print the standard usage messages for our argument array.  You can
338  * specify whether you want to see a short or long usage messages.
339  *
340  * NOTE: if this is called before argv_process then the program name
341  * may be invalid.
342  *
343  * Returns 0 on success and -1 on failure.
344  *
345  * ARGUMENTS:
346  *
347  * args - Our argument array to print the usage messages about.  If
348  * null then an empty array is used.
349  *
350  * which - Either ARGV_USAGE_SHORT (for short usage messages),
351  * ARGV_USAGE_LONG (for long usage messages), or ARGV_USAGE_DEFAULT
352  * (the user's default either long or short).
353  */
354 extern
355 int	argv_usage(const argv_t *args, const int which);
356 
357 /*
358  * int argv_was_used
359  *
360  * See if an argument was used in a previous call to argv_process.
361  *
362  * Returns 1 if yes it was used, else 0 if not.
363  *
364  * ARGUMENTS:
365  *
366  * args - Argument list to search.
367  *
368  * short_arg - Short argument to see if it was used.
369  */
370 extern
371 int	argv_was_used(const argv_t *args, const char short_arg);
372 
373 /*
374  * int argv_long_was_used
375  *
376  * See if a long argument was used in a previous call to argv_process.
377  *
378  * Returns 1 if yes it was used, else 0 if not.
379  *
380  * ARGUMENTS:
381  *
382  * args - Argument list to search.
383  *
384  * long_arg - Long argument to see if it was used.
385  */
386 extern
387 int	argv_long_was_used(const argv_t *args, const char *long_arg);
388 
389 /*
390  * int argv_entry_was_used
391  *
392  * See if an entry in the argument array was used in a previous call
393  * to argv_process.
394  *
395  * Returns 1 if yes it was used, else 0 if not.
396  *
397  * ARGUMENTS:
398  *
399  * argv_entry_p - Pointer to an entry in a argv_t list.
400  */
401 extern
402 int	argv_entry_was_used(const argv_t *argv_entry_p);
403 
404 /*
405  * void argv_cleanup
406  *
407  * Frees up any allocations associated with the argument array during
408  * argv_process.  This should be done at the end of the program or
409  * after all the arguments have been referenced.
410  *
411  * ARGUMENTS:
412  *
413  * args - Argument array we are cleaning up.
414  */
415 extern
416 void	argv_cleanup(const argv_t *args);
417 
418 /*
419  * int argv_copy_args
420  *
421  * Copy all the arguements (not including the 0th) one after the other
422  * into the user specified buffer.
423  *
424  * NOTE: you can get the 0th argument from argv_argv[0] or
425  * argv_program.
426  *
427  * Returns 0 on success and -1 on failure.
428  *
429  * ARGUMENTS:
430  *
431  * buf - Buffer to copy all of the user arguments into.
432  *
433  * buf_size - Size of the buffer.
434  */
435 extern
436 int	argv_copy_args(char *buf, const int buf_size);
437 
438 /*
439  * int argv_value_string
440  *
441  * Convert the value of a RC entry to its string equivalent in the
442  * buffer provided.
443  *
444  * Returns the length of bytes copied into the buffer.
445  *
446  * ARGUMENTS:
447  *
448  * argv_entry_p - Pointer to an entry in a argv_t list.
449  *
450  * buf - Buffer to convert the value into.
451  *
452  * buf_size - Size of the buffer.
453  */
454 extern
455 int	argv_value_string(const argv_t *argv_entry_p, char *buf,
456 			  const int buf_size);
457 
458 /*
459  * int argv_type_info
460  *
461  * Get internal information about the type of the argument.
462  *
463  * Returns the name of the type.
464  *
465  * ARGUMENTS:
466  *
467  * type - Number of argument type.
468  *
469  * size_p - Pointer to an unsigned integer which, if not NULL, will be
470  * set with the size of the type.
471  *
472  * desc_p - Pointer to a constant character pointer which, if not
473  * NULL, will be pointed to a description of the type.
474  */
475 extern
476 const char	*argv_type_info(const unsigned int type, unsigned int *size_p,
477 				const char **desc_p);
478 
479 /*<<<<<<<<<<   This is end of the auto-generated output from fillproto. */
480 
481 #endif /* ! __ARGV_H__ */
482