📄 cdinit.c
字号:
/****************************************************************************
*
* 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 "i64.h"
#include "cvars.h"
#include <limits.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
};
#define DATA_QUAD_SEG_SIZE (16*1024)
#define DATA_QUADS_PER_SEG (DATA_QUAD_SEG_SIZE/sizeof(DATA_QUAD))
#define MAX_DATA_QUAD_SEGS (LARGEST_DATA_QUAD_INDEX/DATA_QUADS_PER_SEG + 1)
static DATA_QUAD *DataQuadSegs[MAX_DATA_QUAD_SEGS];/* segments for data quads*/
static int LastDataQuadSegIndex;
static DATA_QUAD *DataQuadPtr;
static int DataQuadIndex;
static int LastDataQuadIndex;
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 );
local void StoreInt64( TYPEPTR typ );
void InitDataQuads()
{
DataQuadIndex = DATA_QUADS_PER_SEG;
DataQuadSegIndex = -1;
memset( DataQuadSegs, 0, MAX_DATA_QUAD_SEGS * sizeof(DATA_QUAD *) );
}
void FreeDataQuads()
{
unsigned i;
for( i = 0; i < MAX_DATA_QUAD_SEGS; i++ ) {
if( DataQuadSegs[i] == NULL ) break;
FEfree( DataQuadSegs[i] );
}
InitDataQuads();
}
int StartDataQuadAccess()
{
if( DataQuadSegIndex != -1 ) {
DataQuadSegIndex = 0;
DataQuadIndex = 0;
DataQuadPtr = DataQuadSegs[ 0 ];
return( 1 ); // indicate data quads exist
}
return( 0 ); // indicate no data quads
}
DATA_QUAD *NextDataQuad()
{
DATA_QUAD *dq_ptr;
if( DataQuadIndex >= (DATA_QUADS_PER_SEG-1) ) {
++DataQuadSegIndex;
DataQuadIndex = 0;
DataQuadPtr = DataQuadSegs[ DataQuadSegIndex ];
}
++DataQuadIndex;
dq_ptr = DataQuadPtr;
++DataQuadPtr;
return( dq_ptr );
}
void GenDataQuad( DATA_QUAD *dq )
{
if( DataQuadIndex >= (DATA_QUADS_PER_SEG-1) ) {
if( DataQuadSegIndex == MAX_DATA_QUAD_SEGS ) {
CErr1( ERR_INTERNAL_LIMIT_EXCEEDED );
CSuicide();
}
++DataQuadSegIndex;
DataQuadIndex = 0;
DataQuadPtr = (DATA_QUAD *)FEmalloc( DATA_QUAD_SEG_SIZE );
DataQuadSegs[ DataQuadSegIndex ] = DataQuadPtr;
}
memcpy( DataQuadPtr, dq, sizeof(DATA_QUAD) );
++DataQuadIndex;
++DataQuadPtr;
DataQuadPtr->opr = T_EOF;
}
local void ZeroBytes( long n )
{
auto DATA_QUAD dq;
dq.opr = T_CONSTANT;
dq.flags = Q_DATA;
dq.u.long_values[0] = n;
dq.u.long_values[1] = 0;
GenDataQuad( &dq );
}
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 )
{
DATA_QUAD *dq_ptr;
auto DATA_QUAD dq;
dq.flags = 0;
dq.opr = 0;
dq_ptr = &dq;
if( LastDataQuadIndex == DataQuadIndex &&
LastDataQuadSegIndex == DataQuadSegIndex ) {
dq_ptr = DataQuadPtr - 1;
}
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 */
} 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;
}
} 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 );
LastDataQuadIndex = DataQuadIndex;
LastDataQuadSegIndex = DataQuadSegIndex;
}
}
local void StoreIValue64( uint64 value )
{
DATA_QUAD *dq_ptr;
auto 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 );
}
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;
ld = tree->op.float_value->ld;
__LDFD( (long_double near *)&ld,
(double near *)&d );
info->offset = (long)d;
#else
info->offset = (long)tree->op.float_value->ld.value;
#endif
}
if( info->offset != 0 ) CompFlags.non_zero_data = 1;
break;
case OPR_PUSHSTRING:
info->state = IS_ADDR;
if( info->addr_set ){
info->is_error = TRUE;
}
info->addr_set = TRUE;
info->is_str = TRUE;
info->str_h = tree->op.string_handle;
tree->op.string_handle->ref_count++;
CompFlags.non_zero_data = 1;
break;
case OPR_PUSHADDR:
info->state = IS_ADDR;
case OPR_PUSHSYM:
if( info->addr_set ){
info->is_error = TRUE;
}
info->addr_set = TRUE;
info->is_str = FALSE;
SymGet( &sym, tree->op.sym_handle );
info->sym_h = tree->op.sym_handle;
CompFlags.non_zero_data = 1;
if( sym.stg_class == SC_AUTO ){
info->is_error = TRUE;
}
break;
case OPR_INDEX:
if( tree->right->op.opr == OPR_PUSHINT ){
AddrFold( tree->left, info );
offset = tree->right->op.long_value;
}else if( tree->left->op.opr == OPR_PUSHINT ){
AddrFold( tree->right, info );
offset = tree->left->op.long_value;
}else{
info->is_error = TRUE;
}
if( info->state == IS_VALUE ){ // must be foldable
info->is_error = TRUE;
}
info->offset += offset * SizeOfArg( tree->expr_type );
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_ADD:
case OPR_SUB:
if( tree->right->op.opr == OPR_PUSHINT ){
AddrFold( tree->left, info );
if( tree->op.opr == OPR_ADD ) {
info->offset = info->offset+tree->right->op.long_value;
} else {
info->offset = info->offset-tree->right->op.long_value;
}
}else if( tree->left->op.opr == OPR_PUSHINT ){
AddrFold( tree->right, info );
if( tree->op.opr == OPR_ADD ) {
info->offset = tree->left->op.long_value+info->offset;
} else {
info->offset = tree->left->op.long_value-info->offset;
}
}else{
info->is_error = TRUE;
}
if( info->state == IS_VALUE ){ // must be foldable
info->is_error = TRUE;
}
break;
case OPR_ADDROF:
AddrFold( tree->right, info );
info->state = IS_ADDR;
CompFlags.non_zero_data = 1;
break;
case OPR_ARROW:
AddrFold( tree->left, info );
if( info->state == IS_VALUE ){ // must be foldable
info->is_error = TRUE;
}
info->offset += tree->right->op.long_value;
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_POINTS:
AddrFold( tree->left, info );
if( info->state == IS_VALUE ){ // must be foldable
info->is_error = TRUE;
}
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_DOT:
AddrFold( tree->left, info );
info->offset += tree->right->op.long_value;
CompFlags.non_zero_data = 1;
if( tree->op.flags & OPFLAG_RVALUE ) {
info->state = IS_VALUE;
}
break;
case OPR_CONVERT: //should check for pointer to smaller
case OPR_CONVERT_PTR:
AddrFold( tree->right, info );
break;
case OPR_ERROR: // error has already been issued
break;
default:
info->is_error = TRUE;
break;
}
}
local void StorePointer( TYPEPTR typ, TOKEN int_type )
{
int flags;
TREEPTR tree;
TYPEPTR typ2;
int address_wanted;
auto DATA_QUAD dq;
addrfold_info info;
dq.flags = Q_DATA;
flags = 0;
if( CompFlags.strings_in_code_segment ) flags = FLAG_CONST;/*01-sep-89*/
if( typ->decl_type == TYPE_POINTER ) {
if( typ->u.p.decl_flags & (FLAG_FAR|FLAG_HUGE) ) {
dq.flags |= Q_FAR_POINTER;
flags = FLAG_FAR;
} else if( typ->u.p.decl_flags & FLAG_NEAR ) {
dq.flags |= Q_NEAR_POINTER;
flags = 0;
} else {
typ2 = typ->object;
while( typ2->decl_type == TYPE_TYPEDEF ) typ2 = typ2->object;
if( typ2->decl_type == TYPE_FUNCTION ) {
dq.flags |= Q_CODE_POINTER;
} else if( TypeSize( typ ) == TARGET_FAR_POINTER ) {
dq.flags |= Q_FAR_POINTER;
}
}
}
address_wanted = 0;
if( CurToken == T_RIGHT_BRACE) { // t some x = {}
dq.opr = T_ID;
dq.u.var.sym_handle = 0;
dq.u.var.offset = 0;
}else{
tree = AddrExpr();
tree = InitAsgn( typ, tree ); // as if we are assigning
info.offset = 0;
info.sym_h = 0;
info.addr_set = FALSE;
info.state = IS_VALUE;
info.is_str = FALSE;
info.is_error = FALSE;
AddrFold( tree, &info );
FreeExprTree( tree );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -