omfutil.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 528 行 · 第 1/2 页
C
528 行
/****************************************************************************
*
* 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: Utility routines for OMF libraries.
*
****************************************************************************/
#include "wlib.h"
static OmfRecord *omfRec;
static unsigned omfRecLen;
static unsigned long charCount;
static unsigned long symCount;
static unsigned PrimeNos[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 0 /* terminator */
};
void InitOmfUtil()
{
omfRec = MemAlloc( INIT_OMF_REC_SIZE );
omfRecLen = INIT_OMF_REC_SIZE;
charCount = 0;
symCount = 0;
}
void FiniOmfUtil()
{
MemFree( omfRec );
omfRecLen = 0;
}
static void CheckForOverflow(file_offset current)
{
char buffer[10];
if ((current / Options.page_size) > (unsigned long)(USHRT_MAX)) {
sprintf(buffer, "%u", Options.page_size);
FatalError(ERR_LIB_TOO_LARGE, buffer);
}
}
void PadOmf( bool force )
{
unsigned padding;
char *tmpbuf;
// page size is always a power of 2
// therefor x % Options.page_size == x & ( Options.page_size - 1 )
padding = Options.page_size -( LibTell( NewLibrary ) & ( Options.page_size - 1 ) );
if( padding != Options.page_size || force ) {
tmpbuf = MemAlloc( padding );
memset( tmpbuf, 0, padding );
WriteNew( tmpbuf, padding );
MemFree( tmpbuf);
}
}
static bool ReadOmfRecord( libfile io )
{
if( LibRead( io, omfRec, 3 ) != 3 ) {
return( FALSE );
}
if ( omfRec->basic.len + 3 > omfRecLen ){
OmfRecord *new;
omfRecLen = omfRec->basic.len + 3;
new = MemAlloc( omfRecLen );
new->basic.len = omfRec->basic.len;
new->basic.type = omfRec->basic.type;
MemFree( omfRec );
omfRec = new;
}
if( LibRead( io, ( omfRec )->basic.contents, omfRec->basic.len ) != omfRec->basic.len ) {
return( FALSE );
}
return( TRUE );
}
static void WriteOmfRecord( void )
{
WriteNew( omfRec, omfRec->basic.len + 3 );
}
static void WriteTimeStamp( sym_file *file )
{
OmfRecord rec;
unsigned_8 sum;
unsigned i;
rec.time.type = CMD_COMENT;
rec.time.len = sizeof( rec.time ) - 3;
rec.time.attribute = CMT_TNP | CMT_TNL;
rec.time.class = CMT_LINKER_DIRECTIVE;
rec.time.subclass = LDIR_OBJ_TIMESTAMP;
rec.time.stamp = file->arch.date;
rec.time.chksum = 0;
sum = 0;
for( i = 0; i < sizeof( rec.time ); ++i ) {
sum += rec.chkcalc[i];
}
rec.time.chksum = -sum;
WriteNew( &rec, sizeof( rec.time ) );
}
void WriteOmfLibTrailer( void )
{
unsigned size;
size = DIC_REC_SIZE - LibTell( NewLibrary ) % DIC_REC_SIZE;
if( omfRecLen < size ){
omfRecLen = size;
MemFree( omfRec );
omfRec = MemAlloc( size );
}
memset( omfRec, 0, size );
omfRec->basic.type = LIB_TRAILER_REC;
omfRec->basic.len = size - 3;
WriteOmfRecord();
}
void WriteOmfLibHeader( unsigned_32 dict_offset, unsigned_16 dict_size )
{
OmfRecord rec; // i didn't use omfRec because page size can be quite big
LibSeek( NewLibrary, 0, SEEK_SET );
rec.lib_header.type = LIB_HEADER_REC;
rec.lib_header.page_size = Options.page_size - 3;
rec.lib_header.dict_offset = dict_offset;
rec.lib_header.dict_size = dict_size;
if( Options.respect_case ){
rec.lib_header.flags = 1;
} else {
rec.lib_header.flags = 0;
}
WriteNew( &rec, sizeof( rec.lib_header ) );
}
static int isPrime( unsigned num )
{
unsigned *test_p;
unsigned p;
for( test_p = PrimeNos;; ++test_p ) {
if( *test_p == 0 ){
return ( -1 );
}
p = *test_p;
if(( p * p ) > num ) break;
if(( num % p ) == 0 ) {
return( FALSE );
}
}
return( TRUE );
}
/*
* Find the prime number of dictionary pages
*/
static unsigned NextPrime( unsigned maj )
{
int test;
if( maj > 2 ) {
maj |= 1; /* make it odd */
do{
test = isPrime( maj );
maj += 2;
} while( test == 0 );
maj -= 2;
if ( test == -1 ){
return( 0 );
}
}
return( maj );
}
#define _rotl( a, b ) ( ( a << b ) | ( a >> ( 16 - b ) ) )
#define _rotr( a, b ) ( ( a << ( 16 - b ) ) | ( a >> b ) )
static bool InsertOmfDict( OmfLibBlock *lib_block, unsigned num_blocks,
char *sym, unsigned len, unsigned_16 offset )
{
char *leftptr;
char *rightptr;
unsigned_16 curr;
unsigned_16 block;
unsigned_16 bucket;
unsigned_16 dblock;
unsigned_16 dbucket;
unsigned count;
unsigned int loc;
unsigned int entry_len;
unsigned int i;
unsigned int j;
count = len;
leftptr = sym;
rightptr = leftptr + count;
block = count | 0x20;
dblock = 0;
bucket = 0;
dbucket = count | 0x20;
for( ;; ) {
--rightptr;
/* zap to lower case (sort of) */
curr = *rightptr | 0x20;
dblock = curr ^ _rotl( dblock, 2 );
bucket = curr ^ _rotr( bucket, 2 );
if( --count == 0 ) {
break;
}
curr = *leftptr | 0x20;
++leftptr;
block = curr ^ _rotl( block, 2 );
dbucket = curr ^ _rotr( dbucket, 2 );
}
bucket %= NUM_BUCKETS;
dbucket %= NUM_BUCKETS;
if( dbucket == 0 ) {
dbucket = 1;
}
block %= num_blocks;
dblock %= num_blocks;
if( dblock == 0 ) {
dblock = 1;
}
entry_len = (len | 1) + 3 ;
for( i = 0; i < num_blocks; i++ ) {
loc = lib_block[block].fflag * 2;
for( j = 0; j < NUM_BUCKETS; j++ ){
if( lib_block[block].htab[bucket] == 0 ) {
if( ( DIC_REC_SIZE - loc - 2 ) < entry_len ){
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?