swilson%thetone@Sun.COM (Scott Wilson) (09/03/88)
The topic of passing argc and argv to a C program came up on comp.lang.c which got me thinking about the way this works in THINK's LightspeedC. For those who aren't familiar, in LSC to get a pseudo UNIX command line that allows you to type program arguments that will end up as argv, you call your main() function _main(). You then link your program with the file "unix main.c" which has a main() in it that parses the command line and then calls your _main(). I think this is kludgey. I don't like the idea of having code that looks like: #ifdef THINK_C #define main _main #endif This is ugly. To me, there seems to be a better way to do this (I would mail this to THINK, but they don't seem too thrilled to listen to me these days). I would like to see this problem solved by how the program was linked: if "unix main.c" is added to the project then a command line is prompted for and args are passed to main() in the user's program; if "unix main.c" is not in the project then main() is called with argc of 1. This way main() in the user's program would always be called main. The file "unix main.c" could have a _main() in it that would do the command line stuff and then call main(). In the abscence of "unix main.c", another _main() would be linked in that would just set argc to 1 (and either the program name or "" for argv) and call main(). This other, nearly null, _main() would reside in MacTraps or some other convenient place and would be supplanted by the _main() in "unix main.c" if present. Of course, this means that LSC's startup code would jump to _main() to start off instead of main(), but this would be transparent to the program which certainly isn't the case now. I don't think this is currently possible at present, however, which brings me to the next topic. I haven't been able to make it work, but does LSC allow you to supersede some functions of a library without causing link errors? For example let's say you wanted to link with strings but wanted to have your own version of just strcpy(). I believe that this evokes an error message complaining of multiple occurrences of strcpy(). I think this is something LSC should allow, but it would mean there needs to be some method of determining which occurrence of a function was used. UNIX in this case does the following (I think): a function that came from a file given on the command line supersedes any occurrence of a function of the same name that is found in a library. The distinction is between compiled user files and system libraries. LSC could do something similar, if a user's .c contained a function also found in a library then the user's version would be used. This would also mean that code ported to LSC would not have to worry about clashing with some non-standard fucntions in LSC's library (like trying to port a program that had it's own Move() in it (I think that's the name LSC uses, but I don't have it here)). Any comments on this? -- Scott Wilson arpa: swilson@sun.com Sun Microsystems uucp: ...!sun!swilson Mt. View, CA
upstill@pixar.UUCP (Steve Upstill) (09/07/88)
I say it's unfair to expect ThinkC to do something Unix C doesn't: allow the user to supercede an arbitrary function from a library. The Unix linker links in a whole module whenever it defines a single undefined symbol. Steve Upstill
kaufman@polya.Stanford.EDU (Marc T. Kaufman) (09/07/88)
In article <2391@pixar.UUCP> upstill@pixar.UUCP (Steve Upstill) writes: > I say it's unfair to expect ThinkC to do something Unix C doesn't: allow >the user to supercede an arbitrary function from a library. The Unix >linker links in a whole module whenever it defines a single undefined symbol. You imply that the link problem is a "C" restriction. It is not. It is a problem with a particular LINKER implementation. There is no requirement that there be more than one entry point in a module, or that specific entry points cannot be overridden quietly... I had such a linker on a VAX I used, as well as many other large mainframe machines. There is no way a user can know in advance just which entry points are grouped into "modules". For the sake of portability, I often include my own version of routines which may be present on some, but not all, systems the code may run on (such as atan2). It is reasonable to expect that a linker will honor my requests to override specific modules. Marc Kaufman (kaufman@polya.stanford.edu)
jnp@calmasd.GE.COM (John Pantone) (09/08/88)
(Steve Upstill) writes: >I say it's unfair to expect ThinkC to do something Unix C doesn't: >allow the user to supercede an arbitrary function from a library. The >Unix linker links in a whole module whenever it defines a single >undefined symbol. Are you saying that ThinkC and Unix will not allow something like: link my_main with (my_)printf and anything else needed from lib c (except the copy of printf in there) where the printf explicitly specified also exists in lib c, but I wish it to be superceeded by my version? Then the ThinkC and the Unix linker are outmoded and weak, to say the least. REAL linkers have allowed this sort of selective replacement for years. (Even CP/M allow(s/ed) this). -- These opinions are solely mine and in no way reflect those of my employer. John M. Pantone @ GE/Calma R&D, 9805 Scranton Rd., San Diego, CA 92121 ...{ucbvax|decvax}!sdcsvax!calmasd!jnp jnp@calmasd.GE.COM GEnie: J.PANTONE
swilson%thetone@Sun.COM (Scott Wilson) (09/08/88)
> I say it's unfair to expect ThinkC to do something Unix C doesn't: allow >the user to supercede an arbitrary function from a library. The Unix >linker links in a whole module whenever it defines a single undefined symbol. UNIX libraries (.a files) are composed of many separately compiled object files (.o files). As far as I know the linker extracts only the .o files needed to resolve references when linking. If you have your own strcpy, for example, the linker will not get strcpy.o from the library because the reference has already been satisified. Which versions of UNIX are you talking about, because the following has always worked for me without linker complaints: cc try.c strcpy.c -o try I'm only asking THINK C to be as smart as the UNIX linker, not any smarter. -- Scott Wilson arpa: swilson@sun.com Sun Microsystems uucp: ...!sun!swilson Mt. View, CA
hkbirke@mit-amt (Hal Birkeland) (09/08/88)
> UNIX libraries (.a files) are composed of many separately compiled object > files (.o files). As far as I know the linker extracts only the .o files > needed to resolve references when linking. If you have your own strcpy, > for example, the linker will not get strcpy.o from the library because the > reference has already been satisified.... I ran into just such a replacement problem with one recent multi-person software project (we each wrote separate parts and then combined them together). Buried in the middle of one of my partners code was a definition for random (using longs, of course) which returned a random POSITIVE OR NEGATIVE integer. My code grabbed the library random (positive integer return value). The result was that my code crashed when compiled into the project, but ran fine on its own. If the library function was not automatically superceded, the error did not occur (even worse, the problem couldn't be solved until I ran "strings" on the other guys code). After all, YOU CAN NAME YOUR FUNCTIONS ANYTHING YOU WANT while the libraries are ALREADY DEFINED. Please rename the functions rather than reusing the existing symbol... -- hal
conybear@bruce.oz (Roland Conybeare) (09/08/88)
From article <2391@pixar.UUCP>, by upstill@pixar.UUCP (Steve Upstill): > > I say it's unfair to expect ThinkC to do something Unix C doesn't: allow > the user to supercede an arbitrary function from a library. The Unix > linker links in a whole module whenever it defines a single undefined symbol. > > Steve Upstill I disagree! :-) The unix linkers that I have used all link files left to right*, resolving references as they go. So if I wanted to redefine malloc, I could: 1. Write my own malloc 2. Link my version before the standard library e.g. cc myprogram.o mymalloc.o -lc In this case the linker will resolve all malloc's in myprogram.o when it comes across mymalloc.o. It will resolve malloc's in the standard library, using the original malloc defined there. P.S. Caveat Emptor Roland Conybeare * I mean in the order supplied to the linker
levin@bbn.com (Joel B Levin) (09/08/88)
In article <59@calmasd.GE.COM> jnp@calmasd.GE.COM (John Pantone) writes: | |Are you saying that ThinkC and Unix will not allow something like: | |link my_main with (my_)printf and anything else needed from lib c |(except the copy of printf in there) | |where the printf explicitly specified also exists in lib c, but I wish |it to be superceeded by my version? | |Then the ThinkC and the Unix linker are outmoded and weak, to say the |least. REAL linkers have allowed this sort of selective replacement |for years. . . . The UNIX(TM) linkers I have known, and the MPW linker as well, do allow exactly this. But there is one problem that you have to watch out for. Using your example: if the module within the library which contains printf also contains (say) sprintf, AND my_main calls sprintf as well as printf, AND you do not provide a substitute (my_)sprintf, then when the linker attempts to resolve the sprintf reference, it will find itself with two entries for printf. This will make it unhappy. The solution is to determine all the entry points in the standard library module containing printf and to provide those entry points in your own version. As to the previous question: sorry, I have no idea what ThinkC does. /JBL UUCP: {backbone}!bbn!levin POTS: (617) 873-3463 INTERNET: levin@bbn.com
swilson%thetone@Sun.COM (Scott Wilson) (09/09/88)
>If the library function was not automatically superceded, the error did not >occur (even worse, the problem couldn't be solved until I ran "strings" on >the other guys code). After all, YOU CAN NAME YOUR FUNCTIONS ANYTHING YOU >WANT while the libraries are ALREADY DEFINED. > >Please rename the functions rather than reusing the existing symbol... Part of the point, though, is that reusing the library symbol may be exactly what you want. For instance, let's say that code runs great on machine A. When you port it to machine B you find that some library function is broken. So you write your own version of the function and link it in superseding the broken library funtion. If the linker doesn't allow you do this, you resort to ugliness like putting "#define fgetc XXXfgetc" at the top of your code. This is what I have done with THINK C (and I'm not implying their library is broken, but in some cases I wanted to use home-made functions that were more compatible with UNIX). I would much rather just link the code with my versions of the library functions. Another point to consider is that those "already defined" library names can be non-standard names that will conflict with ones you've chosen. For example if you had a program that had a function called cgets() it wouldn't link with THINK C because this is a (non-standard) part of their stdio library. (I think that's the name of the function, but I wouldn't bet my life on it because I don't have my THINK C docs at work.) It sounds like a warning from the linker that a library symbol was being superseded would have prevented your problem while allowing the type of things I describe. I don't how hard that would be to implement, but I could live with the warnings. -- Scott Wilson arpa: swilson@sun.com Sun Microsystems uucp: ...!sun!swilson Mt. View, CA "It's the end of the world as we know it, and I feel fine." -R.E.M.