cdinit.c

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

C
1,580
字号
/****************************************************************************
*
*                            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:  Initialization of data ( e.g. int foo[] = { 0, 1, 2 }; )
*
****************************************************************************/


#include "cvars.h"
#include <limits.h>
#include "i64.h"


local unsigned long BitMask[] = {
    0x00000001,
    0x00000003,
    0x00000007,
    0x0000000F,
    0x0000001F,
    0x0000003F,
    0x0000007F,
    0x000000FF,
    0x000001FF,
    0x000003FF,
    0x000007FF,
    0x00000FFF,
    0x00001FFF,
    0x00003FFF,
    0x00007FFF,
    0x0000FFFF,
    0x0001FFFF,
    0x0003FFFF,
    0x0007FFFF,
    0x000FFFFF,
    0x001FFFFF,
    0x003FFFFF,
    0x007FFFFF,
    0x00FFFFFF,
    0x01FFFFFF,
    0x03FFFFFF,
    0x07FFFFFF,
    0x0FFFFFFF,
    0x1FFFFFFF,
    0x3FFFFFFF,
    0x7FFFFFFF,
    0xFFFFFFFF
 };

/* use a double-linked list of dataquads to facilitate insertions */
typedef struct data_quad_list {
    DATA_QUAD               dq;
    unsigned long           size;
    struct data_quad_list   *prev, *next;
} DATA_QUAD_LIST;

#define DATA_QUAD_SEG_SIZE      (32 * 1024)
#define DATA_QUADS_PER_SEG      (DATA_QUAD_SEG_SIZE / sizeof( DATA_QUAD_LIST ))

#define MAX_DATA_QUAD_SEGS (LARGEST_DATA_QUAD_INDEX / DATA_QUADS_PER_SEG + 1)

static DATA_QUAD_LIST  *DataQuadSegs[MAX_DATA_QUAD_SEGS];/* segments for data quads*/
static DATA_QUAD_LIST  *CurDataQuad;
static int             DataQuadSegIndex;
static int             DataQuadIndex;

local   DATA_QUAD_LIST  *NewDataQuad( void );
local   int             CharArray( TYPEPTR typ );
local   int             WCharArray( TYPEPTR typ );
local   void            InitCharArray( TYPEPTR typ );
local   void            InitWCharArray( TYPEPTR typ );
local   void            StoreFloat( int float_type, unsigned long size );
local   void            StoreInt64( TYPEPTR typ );

int DataQuadsAvailable( void )
{
    DATA_QUAD_LIST  *dql = DataQuadSegs[ 0 ];

    return( dql != NULL && dql->next != NULL );
}

void InitDataQuads( void )
{
    DataQuadIndex = DATA_QUADS_PER_SEG;
    DataQuadSegIndex = -1;
    memset( DataQuadSegs, 0, sizeof( DataQuadSegs ) );
    /* put a guard at the start */
    CurDataQuad = NewDataQuad();
    CurDataQuad->prev = NULL;
    CurDataQuad->next = NULL;
    CurDataQuad->size = 0;
}

void FreeDataQuads( void )
{
    unsigned    i;

    for( i = 0; i < MAX_DATA_QUAD_SEGS; i++ ) {
        if( DataQuadSegs[i] == NULL ) break;
        FEfree( DataQuadSegs[i] );
    }
    InitDataQuads();
}

int StartDataQuadAccess( void )
{
    if( DataQuadsAvailable() ) {
        CurDataQuad = DataQuadSegs[ 0 ]->next;
        return( 1 );                    // indicate data quads exist
    }
    return( 0 );                        // indicate no data quads
}

DATA_QUAD *NextDataQuad( void )
{
    DATA_QUAD   *dq_ptr;

    if( CurDataQuad == NULL )
        return( NULL );
    dq_ptr = &CurDataQuad->dq;
    CurDataQuad = CurDataQuad->next;
    return( dq_ptr );
}

local DATA_QUAD_LIST *NewDataQuad( void )
{
    static DATA_QUAD_LIST   *DataQuadPtr;
    DATA_QUAD_LIST          *dql;

    if( DataQuadIndex >= (DATA_QUADS_PER_SEG - 1) ) {
        if( DataQuadSegIndex == MAX_DATA_QUAD_SEGS ) {
            CErr1( ERR_INTERNAL_LIMIT_EXCEEDED );
            CSuicide();
        }
        ++DataQuadSegIndex;
        DataQuadIndex = 0;
        DataQuadPtr = FEmalloc( DATA_QUAD_SEG_SIZE );
        DataQuadSegs[ DataQuadSegIndex ] = DataQuadPtr;
    }
    dql = DataQuadPtr;
    ++DataQuadIndex;
    ++DataQuadPtr;
    return dql;
}

/* splits the dataquad pointed to by dql so that the current one
   will have size "size" and the new one "oldsize - size" */
local void SplitDataQuad( DATA_QUAD_LIST *dql, unsigned long size )
{
    DATA_QUAD_LIST  *ndql;
    DATA_QUAD       *ndq;
    DATA_QUAD       *dq;
    unsigned long   oldsize;

    ndql = NewDataQuad();
    ndql->next = dql->next;
    ndql->prev = dql;
    dql->next = ndql;
    if( ndql->next != NULL )
        ndql->next->prev = ndql;
    oldsize = dql->size;
    ndql->size = oldsize - size;
    dql->size = size;

    ndq = &ndql->dq;
    dq = &dql->dq;
    memcpy( ndq, dq, sizeof( *dq ) );

    if( dq->flags & Q_DATA ) {
        if( dq->flags & Q_2_INTS_IN_ONE ) {
            dq->flags = ndq->flags = Q_DATA;
            ndq->u.long_values[0] = dq->u.long_values[1];
            ndq->u.long_values[1] = dq->u.long_values[1] = 0;
            size = 0;
        } else if( dq->flags & Q_REPEATED_DATA ) {
            dq->u.long_values[1] = size / (oldsize / dq->u.long_values[1]);
            ndq->u.long_values[1] -= dq->u.long_values[1];
            size = 0;
        } else if( dq->opr == T_CONSTANT ) {
            dq->u.long_values[0] = size;
            ndq->u.long_values[0] -= dq->u.long_values[0];
            size = 0;
        } else if( dq->opr == T_CONST ) {
            dq->u.string_leaf->length = size;
            ndq->u.string_leaf->literal += size;
            ndq->u.string_leaf->length = oldsize - size;
            size = 0;
        }
    }
    if( size != 0 ) {
        /* can't happen ! */
        CSuicide();
    }
}

local void DeleteDataQuad( DATA_QUAD_LIST *dql )
{
    dql->prev->next = dql->next;
    if( dql->next != NULL )
        dql->next->prev = dql->prev;
}

local void GenDataQuad( DATA_QUAD *dq, unsigned long size )
{
    DATA_QUAD_LIST  *dql;
    unsigned long   cursize;

    dql = CurDataQuad->next;
    if( dql != NULL ) {
        /* overwrite the current dataquad */
        cursize = dql->size;
        while( size > cursize && dql->next != NULL ) {
            DeleteDataQuad( dql );
            dql = dql->next;
            cursize += dql->size;
        }
        /* dql now takes up cursize bytes but was defined to
           take up dql->size bytes: split into a dataquad with
           dql->size - (cursize - size) bytes and one with
           cursize - size bytes.
        */
        if( size < cursize )
            SplitDataQuad( dql, dql->size - (cursize - size) );
    } else {
        dql = NewDataQuad();
        CurDataQuad->next = dql;
        dql->prev = CurDataQuad;
        dql->next = NULL;
    }
    dql->size = size;
    memcpy( &dql->dq, dq, sizeof(DATA_QUAD) );
    CurDataQuad = dql;
}

local void ZeroBytes( long n )
{
    DATA_QUAD   dq;

    if( n == 0 ) return;
    dq.opr = T_CONSTANT;
    dq.flags = Q_DATA;
    dq.u.long_values[0] = n;
    dq.u.long_values[1] = 0;
    GenDataQuad( &dq, n );
}

local void RelSeekBytes( long n )
{
    DATA_QUAD_LIST  *dql;

    dql = CurDataQuad;
    while( n < 0 && n <= -(long)dql->size ) {
        n += dql->size;
        dql = dql->prev;
    }
    while( n > 0 && dql->next != NULL ) {
        dql = dql->next;
        n -= dql->size;
    }
    /* now -dql->size < n <= 0 or dql->next == NULL */
    if( n < 0 ) {
        SplitDataQuad( dql, dql->size + n );
    }
    CurDataQuad = dql;
    if( n > 0 ) {
        /* dql->next == NULL */
        ZeroBytes( n );
    }
}

local void ChkConstant( unsigned long value, unsigned long max_value )
{
    if( value > max_value ) {                   /* 13-sep-91 */
        if( (value | (max_value >> 1)) != ~0UL ) {
            CWarn1( WARN_CONSTANT_TOO_BIG, ERR_CONSTANT_TOO_BIG );
        }
    }
}

local void StoreIValue( TOKEN int_type, unsigned long value,
                        unsigned long size )
{
    static DATA_QUAD_LIST   *LastCurDataQuad;
    DATA_QUAD_LIST          *dql;
    DATA_QUAD               *dq_ptr;
    DATA_QUAD               dq;

    dq.flags = 0;
    dq.opr = 0;
    dq_ptr = &dq;
    if( LastCurDataQuad == CurDataQuad ) {
        dq_ptr = &CurDataQuad->dq;
    }
    if( dq_ptr->opr == int_type  &&             /* 06-apr-92 */
        dq_ptr->flags == (Q_DATA | Q_REPEATED_DATA)  &&
        dq_ptr->u.long_values[0] == value ) {
        dq_ptr->u.long_values[1]++;             /* increment repeat count */
        CurDataQuad->size += size;
    } else if( dq_ptr->opr == int_type  &&  dq_ptr->flags == Q_DATA ) {
        if( dq_ptr->u.long_values[0] == value ) {
            dq_ptr->flags |= Q_REPEATED_DATA;
            dq_ptr->u.long_values[1] = 2;       /* repeat count */
        } else {
            dq_ptr->flags |= Q_2_INTS_IN_ONE;
            dq_ptr->u.long_values[1] = value;
        }
        CurDataQuad->size += size;
    } else {
        dq.opr = int_type;
        dq.flags = Q_DATA;
        dq.u.long_values[0] = value;
        if( value != 0 ) CompFlags.non_zero_data = 1;
        GenDataQuad( &dq, size );
        LastCurDataQuad = CurDataQuad;
        return;
    }
    /* if the next dataquad is non-empty we'll have to delete it */
    dql = CurDataQuad->next;
    if( dql != NULL ) {
        if( dql->size > size ) {
            SplitDataQuad( dql, size );
        }
        /* no need to "free" the next one, just remove it from the list */
        DeleteDataQuad( dql );
    }
}

local void StoreIValue64( uint64 value )
{
    DATA_QUAD           *dq_ptr;
    DATA_QUAD           dq;

    dq.opr = T___INT64;
    dq.flags = Q_DATA;
    dq_ptr = &dq;
    dq.u.long64 = value;
    CompFlags.non_zero_data = 1;
    GenDataQuad( &dq, sizeof( int64 ) );
}


typedef struct {
    long                       offset;
    union {
        STR_HANDLE       str_h;
        SYM_HANDLE       sym_h;
    };
    bool                      is_str;
    bool                      addr_set;
    bool                      is_error;
    enum { IS_VALUE, IS_ADDR } state;
} addrfold_info;

local void AddrFold( TREEPTR tree, addrfold_info *info )
{
// Assume tree has been const folded
    SYM_ENTRY           sym;
    long                offset = 0;

    switch( tree->op.opr ) {
    case OPR_PUSHINT:
        info->state = IS_ADDR;
        info->offset = tree->op.long_value;
        if( info->offset != 0 ) CompFlags.non_zero_data = 1;
        break;
    case OPR_PUSHFLOAT:
        info->state = IS_ADDR;
        if( tree->op.float_value->len != 0 ) {
            info->offset = (long)atof( tree->op.float_value->string );
        } else {
#ifdef _LONG_DOUBLE_
            long_double ld;
            double d;

⌨️ 快捷键说明

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