<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<article>
<title>Getopt tutorial</title>

<sect1>
<title>Abstract</title>
<para>
Getopt is the standard way in c and c++ to parse complex command lines on unix. This tutorial discusses how to use getopt, and provides some simple sample code for your enjoyment.
</para>
</sect1>

<sect1><title>Requirements</title>
<para>
Before you can use getopt, you'll need to include the right header. This isn't very hard. To quote the getopt man page, the required details are:
</para>

<programlisting>
#include &lt;unistd.h&gt;

       int getopt(int argc, char * const argv[],
                  const char *optstring);
</programlisting>
<para><emphasis>Code: </emphasis></para>

<para>
As we can see from this, we'll need to include the unistd.h header before things will compile.
</para>
</sect1>

<sect1><title>The options string</title>
<para>
Let's imagine that our program is going to have two command line options. The first will be the name of an input file (otherwise we might read from stdin or something else like that), and the other is an output file (or we'll use stdout). Additionally, there is an extra command line option -g, which turns gronk mode on. Valid command lines might look like (these aren't all the possible combinations):
</para>

<programlisting>
fooapp
fooapp -i infile
fooapp -i infile -o outfile
fooapp -g
</programlisting>

<para>
The way that we tell getopt about these three possible command line options is with the options string.
</para>

<sect2><title>Options with an arguement</title>
<para>
Options which have an arguement are represented in the options string by the letter is that the option, followed by a colon. For example:
</para>

<programlisting>
i:o:
</programlisting>
</sect2>

<sect2><title>Options without an arguement</title>
<para>
Options without an arguement are the same, except that they lack the colon. In our example:
</para>

<programlisting>
g
</programlisting>
</sect2>

<sect2><title>Optional arguements</title>
<para>
You can mark an optional arguement with two colons. There aren't any of these in my example, but if there was one, then it might look like:
</para>

<programlisting>
m::
</programlisting>
</sect2>

<sect2><title>The complete options string</title>
<para>
Therefore, our complete options string for this example is going to look something like:
</para>

<programlisting>
i:o:g
</programlisting>
</sect2>
</sect1>

<sect1><title>So how do you use it?</title>
<para>
Now that we have an options string, there isn't really all that much more to do.
</para>

<programlisting>
#include &lt;unistd.h&gt;
#include &lt;stdio.h&gt;

int
main (int argc, char *argv[])
{
  char *inputFile = NULL, *outputFile = NULL;
  int doGronk = 0, optchar;

  while ((optchar = getopt (argc, argv, "i:o:g")) != -1)
    {
      switch (optchar)
	{
	case 'i':
	  inputFile = (char *) strdup (optarg);
	  break;

	case 'o':
	  outputFile = (char *) strdup (optarg);
	  break;

	case 'g':
	  doGronk = 1;

	default:
	case '?':
	  printf ("Unknown command line option...\n");
	  printf ("Try: %s [-i input] [-o output] [-g]\n", argv[0]);
	  exit (0);
	  break;
	}
    }

  printf ("Command line parsed to: input = %s, output = %s, gronk = %d\n",
	  inputFile, outputFile, doGronk);
  return 1;
}
</programlisting>
<para><emphasis>Code: </emphasis></para>

<para>
You'll note here that there is an extra command line option which we got for free, the <command>?</command> command line option. This is used to display the usage message you see with many unix applications.
</para>

<sect2><title>Proving this works</title>
<para>
We should prove that this works for the sample command line arguements above.
</para>

<programlisting>
[root@localhost howto-getopt]# fooapp
Command line parsed to: input = (null), output = (null), gronk = 0

[root@localhost howto-getopt]# fooapp -i infile
Command line parsed to: input = infile, output = (null), gronk = 0

[root@localhost howto-getopt]# fooapp -i infile -o outfile
Command line parsed to: input = infile, output = outfile, gronk = 0

[root@localhost howto-getopt]# fooapp -g
Command line parsed to: input = (null), output = (null), gronk = 1

[root@localhost howto-getopt]# 
</programlisting>
</sect2>
</sect1>

<sect1><title>Long options</title>
<para>
...
</para>
</sect1>
</article>
