/*********************************************************************
(C) Copyright 1994;       MetaWare Incorporated;  Santa Cruz, CA 95060
This program is the unpublished property and trade secret of MetaWare.
It is to be  utilized  solely  under  license  from  MetaWare  and  it 
is to be maintained on a confidential basis for internal  company  use
only.  The  security  and  protection  of  the program is paramount to
maintenance of the trade secret status.  It is to  be  protected  from
disclosure  to  unauthorized parties, both within the Licensee company
and outside, in a manner not less stringent than that utilized for Li-
censee's own proprietary  internal  information.   No  copies  of  the
source or Object Code are to leave the premises of Licensee's business
except  in  strict accordance with the license agreement signed by Li-
censee with MetaWare.
*********************************************************************/

#ifndef _INIT_H
#define _INIT_H

#ifdef __CPLUSPLUS__
extern "C" {
#endif

extern int _mwscan_args(int build_argv,char **cmd_line,char **argv,char *argv0);

/*--------------------------------------------------------------------------*/
#if _OS2 || _MSNT	/* Things that are common to both OS/2 and NT */

#include <math.h>	/* [struct _exception] */

#ifndef _MWCTOR_H
    #include <mwctor.h>
#endif
extern void _mwcall_onentry_fcns(struct ct_info *ctor_list);
extern void _mwcall_thread_ctors(void);
extern void _mwcall_thread_dtors(void);

#ifndef _REENTRANT
    extern void *_mwexcregp; // thread-local pointer to registration record
#elif !defined(_STATIC_H)
    #include <static.h>
#endif

/* The address of the EXE's _matherr routine is passed through
 * the module_info structure.  We have to save this pointer
 * in a global place where other functions can get to it.
 */
typedef int (*MathErrPtr)(struct _exception *);
extern MathErrPtr _matherr_ptr;		// in _set_mat.c

/* A pointer to the _add_arg routine.  This pointer is either in
 * nowild.c, in which case it points to a dummy function,
 * or it is in wildargs.c, in which case it points to a
 * wildcard expander in wild.c.  The address of the pointer
 * is passed into us from initcon.obj, because the pointer
 * could be in an EXE, but the wildcard expander could be in a DLL.
 */
typedef int (*AddArgPtr)(char *arg, int arglen, char **dest, int expand);
extern AddArgPtr _add_arg;

#endif

/*--------------------------------------------------------------------------*/
#if _OS2

/* DLL entry point notification codes.  The PROCESS codes are standard
 * OS/2 values.  The THREAD codes are unique to High C, and are used
 * to emulate Windows NT.
 */
#define DLL_PROCESS_ATTACH 0
#define DLL_PROCESS_DETACH 1
#define DLL_THREAD_ATTACH 2
#define DLL_THREAD_DETACH 3

void _mwdll_notify(unsigned long flag);

/* The following are pointers to routines that initialize and
 * un-initialize signal handling.  If signal() is not linked in,
 * they point to dummy functions. The input is actually an exception
 * registration record.  init.c saves the input pointer in global
 * _mwexcregp so it can be retrieved for calling _mwuninit_sig_ptr
 * in the "exit" pathway.
 */
extern void (* _mwuninit_sig_ptr) (void *excreg);	// in sigptr.c
extern void (* _mwinit_sig_ptr) (void *excreg);	// in sigptr.c

typedef unsigned long (*InitTermPtr)(unsigned long modh, unsigned long flag);
typedef int (*MainPtr)(int argc, char **argv, char **envp);

/* The module_info structure in startup.asm gives the addresses
 * of the constructor and destructor tables, and the address of main()
 * or _DLL_InitTerm.
 */
struct module_info {
    struct ct_info ct;		// constructor information
#ifdef DLL
    InitTermPtr initterm;	// address of _DLL_InitTerm()
#else
    MainPtr main;		// address of main()
#endif
    AddArgPtr *addarg;		// address of address of _add_arg function
    int is_global;		// use global initialization?
    MathErrPtr exe_matherr;	// pointer to EXE's _matherr()
#ifdef DLL
    InitTermPtr entrypoint;	// module's entry point
#else
    void *entrypoint;		// EXE's entry point (not used)
#endif
#if _PPC
    int *tls_index;		// ptr to module's thread local storage index
#else
    int tls_index;		// module's thread local storage index
#endif
    char *tls_base;		// base of TLS segment
    char *tls_end;		// limit of TLS segment
    unsigned long modh;		// module handle
    };

/* Each process has a shared memory region that is used to
 * store the information that must be accessible to all of the
 * DLLs used by the process.
 */
struct share_mem {
    struct module_info *head;	// list of module information tables for
    				// all DLLs used by this process.
    int init_complete;		// if 1, process startup initialization is done
    int next_tls;		// global thread-local storage index
    };

/* _mwopen_shmem opens or creates the process's shared memory region.
 * This function is found in initdata.c.
 */
struct share_mem *_mwopen_shmem(int create);

/* _ismwexe returns true if the current program (EXE) has an
 * exported symbol "_mwGlobalInit" in its resident name table.
 * This means the the EXE uses multiple DLLs and expects that
 * these DLLS are to be initialized globally.
 */
int _ismwexe(void);	// in _ismwexe.c


/* Variables for dealing with C++ exception handling (in initdata.c):
 *   _mwexc_size contains the size of an exception handler state
 *   _mwexc_init initializes the exception handler state
 * If exception handling is linked in, these variables will get
 * initialized by startup expressions in exc.cpp.
 */
extern int _mwexc_size;
extern void (*_mwexc_init)(void *);

/* Functions for dealing with thread local storage.
 */
void _mwtls_stack(int tlsindex);		/* reserve top of stack */
void _mwtls_set(int tlsindex, void *tlsdata);	/* set pointer to TLS */
void *_mwtls_get(int tlsindex);			/* get pointer to TLS */


/*--------------------------------------------------------------------------*/
#elif _MSNT

#define _ENV_UNKNOWN -1
#define _ENV_WIN32   0
#define _ENV_WIN32S  1
#define _ENV_TNT     2

extern unsigned int _mwenv;
extern void _mwinit_osversion(void);
extern void _mwinit_fp(void);
extern void *_mwalloc_crt_data(unsigned size);  // for thread-local data
extern void _mwfree_crt_data(void *ptr);

/* Each process has a shared memory region (actually just a data variable
 * in the EXE) that is used to store the information that must be accessable
 * to all of the DLLs used by the process.
 */
struct share_mem {
    struct ct_info *ct_head;	// List of constructor information tables for
    				// all DLLs used by this process.
    struct ct_info *ct_last;	// The last element in the list.
    int init_complete;		// If 1, process startup initialization is done
    };

// _mwopen_shmem opens returns a pointer to the shared memory region.
struct share_mem *_mwopen_shmem(void);

/* Each dll stores the following info for use on subsequent calls to the DLL
   entry point.
*/
struct dll_info {
    int is_global;		// use global constructor initialization?
    };

//extern void _mwcall_initseg(void);
//extern void _mwcall_exitseg(void);

struct exe_info {
    int size;			// so we can detect old exe_infos
    int (*main)(int argc, char **argv, char **envp);
    AddArgPtr *addarg;		// address of address of _add_arg function
    MathErrPtr exe_matherr;	// pointer to EXE's _matherr
    int reserved[4];		// set to 0
    };

#define _APP_CONSOLE 1
#define _APP_WINDOWS 2
extern void _mwinit_app(
	int app_type,  /* either _APP_CONSOLE, _APP_WINDOWS */
	struct ct_info *ctinfo,
	struct exe_info *exeinfo );

/* the initialization routine _mwinit_sig_ptr requires the address of an
   exception registration record as an input parameter.  The caller doesn't
   initialize the structure in any way.  The catch is that the address
   of the structure must be a stack address that resides in an active stack
   frame the entire time the application is running.  Thus, the initialization
   routine that calls main may declare such a structure as a local variable
   and pass it to _mwinit_sig_ptr prior to calling main.  The structure is
   actually used as an exception registration record, and linked into the
   linked list of such records beginning at fs:[0].
*/
/* The following are pointers to routines that initialize and
 * un-initialize signal handling.  If signal() is not linked in,
 * they point to dummy functions.  The input is actually an exception
 * registration record.  init.c saves the input pointer in global _mwexcregp
 * so it can be retrieved for calling _mwuninit_sig_ptr in the "exit" pathway.
 */
#define _SIGBUF_SIZE 16  /* must be at least large enough for an exception
			    registration record */
typedef struct {
    unsigned char buf[_SIGBUF_SIZE];
    } _nt_sig_buf;

extern void (* _mwinit_sig_ptr)(_nt_sig_buf *);		// in sigptr.c
extern void (* _mwuninit_sig_ptr)(_nt_sig_buf *);	// in sigptr.c

/*--------------------------------------------------------------------------*/
#elif _MSDOS

/* possible values of the _mwenv global variable */
#define SG_ENV	1	/* Softguard IGC (no longer supported) */
#define PL_ENV  2	/* Phar Lap 386|DOS-Extender */
#define AI_ENV	3	/* A.I. Architects (Eclipse) ((Ergo)) */
#define SSI_ENV	4	/* Windows */
#define D4G_ENV	5	/* Rational DOS/4G DOS Extender */


extern struct {
    unsigned save_eax;
    unsigned save_ebx;
    unsigned save_ecx;
    unsigned save_edx;
    unsigned save_esi;
    unsigned save_edi;
    unsigned save_esp;
    unsigned save_ebp;
    unsigned save_ds;    /* ds, es, fs can be safely casted to unsigned short */
    unsigned save_es;
    unsigned save_fs;
    } _mwinitregs;

/* not used by the library. included for compatibility. may go away */
extern _Far char *_mwargp;
extern int   _mwarglen;
extern _Far char *_mwprognamep;

extern short _mwgsel;		/* graphics selector */
extern unsigned char _mwenv;	/* identifies execution environ (see above) */
extern char _mwinit_ver;	/* 1 if LOC, 2 if GOC */
extern char _mwwind;		/* non-zero if windows execution environment */
extern _Far unsigned char *_mwno87;

#define _CANT_EXPAND  0
#define _CAN_EXPAND   1
/* can turn off heap expansion on either Phar Lap or AI_ENV */
extern unsigned char _mwheap_expansion_enabled;

#ifndef _REENTRANT
    extern _Far char *_mwenvp;
#elif !defined(_STATIC_H)
    #include <static.h>
#endif

/* these routines are listed in the order called during initialization */

    /* first routine called from assembly */
extern void _mwinit_rte(int acad, int padi, unsigned long *acad_padi_cbufadr);
    /* figures out which dos extender we are using, sets _mwenv accordingly */
extern void _mwfeelout_mwenv(void);
    /* sets _osversion, _osmajor, _osminor */
extern int _mwinit_osver(void);
    /* zeros the BSS section */
extern void _mwclear_bss(void);
    /* sets values at _mwstack_limit for pragma on(check_stack) support */
extern void _mwinit_stack_margin(void);
    /* initializes low-level support for calling _mwexpand_heap at runtime */
extern void _mwinit_heap(int acad, int padi, unsigned long *acad_padi_cbufadr);
    /* constructs pointers to the command line and environment */
typedef _Far char *_fcptr;
extern void _mwinit_envp_argp(_fcptr *argp, int *arglen,
	_fcptr *prognamep, _fcptr *envp);
    /* sets the graphics selector _mwgsel */
extern void _mwsetgsel(void);
    /* takes responsibility for higher-level (portable) library initialization
       and then prepares argv and environment and calls main. this is a
       good entry point into the MetaWare library for custom environments
       like embedded applications */
extern void _cinit(_Far char *argp, int arglen, _Far char *prognamep,
	_Far char *envp );
    /* calls all routines supporting 'pragma startup_expr' or C++ static
       constructors */
extern void _mwcall_onentry_fcns(void);
    /* coprocessor initialization */
extern void _mwinit_coproc(void); 
extern void _mwcoproc_exist(void);
    /* a startup_expr, initializes the _environ global variable */
extern void _mwinit_environ(void);

extern int _mwlsl(short selector_val);  /* performs lsl instruction */
extern unsigned short _mwgetcs();	/* returns CS register */


#endif /* _MSDOS */

#ifdef __CPLUSPLUS__
}
#endif

#endif  /* _INIT_H */
