direct.c

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

C
2,214
字号
}

static void dir_add( dir_node *new, int tab )
/*******************************************/
{
    /* note: this is only for those above which do NOT return right away */
    /* put the new entry into the queue for its type of symbol */
    if( Tables[tab].head == NULL ) {
        Tables[tab].head = Tables[tab].tail = new;
        new->next = new->prev = NULL;
    } else {
        new->prev = Tables[tab].tail;
        Tables[tab].tail->next = new;
        Tables[tab].tail = new;
        new->next = NULL;
    }
}

static void dir_init( dir_node *dir, int tab )
/********************************************/
/* Change node and insert it into the table specified by tab */
{
    struct asm_sym      *sym;

    sym = &dir->sym;

    dir->line_num = LineNumber;
    dir->next = dir->prev = NULL;

    switch( tab ) {
    case TAB_SEG:
        sym->state = SYM_SEG;
        dir->e.seginfo = AsmAlloc( sizeof( seg_info ) );
        dir->e.seginfo->lname_idx = 0;
        dir->e.seginfo->group = NULL;
        dir->e.seginfo->segrec = NULL;
        break;
    case TAB_GRP:
        sym->state = SYM_GRP;
        dir->e.grpinfo = AsmAlloc( sizeof( grp_info ) );
        dir->e.grpinfo->idx = ++grpdefidx;
        dir->e.grpinfo->seglist = NULL;
        dir->e.grpinfo->numseg = 0;
        dir->e.grpinfo->lname_idx = 0;
        break;
    case TAB_EXT:
        sym->state = SYM_EXTERNAL;
        dir->e.extinfo = AsmAlloc( sizeof( ext_info ) );
        dir->e.extinfo->idx = ++extdefidx;
        dir->e.extinfo->use32 = Use32;
        dir->e.extinfo->comm = 0;
        break;
    case TAB_COMM:
        sym->state = SYM_EXTERNAL;
        dir->e.comminfo = AsmAlloc( sizeof( comm_info ) );
        dir->e.comminfo->idx = ++extdefidx;
        dir->e.comminfo->use32 = Use32;
        dir->e.comminfo->comm = 1;
        tab = TAB_EXT;
        break;
    case TAB_CONST:
        sym->state = SYM_CONST;
        sym->segment = NULL;
        sym->offset = 0;
        dir->e.constinfo = AsmAlloc( sizeof( const_info ) );
        dir->e.constinfo->data = NULL;
        dir->e.constinfo->count = 0;
        return;
    case TAB_PROC:
        sym->state = SYM_PROC;
        dir->e.procinfo = AsmAlloc( sizeof( proc_info ) );
        dir->e.procinfo->regslist = NULL;
        dir->e.procinfo->paralist = NULL;
        dir->e.procinfo->locallist = NULL;
        break;
    case TAB_MACRO:
        sym->state = SYM_MACRO;
        dir->e.macroinfo = AsmAlloc( sizeof( macro_info ) );
        dir->e.macroinfo->parmlist = NULL;
        dir->e.macroinfo->data = NULL;
        dir->e.macroinfo->srcfile = NULL;
        break;
    case TAB_CLASS_LNAME:
    case TAB_LNAME:
        sym->state = ( tab == TAB_LNAME ) ? SYM_LNAME : SYM_CLASS_LNAME;
        dir->e.lnameinfo = AsmAlloc( sizeof( lname_info ) );
        dir->e.lnameinfo->idx = ++LnamesIdx;
        // fixme
        return;
    case TAB_PUB:
        sym->public = TRUE;
        return;
    case TAB_GLOBAL:
        return;
    case TAB_STRUCT:
        sym->state = SYM_STRUCT;
        dir->e.structinfo = AsmAlloc( sizeof( struct_info ) );
        dir->e.structinfo->size = 0;
        dir->e.structinfo->alignment = 0;
        dir->e.structinfo->head = NULL;
        dir->e.structinfo->tail = NULL;
        return;
    case TAB_LIB:
        break;
    default:
        // unknown table
        /**/myassert( 0 );
        break;
    }
    dir_add( dir, tab );
    return;
}

static void RemoveFromTable( dir_node *dir )
/******************************************/
{
    int tab;

    if( dir->prev != dir->next ) {
        dir->next->prev = dir->prev;
        dir->prev->next = dir->next;
    } else {
        if( dir->prev != NULL ) {
            dir->next->prev = NULL;
            dir->prev->next = NULL;
        }
        switch( dir->sym.state ) {
        case SYM_EXTERNAL:
            tab = TAB_EXT;
            break;
        case SYM_SEG:
            tab = TAB_SEG;
            break;
        case SYM_GRP:
            tab = TAB_GRP;
            break;
        case SYM_PROC:
            tab = TAB_PROC;
            break;
        case SYM_MACRO:
            tab = TAB_MACRO;
            break;
        default:
            return;
        }
        Tables[tab].head = Tables[tab].tail = dir->prev;
    }
}

void dir_change( dir_node *dir, int tab )
/***************************************/
/* Change node type and insert it into the table specified by tab */
{
    FreeInfo( dir );
    RemoveFromTable( dir);
    dir_init( dir, tab );
}

dir_node *dir_insert( const char *name, int tab )
/***********************************************/
/* Insert a node into the table specified by tab */
{
    dir_node            *new;

    /**/myassert( name != NULL );

    /* don't put class lnames into the symbol table - separate name space */
    new = (dir_node *)AllocDSym( name, ( tab != TAB_CLASS_LNAME ) );
    if( new != NULL )
        dir_init( new, tab );
    return( new );
}

void FreeInfo( dir_node *dir )
/****************************/
{
    int i;

    switch( dir->sym.state ) {
    case SYM_GRP:
        {
            seg_list    *segcurr;
            seg_list    *segnext;

            segcurr = dir->e.grpinfo->seglist;
            if( segcurr != NULL ) {
                for( ;; ) {
                    segnext = segcurr->next;
                    AsmFree( segcurr );
                    if( segnext == NULL )
                        break;
                    segcurr = segnext;
                }
            }
            AsmFree( dir->e.grpinfo );
        }
        break;
    case SYM_SEG:
        if( dir->e.seginfo->segrec != NULL )
            ObjKillRec( dir->e.seginfo->segrec );
        AsmFree( dir->e.seginfo );
        break;
    case SYM_EXTERNAL:
        AsmFree( dir->e.extinfo );
        break;
    case SYM_LNAME:
    case SYM_CLASS_LNAME:
        AsmFree( dir->e.lnameinfo );
        break;
    case SYM_CONST:
#ifdef DEBUG_OUT
        if( ( dir->e.constinfo->count > 0 )
            && ( dir->e.constinfo->data[0].token != T_NUM ) ) {
            DebugMsg( ( "freeing const(String): %s = ", dir->sym.name ) );
        } else {
            DebugMsg( ( "freeing const(Number): %s = ", dir->sym.name ) );
        }
#endif
        for( i=0; i < dir->e.constinfo->count; i++ ) {
#ifdef DEBUG_OUT
            if( dir->e.constinfo->data[i].token == T_NUM ) {
                DebugMsg(( "%d ", dir->e.constinfo->data[i].value ));
            } else {
                DebugMsg(( "%s ", dir->e.constinfo->data[i].string_ptr ));
            }
#endif
            AsmFree( dir->e.constinfo->data[i].string_ptr );
        }
        DebugMsg(( "\n" ));
        AsmFree( dir->e.constinfo->data );
        AsmFree( dir->e.constinfo );
        break;
    case SYM_PROC:
        {
            label_list  *labelcurr;
            label_list  *labelnext;
            regs_list   *regcurr;
            regs_list   *regnext;

            labelcurr = dir->e.procinfo->paralist;
            if( labelcurr != NULL ) {
                for( ;; ) {
                    labelnext = labelcurr->next;
                    AsmFree( labelcurr->label );
                    AsmFree( labelcurr->replace );
                    AsmFree( labelcurr );
                    if( labelnext == NULL )
                        break;
                    labelcurr = labelnext;
                }
            }

            labelcurr = dir->e.procinfo->locallist;
            if( labelcurr != NULL ) {
                for( ;; ) {
                    labelnext = labelcurr->next;
                    AsmFree( labelcurr->label );
                    AsmFree( labelcurr->replace );
                    AsmFree( labelcurr );
                    if( labelnext == NULL )
                        break;
                    labelcurr = labelnext;
                }
            }

            regcurr = dir->e.procinfo->regslist;
            if( regcurr != NULL ) {
                for( ;; ) {
                    regnext = regcurr->next;
                    AsmFree( regcurr->reg );
                    AsmFree( regcurr );
                    if( regnext == NULL )
                        break;
                    regcurr = regnext;
                }
            }
            AsmFree( dir->e.procinfo );
        }
        break;
    case SYM_MACRO:
        {
            parm_list       *labelcurr;
            parm_list       *labelnext;
            asmlines        *datacurr;
            asmlines        *datanext;

            /* free the parm list */
            labelcurr = dir->e.macroinfo->parmlist;
            if( labelcurr != NULL ) {
                for( ;; ) {
                    labelnext = labelcurr->next;
                    AsmFree( labelcurr->label );
                    if( labelcurr->replace != NULL ) {
                        AsmFree( labelcurr->replace );
                    }
                    if( labelcurr->def != NULL ) {
                        AsmFree( labelcurr->def );
                    }
                    AsmFree( labelcurr );
                    if( labelnext == NULL )
                        break;
                    labelcurr = labelnext;
                }
            }

            /* free the lines list */
            datacurr = dir->e.macroinfo->data;
            if( datacurr != NULL ) {
                for( ;; ) {
                    datanext = datacurr->next;
                    AsmFree( datacurr->line );
                    AsmFree( datacurr );
                    if( datanext == NULL )
                        break;
                    datacurr = datanext;
                }
            }
            AsmFree( dir->e.macroinfo );
        }
        break;
    case SYM_STRUCT:
        {
            field_list      *ptr;
            field_list      *next;

            for( ptr = dir->e.structinfo->head; ptr != NULL; ptr = next ) {
                AsmFree( ptr->initializer );
                AsmFree( ptr->value );
                next = ptr->next;
                AsmFree( ptr );
            }
            AsmFree( dir->e.structinfo );
        }
        break;
    default:
        break;
    }
}

direct_idx GetLnameIdx( char *name )
/**********************************/
{
    struct asm_sym      *sym;
    dir_node            *dir;

    sym = AsmGetSymbol( name );
    if( sym == NULL )
        return( LNAME_NULL );

    dir = (dir_node *)sym;
    if( sym->state == SYM_UNDEFINED ) {
        return( LNAME_NULL );
    } else if( sym->state == SYM_GRP ) {
        return( dir->e.grpinfo->lname_idx );
    } else if( sym->state == SYM_SEG ) {
        return( dir->e.seginfo->lname_idx );
    } else {    /* it is an lname record */
        return( dir->e.lnameinfo->idx );
    }
}

static direct_idx InsertClassLname( char *name )
/**********************************************/
{
    dir_node            *dir;

    if( strlen( name ) > MAX_LNAME ) {
        AsmError( LNAME_TOO_LONG );
        return( LNAME_NULL );
    }

    dir = dir_insert( name, TAB_CLASS_LNAME );

    /* put it into the lname table */

    AddLnameData( dir );

    return( LnamesIdx );
}

direct_idx LnameInsert( char *name )
/**********************************/
{
    struct asm_sym      *sym;
    dir_node            *dir;

    sym = AsmGetSymbol( name );

    if( sym != NULL ) {
        dir = (dir_node *)sym;
        /* The name is already in the table*/
        if( sym->state == SYM_GRP ) {
            if( dir->e.grpinfo->lname_idx == 0 ) {
                dir->e.grpinfo->lname_idx = ++LnamesIdx;
            }
        } else if( sym->state == SYM_SEG ) {
            if( dir->e.seginfo->lname_idx == 0 ) {
                dir->e.seginfo->lname_idx = ++LnamesIdx;
            }
        } else {
            return( ERROR );
        }
    } else {
        if( strlen( name ) > MAX_LNAME ) {
            AsmError( LNAME_TOO_LONG );
            return( ERROR );
        }

        dir = dir_insert( name, TAB_LNAME );
    }

    /* put it into the lname table */

    AddLnameData( dir );

    return( LnamesIdx );
}

void wipe_space( char *token )
/****************************/
/* wipe out the spaces at the beginning of a token */
{
    char        *start;

    if( token == NULL )
        return;
    if( strlen( token ) == 0 )
        return;

    for( start = token;; start++ ){
        if( *start != ' ' && *start != '\t' ) {
            break;
        }
    }
    if( start == token )
        return;

    memmove( token, start, strlen( start ) + 1 );
}

static uint checkword( char **token )
/***********************************/
/* wipes out prceding and tailing spaces, and make sure token contains only

⌨️ 快捷键说明

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