123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /*
- * gehopt; options processing with both single-character and whole-word
- * options both introduced with -
- */
- #include <stdio.h>
- #include <string.h>
- #include "gethopt.h"
- void
- hoptset(ctx, argc, argv)
- struct h_context *ctx;
- int argc;
- char **argv;
- {
- memset(ctx, 0, sizeof *ctx);
- ctx->argc = argc;
- ctx->argv = argv;
- ctx->optind = 1;
- }
- char *
- hoptarg(ctx)
- struct h_context *ctx;
- {
- return ctx->optarg;
- }
- int
- hoptind(ctx)
- struct h_context *ctx;
- {
- return ctx->optind;
- }
- char
- hoptopt(ctx)
- struct h_context *ctx;
- {
- return ctx->optopt;
- }
- int
- hopterr(ctx,val)
- struct h_context *ctx;
- {
- int old = ctx->opterr;
-
- ctx->opterr = !!val;
- return old;
- }
- struct h_opt *
- gethopt(ctx, opts, nropts)
- struct h_context *ctx;
- struct h_opt *opts;
- int nropts;
- {
- int i;
- int dashes;
-
- if ( (ctx == 0) || ctx->optend || (ctx->optind >= ctx->argc) )
- return 0;
-
- ctx->optarg = 0;
- ctx->optopt = 0;
-
- if ( ctx->optchar == 0) {
- /* check for leading -
- */
- if ( ctx->argv[ctx->optind][0] != '-' ) {
- /* out of arguments */
- ctx->optend = 1;
- return 0;
- }
- if ( ctx->argv[ctx->optind][1] == 0
- || strcmp(ctx->argv[ctx->optind], "--") == 0 ) {
- /* option list finishes with - or -- token
- */
- ctx->optend = 1;
- ctx->optind++;
- return 0;
- }
- dashes = 1;
- if ( ctx->argv[ctx->optind][dashes] == '-' ) {
- /* support GNU-style long option double-dash prefix
- * (if gethopt is passed an unknown option with a double-dash
- * prefix, it won't match a word and then the second dash
- * will be scanned as if it was a regular old single-character
- * option.)
- */
- dashes = 2;
- }
-
- for ( i=0; i < nropts; i++ ) {
- if ( ! opts[i].optword )
- continue;
- if (strcmp(opts[i].optword, dashes+(ctx->argv[ctx->optind]) ) == 0 ) {
- if ( opts[i].opthasarg ) {
- if ( ctx->argc > ctx->optind ) {
- ctx->optarg = ctx->argv[ctx->optind+1];
- ctx->optind += 2;
- }
- else {
- /* word argument with required arg at end of
- *command line
- */
- if ( ctx->opterr )
- fprintf(stderr,
- "%s: option requires an argument -- %s\n",
- ctx->argv[0], opts[i].optword);
- ctx->optind ++;
- return HOPTERR;
- }
- }
- else {
- ctx->optind ++;
- }
- return &opts[i];
- }
- }
- ctx->optchar = 1;
- }
- ctx->optopt = ctx->argv[ctx->optind][ctx->optchar++];
- if ( !ctx->optopt ) {
- /* fell off the end of this argument */
- ctx->optind ++;
- ctx->optchar = 0;
- return gethopt(ctx, opts, nropts);
- }
- for ( i=0; i<nropts; i++ ) {
- if ( opts[i].optchar == ctx->optopt ) {
- /* found a single-char option!
- */
- if ( opts[i].opthasarg ) {
- if ( ctx->argv[ctx->optind][ctx->optchar] ) {
- /* argument immediately follows this options (-Oc)
- */
- ctx->optarg = &ctx->argv[ctx->optind][ctx->optchar];
- ctx->optind ++;
- ctx->optchar = 0;
- }
- else if ( ctx->optind < ctx->argc-1 ) {
- /* argument is next arg (-O c)
- */
- ctx->optarg = &ctx->argv[ctx->optind+1][0];
- ctx->optind += 2;
- ctx->optchar = 0;
- }
- else {
- /* end of arg string (-O); set optarg to null, return
- * (should it opterr on me?)
- */
- ctx->optarg = 0;
- ctx->optind ++;
- ctx->optchar = 0;
- if ( ctx->opterr )
- fprintf(stderr,
- "%s: option requires an argument -- %c\n",
- ctx->argv[0], opts[i].optchar);
- return HOPTERR;
- }
- }
- else {
- if ( !ctx->argv[ctx->optind][ctx->optchar] ) {
- ctx->optind ++;
- ctx->optchar = 0;
- }
- }
- return &opts[i];
- }
- }
- if ( ctx->opterr )
- fprintf(stderr, "%s: illegal option -- %c\n", ctx->argv[0], ctx->optopt);
- return HOPTERR;
- }
- void
- hoptusage(char *pgm, struct h_opt opts[], int nropts, char *arguments)
- {
- int i;
- int optcount;
-
- fprintf(stderr, "usage: %s", pgm);
- /* print out the options that don't have flags first */
-
- for ( optcount=i=0; i < nropts; i++ ) {
- if ( opts[i].optchar && !opts[i].opthasarg) {
- if (optcount == 0 )
- fputs(" [-", stderr);
- fputc(opts[i].optchar, stderr);
- optcount++;
- }
- }
- if ( optcount )
- fputc(']', stderr);
- /* print out the options WITH flags */
- for ( i = 0; i < nropts; i++ )
- if ( opts[i].optchar && opts[i].opthasarg)
- fprintf(stderr, " [-%c %s]", opts[i].optchar, opts[i].opthasarg);
- /* print out the long options */
- for ( i = 0; i < nropts; i++ )
- if ( opts[i].optword ) {
- fprintf(stderr, " [-%s", opts[i].optword);
- if ( opts[i].opthasarg )
- fprintf(stderr, " %s", opts[i].opthasarg);
- fputc(']', stderr);
- }
- /* print out the arguments string, if any */
- if ( arguments )
- fprintf(stderr, " %s", arguments);
- /* and we're done */
- fputc('\n', stderr);
- }
- #if DEBUG
- struct h_opt opts[] = {
- { 0, "css", 0, 1, "css file" },
- { 1, "header", 0, 1, "header file" },
- { 2, 0, 'a', 0, "option a (no arg)" },
- { 3, 0, 'b', 1, "option B (with arg)" },
- { 4, "help", '?', 0, "help message" },
- } ;
- #define NROPT (sizeof opts/sizeof opts[0])
- int
- main(argc, argv)
- char **argv;
- {
- struct h_opt *ret;
- struct h_context ctx;
- int i;
- hoptset(&ctx, argc, argv);
- hopterr(&ctx, 1);
- while (( ret = gethopt(&ctx, opts, NROPT) )) {
- if ( ret != HOPTERR ) {
- if ( ret->optword )
- printf("%s", ret->optword);
- else
- printf("%c", ret->optchar);
- if ( ret->opthasarg ) {
- if ( hoptarg(&ctx) )
- printf(" with argument \"%s\"", hoptarg(&ctx));
- else
- printf(" with no argument?");
- }
- printf(" (%s)\n", ret->optdesc);
- }
- }
- argc -= hoptind(&ctx);
- argv += hoptind(&ctx);
- for ( i=0; i < argc; i++ )
- printf("%d: %s\n", i, argv[i]);
- return 0;
- }
- #endif /*DEBUG*/
|