[net.sources] template.c: a starting point

ajs@hpfcla (03/22/86)

Here's a C program template I use as the starting point for most new
programs.  (Other ones are either throwaways or are stolen from other
code.)  I mentioned this in a net.unix-wizards response, and one person
asked for a copy, then suggested I post it.  What the heck, it's short,
and it does represent a fair amount of iterative refinement.

I'm not trying to sell you on my perfectionist but arcane coding style,
no flames please; just "take what you can use and let the rest go by"
(-- Ken Kesey, and I'm beginning to think THAT should be the USENET
motto).

Alan Silverstein, Hewlett-Packard Fort Collins Systems Division, Colorado
{ihnp4 | hplabs}!hpfcla!ajs, 303-226-3800 x3053, N 40 31'31" W 105 00'43"

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by ajs at hpfcla on Fri Mar 21 14:31:07 1986
#
# This archive contains:
#	template.c	
#
# Error checking via wc(1) will be performed.

echo x - template.c
cat >template.c <<'@EOF'
/*
 * Generic C-source program template.
 * See the manual entry for details.
 */

#include <stdio.h>


/*********************************************************************
 * MISCELLANEOUS GLOBAL VALUES:
 */

#define	PROC				/* null; easy to find procs */
#define	FALSE	0
#define	TRUE	1
#define	CHNULL	('\0')
#define	CPNULL	((char *) NULL)
#define	REG	register

char *usage[] = {
    "usage: %s xxx",
    "-b xxx",
    CPNULL,
};

char	*myname;			/* how program was invoked	*/

int	bflag = FALSE;			/* -b (xxx) option		*/


/************************************************************************
 * M A I N
 */

PROC main (argc, argv)
	int	argc;
	char	**argv;
{
extern	int	optind;			/* from getopt()	*/
extern	char	*optarg;		/* from getopt()	*/
REG	int	option;			/* option "letter"	*/

/*
 * BASENAME:  Full string, or past '/' if any:
 */

	char	*cpBNTemp;		/* temporary pointer */

#define	CPBASENAME(cp)	\
	(((cpBNTemp = strrchr (cp, '/')) == CPNULL) ? cp : (cpBNTemp + 1))

/*
 * PARSE ARGUMENTS:
 */

	myname = *argv;

	while ((option = getopt (argc, argv, "xxx")) != EOF)
	{
	    switch (option)
	    {
	    case 'b':	bflag = TRUE;	break;

	    default:	Usage();
	    }
	}

	argc -= optind;			/* skip options	*/
	argv += optind;

/*
 * READ FROM LIST OF FILES OR STDIN:
 */

	char	*defargv[] = { "-" };	/* argument list	*/
REG	FILE	*filep;			/* open input file	*/
	char	*filename;		/* name to use		*/

	if (argc < 1)				/* no file names */
	{
	    argc = 1;
	    argv = defargv;			/* use default */
	}

	while (argc-- > 0)
	{
	    if (strcmp (*argv, "-") == 0)	/* read stdin */
	    {
		filename = "<stdin>";
		filep	 = stdin;
	    }
	    else if ((filep = fopen ((filename = *argv), "r")) == FILENULL)
		Error ("can't open file \"%s\" to read it", filename);

	    ReadFile (filename, filep);

	    if (ferror (filep))
		Error ("read failed from file \"%s\"", filename);

	    if (filep != stdin)
		fclose (filep);			/* assume it works */

	    argv++;
	}

/*
 * FINISH UP:
 */

	exit (0);

} /* main */


/************************************************************************
 * U S A G E
 *
 * Print usage messages (char *usage[]) to stderr and exit nonzero.
 * Each message is followed by a newline.
 */

PROC Usage()
{
REG	int	which = 0;		/* current line */

	while (usage [which] != CPNULL)
	{
	    fprintf (stderr, usage [which++], myname);
	    putc ('\n', stderr);
	}

	exit (1);

} /* Usage */


/************************************************************************
 * E R R O R
 *
 * Print an error message to stderr and exit nonzero.  Message is preceded
 * by "<myname>: " using global char *myname, and followed by a newline.
 */

/* VARARGS */
PROC Error (message, arg1, arg2, arg3, arg4)
	char	*message;
	long	arg1, arg2, arg3, arg4;
{
	fprintf (stderr, "%s: ", myname);
	fprintf (stderr, message, arg1, arg2, arg3, arg4);
	putc ('\n', stderr);

	exit (1);

} /* Error */


char	*malloc();
char	*Malloc();

/************************************************************************
 * M A L L O C
 *
 * Do a malloc with error checking.
 */

PROC char * Malloc (size)
	int	size;	/* bytes to get */
{
	char	*cp;	/* pointer to memory */

	if ((cp = malloc (size)) == CPNULL)
	    Error ("malloc %d bytes failed", size);

	return (cp);

} /* Malloc */
@EOF
if test "`wc -lwc <template.c`" != '    177    518   3281'
then
	echo ERROR: wc results of template.c are `wc -lwc <template.c` should be     177    518   3281
fi

chmod 444 template.c

exit 0