The Lean Mean C++ Option Parser
example_arg.cc
Go to the documentation of this file.
1 /* Written 2012 by Matthias S. Benkmann
2  *
3  * The author hereby waives all copyright and related rights to the contents
4  * of this example file (example_arg.cc) to the extent possible under the law.
5  */
6 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include "optionparser.h"
18 
19 struct Arg: public option::Arg
20 {
21  static void printError(const char* msg1, const option::Option& opt, const char* msg2)
22  {
23  fprintf(stderr, "%s", msg1);
24  fwrite(opt.name, opt.namelen, 1, stderr);
25  fprintf(stderr, "%s", msg2);
26  }
27 
28  static option::ArgStatus Unknown(const option::Option& option, bool msg)
29  {
30  if (msg) printError("Unknown option '", option, "'\n");
31  return option::ARG_ILLEGAL;
32  }
33 
34  static option::ArgStatus Required(const option::Option& option, bool msg)
35  {
36  if (option.arg != 0)
37  return option::ARG_OK;
38 
39  if (msg) printError("Option '", option, "' requires an argument\n");
40  return option::ARG_ILLEGAL;
41  }
42 
43  static option::ArgStatus NonEmpty(const option::Option& option, bool msg)
44  {
45  if (option.arg != 0 && option.arg[0] != 0)
46  return option::ARG_OK;
47 
48  if (msg) printError("Option '", option, "' requires a non-empty argument\n");
49  return option::ARG_ILLEGAL;
50  }
51 
52  static option::ArgStatus Numeric(const option::Option& option, bool msg)
53  {
54  char* endptr = 0;
55  if (option.arg != 0 && strtol(option.arg, &endptr, 10)){};
56  if (endptr != option.arg && *endptr == 0)
57  return option::ARG_OK;
58 
59  if (msg) printError("Option '", option, "' requires a numeric argument\n");
60  return option::ARG_ILLEGAL;
61  }
62 };
63 
64 enum optionIndex { UNKNOWN, HELP, OPTIONAL, REQUIRED, NUMERIC, NONEMPTY };
65 const option::Descriptor usage[] = {
66 { UNKNOWN, 0,"", "", Arg::Unknown, "USAGE: example_arg [options]\n\n"
67  "Options:" },
68 { HELP, 0,"", "help", Arg::None, " \t--help \tPrint usage and exit." },
69 { OPTIONAL,0,"o","optional",Arg::Optional," -o[<arg>], \t--optional[=<arg>]"
70  " \tTakes an argument but is happy without one." },
71 { REQUIRED,0,"r","required",Arg::Required," -r <arg>, \t--required=<arg> \tMust have an argument." },
72 { NUMERIC, 0,"n","numeric", Arg::Numeric, " -n <num>, \t--numeric=<num> \tRequires a number as argument." },
73 { NONEMPTY,0,"1","nonempty",Arg::NonEmpty," -1 <arg>, \t--nonempty=<arg>"
74  " \tCan NOT take the empty string as argument." },
75 { UNKNOWN, 0,"", "", Arg::None,
76  "\nExamples:\n"
77  " example_arg --unknown -o -n10 \n"
78  " example_arg -o -n10 file1 file2 \n"
79  " example_arg -nfoo file1 file2 \n"
80  " example_arg --optional -- file1 file2 \n"
81  " example_arg --optional file1 file2 \n"
82  " example_arg --optional=file1 file2 \n"
83  " example_arg --optional= file1 file2 \n"
84  " example_arg -o file1 file2 \n"
85  " example_arg -ofile1 file2 \n"
86  " example_arg -unk file1 file2 \n"
87  " example_arg -r -- file1 \n"
88  " example_arg -r file1 \n"
89  " example_arg --required \n"
90  " example_arg --required=file1 \n"
91  " example_arg --nonempty= file1 \n"
92  " example_arg --nonempty=foo --numeric=999 --optional=bla file1 \n"
93  " example_arg -1foo \n"
94  " example_arg -1 -- \n"
95  " example_arg -1 \"\" \n"
96 },
97 { 0, 0, 0, 0, 0, 0 } };
98 
99 int main(int argc, char* argv[])
100 {
101  argc-=(argc>0); argv+=(argc>0); // skip program name argv[0] if present
102  option::Stats stats(usage, argc, argv);
103 
104 #ifdef __GNUC__
105  // GCC supports C99 VLAs for C++ with proper constructor calls.
106  option::Option options[stats.options_max], buffer[stats.buffer_max];
107 #else
108  // use calloc() to allocate 0-initialized memory. It's not the same
109  // as properly constructed elements, but good enough. Obviously in an
110  // ordinary C++ program you'd use new[], but this file demonstrates that
111  // TLMC++OP can be used without any dependency on the C++ standard library.
112  option::Option* options = (option::Option*)calloc(stats.options_max, sizeof(option::Option));
113  option::Option* buffer = (option::Option*)calloc(stats.buffer_max, sizeof(option::Option));
114 #endif
115 
116  option::Parser parse(usage, argc, argv, options, buffer);
117 
118  if (parse.error())
119  return 1;
120 
121  if (options[HELP] || argc == 0)
122  {
123  int columns = getenv("COLUMNS")? atoi(getenv("COLUMNS")) : 80;
124  option::printUsage(fwrite, stdout, usage, columns);
125  return 0;
126  }
127 
128  for (int i = 0; i < parse.optionsCount(); ++i)
129  {
130  option::Option& opt = buffer[i];
131  fprintf(stdout, "Argument #%d is ", i);
132  switch (opt.index())
133  {
134  case HELP:
135  // not possible, because handled further above and exits the program
136  case OPTIONAL:
137  if (opt.arg)
138  fprintf(stdout, "--optional with optional argument '%s'\n", opt.arg);
139  else
140  fprintf(stdout, "--optional without the optional argument\n");
141  break;
142  case REQUIRED:
143  fprintf(stdout, "--required with argument '%s'\n", opt.arg);
144  break;
145  case NUMERIC:
146  fprintf(stdout, "--numeric with argument '%s'\n", opt.arg);
147  break;
148  case NONEMPTY:
149  fprintf(stdout, "--nonempty with argument '%s'\n", opt.arg);
150  break;
151  case UNKNOWN:
152  // not possible because Arg::Unknown returns ARG_ILLEGAL
153  // which aborts the parse with an error
154  break;
155  }
156  }
157 
158  for (int i = 0; i < parse.nonOptionsCount(); ++i)
159  fprintf(stdout, "Non-option argument #%d is %s\n", i, parse.nonOption(i));
160 }
Determines the minimum lengths of the buffer and options arrays used for Parser.
Definition: optionparser.h:950
This is the only file required to use The Lean Mean C++ Option Parser. Just #include it and you&#39;re se...
static ArgStatus None(const Option &, bool)
For options that don&#39;t take an argument: Returns ARG_NONE.
Definition: optionparser.h:926
const char * name
The name of the option as used on the command line.
Definition: optionparser.h:481
A parsed option from the command line together with its argument if it has one.
Definition: optionparser.h:442
Functions for checking the validity of option arguments.
Definition: optionparser.h:923
Checks argument vectors for validity and parses them into data structures that are easier to work wit...
Describes an option, its help text (usage) and how it should be parsed.
Definition: optionparser.h:315
int index() const
Returns Descriptor::index of this Option&#39;s Descriptor, or -1 if this Option is invalid (unused)...
Definition: optionparser.h:542
The argument is acceptable for the option.
Definition: optionparser.h:256
The namespace of The Lean Mean C++ Option Parser.
Definition: optionparser.h:227
const char * arg
Pointer to this Option&#39;s argument (if any).
Definition: optionparser.h:489
static ArgStatus Optional(const Option &option, bool)
Returns ARG_OK if the argument is attached and ARG_IGNORE otherwise.
Definition: optionparser.h:932
int namelen
The length of the option name.
Definition: optionparser.h:510
The argument is not acceptable and that&#39;s fatal.
Definition: optionparser.h:260
void printUsage(OStream &prn, const Descriptor usage[], int width=80, int last_column_min_percent=50, int last_column_own_line_max_percent=75)
Outputs a nicely formatted usage string with support for multi-column formatting and line-wrapping...
ArgStatus
Possible results when checking if an argument is valid for a certain option.
Definition: optionparser.h:251