File indexing completed on 2024-04-28 11:21:08
0001 /* 0002 * gehopt; options processing with both single-character and whole-word 0003 * options both introduced with - 0004 */ 0005 0006 #include <stdio.h> 0007 #include <string.h> 0008 0009 #include "gethopt.h" 0010 0011 0012 void 0013 hoptset(ctx, argc, argv) 0014 struct h_context *ctx; 0015 int argc; 0016 char **argv; 0017 { 0018 memset(ctx, 0, sizeof *ctx); 0019 ctx->argc = argc; 0020 ctx->argv = argv; 0021 ctx->optind = 1; 0022 } 0023 0024 0025 char * 0026 hoptarg(ctx) 0027 struct h_context *ctx; 0028 { 0029 return ctx->optarg; 0030 } 0031 0032 int 0033 hoptind(ctx) 0034 struct h_context *ctx; 0035 { 0036 return ctx->optind; 0037 } 0038 0039 char 0040 hoptopt(ctx) 0041 struct h_context *ctx; 0042 { 0043 return ctx->optopt; 0044 } 0045 0046 0047 int 0048 hopterr(ctx,val) 0049 struct h_context *ctx; 0050 { 0051 int old = ctx->opterr; 0052 0053 ctx->opterr = !!val; 0054 return old; 0055 } 0056 0057 0058 struct h_opt * 0059 gethopt(ctx, opts, nropts) 0060 struct h_context *ctx; 0061 struct h_opt *opts; 0062 int nropts; 0063 { 0064 int i; 0065 int dashes; 0066 0067 0068 if ( (ctx == 0) || ctx->optend || (ctx->optind >= ctx->argc) ) 0069 return 0; 0070 0071 ctx->optarg = 0; 0072 ctx->optopt = 0; 0073 0074 if ( ctx->optchar == 0) { 0075 /* check for leading - 0076 */ 0077 if ( ctx->argv[ctx->optind][0] != '-' ) { 0078 /* out of arguments */ 0079 ctx->optend = 1; 0080 return 0; 0081 } 0082 0083 if ( ctx->argv[ctx->optind][1] == 0 0084 || strcmp(ctx->argv[ctx->optind], "--") == 0 ) { 0085 /* option list finishes with - or -- token 0086 */ 0087 ctx->optend = 1; 0088 ctx->optind++; 0089 return 0; 0090 } 0091 0092 dashes = 1; 0093 if ( ctx->argv[ctx->optind][dashes] == '-' ) { 0094 /* support GNU-style long option double-dash prefix 0095 * (if gethopt is passed an unknown option with a double-dash 0096 * prefix, it won't match a word and then the second dash 0097 * will be scanned as if it was a regular old single-character 0098 * option.) 0099 */ 0100 dashes = 2; 0101 } 0102 0103 for ( i=0; i < nropts; i++ ) { 0104 if ( ! opts[i].optword ) 0105 continue; 0106 0107 if (strcmp(opts[i].optword, dashes+(ctx->argv[ctx->optind]) ) == 0 ) { 0108 if ( opts[i].opthasarg ) { 0109 if ( ctx->argc > ctx->optind ) { 0110 ctx->optarg = ctx->argv[ctx->optind+1]; 0111 ctx->optind += 2; 0112 } 0113 else { 0114 /* word argument with required arg at end of 0115 *command line 0116 */ 0117 if ( ctx->opterr ) 0118 fprintf(stderr, 0119 "%s: option requires an argument -- %s\n", 0120 ctx->argv[0], opts[i].optword); 0121 ctx->optind ++; 0122 return HOPTERR; 0123 } 0124 } 0125 else { 0126 ctx->optind ++; 0127 } 0128 return &opts[i]; 0129 } 0130 } 0131 ctx->optchar = 1; 0132 } 0133 0134 ctx->optopt = ctx->argv[ctx->optind][ctx->optchar++]; 0135 0136 if ( !ctx->optopt ) { 0137 /* fell off the end of this argument */ 0138 ctx->optind ++; 0139 ctx->optchar = 0; 0140 return gethopt(ctx, opts, nropts); 0141 } 0142 0143 for ( i=0; i<nropts; i++ ) { 0144 if ( opts[i].optchar == ctx->optopt ) { 0145 /* found a single-char option! 0146 */ 0147 if ( opts[i].opthasarg ) { 0148 if ( ctx->argv[ctx->optind][ctx->optchar] ) { 0149 /* argument immediately follows this options (-Oc) 0150 */ 0151 ctx->optarg = &ctx->argv[ctx->optind][ctx->optchar]; 0152 ctx->optind ++; 0153 ctx->optchar = 0; 0154 } 0155 else if ( ctx->optind < ctx->argc-1 ) { 0156 /* argument is next arg (-O c) 0157 */ 0158 ctx->optarg = &ctx->argv[ctx->optind+1][0]; 0159 ctx->optind += 2; 0160 ctx->optchar = 0; 0161 } 0162 else { 0163 /* end of arg string (-O); set optarg to null, return 0164 * (should it opterr on me?) 0165 */ 0166 ctx->optarg = 0; 0167 ctx->optind ++; 0168 ctx->optchar = 0; 0169 if ( ctx->opterr ) 0170 fprintf(stderr, 0171 "%s: option requires an argument -- %c\n", 0172 ctx->argv[0], opts[i].optchar); 0173 return HOPTERR; 0174 } 0175 } 0176 else { 0177 if ( !ctx->argv[ctx->optind][ctx->optchar] ) { 0178 ctx->optind ++; 0179 ctx->optchar = 0; 0180 } 0181 } 0182 return &opts[i]; 0183 } 0184 } 0185 if ( ctx->opterr ) 0186 fprintf(stderr, "%s: illegal option -- %c\n", ctx->argv[0], ctx->optopt); 0187 return HOPTERR; 0188 } 0189 0190 0191 void 0192 hoptusage(char *pgm, struct h_opt opts[], int nropts, char *arguments) 0193 { 0194 int i; 0195 int optcount; 0196 0197 fprintf(stderr, "usage: %s", pgm); 0198 0199 /* print out the options that don't have flags first */ 0200 0201 for ( optcount=i=0; i < nropts; i++ ) { 0202 if ( opts[i].optchar && !opts[i].opthasarg) { 0203 if (optcount == 0 ) 0204 fputs(" [-", stderr); 0205 fputc(opts[i].optchar, stderr); 0206 optcount++; 0207 } 0208 } 0209 if ( optcount ) 0210 fputc(']', stderr); 0211 0212 /* print out the options WITH flags */ 0213 for ( i = 0; i < nropts; i++ ) 0214 if ( opts[i].optchar && opts[i].opthasarg) 0215 fprintf(stderr, " [-%c %s]", opts[i].optchar, opts[i].opthasarg); 0216 0217 /* print out the long options */ 0218 for ( i = 0; i < nropts; i++ ) 0219 if ( opts[i].optword ) { 0220 fprintf(stderr, " [-%s", opts[i].optword); 0221 if ( opts[i].opthasarg ) 0222 fprintf(stderr, " %s", opts[i].opthasarg); 0223 fputc(']', stderr); 0224 } 0225 0226 /* print out the arguments string, if any */ 0227 0228 if ( arguments ) 0229 fprintf(stderr, " %s", arguments); 0230 0231 /* and we're done */ 0232 fputc('\n', stderr); 0233 } 0234 0235 0236 #if DEBUG 0237 struct h_opt opts[] = { 0238 { 0, "css", 0, 1, "css file" }, 0239 { 1, "header", 0, 1, "header file" }, 0240 { 2, 0, 'a', 0, "option a (no arg)" }, 0241 { 3, 0, 'b', 1, "option B (with arg)" }, 0242 { 4, "help", '?', 0, "help message" }, 0243 } ; 0244 0245 #define NROPT (sizeof opts/sizeof opts[0]) 0246 0247 0248 int 0249 main(argc, argv) 0250 char **argv; 0251 { 0252 struct h_opt *ret; 0253 struct h_context ctx; 0254 int i; 0255 0256 0257 hoptset(&ctx, argc, argv); 0258 hopterr(&ctx, 1); 0259 0260 while (( ret = gethopt(&ctx, opts, NROPT) )) { 0261 0262 if ( ret != HOPTERR ) { 0263 if ( ret->optword ) 0264 printf("%s", ret->optword); 0265 else 0266 printf("%c", ret->optchar); 0267 0268 if ( ret->opthasarg ) { 0269 if ( hoptarg(&ctx) ) 0270 printf(" with argument \"%s\"", hoptarg(&ctx)); 0271 else 0272 printf(" with no argument?"); 0273 } 0274 printf(" (%s)\n", ret->optdesc); 0275 } 0276 } 0277 0278 argc -= hoptind(&ctx); 0279 argv += hoptind(&ctx); 0280 0281 for ( i=0; i < argc; i++ ) 0282 printf("%d: %s\n", i, argv[i]); 0283 return 0; 0284 } 0285 0286 #endif /*DEBUG*/