]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - hwclock/shhopt.c
1 /* $Id: shhopt.c,v 2.2 1997/07/06 23:11:55 aebr Exp $ */
2 /**************************************************************************
6 * DESCRIPTION Functions for parsing command line arguments. Values
7 * of miscellaneous types may be stored in variables,
8 * or passed to functions as specified.
10 * REQUIREMENTS Some systems lack the ANSI C -function strtoul. If your
11 * system is one of those, you'll ned to write one yourself,
12 * or get the GNU liberty-library (from prep.ai.mit.edu).
14 * WRITTEN BY Sverre H. Huseby <sverrehu@ifi.uio.no>
16 **************************************************************************/
29 /**************************************************************************
31 * P R I V A T E D A T A *
33 **************************************************************************/
35 static void optFatalFunc(const char *, ...);
36 static void (*optFatal
)(const char *format
, ...) = optFatalFunc
;
40 /**************************************************************************
42 * P R I V A T E F U N C T I O N S *
44 **************************************************************************/
46 /*-------------------------------------------------------------------------
50 * FUNCTION Show given message and abort the program.
53 * Arguments used as with printf().
55 * RETURNS Never returns. The program is aborted.
58 void optFatalFunc(const char *format
, ...)
64 vfprintf(stderr
, format
, ap
);
71 /*-------------------------------------------------------------------------
75 * FUNCTION Get number of options in a optStruct.
77 * INPUT opt array of possible options.
79 * RETURNS Number of options in the given array.
81 * DESCRIPTION Count elements in an optStruct-array. The strcture must
82 * be ended using an element of type OPT_END.
85 static int optStructCount(const optStruct opt
[])
89 while (opt
[ret
].type
!= OPT_END
)
96 /*-------------------------------------------------------------------------
100 * FUNCTION Find a matching option.
102 * INPUT opt array of possible options.
103 * s string to match, without `-' or `--'.
104 * lng match long option, otherwise short.
106 * RETURNS Index to the option if found, -1 if not found.
108 * DESCRIPTION Short options are matched from the first character in
112 static int optMatch(const optStruct opt
[], const char *s
, int lng
)
114 int nopt
, q
, matchlen
= 0;
117 nopt
= optStructCount(opt
);
119 if ((p
= strchr(s
, '=')) != NULL
)
122 matchlen
= strlen(s
);
124 for (q
= 0; q
< nopt
; q
++) {
126 if (!opt
[q
].longName
)
128 if (strncmp(s
, opt
[q
].longName
, matchlen
) == 0)
131 if (!opt
[q
].shortName
)
133 if (*s
== opt
[q
].shortName
)
142 /*-------------------------------------------------------------------------
146 * FUNCTION Return a (static) string with the option name.
148 * INPUT opt the option to stringify.
149 * lng is it a long option?
151 * RETURNS Pointer to static string.
154 static char *optString(const optStruct
*opt
, int lng
)
160 strncpy(ret
+ 2, opt
->longName
, 28);
163 ret
[1] = opt
->shortName
;
171 /*-------------------------------------------------------------------------
173 * NAME optNeedsArgument
175 * FUNCTION Check if an option requires an argument.
177 * INPUT opt the option to check.
179 * RETURNS Boolean value.
182 static int optNeedsArgument(const optStruct
*opt
)
184 return opt
->type
== OPT_STRING
185 || opt
->type
== OPT_INT
186 || opt
->type
== OPT_UINT
187 || opt
->type
== OPT_LONG
188 || opt
->type
== OPT_ULONG
;
193 /*-------------------------------------------------------------------------
197 * FUNCTION Remove an entry from an argv-array.
199 * INPUT argc pointer to number of options.
200 * argv array of option-/argument-strings.
201 * i index of option to remove.
203 * OUTPUT argc new argument count.
204 * argv array with given argument removed.
207 static void argvRemove(int *argc
, char *argv
[], int i
)
212 argv
[i
- 1] = argv
[i
];
218 /*-------------------------------------------------------------------------
222 * FUNCTION Perform the action of an option.
224 * INPUT opt array of possible options.
225 * arg argument to option, if it applies.
226 * lng was the option given as a long option?
228 * RETURNS Nothing. Aborts in case of error.
231 static void optExecute(const optStruct
*opt
, char *arg
, int lng
)
235 if (opt
->flags
& OPT_CALLFUNC
)
236 ((void (*)(void)) opt
->arg
)();
238 *((int *) opt
->arg
) = 1;
242 if (opt
->flags
& OPT_CALLFUNC
)
243 ((void (*)(char *)) opt
->arg
)(arg
);
245 *((char **) opt
->arg
) = arg
;
253 tmp
= strtol(arg
, &e
, 10);
255 optFatal(_("invalid number `%s'\n"), arg
);
257 || (opt
->type
== OPT_INT
&& (tmp
> INT_MAX
|| tmp
< INT_MIN
)))
258 optFatal(_("number `%s' to `%s' out of range\n"),
259 arg
, optString(opt
, lng
));
260 if (opt
->type
== OPT_INT
) {
261 if (opt
->flags
& OPT_CALLFUNC
)
262 ((void (*)(int)) opt
->arg
)((int) tmp
);
264 *((int *) opt
->arg
) = (int) tmp
;
265 } else /* OPT_LONG */ {
266 if (opt
->flags
& OPT_CALLFUNC
)
267 ((void (*)(long)) opt
->arg
)(tmp
);
269 *((long *) opt
->arg
) = tmp
;
279 tmp
= strtoul(arg
, &e
, 10);
281 optFatal(_("invalid number `%s'\n"), arg
);
283 || (opt
->type
== OPT_UINT
&& tmp
> UINT_MAX
))
284 optFatal(_("number `%s' to `%s' out of range\n"),
285 arg
, optString(opt
, lng
));
286 if (opt
->type
== OPT_UINT
) {
287 if (opt
->flags
& OPT_CALLFUNC
)
288 ((void (*)(unsigned)) opt
->arg
)((unsigned) tmp
);
290 *((unsigned *) opt
->arg
) = (unsigned) tmp
;
291 } else /* OPT_ULONG */ {
292 if (opt
->flags
& OPT_CALLFUNC
)
293 ((void (*)(unsigned long)) opt
->arg
)(tmp
);
295 *((unsigned long *) opt
->arg
) = tmp
;
307 /**************************************************************************
309 * P U B L I C F U N C T I O N S *
311 **************************************************************************/
313 /*-------------------------------------------------------------------------
315 * NAME optSetFatalFunc
317 * FUNCTION Set function used to display error message and exit.
319 * SYNOPSIS #include "shhmsg.h"
320 * void optSetFatalFunc(void (*f)(const char *, ...));
322 * INPUT f function accepting printf()'like parameters,
323 * that _must_ abort the program.
326 void optSetFatalFunc(void (*f
)(const char *, ...))
333 /*-------------------------------------------------------------------------
335 * NAME optParseOptions
337 * FUNCTION Parse commandline options.
339 * SYNOPSIS #include "shhopt.h"
340 * void optParseOptions(int *argc, char *argv[],
341 * const optStruct opt[], int allowNegNum);
343 * INPUT argc Pointer to number of options.
344 * argv Array of option-/argument-strings.
345 * opt Array of possible options.
347 * a negative number is not to be taken as
350 * OUTPUT argc new argument count.
351 * argv array with arguments removed.
353 * RETURNS Nothing. Aborts in case of error.
355 * DESCRIPTION This function checks each option in the argv-array
356 * against strings in the opt-array, and `executes' any
357 * matching action. Any arguments to the options are
358 * extracted and stored in the variables or passed to
359 * functions pointed to by entries in opt.
361 * Options and arguments used are removed from the argv-
362 * array, and argc is decreased accordingly.
364 * Any error leads to program abortion.
367 void optParseOptions(int *argc
, char *argv
[],
368 const optStruct opt
[], int allowNegNum
)
370 int ai
, /* argv index. */
371 optarg
, /* argv index of option argument, or -1 if none. */
372 mi
, /* Match index in opt. */
374 char *arg
, /* Pointer to argument to an option. */
375 *o
, /* pointer to an option character */
379 * Loop through all arguments.
381 for (ai
= 0; ai
< *argc
; ) {
383 * "--" indicates that the rest of the argv-array does not
386 if (strcmp(argv
[ai
], "--") == 0) {
387 argvRemove(argc
, argv
, ai
);
391 if (allowNegNum
&& argv
[ai
][0] == '-' && isdigit(argv
[ai
][1])) {
394 } else if (strncmp(argv
[ai
], "--", 2) == 0) {
396 /* find matching option */
397 if ((mi
= optMatch(opt
, argv
[ai
] + 2, 1)) < 0)
398 optFatal(_("unrecognized option `%s'\n"), argv
[ai
]);
400 /* possibly locate the argument to this option. */
402 if ((p
= strchr(argv
[ai
], '=')) != NULL
)
405 /* does this option take an argument? */
407 if (optNeedsArgument(&opt
[mi
])) {
408 /* option needs an argument. find it. */
410 if ((optarg
= ai
+ 1) == *argc
)
411 optFatal(_("option `%s' requires an argument\n"),
412 optString(&opt
[mi
], 1));
417 optFatal(_("option `%s' doesn't allow an argument\n"),
418 optString(&opt
[mi
], 1));
420 /* perform the action of this option. */
421 optExecute(&opt
[mi
], arg
, 1);
422 /* remove option and any argument from the argv-array. */
424 argvRemove(argc
, argv
, ai
);
425 argvRemove(argc
, argv
, ai
);
426 } else if (*argv
[ai
] == '-') {
427 /* A dash by itself is not considered an option. */
428 if (argv
[ai
][1] == '\0') {
432 /* Short option(s) following */
436 while (*o
&& !done
) {
437 /* find matching option */
438 if ((mi
= optMatch(opt
, o
, 0)) < 0)
439 optFatal(_("unrecognized option `-%c'\n"), *o
);
441 /* does this option take an argument? */
444 if (optNeedsArgument(&opt
[mi
])) {
445 /* option needs an argument. find it. */
448 if ((optarg
= ai
+ 1) == *argc
)
449 optFatal(_("option `%s' requires an argument\n"),
450 optString(&opt
[mi
], 0));
455 /* perform the action of this option. */
456 optExecute(&opt
[mi
], arg
, 0);
459 /* remove option and any argument from the argv-array. */
461 argvRemove(argc
, argv
, ai
);
462 argvRemove(argc
, argv
, ai
);
464 /* a non-option argument */