rewrite.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,211 行 · 第 1/3 页

C
1,211
字号
/****************************************************************************
*
*                            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 <stddef.h>

#include "errdefns.h"
#include "memmgr.h"
#include "preproc.h"
#include "carve.h"
#include "ptree.h"
#include "yydriver.h"
#include "rewrite.h"
#include "initdefs.h"
#include "pcheader.h"
#include "dbg.h"
#include "context.h"

/*
    The "rewrite file" consists of a string of tokens, each of which is
    preceded by one or more modifiers. The modifiers are decoded as follows:

        byte:   b'00000000' -- next bytes are SRCFILE for source file

                b'10000000' -- next 4 bytes are fetched as signed value
                            -- if value > 0
                                    value is column #, fetch token
                               else
                                    (-value) is line #

                b'1xxxxxxx' -- add 'xxxxxx' to line no., column <-- 0

                b'0xxxxxxx' -- add 'xxxxxx' to column, fetch token

    The sequence for a token is sumarized as:
        (a) optional file modifier
        (b) optional line modifier
        (c) column modifier
        (d) token

    Most tokens can be represented with their token number.  Some need
    more information to be saved like:

    T_STRING, T_LSTRING, T_ID, T_BAD_CHAR
        followed by bytes in token buffer ('\0' terminator)
    T_CONSTANT (integral)
        followed by <ConstType> <4-byte value> (least significant first)
    T_CONSTANT (floating point)
        followed by <ConstType> string of flt-pt number ('\0' terminator)
    T_BAD_TOKEN
        followed by contents of BadTokenInfo
*/

#define CODE_FILE 0x00              // code for SRCFILE
#define CODE_ABS  0x80              // code for line#, col#
#define MASK_ABS_LINE 0x80000000    // mask for absolute line
#define MASK_DELTA_LINE 0x80        // mask for delta line

static REWRITE *currRewrite;
static TOKEN_LOCN *currLocn;

#define BLOCK_REWRITE           8
#define BLOCK_REWRITE_TOKENS    8
#define BLOCK_SRCFILE_HANDLE    8

static carve_t carveREWRITE;
static carve_t carveREWRITE_TOKENS;
static carve_t carveSRCFILE_HANDLE;

static void rewriteInit( INITFINI* defn )
{
    defn = defn;
    currRewrite = NULL;
    carveREWRITE = CarveCreate( sizeof( REWRITE ), BLOCK_REWRITE );
    carveREWRITE_TOKENS = CarveCreate( sizeof( REWRITE_TOKENS ),
                                        BLOCK_REWRITE_TOKENS );
    carveSRCFILE_HANDLE = CarveCreate( sizeof( SRCFILE_HANDLE ),
                                        BLOCK_SRCFILE_HANDLE );
}

static void rewriteFini( INITFINI* defn )
{
    defn = defn;
    RewriteFree( currRewrite );
    currRewrite = NULL;
#ifndef NDEBUG
    CarveVerifyAllGone( carveREWRITE, "REWRITE" );
    CarveVerifyAllGone( carveREWRITE_TOKENS, "REWRITE_TOKENS" );
    CarveVerifyAllGone( carveSRCFILE_HANDLE, "SRCFILE_HANDLE" );
#endif
    CarveDestroy( carveREWRITE );
    CarveDestroy( carveREWRITE_TOKENS );
    CarveDestroy( carveSRCFILE_HANDLE );
}

INITDEFN( rewriting, rewriteInit, rewriteFini )

void RewriteFree( REWRITE *r )
/****************************/
{
    REWRITE_TOKENS *free_rt;
    REWRITE_TOKENS *rt;
    SRCFILE_HANDLE *h;
    SRCFILE_HANDLE *next_h;

    if( r == NULL ) {
        return;
    }
    if( ! r->alternate ) {
        for( rt = r->list; rt != NULL; ) {
            free_rt = rt;
            rt = rt->next;
            CarveFree( carveREWRITE_TOKENS, free_rt );
        }
        for( h = r->srcfiles_refd; h != NULL; h = next_h ) {
            next_h = h->next;
            CarveFree( carveSRCFILE_HANDLE, h );
        }
    }
    CarveFree( carveREWRITE, r );
}

static REWRITE_TOKENS *tokenAlloc( void )
{
    REWRITE_TOKENS *rt;

    rt = CarveAlloc( carveREWRITE_TOKENS );
    rt->next = NULL;
    rt->count = 0;
    rt->free = FALSE;
    return( rt );
}

static void putByte( REWRITE *r, uint_8 v )
{
    REWRITE_TOKENS *rt;

    rt = r->curr;
    if( rt->count == TOKEN_BLOCK_SIZE ) {
        REWRITE_TOKENS *new_rt;

        new_rt = tokenAlloc();
        rt->next = new_rt;
        r->curr = new_rt;
        rt = new_rt;
    }
    rt->stream[ rt->count++ ] = v;
}

static void putString( REWRITE *r, char *p )
{
    for( ; *p != '\0'; ++p ) {
        putByte( r, *p );
    }
    putByte( r, '\0' );
}

static void putBinary( REWRITE *r, uint_8 *bin, unsigned size )
{
    for( ; size > 0; --size, ++bin ) {
        putByte( r, *bin );
    }
}

static uint_32 newSrcFileHandle( REWRITE *r, SRCFILE src_file )
{
    uint_32 index;
    SRCFILE_HANDLE *p;
    SRCFILE_HANDLE **head;
    SRCFILE_HANDLE *e;

    index = 0;
    head = &(r->srcfiles_refd);
    for( p = *head; p != NULL; p = *head ) {
        if( p->srcfile == src_file ) {
            return( index );
        }
        ++index;
        head = &(p->next);
    }
    e = CarveAlloc( carveSRCFILE_HANDLE );
    e->next = NULL;
    e->srcfile = src_file;
    *head = e;
    return( index );
}

static SRCFILE accessSrcFile( REWRITE *r, uint_32 srcfile_index )
{
    SRCFILE_HANDLE *p;

    for( p = r->srcfiles_refd; p != NULL; p = p->next ) {
        if( srcfile_index == 0 ) {
            return( p->srcfile );
        }
        --srcfile_index;
    }
    return( NULL );
}

static void putSrcFile( REWRITE *r, TOKEN_LOCN *locn )
{
    uint_32 srcfile_index;

    srcfile_index = newSrcFileHandle( r, locn->src_file );
    putByte( r, CODE_FILE );
    putBinary( r, (uint_8*)&srcfile_index, sizeof( srcfile_index ) );
    locn->line = 0;
    locn->column = 0;
}

static void putSrcLocn( REWRITE *r, TOKEN_LOCN *locn )
{
    SRCFILE currfile;
    uint_32 absolute;
    uint_8 code_byte;

    currfile = SrcFileCurrent();
    if( currfile != locn->src_file ) {
        locn->src_file = currfile;
        putSrcFile( r, locn );
    }
    if( ( TokenLine - locn->line ) > 127 ) {
        putByte( r, CODE_ABS );
        absolute = TokenLine | MASK_ABS_LINE;
        putBinary( r, (uint_8*)&absolute, sizeof( absolute ) );
        locn->line = TokenLine;
    } else if( ( TokenLine - locn->line ) > 0 ) {
        code_byte = ( TokenLine - locn->line ) | MASK_DELTA_LINE;
        putByte( r, code_byte );
        locn->line = TokenLine;
    }
    if( ( TokenColumn - locn->column ) > 127 ) {
        putByte( r, CODE_ABS );
        absolute = TokenColumn;
        putBinary( r, (uint_8*)&absolute, sizeof( absolute ) );
        locn->column = TokenColumn;
    } else if( ( TokenColumn - locn->column ) > 0 ) {
        code_byte = TokenColumn - locn->column;
        putByte( r, code_byte );
        locn->column = TokenColumn;
    } else {                        // this guards against token at same col.
        putByte( r, CODE_ABS );
        absolute = TokenColumn;
        putBinary( r, (uint_8*)&absolute, sizeof( absolute ) );
        locn->column = TokenColumn;
    }
}

static void saveToken( REWRITE *r, TOKEN_LOCN *locn )
{
    putSrcLocn( r, locn );
    switch( CurToken ) {
    case T_STRING:
    case T_LSTRING:
    case T_ID:
    case T_BAD_CHAR:
        putByte( r, CurToken );
        putString( r, Buffer );
        break;
    case T_BAD_TOKEN:
        putByte( r, CurToken );
        putBinary( r, (uint_8*)&BadTokenInfo, sizeof( BadTokenInfo ) );
        break;
    case T_SAVED_ID:
        putByte( r, T_ID );
        putString( r, SavedId );
        break;
    case T_CONSTANT:
        putByte( r, CurToken );
        putByte( r, ConstType );
        switch( ConstType ) {
        case TYP_LONG_DOUBLE:
        case TYP_DOUBLE:
        case TYP_FLOAT:
            putString( r, Buffer );
            break;
        default:
            putBinary( r, (uint_8*)&Constant64, sizeof( Constant64 ) );
        }
        break;
    default:
        putByte( r, CurToken );
    }
}

static REWRITE *newREWRITE( int end_token, TOKEN_LOCN *locn )
{
    REWRITE *r;
    REWRITE_TOKENS *rt;

    r = CarveAlloc( carveREWRITE );
    rt = tokenAlloc();
    r->list = rt;
    r->curr = rt;
    r->srcfiles_refd = NULL;
    r->token = rt->stream;
    r->last_token = end_token;
    r->busy = FALSE;
    r->free = FALSE;
    r->alternate = FALSE;
    locn->src_file = SrcFileCurrent();
    putSrcFile( r, locn );
    return( r );
}

static REWRITE *dupREWRITE( REWRITE *old_r )
{
    REWRITE *r;

    r = CarveAlloc( carveREWRITE );
    r->list = old_r->list;
    r->curr = old_r->curr;
    r->srcfiles_refd = old_r->srcfiles_refd;
    r->token = old_r->token;
    r->last_token = old_r->last_token;
    r->busy = FALSE;
    r->alternate = TRUE;
    r->free = FALSE;
    return( r );
}

static PTREE recoverToken( PTREE tree )
{
    switch( tree->op ) {
    case PT_INT_CONSTANT:
    case PT_FLOATING_CONSTANT:
        /* these cases are not possible in correct C++ programs */
        /* Buffer and ConstType should still be set */
        CurToken = T_CONSTANT;
        break;
    case PT_ID:
        CurToken = T_SAVED_ID;
        SavedId = tree->u.id.name;
        break;
    case PT_UNARY:
    case PT_BINARY:
        switch( tree->cgop ) {
        case CO_INDIRECT:
            CurToken = T_TIMES;
            break;
        case CO_COLON_COLON:
            CurToken = T_COLON_COLON;
            break;
        case CO_OPERATOR:
            CurToken = T_OPERATOR;
            break;
        case CO_TILDE:
            CurToken = T_TILDE;
            break;
        case CO_NEW:
            CurToken = T_NEW;
            break;
        case CO_DELETE:
            CurToken = T_DELETE;
            break;
        case CO_STORAGE:
            return( tree );
        default:
#ifndef NDEBUG
            CFatal( "recoverToken: unknown tree cgop" );
#endif
            return( tree );
        }
        break;
    default:
#ifndef NDEBUG
        CFatal( "recoverToken: unknown tree cgop" );
#endif
        return( tree );
    }
    saveToken( currRewrite, currLocn );
    return( tree );
}

⌨️ 快捷键说明

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