cwchelp.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 407 行
C
407 行
/****************************************************************************
*
* 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: CauseWay trap file main loop.
*
****************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "watcom.h"
#include "trpimp.h"
#include "dpmi.h"
extern void ReadConfig( void );
#pragma aux ReadConfig "*";
extern void Int01Handler( void );
#pragma aux Int01Handler "*";
extern void Int03Handler( void );
#pragma aux Int03Handler "*";
extern void Int21Handler( void );
#pragma aux Int21Handler "*";
extern void Int31Intercept( void );
#pragma aux Int31Intercept "*";
extern void EInt01Handler( void );
#pragma aux EInt01Handler "*";
extern void EInt03Handler( void );
#pragma aux EInt03Handler "*";
extern void Exc00Handler( void );
#pragma aux Exc00Handler "*";
extern void Exc12Handler( void );
#pragma aux Exc12Handler "*";
extern void Exc13Handler( void );
#pragma aux Exc13Handler "*";
extern void Exc14Handler( void );
#pragma aux Exc14Handler "*";
extern void BreakChecker( void );
#pragma aux BreakChecker "*";
extern unsigned_16 _psp;
extern unsigned_16 PSPSegment;
#pragma aux PSPSegment "*";
extern unsigned_16 cwMajorVersion;
#pragma aux cwMajorVersion "*";
extern void __far *OldInt01;
#pragma aux OldInt01 "*";
extern void __far *OldInt03;
#pragma aux OldInt03 "*";
extern void __far *OldInt09;
#pragma aux OldInt09 "*";
extern void __far *OldInt21h;
#pragma aux OldInt21h "*";
extern void __far *OldInt31;
#pragma aux OldInt31 "*";
extern void __far *OldEInt01;
#pragma aux OldEInt01 "*";
extern void __far *OldEInt03;
#pragma aux OldEInt03 "*";
extern void __far *OldExc00;
#pragma aux OldExc00 "*";
extern void __far *OldExc12;
#pragma aux OldExc12 "*";
extern void __far *OldExc13;
#pragma aux OldExc13 "*";
extern void __far *OldExc14;
#pragma aux OldExc14 "*";
int CW_FarCallReal( rm_call_struct __far *call_st );
#pragma aux CW_FarCallReal = \
"push es" \
"mov es,dx" \
"mov ax,0ff02h" \
"int 0x31" \
"pop es" \
"sbb eax,eax" \
parm [dx edi] value [eax];
void dos_print( char *s );
#pragma aux dos_print = \
"mov ah,9h" \
"int 21h" \
parm [edx];
void dos_delete( char *filename );
#pragma aux dos_delete = \
"mov ah,41h" \
"int 21h" \
parm [edx];
// Needed because assembly stuff expects ES==DS
void fix_es( void );
#pragma aux fix_es = \
"push ds" \
"pop es";
// fuck stupid assembly interfaces
void *get_edi( void );
#pragma aux get_edi = \
"mov eax,edi";
struct trap_info {
unsigned_32 signature;
void *req_addr;
unsigned_32 real_call;
};
struct req_header {
void *buffer;
unsigned_32 length;
};
/* C trap request handlers */
extern unsigned (* const CoreRequests[])( void );
/* Assembly trap request handlers */
typedef unsigned_32 (req_fn)( void *req_in, void *req_out, unsigned_32 req_len );
#pragma aux req_fn parm [esi] [edi] [ecx] value [ecx] modify [eax];
typedef req_fn *preq_fn;
extern preq_fn ReqTable[128];
#pragma aux ReqTable "*";
static struct req_header *ReqAddress;
static char ReqBuffer[1024];
static unsigned_32 ReqLength;
static rm_call_struct RealModeRegs;
extern unsigned_32 DebugLevel;
#pragma aux DebugLevel "*";
char banner[] =
"哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪腬r\n"
"CauseWay Trap helper v4.00. Helper code is public domain. No rights reserved.\r\n"
"哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪腬r\n"
"\r\n$";
#if 0
#define DBG( ... ) dos_printf( __VA_ARGS__ )
#else
#define DBG( ... )
#endif
void dos_printf( const char *format, ... )
{
static char dbg_buf[256];
va_list args;
va_start( args, format );
vsnprintf( dbg_buf, sizeof( dbg_buf ), format, args );
// Convert to DOS string
dbg_buf[ strlen( dbg_buf ) ] = '\$';
dos_print( dbg_buf );
va_end( args );
}
// Print nicely formatted contents of a buffer. Useful for dumping
// debug requests and responses.
void HexDumpBuffer( const char *buf, int length )
{
int i, j;
int line_len;
#define DUMP_LINE_LEN 16
i = 0;
while( length > 0 ) {
line_len = length < DUMP_LINE_LEN ? length : DUMP_LINE_LEN;
for( j = 0; j < line_len; ++j )
dos_printf( "%02x ", buf[i + j] );
for( ; j < DUMP_LINE_LEN; ++j )
dos_printf( " " );
for( j = 0; j < line_len; ++j )
dos_printf( "%c", buf[i + j] );
dos_printf( "\r\n" );
length -= DUMP_LINE_LEN;
i += DUMP_LINE_LEN;
}
}
// Takes care of low-level link to the trap file and dishes out control
// to appropriate functions.
void Dispatcher( void )
{
int len;
unsigned_8 request;
void *out_ptr;
DBG( "Entered trap dispatcher\r\n" );
for( ;; ) {
// Transfer back to real mode
DBG( "Calling real mode..." );
CW_FarCallReal( &RealModeRegs );
DBG( "...back from RM\r\n" );
len = ReqAddress->length;
if( len > sizeof( ReqBuffer ) ) {
dos_printf( "Request buffer too long (%d bytes)!\r\n", len );
len = sizeof( ReqBuffer - 1 );
}
memcpy( ReqBuffer, ReqAddress->buffer, len );
ReqLength = len;
if( DebugLevel )
HexDumpBuffer( ReqBuffer, len );
// Check if this is a get lost message
request = ReqBuffer[0];
if( request == 0 )
break;
// Check if any results are needed and skip processing on
// this pass if they are
if( !(request & 0x80) ) {
// Pass control back to real mode ready for result transfer
DBG( "Calling real mode with results..." );
CW_FarCallReal( &RealModeRegs );
DBG( "...back from RM\r\n" );
}
// Go through all commands in the buffer
out_ptr = ReqAddress->buffer;
do {
int new_len;
request = ReqBuffer[0];
request &= 0x7f;
DBG( "Processing request %d\r\n", request );
if( CoreRequests[request] != NULL ) {
unsigned ret_len;
mx_entry in_entry;
mx_entry out_entry;
in_entry.ptr = (void *)&ReqBuffer;
in_entry.len = len;
In_Mx_Num = 1;
In_Mx_Ptr = &in_entry;
out_entry.ptr = out_ptr;
out_entry.len = 0;
Out_Mx_Num = 1;
Out_Mx_Ptr = &out_entry;
DBG( "Calling C trap request handler..." );
ret_len = CoreRequests[request]();
DBG( "...back from request\r\n" );
out_ptr = (char *)out_ptr + ret_len;
new_len = 0;
} else if( ReqTable[request] == NULL ) {
dos_printf( "Unimplemented request! (%d)\r\n", request );
// Display request buffer if we don't understand it
HexDumpBuffer( ReqBuffer, len );
} else {
DBG( "Calling assembly trap request handler..." );
// TODO: fix_es() and get_edi() need to go once all requests
// are handled in C
fix_es();
new_len = ReqTable[request]( &ReqBuffer, out_ptr, len );
out_ptr = get_edi();
DBG( "...back from request\r\n" );
DBG( "out_ptr: %p\r\n", out_ptr );
}
DBG( "new_len = %d\r\n", new_len );
if( new_len < 0 ) {
// If this happened, we're pretty much fucked
dos_printf( "cwhelp: underflow error in dispatcher!\r\n" );
dos_printf( "request = %d, len = %d, new_len = %d\r\n",
request, len, new_len );
HexDumpBuffer( ReqBuffer, 16 );
break;
}
len = new_len;
} while( len );
ReqAddress->length = (char *)out_ptr - (char *)ReqAddress->buffer;
if( DebugLevel )
HexDumpBuffer( ReqAddress->buffer, ReqAddress->length );
}
DBG( "Exiting trap dispatcher\r\n" );
}
int main( int argc, char **argv )
{
void **trap_ptr;
struct trap_info *trap_header;
unsigned_16 __far *cw_version;
PSPSegment = _psp;
dos_print( banner );
// Look for trap file header off interrupt vector 6
// (refer to LINK_SIGNATURE in dosxlink.c)
trap_ptr = (void *)(6 * sizeof( unsigned_32 ));
trap_header = *trap_ptr;
if( trap_header->signature != 0xdeb0deb0 ) {
dos_printf( "CauseWay trap file signature not found!\r\n" );
return( 1 );
}
// Get the transfer buffer address and real mode callback address
ReqAddress = trap_header->req_addr;
RealModeRegs.ip = trap_header->real_call & 0xFFFF;
RealModeRegs.cs = trap_header->real_call >> 16;
// Process the configuration file
ReadConfig();
// Delete debug log if in debug mode
if( DebugLevel )
dos_delete( "cwhelp.log" );
// Install debug interrupt (single step) handler
OldInt01 = DPMIGetPMInterruptVector( 1 );
DPMISetPMInterruptVector( 1, Int01Handler );
// Install debug breakpoint handler
OldInt03 = DPMIGetPMInterruptVector( 3 );
DPMISetPMInterruptVector( 3, Int03Handler );
// Install debug exception handler
OldEInt01 = DPMIGetPMExceptionVector( 1 );
DPMISetPMExceptionVector( 1, EInt01Handler );
// Install debug breakpoint exception handler
OldEInt03 = DPMIGetPMExceptionVector( 3 );
DPMISetPMExceptionVector( 3, EInt03Handler );
// Install exception 0 (divide by zero) handler
OldExc00 = DPMIGetPMExceptionVector( 0 );
DPMISetPMExceptionVector( 0, Exc00Handler );
// Install exception 12 (stack fault) handler
OldExc12 = DPMIGetPMExceptionVector( 12 );
DPMISetPMExceptionVector( 12, Exc12Handler );
// Install exception 13 (general protection fault) handler
OldExc13 = DPMIGetPMExceptionVector( 13 );
DPMISetPMExceptionVector( 13, Exc13Handler );
// Install exception 14 (page fault) handler
OldExc14 = DPMIGetPMExceptionVector( 14 );
DPMISetPMExceptionVector( 14, Exc14Handler );
// Install int 21h handler to catch termination
OldInt21h = DPMIGetPMInterruptVector( 0x21 );
DPMISetPMInterruptVector( 0x21, Int21Handler );
// Install keyboard interrupt handler so we can break in
OldInt09 = DPMIGetPMInterruptVector( 9 );
DPMISetPMInterruptVector( 9, BreakChecker );
// Install DPMI API handler
OldInt31 = DPMIGetPMInterruptVector( 0x31 );
// Save off the old CauseWay API version
cw_version = OldInt31;
--cw_version;
dos_printf( "CauseWay API version = %#04x\r\n", *cw_version );
DPMISetPMInterruptVector( 0x31, Int31Intercept );
Dispatcher();
// Restore old interrupt/exception handlers
DPMISetPMInterruptVector( 9, OldInt09 );
DPMISetPMInterruptVector( 0x21, OldInt21h );
DPMISetPMInterruptVector( 1, OldInt01 );
DPMISetPMInterruptVector( 3, OldInt03 );
DPMISetPMExceptionVector( 1, OldEInt01 );
DPMISetPMExceptionVector( 3, OldEInt03 );
DPMISetPMExceptionVector( 0, OldExc00 );
DPMISetPMExceptionVector( 12, OldExc12 );
DPMISetPMExceptionVector( 13, OldExc13 );
DPMISetPMExceptionVector( 14, OldExc14 );
return( 0 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?