dfcue.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 671 行 · 第 1/2 页
C
671 行
/****************************************************************************
*
* 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: DWARF DIP source line cues.
*
****************************************************************************/
#include <string.h>
#include <ctype.h>
#include "dfdip.h"
#include "dfld.h"
#include "dfaddr.h"
#include "dfline.h"
#include "dfmod.h"
#include "dfmodinf.h"
/************************/
/*** cue cache **********/
/************************/
extern void InitImpCueInfo( imp_image_handle *ii )
/************************************************/
{
cue_list *list;
list = ii->cue_map;
InitCueList( list );
list->imx = INVALID_IMX;
list->last.mach.segment = 0;
list->last.mach.offset = 0;
list->last.next_offset = 0;
}
static void ResetCueInfo( cue_list *list )
/*****************************************/
{
list->imx = INVALID_IMX;
list->last.mach.segment = 0;
list->last.mach.offset = 0;
list->last.next_offset = 0;
FiniCueInfo( list );
}
extern bool FiniImpCueInfo( imp_image_handle *ii )
/************************************************/
{
int ret;
cue_list *list;
list = ii->cue_map;
if( list->imx != INVALID_IMX ) {
ResetCueInfo( list );
ret = TRUE;
} else {
ret = FALSE;
}
return( ret );
}
imp_mod_handle DIPENTRY DIPImpCueMod( imp_image_handle *ii,
imp_cue_handle *ic )
/**********************************************************/
{
/* Return the module the source cue comes from. */
ii = ii;
return( IMX2IM (ic->imx ) );
}
typedef struct {
uint_16 index;
char *ret;
uint_16 num_dirs;
dr_line_dir *dirs;
} file_walk_name;
static int ACueFile( void *_info, dr_line_file *curr )
/****************************************************/
{
file_walk_name *info = _info;
int cont;
int i;
if( info->index == curr->index ) {
if( curr->name ) {
if( curr->dir != 0) {
for( i = 0; i < info->num_dirs; i++ ) {
if( info->dirs[i].index == curr->dir )
break;
}
if( i < info->num_dirs ) {
info->ret = DCAlloc( strlen( curr->name ) + strlen( info->dirs[i].name ) + 2);
strcpy( info->ret, info->dirs[i].name );
strcat( info->ret, "/");
strcat( info->ret, curr->name );
DCFree( curr->name );
} else {
/* This should be an error, but it isn't fatal as we should
* never get here in practice.
*/
info->ret = curr->name;
}
} else {
info->ret = curr->name;
}
} else {
info->ret = NULL;
}
cont = FALSE;
} else {
cont = TRUE;
DCFree( curr->name );
}
return( cont );
}
static int ACueDir( void *_info, dr_line_dir *curr )
/**************************************************/
{
file_walk_name *info = _info;
if( info ) {
info->dirs = DCRealloc( info->dirs, sizeof( dr_line_dir ) * (info->num_dirs + 1) );
info->dirs[info->num_dirs].index = curr->index;
info->dirs[info->num_dirs].name = DCAlloc( strlen( curr->name ) + 1 );
strcpy( info->dirs[info->num_dirs].name, curr->name );
info->num_dirs++;
}
return( TRUE );
}
static int IsRelPathname( const char *name )
/******************************************/
{
/* Detect UNIX or DOS style relative pathnames */
if( (name[0] == '/') || (name[0] == '\\') ) {
return( FALSE );
}
if( isalpha( name[0] ) && (name[1] == ':')
&& ((name[2] == '/') || (name[2] == '\\')) ) {
return( FALSE );
}
return( TRUE );
}
unsigned DIPENTRY DIPImpCueFile( imp_image_handle *ii,
imp_cue_handle *ic, char *buff, unsigned max )
/********************************************************************/
{
char *name;
char *dir_path;
file_walk_name wlk;
unsigned len;
unsigned dir_len;
im_idx imx;
dr_handle stmts;
dr_handle cu_handle;
int i;
imx = ic->imx;
DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */
stmts = ii->mod_map[imx].stmts;
if( stmts == NULL ) {
DCStatus( DS_FAIL );
return( 0 );
}
cu_handle = ii->mod_map[imx].cu_tag;
if( cu_handle == NULL ) {
DCStatus( DS_FAIL );
return( 0 );
}
wlk.index = ic->fno;
wlk.ret = NULL;
wlk.num_dirs = 0;
wlk.dirs = NULL;
DRWalkLFiles( stmts, ACueFile, &wlk, ACueDir, &wlk );
name = wlk.ret;
// Free directory and file table information
for( i = 0; i < wlk.num_dirs; i++)
DCFree(wlk.dirs[i].name);
DCFree(wlk.dirs);
if( name == NULL ) {
DCStatus( DS_FAIL );
return( 0 );
}
// If compilation unit has a DW_AT_comp_dir attribute, we need to
// stuff that in front of the file pathname, unless that is absolute
dir_len = DRGetCompDirBuff( cu_handle, NULL, 0 );
if( (dir_len > 1) && IsRelPathname( name ) ) { // Ignore empty comp dirs
if( max == 0 ) {
len = NameCopy( buff, name, max ) + dir_len;
} else {
dir_path = DCAlloc( dir_len );
if( dir_path == NULL ) {
DCStatus( DS_FAIL );
return( 0 );
}
DRGetCompDirBuff( cu_handle, dir_path, dir_len );
len = NameCopy( buff, dir_path, max );
DCFree( dir_path );
if( max > len + 1 ) {
len += NameCopy( buff + len, "/", 1 + 1 );
len += NameCopy( buff + len, name, max - len );
}
}
} else {
len = NameCopy( buff, name, max );
}
DCFree( name );
return( len );
}
typedef struct {
uint_16 fno;
dr_line_data first;
} first_cue_wlk;
static int TheFirstCue( void *_wlk, dr_line_data *curr )
/******************************************************/
{
first_cue_wlk *wlk = _wlk;
if( wlk->fno == curr->file ) {
wlk->first = *curr;
return( FALSE );
}
return( TRUE );
}
static int FirstCue( dr_handle stmts, uint_16 fno, imp_cue_handle *ic )
/*********************************************************************/
{
int cont;
first_cue_wlk wlk;
wlk.fno = fno;
cont = DRWalkLines( stmts, SEG_CODE, TheFirstCue, &wlk );
if( cont == FALSE ) {
ic->fno = wlk.first.file;
ic->line = wlk.first.line;
// ic->col = wlk.first.col;
ic->col = 0;
ic->a = NilAddr;
ic->a.mach.segment = wlk.first.seg;
ic->a.mach.offset = wlk.first.offset;
}
return( cont );
}
typedef struct {
dr_handle stmts;
imp_image_handle *ii;
im_idx imx;
IMP_CUE_WKR *wk;
imp_cue_handle *ic;
void *d;
walk_result wr;
} file_walk_cue;
static int ACueFileNum( void *_fc, dr_line_file *curr )
/*****************************************************/
{
file_walk_cue *fc = _fc;
int cont;
imp_cue_handle *ic;
dr_dbg_handle saved;
ic = fc->ic;
DCFree( curr->name );
ic->a = NilAddr;
ic->imx = fc->imx;
if( FirstCue( fc->stmts, curr->index, ic ) ) {
ic->fno = curr->index;
ic->line = 1;
ic->col = 0;
}
saved = DRGetDebug();
fc->wr = fc->wk( fc->ii, ic, fc->d );
DRSetDebug( saved );
if( fc->wr == WR_CONTINUE ) {
cont = TRUE;
} else {
cont = FALSE;
}
return( cont );
}
walk_result DIPENTRY DIPImpWalkFileList( imp_image_handle *ii,
imp_mod_handle im, IMP_CUE_WKR *wk, imp_cue_handle *ic,
void *d )
/*************************************************************************/
{
file_walk_cue wlk;
im_idx imx;
dr_handle stmts;
imx = IM2IMX( im );
DRSetDebug( ii->dwarf->handle ); /* must do at each call into DWARF */
stmts = ii->mod_map[imx].stmts;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?