mirror of
https://github.com/Orc/discount.git
synced 2026-09-25 04:10:00 +03:00
q&d getopt clone for mkd2html that accepts both full-word & single character
options.
This commit is contained in:
@@ -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*/
|
||||
@@ -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*/
|
||||
Reference in New Issue
Block a user