idallen (09/13/82)
How can the C programmer avoid accidentally re-defining an existing C Library function, making it unusable by other C Library functions that need it? How can the programmer avoid accidentally re-defining or using an external needed by the Library? For example, if the programmer didn't know that getlogin() used ttyslot(), s/he might accidentally redefine ttyslot() to be something peculiar. Then getlogin() would fail. Similarly, an accidental re-definition of _doprnt() would render printf() useless. Currently, the only way to avoid this problem is to remember ALL function and external names used in the library, and to avoid these names in our programs. It is probably too late to change the way things work with the existing C library; this is an appeal to future language designers. Somewhere in C history, all the C Library function names should have been renamed to include some special character (or have some special naming convention). Programmers should have been told that this special convention was used to name C Library routines, and that they were NOT to use any externals or function names that used this convention (unless they were specifically replacing the C Library function with their own). If this convention, or a similar one, were followed, programmers would never need to worry about accidentally replacing C library functions with their own. This is the *only* way programmers can avoid accidentally replacing *future* library functions. A special character convention would allow names like: $printf() str$len() get$uid() get$pwent() ... (For the B Language used here at Waterloo, we chose the period as our special character. All B Library function names contain a period.) I don't know if there are any free characters in the C character set that would allow this change to take place. The underscore would be a good-looking character to use, but it's probably been used a lot by people already. Adopting a convention that all library names should *start* or *end* with a character (e.g. Xprintf) doesn't appeal to me. The next time a library-based language gets built, I hope someone thinks of the memory burden of the programmer. -IAN! U of Waterloo (decvax!watmath!idallen)
eric (09/14/82)
Lint will detect the redefinition of library functions. The problem is many people, including myself, don't use lint regularly. I'd like to see this feature of lint (and some others) moved into the C compiler. (your example of redefining _doprnt isn't valid, the prefix _ has been conventionally used for `secret' global names.) I don't think your `special character' scheme will work well. You can't assume there is going to be only one system library. A user might need to use several independently-developed librarys, for example, graphics, fast file system, stdio, etc. There's some use of prefixes in the C library: str in strcmp, strcpy; f in fopen, fread; but it's not consistent: getc, not fgetc. System calls don't use prefixes and also tend to be very common identifiers (open, read, time). These should certainly have been prefixed; application programmers shouldn't have to know about the existence of most of them when using stdio. Ada has done a good job of supporting independent librarys, which they've termed packages. Normally one refers to a package element by prefixing the package name with a dot operator. You could have packages `io' and `gr'. A function `open' in both packages is referred to by io.open and gr.open. There's a statement to make all package elements local symbols, so that you can leave off the prefix. This could cause conflicts, but the compiler should detect them (or you could avoid this language feature). If you have a C-ld with long symbols names, there's no reason you can't use prefixes (io_open is better that fopen though). If you have the resources, you could even change the C library source and documentation to use this convention. Eric Gisin, decvax!watmath!watarts!eric.
gwyn@Brl@sri-unix (09/21/82)
From: Doug Gwyn <gwyn@Brl> Date: 17 Sep 82 5:04:45-EDT (Fri) The usual solution to your problem is to declare your own routines "static". That way they're not known to the linker. Of course this doesn't solve the problem of entry points in a multi-file program conflicting with library names. In this case the only recourse is to check each of your externally- accessible interface routines (there shouldn't be too many) against the appropriate library namelists. Sometimes it is actually useful to be able to replace a system library routine by one's own version, so there are positive aspects to the design too. A complete solution to the problem requires substantial support from the linker. Try talking IBM or DEC into this and see what happens!
mullen@Nrl-Css@sri-unix (09/22/82)
From: mullen at Nrl-Css (Preston Mullen) Date: 17 Sep 1982 12:03:29-EDT The 4.1bsd C compiler allows '$' as a character in identifiers (it's a "letter"). The C preprocessor does too. I can't recall ever seeing this fact documented. P.S. Certain 4.1bsd programs, e.g. ctags and vgrind, do not know this and hence behave strangely when function names include '$'.
dan@Bbn-Unix@sri-unix (09/22/82)
From: Dan Franklin <dan@Bbn-Unix> Date: 17 Sep 1982 13:01:14 EDT (Friday) This is a good point. UNIX is actually quite unusual in not having such a standard prefix for system names. As a matter of C trivia, there are three printing ASCII characters not used anywhere in the language: dollarsign, at-sign, and backquote. Dollarsign seems like a reasonable choice for such a separator.
idallen (09/22/82)
Having to check every one of my own function names against an existing library namelist only works for the current version of the library. If the system library changes, it might well change to use some function or external name that I use in my program. A naming convention is the only way to avoid *future* naming conflicts.
minow (09/23/82)
Vax-11 C and Decus C both allow '$' freely in identifiers. This is needed to access VMS system library functions. Decus C maps '_' to (radix-50) '.' in external symbols. This letter is, however, reserved for operating-system globals (such as those in the RSX-11M file service library), so '_' has been eliminated from the library wherever possible. For example, _doprnt() has been named $$dopn. While I'm on the subject, there are a few useful library routines in Decus C which I would recommend for inclusion on Unix: fgetname(iop, char_buffer) Writes the name used to fopen() the FILE *iop argument. This is implemented on Vax-11C, along with getname(chan, buffer). fwild(file_name, open_mode) Sets up the file system to open a wild-card file. Returns a FILE *. The next file is opened by calling fnext(iop). isalloc(mem_ptr) TRUE if mem_ptr was allocated by malloc(). msize(mem_ptr) The number of bytes allocated (undefined if isalloc(mem_ptr) is FALSE). Fwild/fnext would typically be used as follows: int nfiles; FILE *fd; if ((fd = fwild("foo.*", "r")) == NULL) { perror("foo.*"); exit(1); /* Couldn't parse/setup file */ } for (nfiles = 0; fnext(fd) != NULL; nfiles++) { fgetname(fd, file_name); /* Currently open file */ /* Normal processing of fd using getc, fgets, etc. */ } if (nfiles == 0) printf("No files matching foo.*\n"); Fwild/fnext is fairly simple to implement on VMS, RSTS, and RSX, fairly painful on RT11. I have no idea whether it is even possible on Unix (but you could always fork a shell, feed it the file name, pass that through echo, and build a table of the matches). Martin Minow decvax!minow
henry (09/23/82)
There are two possible problems with using '$' as a character in identifiers to mark them as "system" names. The first is that it is likely to foul up things like yacc, which process C text looking for $ as a marker for special hooks into their innards. The second, decidedly more serious problem, is that... it's not C, folks. No matter what Berkeley says. It's neither standard nor portable. I can't say I'm too delighted with a lot of the other things Berkeley has done, but dammit, they should have kept their hands off the C language! As Dennis Ritchie has been heard to say, "we *had* a standard...". Henry Spencer U of Toronto
dave (09/26/82)
Beginning secret library routines with a capital letter has been used here for a long time, and seems to work. For example, our graphics package uses G (Ginit, Gclose, etc.). Obviously it's a good idea for package writers to pick a letter not used by any packagesl likely to be linked together with the package being created. Dave Sherman CSRG U of Toronto