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 + -
显示快捷键?