[comp.lang.c] main return value

cschmidt@lynx.northeastern.edu (05/13/91)

Forgive me if you have seen this message already.  I first posted this
12 days ago and have not seen it yet on our copy of the comp.lang.c
newsgroup; nor have I seen or received any responses.

What value should the standard function MAIN return?  I ran into this
question when porting some programs from DOS to VMS.  Alternatives:

1.  Declare the MAIN return type as VOID and do not return any value
    to the compiler's exit routines.  The problem with this is that
    when the program actually terminates, it will return a non-zero
    value to DOS as the "exit code".

2.  Declare the MAIN return type as VOID and terminate the function
    with the line "exit (EXIT_SUCCESS)".  The problem with this is
    that the VAX C compiler displays an error message (warning level)
    when the return type of the function MAIN is VOID.

3.  Declare the MAIN return type as INT and terminate the function
    with the line "return EXIT_SUCCESS".  The problem with this is
    that EXIT_SUCCESS is zero, even in the VAX version, and when a VMS
    program terminates and returns zero to VMS, VMS displays the
    system message for status code zero.  (The universal status code
    for success in VMS is one, not zero.)

4.  Declare the MAIN return type as INT and terminate the function
    with the line "return MAIN_SUCCESS", where MAIN_SUCCESS is an
    application-defined OS-dependent macro (which would be zero for
    DOS, one for VMS).  This is the only solution I can think of right
    now that would be lint-free and that would not cause the program
    to return a non-success error status code to the OS.

I expect many experienced C programmers will be surprised to learn
that it is impossible to write a portable, lint-free "hello world"
program in C that compiles and links without errors.

Christopher Schmidt
cschmidt@lynx.northeastern.edu

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (05/13/91)

In article <memo.1010816@lynx.northeastern.edu>, cschmidt@lynx.northeastern.edu writes:
> 3.  Declare the MAIN return type as INT and terminate the function
>     with the line "return EXIT_SUCCESS".  The problem with this is
>     that EXIT_SUCCESS is zero, even in the VAX version, and when a VMS
>     program terminates and returns zero to VMS, VMS displays the
>     system message for status code zero.  (The universal status code
>     for success in VMS is one, not zero.)

The whole _point_ ofg having EXIT_SUCCESS and EXIT_FAILURE in the
standard is so that they can be configured for the host operating system.
If a C implementation defines EXIT_SUCCESS to be something that provokes
an error, that implementation is _broken_.  You may have to provide your
own header #defining EXIT_SUCCESS correctly.

However, I note that VMS was hacked a couple of years ago so that a 0
return from a C program would _not_ provoke an error report from DCL.
Are you running a current version of VMS?

> I expect many experienced C programmers will be surprised to learn
> that it is impossible to write a portable, lint-free "hello world"
> program in C that compiles and links without errors.

Not at all.  There is no limit to the way compilers can be broken.
(Example: A certain C compiler for M680x0s used to emit the right
opcode for a certain unsigned comparison, but the assembler (from
the same vendor) that was its back end reversed the sense...)

-- 
Bad things happen periodically, and they're going to happen to somebody.
Why not you?					-- John Allen Paulos.

gwyn@smoke.brl.mil (Doug Gwyn) (05/13/91)

In article <memo.1010816@lynx.northeastern.edu> cschmidt@lynx.northeastern.edu writes:
>What value should the standard function MAIN return?

If main returns at all, it returns an int.  It should be so declared.

>3.  Declare the MAIN return type as INT and terminate the function
>    with the line "return EXIT_SUCCESS".  The problem with this is
>    that EXIT_SUCCESS is zero, even in the VAX version, and when a VMS
>    program terminates and returns zero to VMS, VMS displays the
>    system message for status code zero.  (The universal status code
>    for success in VMS is one, not zero.)

If your VMS C compiler really has this bug, get the vendor to fix it.
The DEC representative to X3J11 agreed than VMS C would map a 0 exit
status value to SYS$SUCCESS (an odd number, probably 1) before
handing in back to the invoking environment.  The EXIT_* macros were
introduced primarily as a political compromise to accommodate VMS C.

wirzeniu@kruuna.Helsinki.FI (Lars Wirzenius) (05/13/91)

In article <memo.1010816@lynx.northeastern.edu> cschmidt@lynx.northeastern.edu writes:
>What value should the standard function MAIN return?  I ran into this
>question when porting some programs from DOS to VMS.  Alternatives:
>
>1. [void main(), no exit code]
>2. [void main(), exit(EXIT_SUCCESS)]
>3. [int main(), return EXIT_SUCCESS]
>4. [int main(), return MAIN_SUCCESS]
>[EXIT_SUCCESS == 0 causes problems in VMS]

According to the standard (or rather, all of my books covering the
standard, I don't have a copy of the real thing), the only legal
prototypes for main are:

	int main(void);
	int main(int, char **);		/* note: char ** <=> char [] */

This means that void is out of the question as the return type.

Your second problem, what value to return to the operating system, isn't
really tied up with the type of main (it is possible to terminate the
program and return a value to the operating system from anywhere in the
program with the exit function). 

If it is true that the VMS C compiler defines EXIT_SUCCESS as 0, and the
operating systems interprets that as failure, then I would think that
the VMS C compiler has a bug (actually, I think that the standard says
that 0 should always indicate success, regardless of environment, I
don't have any reference book handy, however; it would mean that VAX C
should translate exit(0) to 1, and vice versa).

I use EXIT_SUCCESS and EXIT_FAILURE, and define them if they aren't
defined by the implementation (not all environments define them).  If an
implementation defines them incorrectly, I would redefine them better,
something like:

	#ifndef EXIT_SUCCESS
	#define DEFINE_EXIT_CODES
	#endif

	#ifdef DEFINE_EXIT_CODES
	#undef EXIT_SUCCESS
	#undef EXIT_FAILURE
	#define EXIT_SUCCESS	0
	#define EXIT_FAILURE	1
	#endif

In a makefile or somewhere, the macro DEFINE_EXIT_CODES would then be
defined for systems that require a redefinition of EXIT_*. I don't think
this should cause any troubles.

I prefer EXIT_SUCCESS and EXIT_FAILURE to MAIN_* (or other similar
macros of my own), since the standard ones are (supposedly) known to all
good C programmers, whereas the MAIN_* would require everyone looking
through the code to check their definition.


-- 
Lars Wirzenius  wirzenius@cc.helsinki.fi

rankin@eql.caltech.edu (Pat Rankin) (05/14/91)

In article <16136@smoke.brl.mil>, gwyn@smoke.brl.mil (Doug Gwyn) writes...
>In article <memo.1010816@lynx.northeastern.edu> cschmidt@lynx.northeastern.edu writes:
>>What value should the standard function MAIN return?
..
>>    [end] with the line "return EXIT_SUCCESS".  The problem with this is
>>    that EXIT_SUCCESS is zero, even in the VAX version, and when a VMS
>>    program terminates and returns zero to VMS, VMS displays the
>>    system message for status code zero.
> 
> If your VMS C compiler really has this bug, get the vendor to fix it.
> The DEC representative to X3J11 agreed than VMS C would map a 0 exit
> status value to SYS$SUCCESS (an odd number, probably 1) before
> handing in back to the invoking environment.  The EXIT_* macros were
> introduced primarily as a political compromise to accommodate VMS C.

     The run-time library routine ``exit()'' does convert 0 to a successful
status (SS$_NORMAL :-).  However, the compiler--which does not claim to be
ANSI compliant yet--does not do the same conversion for ``return'' from
main().  Needless to say, having main's return differ from from exit is non-
conforming.

     <stdlib.h> defines EXIT_SUCCESS as 0, which is a problem considering
the compiler's failure to fixup the final return value.  Since a new
compiler release came out a couple of months ago and didn't fix this
problem, it may be around for a while...

     I suggest the following work-around:
#include <stdlib.h>
#ifdef VMS
# include <ssdef.h>
# include <stsdef.h>
# undef EXIT_SUCCESS
# define EXIT_SUCCESS SS$_NORMAL
# undef EXIT_FAILURE
# define EXIT_FAILURE (SS$_ABORT | STS$M_INHIB_MSG)
#else
# ifndef EXIT_SUCCESS
#  define EXIT_SUCCESS 0
# endif
# ifndef EXIT_FAILURE
#  define EXIT_FAILURE 1
# endif
#endif

     You can hard code 1 and 0x1000002C instead of the SS$_ values if you
don't want to #include those VMS-specific headers.  You can omit the #undefs
for VAXC, but GNUC will issue warnings without them.  (The VMS port of gcc
doesn't fixup the value returned from main() [yet?] either.  As a matter of
fact, the latest release still doesn't even have <stdlib.h> available, even
though it predefines __STDC__ as 1 by default.)

     One thing to note is that main() is called directly from the "image
activator" portion of the command interpretor.  The equivalent of crt0 is
inserted by the compiler prior to the first executable code within main
itself rather than linked as something which calls main, so it isn't around
to receive and post-process the final value returned by main.  The problem
should be pretty easy to solve though.

		Pat Rankin, rankin@eql.caltech.edu

adrian@mti.mti.com (Adrian McCarthy) (05/14/91)

In article <1991May13.091939.9042@klaava.Helsinki.FI> wirzeniu@kruuna.Helsinki.FI (Lars Wirzenius) writes:
>In article <memo.1010816@lynx.northeastern.edu> cschmidt@lynx.northeastern.edu writes:
>>What value should the standard function MAIN return?  I ran into this
>>question when porting some programs from DOS to VMS.  Alternatives:
>>
>>1. [void main(), no exit code]
>>2. [void main(), exit(EXIT_SUCCESS)]
>>3. [int main(), return EXIT_SUCCESS]
>>4. [int main(), return MAIN_SUCCESS]
>>[EXIT_SUCCESS == 0 causes problems in VMS]
>
>According to the standard ...

First of all, VAX C does not claim to be standard.  Fortunately, however,
many of its behaviors do conform to the standard.

>If it is true that the VMS C compiler defines EXIT_SUCCESS as 0, and the
>operating systems interprets that as failure,

But EXIT_SUCCESS wasn't defined for use by the environment.  It was defined
for use with exit().

> then I would think that
>the VMS C compiler has a bug (actually, I think that the standard says
>that 0 should always indicate success, regardless of environment, I
>don't have any reference book handy, however; it would mean that VAX C
>should translate exit(0) to 1, and vice versa).

VAX C does map exit(0) to SS$_NORMAL (1).  But if you look over that list
of alternatives, this (working) solution was omitted:

5.  [int main(), exit(EXIT_SUCCESS)]

This is both portable and ANSI compliant.  It is unecessary to redefine
EXIT_SUCCESS.  EXIT_SUCCESS and EXIT_FAILURE are defined solely for use
with the exit() function (that's why these symbols are prefixed with EXIT_).

Now K&R 2 does contain the provacative statement:  ``Within main,
return expr is equivalent to exit(expr).'' [p. 164]  So *if* VAX C were
compliant, we would expect it to treat the return from main() as a special
case, doing all the same mappings.  Currently it does not do that.

Aid.

rjohnson@shell.com (Roy Johnson) (05/21/91)

In article <memo.1010816@lynx.northeastern.edu> cschmidt@lynx.northeastern.edu writes:
   What value should the standard function MAIN return?  I ran into this
   question when porting some programs from DOS to VMS.  Alternatives:

   1.  [...]
   2.  Declare the MAIN return type as VOID and terminate the function
       with the line "exit (EXIT_SUCCESS)".  The problem with this is
       that the VAX C compiler displays an error message (warning level)
       when the return type of the function MAIN is VOID.

How about declaring MAIN to return type INT, and terminate the function
with
  exit(EXIT_SUCCESS);
  return 0;

The return value of 0 will never be reached, but the compiler will
not complain, and you'll always get success.

   [3.  ... 4. ...]

   I expect many experienced C programmers will be surprised to learn
   that it is impossible to write a portable, lint-free "hello world"
   program in C that compiles and links without errors.

Actually, it is possible; it's just that the interpretation of the
return value is up to the platform.
--
=============== !You!can't!get!here!from!there!rjohnson ===============
Feel free to correct me, but don't preface your correction with "BZZT!"
Roy Johnson, Shell Development Company

cschmidt@lynx.northeastern.edu (06/07/91)

Thanks to all who posted or mailed replies to my question about the
"main" function.  Sorry for being so tardy in posting this summary.

The question was, what normal (ie non-error) value should main return
in an ANSI C program?  The answer is implied by the following two
rules about ANSI C.  I am grateful to those who pointed out these
rules.  Eventually, I found these rules on page 106 in the book
"Standard C" by Plauger and Brodie.

(1) The main function should be declared as returning int.

(2) The statement "return x;" in the body of main is equivalent to
    "exit (x);".

This then is the correct form:

    #include <stdlib.h>     /* defines EXIT_SUCCESS */
    int main (...)
    { ... return EXIT_SUCCESS; }

This issue arose when I was porting some programs to VAX C, which it
turns out is not ANSI.  VAX C violates rule (2) above.  Thanks to
those of you who suggested workarounds.

It is almost always a programming error when a function declared as
returning a value has no "return" statement.  Such a function is not
what I would call lint-free.

Christopher Schmidt
cschmidt@lynx.northeastern.edu