| 1 |
|
|---|
| 2 | GETARG(3) BSD Library Functions Manual GETARG(3)
|
|---|
| 3 |
|
|---|
| 4 | NNAAMMEE
|
|---|
| 5 | ggeettaarrgg, aarrgg__pprriinnttuussaaggee -- collect command line options
|
|---|
| 6 |
|
|---|
| 7 | SSYYNNOOPPSSIISS
|
|---|
| 8 | ##iinncclluuddee <<ggeettaarrgg..hh>>
|
|---|
| 9 |
|
|---|
| 10 | _i_n_t
|
|---|
| 11 | ggeettaarrgg(_s_t_r_u_c_t _g_e_t_a_r_g_s _*_a_r_g_s, _s_i_z_e___t _n_u_m___a_r_g_s, _i_n_t _a_r_g_c, _c_h_a_r _*_*_a_r_g_v,
|
|---|
| 12 | _i_n_t _*_o_p_t_i_n_d);
|
|---|
| 13 |
|
|---|
| 14 | _v_o_i_d
|
|---|
| 15 | aarrgg__pprriinnttuussaaggee(_s_t_r_u_c_t _g_e_t_a_r_g_s _*_a_r_g_s, _s_i_z_e___t _n_u_m___a_r_g_s,
|
|---|
| 16 | _c_o_n_s_t _c_h_a_r _*_p_r_o_g_n_a_m_e, _c_o_n_s_t _c_h_a_r _*_e_x_t_r_a___s_t_r_i_n_g);
|
|---|
| 17 |
|
|---|
| 18 | DDEESSCCRRIIPPTTIIOONN
|
|---|
| 19 | ggeettaarrgg() collects any command line options given to a program in an eas-
|
|---|
| 20 | ily used way. aarrgg__pprriinnttuussaaggee() pretty-prints the available options, with
|
|---|
| 21 | a short help text.
|
|---|
| 22 |
|
|---|
| 23 | _a_r_g_s is the option specification to use, and it's an array of _s_t_r_u_c_t
|
|---|
| 24 | _g_e_t_a_r_g_s elements. _n_u_m___a_r_g_s is the size of _a_r_g_s (in elements). _a_r_g_c and
|
|---|
| 25 | _a_r_g_v are the argument count and argument vector to extract option from.
|
|---|
| 26 | _o_p_t_i_n_d is a pointer to an integer where the index to the last processed
|
|---|
| 27 | argument is stored, it must be initialised to the first index (minus one)
|
|---|
| 28 | to process (normally 0) before the first call.
|
|---|
| 29 |
|
|---|
| 30 | _a_r_g___p_r_i_n_t_u_s_a_g_e take the same _a_r_g_s and _n_u_m___a_r_g_s as getarg; _p_r_o_g_n_a_m_e is the
|
|---|
| 31 | name of the program (to be used in the help text), and _e_x_t_r_a___s_t_r_i_n_g is a
|
|---|
| 32 | string to print after the actual options to indicate more arguments. The
|
|---|
| 33 | usefulness of this function is realised only be people who has used pro-
|
|---|
| 34 | grams that has help strings that doesn't match what the code does.
|
|---|
| 35 |
|
|---|
| 36 | The _g_e_t_a_r_g_s struct has the following elements.
|
|---|
| 37 |
|
|---|
| 38 | struct getargs{
|
|---|
| 39 | const char *long_name;
|
|---|
| 40 | char short_name;
|
|---|
| 41 | enum { arg_integer,
|
|---|
| 42 | arg_string,
|
|---|
| 43 | arg_flag,
|
|---|
| 44 | arg_negative_flag,
|
|---|
| 45 | arg_strings,
|
|---|
| 46 | arg_double,
|
|---|
| 47 | arg_collect
|
|---|
| 48 | } type;
|
|---|
| 49 | void *value;
|
|---|
| 50 | const char *help;
|
|---|
| 51 | const char *arg_help;
|
|---|
| 52 | };
|
|---|
| 53 |
|
|---|
| 54 | _l_o_n_g___n_a_m_e is the long name of the option, it can be NULL, if you don't
|
|---|
| 55 | want a long name. _s_h_o_r_t___n_a_m_e is the characted to use as short option, it
|
|---|
| 56 | can be zero. If the option has a value the _v_a_l_u_e field gets filled in
|
|---|
| 57 | with that value interpreted as specified by the _t_y_p_e field. _h_e_l_p is a
|
|---|
| 58 | longer help string for the option as a whole, if it's NULL the help text
|
|---|
| 59 | for the option is omitted (but it's still displayed in the synopsis).
|
|---|
| 60 | _a_r_g___h_e_l_p is a description of the argument, if NULL a default value will
|
|---|
| 61 | be used, depending on the type of the option:
|
|---|
| 62 |
|
|---|
| 63 | arg_integer the argument is a signed integer, and _v_a_l_u_e should
|
|---|
| 64 | point to an _i_n_t.
|
|---|
| 65 |
|
|---|
| 66 | _a_r_g___s_t_r_i_n_g the argument is a string, and _v_a_l_u_e should point to a
|
|---|
| 67 | _c_h_a_r_*.
|
|---|
| 68 |
|
|---|
| 69 | _a_r_g___f_l_a_g the argument is a flag, and _v_a_l_u_e should point to a
|
|---|
| 70 | _i_n_t. It gets filled in with either zero or one,
|
|---|
| 71 | depending on how the option is given, the normal case
|
|---|
| 72 | being one. Note that if the option isn't given, the
|
|---|
| 73 | value isn't altered, so it should be initialised to
|
|---|
| 74 | some useful default.
|
|---|
| 75 |
|
|---|
| 76 | _a_r_g___n_e_g_a_t_i_v_e___f_l_a_g this is the same as _a_r_g___f_l_a_g but it reverses the mean-
|
|---|
| 77 | ing of the flag (a given short option clears the
|
|---|
| 78 | flag), and the synopsis of a long option is negated.
|
|---|
| 79 |
|
|---|
| 80 | _a_r_g___s_t_r_i_n_g_s the argument can be given multiple times, and the val-
|
|---|
| 81 | ues are collected in an array; _v_a_l_u_e should be a
|
|---|
| 82 | pointer to a _s_t_r_u_c_t _g_e_t_a_r_g___s_t_r_i_n_g_s structure, which
|
|---|
| 83 | holds a length and a string pointer.
|
|---|
| 84 |
|
|---|
| 85 | _a_r_g___d_o_u_b_l_e argument is a double precision floating point value,
|
|---|
| 86 | and _v_a_l_u_e should point to a _d_o_u_b_l_e.
|
|---|
| 87 |
|
|---|
| 88 | _a_r_g___c_o_l_l_e_c_t allows more fine-grained control of the option parsing
|
|---|
| 89 | process. _v_a_l_u_e should be a pointer to a
|
|---|
| 90 | _g_e_t_a_r_g___c_o_l_l_e_c_t___i_n_f_o structure:
|
|---|
| 91 |
|
|---|
| 92 | typedef int (*getarg_collect_func)(int short_opt,
|
|---|
| 93 | int argc,
|
|---|
| 94 | char **argv,
|
|---|
| 95 | int *optind,
|
|---|
| 96 | int *optarg,
|
|---|
| 97 | void *data);
|
|---|
| 98 |
|
|---|
| 99 | typedef struct getarg_collect_info {
|
|---|
| 100 | getarg_collect_func func;
|
|---|
| 101 | void *data;
|
|---|
| 102 | } getarg_collect_info;
|
|---|
| 103 |
|
|---|
| 104 | With the _f_u_n_c member set to a function to call, and
|
|---|
| 105 | _d_a_t_a to some application specific data. The parameters
|
|---|
| 106 | to the collect function are:
|
|---|
| 107 |
|
|---|
| 108 | _s_h_o_r_t___f_l_a_g non-zero if this call is via a short option
|
|---|
| 109 | flag, zero otherwise
|
|---|
| 110 |
|
|---|
| 111 | _a_r_g_c, _a_r_g_v the whole argument list
|
|---|
| 112 |
|
|---|
| 113 | _o_p_t_i_n_d pointer to the index in argv where the flag is
|
|---|
| 114 |
|
|---|
| 115 | _o_p_t_a_r_g pointer to the index in argv[*optind] where the
|
|---|
| 116 | flag name starts
|
|---|
| 117 |
|
|---|
| 118 | _d_a_t_a application specific data
|
|---|
| 119 |
|
|---|
| 120 | You can modify _*_o_p_t_i_n_d, and _*_o_p_t_a_r_g, but to do this
|
|---|
| 121 | correct you (more or less) have to know about the
|
|---|
| 122 | inner workings of getarg.
|
|---|
| 123 |
|
|---|
| 124 | You can skip parts of arguments by increasing _*_o_p_t_a_r_g
|
|---|
| 125 | (you could implement the --zz_3 set of flags from ggzziipp
|
|---|
| 126 | with this), or whole argument strings by increasing
|
|---|
| 127 | _*_o_p_t_i_n_d (let's say you want a flag --cc _x _y _z to specify
|
|---|
| 128 | a coordinate); if you also have to set _*_o_p_t_a_r_g to a
|
|---|
| 129 | sane value.
|
|---|
| 130 |
|
|---|
| 131 | The collect function should return one of
|
|---|
| 132 | ARG_ERR_NO_MATCH, ARG_ERR_BAD_ARG, ARG_ERR_NO_ARG,
|
|---|
| 133 | ENOMEM on error, zero otherwise.
|
|---|
| 134 |
|
|---|
| 135 | For your convenience there is a function,
|
|---|
| 136 | ggeettaarrgg__ooppttaarrgg(), that returns the traditional argument
|
|---|
| 137 | string, and you pass it all arguments, sans data, that
|
|---|
| 138 | where given to the collection function.
|
|---|
| 139 |
|
|---|
| 140 | Don't use this more this unless you absolutely have
|
|---|
| 141 | to.
|
|---|
| 142 |
|
|---|
| 143 | Option parsing is similar to what getopt uses. Short options without
|
|---|
| 144 | arguments can be compressed (--xxyyzz is the same as --xx --yy --zz), and short
|
|---|
| 145 | options with arguments take these as either the rest of the argv-string
|
|---|
| 146 | or as the next option (--oo_f_o_o, or --oo _f_o_o).
|
|---|
| 147 |
|
|---|
| 148 | Long option names are prefixed with -- (double dash), and the value with
|
|---|
| 149 | a = (equal), ----ffoooo==_b_a_r. Long option flags can either be specified as
|
|---|
| 150 | they are (----hheellpp), or with an (boolean parsable) option (----hheellpp==_y_e_s,
|
|---|
| 151 | ----hheellpp==_t_r_u_e, or similar), or they can also be negated (----nnoo--hheellpp is the
|
|---|
| 152 | same as ----hheellpp==no), and if you're really confused you can do it multiple
|
|---|
| 153 | times (----nnoo--nnoo--hheellpp==_f_a_l_s_e, or even ----nnoo--nnoo--hheellpp==_m_a_y_b_e).
|
|---|
| 154 |
|
|---|
| 155 | EEXXAAMMPPLLEE
|
|---|
| 156 | #include <stdio.h>
|
|---|
| 157 | #include <string.h>
|
|---|
| 158 | #include <getarg.h>
|
|---|
| 159 |
|
|---|
| 160 | char *source = "Ouagadougou";
|
|---|
| 161 | char *destination;
|
|---|
| 162 | int weight;
|
|---|
| 163 | int include_catalog = 1;
|
|---|
| 164 | int help_flag;
|
|---|
| 165 |
|
|---|
| 166 | struct getargs args[] = {
|
|---|
| 167 | { "source", 's', arg_string, &source,
|
|---|
| 168 | "source of shippment", "city" },
|
|---|
| 169 | { "destination", 'd', arg_string, &destination,
|
|---|
| 170 | "destination of shippment", "city" },
|
|---|
| 171 | { "weight", 'w', arg_integer, &weight,
|
|---|
| 172 | "weight of shippment", "tons" },
|
|---|
| 173 | { "catalog", 'c', arg_negative_flag, &include_catalog,
|
|---|
| 174 | "include product catalog" },
|
|---|
| 175 | { "help", 'h', arg_flag, &help_flag }
|
|---|
| 176 | };
|
|---|
| 177 |
|
|---|
| 178 | int num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */
|
|---|
| 179 |
|
|---|
| 180 | const char *progname = "ship++";
|
|---|
| 181 |
|
|---|
| 182 | int
|
|---|
| 183 | main(int argc, char **argv)
|
|---|
| 184 | {
|
|---|
| 185 | int optind = 0;
|
|---|
| 186 | if (getarg(args, num_args, argc, argv, &optind)) {
|
|---|
| 187 | arg_printusage(args, num_args, progname, "stuff...");
|
|---|
| 188 | exit (1);
|
|---|
| 189 | }
|
|---|
| 190 | if (help_flag) {
|
|---|
| 191 | arg_printusage(args, num_args, progname, "stuff...");
|
|---|
| 192 | exit (0);
|
|---|
| 193 | }
|
|---|
| 194 | if (destination == NULL) {
|
|---|
| 195 | fprintf(stderr, "%s: must specify destination\n", progname);
|
|---|
| 196 | exit(1);
|
|---|
| 197 | }
|
|---|
| 198 | if (strcmp(source, destination) == 0) {
|
|---|
| 199 | fprintf(stderr, "%s: destination must be different from source\n");
|
|---|
| 200 | exit(1);
|
|---|
| 201 | }
|
|---|
| 202 | /* include more stuff here ... */
|
|---|
| 203 | exit(2);
|
|---|
| 204 | }
|
|---|
| 205 |
|
|---|
| 206 | The output help output from this program looks like this:
|
|---|
| 207 |
|
|---|
| 208 | $ ship++ --help
|
|---|
| 209 | Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city]
|
|---|
| 210 | [--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...
|
|---|
| 211 | -s city, --source=city source of shippment
|
|---|
| 212 | -d city, --destination=city destination of shippment
|
|---|
| 213 | -w tons, --weight=tons weight of shippment
|
|---|
| 214 | -c, --no-catalog include product catalog
|
|---|
| 215 |
|
|---|
| 216 | BBUUGGSS
|
|---|
| 217 | It should be more flexible, so it would be possible to use other more
|
|---|
| 218 | complicated option syntaxes, such as what ps(1), and tar(1), uses, or the
|
|---|
| 219 | AFS model where you can skip the flag names as long as the options come
|
|---|
| 220 | in the correct order.
|
|---|
| 221 |
|
|---|
| 222 | Options with multiple arguments should be handled better.
|
|---|
| 223 |
|
|---|
| 224 | Should be integreated with SL.
|
|---|
| 225 |
|
|---|
| 226 | It's very confusing that the struct you pass in is called getargS.
|
|---|
| 227 |
|
|---|
| 228 | SSEEEE AALLSSOO
|
|---|
| 229 | getopt(3)
|
|---|
| 230 |
|
|---|
| 231 | ROKEN September 24, 1999 ROKEN
|
|---|