frag-opt(3)

FRAG-OPT(3) Library Functions Manual FRAG-OPT(3)

NAME

frag-opt - a portable, re-entrant argument parsing library

SYNOPSIS

#include <frag-opt.h>

FRAG *frag_init(frag_option *fops, int argc, char **argv, int flags);
int frag_parse(FRAG *frag);
const char * frag_err(FRAG *frag);
void frag_usage(FRAG *frag);
void frag_free(FRAG *frag);

typedef struct {
signed int id; /* the id-number */
char chr; /* short option */
char *str; /* long option */
int type; /* type */
char *arg; /* argument name */
char *desc; /* description */
} frag_option;

typedef struct {
int index; /* where are we going */
int chr; /* more specificly */
int id; /* the id-number of the option (or error) */
int type; /* what type the option was (enable or disable) */
/* + some other fields you don't need to know or care about */
} FRAG;

DESCRIPTION

frag-opt is a portable, re-entrant argument parsing library, designed in the spirit of getopt. frag-opt can parse the normal short (a dash followed by a character, "-o") and both GNU-style (two dashes followed by a string, "--option") and X-style (one dash followed by a string, "-option") long options as well as short negation options (a plus-sign followed by a character, "+o") and long negation options (two dashes followed by the string "no-" followed by a string, "--no-option").

This man-page is meant as a referance, the complete manual is in info-format.

USAGE

First you will have to create an array of frag_option structures (the example below shows how to do this easily). Then you have to create the FRAG-structure using the frag_init() funtion. Then you have to call frag_parse() to actually parse the arguments. frag_parse() puts the correct identification number in frag->id, so you can handle the identification with a switch-statement. frag_parse() returns the number of arguments left to parse, which means that it will return 0 when there is nothing to do anymore, which means that you can wrap the switch-statement in a nice while-loop with frag_parse() as it's condition. See the example below.

FRAG_OPTION FIELDS

id
This is the identification-number of the option. Some people like to use plain numbers here (like in the example), while some people like to use the ascii-value of a character ('h'). The only requirement is that it is a positive integer (zero is accepted, and usually used for the program itself).

chr
This is the short option. At the moment any character is acceptable. Using common sense (and/or alphanumeric characters) is recommended though, as for example '-' won't work right. Case matters.

str
This is the long option. No checking is done for the strings at the moment. Traditionally only alphanumeric characters (usually in lower case) and the dash (to substitute space) are used in long options. Case matters.

type
This is the type of the option. Zero means that it is a normal option. FRAG_ARG means it takes an argument. FRAG_OPT_ARG means it takes an optional argument. FRAG_NEG means it is negatable. If you bit-OR FRAG_HIDDEN with any of the above, the option won't show in the help message. If FRAG_ALIAS is OR'd with them, the option is printed as if it was just another alternative of the previous option (description is discarded).

arg
This is used in the help message to describe what kind of argument the option takes. If the option takes an argument and this is NULL, "VALUE" is used instead. Brackets are automatically used for optional arguments.

desc
This is used in the help message to describe what the option does. Long lines are automatically word-wrapped. Any tabs and newlines are printed, so you can do some rudimentary formatting if you think it's necessary.

FRAG_OPTION MACROS

FRAG_PROGRAM
If you want to get arguments to the program itself (filenames for example), use the FRAG_PROGRAM-macro. FRAG_PROGRAM covers the short option, long option and type fields of the structure. You can choose the identification number yourself. The arg-name-string is used in the help-message-creation like this: "usage: PROGRAM-NAME [OPTIONS] ARG-NAME", so if the arguments for the program are optional, remember to put brackets in the string. The description field will be printed on the line following the usage-text (word-wrapped of course). Both the arg-name and the description can be NULL to disable them.

FRAG_END_ARRAY
To end the array, use FRAG_END_ARRAY. FRAG_END_ARRAY covers all fields. If you do not use FRAG_END_ARRAY, frag-opt will segfault.

FRAG_INIT FLAGS

When calling frag_init(), you can give several flags OR'd together as it's last argument. If you don't know what OR'ing is see the example below and if you still don't understand, ask someone.

FRAG_DISABLE_DOUBLEDASH
Disables the behaviour where all arguments after a "--" are interpreted to be arguments for the program.

FRAG_DISABLE_GROUPS
Disables groups of short options like "-xzv".

FRAG_DISABLE_EQUALS_LONG
Disables the "--option=ARGUMENT" way of giving arguments to options.

FRAG_ENABLE_SPACED_LONG
Enables the "--option ARGUMENT" way of giving arguments to options.

FRAG_DISABLE_SPACED_SHORT
Disables the "-o ARGUMENT" way of giving arguments to options.

FRAG_ENABLE_NO_SPACE_SHORT
Enables the "-oARGUMENT" way of giving arguments to options.

FRAG_DISABLE_LONG_OPTIONS
Disables long options altogether.

FRAG_DISABLE_SHORT_OPTIONS
Disables short options altogether.

FRAG_DISABLE_NEGATION_OPTIONS
Disables negation options altogether (both long and short).

FRAG_ENABLE_ONEDASH_LONG
Enable X-style long options can be used with "-option". Consider disabling groups if using this, since the "-utc" group could be interpreted as the long option "-utc". If the options are designed so that no such overlapping is possible, then there is no danger.

FRAG_QUIET
Does not print error-messages. An alternative way of getting a description is using frag_err() which returns a simpler, constant string.

RETURN VALUE

frag_init() returns a pointer to the FRAG-structure or NULL if out of memory (or if there's something wrong with the array), frag_parse() returns the number of arguments left to parse and frag_err() returns a constant string describing the error that happened. frag_usage() and frag_free() don't return anything.

EXAMPLE

The following example implements most of frag-opt's features.


#include <stdio.h>
#include <stdlib.h>
#include <frag-opt.h>


int main(int argc, char **argv)
{
int recursion = 0;
int depth = 0;
char *end;
FRAG *frag;
frag_option fops[] = {
{ 0, FRAG_PROGRAM, "[FILES]", "an example program" },
{ 1, 'h', "help", 0 NULL, "print this message" },
{ 1, 'u', "usage", FRAG_ALIAS, NULL, NULL },
{ 2, 'v', "version", 0, NULL, "print version info" },
{ 3, 'r', "recursive", FRAG_NEG, NULL, "search recursively" },
{ 4, 'd', "depth", FRAG_ARG, "DEPTH", "depth of recursion" },
{ FRAG_END_ARRAY }
};


frag = frag_init(fops, argc, argv, FRAG_ENABLE_SPACED_LONG
| FRAG_ENABLE_NO_SPACE_SHORT);
if (frag == NULL) {
printf("out of memory\n");
exit(EXIT_FAILURE);
}


while (frag_parse(frag)) {
switch (frag->id) {
case 0:
printf("arg: %s\n", frag->arg);
break;
case 1:
frag_usage(frag);
frag_free(frag);
exit(EXIT_SUCCESS);
case 2:
printf("example version 1.0.0\n");
frag_free(frag);
exit(EXIT_SUCCESS);
case 3:
recursion = frag->type;
break;
case 4:
depth = atoi(frag->arg);
if (depth < 0) {
printf("depth must be a positive integer\n");
frag_free(frag);
exit(EXIT_FAILURE);
} else if (depth == 0)
recursion = 0;
else
recursion = 1;
break;
default: /* an error occured */
frag_usage(frag);
frag_free(frag);
exit(EXIT_FAILURE);
}
}
frag_free(frag);


printf("recursion is %d, depth is %d\n", recursion, depth);


return 0;
}

Then, link it with frag-opt (-lfrag-opt with normal compilers) and you're done. Of course a real program would check that the argument actually is a number and use a function like strtol(3) to convert it to a number.

AUTHOR

Written by Ville Jokela.

URL

http://koti.mbnet.fi/midiania/hack/index.html#frag-opt

SEE ALSO

getopt(3), popt(3)

The full documentation for frag-opt is maintained as a Texinfo manual. If the info(1) program and the frag-opt library are properly installed at your site, the command

info frag-opt

should give you access to the complete manual.

2005-04-08