dfline.c

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

C
537
字号
/****************************************************************************
*
*                            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 <stdlib.h>
#include "dfdip.h"
#include "dfline.h"

typedef struct {
    dword           offset;
    dword           line;
    unsigned_16     fno;
}cue_info;

enum {
    CUES_PER_BLK = 256,
};

typedef struct cue_blk{
    struct cue_blk     *next;
    cue_info            info[CUES_PER_BLK]; /*variable*/
}cue_blk;

struct seg_cue{
    struct seg_cue *next;
    addr_seg        seg;
    dword           low;
    dword           high;
    unsigned_16     count;    /*#entries collected by head */
    cue_blk         *head;    /* list of cues              */
};



extern void  InitCueList( cue_list *ctl ){
/*********************************/

    ctl->head = NULL;
}

extern  seg_cue *InitSegCue( cue_list *ctl, addr_seg seg, dword offset ){
/************************************************************************/
/* Keep in asending order  seg:offset */
    seg_cue  *curr;
    seg_cue **lnk;

    lnk = &ctl->head;
    while( (curr = *lnk) != NULL ){
        if( seg < curr->seg )break;
        if( seg == curr->seg && offset <  curr->low  )break;
        lnk = &curr->next;
    }
    curr = DCAlloc( sizeof( *curr ) );
    curr->seg = seg;
    curr->low = offset;
    curr->high = offset;
    curr->count = 0;
    curr->head = NULL;
    curr->next = *lnk;
    *lnk = curr;
    return( curr );
}

extern  void AddCue( seg_cue *ctl, dr_line_data *new ){
/************************************************************/
// Add a new offset to the last block if full alloc a new one
// bump the item count
    cue_blk     *blk, **lnk;
    cue_info    *next;
    unsigned_16 rem;    /*#entries in last blk */

    rem = ctl->count % CUES_PER_BLK;
    blk = ctl->head;
    if( blk != NULL ){
        while( blk->next  != NULL ){
            blk = blk->next;
        }
        lnk = &blk->next;
    }else{
        lnk = &ctl->head;
    }
    if( rem == 0 ){
        blk = DCAlloc( sizeof( *blk ) );
        blk->next = NULL;
        *lnk = blk;
    }
    next = &blk->info[rem];
    next->offset = new->offset;
    next->line = new->line;
    next->fno = new->file;
    if( new->offset > ctl->high ){
        ctl->high = new->offset;
    }
    ++ctl->count;
}


typedef struct{
    unsigned_16 hi;
    cue_info   *base;
    addr_off    key;
    unsigned_16 last;
}off_cmp;


static  long BlkOffSearch( off_cmp *cmp  ){
/****************************************/
// Do a B-search on the blk
    cue_info    *curr;
    cue_info    *base;
    addr_off    key;
    unsigned_16 lo;
    unsigned_16 mid;
    unsigned_16 hi;
    long        diff;

    key = cmp->key;
    base = cmp->base;
    hi = cmp->hi;
    lo = 0;
    for(;;){
        mid = (lo + hi)/2;
        curr = &base[mid];
        diff = (long)key - (long)curr->offset;
        if( mid == lo ){ /* fix up last cmp */
            break;
        }
        if( diff < 0 ){               // key < mid
            hi = mid;
        }else{                        // key > mid
            lo = mid;
        }
    }
    cmp->last = mid;
    cmp->base = curr;
    return( diff );
}

static  seg_cue  *FindSegCue( cue_list *list, addr_ptr *mach ){
/************************************************************/
    seg_cue   *ctl;
    seg_cue   *last;

    last = NULL;
    ctl = list->head;
    while( ctl != NULL ){
        if( mach->segment == ctl->seg ){
            if( mach->offset < ctl->low )break;
            last = ctl;
        }
        ctl = ctl->next;
    }
    return( last );
}

extern  int FindCueOffset( cue_list *list, addr_ptr *mach, cue_item *ret ){
/****************************************************/
    cue_blk    *blk;
    cue_info   *info;
    off_cmp     cmp;
    unsigned_16 rem;
    seg_cue   *ctl;
    long       diff;
    dword      next_off;

    info = NULL;
    ctl = FindSegCue( list, mach );
    if( ctl != NULL ){
        rem = CUES_PER_BLK;
        blk = ctl->head;
        while( blk != NULL ){
            if( blk->next == NULL ){ /* last blk */
                rem = ctl->count % CUES_PER_BLK;
                if( rem == 0 ){
                    rem = CUES_PER_BLK; /* never have empty blocks */
                }
            }
            info = &blk->info[rem-1];
            cmp.last  = rem-1;
            cmp.hi = rem;
            if( info->offset >= mach->offset ){
                cmp.key  = mach->offset;
                cmp.base = &blk->info[0];
                diff = BlkOffSearch( &cmp );
                if( diff >= 0 ){
                    info = cmp.base;
                    break;
                }else{
                     //shouldn't happen an error
                    return( FALSE );
                }
            }
            blk = blk->next;
        }
        ret->fno = info->fno;
        ret->line = info->line;
        ret->mach.offset = info->offset;
        ret->mach.segment = ctl->seg;
        ret->col = 0;
        if( cmp.last+1 < cmp.hi ){
            ++info;
            next_off = info->offset;
        }else{
            if( blk != NULL ){
                blk = blk->next;
            }
            if( blk == NULL ){
                next_off = 0xffffffff; /* high value */
                if( (ctl = ctl->next ) != NULL ){
                    if( ctl->seg == ret->mach.segment ){
                        next_off = ctl->low;
                    }
                }
            }else{
                 next_off= blk->info[0].offset;
            }
        }
        ret->next_offset = next_off;
        return( TRUE );
    }
    return( FALSE );
}

typedef enum{
    ST_START_LOW,         // look for next lower than cue
    ST_START_HIGH,        // look for next higher than cue
    ST_START_CLOSEST,     // look for lower or equal to cue
    ST_START_FILE,        // look for any cue with file
    ST_WRAP_LOW,          // found wrapped past low
    ST_WRAP_HIGH,         // found wrapped past high
    ST_SQUEEZE_LOW,       // found next lower
    ST_FOUND_CLOSEST,     // found next lower
    ST_SQUEEZE_HIGH,      // found next higher
}line_state;

extern   dfline_find FindCue( cue_list    *list,
                              cue_item    *item,
                              dfline_search what ){
/****************************************************/
    cue_blk        *blk;
    cue_info       *info;

⌨️ 快捷键说明

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