direct.c

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

C
2,214
字号
/*************************/
{
    if( CurrSeg == NULL ) {
        Use32 = ModuleInfo.defUse32;
    } else {
        Globals.code_seg = SEGISCODE( CurrSeg );
        Use32 = CurrSeg->seg->e.seginfo->segrec->d.segdef.use_32;
        if( Use32 && ( ( Code->info.cpu & P_CPU_MASK ) < P_386 ) ) {
            AsmError( WRONG_CPU_FOR_32BIT_SEGMENT );
            return( ERROR );
        }
    }
    return( NOT_ERROR );
}

int SetUse32Def( bool flag )
/**************************/
{
    if( ( CurrSeg == NULL )               // outside any segments
        && ( !ModuleInfo.init             // model not defined
            || ModuleInfo.cmdline ) ) {   // model defined on cmdline by -m?
        ModuleInfo.defUse32 = flag;
    }
    return( SetUse32() );
}

int  SetCurrSeg( int i )
/**********************/
{
    char        *name;
    struct asm_sym      *sym;

    name = AsmBuffer[i]->string_ptr;

    switch( AsmBuffer[i+1]->value ) {
    case T_SEGMENT:
        FlushCurrSeg();
        sym = AsmGetSymbol( name );
        /**/ myassert( sym != NULL );
        push_seg( (dir_node *)sym );
        break;
    case T_ENDS:
        FlushCurrSeg();
        pop_seg();
        break;
    default:
        break;
    }
    return( SetUse32() );
}

static int token_cmp( char **token, int start, int end )
/******************************************************/
/* compare token against those specified in TypeInfo[ start...end ] */
{
    int         i;
    char        *str;
    char        *tkn;

    str = *token;

    for( i = start; i <= end; i++ ) {
        tkn = TypeInfo[i].string;
        if( tkn == NULL )
            continue;
        if( stricmp( tkn, str ) == 0 ) {
            // type is found
            return( i );
        }
    }
    return( ERROR );        // No type is found
}

static seg_type ClassNameType( char *name )
/*****************************************/
{
    int     slen;
    char    uname[257];

    if( name == NULL )
        return( SEGTYPE_UNDEF );
    if( ModuleInfo.init ) {
        if( stricmp( name, Options.code_class ) == 0 ) {
            return( SEGTYPE_ISCODE );
        }
    }
    slen = strlen( name );
    strcpy( uname, name );
    strupr( uname );
    switch( slen ) {
    default:
    case 5:
        // 'CONST'
        if( memcmp( uname, "CONST", 6 ) == 0 )
            return( SEGTYPE_ISDATA );
        // 'STACK'
        if( memcmp( uname, "STACK", 6 ) == 0 )
            return( SEGTYPE_ISDATA );
        // 'DBTYP'
        if( memcmp( uname, "DBTYP", 6 ) == 0 )
            return( SEGTYPE_ISDATA );
        // 'DBSYM'
        if( memcmp( uname, "DBSYM", 6 ) == 0 )
            return( SEGTYPE_ISDATA );
    case 4:
        // 'CODE'
        if( memcmp( uname , "CODE", 5 ) == 0 )
            return( SEGTYPE_ISCODE );
        // '...DATA'
        if( memcmp( uname + slen - 4, "DATA", 4 ) == 0 )
            return( SEGTYPE_ISDATA );
    case 3:
        // '...BSS'
        if( memcmp( uname + slen - 3, "BSS", 3 ) == 0 )
            return( SEGTYPE_ISDATA );
    case 2:
    case 1:
    case 0:
        return( SEGTYPE_UNDEF );
    }
}

static seg_type SegmentNameType( char *name )
/*******************************************/
{
    int     slen;
    char    uname[257];

    slen = strlen( name );
    strcpy( uname, name );
    strupr( uname );
    switch( slen ) {
    default:
    case 5:
        // '..._TEXT'
        if( memcmp( uname + slen - 5, DEFAULT_CODE_NAME, 5 ) == 0 )
            return( SEGTYPE_ISCODE );
        // '..._DATA'
        if( memcmp( uname + slen - 5, DEFAULT_DATA_NAME, 5 ) == 0 )
            return( SEGTYPE_ISDATA );
        // 'CONST'
        if( memcmp( uname, "CONST", 5 ) == 0 )
            return( SEGTYPE_ISDATA );
    case 4:
        // '..._BSS'
        if( memcmp( uname + slen - 4, "_BSS", 4 ) == 0 )
            return( SEGTYPE_ISDATA );
    case 3:
    case 2:
    case 1:
    case 0:
        return( SEGTYPE_UNDEF );
    }
}


int SegDef( int i )
/*****************/
{
    char                defined;
    char                *token;
    obj_rec             *seg;
    obj_rec             *oldobj;
    direct_idx          classidx;
    uint                type;           // type of option
    uint                initstate = 0;  // to show if a field is initialized
    char                oldreadonly;    // readonly value of a defined segment
    char                oldiscode;      // iscode value of a defined segment
    bool                ignore;
    dir_node            *dirnode;
    char                *name;
    struct asm_sym      *sym;

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

    name = AsmBuffer[i]->string_ptr;

    switch( AsmBuffer[i+1]->value ) {
    case T_SEGMENT:
        seg = ObjNewRec( CMD_SEGDEF );

        /* Check to see if the segment is already defined */
        sym = AsmGetSymbol( name );
        if( sym != NULL ) {
            dirnode = (dir_node *)sym;
            if ( sym->state == SYM_SEG ) {
                // segment already defined
                defined = TRUE;
                oldreadonly = dirnode->e.seginfo->readonly;
                oldiscode = dirnode->e.seginfo->iscode;
                ignore = dirnode->e.seginfo->ignore;
                if( dirnode->e.seginfo->lname_idx == 0 ) {
                    // segment was mentioned in a group statement, but not really set up
                    defined = FALSE;
                    seg->d.segdef.idx = ++segdefidx;
                }
            } else {
                // symbol is different kind, change to segment
                dir_change( dirnode, TAB_SEG );
                seg->d.segdef.idx = ++segdefidx;
                defined = FALSE;
                ignore = FALSE;
            }
        } else {
            // segment is not defined
            dirnode = dir_insert( name, TAB_SEG );
            seg->d.segdef.idx = ++segdefidx;
            defined = FALSE;
            ignore = FALSE;
        }

        /* Setting up default values */
        if( !defined ) {
            seg->d.segdef.align = ALIGN_PARA;
            seg->d.segdef.combine = COMB_INVALID;
            seg->d.segdef.use_32 = ModuleInfo.defUse32;
            seg->d.segdef.class_name_idx = 1;
            /* null class name, in case none is mentioned */
            dirnode->e.seginfo->readonly = FALSE;
            dirnode->e.seginfo->iscode = SEGTYPE_UNDEF;
        } else {
            oldobj = dirnode->e.seginfo->segrec;
            dirnode->e.seginfo->readonly = oldreadonly;
            dirnode->e.seginfo->iscode = oldiscode;
            seg->d.segdef.align = oldobj->d.segdef.align;
            seg->d.segdef.combine = oldobj->d.segdef.combine;
            if( !ignore ) {
                seg->d.segdef.use_32 = oldobj->d.segdef.use_32;
            } else {
                seg->d.segdef.use_32 = ModuleInfo.defUse32;
            }
            seg->d.segdef.class_name_idx = oldobj->d.segdef.class_name_idx;
        }
        dirnode->e.seginfo->ignore = FALSE; // always false unless set explicitly
        seg->d.segdef.access_valid = FALSE;
        seg->d.segdef.seg_length = 0;

        if( lastseg.stack_size > 0 ) {
            seg->d.segdef.seg_length = lastseg.stack_size;
            lastseg.stack_size = 0;
        }

        i+=2; /* go past segment name and "SEGMENT " */

        for( ; i < Token_Count; i ++ ) {
            if( AsmBuffer[i]->token == T_STRING ) {

                /* the class name - the only token which is of type STRING */
                token = AsmBuffer[i]->string_ptr;

                classidx = FindLnameIdx( token );
                if( classidx == LNAME_NULL ) {
                    classidx = InsertClassLname( token );
                    if( classidx == LNAME_NULL ) {
                        return( ERROR );
                    }
                }
                seg->d.segdef.class_name_idx = classidx;
                continue;
            }

            /* go through all tokens EXCEPT the class name */
            token = AsmBuffer[i]->string_ptr;

            // look up the type of token
            type = token_cmp( &token, TOK_READONLY, TOK_AT );
            if( type == ERROR ) {
                AsmError( UNDEFINED_SEGMENT_OPTION );
                return( ERROR );
            }

            /* initstate is used to check if any field is already
            initialized */

            if( initstate & TypeInfo[type].init ) {
                AsmError( SEGMENT_PARA_DEFINED ); // initialized already
                return( ERROR );
            } else {
                initstate |= TypeInfo[type].init; // mark it initialized
            }
            switch( type ) {
            case TOK_READONLY:
                dirnode->e.seginfo->readonly = TRUE;
                break;
            case TOK_BYTE:
            case TOK_WORD:
            case TOK_DWORD:
            case TOK_PARA:
            case TOK_PAGE:
                seg->d.segdef.align = TypeInfo[type].value;
                break;
            case TOK_PRIVATE:
            case TOK_PUBLIC:
            case TOK_STACK:
            case TOK_COMMON:
            case TOK_MEMORY:
                seg->d.segdef.combine = TypeInfo[type].value;
                break;
            case TOK_USE16:
            case TOK_USE32:
                seg->d.segdef.use_32 = TypeInfo[type].value;
                break;
            case TOK_IGNORE:
                dirnode->e.seginfo->ignore = TRUE;
                break;
            case TOK_AT:
                seg->d.segdef.align = SEGDEF_ALIGN_ABS;
                ExpandTheWorld( i + 1, FALSE, TRUE);
                if( AsmBuffer[i+1]->token == T_NUM ) {
                    i++;
                    seg->d.segdef.abs.frame = AsmBuffer[i]->value;
                    seg->d.segdef.abs.offset = 0;
                } else {
                    AsmError( UNDEFINED_SEGMENT_OPTION );
                    return( ERROR );
                }
                break;
            default:
                AsmError( UNDEFINED_SEGMENT_OPTION );
                return( ERROR );
            }
        }
        token = GetLname( seg->d.segdef.class_name_idx );
        if( dirnode->e.seginfo->iscode != SEGTYPE_ISCODE ) {
            seg_type res;

            res = ClassNameType( token );
            if( res != SEGTYPE_UNDEF ) {
                dirnode->e.seginfo->iscode = res;
            } else {
                res = SegmentNameType( name );
                dirnode->e.seginfo->iscode = res;
            }
        }

        if( defined && !ignore && !dirnode->e.seginfo->ignore ) {
            /* Check if new definition is different from previous one */

            oldobj = dirnode->e.seginfo->segrec;
            if( ( oldreadonly != dirnode->e.seginfo->readonly )
                || ( oldobj->d.segdef.align != seg->d.segdef.align )
                || ( oldobj->d.segdef.combine != seg->d.segdef.combine )
                || ( oldobj->d.segdef.use_32 != seg->d.segdef.use_32 )
                || ( oldobj->d.segdef.class_name_idx != seg->d.segdef.class_name_idx ) ) {
                ObjKillRec( seg );
                AsmError( SEGDEF_CHANGED );
                return( ERROR );
            } else {
                // definition is the same as before
                ObjKillRec( seg );
                if( push_seg( dirnode ) == ERROR ) {
                    return( ERROR );
                }
            }
        } else if( defined && ignore ) {
            /* reset to the new values */
            oldobj = dirnode->e.seginfo->segrec;
            oldobj->d.segdef.align = seg->d.segdef.align;
            oldobj->d.segdef.combine = seg->d.segdef.combine;
            oldobj->d.segdef.use_32 = seg->d.segdef.use_32;
            oldobj->d.segdef.class_name_idx = seg->d.segdef.class_name_idx;

            ObjKillRec( seg );
            if( push_seg( dirnode ) == ERROR ) {
                return( ERROR );
            }
        } else if( defined && dirnode->e.seginfo->ignore ) {
            /* keep the old values */
            dirnode->e.seginfo->readonly = oldreadonly;
            dirnode->e.seginfo->iscode = oldiscode;
            dirnode->e.seginfo->ignore = ignore;
            ObjKillRec( seg );
            if( push_seg( dirnode ) == ERROR ) {
                return( ERROR );
            }
        } else {
            /* A new definition */
            dirnode->e.seginfo->segrec = seg;
            dirnode->e.seginfo->start_loc = 0;
            dirnode->e.seginfo->current_loc = 0;
            if( push_seg( dirnode ) == ERROR ) {
                return( ERROR );
            }
            sym = &dirnode->sym;
            GetSymInfo( sym );
            sym->offset = 0;
            LnameInsert( name );
        }
        if( CurrSeg != NULL ) {
            if( !ModuleInfo.mseg
                && ( CurrSeg->seg->e.seginfo->segrec->d.segdef.use_32 != ModuleInfo.use32 ) ) {
                ModuleInfo.mseg = TRUE;
            }
            if( CurrSeg->seg->e.seginfo->segrec->d.segdef.use_32 ) {
                ModuleInfo.use32 = TRUE;
            }
        }
        break;
    case T_ENDS:
        if( CurrSeg == NULL ) {
            AsmError( SEGMENT_NOT_OPENED );
            return( ERROR );
        }

        sym = AsmGetSymbol( name );
        if( sym == NULL ) {
            AsmErr( SEG_NOT_DEFINED, name );
            return( ERROR );
        }
        if( (struct dir_node *)sym != CurrSeg->seg ) {
            AsmError( BLOCK_NESTING_ERROR );
            return( ERROR );
        }
        pop_seg();
        break;
    default:
        return( ERROR );
    }
    return( SetUse32() );
}

int Include( int i )
/******************/
{
    switch( AsmBuffer[i]->token ) {
    case T_ID:
    case T_STRING:
    case T_PATH:
        return( InputQueueFile( AsmBuffer[i]->string_ptr ) );
    default:
        AsmError( EXPECTED_FILE_NAME );
        return( ERROR );
    }
}

int IncludeLib( int i )
/*********************/
{
    char *name;
    struct asm_sym *sym;

⌨️ 快捷键说明

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