forked from KolibriOS/kolibrios
fopen fread fseek lseek ftell
git-svn-id: svn://kolibrios.org@548 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
293
programs/develop/open watcom/trunk/clib/crt/initrtns.c
Normal file
293
programs/develop/open watcom/trunk/clib/crt/initrtns.c
Normal file
@@ -0,0 +1,293 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Open Watcom Project
|
||||
*
|
||||
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original
|
||||
* Code as defined in and that are subject to the Sybase Open Watcom
|
||||
* Public License version 1.0 (the 'License'). You may not use this file
|
||||
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
|
||||
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
|
||||
* provided with the Original Code and Modifications, and is also
|
||||
* available at www.sybase.com/developer/opensource.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
|
||||
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
|
||||
* NON-INFRINGEMENT. Please see the License for the specific language
|
||||
* governing rights and limitations under the License.
|
||||
*
|
||||
* ========================================================================
|
||||
*
|
||||
* Description: Initialization and termination of clib.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "variety.h"
|
||||
#include "initfini.h"
|
||||
#include "rtinit.h"
|
||||
|
||||
#define PNEAR ((__type_rtp)0)
|
||||
#define PFAR ((__type_rtp)1)
|
||||
#define PDONE ((__type_rtp)2)
|
||||
|
||||
#if ( COMP_CFG_COFF == 1 ) || defined(__AXP__) || defined(__PPC__) || defined(__MIPS__)
|
||||
// following is an attempt to drop the need for an assembler
|
||||
// segment definitions file
|
||||
// unfortunately, the use of XIB,XIE,YIB,YIE doesn't get the
|
||||
// right sort of segments by default
|
||||
#pragma data_seg( ".rtl$xib", "DATA" );
|
||||
YIXI( TS_SEG_XIB, _Start_XI, 0, 0 )
|
||||
#pragma data_seg( ".rtl$xie", "DATA" );
|
||||
YIXI( TS_SEG_XIE, _End_XI, 0, 0 )
|
||||
#pragma data_seg( ".rtl$yib", "DATA" );
|
||||
YIXI( TS_SEG_YIB, _Start_YI, 0, 0 )
|
||||
#pragma data_seg( ".rtl$yie", "DATA" );
|
||||
YIXI( TS_SEG_YIE, _End_YI, 0, 0 )
|
||||
#pragma data_seg( ".data", "DATA" );
|
||||
#elif defined(_M_IX86)
|
||||
extern struct rt_init _Start_XI;
|
||||
extern struct rt_init _End_XI;
|
||||
|
||||
extern struct rt_init _Start_YI;
|
||||
extern struct rt_init _End_YI;
|
||||
#else
|
||||
#error unsupported platform
|
||||
#endif
|
||||
|
||||
typedef void (*pfn)(void);
|
||||
typedef void (_WCI86FAR * _WCI86FAR fpfn)(void);
|
||||
typedef void (_WCI86NEAR * _WCI86NEAR npfn)(void);
|
||||
|
||||
#if defined(__AXP__) || defined(__PPC__) || defined(__MIPS__)
|
||||
#define __GETDS()
|
||||
#define save_ds()
|
||||
#define restore_ds()
|
||||
#define save_es()
|
||||
#define restore_es()
|
||||
#define setup_es()
|
||||
#elif defined(__WINDOWS_386__)
|
||||
#define __GETDS()
|
||||
#define save_ds()
|
||||
#define restore_ds()
|
||||
#define save_es()
|
||||
#define restore_es()
|
||||
#define setup_es()
|
||||
#elif defined(__386__)
|
||||
#define __GETDS()
|
||||
#define save_ds()
|
||||
#define restore_ds()
|
||||
#if defined(__FLAT__)
|
||||
#define save_es()
|
||||
#define restore_es()
|
||||
#define setup_es()
|
||||
#else
|
||||
extern void save_es( void );
|
||||
#pragma aux save_es = modify exact [es];
|
||||
extern void restore_es( void );
|
||||
#pragma aux restore_es = modify exact [es];
|
||||
extern void setup_es( void );
|
||||
#pragma aux setup_es = \
|
||||
"push ds" \
|
||||
"pop es" \
|
||||
modify exact [es];
|
||||
#endif
|
||||
#elif defined(M_I86)
|
||||
extern void save_dx( void );
|
||||
#pragma aux save_dx = modify exact [dx];
|
||||
extern void _WCI86NEAR __GETDS( void );
|
||||
#pragma aux __GETDS "__GETDS";
|
||||
extern void save_ds( void );
|
||||
#pragma aux save_ds = "push ds" modify exact [sp];
|
||||
extern void restore_ds( void );
|
||||
#pragma aux restore_ds = "pop ds" modify exact [sp];
|
||||
#define save_es()
|
||||
#define restore_es()
|
||||
#else
|
||||
#error unsupported platform
|
||||
#endif
|
||||
|
||||
#if defined(M_I86)
|
||||
static void callit_near( npfn *f ) {
|
||||
// don't call a null pointer
|
||||
if( *f ) {
|
||||
save_dx();
|
||||
save_ds();
|
||||
// call function
|
||||
(void)(**f)();
|
||||
restore_ds();
|
||||
}
|
||||
}
|
||||
|
||||
static void callit_far( fpfn _WCI86NEAR *f ) {
|
||||
// don't call a null pointer
|
||||
if( *f ) {
|
||||
save_ds();
|
||||
// call function
|
||||
(void)(**f)();
|
||||
restore_ds();
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void callit( pfn *f ) {
|
||||
// don't call a null pointer
|
||||
if( *f ) {
|
||||
// QNX needs es==ds
|
||||
setup_es();
|
||||
// call function
|
||||
(void)(**f)();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
; - takes priority limit parm in eax, code will run init routines whose
|
||||
; priority is < eax (really al [0-255])
|
||||
; eax==255 -> run all init routines
|
||||
; eax==15 -> run init routines whose priority is <= 15
|
||||
;
|
||||
*/
|
||||
|
||||
void __InitRtns( unsigned limit ) {
|
||||
__type_rtp local_limit;
|
||||
struct rt_init _WCI86NEAR *pnext;
|
||||
save_ds();
|
||||
save_es();
|
||||
__GETDS();
|
||||
|
||||
local_limit = (__type_rtp)limit;
|
||||
for(;;) {
|
||||
{
|
||||
__type_rtp working_limit;
|
||||
struct rt_init _WCI86NEAR *pcur;
|
||||
|
||||
pcur = (struct rt_init _WCI86NEAR*)&_Start_XI;
|
||||
#if defined(COMP_CFG_COFF)
|
||||
pcur++;
|
||||
#endif
|
||||
pnext = (struct rt_init _WCI86NEAR*)&_End_XI;
|
||||
working_limit = local_limit;
|
||||
|
||||
// walk list of routines
|
||||
while( pcur < (struct rt_init _WCI86NEAR*)&_End_XI )
|
||||
{
|
||||
// if this one hasn't been called
|
||||
if( pcur->rtn_type != PDONE ) {
|
||||
// if the priority is better than best so far
|
||||
if( pcur->priority <= working_limit )
|
||||
{
|
||||
// remember this one
|
||||
pnext = pcur;
|
||||
working_limit = pcur->priority;
|
||||
}
|
||||
}
|
||||
// advance to next entry
|
||||
pcur++;
|
||||
}
|
||||
// check to see if all done, if we didn't find any
|
||||
// candidates then we can return
|
||||
if( pnext == (struct rt_init _WCI86NEAR*)&_End_XI ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if defined(M_I86)
|
||||
if( pnext->rtn_type == PNEAR ) {
|
||||
callit_near( (npfn *)&pnext->rtn );
|
||||
} else {
|
||||
callit_far( (fpfn _WCI86NEAR *)&pnext->rtn );
|
||||
}
|
||||
#else
|
||||
callit( &pnext->rtn );
|
||||
#endif
|
||||
// mark entry as invoked
|
||||
pnext->rtn_type = PDONE;
|
||||
}
|
||||
restore_es();
|
||||
restore_ds();
|
||||
}
|
||||
|
||||
/*
|
||||
; - takes priority range parms in eax, edx, code will run fini routines whose
|
||||
; priority is >= eax (really al [0-255]) and <= edx (really dl [0-255])
|
||||
; eax==0, edx=255 -> run all fini routines
|
||||
; eax==16, edx=255 -> run fini routines in range 16..255
|
||||
; eax==16, edx=40 -> run fini routines in range 16..40
|
||||
*/
|
||||
#if defined(M_I86)
|
||||
void _WCI86FAR __FFiniRtns( unsigned min_limit, unsigned max_limit ) {
|
||||
__FiniRtns( min_limit, max_limit );
|
||||
}
|
||||
#endif
|
||||
|
||||
void __FiniRtns( unsigned min_limit, unsigned max_limit )
|
||||
{
|
||||
__type_rtp local_min_limit;
|
||||
__type_rtp local_max_limit;
|
||||
struct rt_init _WCI86NEAR *pnext;
|
||||
save_ds();
|
||||
save_es();
|
||||
__GETDS();
|
||||
|
||||
local_min_limit = (__type_rtp)min_limit;
|
||||
local_max_limit = (__type_rtp)max_limit;
|
||||
for(;;) {
|
||||
{
|
||||
__type_rtp working_limit;
|
||||
struct rt_init _WCI86NEAR *pcur;
|
||||
|
||||
pcur = (struct rt_init _WCI86NEAR*)&_Start_YI;
|
||||
#if defined(COMP_CFG_COFF)
|
||||
pcur++;
|
||||
#endif
|
||||
pnext = (struct rt_init _WCI86NEAR*)&_End_YI;
|
||||
working_limit = local_min_limit;
|
||||
|
||||
// walk list of routines
|
||||
while( pcur < (struct rt_init _WCI86NEAR*)&_End_YI )
|
||||
{
|
||||
// if this one hasn't been called
|
||||
if( pcur->rtn_type != PDONE ) {
|
||||
// if the priority is better than best so far
|
||||
if( pcur->priority >= working_limit )
|
||||
{
|
||||
// remember this one
|
||||
pnext = pcur;
|
||||
working_limit = pcur->priority;
|
||||
}
|
||||
}
|
||||
// advance to next entry
|
||||
pcur++;
|
||||
}
|
||||
// check to see if all done, if we didn't find any
|
||||
// candidates then we can return
|
||||
if( pnext == (struct rt_init _WCI86NEAR*)&_End_YI ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pnext->priority <= local_max_limit ) {
|
||||
#if defined(M_I86)
|
||||
if( pnext->rtn_type == PNEAR ) {
|
||||
callit_near( (npfn *)&pnext->rtn );
|
||||
} else {
|
||||
callit_far( (fpfn _WCI86NEAR *)&pnext->rtn );
|
||||
}
|
||||
#else
|
||||
callit( &pnext->rtn );
|
||||
#endif
|
||||
}
|
||||
// mark entry as invoked even if we don't call it
|
||||
// if we didn't call it, it is because we don't want to
|
||||
// call finirtns with priority > max_limit, in that case
|
||||
// marking the function as called, won't hurt anything
|
||||
pnext->rtn_type = PDONE;
|
||||
}
|
||||
restore_es();
|
||||
restore_ds();
|
||||
}
|
||||
|
Reference in New Issue
Block a user