⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stringl.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 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 "plusplus.h"
#include "memmgr.h"
#include "stringl.h"
#include "escchars.h"
#include "scan.h"
#include "initdefs.h"
#include "segment.h"
#include "pcheader.h"
#include "errdefns.h"
#include "preproc.h"
#include "carve.h"

#define DEFINE_UNICODE
#include "unicode.h"

static STRING_CONSTANT uniqueStrings;
static STRING_CONSTANT trashedStrings;

static unsigned stringCount;
static STRING_CONSTANT *stringTranslateTable;

static struct {
    unsigned            unique : 1;
} stringData;

static void walk_strings(       // WALK STRINGS IN A LIST
    STRING_CONSTANT str,        // - first string in a list
    void (*walker)              // - walking routine
        ( STRING_CONSTANT ) )   // - - current string
{
    while( str != NULL ) {
        (*walker)( str );
        str = str->next;
    }
}


void StringWalk(                // WALK DEFINED STRING LITERALS
    void (*walker)              // - walking routine
        ( STRING_CONSTANT ) )   // - - current string
{
    walk_strings( uniqueStrings, walker );
}

static void stringUnique( int yes )
{
    stringData.unique = yes;
}


static void stringInit(         // INITIALIZATION
    INITFINI* defn )            // - definition
{
    defn = defn;
    uniqueStrings = NULL;
    trashedStrings = NULL;
    stringCount = 0;
    stringUnique( 0 );
}

INITDEFN( strings, stringInit, InitFiniStub )

static STRING_CONSTANT initLiteral( STRING_CONSTANT literal )
{
    literal->next = NULL;
    literal->cg_handle = NULL;
    literal->segid = SEG_NULL;
    literal->concat = FALSE;
    literal->multi_line = FALSE;
    literal->wide_string = FALSE;
    return( literal );
}

static STRING_CONSTANT findLiteral( unsigned len )
{
    STRING_CONSTANT literal;
    STRING_CONSTANT prev;

    prev = NULL;
    literal = trashedStrings;
    while( literal != NULL ) {
        if( len <= literal->len ) {
            /* try to use more than 1/2 of the trashed string */
            if( len >= literal->len / 2 ) {
                if( prev != NULL ) {
                    prev->next = literal->next;
                } else {
                    trashedStrings = literal->next;
                }
                return( initLiteral( literal ) );
            }
        }
        prev = literal;
        literal = literal->next;
    }
    literal = CPermAlloc( offsetof( STRING_LITERAL, string ) + len + 1 );
    return( initLiteral( literal ) );
}

static unsigned compressLiteral( char *tgt, char *str, unsigned len )
/********************************************************************/
{
    unsigned chr;               // - current character
    char     chr_1;             // - one char ahead of current char
    char     classification;    // - escape classification
    int      max_digs;          // - max digits remaining
    unsigned new_len;           // - length after escapes processed
    struct {
        unsigned wide_string : 1;
    } flags;

#define store_chr(tgt,chr)  if(tgt) *tgt++ = (chr)

    flags.wide_string = FALSE;
    if( CurToken == T_LSTRING ) {
        flags.wide_string = TRUE;
    }
    new_len = 0;
    for( ; len > 0; ) {
        chr = *str++;
        --len;
        if( ( len > 0 ) && ( chr == '\\' ) ) {
            chr = *str++;
            -- len;
            classification = classify_escape_char( chr );
            if( classification == ESCAPE_OCTAL ) {
                chr_1 = octal_dig( chr );
                chr = 0;
                max_digs = 3;
                for( ; ; ) {
                    chr = ( chr << 3 ) | chr_1;
                    if( len == 0 ) break;
                    if( --max_digs == 0 ) break;
                    chr_1 = octal_dig( *str );
                    if( chr_1 == 8 ) break;
                    -- len;
                    ++ str;
                }
            } else if( classification == ESCAPE_HEX ) {
                if( ( len > 1 ) && ( 16 != hex_dig( *str ) ) ) {
                    chr = 0;
                    max_digs = 8;
                    for( ; ; ) {
                        if( len == 0 ) break;
                        if( max_digs == 0 ) break;
                        chr_1 = hex_dig( *str );
                        if( chr_1 == 16 ) break;
                        chr = ( chr << 4 ) | chr_1 ;
                        -- max_digs;
                        ++ str;
                        -- len;
                    }
                }
            } else if( classification != ESCAPE_NONE ) {
                chr = classification;
            }
            if( flags.wide_string ) {
                store_chr( tgt, chr );
                ++ new_len;
                chr = chr >> 8;
            }
        } else {
            if( CharSet[chr] & C_DB ) {       /* if double-byte character */
                if( CompFlags.jis_to_unicode && flags.wide_string ) {
                    chr = (chr << 8) + *str;
                    chr = JIS2Unicode( chr );
                    store_chr( tgt, chr );
                    chr = chr >> 8;
                } else {
                    store_chr( tgt, chr );
                    chr = *str;
                }
                ++ new_len;
                ++ str;
                -- len;
            } else if( flags.wide_string ) {
                if( CompFlags.use_unicode ) {           /* 05-jun-91 */
                    chr = UniCode[ chr ];
                } else if( CompFlags.jis_to_unicode ) {
                    chr = JIS2Unicode( chr );
                }
                store_chr( tgt, chr );
                ++ new_len;
                chr = chr >> 8;
//          } else {
//              _ASCIIOUT( chr );
            }
        }
        store_chr( tgt, chr );
        ++new_len;
    }
    --new_len;  /* take one of the '\0' from the end */
    return( new_len );
}


static STRING_CONSTANT makeLiteral( char *s, unsigned len )
/*********************************************************/
{
    STRING_CONSTANT literal;
    unsigned        new_len;

    new_len = len;
    if( CurToken == T_LSTRING ) {
        new_len = compressLiteral( NULL, s, len + 1 );
    }
    literal = findLiteral( new_len );
    literal->len = compressLiteral( literal->string, s, len + 1 );
    if( CurToken == T_LSTRING ) {
        literal->wide_string = TRUE;
    }
    return( literal );
}

void StringTrash( STRING_CONSTANT string )
/****************************************/
{
    STRING_CONSTANT *head;
    STRING_CONSTANT search;

    head = &uniqueStrings;
    for( search = *head; search != NULL; search = *head ) {
        if( string == search ) {
            --stringCount;
            *head = search->next;
            string->next = trashedStrings;
            trashedStrings = string;
            return;
        }
        head = &(search->next);
    }
}


static STRING_CONSTANT stringAdd(// ADD LITERAL TO STRING
    STRING_CONSTANT literal,    // - literal to be added
    STRING_CONSTANT *list )     // - addr( list )
{
    literal->next = *list;
    *list = literal;
    return( literal );
}


STRING_CONSTANT StringCreate( char *s, unsigned len )
/***************************************************/
{
    ++stringCount;
    return( stringAdd( makeLiteral( s, len ), &uniqueStrings ) );
}

void StringConcatDifferentLines( STRING_CONSTANT v )
/**************************************************/
{
    v->multi_line = TRUE;
}

STRING_CONSTANT StringConcat( STRING_CONSTANT v1, STRING_CONSTANT v2 )
/********************************************************************/
{
    STRING_CONSTANT literal;
    unsigned        len;        // - length

    if( v1->wide_string != v2->wide_string ) {
        // an error has already been diagnosed
        StringTrash( v2 );
        return v1;
    }
    literal = findLiteral( v1->len + v2->len );
    literal->concat = TRUE;
    memcpy( literal->string, v1->string, v1->len );
    len = v1->len;
    if( v1->wide_string ) {
        --len;
        literal->wide_string = TRUE;
    }
    if( v1->multi_line ) {
        literal->multi_line = TRUE;
    }
    literal->len = len + v2->len;
    memcpy( &(literal->string[ len ]), v2->string, v2->len + 1 );
    StringTrash( v1 );
    StringTrash( v2 );
    ++stringCount;
    return( stringAdd( literal, &uniqueStrings ) );
}

boolean StringSame( STRING_CONSTANT v1, STRING_CONSTANT v2 )
/**********************************************************/
{
    if( v1->len != v2->len ) {
        return( FALSE );
    }
    return( memcmp( v1->string, v2->string, v1->len + 1 ) == 0 );
}

size_t StringByteLength( STRING_CONSTANT s )
/******************************************/
{
    // byte length should include '\0' character
    return s->len + TARGET_CHAR;
}

size_t StringAWStrLen( STRING_CONSTANT s )
/****************************************/
{
    size_t len;

    // string length should include '\0' character
    if( s->wide_string ) {
        DbgAssert( s->len & 1 );
        len = ( s->len + 1 ) / TARGET_WIDE_CHAR;
    } else {
        len = ( s->len + 1 ) / TARGET_CHAR;
    }
    return( len );
}

char *StringBytes( STRING_CONSTANT s )
/************************************/
{
    return s->string;
}

static int cmpString( const void *lp, const void *rp )
{
    STRING_CONSTANT left = *(STRING_CONSTANT *)lp;
    STRING_CONSTANT right = *(STRING_CONSTANT *)rp;

    if( left < right ) {
        return( -1 );
    } else if( left > right ) {
        return( 1 );
    }
    return( 0 );
}

pch_status PCHInitStringPool( boolean writing )
{
    STRING_CONSTANT curr;
    STRING_CONSTANT *p;

    if( ! writing ) {
        return( PCHCB_OK );
    }
    stringTranslateTable = CMemAlloc( stringCount * sizeof( STRING_CONSTANT ) );
    p = stringTranslateTable;
    for( curr = uniqueStrings; curr != NULL; curr = curr->next ) {
        *p = curr;
        ++p;
    }
    qsort( stringTranslateTable, stringCount, sizeof( STRING_CONSTANT ), cmpString );
#ifndef NDEBUG
    {
        int i;
        for( i = 1; i < stringCount; ++i ) {
            if( stringTranslateTable[i-1] == stringTranslateTable[i] ) {
                CFatal( "two identical strings in translation table" );
            }
        }
    }
#endif
    return( PCHCB_OK );
}

pch_status PCHFiniStringPool( boolean writing )
{
    writing = writing;
    CMemFreePtr( &stringTranslateTable );
    return( PCHCB_OK );
}

pch_status PCHReadStringPool( void )
{
    STRING_CONSTANT *p;
    STRING_CONSTANT str;
    size_t str_len;

    while( uniqueStrings != NULL ) {
        StringTrash( uniqueStrings );
    }
    PCHRead( &stringCount, sizeof( stringCount ) );
    stringTranslateTable = CMemAlloc( stringCount * sizeof( STRING_CONSTANT ) );
    p = stringTranslateTable;
    for(;;) {
        str_len = PCHReadUInt();
        if( str_len == 0 ) break;
        str = findLiteral( str_len );
        str->len = str_len - 1;
        PCHRead( str->string, str_len );
        stringAdd( str, &uniqueStrings );
        *p = str;
        ++p;
    }
    return( PCHCB_OK );
}

pch_status PCHWriteStringPool( void )
{
    size_t dummy_len;
    int i;
    STRING_CONSTANT str;
    STRING_CONSTANT *p;

    PCHWrite( &stringCount, sizeof( stringCount ) );
    p = stringTranslateTable;
    for( i = 0; i < stringCount; ++i ) {
        str = p[i];
        dummy_len = StringByteLength( str );
        PCHWriteUInt( dummy_len );
        PCHWrite( StringBytes( str ), dummy_len );
    }
    dummy_len = 0;
    PCHWriteUInt( dummy_len );
    return( PCHCB_OK );
}

STRING_CONSTANT StringMapIndex( STRING_CONSTANT index )
/*****************************************************/
{
    if( index < (STRING_CONSTANT) PCH_FIRST_INDEX ) {
        return( NULL );
    }
#ifndef NDEBUG
    if( ((unsigned) index) >= stringCount + PCH_FIRST_INDEX ) {
        CFatal( "invalid string index" );
    }
#endif
    return stringTranslateTable[ ((unsigned) index) - PCH_FIRST_INDEX ];
}

static int cmpFindString( const void *kp, const void *tp )
{
    STRING_CONSTANT key = *(STRING_CONSTANT *)kp;
    STRING_CONSTANT table = *((STRING_CONSTANT *)tp);

    if( key < table ) {
        return( -1 );
    } else if( key > table ) {
        return( 1 );
    }
    return( 0 );
}

STRING_CONSTANT StringGetIndex( STRING_CONSTANT str )
/**************************************************/
{
    STRING_CONSTANT *found;

    if( str == NULL ) {
        return( (STRING_CONSTANT) PCH_NULL_INDEX );
    }
    found = bsearch( &str, stringTranslateTable, stringCount, sizeof( STRING_CONSTANT ), cmpFindString );
    if( found == NULL ) {
#ifndef NDEBUG
        CFatal( "invalid string passed to StringGetIndex" );
#endif
        return( (STRING_CONSTANT) PCH_ERROR_INDEX );
    }
    return( (STRING_CONSTANT) (( found - stringTranslateTable ) + PCH_FIRST_INDEX ) );
}

⌨️ 快捷键说明

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