Topic: Why int main()?


Author: poenitz@gmx.net (=?iso-8859-1?Q?Andr=E9_P=F6nitz?=)
Date: Wed, 7 May 2003 17:54:18 +0000 (UTC)
Raw View
James Kanze <kanze@gabi-soft.de> wrote:
>> The fact that it "happens to work OK" is not a compelling reason to
>> codify the bad practice.
>
> What's bad about it (except the formal issues)?  Most of my programs
> never return.

I think the only reason to insist on 'int main' is to have a means to
distinguish definitely bad books from possibly not so bad ones at a glance.

If an author writes 'void main()' it is not to expected that he pays much
attention on less obvious but more important details of the language.

If, OTOH, he writes 'int main()' he might be sufficiently pedantic and/or
lucky to get the rest of his book right ;-)

Andre'

--
Those who desire to give up Freedom in order to gain Security, will not have,
nor do they deserve, either one.     (T. Jefferson or B. Franklin or both...)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Tue, 29 Apr 2003 05:54:53 +0000 (UTC)
Raw View
ron@sensor.com ("Ron Natalie") wrote in message
news:<uKeqa.21$7j1.6@fe02.atl2.webusenet.com>...
> "James Kanze" <kanze@gabi-soft.de> wrote in message
> news:d6651fb6.0304250502.36818e4d@posting.google.com...

> > You mean, dynamically change the return type of a function at
> > run-time? We could do that to, I suppose, but I don't think that the
> > results should be called C or C++. (Maybe lisp?)

> No, I thought you were asking that the programmer be able to define an
> arbitrary main return type (at compile time).

Not that the programmer could definite it.  What could the system
possibly do with a MyClass if I decide to return that.

The only thing I don't see is why given that we allow the implementation
to define additional signatures for main, we insist that these
additional, non-standard signatures have the return type int.

> > What's bad, then, is the same thing that is bad whenever you use an
> > implementation defined extension on a system which doesn't define
> > it. How is this any different than using:

> Who's talking about implentation defined extension?

I thought we were.

> I think the thread got lost at some point.

My impression as well.

> I thought we were talking about required main signatures. Frankly,
> there really ought to only be one (int main(int, char**)). The only
> reason C90 supported otherwise (and now we're stuck with it), is that
> most (UNIX) existing implmenetations just happened to do the right
> thing if you under declared the actual number of arguments.

Totally agreed.

I have no particular problem for allowing the implementation to define
additional signatures.  I don't see a particular need for it, but again,
for historical reasons, we're probably stuck with at least allowing:

    int main( int, char**, char** )

And if we allow additional, implementation defined signatures, I find
really only two defensible positions:

  - an implementation may add additional arguments after the two in the
    required signature, or

  - an implementation can pretty much do whatever it wants.

We're somewhere between the two positions; something like:
    int main( char*, double )
is a legal extension, but
    void main( int, char** )
isn't.  And I'll admit that I find THAT fairly arbitrary.

> The more you require gunking up the main's function type, the more you
> make it difficult for further implementations who don't use a
> subroutine linkage compatible with assumptions made for PDP-11's.

> > BTW: do you (or anyone else, for that matter) actually know of a
> > machine where misdeclaring an int return type as void will cause
> > problems if the function doesn't return. I know that there are
> > frequently differences between int and a struct (often, if the
> > return type is a struct, the compiler will pass a hidden first
> > parameter to the address of memory where it should be returned), but
> > I've never actually heard of a machine that didn't return an int in
> > a register.

> Nope, but do you want to preclude this? You were the one who wanted to
> wide the type.

Me.  I didn't want anything.  The only signature I ever use (regardless
of what the implementation supports) is "int main( int, char** )".
Logically, I would argue that 1) it would perhaps be better if the
implementation could define the return type (and the parameter type for
exit), and the only guaranteed legal values were EXIT_SUCCESS and
EXIT_FAILURE, and 2) IF we allow additional implementation defined
signatures (and we do), there is really no reason to restrict the return
type of THEM.

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: K.Hagan@thermoteknix.co.uk ("Ken Hagan")
Date: Tue, 29 Apr 2003 17:18:45 +0000 (UTC)
Raw View
James Kanze wrote:
>
> Me.  I didn't want anything.  The only signature I ever use
> (regardless of what the implementation supports) is "int main( int,
> char** )". Logically, I would argue that 1) it would perhaps be
> better if the implementation could define the return type (and the
> parameter type for exit), and the only guaranteed legal values were
> EXIT_SUCCESS and EXIT_FAILURE, and 2) IF we allow additional
> implementation defined signatures (and we do), there is really no
> reason to restrict the return type of THEM.

For (1), surely the logical signature is

    bool main(/*your args here*/)

and if in future we go for "process lives until last thread exits"
then the logical return type for main() is void, with exit() being
the only sensible way to return a failure code to the OS. (For
thread "return values" it is a SMOP to leave arbitrary amounts of
information lying around where other threads can pick it up. I
see no merit in forcing anyone to pass that information through
the thread's startup routine.)

But, like you, I'm not campaigning for anything here. The current
rules force me to write an extra line of code. I can live with that.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: terekhov@web.de (Alexander Terekhov)
Date: Tue, 29 Apr 2003 17:19:11 +0000 (UTC)
Raw View
James Kanze wrote:
[...]
> > No, I thought you were asking that the programmer be able to define an
> > arbitrary main return type (at compile time).

That was me.

>
> Not that the programmer could definite it.  What could the system
> possibly do with a MyClass if I decide to return that.

"The system" would simply terminate the initial/main thread.
Other thread(s) could presumably do something with a MyClass
object... after joining with the initial/main thread.

#include <thread>
#include <string>
#include <iostream>

typedef std::joinable_thread_ptr<std::string> main_thread_ptr;

void f(main_thread_ptr mtp) {
  main_thread_ptr::join_t result = mtp->cancel().join();
  const char * msg = std::thread_canceled(result) ?
        "canceled" : result->c_str();
  std::cout << msg << std::endl;
}

std::string main() {
  std::new_thread(&f, main_thread_ptr(std::thread_self()));
  std::thread_testcancel();
  std::thread_exit(std::string("hello world"));
  // Never reach here
  return "";
}

regards,
alexander.

--
"If the } that terminates a function is reached, and the
 value of the function call is used by the caller, the
 behavior is undefined."
                                    -- ISO/IEC 9899:1999

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Fri, 25 Apr 2003 19:25:33 +0000 (UTC)
Raw View
"James Kanze" <kanze@gabi-soft.de> wrote in message news:d6651fb6.0304250502.36818e4d@posting.google.com...

>
> You mean, dynamically change the return type of a function at run-time?
> We could do that to, I suppose, but I don't think that the results
> should be called C or C++.  (Maybe lisp?)

No, I thought you were asking that the programmer be able to define
an arbitrary main return type (at compile time).

> What's bad, then, is the same thing that is bad whenever you use an
> implementation defined extension on a system which doesn't define it.
> How is this any different than using:

Who's talking about implentation defined extension?    I think the
thread got lost at some point.   I thought we were talking about
required main signatures.   Frankly, there really ought to only be
one  (int main(int, char**)).   The only reason C90 supported
otherwise (and now we're stuck with it), is that most (UNIX)
existing implmenetations just happened to do the right thing
if you under declared the actual number of arguments.

The more you require gunking up the main's function type, the more you make
it difficult for further implementations who don't use a subroutine linkage
compatible with assumptions made for PDP-11's.

> BTW: do you (or anyone else, for that matter) actually know of a machine
> where misdeclaring an int return type as void will cause problems if the
> function doesn't return.  I know that there are frequently differences
> between int and a struct (often, if the return type is a struct, the
> compiler will pass a hidden first parameter to the address of memory
> where it should be returned), but I've never actually heard of a machine
> that didn't return an int in a register.

Nope, but do you want to preclude this?  You were the one who wanted to
wide the type.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Mon, 28 Apr 2003 03:10:18 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> The only question is what restrictions should be imposed on
> implementation defined additional versions.  And my opinion is that
> since they are implementation defined anyway, there is no reason for any
> restrictions.  If an implementation wants to add a:
>     double main( char*, float )
> why not?

It is already permitted for an implementation to accept a char* and
float. 3.6.1/2:
    An implementation shall not predefine the main function. This
    function shall not be overloaded. It shall have a return type
    of int, but otherwise its type is implementation-defined. All
    implementations shall allow both of the following definitions
    of main:
        int main() { /* ... */ }
    and
        int main(int argc, char*argv[]) { /* ... */ }

As for returning double instead of int -- consider 1.1/1:

    This International Standard specifies requirements for
    implementations of the C++ programming language. The first such
    requirement is that they implement the language, and so this
    International Standard also defines C++.

That, along with the definition of undefined behavior, allows the
compiler to do anything it wants with programs that are not compliant.
In other words -- a program which uses "double main(char*,float)" does
not comply with the C++ standard, and so it is not portable, but
there's no reason that individual implementations can't accept it.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 24 Apr 2003 20:50:10 +0000 (UTC)
Raw View
ron@sensor.com ("Ron Natalie") wrote
> "James Kanze" <kanze@gabi-soft.de> wrote
> > What needs to be added to the compiler?  All I see here is a typedef of
> > main_t, in some header file.
>
> I thought you were asking for the program to be able to change it.

That's certainly not what I understood this to mean. (Since the
run-time system would be compiled before your definition, I can't
imagine this working properly anyway.)

All I meant was, this is how we allow implementation-defined return
types to work with standard programs. Just as the implementation can
use any reasonable integer type for size_t, it could do the same thing
for main_t.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 24 Apr 2003 20:55:24 +0000 (UTC)
Raw View
a9804814@unet.univie.ac.at (Thomas Mang)
> A point against "void main()":
> It violates the overloading rules because we'd have then 2
> functions differing only in the return type.

3.6.1/2 ... the main function... shall not be overloaded.

> OTOH, main is special anyways, why not make it special regarding this too,
> since there is hardly an ambiguity to expect in practice........

Can you imagine what would happen if a program had two global functions
named main()?
    int main()            { std::cout << "Version 1" << endl; }
    int main(int, char**) { std::cout << "Version 2" << endl; }

If the implementation manages different signatures for main by using
the assembly-language concept called "weak references", then it will
end up calling whichever version of main that the start-up code
happens to check first. (Or maybe it calls BOTH of them, one after
the other!) If it uses some other technique, maybe it gets a linker
error. Otherwise I have no idea what to expect -- no, not a clue.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Fri, 25 Apr 2003 18:03:45 +0000 (UTC)
Raw View
ron@sensor.com ("Ron Natalie") wrote in message
news:<KJHpa.105$b9.92@fe02.atl2.webusenet.com>...
> "Thomas Mang" <a9804814@unet.univie.ac.at> wrote in message
> news:3EA7067C.BD7A6968@unet.univie.ac.at...

> > A point against "void main()":

> > It violates the overloading rules because we'd have then 2 functions
> > differing only in the return type.

The present situation is that we have one function differing in number
of parameters.  Might as well go all out, and let it differ in
everything:-).

> > OTOH, main is special anyways, why not make it special regarding
> > this too, since there is hardly an ambiguity to expect in
> > practice........

> Main is sort of reverse overloaded anyhow.

Underloaded?

Practically speaking, in a language with more or less strict static
type checking, there should be one, and only one, legal definition for
main, say:

    main_t main( int argc, char const* const* argv )

Anything else would be illegal.

For historical reasons, we don't have that luxury.  An implementation
must support at least two versions, the return type of those two
versions must be int, and an integral value of 0 as the return value
must be interpreted as successful completion.  The first condition is
awkward at best, and IMHO the last two are unnecessarily restrictive.
But it's too late for that now.

The only question is what restrictions should be imposed on
implementation defined additional versions.  And my opinion is that
since they are implementation defined anyway, there is no reason for any
restrictions.  If an implementation wants to add a:
    double main( char*, float )
why not?

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Fri, 25 Apr 2003 18:03:48 +0000 (UTC)
Raw View
ron@sensor.com ("Ron Natalie") wrote in message
news:<Rgzpa.11953$o21.3965@fe02.atl2.webusenet.com>...
> "James Kanze" <kanze@gabi-soft.de> wrote in message
> news:d6651fb6.0304230831.57a6e4f6@posting.google.com...

> > What needs to be added to the compiler?  All I see here is a typedef
> > of main_t, in some header file.

> I thought you were asking for the program to be able to change it.

You mean, dynamically change the return type of a function at run-time?
We could do that to, I suppose, but I don't think that the results
should be called C or C++.  (Maybe lisp?)

> > > void main has never been legal in C or C++.

> > I'd have to look that up in my K&R.  C90 didn't explicitly ban it,
> > however.

> You won't find the word void anywhere in K&R.

True.  The standard way to implement a "void" function was to not
specify a return value, but formally speaking, that meant that the
function returned an int.

> Void didn't show up in C until about 1978 or so.  Your understanding
> of C90 is wrong.  C90 is even more restrictive than C++.  It requires
> the hosted environment to do int main(void) and int main(int,
> char*[]), with no option for other definition.

The only copy of the standard I have handy is the one for C99; my copy
of the C90 standard is at home, and I am at the office.  But I'm fairly
sure that this is one place where there wasn't a change, and the C99
standard very explicitly allows other forms.  And I can explicitly
remember this being the case in C90 as well.

> > > The fact that it "happens to work OK" is not a compelling reason
> > > to codify the bad practice.

> > What's bad about it (except the formal issues)?  Most of my programs
> > never return.

> What's bad is what happens if you are on a machine where mismatching
> void and int returns is not benign.

What's bad, then, is the same thing that is bad whenever you use an
implementation defined extension on a system which doesn't define it.
How is this any different than using:

    int main( int argc, char** argv, char** env )

on a system which doesn't support it?  It is quite clear that anything
BUT the two forms specified in the standard are in the realm of system
specific extensions.

BTW: do you (or anyone else, for that matter) actually know of a machine
where misdeclaring an int return type as void will cause problems if the
function doesn't return.  I know that there are frequently differences
between int and a struct (often, if the return type is a struct, the
compiler will pass a hidden first parameter to the address of memory
where it should be returned), but I've never actually heard of a machine
that didn't return an int in a register.

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 16 Apr 2003 19:27:43 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote
[re main() returning int]
>   - Why int?  That's what Unix and MS-DOS used, but it certainly isn't
>     universal.  The logical solution would have been an implementation
>     defined type, main_t with only the return of the macros EXIT_SUCCESS
>     and EXIT_FAILURE guaranteed by the standard.  That would have broken
>     a lot of existing programs, however.

Would it?

Suppose we insist that either main_t is a typedef for int, or else it
is convertible from int. Most programs would need only one trivial
change in order to be compatible; furthermore, on existing platforms,
the code would continue to function properly until this change was made.

>   - Why not allow void?  Either define falling off the end of a void
>     main as equivalent to return EXIT_SUCCESS from a non-void main, or
>     say that any return value is undefined (which is what actually
>     happens in most implementations today).  Or say that returning from
>     a void main is illegal (undefined behavior) -- generally, when
>     people write void main, it is because they don't return, either
>     because the program consists of an endless loop, or because they
>     always call exit.

That hasn't been my experience. Most of the uses of "void main" that
I've seen have been in textbooks! (Probably because I attack the
practice whenever I see it.) Saying that "void main" indicates that
the program never intends to exit is quite logical, but it doesn't
match existing practice very well.

I've been a strong proponent of ignoring void main, even when the
local platform supports it -- but my impression is that a LOT of
people routinely use it, without even realizing it's wrong. Which
makes me think that maybe we should support it after all. The C++
standard is supposed to document existing practice, yes?

Perhaps we should recognize any of these signatures:
    int main(int, char**);
    int main();
    void main();

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 16 Apr 2003 19:50:58 +0000 (UTC)
Raw View
> > terekhov@web.de (Alexander Terekhov) wrote
> > > In the next round, I'd probably try to make {thread::}main's return
> > > type "application-chosen" -- other thread(s) (if any) could then join
> > > and obtain whatever-return-value (if it's not void)... and adopt a
> > > rather simple POSIX behavior of "passive exit" on last thread
> > > termination. Oder? ;-)

> Allan W wrote:
> > That's assuming a lot.

terekhov@web.de (Alexander Terekhov) wrote
> Let's see...

> > Let's assume that every conforming C++ compiler will have to support
> > threads (a huge assumption!).
>
> Every conforming C++ implementation ALREADY supports "threads" -- one
> thread per C++ program... or more than one... if it supports MULTIPLE
> threads per C++ program.

First, picking on nits of ambiguous language doesn't really clarify
the issue or advance the discussion in any meaningful way. Furthermore,
the word "threads" is plural...

Second, it's not even true. Look in the existing C++ standard for the
word "thread." You'll find it exactly once -- in 15.1/2 [except.throw],
in the phrase "thread of control," where it talks about exception
handlers. Clearly not a "thread" in the sense that you originally used it.

> >                               Let's further assume that when one thread
> > terminates, some other thread (at least the one that spawned it in the
> > first place) is able to get the "return value," no matter how large
> > that might be.
> >
> > You're still making two even bigger assumptions.
> > 1) The process will live as long as *ANY* thread does. As opposed to,
> >    "the process will live as long as the FIRST thread does."
>
> That's not the way how things {currently ;-)} work out there.

Which is exactly my point. At least on some OS's (Microsoft Windows),
the initial thread is the "main" thread; when it exits, the program
terminates. But you said " 'passive exit' on last thread termination"
(quoted above) which is something else entirely.

> > 2) Returning class data from the MAIN thread makes sense.
>
> Threads don't return "class data". Thread routines COULD "return"
> something (thread-exit "returns" including). Joinable [non-detached]
> threads allow to retrieve those objects. In C++, "manual detach"
> doesn't make much sense because it can be done "automatically" using
> smart thread-object pointers. Just like you can ignore any function
> return you'd be able to ignore any thread routine return. Again,
> nothing special here as well.

The discussion was about return values from main(). Where are you
going with this?

> >    But what happens if the program has only one thread, and it returns
> >    data of type customer? What will the OS do with a customer?
>
> The implementation will do nothing special other than destroying "a
> customer" object.

Two problems with this.

First, you're suggesting that the return data is ignored. Why bother
returning data if it's going to be ignored? The current int value seems
more than sufficient -- precisely because it is NOT ignored on some OS's.

Second, think about the technical complications. You said that the
OS would destroy the customer object. Does that mean it runs the
destructor? The rest of the program has shut down, and all other
objects have been destroyed... what does it mean to destroy an object
when the rest of the run-time system has closed?

> >    The OS needs to know if the program ran successfully
>
> That's what "passive exit" on last thread termination is all about.

But doesn't this break all existing programs?

> >                                                          or not; if not,
> >    it might need some indication of generally what went wrong. This
> >    sounds a lot like the integer scheme currently in use on all Unix
>
> http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-review-l&id=1355
> (Subject: Defect in XBD 3.297 Process Termination)
>
> >    systems, and carefully cloned on almost all other systems (including
> >    the MSDOS-subsystem of all Microsoft Windows platforms).
>
> Thread cleanup aside, "passive exit" already works "just fine" on all
> Microsoft Windows platforms. Well, why don't you simply try it? Hints:
> ExitThread, _endthread, _endthreadex.

But you can't use these on portable programs!

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Wed, 16 Apr 2003 19:51:32 +0000 (UTC)
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote in message news:7f2735a5.0304161119.2d516e7d@posting.google.com...

> Suppose we insist that either main_t is a typedef for int, or else it
> is convertible from int. Most programs would need only one trivial
> change in order to be compatible; furthermore, on existing platforms,
> the code would continue to function properly until this change was made.

Great more godawful changes that make main different than every other
function.   This means more goofy stuff that has to get added to something
that knows it's compiling main and possibly additional linkage overhead
to support this.

> I've been a strong proponent of ignoring void main, even when the
> local platform supports it -- but my impression is that a LOT of
> people routinely use it, without even realizing it's wrong. Which
> makes me think that maybe we should support it after all. The C++
> standard is supposed to document existing practice, yes?

No.  The practice was wrong before, it is wrong now.   The C++ standard
only has a preference for things that were legal before, to avoid making them
illegal.   void main has never been legal in C or C++.   The fact that it
"happens to work OK" is not a compelling reason to codify the bad practice.

>
> Perhaps we should recognize any of these signatures:
>     int main(int, char**);
>     int main();
>     void main();

 The only reason that multiple signatures exist and are codified
in C++ is that early implementations worked fine when you passed unused
arguments.   People got used to not being required to declare argc and argv
if they didn't use them, so the bad practice was standardized.



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: SPAMstephen.howeGUARD@tnsofres.com ("Stephen Howe")
Date: Wed, 16 Apr 2003 21:26:52 +0000 (UTC)
Raw View
> Actually, it's even stupider than that.   It was a SOP for those who
insist
> that Dennis's original "Hello World" program still be valid C (the
stupidity
> is just one carried over from C).   Of course it's particularly stupid
because
> even in C, there is no implicit int anymore, so the program doesn't
compile
> anyway.

Right.

I for one would sanction that main has to have a return statement in the
next standard. There is absolutely _NO_ good reason why main cannot behave
just like other functions if at all possible (I know it is special).
Dropping "off the bottom" of main is appalling and I am amazed that was
retained in the standard when implicit int was removed.

Stephen Howe





---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: algrant@myrealbox.com (Al Grant)
Date: Thu, 17 Apr 2003 17:44:39 +0000 (UTC)
Raw View
SPAMstephen.howeGUARD@tnsofres.com ("Stephen Howe") wrote in message news:<3e9dc9fd$0$4860$ed9e5944@reading.news.pipex.net>...
> I for one would sanction that main has to have a return statement in the
> next standard. There is absolutely _NO_ good reason why main cannot behave
> just like other functions if at all possible (I know it is special).
> Dropping "off the bottom" of main is appalling and I am amazed that was
> retained in the standard when implicit int was removed.

Right, there is no good reason why main cannot behave just like
other functions.  But it is other functions that need fixing.
E.g. consider

   void g(void);
   int f(bool b) { if (b) return 1; g(); }

Should this be legal?  Sure, if g() calls exit(), or longjmp(),
or throws an exception, or goes into an infinite loop.
The committee seem to have tentatively grasped the concept of
"non standard returns" in the context of main without accepting
its utility in general.  Some compilers already provide a
"no return" annotation - evidently useful for the real world,
so why not add it to the language?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: K.Hagan@thermoteknix.co.uk ("Ken Hagan")
Date: Thu, 17 Apr 2003 17:45:03 +0000 (UTC)
Raw View
===================================== MODERATOR'S COMMENT:
 Warning:  platform-specific topic drift.


===================================== END OF MODERATOR'S COMMENT
Allan W wrote:
>
> Which is exactly my point. At least on some OS's (Microsoft Windows),
> the initial thread is the "main" thread; when it exits, the program
> terminates. But you said " 'passive exit' on last thread termination"
> (quoted above) which is something else entirely.

This isn't quite true. Windows will keep a process alive until
all threads exit, unless one of the threads calls ExitProcess().
In practice, the main thread is spawned from a routine that
calls ExitProcess(), but there is nothing to stop either you
or your library vendor calling ExitThread() first.

Supporting passive termination on Windows would therefore be a
trivial modification to the vendor's startup code.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: terekhov@web.de (Alexander Terekhov)
Date: Thu, 17 Apr 2003 17:45:16 +0000 (UTC)
Raw View
Allan W wrote:
[...]
> > > You're still making two even bigger assumptions.
> > > 1) The process will live as long as *ANY* thread does. As opposed to,
> > >    "the process will live as long as the FIRST thread does."
> >
> > That's not the way how things {currently ;-)} work out there.
>
> Which is exactly my point. At least on some OS's (Microsoft Windows),
> the initial thread is the "main" thread; when it exits, the program
> terminates. But you said " 'passive exit' on last thread termination"
> (quoted above) which is something else entirely.

I said: Thread cleanup aside, "passive exit" already works "just fine"
on all Microsoft Windows platforms. I've also asked you to simply try
to exit initial/main thread and see whether it will cause process
termination if the exiting thread isn't the last one.

>
> > > 2) Returning class data from the MAIN thread makes sense.
> >
> > Threads don't return "class data". Thread routines COULD "return"
> > something (thread-exit "returns" including). Joinable [non-detached]
> > threads allow to retrieve those objects. In C++, "manual detach"
> > doesn't make much sense because it can be done "automatically" using
> > smart thread-object pointers. Just like you can ignore any function
> > return you'd be able to ignore any thread routine return. Again,
> > nothing special here as well.
>
> The discussion was about return values from main(). Where are you
> going with this?

See the "examples" that I've posted to this thread. The second thread
can also be joined (you'd need another "joiner" thread, though).

[...]
> > >    The OS needs to know if the program ran successfully
> >
> > That's what "passive exit" on last thread termination is all about.
>
> But doesn't this break all existing programs?

A *change* would break "some" programs, but not all.

http://groups.google.com/groups?selm=pEu_9.187%24_l3.134%40news.cpqcorp.net
-------------------------------------8<------------------------------------
>> > C99:
>> >
>> > "reaching the } that terminates the main function returns a
>> >  value of 0."
>>
>> Interesting. I missed that. Well, it's consistent with the POSIX "passive
>> exit" when the last thread terminates.
>
> I wish they had defined it as "reaching the } that terminates
> the main function shall terminate the initial thread with the
> effect of executing pthread_exit(0)". ;-)

That could be a problem, since POSIX lacks Sun's "daemon thread" attribute.
That is, your change would rely on passive process exit rather than forcing
immediate exit, and some applications would simply cease to exit at all.

At least, for nonthreaded programs, it'd have the same effect as the C99
rule: the main thread is the only one, and its termination results in
passive process termination with the status 0.
-------------------------------------8<------------------------------------

Clearly, it would have to be another/additional "main() family" [preserving
the "old"/current one] in order to NOT break some existing progs.

regards,
alexander.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Thu, 17 Apr 2003 19:16:25 +0000 (UTC)
Raw View
"Al Grant" <algrant@myrealbox.com> wrote in message news:5765b025.0304162335.536cf0ec@posting.google.com...

> The committee seem to have tentatively grasped the concept of
> "non standard returns" in the context of main without accepting
> its utility in general.

You've lost me.   It's already explicitly part of the language.   The standard
says it's undefined behavior to fall off the bottom of a non-void function
OTHER THAN MAIN.  The only thing that needs fixing is the "OTHER THAN
MAIN" exception.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Huw@Tesco.net ("Huw Ford")
Date: Fri, 11 Apr 2003 09:52:12 +0000 (UTC)
Raw View
Why was main defined as returning int?
A lot of my work has been with embedded devices where the program never
returns from main.
For example main would look like this;

int main(int argc,char* argv[])
{
    while(true)
    {
        DoThings();
    };
    return 0;
}

The return value should never be reached and even if main did return there
would be nothing that could be done with the return value.
A lot of compilers will accept "void main()" so why must main return an int?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-ben.hutchings@businesswebsoftware.com (Ben Hutchings)
Date: Fri, 11 Apr 2003 18:49:04 +0000 (UTC)
Raw View
In article <Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net>,
"Huw Ford" wrote:
> Why was main defined as returning int?
> A lot of my work has been with embedded devices where the program never
> returns from main.

Then you're probably working with freestanding implementations, where the
entry point is implementation-defined, so it might not be called main and
might not be expected to return int.  (Section 3.6.1 paragraph 1.)

<snip>
> A lot of compilers will accept "void main()" so why must main return an
> int?

In most environments, a terminating process returns some kind of status
value indicating at least success or failure.  Logically main() should
return a value that becomes this status value.  At least some C compilers
treat main() just like any other function, and their startup code expects
it to return an int.  This could have been changed in C++, since C++
compilers do have to treat main() specially in some respects, but why
change it when a return type of int is logically correct?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmaddox@isicns.com (Randy Maddox)
Date: Fri, 11 Apr 2003 18:49:29 +0000 (UTC)
Raw View
Huw@Tesco.net ("Huw Ford") wrote in message news:<Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net>...
> Why was main defined as returning int?
> A lot of my work has been with embedded devices where the program never
> returns from main.
> For example main would look like this;
>
> int main(int argc,char* argv[])
> {
>     while(true)
>     {
>         DoThings();
>     };
>  return 0;
> }
>
> The return value should never be reached and even if main did return there
> would be nothing that could be done with the return value.
> A lot of compilers will accept "void main()" so why must main return an int?
>

Because that's what the C++ Standard specifies in subclause 3.6.1?

Seriously, although your situation is different, many applications do
need to return a value of some type to the OS to let the user know
whether the program was succesful or had a problem.  Since this is
such a common need a standard way of supplying such a value had to be
specified.  Obviously if every program had its own way of reporting
its termination status there would be no way for that to work
portably.  So the writers of the C++ Standard chose the same behavior
as was already long specified for C programs as the way to provide
this commonly needed functionality.

Compilers that accept void main() are providing a non-standard
extension.  It may work fine for you in a particular case, but it is
not standard behavior and you cannot expect it to be portable.

Randy.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: K.Hagan@thermoteknix.co.uk ("Ken Hagan")
Date: Fri, 11 Apr 2003 18:49:39 +0000 (UTC)
Raw View
"Huw Ford" wrote:
> Why was main defined as returning int?

I'd guess ... because the remit of the original *C* committee was to
standardise existing practice and such practice was overwhelmingly
that of UNIX (and its offshoots such as MS-DOS). The return value is
useful there.

It's probably not a good way to design a language, but it does have
the merit that existing practice is known to work, at least for those
practising it.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Fri, 11 Apr 2003 18:50:03 +0000 (UTC)
Raw View
""Huw Ford"" <Huw@Tesco.net> wrote in message news:Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net...
> Why was main defined as returning int?

Tradition.  There was no void in early implementation, so main returned int
by default.   Later, C was pretty well entrenched in the UNIX concept of the
return value of main being passed back as a program status.

> A lot of my work has been with embedded devices where the program never
> returns from main.

Embedded devices are not required to have any constraints on main (or even to
have a main).

> A lot of compilers will accept "void main()" so why must main return an int?

You are lucky that they do.   The main reason you get away with it is that the
void  and int returns coexist benignly.   But the standard specifically says
main returns int, compilers that do so (without a diagnostic) are technically
incorrect.  Change main to return a class or something large and I suspect
you'd run into a lot more places where it didn't work than where it did.

For a more pragmatic reason, think of it this way.   In C++, both the caller
of the function and the called function definition must have the same type.
Now for most functions, you control both sides, you are free to redefine
the type of your functions.   However, you don't call main.   It is called by
the startup code for you.   You can't just unilaterally change it to what you
want.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Fri, 11 Apr 2003 18:50:42 +0000 (UTC)
Raw View
In article <Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net>, Huw Ford
<Huw@Tesco.net> writes
>A lot of compilers will accept "void main()" so why must main return an int?

Because Standards are about portability. It is easy for a system to
ignore a return value when it does not need one, it is much harder to
create one where it is needed and none has been provided.



--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nospam42@attbi.com ("Chris Putnam")
Date: Fri, 11 Apr 2003 19:49:59 +0000 (UTC)
Raw View
I believe this originated in order for UNIX programs to return an error code
to the process or shell that launched the program.  Among other things, this
allows a shell scripting language (such as CSH or Windows batch files) to
execute code conditionally depending on the result of a previous command.

In my experience, compilers that accept the void main() signature do so by
providing a wrapper function to match whatever signature the OS requires.
For instance, if the OS needs an int main( int argc, char *argv) signature,
the compiler/linker might provide the following wrapper for the OS to call:

int wrapper_main( int argc, char *argv)
{
    main();
    return 0;
}

In this case, the compiler arranges for the OS to call wrapper_main()
instead.

Chris

""Huw Ford"" <Huw@Tesco.net> wrote in message
news:Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net...
> Why was main defined as returning int?
> A lot of my work has been with embedded devices where the program never
> returns from main.
> For example main would look like this;
>
> int main(int argc,char* argv[])
> {
>     while(true)
>     {
>         DoThings();
>     };
>     return 0;
> }
>
> The return value should never be reached and even if main did return there
> would be nothing that could be done with the return value.
> A lot of compilers will accept "void main()" so why must main return an
int?
>
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]
>


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Fri, 11 Apr 2003 20:03:48 +0000 (UTC)
Raw View
""Chris Putnam"" <nospam42@attbi.com> wrote in message news:1050087548.757301@hqnntp01.autodesk.com...

> In my experience, compilers that accept the void main() signature do so by
> providing a wrapper function to match whatever signature the OS requires.

Not in my experience.   In my experience it is because the way the subroutine
linkage works, you can get away with mixing up void and int returns.   Typically
an int return is just a value in one of the general purpose registers so the only
difference is the setting or omitting setting a value in the register.

It's just sheer luck that it works.   Try this:

    struct {
        char x[100];
    } main() {
     }

and see what happens.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Fri, 11 Apr 2003 22:54:02 +0000 (UTC)
Raw View
Francis Glassborow wrote:
> In article <Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net>, Huw Ford
> <Huw@Tesco.net> writes
>
>> A lot of compilers will accept "void main()" so why must main return
>> an int?
>
>
> Because Standards are about portability. It is easy for a system to
> ignore a return value when it does not need one, it is much harder to
> create one where it is needed and none has been provided.

And yet there's a wart in C++ because main is the _only_
function returning int where we do not have to providfe a
return value when the function exits, as a default value
is indeed provided.

Standardising void main() as being the same as int main()
but not allowing an expression after return, and acting
as if it was int main() returning 0, would be quite
possible technically.  It would gain nothing except to
silence the endless discussion of why void main is not
legal.

It's trivial to turn a program with void main into a legal
one: s/void main/int main/.  A saving of one character,
and the code becomes standard C++ (in that aspect at least).

-- James.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jackklein@spamcop.net (Jack Klein)
Date: Sat, 12 Apr 2003 05:10:19 +0000 (UTC)
Raw View
On Fri, 11 Apr 2003 22:54:02 +0000 (UTC), jdennett@acm.org (James
Dennett) wrote in comp.std.c++:

> Francis Glassborow wrote:
> > In article <Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net>, Huw Ford
> > <Huw@Tesco.net> writes
> >
> >> A lot of compilers will accept "void main()" so why must main return
> >> an int?
> >
> >
> > Because Standards are about portability. It is easy for a system to
> > ignore a return value when it does not need one, it is much harder to
> > create one where it is needed and none has been provided.
>
> And yet there's a wart in C++ because main is the _only_
> function returning int where we do not have to providfe a
> return value when the function exits, as a default value
> is indeed provided.

In the opinion of many, myself included, that was a mistake.  It
appears to me to be a sop to those who whined about having to type a
"return 0;".  At that it was better than standardizing "void main()",
and of course there might be other reasons I am not aware of.

Sadly, the C standard has done this as well, with even less
justification, as main() is not unique in C the way it is in C++.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: terekhov@web.de (Alexander Terekhov)
Date: Sun, 13 Apr 2003 03:22:35 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net>, Huw Ford
> <Huw@Tesco.net> writes
> >A lot of compilers will accept "void main()" so why must main return an int?
>
> Because Standards are about portability. ....

In the next round, I'd probably try to make {thread::}main's return
type "application-chosen" -- other thread(s) (if any) could then join
and obtain whatever-return-value (if it's not void)... and adopt a
rather simple POSIX behavior of "passive exit" on last thread
termination. Oder? ;-)

regards,
alexander.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 16 Apr 2003 00:01:10 +0000 (UTC)
Raw View
terekhov@web.de (Alexander Terekhov) wrote
> In the next round, I'd probably try to make {thread::}main's return
> type "application-chosen" -- other thread(s) (if any) could then join
> and obtain whatever-return-value (if it's not void)... and adopt a
> rather simple POSIX behavior of "passive exit" on last thread
> termination. Oder? ;-)

That's assuming a lot.

Let's assume that every conforming C++ compiler will have to support
threads (a huge assumption!). Let's further assume that when one thread
terminates, some other thread (at least the one that spawned it in the
first place) is able to get the "return value," no matter how large
that might be.

You're still making two even bigger assumptions.
1) The process will live as long as *ANY* thread does. As opposed to,
   "the process will live as long as the FIRST thread does." Seems to
   me that some OS's won't support this directly; instead, the runtime
   system will keep control of what the OS calls the main thread, and
   it can spawn a thread to run a main program. The trouble with this
   approach is that ALL programs are now multi-threaded.

2) Returning class data from the MAIN thread makes sense.

   But what happens if the program has only one thread, and it returns
   data of type customer? What will the OS do with a customer?

   The OS needs to know if the program ran successfully or not; if not,
   it might need some indication of generally what went wrong. This
   sounds a lot like the integer scheme currently in use on all Unix
   systems, and carefully cloned on almost all other systems (including
   the MSDOS-subsystem of all Microsoft Windows platforms).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 16 Apr 2003 00:01:37 +0000 (UTC)
Raw View
terekhov@web.de (Alexander Terekhov) wrote in message
news:<3E9821CE.8AC8B8C6@web.de>...
> Francis Glassborow wrote:

> > In article <Qbvla.955$5Z2.28625@newsfep1-win.server.ntli.net>, Huw Ford
> > <Huw@Tesco.net> writes
> > >A lot of compilers will accept "void main()" so why must main
> > >return an int?

> > Because Standards are about portability. ....

> In the next round, I'd probably try to make {thread::}main's return
> type "application-chosen" -- other thread(s) (if any) could then join
> and obtain whatever-return-value (if it's not void)... and adopt a
> rather simple POSIX behavior of "passive exit" on last thread
> termination. Oder? ;-)

Interesting point of view.  There are several interesting points, in
fact:

  - Why int?  That's what Unix and MS-DOS used, but it certainly isn't
    universal.  The logical solution would have been an implementation
    defined type, main_t with only the return of the macros EXIT_SUCCESS
    and EXIT_FAILURE guaranteed by the standard.  That would have broken
    a lot of existing programs, however.

  - Why not allow void?  Either define falling off the end of a void
    main as equivalent to return EXIT_SUCCESS from a non-void main, or
    say that any return value is undefined (which is what actually
    happens in most implementations today).  Or say that returning from
    a void main is illegal (undefined behavior) -- generally, when
    people write void main, it is because they don't return, either
    because the program consists of an endless loop, or because they
    always call exit.

  - And the business of threads introduces additional issues.  Posix
    threads return a void*, for example, and not an int.  Logically, I
    would expect a process to act sort of like a thread in the overall
    system, with a similar sort of return value.  On the other hand,
    existing practice...

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 16 Apr 2003 00:01:47 +0000 (UTC)
Raw View
ron@sensor.com ("Ron Natalie") wrote in message
news:<i1Fla.21842$eo4.9547@fe10.atl2.webusenet.com>...
> ""Chris Putnam"" <nospam42@attbi.com> wrote in message
> news:1050087548.757301@hqnntp01.autodesk.com...

> > In my experience, compilers that accept the void main() signature do
> > so by providing a wrapper function to match whatever signature the
> > OS requires.

> Not in my experience.  In my experience it is because the way the
> subroutine linkage works, you can get away with mixing up void and int
> returns.  Typically an int return is just a value in one of the
> general purpose registers so the only difference is the setting or
> omitting setting a value in the register.

> It's just sheer luck that it works.

That and the fact that compiler writers don't like unnecessarily
breaking user code, even if the code is wrong.

> Try this:

>     struct {
>         char x[100];
>     } main() {
>      }

> and see what happens.

Works on my machine (Sun Sparc, Solaris, gcc 3.2.2 and Sun CC):-).
After I'd modified it so that the type wasn't defined in the return
value, of course.

With gcc, I had to compile it as C.  G++ won't accept a return type
other than int.  (Sun CC warns about an anachronism.  I don't know when
they thought this was legal.)

If I add a return statement with a value, it core dumps.  And I suspect
that on Intel processors, trying to use argc and argv in main will get
you into trouble as well.  But your example works.  (I know what you
were trying to say, and agree 100%.  It's just that just saying try this
is a dangerous way to point it out, unless you're sure that it will fail
on all implementations.)

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Wed, 16 Apr 2003 00:02:43 +0000 (UTC)
Raw View
"Jack Klein" <jackklein@spamcop.net> wrote in message news:9k6f9vkh1959gdaln74lutrdbv9kr9rq0c@4ax.com...

> In the opinion of many, myself included, that was a mistake.  It
> appears to me to be a sop to those who whined about having to type a
> "return 0;".  At that it was better than standardizing "void main()",
> and of course there might be other reasons I am not aware of.
>
Actually, it's even stupider than that.   It was a SOP for those who insist
that Dennis's original "Hello World" program still be valid C (the stupidity
is just one carried over from C).   Of course it's particularly stupid because
even in C, there is no implicit int anymore, so the program doesn't compile
anyway.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Wed, 16 Apr 2003 00:02:48 +0000 (UTC)
Raw View
"Alexander Terekhov" <terekhov@web.de> wrote in message news:3E9821CE.8AC8B8C6@web.de...
\
>
> In the next round, I'd probably try to make {thread::}main's return
> type "application-chosen" -- other thread(s) (if any) could then join
> and obtain whatever-return-value (if it's not void)... and adopt a
> rather simple POSIX behavior of "passive exit" on last thread
> termination. Oder? ;-)
>
How is the application supposed to chose.   Ask yourself, who
calls main?   It's not normally anything that's under the application
control.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: terekhov@web.de (Alexander Terekhov)
Date: Wed, 16 Apr 2003 14:10:58 +0000 (UTC)
Raw View
< c.p.t. added >

Ron Natalie wrote:
>
> "Alexander Terekhov" <terekhov@web.de> wrote in message news:3E9821CE.8AC8B8C6@web.de...
> \
> >
> > In the next round, I'd probably try to make {thread::}main's return
> > type "application-chosen" -- other thread(s) (if any) could then join
> > and obtain whatever-return-value (if it's not void)... and adopt a
> > rather simple POSIX behavior of "passive exit" on last thread
> > termination. Oder? ;-)
> >
> How is the application supposed to chose.   Ask yourself, who
> calls main?   It's not normally anything that's under the application
> control.

The implementation calls main(). As for "application control"...

<dreams on>

#include <thread>
#include <iostream>

typedef std::joinable_thread_ptr<const char *> main_thread_ptr;

void f(main_thread_ptr mtp) {
  main_thread_ptr::join_t result = mtp->cancel().join();
  const char * msg = std::thread_canceled(result) ? "canceled" : *result;
  std::cout << msg << std::endl;
}

const char * main() {
  std::new_thread(&f, main_thread_ptr(std::thread_self()));
  std::thread_testcancel();
  return "hello world";
}

<dreams off>

-or- (status checking [and "old" C-style casts] aside for a moment...)

#include <cthread>  // that's WG21-"controlled" <pthread.h>-"copy" ;-)
#include <iostream>
using namespace std;

extern "C" void * f(void * p) {
  void * result;
  pthread_t * pmain_tid = (pthread_t *)p;
  pthread_cancel(*pmain_tid);
  pthread_join(*pmain_tid, &result);
  delete pmain_tid;
  const char * msg = PTHREAD_CANCELED == result ?
    "canceled" : (const char *)result;
  cout << msg << endl;
  return 0;
}

int main() {
  pthread_t * pmain_tid = new pthread_t(pthread_self()), tid;
  pthread_create(&tid, 0, &f, pmain_tid);
  pthread_testcancel();
  pthread_exit((void*)"hello world");
}

regards,
alexander.

--
http://tinyurl.com/9n1v
(Subject: Re: Next revision of boost::thread)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: terekhov@web.de (Alexander Terekhov)
Date: Wed, 16 Apr 2003 14:11:45 +0000 (UTC)
Raw View
Allan W wrote:
>
> terekhov@web.de (Alexander Terekhov) wrote
> > In the next round, I'd probably try to make {thread::}main's return
> > type "application-chosen" -- other thread(s) (if any) could then join
> > and obtain whatever-return-value (if it's not void)... and adopt a
> > rather simple POSIX behavior of "passive exit" on last thread
> > termination. Oder? ;-)
>
> That's assuming a lot.

Let's see...

>
> Let's assume that every conforming C++ compiler will have to support
> threads (a huge assumption!).

Every conforming C++ implementation ALREADY supports "threads" -- one
thread per C++ program... or more than one... if it supports MULTIPLE
threads per C++ program.

>                               Let's further assume that when one thread
> terminates, some other thread (at least the one that spawned it in the
> first place) is able to get the "return value," no matter how large
> that might be.
>
> You're still making two even bigger assumptions.
> 1) The process will live as long as *ANY* thread does. As opposed to,
>    "the process will live as long as the FIRST thread does."

That's not the way how things {currently ;-)} work out there.

>                                                              Seems to
>    me that some OS's won't support this directly;

Do you know some OS that doesn't "support this directly"? I don't.

>                                                   instead, the runtime
>    system will keep control of what the OS calls the main thread,

Main THREAD is nothing special. main() FUNCTION INVOCATION [which
is done by the implementation] is kinda-special... because instead
of doing

       pthread_exit(main(/*...*/));

C/C++ implementations are required to do

       exit(main(/*...*/));

That's it [the difference between C and C++ mains aside for a moment].

>                                                                   and
>    it can spawn a thread to run a main program. The trouble with this
>    approach is that ALL programs are now multi-threaded.

Nope.

In [non-"braindamged" C++], pthread_exit() and cancel delivery shall
result in nothing "special"(*) other than raising some {standard}
exception. You don't really need multiple threads to have pthread_exit
[thread exit] and thread cancelation. You do need multiple threads
to join something, however.

>
> 2) Returning class data from the MAIN thread makes sense.

Threads don't return "class data". Thread routines COULD "return"
something (thread-exit "returns" including). Joinable [non-detached]
threads allow to retrieve those objects. In C++, "manual detach"
doesn't make much sense because it can be done "automatically" using
smart thread-object pointers. Just like you can ignore any function
return you'd be able to ignore any thread routine return. Again,
nothing special here as well.

>
>    But what happens if the program has only one thread, and it returns
>    data of type customer? What will the OS do with a customer?

The implementation will do nothing special other than destroying "a
customer" object.

>
>    The OS needs to know if the program ran successfully

That's what "passive exit" on last thread termination is all about.

>                                                          or not; if not,
>    it might need some indication of generally what went wrong. This
>    sounds a lot like the integer scheme currently in use on all Unix

http://www.opengroup.org/sophocles/show_mail.tpl?source=L&listname=austin-review-l&id=1355
(Subject: Defect in XBD 3.297 Process Termination)

>    systems, and carefully cloned on almost all other systems (including
>    the MSDOS-subsystem of all Microsoft Windows platforms).

Thread cleanup aside, "passive exit" already works "just fine" on all
Microsoft Windows platforms. Well, why don't you simply try it? Hints:
ExitThread, _endthread, _endthreadex.

regards,
alexander.

(*) utterly silly "forced unwinding" aside for a moment.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 23 Apr 2003 16:37:59 +0000 (UTC)
Raw View
algrant@myrealbox.com (Al Grant) wrote in message
news:<5765b025.0304162335.536cf0ec@posting.google.com>...
> SPAMstephen.howeGUARD@tnsofres.com ("Stephen Howe") wrote in message
> news:<3e9dc9fd$0$4860$ed9e5944@reading.news.pipex.net>...
> > I for one would sanction that main has to have a return statement in
> > the next standard. There is absolutely _NO_ good reason why main
> > cannot behave just like other functions if at all possible (I know
> > it is special).  Dropping "off the bottom" of main is appalling and
> > I am amazed that was retained in the standard when implicit int was
> > removed.

> Right, there is no good reason why main cannot behave just like other
> functions.  But it is other functions that need fixing.  E.g. consider

>    void g(void);
>    int f(bool b) { if (b) return 1; g(); }

> Should this be legal?

It is legal, so the question should be: do we want to make it illegal.

> Sure, if g() calls exit(), or longjmp(), or throws an exception, or
> goes into an infinite loop.

For a more telling example, you should use a return which isn't int.
It's trivial to insert a return 0.  But what do you do if the return
value is a user type which has no trivial constructors, and you have
nothing with which to call the constructors?

> The committee seem to have tentatively grasped the concept of "non
> standard returns" in the context of main without accepting its utility
> in general.

I'm not sure what the committee had in mind when they made the special
rules for int, but 1) the rules can't easily be extended to functions
returning user defined types, and 2) they don't change anything in the
case of functions where you don't fall off the end.  I don't see any
need for the exception.

> Some compilers already provide a "no return" annotation - evidently
> useful for the real world, so why not add it to the language?

To solve what problem?

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.de (James Kanze)
Date: Wed, 23 Apr 2003 16:38:10 +0000 (UTC)
Raw View
ron@sensor.com ("Ron Natalie") wrote in message
news:<Lbina.6887$Y57.3348@fe05.atl2.webusenet.com>...
> "Allan W" <allan_w@my-dejanews.com> wrote in message
> news:7f2735a5.0304161119.2d516e7d@posting.google.com...
> > Suppose we insist that either main_t is a typedef for int, or else
> > it is convertible from int. Most programs would need only one
> > trivial change in order to be compatible; furthermore, on existing
> > platforms, the code would continue to function properly until this
> > change was made.

> Great more godawful changes that make main different than every other
> function.  This means more goofy stuff that has to get added to
> something that knows it's compiling main and possibly additional
> linkage overhead to support this.

What needs to be added to the compiler?  All I see here is a typedef of
main_t, in some header file.

> > I've been a strong proponent of ignoring void main, even when the
> > local platform supports it -- but my impression is that a LOT of
> > people routinely use it, without even realizing it's wrong. Which
> > makes me think that maybe we should support it after all. The C++
> > standard is supposed to document existing practice, yes?

> No.  The practice was wrong before, it is wrong now.  The C++ standard
> only has a preference for things that were legal before, to avoid
> making them illegal.

Before the C standard, anything a compiler implementor wanted to do was
legal:-).  (On the other hand, this void main business seems to be a
recent phenomena.  I can't recall seeing any void main in the days when
I was learning C.)

> void main has never been legal in C or C++.

I'd have to look that up in my K&R.  C90 didn't explicitly ban it,
however.

> The fact that it "happens to work OK" is not a compelling reason to
> codify the bad practice.

What's bad about it (except the formal issues)?  Most of my programs
never return.

> > Perhaps we should recognize any of these signatures:
> >     int main(int, char**);
> >     int main();
> >     void main();

>  The only reason that multiple signatures exist and are codified in
> C++ is that early implementations worked fine when you passed unused
> arguments.  People got used to not being required to declare argc and
> argv if they didn't use them, so the bad practice was standardized.

I can buy that.  (On the other hand, I can't remember ever writing a
program which didn't use argc and argv.  For most of my work, the most
reasonable signature would be:

    void main( int argc, char** argv ) ;
)

--
James Kanze             GABI Software             mailto:kanze@gabi-soft.fr
Conseils en informatique orient   e objet/
                           Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, T   l. : +33 (0)1 30 23 45 16

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Wed, 23 Apr 2003 17:03:51 +0000 (UTC)
Raw View
"James Kanze" <kanze@gabi-soft.de> wrote in message news:d6651fb6.0304230831.57a6e4f6@posting.google.com...

>
> What needs to be added to the compiler?  All I see here is a typedef of
> main_t, in some header file.

I thought you were asking for the program to be able to change it.


>
> > void main has never been legal in C or C++.
>
> I'd have to look that up in my K&R.  C90 didn't explicitly ban it,
> however.

You won't find the word void anywhere in K&R.  Void didn't show up in
C until about 1978 or so.    Your understanding of C90 is wrong.   C90
is even more restrictive than C++.   It requires the hosted environment
to do int main(void) and int main(int, char*[]), with no option for other
definition.

>
> > The fact that it "happens to work OK" is not a compelling reason to
> > codify the bad practice.
>
> What's bad about it (except the formal issues)?  Most of my programs
> never return.

What's bad is what happens if you are on a machine where mismatching
void and int returns is not benign.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: a9804814@unet.univie.ac.at (Thomas Mang)
Date: Thu, 24 Apr 2003 02:17:48 +0000 (UTC)
Raw View

James Kanze schrieb:

> ron@sensor.com ("Ron Natalie") wrote in message
> news:<Lbina.6887$Y57.3348@fe05.atl2.webusenet.com>...
> > "Allan W" <allan_w@my-dejanews.com> wrote in message
> > news:7f2735a5.0304161119.2d516e7d@posting.google.com...
> > > Suppose we insist that either main_t is a typedef for int, or else
> > > it is convertible from int. Most programs would need only one
> > > trivial change in order to be compatible; furthermore, on existing
> > > platforms, the code would continue to function properly until this
> > > change was made.
>
> > Great more godawful changes that make main different than every other
> > function.  This means more goofy stuff that has to get added to
> > something that knows it's compiling main and possibly additional
> > linkage overhead to support this.
>
> What needs to be added to the compiler?  All I see here is a typedef of
> main_t, in some header file.
>
> > > I've been a strong proponent of ignoring void main, even when the
> > > local platform supports it -- but my impression is that a LOT of
> > > people routinely use it, without even realizing it's wrong. Which
> > > makes me think that maybe we should support it after all. The C++
> > > standard is supposed to document existing practice, yes?
>
> > No.  The practice was wrong before, it is wrong now.  The C++ standard
> > only has a preference for things that were legal before, to avoid
> > making them illegal.
>
> Before the C standard, anything a compiler implementor wanted to do was
> legal:-).  (On the other hand, this void main business seems to be a
> recent phenomena.  I can't recall seeing any void main in the days when
> I was learning C.)
>
> > void main has never been legal in C or C++.
>
> I'd have to look that up in my K&R.  C90 didn't explicitly ban it,
> however.
>
> > The fact that it "happens to work OK" is not a compelling reason to
> > codify the bad practice.
>
> What's bad about it (except the formal issues)?  Most of my programs
> never return.

A point against "void main()":
It violates the overloading rules because we'd have then 2 functions differing
only in the return type.
OTOH, main is special anyways, why not make it special regarding this too,
since there is hardly an ambiguity to expect in practice........

regards,

Thomas

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ron@sensor.com ("Ron Natalie")
Date: Thu, 24 Apr 2003 02:24:47 +0000 (UTC)
Raw View
"Thomas Mang" <a9804814@unet.univie.ac.at> wrote in message news:3EA7067C.BD7A6968@unet.univie.ac.at...

> A point against "void main()":
> It violates the overloading rules because we'd have then 2 functions differing
> only in the return type.
> OTOH, main is special anyways, why not make it special regarding this too,
> since there is hardly an ambiguity to expect in practice........

Main is sort of reverse overloaded anyhow.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 24 Apr 2003 18:43:43 +0000 (UTC)
Raw View
In article <3EA7067C.BD7A6968@unet.univie.ac.at>, Thomas Mang
<a9804814@unet.univie.ac.at> writes
>A point against "void main()":
>It violates the overloading rules because we'd have then 2 functions differing
>only in the return type.
>OTOH, main is special anyways, why not make it special regarding this too,
>since there is hardly an ambiguity to expect in practice........

Actually, despite what the standard may say, I do not think that main is
a function in C++ (it is in C though a curiously overloaded one). You
cannot call it, you cannot take its address and the user cannot overload
it. Has the feel of an entry point with function like syntax.

We could get round many of people's quibbles with main if we wrote:

Every program running in a hosted environment has a single entry point
called main which has the following syntax:
...


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow      ACCU

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rlankine@hotmail.com ("Risto Lankinen")
Date: Thu, 24 Apr 2003 18:43:51 +0000 (UTC)
Raw View
"Thomas Mang" <a9804814@unet.univie.ac.at> wrote in message
news:3EA7067C.BD7A6968@unet.univie.ac.at...
>
> A point against "void main()":
> It violates the overloading rules because we'd have then 2 functions
differing
> only in the return type.

Not really because that, and int main(), would never
coexist in a single program since there would still be
just one main() function.

Cheers!

 - Risto -


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]