You are here: Home / Past Courses / Fall 2011 - ECPE 177 / Projects / Argument Parsing with argp()

Argument Parsing with argp()

C source code icon swget.c — C source code, 3 KB (3134 bytes)

File contents

// argp() demo program for swget project
// To compile:  gcc -std=c99 -Werror -Wall -Wextra swget.c -o swget

#include <stdio.h>        // Provides for printf, etc...
#include <stdlib.h>       // Provides for exit, ...
#include <string.h>       // Provides for memset, ...
#include <argp.h>         // Provides GNU argp() argument parser


// Set up the argument parser
const char *argp_program_version = "swget 1.0";
const char *argp_program_bug_address = "<jshafer@pacific.edu>";
static char doc[] = "swget -- a simple web download utility";
static char args_doc[] = "";  // No standard arguments
                              // (i.e. arguments without "names")


// Options.  Field 1 in ARGP.
// Order of fields: {NAME, KEY, ARG, FLAGS, DOC, GROUP}.
static struct argp_option options[] = {
  {"url",        'u', "URL",      0,  "URL of object to download", 0 },
  {"destdir",    'd', "DESTDIR",  0,  "Directory to save downloaded object to", 0 },
  {"verbose",    'v', 0,          0,  "Provide verbose output, including server headers", 0 },
  { 0, 0, 0, 0, 0, 0} // Last entry should be all zeros in all fields
};

/* Used by main to communicate with parse_opt. */
struct arguments
{
  // char *args[0];   // No standard arguments (without flags)
  int verbose; 	   // For --verbose /-v
  char *url;	  // Argument for --url / -d
  char *destdir;  // Argument for --destdir / -d
};

// Parser. Field 2 in ARGP.
// Order of parameters: KEY, ARG, STATE.
// Parse a single option.
static error_t parse_opt (int key, char *arg, struct argp_state *state)
{
  /* Get the input argument from argp_parse, which we
     know is a pointer to our arguments structure. */
  struct arguments *arguments = state->input;

  // Figure out which option we are parsing, and decide
  // how to store it  
  switch (key)
    {
    case 'v':
      arguments->verbose = 1;
      break;
    case 'u':
      arguments->url = arg;
      break;
    case 'd':
      arguments->destdir = arg;
      break;
      
    case ARGP_KEY_END:
      // Reached the last key.
      // Check if our url and destdir REQUIRED "options" have been set to non-default values
      if (strcmp(arguments->url, "") ==0 || strcmp(arguments->destdir, "") == 0)
	{
	  argp_usage (state);
	}
      break;
      
    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}

// Our argp parser.
static struct argp argp = { options, parse_opt, args_doc, doc, 0, 0, 0 };

int main (int argc, char **argv)
{
	struct arguments arguments;

	// Parse our arguments; every option seen by parse_opt will be reflected in arguments.
	// Default values.
	arguments.verbose = 0;
	arguments.url = ""; // Empty string - only contains null character
	arguments.destdir = "";

	argp_parse (&argp, argc, argv, 0, 0, &arguments);

	printf ("User arguments:\n"
	        " url=%s\n"
	        " destdir=%s\n"
	        " verbose=%s\n",
	        arguments.url, // This is a pointer to the start of the URL char array
	        arguments.destdir, // This is a pointer to the start of the destir char array
	        arguments.verbose ? "yes" : "no"); // This is an integer we are testing

	return (0);
}