[mod.computers.vax] Important change to VMS C v2.2 with VMS v4.4

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
-------