[net.sources] stdmain.c: a standard main program with argument scanning

ken@turtlevax.UUCP (Ken Turkowski) (08/20/84)

echo x - README
cat >README <<'!Funky!Stuff!'
Lately I've seen several programs that use scanargs() and getopt() for
argument scanning.  Several systems do not have these subroutines in
their standard libraries, so it makes such code difficult to compile.
I am enclosing here a program I call "stdmain.c", which resides in my
home directory, and which I read in every time I generate a new
program.

It has a builtin argument scanner that looks at all arguments before
doing anything else, and accommodates several different types of flag
formats:
    1) Flags as separate arguments (-c -O -n -x);
    2) concatenated (-cOnx);
    3) attached flag parameters (-DDEBUG -b1200 -ooutput.file);
    4) and/or separate parameters (-D DEBUG -b 1200 -o output.file).
You may mix or match formats.  It checks to make sure that there is an
argument for the last flag if one is expected.  One type of format not
accommodated is that with flags longer than one character
(-baud=1200 -verbose).

Needless to say, if a flag requires an additional argument, that flag
must either be separate or the last flag in a concatenated argument
(-cOnxooutput.file -- pretty obscure, but accommodated).

Two examples are given, '-v', a Boolean flag, and '-o', a flag with a
value.  Other flags may be added by using the same format for these two.
!Funky!Stuff!
echo x - stdmain.c
cat >stdmain.c <<'!Funky!Stuff!'
# include <stdio.h>

int verbose;
int exitcode = { -1 };
char *progname;
Usage() {
	fprintf(stderr,
"Usage: %s\n", progname);
}

static char SccsId[] = "%W%\t%G%";

# define ARGVAL() (*++(*argv) || (--argc && *++argv))

/* stdmain.c -- (C) 1984 Ken Turkowski (turtlevax!ken)
 * distrubuted to USENET 8/19/84, but may not be sold for profit
 */
main(argc, argv)
int argc;
char **argv;
{
	char *ifname, *ofname;

	/* Initialization */
	progname = *argv;
	ifname = NULL; ofname = NULL;
	verbose = 0;

	/* Argument Processing */
	for (argc--, argv++; argc > 0; argc--, argv++) {
	    if (**argv == '-') {	/* A flag argument */
		while (*++(*argv)) {	/* Process all flags in this arg */
		    switch (**argv) {
			case 'v';
			    verbose = 1;
			    break;
			case 'o':	/* Output file name */
			    if (!ARGVAL())
				exeunt("Missing output file name\n");
			    ofname = *argv;
			    goto nextarg;
			default:
			    fprintf(stderr, "Unknown flag: '%c'; ", **argv);
			    Usage();
		    }
		}
	    }
	    else {		/* Input file name */
		if (ifname) {
		    fprintf(stderr, "Discarding extra input file name: %s\n",
			    *argv);
		    goto nextarg;
		}
		ifname = *argv;
		goto nextarg;
	    }
	    nextarg: continue;
	}

	/* Open input file */
	if (ifname && (freopen(ifname, "r", stdin) == NULL)) {
	    perror(ifname ? ifname : "stdin"); exit(-1);
	}

	/* Open output file */
	if (ofname && (freopen(ofname, "w", stdout) == NULL)) {
	    perror(ofname ? ofname : "stdout"); exit(-1);
	}

	exit(0);
}

/* Exeunt -- a graceful exit for abnormal conditions */
exeunt(mess, arg1, arg2, arg3, arg4)
char *mess;
int arg1, arg2, arg3, arg4;
{
	fprintf(stderr, mess, arg1, arg2, arg3, arg4);
	exit(exitcode);
}
!Funky!Stuff!
exit 0
-- 
Ken Turkowski @ CADLINC, Palo Alto, CA
UUCP: {amd,decwrl,dual,flairvax,nsc}!turtlevax!ken
ARPA: turtlevax!ken@DECWRL.ARPA