idedrv.c

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

C
818
字号
/****************************************************************************
*
*                            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:  Driver for DLLs pluggable into the IDE (and wmake).
*
****************************************************************************/


#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include "idedll.h"
#include "idedrv.h"
#include "walloca.h"


#ifndef USE_RUNYOURSELF_ARGV
    #if defined(__UNIX__)
        #define USE_RUNYOURSELF_ARGV
    #endif
#endif


#if defined( __OS2__ ) || defined( __NT__ )
    //
    // DLLs implemented only for:
    //      OS/2 (386, PowerPC)
    //      NT (386, Alpha AXP, PowerPC)

    // you can use link in the dll objects into the stub in other os's
    //(eg dos--if you consider that an os) by defining STATIC_LINKAGE
    // and IDE_PGM. note that IDE_PGM needs to be defined anywhere that
    // IDEDLL_EXPORT is used and/or idedll.h is included

    #if defined( __OS2__ ) && !defined( __OSI__ )
        #define DLLS_IMPLEMENTED

        // The following are defined in os2.h
        #undef  COMMENT
        #define ERR         OS2_ERR

        #define INCL_DOS
        #include "os2.h"
        #define IDETOOL_GETVER          "_IDEGetVersion@0"
        #define IDETOOL_INITDLL         "_IDEInitDLL@12"
        #define IDETOOL_RUNSELF         "_IDERunYourSelf@12"
        #define IDETOOL_RUNSELF_ARGV    "_IDERunYourSelf@16"
        #define IDETOOL_FINIDLL         "_IDEFiniDLL@4"
        #define IDETOOL_STOPRUN         "_IDEStopRunning@0"
        #define IDETOOL_INITINFO        "_IDEPassInitInfo@8"
        #undef  ERR
        typedef HMODULE DLL_HANDLE;
    #elif defined( __NT__ )
        #define DLLS_IMPLEMENTED
        #include <windows.h>
        #define IDETOOL_GETVER          "_IDEGetVersion@0"
        #define IDETOOL_INITDLL         "_IDEInitDLL@12"
        #define IDETOOL_RUNSELF         "_IDERunYourSelf@12"
        #define IDETOOL_RUNSELF_ARGV    "_IDERunYourSelf@16"
        #define IDETOOL_FINIDLL         "_IDEFiniDLL@4"
        #define IDETOOL_STOPRUN         "_IDEStopRunning@0"
        #define IDETOOL_INITINFO        "_IDEPassInitInfo@8"
        typedef HINSTANCE DLL_HANDLE;
    #else
        #include "bool.h"
    #endif

    #ifdef DLLS_IMPLEMENTED
        typedef unsigned IDEDLL_EXPORT (*GetVerFn)( void );
        typedef IDEBool IDEDLL_EXPORT (*InitDllFn)( IDECBHdl hdl
                                                  , IDECallBacks *cb
                                                  , IDEDllHdl *info );
        typedef IDEBool IDEDLL_EXPORT (*RunSelfFn)( IDEDllHdl hdl
                                                  , const char *opts
                                                  , IDEBool *fatalerr );
        typedef IDEBool IDEDLL_EXPORT (*RunSelfFnArgv)( IDEDllHdl hdl
                                                  , int
                                                  , char **argv
                                                  , IDEBool *fatalerr );
        typedef void IDEDLL_EXPORT (*FiniDllFn)( IDEDllHdl hdl );
        typedef void IDEDLL_EXPORT (*StopRunFn)( void );
        typedef IDEBool IDEDLL_EXPORT (*PassInitInfo)( IDEDllHdl hdl
                                                     , IDEInitInfo *info );
    #endif

#else
    #include "bool.h"
#endif

#if (defined DLLS_IMPLEMENTED || (defined STATIC_LINKAGE && defined IDE_PGM) )

typedef void (*P_FUN)( void );

#ifndef STATIC_LINKAGE

#ifdef __OS2__
    //
    // OS/2 Interface
    //

static int sysdepDLLLoad( IDEDRV *inf )
{
#define SIZE 32
    unsigned char   badfile[SIZE];

    return (int)DosLoadModule( (PSZ)badfile
                             , sizeof( badfile )
                             , (PSZ)inf->dll_name
                             , (DLL_HANDLE *)&inf->dll_handle );
}

static int sysdepDLLUnload( IDEDRV *inf )
{
    DosFreeModule( (DLL_HANDLE)inf->dll_handle );
    return( 0 );    // sometimes get failure in good situations
}

static int sysdepDLLgetProc( IDEDRV *inf
                           , char const *fun_name
                           , P_FUN *fun )
{
    int retcode;

    retcode = (int)DosQueryProcAddr( (DLL_HANDLE)inf->dll_handle
                                   , 0
                                   , (PSZ)fun_name
                                   , (PFN *)fun );
    if( 0 != retcode ) {
        // DLL could be linked case-insensitive
        unsigned    size = strlen( fun_name ) + 1;
        char        *p = alloca( size );

        p = memcpy( p, fun_name, size );
        p = strupr( p );
        retcode = (int)DosQueryProcAddr( (DLL_HANDLE)inf->dll_handle
                                       , 0
                                       , (PSZ)p
                                       , (PFN *)fun );
    }
    return( retcode );
}

#endif // __OS2__

#ifdef __NT__
    //
    // NT Interface
    //

static int sysdepDLLLoad( IDEDRV *inf )
{
    inf->dll_handle = (void *)LoadLibrary( inf->dll_name );
    return( 0 == inf->dll_handle );
}

static int sysdepDLLUnload( IDEDRV *inf )
{
    return( !(int)FreeLibrary( (DLL_HANDLE)inf->dll_handle ) );
}

static int sysdepDLLgetProc( IDEDRV *inf,
                             char const *fun_name,
                             P_FUN *fun )
{
    P_FUN fp = (P_FUN)GetProcAddress( (DLL_HANDLE)inf->dll_handle, fun_name );

    *fun = fp;
    return( 0 == fp );
}

#endif // __NT__

#endif // STATIC_LINKAGE



typedef int (*USER_DLL_FUN)( char const * );
typedef int (*USER_DLL_FUN_ARGV)( int, char ** );

#ifndef CHAIN_CALLBACK

static IDEBool __stdcall stubPrintMsgFn( IDECBHdl hdl, char const *msg )
{
    hdl = hdl;
#ifndef NDEBUG
    fputs( "stubPrintMsgFn called!\n", errout );
    fputs( msg, errout );
    fputc( '\n', errout );
#else
    msg = msg;
#endif
    return( FALSE );
}

#ifndef NDEBUG
static void __stdcall printProgressIndex( IDECBHdl hdl, unsigned index )
{
    hdl = hdl;
    fprintf( errout, "progress: %u\n", index );
}
#else
#define printProgressIndex      NULL
#endif

static IDEBool __stdcall printMessage( IDECBHdl hdl, char const *msg )
{
    hdl = hdl;
    fputs( msg, errout );
    fputc( '\n', errout );
    return( FALSE );
}

static IDEBool __stdcall printWithInfo( IDECBHdl hdl, IDEMsgInfo *inf )
{
    FILE    *fp;
    char    prt_buffer[ 512 ];

    hdl = hdl;
    IdeMsgFormat( hdl
                , inf
                , prt_buffer
                , sizeof( prt_buffer )
                , &printWithInfo );
    switch( inf->severity ) {
    case IDEMSGSEV_BANNER:
    case IDEMSGSEV_DEBUG:
    case IDEMSGSEV_NOTE_MSG:
        fp = stdout;
        break;
    case IDEMSGSEV_WARNING:
    case IDEMSGSEV_ERROR:
    case IDEMSGSEV_NOTE:
    default:
        fp = errout;
    }
    fputs( prt_buffer, fp );
    fputc( '\n', fp );
    fflush( fp );
    return( FALSE );
}

static IDEBool __stdcall printWithCrLf( IDECBHdl hdl, const char *message )
{
    hdl = hdl;
    fputs( message, errout );
    fflush( errout );
    return( FALSE );
}

static IDEBool __stdcall getInfoCB( IDECBHdl hdl, IDEInfoType type,
                                unsigned long extra, unsigned long lparam )
{
    int retn;

    extra = extra;
    hdl = hdl;
    switch( type ) {
      default:
        retn = TRUE;
        break;
      case IDE_GET_ENV_VAR:
      { char const* env_var;
        char const* env_val;
        char const * * p_env_val;
        env_var = (char const*)extra;
        env_val = getenv( env_var );
        p_env_val = (char const * *)lparam;
        *p_env_val = env_val;
        retn = ( env_val == NULL );
      } break;
    }
    return( retn );
}


static IDECallBacks callbacks = {     // CALL-BACK STRUCTURE
    // building functions
    NULL,                       // RunBatch
    printMessage,               // PrintMessage
    printWithCrLf,              // PrintWithCRLF
    printWithInfo,              // PrintWithInfo

    // Query functions
    getInfoCB,                  // GetInfo

    stubPrintMsgFn,             // ProgressMessage
    NULL,                       // RunDll
    NULL,                       // RunBatchCWD
    NULL,                       // OpenJavaSource
    NULL,                       // OpenClassFile
    NULL,                       // PackageExists
    NULL,                       // GetSize
    NULL,                       // GetTimeStamp
    NULL,                       // IsReadOnly
    NULL,                       // ReadData
    NULL,                       // Close
    NULL,                       // ReceiveOutput

    printProgressIndex,         // ProgressIndex
};
static IDECallBacks *CBPtr = &callbacks;
#else
static IDECallBacks *CBPtr = NULL;
#endif

static IDEInitInfo info =           // INFORMATION STRUCTURE
{   IDE_CUR_INFO_VER                // - ver
,   0                               // - ignore_env
,   1                               // - cmd_line_has_files
,   0                               // - console_output
,   0                               // - progress messages
,   0                               // - progress index
};

static IDEInitInfo  *InfoPtr = NULL;

#ifndef STATIC_LINKAGE
static IDEDRV   *Inf;
#endif

#ifdef __OSI__
#define NO_CTRL_HANDLERS
#endif

#ifndef NO_CTRL_HANDLERS
static void StopRunning( void )
{
// Provide static and dynamic linking
#ifdef STATIC_LINKAGE
    IDEStopRunning();
#else
    StopRunFn   idestopdll;
    int         retcode;

    retcode = sysdepDLLgetProc( Inf, IDETOOL_STOPRUN, (P_FUN*)&idestopdll );
    if( IDEDRV_SUCCESS == retcode ) {
       idestopdll();
    }
#endif
}
#endif // NO_CTRL_HANDLERS

#ifndef NO_CTRL_HANDLERS
static void intHandler( int sig_num )
{
    sig_num = sig_num;
    StopRunning();
}
#endif // NO_CTRL_HANDLERS

static void initInterrupt( void )
{
#ifndef NO_CTRL_HANDLERS
    signal( SIGINT, intHandler );
#ifndef __UNIX__
    signal( SIGBREAK, intHandler );
#endif // __UNIX__
#endif // NO_CTRL_HANDLERS
}

static void finiInterrupt( void )
{
#ifndef NO_CTRL_HANDLERS
    signal( SIGINT, SIG_DFL );
#ifndef __UNIX__
    signal( SIGBREAK, SIG_DFL );
#endif // __UNIX__
#endif // NO_CTRL_HANDLERS
}

#ifndef NDEBUG
#define _SET_PROGRESS \
    if( getenv( "__idedrv_progress_messages" ) ) { info.progress_messages = 1; } \
    if( getenv( "__idedrv_progress_index" ) ) { info.progress_index = 1; }
#else
#define _SET_PROGRESS
#endif

#ifdef STATIC_LINKAGE
static int ensureLoaded( IDEDRV *inf, int *p_runcode )
{
    int runcode = 0;
    int retcode = IDEDRV_SUCCESS;

⌨️ 快捷键说明

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