Subject: standards/36550: some strong suggestions for improvements on share/misc/style
To: None <standards-manager@netbsd.org, gnats-admin@netbsd.org,>
From: Greg A. Woods <woods@planix.com>
List: netbsd-bugs
Date: 06/24/2007 19:00:01
>Number: 36550
>Category: standards
>Synopsis: some strong suggestions for improvements on share/misc/style
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: standards-manager
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sun Jun 24 19:00:00 +0000 2007
>Originator: Greg A. Woods
>Release: netbsd-current
>Organization:
Planix, Inc.; Toronto, Ontario; Canada
>Environment:
>Description:
The NetBSD "knf" style is quite good, but it falls down very
badly in a number of relatively minor places.
The enclosed changes should speak for themselves. They're based
on my own 25 years of experience doing intensive C programming,
with the majority of my time spent on modifying other people's
code.
Please consider them as very strong suggestions for improving
the readability and _reliability_ of NetBSD code.
Note also that, as it happens, many of these changes work very
well with the following settings for GNU Emacs c-mode, which,
for example, makes formatting continued lines and comment
paragraphs a one-button job. You guys using just "vi" will get
carpal tunnel syndrome trying to do the same re-formatting
manually. :-)
;; the following isn't 100% complete (e.g. it makes use of private
;; functions defined elsewhere in my ~/.emacs.el). Contact me for a
;; complete working exmaple, or fetch it from the usual place (i.e. my
;; own directory on my ftp server)
;;
(require 'cc-mode)
(setq c-font-lock-extra-types
'("FILE"
"fd_set"
"jmp_buf"
"va_list"
"\\sw+_t"
"t_\\sw+"
"u_\\sw+"
"uchar"
"uint"
"ulong"
"unchar"
"ushort"))
(defconst my-c-style
'((c-backslash-column . 78)
(c-basic-offset . 8)
(c-block-comment-prefix . "* ")
(c-cleanup-list . (brace-else-brace
brace-elseif-brace
scope-operator)) ; (scope-operator)
(c-comment-continuation-stars . "* ")
(c-comment-only-line-offset . (0 . 0))
;; ACTION can be either a function symbol or a list containing any
;; combination of the symbols `before' or `after'. If the list is empty,
;; no newlines are inserted either before or after the brace.
(c-hanging-braces-alist . ((block-open . (after))
(block-close . (before))
(brace-list-open . nil)
(brace-list-close . nil)
(brace-list-intro . nil)
(brace-list-entry . nil)
(class-open . (after))
(class-close . nil)
(defun-open . (before after))
(defun-close . (before))
(inline-open . nil)
(inline-close . nil)
(statement-case-open . nil)
(substatement-open . nil)))
(c-hanging-colons-alist . ((member-init-intro before)
(inher-intro)
(case-label after)
(label after)
(access-label after)))
(c-label-minimum-indentation . 0)
;; an OFFSET is nil; an inteter (usually zero); one of the symbols: `+',
;; `-', `++', `--', `*', or `/' (a positive or negative multiple of
;; `c-basic-offset' is added; 1, -1, 2, -2, 0.5, and -0.5, respectively); a
;; vector; a function; or a list.
(c-offsets-alist . ((arglist-close . c-lineup-close-paren) ; +
(arglist-cont-nonempty . c-lineup-arglist) ; +
(arglist-intro . c-lineup-arglist-intro-after-paren) ; +
(block-open . -) ; 0
(func-decl-cont . 0) ; +
(inline-open . 0) ; +
(statement-case-open . *) ; 0
(statement-cont . c-lineup-math) ; +
(substatement-open . 0)))) ; +
"My PERSONAL C Style, similar to NetBSD KNF.")
(c-add-style "PERSONAL" my-c-style nil)
(defun my-c-mode-common-hook ()
"My setup hook to be called by all CC Mode modes for common initializations."
;; other customizations
(setq tab-width 8) ; normal, standard, default TAB chars
(setq fill-column 79)
(setq comment-column 40)
(eval-when-compile
(if (< init-emacs-type 21)
(defvar comment-style)))
(setq comment-style 'extra-line) ; not used, but maybe someday?
(setq indent-tabs-mode t) ; only use tabs
(if (elisp-file-in-loadpath-p "filladapt")
(progn
(require 'filladapt)
(c-setup-filladapt)
;; we supposedly can't autoload this thing, yet that means this
;; function will not be defined at compile time...
(eval-when-compile
(if (elisp-file-in-loadpath-p "filladapt")
(require 'filladapt)))
(turn-on-filladapt-mode)))
;; CC Mode things that are not style variables...
(setq c-echo-syntactic-information-p nil)
(setq c-electric-pound-behavior '(alignleft)) ; nil
(setq c-recognize-knr-p t) ; yes, PLEASE!
(setq c-tab-always-indent nil) ; insert tabs if not in left margin
(c-toggle-auto-state 1) ; try this on for size!
;; keybindings for all of the supported languages. We can put these in
;; c-mode-base-map because awk-mode-map, c-mode-map, c++-mode-map,
;; objc-mode-map, java-mode-map, idl-mode-map, pike-mode-map, and so on
;; inherit from it.
(define-key c-mode-base-map "\C-m" 'c-context-line-break)
(define-key c-mode-base-map "\ej" 'c-fill-paragraph)
;; even cc-mode is sometimes too over-bearing. It seems to
;; insist re-setting some key bindings without regard to the
;; global key map.
(override-local-key-settings)
(override-default-variable-settings))
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)
;; Derived modes don't have their major-mode (or mode-name) set until after the
;; parent mode has been initialized. For example this causes c-default-style
;; to be useless with any modes derived from c-mode. This silly function
;; attempts to work around that bug and can be used in the initialization hook
;; for any such mode derived from c-mode (such as awk-mode).
;;
(defun my-derived-c-mode-hook ()
"Silly setup hook to be called by modes derived from c-mode."
(let ((style (if (stringp c-default-style)
c-default-style
(or (cdr (assq major-mode c-default-style))
(cdr (assq 'other c-default-style))
"gnu"))))
(c-set-style style 't)))
>How-To-Repeat:
>Fix:
Note that some of these changes are merely re-folding of
paragraphs....
Index: share/misc/style
===================================================================
RCS file: /cvs/master/m-NetBSD/main/src/share/misc/style,v
retrieving revision 1.38
diff -u -r1.38 style
--- share/misc/style 2 Nov 2006 22:44:41 -0000 1.38
+++ share/misc/style 24 Jun 2007 18:26:28 -0000
@@ -1,8 +1,10 @@
+/* -*-c-*- */
/* $NetBSD: style,v 1.38 2006/11/02 22:44:41 christos Exp $ */
/*
- * The revision control tag appears first, with a blank line after it.
- * Copyright text appears after the revision control tag.
+ * The revision control tag appears first, possibly preceded by an emacs mode
+ * identifier (which must be on the very first line), with a blank line after
+ * it. Copyright text appears after the revision control tag.
*/
/*
@@ -38,26 +40,48 @@
/* Most single-line comments look like this. */
/*
- * Multi-line comments look like this. Make them real sentences. Fill
- * them so they look like real paragraphs.
+ * Multi-line comments look like this. Make them real sentences. Fold them at
+ * 80 characters so they look like real paragraphs.
+ *
+ * Put blank lines between paragraphs.
*/
/*
- * Attempt to wrap lines longer than 80 characters appropriately.
- * Refer to the examples below for more information.
+ * Attempt to fold all lines longer than 80 characters appropriately.
+ *
+ * The only place this is critically important though is in the paragraphs of
+ * text in a comment. Don't fold lines where doing so would make readability
+ * worse than requiring the reader to scroll horizontally should they be so
+ * unfortunate to be using a narrow terminal or window.
+ *
+ * Refer to the examples below.
*/
/*
* EXAMPLE HEADER FILE:
*
* A header file should protect itself against multiple inclusion.
+ *
* E.g, <sys/socket.h> would contain something like:
+ *
+ * In most case one should indent the preprocessor identifiers after the `#' by
+ * one space for every level of nesting.
*/
#ifndef _SYS_SOCKET_H_
-#define _SYS_SOCKET_H_
+# define _SYS_SOCKET_H_
+
/*
* Contents of #include file go between the #ifndef and the #endif at the end.
+ *
+ * Preprocessor identifiers should not be indented an extra level for the
+ * multiple-inclusion protection wrapper.
*/
+#define NULL 0
+#if defined(_XOPEN_SOURCE) || defined(_NETBSD_SOURCE)
+# define P_tmpdir "/var/tmp/"
+#endif
+/* a blank line before the end of the multiple-inclusion wrapper */
+
#endif /* !_SYS_SOCKET_H_ */
/*
* END OF EXAMPLE HEADER FILE.
@@ -70,6 +94,7 @@
/*
* If it's a network program, put the network include files next.
+ *
* Group the includes files by subdirectory.
*/
#include <net/if.h>
@@ -79,8 +104,9 @@
#include <protocols/rwhod.h>
/*
- * Then there's a blank line, followed by the /usr include files.
- * The /usr include files should be sorted!
+ * Then there's a blank line, followed by the /usr/include files.
+ *
+ * The /usr/include files can and should be sorted!
*/
#include <assert.h>
#include <errno.h>
@@ -99,12 +125,16 @@
/*
* ANSI function declarations for private functions (i.e. functions not used
- * elsewhere) and the main() function go at the top of the source module.
+ * elsewhere) and the main() function go at the top of the source module.
+ *
* Don't associate a name with the types. I.e. use:
+ *
* void function(int);
+ *
* Use your discretion on indenting between the return type and the name, and
* how to wrap a prototype too long for a single line. In the latter case,
* lining up under the initial left parenthesis may be more readable.
+ *
* In any case, consistency is important!
*/
static char *function(int, int, float, int);
@@ -115,14 +145,20 @@
/*
* Macros are capitalized, parenthesized, and should avoid side-effects.
- * Spacing before and after the macro name may be any whitespace, though
- * use of TABs should be consistent through a file.
- * If they are an inline expansion of a function, the function is defined
- * all in lowercase, the macro has the same name all in uppercase.
+ *
+ * Spacing before and after the macro name may be any whitespace, though use of
+ * TABs should be consistent through a file.
+ *
+ * If they are an inline expansion of a function, the function is defined all
+ * in lowercase, the macro has the same name all in uppercase.
+ *
* If the macro is an expression, wrap the expression in parenthesis.
+ *
* If the macro is more than a single statement, use ``do { ... } while (0)'',
- * so that a trailing semicolon works. Right-justify the backslashes; it
- * makes it easier to read. The CONSTCOND comment is to satisfy lint(1).
+ * so that a trailing semicolon works. Right-justify the backslashes; it makes
+ * it easier to see.
+ *
+ * The CONSTCOND comment is to inform lint(1) of the constant test condition.
*/
#define MACRO(v, w, x, y) \
do { \
@@ -139,21 +175,34 @@
} et;
/*
- * When declaring variables in structures, declare them organized by use in
- * a manner to attempt to minimize memory wastage because of compiler alignment
- * issues, then by size, and then by alphabetical order. E.g, don't use
- * ``int a; char *b; int c; char *d''; use ``int a; int b; char *c; char *d''.
+ * When declaring variables in structures, declare them organized by use in a
+ * manner to attempt to minimize memory wastage because of compiler alignment
+ * issues, then by size, and then by alphabetical order. E.g, don't use:
+ *
+ * int a;
+ * char *b;
+ * int c;
+ * char *d;
+ *
+ * use:
+ *
+ * int a;
+ * int b;
+ * char *c;
+ * char *d;
+ *
* Each variable gets its own type and line, although an exception can be made
* when declaring bitfields (to clarify that it's part of the one bitfield).
+ *
* Note that the use of bitfields in general is discouraged.
*
- * Major structures should be declared at the top of the file in which they
- * are used, or in separate header files, if they are used in multiple
- * source files. Use of the structures should be by separate declarations
- * and should be "extern" if they are declared in a header file.
+ * Major structures should be declared at the top of the file in which they are
+ * used, or in separate header files, if they are used in multiple source
+ * files. Use of the structures should be by separate declarations and should
+ * be "extern" if they are declared in a header file.
*
- * It may be useful to use a meaningful prefix for each member name.
- * E.g, for ``struct softc'' the prefix could be ``sc_''.
+ * It may be useful to use a meaningful prefix for each member name. E.g, for
+ * ``struct softc'' the prefix could be ``sc_''.
*/
struct foo {
struct foo *next; /* List of active foo */
@@ -175,9 +224,8 @@
uint32_t zero;
/*
- * All major routines should have a comment briefly describing what
- * they do. The comment before the "main" routine should describe
- * what the program does.
+ * All major routines should have a comment briefly describing what they do.
+ * The comment before the "main" routine should describe what the program does.
*/
int
main(int argc, char *argv[])
@@ -187,22 +235,21 @@
char *ep;
/*
- * At the start of main(), call setprogname() to set the program
- * name. This does nothing on NetBSD, but increases portability
- * to other systems.
+ * At the start of main(), call setprogname() to set the program name.
+ * This does nothing on NetBSD, but increases portability to other
+ * systems.
*/
setprogname(argv[0]);
/*
- * For consistency, getopt should be used to parse options.
- * Options should be sorted in the getopt call and the switch
- * statement, unless parts of the switch cascade. For the
- * sorting order, see the usage() example below. Don't forget
- * to add option descriptions to the usage and the manpage.
- * Elements in a switch statement that cascade should have a
- * FALLTHROUGH comment. Numerical arguments should be checked
- * for accuracy. Code that cannot be reached should have a
- * NOTREACHED comment.
+ * For consistency, getopt should be used to parse options. Options
+ * should be sorted in the getopt call and the switch statement, unless
+ * parts of the switch cascade. For the sorting order, see the usage()
+ * example below. Don't forget to add option descriptions to the usage
+ * and the manpage. Elements in a switch statement that cascade should
+ * have a FALLTHROUGH comment. Numerical arguments should be checked
+ * for accuracy. Code that cannot be reached should have a NOTREACHED
+ * comment.
*/
while ((ch = getopt(argc, argv, "abn")) != -1) {
switch (ch) { /* Indent the switch. */
@@ -215,9 +262,16 @@
case 'n':
errno = 0;
num = strtol(optarg, &ep, 10);
+ /*
+ * fold long expressions and line up continuation lines
+ * as appropriate for nesting, with the operators
+ * trailing...
+ */
if (num <= 0 || *ep != '\0' || (errno == ERANGE &&
- (num == LONG_MAX || num == LONG_MIN)) )
+ (num == LONG_MAX ||
+ num == LONG_MIN))) {
errx(1, "illegal number -- %s", optarg);
+ }
break;
case '?':
default:
@@ -230,24 +284,29 @@
/*
* Space after keywords (while, for, return, switch). No braces are
- * required for control statements with only a single statement,
- * unless it's a long statement.
+ * required for control statements with only a single statement, unless
+ * it's a long statement, but always using braces makes for better
+ * readability, fewer stupid bugs, and more easily navigable code
+ * (e.g. in your text editor).
*
* Forever loops are done with for's, not while's.
*/
- for (p = buf; *p != '\0'; ++p)
+ for (p = buf; *p != '\0'; ++p) {
continue; /* Explicit no-op */
- for (;;)
+ }
+ for (;;) {
stmt;
+ }
/*
- * Braces are required for control statements with a single statement
- * that may expand to nothing.
+ * Another reason for always using braces. They are required for
+ * control statements with a single statement that may expand to
+ * nothing. For example:
*/
#ifdef DEBUG_FOO
-#define DPRINTF(a)
+# define DPRINTF(a) /* nothing */
#else
-#define DPRINTF(a) printf a
+# define DPRINTF(a) printf a
#endif
if (broken) {
DPRINTF(("broken is %d\n", broken));
@@ -263,15 +322,13 @@
}
/* Second level indents are four spaces. */
- while (cnt < 20)
- z = a + really + long + statement + that + needs + two lines +
- gets + indented + four + spaces + on + the + second +
- and + subsequent + lines;
-
+ while (cnt < 20) {
+ z = a + really + longish + statement + that + needs + two +
+ lines + gets + indented + as + needed + on + the +
+ second + and + subsequent + lines + line + up;
+ } /* braces are also particularly important for multi-line stmts */
/*
* Closing and opening braces go on the same line as the else.
- * Don't add braces that aren't necessary except in cases where
- * there are ambiguity or readability issues.
*/
if (test) {
/*
@@ -285,18 +342,21 @@
} else if (bar) {
stmt;
stmt;
- } else
+ } else {
stmt;
+ } /* braces after if/elseif/else are particularly important! */
/* No spaces after function names. */
- if ((result = function(a1, a2, a3, a4)) == NULL)
+ if ((result = function(a1, a2, a3, a4)) == NULL) {
exit(1);
+ }
/*
- * Unary operators don't require spaces, binary operators do.
- * Don't excessively use parenthesis, but they should be used if
- * statement is really confusing without them, such as:
- * a = b->c[0] + ~d == (e || f) || g && h ? i : j >> 1;
+ * Unary operators don't require spaces, binary operators do. Don't
+ * excessively use parenthesis, but they should be used if statement is
+ * really confusing without them, such as:
+ *
+ * a = b->c[0] + ~d == (e || f) || g && h ? i : j >> 1;
*/
a = ((b->c[0] + ~d == (e || f)) || (g && h)) ? i : (j >> 1);
k = !(l & FLAGS);
@@ -304,27 +364,35 @@
/*
* Exits should be EXIT_SUCCESS on success, and EXIT_FAILURE on
* failure. Don't denote all the possible exit points, using the
- * integers 1 through 127. Avoid obvious comments such as "Exit
- * 0 on success.". Since main is a function that returns an int,
- * prefer returning from it, than calling exit.
+ * integers 1 through 127. Avoid obvious comments such as "Exit 0 on
+ * success.". Since main is a function that returns an int, prefer
+ * returning from it, than calling exit.
*/
- return EXIT_SUCCESS;
+ return (EXIT_SUCCESS);
}
/*
- * The function type must be declared on a line by itself
- * preceding the function.
+ * The function type must be declared on a line by itself preceding the
+ * function and the function name must start at the beginning of the line.
+ *
+ * The function parameters should be declared on separate lines, indented by
+ * tabs, to facilitate short comments about their purpose or meaning.
+ *
+ * Function prototypes should go in the include file "extern.h".
*/
static char *
-function(int a1, int a2, float fl, int a4)
+function(
+ int a1, /* the first and best parameter */
+ int a2, /* a similar parameter */
+ float fl, /* what a number that will be! */
+ int a4) /* and lastly a final parameter */
{
/*
- * When declaring variables in functions declare them sorted by size,
- * then in alphabetical order; multiple ones per line are okay.
- * Function prototypes should go in the include file "extern.h".
- * If a line overflows reuse the type keyword.
+ * When defining local variables in functions declare them sorted by
+ * size, then in alphabetical order; multiple ones per line are okay.
+ * If a line overflows reuse the type keyword again on a new line.
*
- * DO NOT initialize variables in the declarations.
+ * Use separate lines to initialize variables in definitions.
*/
extern u_char one;
extern char two;
@@ -332,44 +400,60 @@
double five;
int *six, seven;
char *eight, *nine, ten, eleven, twelve, thirteen;
+ char *seventeen = "foo";
+ char *eightteen = "fie";
+ char *nineteen = "fee";
+ char *twenty = "fo";
+ char *twentyone = "fum";
char fourteen, fifteen, sixteen;
/*
- * Casts and sizeof's are not followed by a space. NULL is any
- * pointer type, and doesn't need to be cast, so use NULL instead
- * of (struct foo *)0 or (struct foo *)NULL. Also, test pointers
- * against NULL. I.e. use:
- *
- * (p = f()) == NULL
- * not:
- * !(p = f())
+ * Casts and sizeof's are _always_ followed by a space (so as to avoid
+ * looking like a call to a function pointer). NULL is any pointer
+ * type, and does not need to be cast in an assignment or a comparison
+ * (but do cast it when it's used as a parameter so that it's clear you
+ * know you're passing a null of the pointer of the given type)
+ *
+ * You can test pointers against NULL or truth as desired. I.e.:
*
- * Don't use `!' for tests unless it's a boolean.
- * E.g. use "if (*p == '\0')", not "if (!*p)".
+ * ((p = f()) == NULL)
+ * or:
+ * (!(p = f()))
*
- * Routines returning ``void *'' should not have their return
- * values cast to more specific pointer types.
+ * You can use `!' for tests where the idiom suits. E.g. use either
+ * "if (*p == '\0')", or "if (!*p)".
+ *
+ * Routines returning ``void *'' need not have their return values cast
+ * to more specific pointer types.
*
* Use err/warn(3), don't roll your own!
*/
- if ((four = malloc(sizeof(struct foo))) == NULL)
- err(1, NULL);
- if ((six = (int *)overflow()) == NULL)
+ if ((four = malloc(sizeof(struct foo))) == NULL) {
+ err(1, (char *) NULL);
+ }
+ if ((six = (int *) overflow()) == NULL) {
errx(1, "Number overflowed.");
+ }
- /* No parentheses are needed around the return value. */
- return eight;
+ /* Parentheses should be used around the return value. */
+ return (eight);
}
/*
- * Use ANSI function declarations. ANSI function braces look like
- * old-style (K&R) function braces.
- * As per the wrapped prototypes, use your discretion on how to format
- * the subsequent lines.
+ * Use ANSI function declarations. ANSI function braces look like old-style
+ * (K&R) function braces.
+ *
+ * As per the wrapped prototypes, use your discretion on how to format the
+ * subsequent lines.
*/
static int
-dirinfo(const char *p, struct stat *sb, struct dirent *de, struct statfs *sf,
- int *rargc, char **rargv[])
+dirinfo(
+ const char *p, /* a pointer to a constant string */
+ struct stat *sb, /* some stuff */
+ struct dirent *de, /* good info */
+ struct statfs *sf, /* big and important */
+ int *rargc, /* a return value */
+ char **rargv[]) /* another return value */
{ /* Insert an empty line if the function has no local variables. */
/*
@@ -379,29 +463,41 @@
_DIAGASSERT(p != NULL);
_DIAGASSERT(filedesc != -1);
- if (stat(p, sb) < 0)
+ if (stat(p, sb) < 0) {
err(1, "Unable to stat %s", p);
+ }
/*
* To printf quantities that might be larger that "long", include
* <inttypes.h>, cast quantities to intmax_t or uintmax_t and use
* PRI?MAX constants, which may be found in <machine/int_fmtio.h>.
+ *
+ * Break long parameter lists, after long strings if appropriate, and
+ * line up the continuation lines at the beginning of the first
+ * parameter.
*/
- (void)printf("The size of %s is %" PRIdMAX " (%#" PRIxMAX ")\n", p,
- (intmax_t)sb->st_size, (uintmax_t)sb->st_size);
+ (void) printf("The size of %s is %" PRIdMAX " (%#" PRIxMAX ") and this is a really long string\n",
+ p, (intmax_t) sb->st_size, (uintmax_t) sb->st_size);
/*
* To printf quantities of known bit-width, use the corresponding
* defines (generally only done within NetBSD for quantities that
* exceed 32-bits).
- */
- (void)printf("%s uses %" PRId64 " blocks and has flags %#" PRIx32 "\n",
- p, sb->st_blocks, sb->st_flags);
+ *
+ * An obvious place to use STD-C string constant concatentation is when
+ * a single string constant contains multiple lines. Fold at the
+ * newlines, indent to match the string above.
+ */
+ (void) printf("%s uses %" PRId64 " blocks and has flags %#" PRIx32 "\n"
+ "and this is a second line from the same printf\n",
+ p, (int64_t) sb->st_blocks, (uint32_t) sb->st_flags);
/*
* There are similar constants that should be used with the *scanf(3)
* family of functions: SCN?MAX, SCN?64, etc.
*/
+
+ return (0);
}
/*
@@ -412,14 +508,16 @@
#include <stdarg.h>
void
-vaf(const char *fmt, ...)
+vaf(
+ const char *fmt, /* the message format */
+ ...) /* a variable parameter list */
{
va_list ap;
va_start(ap, fmt);
STUFF;
va_end(ap);
- /* No return needed for void functions. */
+ /* No "return" needed for void functions. */
}
static void
@@ -428,26 +526,30 @@
/*
* Use printf(3), not fputs/puts/putchar/whatever, it's faster and
- * usually cleaner, not to mention avoiding stupid bugs.
- * Use snprintf(3) or strlcpy(3)/strlcat(3) instead of sprintf(3);
- * again to avoid stupid bugs.
- *
- * Usage statements should look like the manual pages.
- * Options w/o operands come first, in alphabetical order
- * inside a single set of braces, upper case before lower case
- * (AaBbCc...). Next are options with operands, in the same
- * order, each in braces. Then required arguments in the
- * order they are specified, followed by optional arguments in
- * the order they are specified. A bar (`|') separates
- * either/or options/arguments, and multiple options/arguments
- * which are specified together are placed in a single set of
- * braces.
+ * usually cleaner, not to mention avoiding stupid bugs. Use
+ * snprintf(3) or strlcpy(3)/strlcat(3) instead of sprintf(3); again to
+ * avoid stupid bugs.
+ *
+ * Usage statements should look like in the manual pages.
+ *
+ * Options w/o operands come first, in alphabetical order inside a
+ * single set of braces, upper case before lower case (AaBbCc...).
+ * Next are options with operands, in the same order, each in braces.
+ * Then required arguments in the order they are specified, followed by
+ * optional arguments in the order they are specified. A bar (`|')
+ * separates either/or options/arguments, and multiple
+ * options/arguments which are specified together are placed in a
+ * single set of braces.
*
* Use getprogname() instead of hardcoding the program name.
*
+ * The word "usage" should have all lower case letters.
+ *
* "usage: f [-aDde] [-b b_arg] [-m m_arg] req1 req2 [opt1 [opt2]]\n"
* "usage: f [-a | -b] [-c [-de] [-n number]]\n"
*/
- (void)fprintf(stderr, "usage: %s [-ab]\n", getprogname());
+ (void) fprintf(stderr, "usage: %s [-ab]\n", getprogname());
+ /* a blank line bofore return or exit() */
+
exit(EXIT_FAILURE);
}