q&d getopt clone for mkd2html that accepts both full-word & single character

options.
This commit is contained in:
david parsons
2017-01-23 16:02:07 -08:00
parent ed64333f38
commit d08bd68128
2 changed files with 270 additions and 0 deletions
+229
View File
@@ -0,0 +1,229 @@
/*
* gehopt; options processing with both single-character and whole-work
* 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;
{
bzero(ctx, 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;
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;
}
for ( i=0; i < nropts; i++ ) {
if ( ! opts[i].optword )
continue;
if (strcmp(opts[i].optword, 1+(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;
}
#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*/
+41
View File
@@ -0,0 +1,41 @@
/*
* gethopt; options processing with both single-character and whole-work
* options both introduced with -
*/
#ifndef __GETHOPT_D
#define __GETHOPT_D
#include <stdio.h>
#include <string.h>
struct h_opt {
int option;
char *optword;
char optchar;
int opthasarg;
char *optdesc;
} ;
#define HOPTERR ((struct h_opt*)-1)
struct h_context {
char **argv;
int argc;
int optchar;
int optind;
char *optarg;
char optopt;
int opterr:1;
int optend:1;
} ;
extern char *hoptarg(struct h_context *);
extern int hoptind(struct h_context *);
extern char hoptopt(struct h_context *);
extern void hoptset(struct h_context *, int, char **);
extern int hopterr(struct h_context *, int);
extern struct h_opt *gethopt(struct h_context *, struct h_opt*, int);
#endif/*__GETHOPT_D*/