Date: Tue, 20 Sep 94 14:40 PDT From: jdp AT polstra DOT com (John Polstra) To: dj AT ctron DOT com Cc: djgpp AT polstra DOT com Subject: Re: strange linker behavior I wrote, and DJ replied: > > The implementation is absolutely not allowed to pollute any other > > portions of the global name space. The djgpp C library is a bad offender > > in this regard. > > Which is better - 100% ansi/posix conformance, or compatibility with > other compilers? That's a tough question, of course. It's especially difficult in the DOS world, which has evolved its own de-facto standards concerning what library functions and header files should be present. To some extent, you can get the best of both worlds, though. ANSI doesn't forbid the compiler implementation from providing functions (global names) in addition to those required by the standard. It merely demands that those names not get in the way of a user unless he asks for them. In practice, this means two things: 1. The prototypes / declarations for extra functions must not appear in any of the standard ANSI header files (or in any other files included by the ANSI header files). The ANSI standard header files are the following: The ANSI headers must declare only those symbols specified in the standard (and they must declare all of them). 2. (Here comes a little lie, which I will clear up in a minute.) If the implementation provides any extra global functions (e.g., delay() or read() or write()), none of the standard library functions are allowed to use the extra ones. For example, the implementation of fgetc() is not allowed to call read(). The little lie in the above is this: The library actually *is* allowed to implement fgetc() in terms of read(), provided that it behaves as if it didn't, from the user's point of view. (Likewise for other functions, of course.) That is, if fgetc() calls read(), then it better still work if the user defines his own global function named read() that does something entirely different. Getting the header files and library just right is not all that easy! Vendors do it wrong all the time. Incidentally, to expand on #2 above, I'll give an example of how a library can achieve the "as if" behavior. As most Unix programmers realize, fputc() is always really implemented using read(). But the ANSI-conforming library must behave as if it were not. Yet, it must still make read() available to Unix programmers who want to use that function (which is Posix standard, by the way). One way to do this is: * The library puts all the functionality of read() into a different function named "_read". * fputc() calls _read() to get its I/O done. * The user-visible read() function is just a wrapper that calls _read(). * read() and _read() are in separate object modules in the run-time library, so that they can be pulled in from the library independently of one another. That way, the user can write his own version of read(), causing the library version not to be used. But that won't affect the behavior of the standard function fputc(), which uses _read() instead. Another way to do it involves using so-called "weak" symbols. But they're not supported by the COFF object format that djgpp uses. I hope this is helpful. John Polstra jdp AT polstra DOT com John D. Polstra & Co., Inc. Phone (206) 932-6482 Seattle, Washington USA Fax (206) 935-1262 "Self-knowledge is always bad news." -- John Barth