Using the automatic option parser in your own programs

This is how you can make your own programs handle options using a standard option parser just like all of the test programs supplied with Prosody.

Your program code

The option parser is generated from a file which lists the options required. To use it, you need some code like this in your program:

	static const char version[] = "v1.2";

	#include "gen/ansplay.args.i"

	int main(int argc, char **argv)
	{
	 		/* <- your normal declarations here */
	 ARGS_DECL
	 		/* <- possibly more normal declarations */
	 (void) argc;
	 if (ARGS_CALL || !*argv || argv[1]) {
		fprintf(stderr, "Usage: %s" ARGS_USAGE " file\n", progname);
		return 1;
	 }
			 /* use the options by referring to arg.OPTIONNAME */

So how does this work?

The #include
This is the automatically generated parser itself. See below for how to build it.
ARGS_DECL
This declares anything needed. In particular, it declares a structure called arg into which all the option values will be stored.
ARGS_CALL
This is where the actual parsing takes place. As well as interpreting any options, it moves argv to the first non-option. Since this would lose the name of the program (which was in argv[0]) it copies the program name into the variable progname. In the example, the program expects to have a file name as its only non-option argument. Therefore the "if (..." tests for a parsing error (ARGS_CALL returns a non-zero value if the options are syntactically invalid), and then tests to make sure that there is exactly one argument remaining (by checking for the null pointer which is always the last entry in argv).
ARGS_USAGE
This is a string which is built up from all the options. When printing a usage message this ensures that it correctly describes all the options. Since it is constructed automatically, no differences can creep in between the message and the options actually available.
arg.optionname
When ARGS_CALL has returned successfully, all the option values are in the arg structure. For example, if you have an option "-v 6" which is the volume option, then arg.volume will be six. The names of the fields are the long option names which are also used in the usage message, so a program with such a volume option would have "... -v volume ..." in its usage message.

The option specification

You also need the file which specifies the options. Here is an example. It's the argument specification for ansplay.

	-TiNGtrace
	a	agc		unsigned
	F	format		string
	s	speed		signed
	t	timeslot	timeslot
	v	volume		signed

The usage message is:

	Usage: ansplay [--version] [-a agc] [-F format] [-s speed] [-t timeslot] [-v volume] file

As you can see, there are five normal options, the special "-version" option, and the special "-TiNGtrace n" option (which is not listed).

Each line specifies one option. Normally, the first column shows the name of each option. The next column gives a longer name to it. This name is used in the "usage" message and as the name of the field in the arg structure. The third column says what kind of option it is. There are five kinds of options:

typemeaning
bool A boolean option. This takes no value, so it is either present or absent. The value in the arg field is zero if the option was omitted, non-zero otherwise.
unsigned An unsigned number. The value associated with this option will be returned in an unsigned long.
signed A signed number. The value associated with this option will be returned in a long.
string An arbitrary string. The value associated with this option will be returned in a char *. Note that this is the only option whose presence can be detected by the application, since the NULL string is returned if the option is omitted.
timeslot A timeslot specification. This uses the type MVIP which you must define. It must be a structure with three fields: stream, timeslot, and type. If the user invokes the command with a timeslot option whose value is 1:2:u then these fields will be set to 1, 2, and kSMTimeslotTypeMuLaw respectively. The values used in the type field are:
typeletter specifiedMeaning
kSMTimeslotTypeALawaA-law
kSMTimeslotTypeMuLawumu-law
kSMTimeslotTypeDatarraw

The first line in the example argument specification specifies the special option "-TiNGtrace". This option is treated differently from all the others because the code generated to handle it does everything required. The program does not need to know when it is used. When used, this option controls API tracing by setting the global variable TiNGtrace to the value specified with the option.

Building the parser

Run the perl script $(TiNG)/libutil/mkargs.pl passing it the name of the file in which you put the option specification. It will print out some C code which implements the option parsing. For example:

	perl ../libutil/mkargs.pl ansplay.args >gen/ansplay.args.i

You can use any name you like for the output file, but in Prosody the extension ".i" is used for C code which is #included into another file, while ".h" is used only for declarations.

That's it.