watlnum.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 654 行 · 第 1/2 页
C
654 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "dipwat.h"
#include "dbcue.h"
#include <stddef.h>
#include <string.h>
extern void *InfoLoad(imp_image_handle *, imp_mod_handle,unsigned,unsigned,void (*)());
extern void InfoUnlock(void);
extern void InfoSpecUnlock(void *);
extern unsigned InfoSize(imp_image_handle *, imp_mod_handle,unsigned int, unsigned );
extern mem_block FindSegBlock(imp_image_handle *, imp_mod_handle,unsigned long );
extern mod_info *ModPointer( imp_image_handle *, imp_mod_handle );
extern unsigned PrimaryCueFile( imp_image_handle *, imp_cue_handle *, char *, unsigned );
extern void *FindSpecCueTable( imp_image_handle *, imp_mod_handle, void ** );
extern address NilAddr;
static void *LinStart;
static void *LinEnd;
static byte V2Lines;
#define NO_LINE ((unsigned_16)-1)
typedef union {
v2_line_segment v2;
v3_line_segment v3;
} line_segment;
#define NEXT_SEG( ptr ) (V2Lines ? ((line_segment *)&((ptr)->v2.line[(ptr)->v2.num])) \
: ((line_segment *)&((ptr)->v3.line[(ptr)->v3.num])))
#define LINE_SEG( ptr ) (V2Lines ? (ptr)->v2.segment : (ptr)->v3.segment)
#define LINE_NUM( ptr ) (V2Lines ? (ptr)->v2.num : (ptr)->v3.num)
#define LINE_LINE( ptr) (V2Lines ? (ptr)->v2.line : (ptr)->v3.line)
static int CueFind( cue_state *base, cue_idx cue, cue_state *ret )
{
cue_state *curr;
long diff;
unsigned_16 lo;
unsigned_16 mid;
int ok;
unsigned hi;
if( base == NULL ) return( 0 );
hi = *(unsigned_16*)base;
base = (void *)((char *)base + 2);
cue -= PRIMARY_RANGE;
ok = 0;
lo = 0;
for(;;){
mid = (lo + hi)/2;
curr = &base[mid]; // compare keys
diff = (long)cue - (long)(curr->cue);
if( mid == lo )break;
if( diff < 0 ){ // key < mid
hi = mid;
}else if( diff > 0 ){ // key > mid
lo = mid;
}else{ // key == mid
break;
}
}
if( diff >= 0 ){
ok = 1;
}
*ret = *curr;
ret->line += diff;
ret->fno += 2; /* 0 => no file, 1 => primary file */
return( ok );
}
static unsigned long SpecCueLine( imp_image_handle *ii, imp_cue_handle *ic,
unsigned cue_id )
{
cue_state info;
unsigned long ret;
void *start;
void *base;
ret = 0;
start = FindSpecCueTable( ii, ic->im, &base );
if( start != NULL ) {
if( CueFind( start, cue_id, &info ) ){
ret = info.line;
}
InfoSpecUnlock( base );
}
return( ret );
}
static unsigned SpecCueFileId( imp_image_handle *ii, imp_cue_handle *ic,
unsigned cue_id )
{
cue_state info;
unsigned long ret;
void *start;
void *base;
ret = 0;
start = FindSpecCueTable( ii, ic->im, &base );
if( start != NULL ) {
if( CueFind( start, cue_id, &info ) ){
ret = info.fno;
}
InfoSpecUnlock( base );
}
return( ret );
}
static unsigned SpecCueFile( imp_image_handle *ii, imp_cue_handle *ic,
unsigned file_id, char *buff, unsigned max )
{
unsigned_16 size;
unsigned_16 len;
unsigned_16 *index;
char *name;
void *start;
void *base;
len = 0;
start = FindSpecCueTable( ii, ic->im, &base );
if( start != NULL ) {
size = *(unsigned_16*)start;
start = (char *)start + 2;
start = (char *)start + size * sizeof( cue_state );
size = *(unsigned_16*)start;
start = (char *)start + 2;
index = start;
name = (char *)start + size * sizeof( unsigned_16 );
name += index[file_id-2]; /* see comment in CueFind */
len = strlen( name );
if( max > 0 ) {
--max;
if( max > len ) max = len;
memcpy( buff, name, max );
buff[ max ] = '\0';
}
InfoSpecUnlock( base );
}
return( len );
}
/*
* GetLineInfo -- get the line number infomation for a module
*/
static void UnlockLine( void )
{
if( LinStart != NULL ) {
InfoSpecUnlock( LinStart );
LinStart = NULL; /* so we don't unlock the same section twice */
}
}
static dip_status GetLineInfo( imp_image_handle *ii, imp_mod_handle im,
unsigned entry )
{
if( entry != 0 ) UnlockLine();
LinStart = InfoLoad( ii, im, DMND_LINES, entry, NULL );
if( LinStart == NULL ) return( DS_FAIL );
LinEnd = (byte *)LinStart + InfoSize( ii, im, DMND_LINES, entry );
V2Lines = ii->v2;
return( DS_OK );
}
struct search_info {
imp_cue_handle ic;
unsigned num;
addr_off off;
search_result have;
byte found;
void *special_table;
enum { ST_UNKNOWN, ST_NO, ST_YES } have_spec_table;
};
static line_info *FindLineOff( addr_off off, addr_off adj,
void *start, void *end,
struct search_info *close, imp_image_handle *ii )
{
line_info *ln_ptr;
int low, high, target;
addr_off chk;
void *dummy;
low = 0;
/* get number of entries minus one */
high = ((char *)end - (char *)start) / sizeof( line_info ) - 1;
/* point at first entry */
ln_ptr = start;
while( low <= high ) {
target = (low + high) >> 1;
chk = ln_ptr[ target ].code_offset + adj;
if( off < chk ) {
high = target - 1;
} else if( off > chk ) {
low = target + 1;
} else { /* exact match */
if( ln_ptr[ target ].line_number >= PRIMARY_RANGE ) {
/* a special cue - have to make sure we have the table */
if( close->have_spec_table == ST_UNKNOWN ) {
if( FindSpecCueTable( ii, close->ic.im, &dummy ) != NULL ) {
close->have_spec_table = ST_YES;
} else {
close->have_spec_table = ST_NO;
}
}
if( close->have_spec_table == ST_YES ) {
return( &ln_ptr[ target ] );
}
} else {
return( &ln_ptr[ target ] );
}
/* if it's a special & we don't have the table, ignore entry */
high = target - 1;
}
}
if( high < 0 ) return( NULL );
if( ln_ptr[ high ].line_number >= PRIMARY_RANGE ) {
/* a special cue - have to make sure we have the table */
if( close->have_spec_table == ST_UNKNOWN ) {
if( FindSpecCueTable( ii, close->ic.im, &dummy ) != NULL ) {
close->have_spec_table = ST_YES;
} else {
close->have_spec_table = ST_NO;
}
}
if( close->have_spec_table == ST_NO ) {
/* if it's a special & we don't have the table, ignore entry */
for( ;; ) {
--high;
if( high < 0 ) return( NULL );
if( ln_ptr[ high ].line_number < PRIMARY_RANGE ) break;
}
}
}
return( &ln_ptr[ high ] );
}
#define BIAS( p ) ((byte *)(p) - (byte *)LinStart)
#define UNBIAS( o ) ((void *)((byte *)LinStart + (o)))
static void SearchSection( imp_image_handle *ii,
struct search_info *close, address addr )
{
line_segment *seg;
line_segment *next;
line_info *info;
mem_block block;
close->found = 0;
for( seg = LinStart; seg < LinEnd; seg = next ) {
next = NEXT_SEG( seg );
block = FindSegBlock( ii, close->ic.im, LINE_SEG( seg ) );
if( DCSameAddrSpace( block.start, addr ) != DS_OK ) continue;
if( block.start.mach.offset > addr.mach.offset ) continue;
if( block.start.mach.offset + block.len <= addr.mach.offset ) continue;
info = FindLineOff( addr.mach.offset, block.start.mach.offset,
LINE_LINE( seg ), next, close, ii );
if( info == NULL ) continue;
if( close->have == SR_NONE
|| info->code_offset+block.start.mach.offset>close->off ) {
close->found = 1;
close->ic.seg_bias = BIAS( seg );
close->ic.info_bias = BIAS( info );
close->off = block.start.mach.offset + info->code_offset;
if( close->off == addr.mach.offset ) {
close->have = SR_EXACT;
} else {
close->have = SR_CLOSEST;
}
}
}
}
search_result DIPENTRY DIPImpAddrCue( imp_image_handle *ii, imp_mod_handle im,
address addr, imp_cue_handle *ic )
{
struct search_info close;
unsigned save_entry;
close.ic.im = im;
close.have = SR_NONE;
close.ic.entry = 0;
close.have_spec_table = ST_UNKNOWN;
for( ;; ) {
if( GetLineInfo( ii, close.ic.im, close.ic.entry ) != DS_OK ) break;
SearchSection( ii, &close, addr );
if( close.found ) save_entry = close.ic.entry;
if( close.have == SR_EXACT ) break;
++close.ic.entry;
}
*ic = close.ic;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?