Subject: Re: which echo.c would you choose?
To: Jonathan Cline <Cline@d2tech.com>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: current-users
Date: 11/30/1999 01:08:58
This has nothing whatsoever to do with anything i386-specific, so it
doesn't belong on port-i386.  I'm Cc:ing it to current-users, and
setting a Reply-To: header there.  If anyone has a better idea for
where it belongs, feel free.

> Here I'll present some different echo.c's without labelling their
> ancestry.  Tell me, which version is the best and why?

Best according to what metric?

Here's a brief summary of significant differences as I see them.  All
versions use a flag variable to handle no-newline.  All versions look
for a -n option.  All versions print arguments with a space between
each and the next, and (unless suppressed) a newline after the last.
All versions print the space and newline with putchar().  Except that
version A also checks for trailing \c, their functionality looks
identical.  (I am not competent to tell whether its \c functionality is
correct according to the standard, if any, that specifies \c.)

They vary significantly in how they detect -n, how they handle setting
the flag variable, what call they use to print arguments, and where
they have (void) casts.  Except for one indentation glitch in version C
(which might be due to sloppy tabs), they all use basically the same
indentation and brace placement style, one not far from the NetBSD
pseudo-standard.

Version A: -n noticed via strcmp.  Flag set in each branch of an
if-else.  Prints arguments with printf("%s",...).  (void) cast on
printf, none on putchar.

Version B: -n noticed via strcmp.  Flag set in each branch of an
if-else.  Prints with printf("%s",...).  (void) casts on printf and
putchar both.

Version C: -n noticed via three single-character == operations ('-',
'n', '\0').  Flag variable set unconditionally to 0, then conditionally
to 1.  Prints with fputs.  (void) casts on fputs and putchar both.

Version D: -n noticed via strcmp.  Flag set in each branch of an
if-else.  Prints with fputs.  (void) cast on fputs, none on putchar.

Where I personally come down on these issues is:

- Use strcmp for -n.  Reason: efficiency difference is lost in the
   noise, so the maintainability advantage takes over.

- Set the flag one way unconditionally, then the other conditionally.
   Reason: uniformity of style with larger works.  In a work this small
   the difference is more or less irrelevant, but in larger works it
   can be reassuringly centralized to set all flags to the defaults in
   one place, then change them as appropriate in comparatively
   scattered places - if flag-setting is done in if-elses, one has to
   check that the if-else is executed to be sure the flag variable is
   initialized sensibly.  (The initialization can be omitted if the
   variable has static duration and the default initialization for its
   type is correct.)

- Print with printf.  Reason: again, for this application efficiency is
   effectively irrelevant, so go with what's clearest for maintainers.
   (To those who think efficiency really matters, why are you using
   stdio at all, instead of constructing the iov from hell and using
   writev?)

- Skip all the (void) casts.  This is one of the cases in which I
   entirely agree with Richard Stallman: there is nothing wrong with
   ignoring return values, and any tool that thinks otherwise should be
   ignored or configured into saner behavior.  (As an example of this
   sort of configuration, I have a wrapper for lint that filters out
   messages that I have found are almost uniformly useless noise.)

If I had to choose among only the four programs presented, I would
probably pick B, unless handling \c were important, in which case A
would be the only candidate on simple functionality grounds.

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B