getopt.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdint.h>
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include <getopt.h>
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 char *optarg;
00039
00040
00041
00042
00043
00044
00045
00046 int optind;
00047
00048
00049
00050
00051
00052
00053 int nextchar;
00054
00055
00056
00057
00058
00059
00060
00061 int optopt;
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 static const char * get_argv_argument ( int argc, char * const argv[] ) {
00073 char *arg;
00074
00075
00076 if ( optind >= argc )
00077 return NULL;
00078 arg = argv[optind];
00079
00080
00081
00082
00083 if ( *arg == '-' )
00084 return NULL;
00085
00086
00087 optind++;
00088 return arg;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 static int match_long_option ( int argc, char * const argv[],
00102 const char *opttext,
00103 const struct option *longopt, int *option ) {
00104 size_t optlen;
00105 const char *argument = NULL;
00106
00107
00108 optlen = strlen ( longopt->name );
00109 if ( strncmp ( opttext, longopt->name, optlen ) != 0 )
00110 return 0;
00111
00112
00113 if ( opttext[optlen] == '=' ) {
00114 argument = &opttext[ optlen + 1 ];
00115 } else if ( opttext[optlen] ) {
00116
00117 return 0;
00118 }
00119
00120
00121 optind++;
00122
00123
00124
00125
00126 if ( ( longopt->has_arg != no_argument ) && ( ! argument ) )
00127 argument = get_argv_argument ( argc, argv );
00128
00129
00130 if ( ( longopt->has_arg == required_argument ) && ( ! argument ) ) {
00131 printf ( "Option \"%s\" requires an argument\n",
00132 longopt->name );
00133 *option = ':';
00134 return 1;
00135 }
00136
00137
00138 if ( ( longopt->has_arg == no_argument ) && argument ) {
00139 printf ( "Option \"%s\" takes no argument\n", longopt->name );
00140 *option = ':';
00141 return 1;
00142 }
00143
00144
00145 optarg = ( char * ) argument;
00146 if ( longopt->flag ) {
00147 *(longopt->flag) = longopt->val;
00148 *option = 0;
00149 } else {
00150 *option = longopt->val;
00151 }
00152 return 1;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 static int match_short_option ( int argc, char * const argv[],
00166 const char *opttext, int shortopt,
00167 enum getopt_argument_requirement has_arg,
00168 int *option ) {
00169 const char *argument = NULL;
00170
00171
00172 if ( *opttext != shortopt )
00173 return 0;
00174
00175
00176 opttext++;
00177 nextchar++;
00178 if ( *opttext ) {
00179 if ( has_arg != no_argument ) {
00180
00181 argument = opttext;
00182 optind++;
00183 nextchar = 0;
00184 }
00185 } else {
00186
00187 optind++;
00188 nextchar = 0;
00189 }
00190
00191
00192
00193
00194 if ( ( has_arg != no_argument ) && ( ! argument ) )
00195 argument = get_argv_argument ( argc, argv );
00196
00197
00198 if ( ( has_arg == required_argument ) && ( ! argument ) ) {
00199 printf ( "Option \"%c\" requires an argument\n", shortopt );
00200 *option = ':';
00201 return 1;
00202 }
00203
00204
00205 optarg = ( char * ) argument;
00206 *option = shortopt;
00207 return 1;
00208 }
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 int getopt_long ( int argc, char * const argv[], const char *optstring,
00225 const struct option *longopts, int *longindex ) {
00226 const char *opttext = argv[optind];
00227 const struct option *longopt;
00228 int shortopt;
00229 enum getopt_argument_requirement has_arg;
00230 int option;
00231
00232
00233 if ( optind >= argc )
00234 return -1;
00235
00236
00237 if ( *(opttext++) != '-' )
00238 return -1;
00239
00240
00241 if ( *(opttext++) == '-' ) {
00242 for ( longopt = longopts ; longopt->name ; longopt++ ) {
00243 if ( ! match_long_option ( argc, argv, opttext,
00244 longopt, &option ) )
00245 continue;
00246 if ( longindex )
00247 *longindex = ( longopt - longopts );
00248 return option;
00249 }
00250 optopt = '?';
00251 printf ( "Unrecognised option \"--%s\"\n", opttext );
00252 return '?';
00253 }
00254
00255
00256 if ( nextchar < 1 )
00257 nextchar = 1;
00258 opttext = ( argv[optind] + nextchar );
00259 while ( ( shortopt = *(optstring++) ) ) {
00260 has_arg = no_argument;
00261 while ( *optstring == ':' ) {
00262 has_arg++;
00263 optstring++;
00264 }
00265 if ( match_short_option ( argc, argv, opttext, shortopt,
00266 has_arg, &option ) ) {
00267 return option;
00268 }
00269 }
00270 optopt = *opttext;
00271 printf ( "Unrecognised option \"-%c\"\n", optopt );
00272 return '?';
00273 }