From: jww@evolving.com (John W. Woolley)
Newsgroups: comp.lang.c
Subject: SCCS eats good code -- help requested
Date: 18 Dec 92 21:54:13 GMT
Organization: Evolving Systems, Inc.
X-Newsreader: Tin 1.1 PL4


The other day I found what may qualify as the odd bug of the week.
I'd be happy for any suggestions as to what to do about this.  Email
me, please.

Evolving Systems recently began using a new source control system,
CMVC, which as I understand it is a wrapper around SCCS.  The new
source control system interacted with our code in an unintended way.

We had a chunk of source so:

  if (strftime(time_str, 64, "%w%H%M%S", time_struct) != 7)
          ret_value = FAILURE;

Nice normal ANSI C.  But SCCS had spotted the string %H% in the
above bit of code, and had done its replacement thing so:

  if (strftime(time_str, 64, "%w12/14/92M%S", time_struct) != 7)
          ret_value = FAILURE;

which caused strftime to yield results differing somewhat from those
intended.

(Admire for a moment the potential subtlety of this bug.  A customer
 phones the help desk, unhappy that the code doesn't work.  You get
 the IR, and try to reproduce his complaint; he's right, it fails.
 So you check out the offending module, looking for suspicious code.
 You see no bug, for the simple and sufficient reason that you,
 naturally enough, checked the code out for edit, and the bug isn't
 there in a writeable version.  You maybe tweak a comment here and
 there.  You recompile.  You run the program -- everything goes fine.
 Bug fixed.  You check the source back in and tell your boss that
 everything's cool.

 But, the moment it the module gets checked out in the Golden Area
 for a remake, BAM, bug time again.  Your boss calls you.  Your boss
 threatens you.  You are unhappy.

 This is a new and wonderful thing -- a bug that only exists in code
 that has been debugged, never in code you're trying to debug.)

One bit of good news is that printf and scanf have no upper-case
conversion specifiers except E, G, and X; and one of those, X, is
not mucked with by SCCS.  So only %E% and %G% might cause problems
with those functions.  But strftime's specifiers have lots of overlap
with SCCS's magic strings.

You can keep SCCS from doing the substitutions by calling its
"get" command with a "-k" parameter, but that short-circuits all
substitutions, even benign or beneficial ones; and we need those.
You can keep it from happening in your code by breaking up the
specifier strings thus:

  if (strftime(time_str, 64, "%w" "%H" "%M" "%S", time_struct) != 7)
          ret_value = FAILURE;

or thus:

  if (strftime(time_str, 64, "%w\%H\%M\%S", time_struct) != 7)
          ret_value = FAILURE;

but that's a really ugly kind of kluge, and one that's almost certain
to be undone by the first eager-fingered editor through the source
code who doesn't know why you did it.  (Oh, comments?  Well, yeah,
they might help, but let's be real ...)  And, really, you shouldn't
have to mess with source code to keep the source control system from
messing you up.

So does anyone know anything good we can do about this?  We can't be
the first site ever to struggle with format strings and SCCS.

-- John Woolley (jww@evolving.com)
Newsgroups: comp.lang.c