queues.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 428 行

C
428
字号
/****************************************************************************
*
*                            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:  Output OBJ queues routines
*
****************************************************************************/

#include "asmglob.h"

#include "asmalloc.h"
#include "mangle.h"
#include "asmins.h"
#include "directiv.h"
#include "queue.h"
#include "queues.h"

#include "myassert.h"

typedef struct queuenode {
    void *next;
    void *data;
} queuenode;

static qdesc   *LnameQueue  = NULL;   // queue of LNAME structs
static qdesc   *PubQueue    = NULL;   // queue of pubdefs
static qdesc   *GlobalQueue = NULL;   // queue of global / externdefs
static qdesc   *AliasQueue  = NULL;   // queue of aliases
static qdesc   *LinnumQueue = NULL;   // queue of linnum_data structs

static void QAddQItem( qdesc **queue, queuenode *node )
/*****************************************************/
{
    if( *queue == NULL ) {
        *queue = AsmAlloc( sizeof( qdesc ) );
        QInit( *queue );
    }
    QEnqueue( *queue, node );
}

static void QAddItem( qdesc **queue, void *data )
/***********************************************/
{
    struct queuenode    *node;

    node = AsmAlloc( sizeof( queuenode ) );
    node->data = data;
    if( *queue == NULL ) {
        *queue = AsmAlloc( sizeof( qdesc ) );
        QInit( *queue );
    }
    QEnqueue( *queue, node );
}

static long QCount( qdesc *q )
/****************************/
/* count the # of entries in the queue, if the retval is -ve we have an error */
{
    long        count = 0;
    queuenode   *node;

    if( q == NULL )
        return( 0 );
    for( node = q->head; node != NULL; node = node->next ) {
        if( ++count < 0 ) {
            return( -1 );
        }
    }
    return( count );
}

void AddPublicData( dir_node *dir )
/*********************************/
{
    QAddItem( &PubQueue, dir );
}

uint GetPublicData(
    uint *seg,
    uint *grp,
    char *cmd,
    char ***NameArray,
    struct pubdef_data **data,
    bool *need32,
    bool first )
/****************************/
{
    static struct queuenode    *start;
    struct queuenode           *curr;
    struct asm_sym             *sym;
    dir_node                   *pub;
    uint                       count;
    uint                       i;
    struct pubdef_data         *d;
    struct asm_sym             *curr_seg;

    if( PubQueue == NULL )
        return( 0 );
    if( first )
        start = PubQueue->head;
    if( start == NULL )
        return( 0 );

    *need32 = FALSE;
    *cmd = CMD_PUBDEF;
    sym = (asm_sym *)start->data;
    if( sym->state == SYM_UNDEFINED ) {
        AsmErr( SYMBOL_NOT_DEFINED, sym->name );
        return( 0 );
    }
    curr_seg = sym->segment;
    if( curr_seg == NULL ) {      // absolute symbol ( without segment )
        *seg = 0;
        *grp = 0;
    } else {
        *seg = GetSegIdx( curr_seg );
        *grp = GetGrpIdx( GetGrp( curr_seg ) );
    }
    curr = start;
    for( count = 0; curr != NULL; curr = curr->next ) {
        if( count == MAX_PUB_SIZE )  // don't let the records get too big
            break;
        sym = (asm_sym *)curr->data;
        if( sym->segment != curr_seg )
            break;
        if( sym->state == SYM_PROC ) {
            if( ((dir_node *)sym)->e.procinfo->visibility == VIS_PRIVATE ) {
                if( *cmd == CMD_PUBDEF ) {
                    if( curr != start )
                        break;
                    *cmd = CMD_STATIC_PUBDEF;
                } /* else we are just continuing a static def. */
            } else {
                if( *cmd == CMD_STATIC_PUBDEF ) {
                    break;
                }
            }
        }
        count++;
        /* if we don't get to here, this entry is part of the next pubdef */
    }
    *NameArray = AsmAlloc( count * sizeof( char * ) );
    for( i = 0; i < count; i++ ) {
        (*NameArray)[i] = NULL;
    }

    *data = d = AsmAlloc( count * sizeof( struct pubdef_data ) );

    for( curr = start, i = 0; i < count; i++, curr = curr->next ) {
        sym = (asm_sym *)curr->data;
        if( sym->segment != curr_seg )
            break;
        if( sym->offset > 0xffffUL )
            *need32 = TRUE;

        (*NameArray)[i] = Mangle( sym, NULL );

        d[i].name = i;
        /* No namecheck is needed by name manager */
        if( sym->state != SYM_CONST ) {
            d[i].offset = sym->offset;
        } else {
            pub = (dir_node *)sym;
            if( pub->e.constinfo->data[0].token != T_NUM  ) {
                AsmWarn( 2, PUBLIC_CONSTANT_NOT_NUMERIC );
                d[i].offset = 0;
            } else {
                d[i].offset = pub->e.constinfo->data[0].value;
            }
        }
        d[i].type.idx = 0;
    }
    start = curr;
    return( count );
}

static void FreePubQueue( void )
/******************************/
{
    if( PubQueue != NULL ) {
        while( PubQueue->head != NULL ) {
            AsmFree( QDequeue( PubQueue ) );
        }
        AsmFree( PubQueue );
    }
}

void AddAliasData( char *data )
/*****************************/
{
    QAddItem( &AliasQueue, data );
}

char *GetAliasData( bool first )
/******************************/
{
    static queuenode    *node;
    char                *p;

    if( AliasQueue == NULL )
        return( NULL );
    if( first )
        node = AliasQueue->head;
    if( node == NULL )
        return( NULL );
    p = node->data ;
    node = node->next;
    return( p );
}

static void FreeAliasQueue( void )
/********************************/
{
    if( AliasQueue != NULL ) {
        while( AliasQueue->head != NULL ) {
            queuenode   *node;

            node = QDequeue( AliasQueue );
            AsmFree( node->data );
            AsmFree( node );
        }
        AsmFree( AliasQueue );
    }
}

void AddLnameData( dir_node *dir )
/********************************/
{
    QAddItem( &LnameQueue, dir );
}

direct_idx FindLnameIdx( char *name )
/***********************************/
{
    queuenode           *node;
    dir_node            *dir;

    if( LnameQueue == NULL )
        return( LNAME_NULL);

    for( node = LnameQueue->head; node != NULL; node = node->next ) {
        dir = (dir_node *)node->data;
        if( dir->sym.state != SYM_CLASS_LNAME )
            continue;
        if( stricmp( dir->sym.name, name ) == 0 ) {
            return( dir->e.lnameinfo->idx );
        }
    }
    return( LNAME_NULL );
}

char *GetLname( direct_idx idx )
/******************************/
{
    queuenode           *node;
    dir_node            *dir;

    if( LnameQueue == NULL )
        return( NULL);

    for( node = LnameQueue->head; node != NULL; node = node->next ) {
        dir = (dir_node *)node->data;
        if( dir->sym.state != SYM_CLASS_LNAME )
            continue;
        if( dir->e.lnameinfo->idx == idx ) {
            return( dir->sym.name );
        }
    }
    return( NULL );
}

unsigned GetLnameData( char **data )
/**********************************/
{
    char            *lname = NULL;
    unsigned        total_size = 0;
    queuenode       *curr;
    dir_node        *dir;
    int             len;

    if( LnameQueue == NULL )
        return( 0 );

    for( curr = LnameQueue->head; curr != NULL ; curr = curr->next ) {
        dir = (dir_node *)(curr->data);
        myassert( dir != NULL );
        total_size += 1 + strlen( dir->sym.name );
    }

    if( total_size > 0 ) {
        int     i = 0;

        lname = AsmAlloc( total_size * sizeof( char ) + 1 );
        for( curr = LnameQueue->head; curr != NULL ; curr = curr->next ) {
            dir = (dir_node *)(curr->data);

            len = strlen( dir->sym.name );
            lname[i] = (char)len;
            i++;
            strcpy( lname+i, dir->sym.name );
            //For the Q folks... strupr( lname+i );
            i += len; // overwrite the null char
        }
    }
    *data = lname;
    return( total_size );
}

static void FreeLnameQueue( void )
/********************************/
{
    dir_node *dir;
    queuenode *node;

    if( LnameQueue != NULL ) {
        while( LnameQueue->head != NULL ) {
            node = QDequeue( LnameQueue );
            dir = (dir_node *)node->data;
            if( dir->sym.state == SYM_CLASS_LNAME ) {
                AsmFree( dir->e.lnameinfo );
                AsmFree( dir->sym.name );
                AsmFree( dir );
            }
            AsmFree( node );
        }
        AsmFree( LnameQueue );
    }
}

void AddGlobalData( dir_node *dir )
/*********************************/
{
    QAddItem( &GlobalQueue, dir );
}

void GetGlobalData( void )
/************************/
/* turn the globals into either externs or publics as appropriate */
{
    queuenode           *curr;
    struct asm_sym      *sym;

    if( GlobalQueue == NULL )
        return;
    for( ; ; ) {
        curr = (queuenode *)QDequeue( GlobalQueue );
        if( curr == NULL )
            break;
        sym = (asm_sym *)curr->data;
        if( sym->state == SYM_UNDEFINED ) {
            dir_change( (dir_node *)curr->data, TAB_EXT );
            AsmFree( curr );
        } else {
            /* make this record a pubdef */
            sym->public = TRUE;
            QAddQItem( &PubQueue, curr );
        }
    }
    AsmFree( GlobalQueue );
    GlobalQueue = NULL;
}

void AddLinnumData( struct line_num_info *data )
/**********************************************/
{
    QAddItem( &LinnumQueue, data );
}

int GetLinnumData( struct linnum_data **ldata, bool *need32 )
/***********************************************************/
{
    queuenode               *node;
    struct line_num_info    *next;
    int                     count, i;

    count = QCount( LinnumQueue );
    if( count == 0 )
        return( count );
    *need32 = FALSE;
    *ldata = AsmAlloc( count * sizeof( struct linnum_data ) );
    for( i = 0; i < count; i++ ) {
        node = QDequeue( LinnumQueue );
        next = (struct line_num_info *)(node->data);
        if( *ldata != NULL ) {
            (*ldata)[i].number = next->number;
            (*ldata)[i].offset = next->offset;
            if( next->offset > 0xffffUL ) {
                *need32 = TRUE;
            }
        }
        AsmFree( next );
        AsmFree( node );
    }
    AsmFree( LinnumQueue );
    LinnumQueue = NULL;
    return( count );
}

void FreeAllQueues( void )
/************************/
{
    FreePubQueue();
    FreeAliasQueue();
    FreeLnameQueue();
}

⌨️ 快捷键说明

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