[comp.sources.d] some comments on my bitstring package

paul@vixie.UUCP (06/11/87)

Alan sent me mail containing comments and diffs for the bitstring package
I posted in mod.sources a few months ago.  Since I have now answered these
questions several times, I think I'd better get efficient and send my
defense to the net at large.  My reply to Alan is detailed enough to do
the job.  Here it is:
----------------------------------------------------------------------
It's nice to see interest displayed in my code, but ... I already had this
discussion with Rich $alz, moderator of mod.sources (comp.sources.unix), and
if I was able to convince HIM that I had reasons for doing it as I did it, I
hope I can now also convince YOU.

You write:

>  a)	I want to staticly initialize my bitmasks:
>	bit_decl(chrBitMask,128) = {0, 0x7FFFFFF, 0xFFFFFFFF, 0x7F };

These macros are a conceptual tool, more than anything else.  They are
intended to create an abstract called a "bit string".  This usage depends
explicitly on these "bit strings" having the underlying form of "array of
integer", which may not always be true -- I wanted the definition of the
macros to make NO assumptions on implementation.  Note the item in the
man page about a possible future enhancement: bounds checking, probably
to be implemented by keeping an extra array element at the front of the
'int array' side of the abstraction, that would hold the maximum size of
the array.  Where would that leave your example, above?

If an initializing version were to be created, then, in order to match the
abstraction, it would have to accept {1,1,0,0,1,1,1,0,1,1,0} or something
like it -- bits, in other words.  This would have to be done as a function
call, which would mean that the macro could not be used for globals.  Since
I could find no easy and abstractly clean way to do initialization, I
didn't do it.  Initialization would be great, but C constrains me -- C++
would let me do what I want, here, but that's not portable (yet).

Note that these macros are NOT emulating function calls.  There is no way
to make a function which can be called to introduce variables -- so thinking
of bit_decl or bit_ref as functions is just not correct.  Since they are
not functions, and could not be functions given what they do, I decided to
make them look as much as possible like NON-functions, i.e. macros, therefore
no semicolons.

Again, I'd like to stress that I put a lot of thought into these, and I've
used these in several different forms now -- they were tuned and tweaked
many times before release.  The released version is intentional in every
respect, which means: I had a reason for every brace and semicolon.  I
should have included a paper on just why it was done the way it was, since
you are the fourth person now to suggest changes.  To continue, you write:

>  b)	I want to possibly embed bit_set or bit_clear calls within
>	a parenthized expression:
>	if (bit_set(chrBitMask,c), bit_test(chrBitMask,c2))
>
>Granted, case (2) may be considered as contributing to criminal
>acts of coding, but, just because it's ugly, doesn't mean that
>it's not desireable to someone, somewhere.

In order to be usable in an expression as in your example, bit_set and
bit_clear would have to have some defined, meaningful (and useful) value.
The way the macros are currently written, the value of the expression
used in bit_set and bit_clear is the contents of the new 'int' after
having been modified -- this is out, since I wanted to hide the implement-
ation from the clients.  For a while, I had bit_set and bit_clear as
expressions, that returned the previous value of the bit you modified.
This was useful, but it slowed things WAY down and required a temporary
variable (which, being global, could not be put in a register).  I decided
to isolate the expression completely, to avoid the violation-of-abstration||
massivley-inefficient problem.  The existing version is, indeed, not as
useful as it could be; it's the result of various trade-offs, though, and
I support the implementation as it stands.  Here, the braces are intended
to isolate what lies beneath.

bit_set and bit_clear COULD be function calls, given what they do; for the
isolation value, though, I decided to use braces in the definition.  If you
use a semicolon on the macro call, you end up with {xxxx};, and I'm not sure
what C will do with the ';' in that context.  I know that if you try to use
the macro as an expression, the compiler will barf on you.  I like things
like that -- better than defining it as "undefined" and having your code
not be portable to a different implementation of bitstring.h...

>Macros should allow for maximum utilization through minimum
>restriction in usage.  Thus, coding the macros as block
>expressions "{ ... }" forces the macro call to never be used
>within an expression.  As a matter of principle, I consider this
>to be an unnecessary restriction, without apparent justification.
>Similarly, including the ';' with the "bit_decl" macro precludes
>any initialization, without any good reason for it.

I hope I've shown "apparent justification" and "good reason", above.  Once
again: every brace and semicolon has a reason for being there.  I agree that
to someone coming upon bitstring.h "code", without going through all the
process of thought I went through, will not neccessarily see why I did things
as I did.  I hope this letter will help.  Going on:

>If I were the original author of these macros, I wouldn't hesitate
>to change them to follow my coding philosophies.  However, since
>they are someone else's, and since they are no doubt being used
>already as they are, it behooves me to avoid incompatible changes.
>For these reasons, I've created a new name for the previous
>"bit_decl": "bit_dcl", which doesn't include the ";", allowing
>static initialization. "Bit_decl" was rewritten as a call to
>"bit_dcl" with a trailing ";".  Hopefully, no old code should
>break.

No old code would break, but new code would not be portable unless
unreasonable restrictions were placed on the implementation mechanism
used for bitstring.h.  Allowing initialization means that initializations
are not portable, and I don't want to do that.  Right now, in the current
(released) form, bitstring.h carefully does the same thing no matter what
the implementor decided to do.  I, myself, have tried "char" and "short"
on the system I use here, since I have a 32-bit chip on a 16-bit bus.
Since C expands expressions to 'int' size, I gained nothing from it.
Someone else might, though, given a different C compiler, or given a need
for range checking, or ...

>I've removed the braces in "bit_set" and "bit_clear".  This should
>only break code which invoked the macros without semi-colons (a
>bad practice anyway -- the macros are emulating function calls,
>and the syntax should be identical).  This change allows calls to
>these macros to be embedded within comma-expressions.

I covered this above, but to recap: if they can be used as expressions,
they have to have a defined value.  The defined value cannot be the one
returned in the current implementation -- which is the contents of an 'int'
in the underlying implementation after having been modified -- because the
'int' is implementation-dependent, and defined expression-values need to fit
the abstraction.  Never mind the fact that YOU only want to use it in a
comma-expression -- if it can be used as an expression, it MUST have a
defined value that fits the abstraction.  Defined values that fit the
abstraction are all horribly inefficient, whereas the current definition
(as a statement only) makes it possible to implement it fast enough that
it can often be used "inner-loop" with surprisingly fast results.  Also,
a recap: these macros are MACROS, not function-calls; they should look
like macros as much as possible.  The definition calls for them to be
macros -- which does not restrict implementors, since they are free to
code macros that just call functions.

>Following, now, is a context-diff, which can be used with "patch"
>to modify your bitstring.h.  Also, tacked afterwards, is the
>entire source, in case your source has varied greatly since I've
>recieved it.
>
>Alan Stebbens (aks@acc-sb-unix.ARPA)

I'm sorry, Alan, but I will not install these changes unless you can argue
against the reasons I defined the bitstring package the way I did.  I do
appreciate the interest, and I'm certainly glad to see the code get used;
however, please believe me when I say that every change you suggest was
considered (some were implemented and used!) and later rejected for one of
various reasons.  Rich $alz can attest to this, if he ever returns.
-----------------------------------------------------------------------
-- 
Paul A Vixie Esq
329 Noe Street       {ptsfa, crash, hoptoad, ucat}!vixie!paul
San Francisco        ptsfa!vixie!paul@ames.ames.arc.nasa.gov
CA  94116            paul@vixie.UUCP     (415) 864-7013