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