Data Pile

Against Digital Amnesia

Programming With the APR - Using Apr_getopt

This article will show you how to use the built in command line parser that comes with the APR. There will be two source files, one showing you how to use apr_getopt just to parse simple, single options and the other peace of source will show you how to use it with so called long options. You can download the single option parser here and the long options parser here.

NOTE: The program supplied should actually use apr_app_initialize(&argc, &argv, NULL); since apr_initialize() is intended for library use only.

Prerequisites

Like everytime, you need to have APR libraries installed in order to be able to use them. You’ll additionally need the header files too, so if you’re installing from some distribution specific mechanism, be sure to have the “-dev” packages installed as well.

Explanation

There is really not that much to explain this time. We first initialize APR, create a pool, then initialize the getopt parser and then we’re walking through the options specified on the command line. The most notable part here is the line: cmdLineArgs->interleave = 1;. Setting the interleave to one allows us to have options and final arguments specified “wildly” on the command line. That means that the order of argument is not relevant. You can specify ./aprGetoptLong --choose what -h lalalal or you can type: ./aprGetoptLong --choose what lalala -h which, in this case would lead to the same result.

Simple options code

APR With Simple Short Options Code (aprGetopt.c) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <apr.h>
#include <apr_file_io.h>
#include <apr_getopt.h>

/* Compile with 
 * $> export APR_LIBS="`apr-1-config --cflags --cppflags --includes --ldflags --link-ld --libs`"
 * $> export APU_LIBS="`apu-1-config --includes --ldflags --link-ld --libs`"
 * $> gcc aprGetopt.c -o aprGetopt $APR_LIBS $APU_LIBS
 */
int main(int argc, const char * const *argv)
{
  apr_pool_t *p = NULL;
  apr_getopt_t *cmdLineArgs = NULL;
  apr_status_t rv;
  char optChar;
  const char *optArg = NULL;

  /* Will hold the position for the non optional 
   * args in the APR parsed argv  
   */
  int processedOptions = 0;

  /* cleanly handle fileIO this time */
  apr_file_t *out = NULL;
  apr_file_t *err = NULL;

  /* init APR, create memory pool */
  apr_initialize();
  atexit(apr_terminate);
  apr_pool_create(&p, NULL);

  /* Open stdin, stderr */
  apr_file_open_stdout(&out, p);
  apr_file_open_stderr(&err, p);

  /* init APRs getopt */
  apr_getopt_init(&cmdLineArgs, p, argc, argv);

  /* If not using the getopt_long version, this
   * this is ignored
   */
  //cmdLineArgs->interleave = 1;

  /* Now step through the options given */
  while ((rv = apr_getopt(cmdLineArgs, "hc:", &optChar, &optArg)) == APR_SUCCESS) {
    switch(optChar) {
    case 'h':
      apr_file_printf(out, "Read option h ...\n");
      break;
    case 'c':
      apr_file_printf(out, "Read option c with argument %s\n", optArg);
      break;
    default:
      apr_file_printf(out, "Default reached ...\n");
    }
  }

  if (APR_STATUS_IS_BADCH(rv)) {
    apr_file_printf(err, "Read bad option ...\n");
  }

  processedOptions = cmdLineArgs->ind;
  /* Now spit out non options */
  while (processedOptions < argc) {
    apr_file_printf(out, "Non opt arg: %s\n", cmdLineArgs->argv[processedOptions++]);
  }


  apr_pool_destroy(p);
  return 0;
}

Now that you have seen how it works with simple options, long options is no more magic. You just have to additionally initialize an array basically, but see for yourself.

Long options code

APR With Simple Long Options Code (aprGetoptLong.c) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <apr.h>
#include <apr_file_io.h>
#include <apr_getopt.h>


/* Compile with 
 * $> export APR_LIBS="`apr-1-config --cflags --cppflags --includes --ldflags --link-ld --libs`"
 * $> export APU_LIBS="`apu-1-config --includes --ldflags --link-ld --libs`"
 * $> gcc aprGetoptLong.c -o aprGetoptLong $APR_LIBS $APU_LIBS
 */
int main(int argc, const char * const *argv)
{
  apr_pool_t *p = NULL;
  apr_getopt_t *cmdLineArgs = NULL;
  apr_status_t rv;
  int optChar = 0;
  const char *optArg = NULL;

  /* Will hold the position for the non optional 
   * args in the APR parsed argv  
   */
  int processedOptions = 0;

  /* cleanly handle fileIO this time */
  apr_file_t *out = NULL;
  apr_file_t *err = NULL;

  /* Let's handle long opts too */
  const apr_getopt_option_t longOpts[] = {{"help", 'h', 0, "Show help"}, {"choose", 'c', 1, "Choose something"}};

  /* init APR, create memory pool */
  apr_initialize();
  atexit(apr_terminate);
  apr_pool_create(&p, NULL);

  /* Open stdin, stderr */
  apr_file_open_stdout(&out, p);
  apr_file_open_stderr(&err, p);

  /* init APRs getopt */
  apr_getopt_init(&cmdLineArgs, p, argc, argv);

  /* Allow options to be added after arguments */
  cmdLineArgs->interleave = 1;

  /* Now step through the options given */
  while ((rv = apr_getopt_long(cmdLineArgs, longOpts, &optChar, &optArg)) == APR_SUCCESS) {
    switch(optChar) {
    case 'h':
      apr_file_printf(out, "Read option h ...\n");
      break;
    case 'c':
      apr_file_printf(out, "Read option c with argument %s \n", optArg);
      break;
    default:
      apr_file_printf(out, "Default reached ...\n");
    }
  }

  if (APR_STATUS_IS_BADCH(rv)) {
    apr_file_printf(err, "Read bad option ...\n");
  }

  processedOptions = cmdLineArgs->ind;
  /* Now spit out non options */
  while (processedOptions < argc) {
    apr_file_printf(out, "Non opt arg: %s\n", cmdLineArgs->argv[processedOptions++]);
  }


  apr_pool_destroy(p);
  return 0;
}

Hope you enjoyed it.