Joel C. Salomon:
>http://plan9.bell-labs.com/sys/doc/comp.html<
Thank you for that link.
I can see some interesting things in that very C-like language:
>The #if directive was omitted because it greatly complicates the preprocessor,
>is never necessary, and is usually abused. Conditional compilation in general
>makes code hard to understand; the Plan 9 source uses it sparingly. Also,
>because the compilers remove dead code, regular if statements with constant
>conditions are more readable equivalents to many #ifs.<
Can the "static if" be removed from D then?
------------------
Variables inside functions can have any order, are D compilers too doing this?
>Unlike its counterpart on other systems, the Plan 9 loader rearranges data to
>optimize access. This means the order of variables in the loaded program is
>unrelated to its order in the source. Most programs dont care, but some
>assume that, for example, the variables declared by
int a;
int b;
will appear at adjacent addresses in memory. On Plan 9, they wont.<
------------------
Plan 9 uses this strategy to solve endianess-induced troubles in integer I/O:
>Plan 9 is a heterogeneous environment, so programs must expect that external
>files will be written by programs on machines of different architectures. The
>compilers, for instance, must handle without confusion object files written by
>other machines. The traditional approach to this problem is to pepper the
>source with #ifdefs to turn byte-swapping on and off. Plan 9 takes a different
>approach: of the handful of machine-dependent #ifdefs in all the source,
>almost all are deep in the libraries. Instead programs read and write files in
>a defined format, either (for low volume applications) as formatted text, or
>(for high volume applications) as binary in a known byte order. If the
>external data were written with the most significant byte first, the following
>code reads a 4-byte integer correctly regardless of the architecture of the
>executing machine (assuming an unsigned long holds 4 bytes):
ulong getlong(void) {
ulong l;
l = (getchar()&0xFF)<<24;
l |= (getchar()&0xFF)<<16;
l |= (getchar()&0xFF)<<8;
l |= (getchar()&0xFF)<<0;
return l;
}
Note that this code does not swap the bytes; instead it just reads them in
the correct order. Variations of this code will handle any binary format and
also avoid problems involving how structures are padded, how words are aligned,
and other impediments to portability. Be aware, though, that extra care is
needed to handle floating point data.<
------------------
I don't fully understand this:
>the declaration
extern register reg;
(this appearance of the register keyword is not ignored) allocates a global
register to hold the variable reg. External registers must be used carefully:
they need to be declared in all source files and libraries in the program to
guarantee the register is not allocated temporarily for other purposes.
Especially on machines with few registers, such as the i386, it is easy to link
accidentally with code that has already usurped the global registers and there
is no diagnostic when this happens. Used wisely, though, external registers are
powerful. The Plan 9 operating system uses them to access per-process and
per-machine data structures on a multiprocessor. The storage class they provide
is hard to create in other ways.<
Bye,
bearophile