dosxlink.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 555 行 · 第 1/2 页

C
555
字号
static char *CheckPath( char *path, char *fullpath, char **endname )
{
    char        *namep;
    char        *name;

    namep = NAME "\0" OTHER_NAMES;
    for( ;; ) {
        name = SearchPath( path, namep, fullpath, endname );
        if( *name != '\0' ) return( name );
        if( *namep == '\0' ) return( NULL );
        namep += strlen( namep ) + 1;
    }
}

#define LOW( c )        ((c)|0x20)      /*Quick and dirty lower casing*/

static char *FindExtender( char *fullpath, char **endname )
{
    #if defined(DOS4G)
        char    *name;
        char    *d4gname;
        unsigned len;

        d4gname = FindEnv( "DOS4GPATH=" );
        if( d4gname != NULL ) {
_DBG_Write("Got DOS4GPATH -<");
_DBG_Write(d4gname);
_DBG_Writeln(">");
            len = strlen( d4gname );
            if( len > 4 ) {
                name = d4gname + len - 4;
                if( name[0] == '.'
                    && LOW(name[1]) == 'e'
                    && LOW(name[2]) == 'x'
                    && LOW(name[3]) == 'e' ) {
_DBG_Writeln( "is exe\r\n" );
                    CopyStr( d4gname, fullpath );
                    *endname = &fullpath[strlen(fullpath)];
                    return( fullpath );
                }
            }
            name = CheckPath( d4gname, fullpath, endname );
            if( name != NULL ) {
_DBG_Writeln( "found in path\r\n" );
                return( name );
            }
        }
    #endif
    return( CheckPath( FindEnv( "PATH=" ), fullpath, endname ) );
}

#if defined(PHARLAP)

#include "exedos.h"
#include "exeos2.h"
#include "exepe.h"

static char *GetHelpName( char *exe_name )
{
    /*
      if executable is:
          PE format, subsystem PE_SS_PL_DOSSTYLE (0x42) then PEDHELP.EXP
      or:
          PE format, other subsystems then PENHELP.EXP
      otherwise:
          PLSHELP.EXP
    */
    tiny_ret_t          ret;
    int                 handle;
    unsigned_32         off;
    union {
        dos_exe_header  dos;
        pe_header       pe;
    }   head;

    handle = -1;
    ret = TinyOpen( exe_name, 0 );
    if( TINY_ERROR( ret ) ) goto exp;
    handle = TINY_INFO( ret );
    TinyRead( handle, &head.dos, sizeof( head.dos ) );
    if( head.dos.signature != DOS_SIGNATURE ) goto exp;
    TinySeek( handle, OS2_NE_OFFSET, SEEK_SET );
    TinyRead( handle, &off, sizeof( off ) );
    TinySeek( handle, off, SEEK_SET );
    TinyRead( handle, &head.pe, sizeof( head.pe ) );
    TinyClose( handle );
    handle = -1;
    switch( head.pe.signature ) {
    case PE_SIGNATURE:
    case PL_SIGNATURE:
        if( head.pe.subsystem == PE_SS_PL_DOSSTYLE ) {
            _DBG_Writeln( "Want PEDHELP" );
            return( HELPNAME_DS );
        }
        _DBG_Writeln( "Want PENHELP" );
        return( HELPNAME_NS );
    }
exp:
    if( handle != -1 ) TinyClose( handle );
    _DBG_Writeln( "Want PLSHELP" );
    return( HELPNAME );
}
#endif
#endif

#define LINK_SIGNATURE 0xdeb0deb0L

#if defined(DOS4G) || defined(CAUSEWAY)
#define LINK_VECTOR     0x06
#else
#define LINK_VECTOR     0x01
#endif

#ifdef SERVER
#if defined(ACAD)
void InitMeg1( void )
{
    extern short GetCS( void );
    if( Meg1 == 0 ) {
        if( GetCS() & 3 ) {
            Meg1 = 0x37;
        } else {
            Meg1 = 0x60;
        }
    }
}

#endif
#endif
char *RemoteLink( char *parm, char server )
{

    #ifdef SERVER
                unsigned long           link;
        #if defined(ACAD)
            {
                XVersion = 2;
                InitMeg1();
            }
        #elif defined(PHARLAP)
        {
            CONFIG_INF                  config;
            static char                 buff[256];

            _dx_config_inf(&config, buff );
            XVersion = config.c_major;
            if( XVersion >= 3 ) {
                Meg1 = config.c_dos_sel;
            } else {
                Meg1 = 0x60;
            }
        }
        #endif
        link = GetDosLong( LINK_VECTOR*4 );
        if( link >= (1024UL*1024UL) || GetDosLong(link) != LINK_SIGNATURE ) {
            return( TRP_ERR_not_from_command );
        }
        RMBuffPtr = GetDosLong( link + 4 );
        RMProcAddr = GetDosLong( link + 8 );
        PutDosLong( LINK_VECTOR*4, GetDosLong( link + 12 ) );
        RMBuffLen = RMBuffPtr + sizeof( long );
    #else
        static char     fullpath[256];              /* static because ss != ds */
        static char     buff[256];
        static char     *endname;
        char            *name;
        char            *buffp;
        char            *endparm;
        void            far *link[4];
        void            far * far * link_ptr;

        _DBG_EnterFunc( "RemoteLink()" );
        BackFromFork = 0;
        link_ptr = (void far *)(LINK_VECTOR*4);
        link[ 3 ] = *link_ptr;
        link[ 2 ] = MK_FP( MyCS(), (unsigned )BackFromProtMode );
        link[ 1 ] = (void far *)MK_LINEAR( &Buff );
        link[ 0 ] = (void far *)LINK_SIGNATURE;
        *link_ptr = (void far *)MK_LINEAR( &link );
        if( parm == NULL ) parm = "\0\0";
        while( *parm == ' ' ) ++parm;
        if( *parm == '`' ) {
            buffp = buff;
            ++parm;
            for( ;; ) {
                *buffp = *parm;
                ++buffp;
                if( *parm == '\0' ) break;
                ++parm;
                if( parm[-1] == '`' ) break;
            }
            *buffp = '\0';
        }
        while( *parm == ' ' ) ++parm;
        if( setjmp( RealModeState ) == 0 ) {
            name = FindExtender( fullpath, &endname );
            if( name == NULL ) {
                _DBG_ExitFunc( "RemoteLink(), unable to find extender" );
                return( TRP_ERR_no_extender );
            }
            _DBG_Write( "Extender name: " );
            _DBG_NoTabWriteln( name );
            endname += strlen( endname )+1;
            #if defined(ACAD)
                buffp = buff;
                buff[ 0 ] = '\0';
            #else
            {
                static char     *endhelp;
                char            *help_name;

#if defined(PHARLAP)
                help_name = GetHelpName( parm + strlen( parm ) + 1 );
#else
                help_name = HELPNAME;
#endif
                buffp = SearchPath( FindEnv( "PATH=" ), help_name, buff, &endhelp );
                if( !*buffp ) {
                    _DBG_ExitFunc( "RemoteLink(), unable to find extender "
                                   "help file" );
                    return( TRP_ERR_no_extender );
                }
            }
            #endif
            _DBG_Write( "Extender help name: " );
            _DBG_NoTabWriteln( buffp );
            endparm = CopyStr( parm, endname+1 );
            endparm = CopyStr( buffp, CopyStr( " ", endparm ) );
            #if defined(PHARLAP)
                endparm = CopyStr( " ", endparm );
                endparm = CopyStr( parm + strlen( parm ) + 1, endparm );
            #endif
            *endname = endparm - endname - 1;
            *endparm = '\r';
            endparm[ 1 ] = '\0';
            _DBG_Write( "Extender Cmd line: " );
            _DBG_NoTabWriteln( endname );
            _DBG_Writeln( "calling _fork() to start extender/debugee" );
            if( _fork( name, endname ) != 0 ) {
                _DBG_ExitFunc( "RemoteLink(), unable to start extender" );
                return( TRP_ERR_cant_start_extender );
            }
        } else if( BackFromFork || !BeenToProtMode ) {
            _DBG_ExitFunc( "RemoteLink(), extender could not start extender "
                           "help file" );
            return( TRP_ERR_cant_start_extender );
        }
    #endif
    parm = parm;
    server = server;
    _DBG_ExitFunc( "RemoteLink()" );
    return( 0 );
}

#pragma aux doskludge = 0xB8 0x00 0x2a  /* mov  ax,2a00H */ \
                        0x83 0xec 0x50 /* sub   sp,50H */ \
                        0xcd 0x21      /* int   21H */ \
                        parm caller [ ax ] \
                        modify [ sp cx dx ] \
                        ;
extern void doskludge( void );

void RemoteUnLink( void )
{
#ifdef SERVER
    CallRealMode( RMProcAddr );
#else
    _DBG_EnterFunc( "RemoteUnLink()" );
    if( setjmp( RealModeState ) == 0 ) {
        doskludge(); /* Ask brian. I don't feel like writing a book */
        SetPSP( OldPSP );
        longjmp( ProtModeState, 0 );
    }
    _DBG_ExitFunc( "RemoteUnLink()" );
#endif
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?