b_write.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,191 行 · 第 1/3 页
C
1,191 行
/****************************************************************************
*
* 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 <string.h> // for memset
#include <stdarg.h> // for BRIAddType
#include <assert.h>
#include "b_write.h"
#include "carve.h"
#ifndef boolean
typedef int boolean;
#endif
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif
#ifndef EOF
#include <stdio.h>
#endif
#define BRI_write( cli, buf, len ) cli->rtns.write( cli->io_cookie, buf, len )
#define BRI_lseek( cli, off, whe ) cli->rtns.lseek( cli->io_cookie, off, whe )
#define BRI_malloc( cli, size ) cli->rtns.malloc( size )
#define BRI_free( cli, ptr ) cli->rtns.free( ptr )
#define LIST_BLOCK 0x180
#define CHAR_BLOCK 0x180
#define NUM_BUCKETS 0x100
#define BRI_MAX_LINE 0x00007ffful
#define BRI_MAX_COL 0x0000007ful
#define TYPE_BRANCH 8
#define TYPE_FULL( t ) ((t)->type_ids[TYPE_BRANCH-2]!=NULL)
#define TYPE_BOTTOM( t ) ((t)->next[0]==NULL)
/******************************
Type Declarations.
******************************/
typedef struct BRI_FileCounter {
BRI_StringID filename_id;
uint_32 line,column;
boolean template;
struct BRI_FileCounter * next;
} BRI_FileCounter;
typedef struct BRI_TypeCounter {
struct BRI_TypeCounter *next[TYPE_BRANCH];
BRI_TypeID type_ids[TYPE_BRANCH-1];
} BRI_TypeCounter;
typedef struct BRI_HashString {
struct BRI_HashString * next;
BRI_StringID index;
unsigned offset;
} BRI_HashString;
struct BRI_Handle {
/* callback functions */
BRI_Routines rtns;
/* Browse header */
BRI_Header * hdr;
/* file io information */
int io_cookie;
unsigned long start;
/* other data */
BRI_FileCounter * files;
BRI_TypeCounter * types;
carve_t carve_types;
/* string storage */
BRI_HashString * table[NUM_BUCKETS];
char * char_buf;
unsigned buf_size;
unsigned buf_top;
carve_t carve_string;
};
/*****************************
Static functions.
*****************************/
static uint_32 const bmask[5] = {
0x00000000,
0x000000ff,
0x0000ffff,
0x00ffffff,
0xffffffff,
};
/* hashString
*/
static int hashString( char const *string, int len )
/**************************************************/
{
uint_32 *s = (uint_32*) string;
uint_32 mask;
uint_32 c;
uint_32 g;
uint_32 h;
h = len;
c = len;
if( len > sizeof( uint_32 ) ) {
do {
c += *s;
h = ( h << 4 ) + c;
g = h & ~0x0ffffff;
h ^= g;
h ^= g >> (4+4+4+4+4);
++s;
len -= sizeof( uint_32 );
} while( len > sizeof( uint_32 ) );
}
mask = bmask[ len ];
c += *s & mask;
h = ( h << 4 ) + c;
g = h & ~0x0ffffff;
h ^= g;
h ^= g >> (4+4+4+4+4);
g = h & ~0x0fff;
h ^= g;
h ^= g >> (4+4+4);
h ^= h >> (2+4);
assert( ( h & ~0x0fff ) == 0 );
return( (int) (h%NUM_BUCKETS) );
}
/* insertStringID -- Insert a string into the string table without
replacement.
*/
static BRI_StringID insertStringID( BRI_HANDLE handle, BRI_StringID index,
char const *string, uint_32 length )
/************************************************************************/
{
BRI_StringID result;
BRI_HashString * current;
BRI_HashString * prev;
BRI_HashString * newstring;
int hash_val;
int comparison;
hash_val = hashString( string, length );
prev = NULL;
current = handle->table[hash_val];
while( current != NULL ){
comparison = strcmp( handle->char_buf+current->offset, string );
if( comparison >= 0 ){
break;
}
prev = current;
current = current->next;
}
if( current == NULL || comparison > 0 ){
newstring = CarveAlloc( handle->carve_string );
newstring->next = current;
newstring->index = index;
if( prev != NULL ){
prev->next = newstring;
} else {
handle->table[hash_val] = newstring;
}
if( length + handle->buf_top > handle->buf_size ){
int new_size;
char * temp;
new_size = 2*handle->buf_size;
if( new_size < length + handle->buf_top ){
new_size = length + handle->buf_top;
}
temp = BRI_malloc( handle, new_size*sizeof(char) );
memcpy( temp, handle->char_buf, handle->buf_size );
BRI_free( handle, handle->char_buf );
handle->char_buf = temp;
handle->buf_size = new_size;
}
newstring->offset = handle->buf_top;
memcpy( handle->char_buf+handle->buf_top, string,
length*sizeof(char) );
handle->buf_top += length;
result = index;
} else {
result = current->index;
}
return result;
}
/* insertTypeID -- Record a type id as having been seen.
Assumes the id was not seen previously.
*/
static void insertTypeID( BRI_HANDLE handle, BRI_TypeID type_id )
/***************************************************************/
{
BRI_TypeCounter *current;
BRI_TypeCounter *parent;
BRI_TypeID temp_id;
int follow;
int i;
current = handle->types;
if( current == NULL ){
current = CarveAlloc( handle->carve_types );
memset( current->type_ids, 0,
(TYPE_BRANCH-1)*sizeof(BRI_TypeID) );
memset( current->next, 0, TYPE_BRANCH*sizeof(BRI_TypeCounter *) );
current->type_ids[0] = type_id;
handle->types = current;
return;
}
parent = NULL;
for(;;){
if( TYPE_FULL( current ) ){
// Split the current node
BRI_TypeCounter *sibling;
BRI_TypeCounter *temp_ctr1, *temp_ctr2;
BRI_TypeID promote;
int divider;
divider = TYPE_BRANCH/2;
sibling = CarveAlloc( handle->carve_types );
memset( sibling->next, 0, TYPE_BRANCH*sizeof(BRI_TypeCounter *) );
memset( sibling->type_ids, 0,
(TYPE_BRANCH-1)*sizeof(BRI_TypeID) );
memcpy( sibling->next, current->next+divider,
divider*sizeof( BRI_TypeCounter * ) );
memcpy( sibling->type_ids, current->type_ids+divider,
(divider-1)*sizeof( BRI_TypeID ) );
promote = current->type_ids[divider-1];
memset( current->next+divider, 0,
divider*sizeof( BRI_TypeCounter * ) );
memset( current->type_ids+divider-1, 0,
divider*sizeof( BRI_TypeID ) );
if( parent == NULL ){
temp_ctr1 = CarveAlloc( handle->carve_types );
memset( temp_ctr1->next, 0,
TYPE_BRANCH*sizeof(BRI_TypeCounter *) );
memset( temp_ctr1->type_ids, 0,
(TYPE_BRANCH-1)*sizeof(BRI_TypeID) );
temp_ctr1->next[0] = current;
temp_ctr1->next[1] = sibling;
temp_ctr1->type_ids[0] = promote;
handle->types = temp_ctr1;
} else {
for( i=follow; i<TYPE_BRANCH-1; i++ ){
temp_id = parent->type_ids[i];
parent->type_ids[i] = promote;
promote = temp_id;
}
temp_ctr2 = sibling;
for( i=follow+1; i<TYPE_BRANCH; i++ ){
temp_ctr1 = parent->next[i];
parent->next[i] = temp_ctr2;
temp_ctr2 = temp_ctr1;
}
}
if( type_id > promote ){
current = sibling;
}
}
if( TYPE_BOTTOM( current ) ){
break;
}
for( follow=0; follow<TYPE_BRANCH-1; follow++ ){
if( current->type_ids[follow] == BRI_NULL_ID ){
break;
} else if( current->type_ids[follow] > type_id ){
break;
}
}
parent = current;
current = current->next[follow];
}
for( follow=0; follow<TYPE_BRANCH-1; follow++ ){
if( current->type_ids[follow] == BRI_NULL_ID ){
break;
} else if( current->type_ids[follow] > type_id ){
break;
}
}
for( i=follow; i<TYPE_BRANCH-1; i++ ){
temp_id = current->type_ids[i];
current->type_ids[i] = type_id;
type_id = temp_id;
}
return;
}
/******************************
External functions.
******************************/
/* BRIBeginWrite -- Create a browse handle, ready for use.
*/
BRI_HANDLE BRIBeginWrite( BRI_Routines const *rtns, int io_cookie,
unsigned long start )
/*****************************************************************/
{
BRI_HANDLE result;
BRI_Header * hdr;
result = (BRI_HANDLE) rtns->malloc( sizeof(BRI_Handle) );
if( result == NULL ) {
// TODO: FATAL ERROR
return (BRI_HANDLE) NULL;
}
memset( result, 0, sizeof( *result ) );
result->rtns = *rtns;
result->io_cookie = io_cookie;
result->start = start;
result->files = NULL;
result->types = NULL;
result->carve_types = CarveCreate( sizeof(BRI_TypeCounter), LIST_BLOCK );
result->char_buf = BRI_malloc( result, CHAR_BLOCK*sizeof(char) );
result->buf_size = CHAR_BLOCK;
result->buf_top = 0;
memset( result->table, 0, NUM_BUCKETS*sizeof(BRI_HashString*) );
result->carve_string = CarveCreate( sizeof(BRI_HashString), LIST_BLOCK );
hdr = (BRI_Header *) BRI_malloc( result, sizeof( BRI_Header ) );
memset( hdr, 0, sizeof(*hdr) );
hdr->magic = BRI_MAGIC;
hdr->major_ver = BRI_MAJOR_VER;
hdr->minor_ver = BRI_MINOR_VER;
BRI_write( result, hdr, sizeof( *hdr ) );
result->hdr = hdr;
return result;
}
/* BRIEndWrite -- Finish using a browse handle and destroy it.
*/
void BRIEndWrite( BRI_HANDLE handle )
/***********************************/
{
int out_len;
// int i;
// Get the current position in the file.
out_len = BRI_lseek( handle, 0, BRI_SEEK_CUR );
handle->hdr->file_len = out_len - handle->start;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?