RIMBOLD@ulowell.CSNET.UUCP (06/10/86)
While working on some system stuff, I noticed the following change: You used to be able to create a C program and have the entry point to that program be the first procedure in the program, regardless of whether or not that first procedure was named 'main' or not. That no longer happens. It doesn't complain, but doesn't work either. I tried this trick yesterday and noticed that the argc and argv had no relation to reality when I put them into a first procedure as so ' diskuse(argc, argv) '. As soon as I changed the name of the first procedure to main, as so 'main(argc, argv) '. It worked fine. I guess DEC is getting around to making their C a little (very little) more standard. Oh, I almost forgot. The optimizer now works as well. No more garbage about 'Submit an SPR'. 'Rob ulowell!rimbold rimbold@ulowell.CSNET
LEICHTER-JERRY@YALE.ARPA.UUCP (06/14/86)
...You used to be able to create a C program and have the entry point to that program be the first procedure in the program, regardless of whether or not that first procedure was named 'main' or not.... It doesn't complain, but doesn't work either. I ... noticed that ... argc and argv had no relation to reality when ... [my] first procedure ... [was] 'diskuse(argc,argv)'. As soon as I changed the name of the first procedure to main ... [i]t worked fine. I guess DEC is getting around to making their C a little (very little) more standard. Oh, I almost forgot. The optimizer now works as well. No more garbage about 'Submit an SPR'. 'Rob The VAX C library contains a routine that picks up and formats the command line arguments. That routine must be executed before you can get at the arguments. I don't know how VAX C Version 1 dealt with this; it may have used the LIB$INITIALIZE facility to ensure that the routine ran before any user code. That approach has a lot of limitations. In any case, VAX C Version 2 uses a simpler approach: The compiled code for the main program starts off with a JSB to the appropriate library routine. (If you look at the generated machine code, you'll see the JSB.) If this routine isn't called, your arguments are not available. This, of course, leads to a problem: The C compiler needs to know which is the "main" program in order to know when to insert the JSB - you wouldn't want it inserted in every function! Standard C specifies that the "main program" is ALWAYS the function named "main". Hence, if you compile a function whose name is "main", VAX C will insert the call. VAX C also provides a non-porta- ble extension: If you insert the option "main_program" between the function's name and the declaration of its parameters - something like: diskuse(argc,argv) main_program int argc; char *argv[]; the compiler will also insert the JSB. This is half the problem: Getting the arguments set up once the program has started. The other half is specifying to the Linker where the transfer ad- dress for the program is, that is, what function should be called to begin execution of the resulting image. The VMS Linker allows routines to be defined in one of 3 states: Not a transfer address (default; the image MAY NOT start here); strong transfer address (the image MUST start here); weak transfer address (the image MAY start here). The Linker will report an error if it sees no transfer address at all, or more than one strong transfer address. If it sees at least one weak transfer address, but no strong transfer addresses, it will choose some weak transfer address as the starting point. The VAX C compiler marks a function named main, or any function with the main_program option, as a strong transfer address. Hence, if such a function is included in the image, execution will definitely start there, and the Linker will complain if more than one such function is seen. (The compiler will complain if a single source file includes two "main routines".) All other functions are marked as weak transfer addresses. Hence, if you link up a VAX C image that does NOT contain a main program anywhere, the Linker will chose some other function as the entry point. Which one? Always the first one seen in the first module presented to the Linker. The use of this "first function will be transfer address" feature should probably be avoided - it's non-portable (though I'd guess it's in VAX C exactly because other implementations did this - Unix is one, in fact - and programs came to rely on it. Note that the VAX C compiler actually has to do something positive to make the functions it creates weak transfer addresses; other VMS compilers generally don't do this.) More important, it makes proper operation of your code sensitive to the order in which the modules happen to be presented to the Linker, and the order in which functions happen to appear in the source code. Hardly dependencies that will ease debugging and main- tenance! -- Jerry -------