/* Startup code needed by GCC C++ output code.  */
/* Copyright (C) 1991 Free Software Foundation, Inc.

This file is part of GNU CC.

GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */

/* As a special exception, if you link this file with files
   compiled with GCC to produce an executable, this does not cause
   the resulting executable to be covered by the GNU General Public License.
   This exception does not however invalidate any other reasons why
   the executable file might be covered by the GNU General Public License.  */

/*  init_main.c: Originally developed by James Kempf for SUN,
 *               adapted and commented for FSF by Heinz Seidl (hgs@cygnus.com)
 */

#include <assert.h>
#include "init_main.h"
#include "config.h"

/* define NO_ATEXIT in config.h if there isn't one */

#ifndef NO_ATEXIT
  #define ATEXIT(FCTNP) 0
#else
  #ifdef sun
    extern int on_exit( void (*)(), int); 
    #define ATEXIT(FCTNP) on_exit( FCTNP, 0)
  #else
    extern int atexit( void (*)()); /* defined in stdlib.h */
    #define ATEXIT(FCTNP) atexit( FCTNP)
  #endif
#endif /* NO_ATEXIT

/* 
 * The main module and all shared modules have each their own __C/DTOR_LIST__.
 * When a module is to be final/initialized, `__function_list_addr' gets the
 * address of the  __C/DTOR_LIST__ of that module.
 * (For the main module we can simple take the globals __C/DTOR_LIST__, for
 * shared objects, we have to use functionality of the runtime linker ld.so
 * to get the addresses. All this has to be done in the main program, since
 * a lot of functionality of ld.so does not work as documented).
 */

ep_fp * __function_list_addr = 0;

extern ep_fp __CTOR_LIST__[];
extern ep_fp __DTOR_LIST__[];

int __main();
void INITIALIZE_MODULE();
void FINALIZE_MODULE();
void __initialize_libraries();
void __finalize_libraries();
void exit(/*int*/);
void _exit(/*int*/);
void _cleanup();

entry_pt INIT_START;
entry_pt INIT_END;


/*************************************************************************
 * Main initialization and finalization
 ************************************************************************/

/* 
 * Initialize first (dynamically linked) libraries, then the main module.
 * Finalize first the main module then (dynamically linked) libraries.
 */



void __initialize_main()
{
    __function_list_addr = __CTOR_LIST__;
    INITIALIZE_MODULE();
}

void __finalize_main()
{
    __function_list_addr = __DTOR_LIST__;
    FINALIZE_MODULE();
}


int __main()
{
    int ret = 0;

    INIT_START(); /* user supplied function */

    __initialize_libraries();             /* first the libraries */
    __initialize_main();		  /* second main module */

    INIT_END();   /* user supplied function */

    ret = ATEXIT( __finalize_main);      assert( ret == 0);
    ret = ATEXIT( __finalize_libraries); assert( ret == 0);
    return(ret);
}


#ifndef HAVE_ATEXIT
void exit( int status)
{
    __finalize_main(); 		          /* first main module */
    __finalize_libraries();               /* second the libraries */
#ifdef GPROF
    _mcleanup();
#endif
    _cleanup();
    _exit(status);
}
#endif
