direct.c

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

C
2,214
字号
   one word */
{
    char        *ptrhead;
    char        *ptrend;

    /* strip the space in the front */
    for( ptrhead = *token; ; ptrhead++ ) {
        if( ( *ptrhead != ' ' ) && ( *ptrhead != '\t' ) ) {
            break;
        }
    }

    /* Then search for the first ending space */
    ptrend = strchr( ptrhead, ' ' );
    if( ptrend == NULL ) {
        ptrend = strchr( ptrhead, '\t' );
    }
    if( ptrend == NULL ) {
        ptrend = strchr( ptrhead, '\n' );
    }

    /* Check if there is any letters following that ending space */
    if( ptrend != NULL ) {
        *ptrend = '\0';
        ptrend++;
        while( *ptrend != '\0' ) {
            if( ( *ptrend != ' ' ) && ( *ptrend != '\t' ) && ( *ptrend != '\n' ) ) {
                return( ERROR );
            }
            ptrend++;
        }
    }

    *token = ptrhead;
    return( NOT_ERROR );
}

uint GetExtIdx( struct asm_sym *sym )
/***********************************/
{
    dir_node            *dir;

    dir = (dir_node *)sym;
    /**/myassert( dir != NULL );
    return( dir->e.extinfo->idx );
}

uint_32 GetCurrAddr( void )
/*************************/
{
    if( CurrSeg == NULL )
        return( 0 );
    return( CurrSeg->seg->e.seginfo->current_loc );
}

dir_node *GetCurrSeg( void )
/**************************/
{
    if( CurrSeg == NULL )
        return( 0 );
    return( CurrSeg->seg );
}

uint_32 GetCurrSegAlign( void )
/*****************************/
{
    if( CurrSeg == NULL )
        return( 0 );
    switch( CurrSeg->seg->e.seginfo->segrec->d.segdef.align ) {
    case ALIGN_ABS: // same as byte aligned ?
    case ALIGN_BYTE:
        return( 1 );
    case ALIGN_WORD:
        return( 2 );
    case ALIGN_DWORD:
        return( 4 );
    case ALIGN_PARA:
        return( 16 );
    case ALIGN_PAGE:
        return( 256 );
    case ALIGN_4KPAGE:
        return( 4096 );
    default:
        return( 0 );
    }
}

uint_32 GetCurrSegStart( void )
/*****************************/
{
    if( CurrSeg == NULL )
        return( 0 );
    /**/myassert( !write_to_file
                || ( CurrSeg->seg->e.seginfo->current_loc - BufSize )
                     == CurrSeg->seg->e.seginfo->start_loc );
    return( CurrSeg->seg->e.seginfo->start_loc );
}

static int GetLangType( int i )
/*****************************/
{
    if( AsmBuffer[i]->token != T_RES_ID)
        return( LANG_NONE );
    switch( AsmBuffer[i]->value ) {
    case T_C:
        return( LANG_C );
    case T_BASIC:
        return( LANG_BASIC );
    case T_FORTRAN:
        return( LANG_FORTRAN );
    case T_PASCAL:
        return( LANG_PASCAL );
    case T_WATCOM_C:
        return( LANG_WATCOM_C );
    case T_STDCALL:
        return( LANG_STDCALL );
    case T_SYSCALL:
        return( LANG_SYSCALL );
    default:
        return( LANG_NONE );
    }
}

int GlobalDef( int i )
/********************/
{
    char                *token;
    char                *mangle_type = NULL;
    char                *typetoken;
    int                 type;
    struct asm_sym      *sym;
    dir_node            *dir;
    int                 lang_type;

    mangle_type = Check4Mangler( &i );
    for( ; i < Token_Count; i++ ) {
        lang_type = GetLangType( i );
        if( lang_type != LANG_NONE )
            i++;
        /* get the symbol name */
        token = AsmBuffer[i++]->string_ptr;

        /* go past the colon */
        if( AsmBuffer[i]->token != T_COLON ) {
            AsmError( COLON_EXPECTED );
            return( ERROR );
        }
        i++;

        typetoken = AsmBuffer[i]->string_ptr;
        type = token_cmp( &typetoken, TOK_EXT_NEAR, TOK_EXT_ABS );

        if( type == ERROR ) {
            AsmError( INVALID_QUALIFIED_TYPE );
            return( ERROR );
        }
        for( ; i< Token_Count && AsmBuffer[i]->token != T_COMMA; i++ ) ;

        sym = AsmGetSymbol( token );

        if( ( sym != NULL ) && ( sym->state != SYM_UNDEFINED ) ) {
            return( PubDef( 0 ) ); // it is defined here, so make a pubdef
        }

        if( sym == NULL ) {
            dir = dir_insert( token, TAB_GLOBAL );
            sym = &dir->sym;
        } else {
            dir = (dir_node *)sym;
        }

        if( dir == NULL )
            return( ERROR );

        GetSymInfo( sym );
        sym->offset = 0;
        sym->state = SYM_UNDEFINED;
        // FIXME !! symbol can have different type
        sym->mem_type = TypeInfo[type].value;
        // FIXME !! symbol can have different language type
        SetMangler( sym, mangle_type, lang_type );

        /* put the symbol in the globaldef table */

        AddGlobalData( dir );
    }
    return( NOT_ERROR );
}

asm_sym *MakeExtern( char *name, memtype mem_type, bool already_defd )
/********************************************************************/
{
    dir_node        *ext;
    struct asm_sym  *sym;

    sym = AsmGetSymbol( name );
    if( ( sym != NULL ) && already_defd ) {
        ext = (dir_node *)sym;
        dir_change( ext, TAB_EXT );
    } else {
        ext = dir_insert( name, TAB_EXT );
        if( ext == NULL ) {
            return( NULL );
        }
        sym = &ext->sym;
    }
    GetSymInfo( sym );
    sym->offset = 0;
    sym->mem_type = mem_type;
    return( sym );
}

int ExtDef( int i )
/*****************/
{
    char                *token;
    char                *mangle_type = NULL;
    char                *typetoken;
    int                 type;
    memtype             mem_type;
    struct asm_sym      *sym;
    int                 lang_type;

    mangle_type = Check4Mangler( &i );
    for( ; i < Token_Count; i++ ) {
        lang_type = GetLangType( i );
        if( lang_type != LANG_NONE )
            i++;
        /* get the symbol name */
        token = AsmBuffer[i++]->string_ptr;

        /* go past the colon */
        if( AsmBuffer[i]->token != T_COLON ) {
            AsmError( COLON_EXPECTED );
            return( ERROR );
        }
        i++;

        typetoken = AsmBuffer[i]->string_ptr;
        type = token_cmp( &typetoken, TOK_EXT_NEAR, TOK_EXT_ABS );

        if( type == ERROR ) {
            if( !IsLabelStruct( AsmBuffer[i]->string_ptr ) ) {
                AsmError( INVALID_QUALIFIED_TYPE );
                return( ERROR );
            }
            mem_type = MT_STRUCT;
        } else {
            mem_type = TypeInfo[type].value;
        }
        for( ; i< Token_Count && AsmBuffer[i]->token != T_COMMA; i++ );

        sym = AsmGetSymbol( token );

        if( sym != NULL ) {
            if( sym->state == SYM_UNDEFINED ) {
                if( MakeExtern( token, mem_type, TRUE ) == NULL ) {
                    return( ERROR );
                }
            } else if( sym->mem_type != mem_type ) {
                AsmError( EXT_DEF_DIFF );
                return( ERROR );
            }
        } else {
            sym = MakeExtern( token, mem_type, FALSE );
            if( sym == NULL ) {
                return( ERROR );
            }
        }
        SetMangler( sym, mangle_type, lang_type );
    }
    return( NOT_ERROR );
}

static char *Check4Mangler( int *i )
/**********************************/
{
    char *mangle_type = NULL;

    if( AsmBuffer[*i]->token == T_STRING ) {
        mangle_type = AsmBuffer[*i]->string_ptr;
        (*i)++;
        if( AsmBuffer[*i]->token != T_COMMA ) {
            AsmWarn( 2, EXPECTING_COMMA );
        } else {
            (*i)++;
        }
    }
    return( mangle_type );
}

int PubDef( int i )
/*****************/
{
    char                *mangle_type = NULL;
    char                *token;
    struct asm_sym      *sym;
    dir_node            *node;
    int                 lang_type;

    mangle_type = Check4Mangler( &i );
    for( ; i < Token_Count; i+=2 ) {
        lang_type = GetLangType( i );
        if( lang_type != LANG_NONE )
            i++;
        token = AsmBuffer[i]->string_ptr;
        /* Add the public name */

        if( checkword( &token ) == ERROR ) {
            AsmError( EXPECTING_COMMA );
            return( ERROR );
        }

        sym = AsmGetSymbol( token );
        if( sym != NULL ) {
            node = (dir_node *)sym;
            if( sym->state == SYM_CONST ) {
                /* check if the symbol expands to another symbol,
                 * and if so, expand it */
                 if( node->e.constinfo->data[0].token == T_ID ) {
                    ExpandTheWorld( i, FALSE, TRUE );
                    return( PubDef( i ) );
                 }
            }
            /* make the existing symbol public */

            switch( sym->state ) {
            case SYM_UNDEFINED:
            case SYM_INTERNAL:
            case SYM_EXTERNAL:
            case SYM_STACK:
            case SYM_CONST:
                break;
            case SYM_PROC:
                if( node->e.procinfo->visibility != VIS_EXPORT ) {
                    node->e.procinfo->visibility = VIS_PUBLIC;
                }
            default:
                break;
            }
        } else {
            node = dir_insert( token, TAB_PUB );
            AddPublicData( node );
            sym = &node->sym;
        }
        SetMangler( sym, mangle_type, lang_type );
        if( !sym->public ) {
            /* put it into the pub table */
            sym->public = TRUE;
            AddPublicData( node );
        }
    }
    return( NOT_ERROR );
}

static dir_node *CreateGroup( char *name )
/****************************************/
{
    dir_node    *grp;

    grp = (dir_node *)AsmGetSymbol( name );

    if( grp == NULL ) {
        grp = dir_insert( name, TAB_GRP );
        LnameInsert( name );
    } else if( grp->sym.state == SYM_UNDEFINED ) {
        dir_change( grp, TAB_GRP );
        LnameInsert( name );
    } else if( grp->sym.state != SYM_GRP ) {
        AsmErr( SYMBOL_PREVIOUSLY_DEFINED, name );
        grp = NULL;
    }
    return( grp );
}

int GrpDef( int i )
/*****************/
{
    char        *name;
    dir_node    *grp;
    seg_list    *new;
    seg_list    *curr;
    dir_node    *seg;

    if( i < 0 ) {
        AsmError( GRP_NAME_MISSING );
        return( ERROR );
    }

    name = AsmBuffer[i]->string_ptr;
    grp = CreateGroup( name );
    if( grp == NULL )
        return( ERROR );

    for( i+=2;              // skip over the GROUP directive
         i < Token_Count;   // stop at the end of the line
         i+=2 ) {           // skip over commas
        name = AsmBuffer[i]->string_ptr;
        /* Add the segment name */

        if( checkword( &name ) == ERROR ) {
            AsmError( EXPECTING_COMMA );
            return( ERROR );
        }

        seg = (dir_node *)AsmGetSymbol( name );
        if( seg == NULL ) {
            seg = dir_insert( name, TAB_SEG );
        } else if( seg->sym.state == SYM_UNDEFINED ) {
            dir_change( seg, TAB_SEG );
        } else if( seg->sym.state != SYM_SEG ) {
            AsmErr( SYMBOL_PREVIOUSLY_DEFINED, name );
            return( ERROR );
        }
        if( seg->e.seginfo->group == &grp->sym )    // segment is in group already
            continue;
        if( seg->e.seginfo->group != NULL ) {      // segment is in another group
            AsmError( SEGMENT_IN_GROUP );
            return( ERROR );
        }
        /* set the grp index of the segment */
        seg->e.seginfo->group = &grp->sym;

        new = AsmAlloc( sizeof(seg_list) );
        new->seg = seg;
        new->next = NULL;
        grp->e.grpinfo->numseg++;

        /* insert the segment at the end of linked list */
        if( grp->e.grpinfo->seglist == NULL ) {
            grp->e.grpinfo->seglist = new;
        } else {
            curr = grp->e.grpinfo->seglist;
            while( curr->next != NULL ) {
                curr = curr->next;
            }
            curr->next = new;
        }
    }
    return( NOT_ERROR );
}

static int SetUse32( void )

⌨️ 快捷键说明

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