The first sentence is right on the money. In addition to module variables,
I define a global structure as:
extern struct G {
/* the real globals */
} g;
and then in the main program I define the instance as "struct G g;" This
is more for apps than operating systems.
Further to the avoidance of pollution of the external global namespace, I
define local functions as static. Indeed, in one parser I had over 1400
very small functions, none of them with external scope. Instead, I defined
a structure of function pointers and exposed one name to the rest of the
world. Sound stupid? Well, that stupidity had its place: the "opcode" in
the pseudo-instruction stream was the offset into this structure of
pointers to the pointer of interest, which made the main loop for the
parser about five lines long, and not a switch statement to be seen. Three
of those lines were to handle unknown-opcodes...
I also am partial to arrays of function pointers when appropriate. Ever
think how easy it would be to implement a TCP stack that would handle the
"lamp-test packet" as a single special case? Granted, it results in a
small amount of code bloat over the traditional in-line test method, but it
does make you think about EVERY SINGLE ONE OF THE 64 COMBINATIONS of
Urg/Ack/Psh/Rst/Syn/Fin (to use the labels from the 1985 version of RFC
793) and what they really mean. Especially the combination with all bits set.
Satch
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/