⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cprag86.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        if( CurToken == T_CONSTANT ) {
            if( i < MAXIMUM_BYTESEQ ) {
                buff[ i++ ] = Constant;
            } else {
                if( ! too_many_bytes ) {
                    CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
                    too_many_bytes = 1;
                }
            }
            NextToken();
        } else {
            fixword = FixupKeyword();
            if( fixword == FIXWORD_NONE ) break;
            if( fixword == FIXWORD_FLOAT ) {
#if _CPU == 8086
                AddAFix( i, NULL, FIX_SEG, 0 );
#endif
            } else { /* seg or offset */
                if( CurToken != T_ID ) {
                    CErr1( ERR_EXPECTING_ID );
                } else {
                    name = CStrSave( Buffer );
                    offset = 0;
                    NextToken();
                    if( CurToken == T_PLUS ) {
                        NextToken();
                        if( CurToken == T_CONSTANT ) {
                            offset = Constant;
                            NextToken();
                        }
                    } else if( CurToken == T_MINUS ) {
                        NextToken();
                        if( CurToken == T_CONSTANT ) {
                            offset = -Constant;
                            NextToken();
                        }
                    }
                }
                switch( fixword ) {
                case FIXWORD_RELOFF:
#if _CPU == 8086
                    AddAFix( i, name, FIX_RELOFF16, offset );
                    i += 2;
#else
                    AddAFix( i, name, FIX_RELOFF32, offset );
                    i += 4;
#endif
                    break;
                case FIXWORD_OFFSET:
#if _CPU == 8086
                    AddAFix( i, name, FIX_OFF16, offset );
                    i += 2;
#else
                    AddAFix( i, name, FIX_OFF32, offset );
                    i += 4;
#endif
                    break;
                case FIXWORD_SEGMENT:
                    AddAFix( i, name, FIX_SEG, 0 );
                    i += 2;
                    break;
                }
                if( i > MAXIMUM_BYTESEQ ) {
                    if( ! too_many_bytes ) {
                        CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
                        too_many_bytes = 1;
                    }
                }
            }
        }
    }
    if( too_many_bytes ) {
        FreeAsmFixups();
        uses_auto = 0;
    } else {
        uses_auto = InsertFixups( buff, i );
    }
    CompFlags.pre_processing = 2;
#if _CPU == 8086  ||  _CPU == 386
    AsmSymFini();
#endif
    return( uses_auto );
}


hw_reg_set PragRegName( char *str )
{
    int         i;
    char        *p;
    hw_reg_set  name;

    if( *str == '_' ) {
        ++str;
        if( *str == '_' ) {
            ++str;
        }
    }
    i = 0;
    p = Registers;
    while( *p != '\0' ) {
        if( stricmp( p, str ) == 0 ) return( RegBits[ i ] );
        i++;
        while( *p++ != '\0' ) {;}
    }
    if( strcmp( str, "8087" ) == 0 ) {
        HW_CAsgn( name, HW_FLTS );
    } else {
        HW_CAsgn( name, HW_EMPTY );
    }
    return( name );
}



local void GetParmInfo( void )
{
    struct {
        unsigned f_pop           : 1;
        unsigned f_reverse       : 1;
        unsigned f_loadds        : 1;
        unsigned f_nomemory      : 1;
        unsigned f_list          : 1;
    } have;

    have.f_pop           = 0;
    have.f_reverse       = 0;
    have.f_loadds        = 0;
    have.f_nomemory      = 0;
    have.f_list          = 0;
    for( ;; ) {
        if( !have.f_pop && PragRecog( "caller" ) ) {
            CurrInfo->class |= CALLER_POPS;
            have.f_pop = 1;
        } else if( !have.f_pop && PragRecog( "routine" ) ) {
            CurrInfo->class &= ~ CALLER_POPS;
            have.f_pop = 1;
        } else if( !have.f_reverse && PragRecog( "reverse" ) ) {
            CurrInfo->class |= REVERSE_PARMS;
            have.f_reverse = 1;
        } else if( !have.f_nomemory && PragRecog( "nomemory" ) ) {
            CurrInfo->class |= NO_MEMORY_READ;
            have.f_nomemory = 1;
        } else if( !have.f_loadds && PragRecog( "loadds" ) ) {
            CurrInfo->class |= LOAD_DS_ON_CALL;
            have.f_loadds = 1;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            PragManyRegSets();
            have.f_list = 1;
        } else {
            break;
        }
    }
}


local void GetRetInfo( void )
{
    struct {
        unsigned f_no8087        : 1;
        unsigned f_list          : 1;
        unsigned f_struct        : 1;
    } have;

    have.f_no8087  = 0;
    have.f_list    = 0;
    have.f_struct  = 0;
    CurrInfo->class &= ~ NO_8087_RETURNS;               /* 29-mar-90 */
    for( ;; ) {
        if( !have.f_no8087 && PragRecog( "no8087" ) ) {
            have.f_no8087 = 1;
            HW_CTurnOff( CurrInfo->returns, HW_FLTS );
            CurrInfo->class |= NO_8087_RETURNS;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            have.f_list = 1;
            CurrInfo->class |= SPECIAL_RETURN;
            CurrInfo->returns = PragRegList();
        } else if( !have.f_struct && PragRecog( "struct" ) ) {
            have.f_struct = 1;
            GetSTRetInfo();
        } else {
            break;
        }
    }
}


local void GetSTRetInfo( void )
{
    struct {
        unsigned f_float        : 1;
        unsigned f_struct       : 1;
        unsigned f_allocs       : 1;
        unsigned f_list         : 1;
    } have;

    have.f_float  = 0;
    have.f_struct = 0;
    have.f_allocs = 0;
    have.f_list   = 0;
    for( ;; ) {
        if( !have.f_float && PragRecog( "float" ) ) {
            have.f_float = 1;
            CurrInfo->class |= NO_FLOAT_REG_RETURNS;
        } else if( !have.f_struct && PragRecog( "struct" ) ) {
            have.f_struct = 1;
            CurrInfo->class |= NO_STRUCT_REG_RETURNS;
        } else if( !have.f_allocs && PragRecog( "routine" ) ) {
            have.f_allocs = 1;
            CurrInfo->class |= ROUTINE_RETURN;
        } else if( !have.f_allocs && PragRecog( "caller" ) ) {
            have.f_allocs = 1;
            CurrInfo->class &= ~ROUTINE_RETURN;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            have.f_list = 1;
            CurrInfo->class |= SPECIAL_STRUCT_RETURN;
            CurrInfo->streturn = PragRegList();
        } else {
            break;
        }
    }
}


local void GetSaveInfo( void )
{
    hw_reg_set  modlist;
    hw_reg_set  default_flt_n_seg;
    hw_reg_set  flt_n_seg;

    struct {
        unsigned f_exact        : 1;
        unsigned f_nomemory     : 1;
        unsigned f_list         : 1;
    } have;

    have.f_exact    = 0;
    have.f_nomemory = 0;
    have.f_list     = 0;
    for( ;; ) {
        if( !have.f_exact && PragRecog( "exact" ) ) {
            CurrInfo->class |= MODIFY_EXACT;
            have.f_exact = 1;
        } else if( !have.f_nomemory && PragRecog( "nomemory" ) ) {
            CurrInfo->class |= NO_MEMORY_CHANGED;
            have.f_nomemory = 1;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            modlist = PragRegList();
            have.f_list = 1;
        } else {
            break;
        }
    }
    if( have.f_list ) {
        HW_Asgn( default_flt_n_seg, DefaultInfo.save );
        HW_CTurnOn( CurrInfo->save, HW_FULL );
        if( !have.f_exact && !CompFlags.save_restore_segregs ) {
            HW_CAsgn( flt_n_seg, HW_FLTS );
            HW_CTurnOn( flt_n_seg, HW_SEGS );
            HW_TurnOff( CurrInfo->save, flt_n_seg );
            HW_OnlyOn( default_flt_n_seg, flt_n_seg );
            HW_TurnOn( CurrInfo->save, default_flt_n_seg );
        }
        HW_TurnOff( CurrInfo->save, modlist );
    }
}

void GetAsmLine()
{
    char        buf[256];

    CompFlags.pre_processing = 1;       // cause T_NULL token at end of line
    if( strcmp( Buffer, "_emit" ) == 0 ) {
        NextToken();                    // get numeric constant
        if( CurToken != T_CONSTANT ) {
            ExpectConstant();
        } else {
            CodeBuffer[Address++] = Constant;
            NextToken();
        }
    } else {
        buf[0] = '\0';
        for(;;) {
            if( CurToken == T_SEMI_COLON ) {
                // ; .ASM comment
                for(;;) {
                    NextToken();
                    if( CurToken == T_EOF ) break;
                    if( CurToken == T_NULL ) break;
                }
                break;
            }
            if( CurToken == T_EOF ) break;
            if( CurToken == T_NULL ) break;
            if( CurToken == T___ASM ) break;
            if( CurToken == T_RIGHT_BRACE ) break;
            strncat( buf, Buffer, 255 );
            if( CurToken != T_DOT )
                strncat( buf, " ", 255 );
            NextToken();
        }
        AsmLine( buf );
    }
    CompFlags.pre_processing = 0;       // cause T_NULL token at end of line
}

static void MakeInlineAsmFunc( unsigned char *buff )
{
    int                 i;
    SYM_HANDLE          sym_handle;
    TREEPTR             tree;
    int                 uses_auto;
    auto char           name[8];

    i = Address;
    if( i != 0 ) {
        sprintf( name, "F.%d", AsmFuncNum );
        ++AsmFuncNum;
        CreateAux( name );
        *CurrInfo = DefaultInfo;
        CurrInfo->use = 1;
        CurrInfo->save = AsmRegsSaved;  // indicate no registers saved
        uses_auto = InsertFixups( buff, i );
        if( uses_auto ) {
            /*
               We want to force the calling routine to set up a [E]BP frame
               for the use of this pragma. This is done by saying the pragma
               modifies the [E]SP register. A kludge, but it works.
            */
            HW_CTurnOff( CurrInfo->save, HW_SP );
        }
        CurrEntry->info = CurrInfo;
        CurrEntry->next = AuxList;
        AuxList = CurrEntry;
        CurrEntry = NULL;
        sym_handle = MakeFunction( CStrSave( name ),
                        FuncNode( GetType( TYPE_VOID ), 0, NULL ) );
        tree = LeafNode( OPR_FUNCNAME );
        tree->op.sym_handle = sym_handle;
        tree = ExprNode( tree, OPR_CALL, NULL );
        tree->expr_type = GetType( TYPE_VOID );
        AddStmt( tree );
    }
}

void AsmStmt()
{
    int                 too_many_bytes;
    auto unsigned char  buff[ MAXIMUM_BYTESEQ + 32 ];

    // indicate that we are inside an __asm statement so scanner will
    // allow tokens unique to the assembler. e.g. 21h
    CompFlags.inside_asm_stmt = 1;
    NextToken();
    CodeBuffer = &buff[0];
    Address = 0;
    if( CurToken == T_LEFT_BRACE ) {
        NextToken();
        too_many_bytes = 0;
        for(;;) {               // grab assembler lines
            GetAsmLine();
            if( Address >= MAXIMUM_BYTESEQ ) {
                if( ! too_many_bytes ) {
                    CErr1( ERR_TOO_MANY_BYTES_IN_PRAGMA );
                    too_many_bytes = 1;
                }
                Address = 0;    // reset index to we don't overrun buffer
            }
            if( CurToken == T_RIGHT_BRACE ) break;
            if( CurToken == T_EOF ) break;
            NextToken();
        }
        CompFlags.pre_processing = 0;
        CompFlags.inside_asm_stmt = 0;
        MakeInlineAsmFunc( buff );
        NextToken();
    } else {
        GetAsmLine();           // grab single assembler instruction
        CompFlags.pre_processing = 0;
        CompFlags.inside_asm_stmt = 0;
        MakeInlineAsmFunc( buff );
        if( CurToken == T_NULL ) {
            NextToken();
        }
    }
    AsmSymFini();
}

⌨️ 快捷键说明

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