cpragma.c

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

C
1,622
字号
    int priority;

    if( CurToken == T_LEFT_PAREN ) {
        NextToken();
        if( PragRecog( "compiler" ) ) {
            priority = INIT_PRIORITY_LIBRARY - 1;
        } else if( PragRecog( "lib" ) ) {
            priority = INIT_PRIORITY_LIBRARY;
        } else {
            priority = INIT_PRIORITY_PROGRAM;
            MustRecog( T_ID );
        }
        CompInfo.init_priority = priority;
        MustRecog( T_RIGHT_PAREN );
    }
}


// forms: #pragma extref symbol
//        #pragma extref ( symbol, ..., symbol )
//
// causes a external reference to be emitted for the symbol
//
static void newPRAG_EXT_REF( SYMBOL sym )
{
    PRAG_EXT_REF* entry = RingAlloc( &pragmaExtrefs, sizeof( PRAG_EXT_REF ) );
    entry->extref = sym;
}

static int parseExtRef(     // PARSE SYMBOL NAME
    void )
{
    int err;                // TRUE ==> syntax error

    if( PragIdCurToken() ) {
        char* name = NameCreateLen( Buffer, TokenLen );
        SEARCH_RESULT* result;
        result = ScopeFindNaked( GetCurrScope()
                               , NameCreateLen( Buffer, TokenLen ) );
        if( result == NULL ) {
            CErr2p( ERR_PRAG_EXTREF_NONE, Buffer );
        } else {
            SYMBOL_NAME sname = result->sym_name;
            SYMBOL sym = sname->name_syms;
            ScopeFreeResult( result );
            if( sym == NULL ) {
                CErr2p( ERR_PRAG_EXTREF_BAD, Buffer );
            } else if( SymIsFunction( sym ) ) {
                if( IsOverloadedFunc( sym ) ) {
                    CErr2p( ERR_PRAG_EXTREF_OVERLOADED, sym );
                    sym = NULL;
                }
            } else if( SymIsData( sym ) ) {
                // no checks now
            } else {
                CErr2p( ERR_PRAG_EXTREF_BAD, sym );
                sym = NULL;
            }
            if( sym != NULL ) {
                newPRAG_EXT_REF( sym );
            }
        }
        NextToken();
        err = 0;
    } else {
        err = 1;
    }
    return err;
}


static void pragExtRef(     // #pragma extref ...
    void )
{
    int err;                // - TRUE ==> error occurred

    if( CurToken == T_LEFT_PAREN ) {
        PPState = PPS_EOL;
        NextToken();
        for( ; ; ) {
            err = parseExtRef();
            if( err ) break;
            if( CurToken != T_COMMA )  break;
            NextToken();
        }
        PPState = PPS_EOL | PPS_NO_EXPAND;
        if( ! err ) {
            MustRecog( T_RIGHT_PAREN );
        }
    } else {
        parseExtRef();
    }
}


void PragmaExtrefsValidate      // VALIDATE EXTREFS FOR PRAGMAS
    ( void )
{
    PRAG_EXT_REF* entry;        // - current entry

    RingIterBeg( pragmaExtrefs, entry ) {
        SYMBOL sym = entry->extref;
        if( SymIsExtern( sym ) ) {
            if( IsOverloadedFunc( sym ) ) {
                CErr2p( ERR_PRAG_EXTREF_OVERLOADED, sym );
                entry->extref = NULL;
            }
        } else {
            CErr2p( ERR_PRAG_EXTREF_EXTERN, sym );
            entry->extref = NULL;
        }
    } RingIterEnd( entry );
}


void PragmaExtrefsInject        // INJECT EXTREFS FOR PRAGMAS
    ( void )
{
    PRAG_EXT_REF* entry;        // - current entry

    RingIterBeg( pragmaExtrefs, entry ) {
        SYMBOL sym = entry->extref;
        if( NULL != sym ) {
            CgInfoAddPragmaExtref( sym );
        }
    } RingIterEnd( entry );
}


static void pragIntrinsic(      // SET FUNCTIONS TO BE (NOT TO BE) INTRINSIC
    boolean intrinsic )         // - TRUE ==> function to be intrinsic
{
    if( CurToken == T_LEFT_PAREN ) {
        NextToken();
        while( PragIdCurToken() ) {
            ScopeIntrinsic( intrinsic );
            NextToken();
            if( CurToken != T_COMMA )  break;
            NextToken();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}


static void pragDumpObjectModel( // DUMP OBJECT MODEL
    void )
{
    if( PragIdCurToken() ) {
        SEARCH_RESULT* result = ScopeFindNaked( GetCurrScope()
                                              , NameCreateLen( Buffer, TokenLen ) );
        if( result == NULL ) {
            CErr2p( ERR_DUMP_OBJ_MODEL, Buffer );
        } else {
            SYMBOL_NAME sname = result->sym_name;
            ScopeFreeResult( result );
            if( sname->name_syms == NULL ) {
                TYPE type = sname->name_type->sym_type;
                if( TypeDefined( type ) ) {
                    TYPE dump_type;
                    dump_type = StructType( type );
                    if( dump_type != NULL ) {
                        DumpObjectModelClass( dump_type );
                    } else {
                        dump_type = EnumType( type );
                        if( dump_type != NULL ) {
                            DumpObjectModelEnum( dump_type );
                        } else {
                            CErr2p( ERR_DUMP_OBJ_MODEL, Buffer );
                        }
                    }
                } else {
                    CErr2p( ERR_DUMP_OBJ_MODEL, Buffer );
                }
            } else {
                CErr2p( ERR_DUMP_OBJ_MODEL, Buffer );
            }
        }
        NextToken();
    }
}


static DT_METHOD parseDtorMethod( // PARSE A DESTRUCTOR METHOD
    void )
{
    DT_METHOD method;           // - method specified

    if( PragRecog( "direct" ) ) {
        method = DTM_DIRECT;
    } else if( PragRecog( "small" ) ) {
        method = DTM_TABLE_SMALL;
    } else if( PragRecog( "table" ) ) {
        method = DTM_TABLE;
    } else {
        method = DTM_COUNT;
    }
    return method;
}


static void pragDestruct(       // SPECIFY DESTRUCTION MECHANISM
    void )
{
    DT_METHOD method;           // - method
    DT_METHOD next;             // - next method spec

    if( CurToken == T_LEFT_PAREN ) {
        NextToken();
        method = DTM_COUNT;
        for( ; ; ) {
            if( CurToken == T_RIGHT_PAREN ) {
                NextToken();
                break;
            }
            next = parseDtorMethod();
            switch( next ) {
              default :
                method = DTM_COUNT;
                break;
              case DTM_DIRECT :
                switch( method ) {
                  case DTM_TABLE :
                    method = DTM_DIRECT_TABLE;
                    continue;
                  case DTM_TABLE_SMALL :
                    method = DTM_DIRECT_SMALL;
                    continue;
                  case DTM_COUNT :
                    method = next;
                    continue;
                  default :
                    continue;
                }
              case DTM_TABLE :
                switch( method ) {
                  case DTM_DIRECT :
                    method = DTM_DIRECT_TABLE;
                    continue;
                  case DTM_COUNT :
                    method = next;
                    continue;
                  default :
                    continue;
                }
              case DTM_TABLE_SMALL :
                switch( method ) {
                  case DTM_DIRECT :
                    method = DTM_DIRECT_SMALL;
                    continue;
                  case DTM_DIRECT_TABLE :
                  case DTM_TABLE :
                    method = DTM_TABLE_SMALL;
                    continue;
                  case DTM_COUNT :
                    method = next;
                    continue;
                  default :
                    continue;
                }
            }
            break;
        }
    } else {
        method = parseDtorMethod();
    }
    if( method != DTM_COUNT ) {
        CompInfo.dt_method_speced = method;
        CompFlags.dt_method_pragma = TRUE;
    }
}

#ifndef NDEBUG
static void pragBreak()
{
    __trap();
}
#endif

static boolean startPrag( char *id )
{
    unsigned save;

    // use this function when you want to immediately process macros
    // after you recognize the pragma (PragRecog performs a NextToken
    // so the pre-processing flag has to be set before PragRecog is called)
    save = PPState;
    PPState = PPS_EOL;
    // NextToken inside of PragRecog will process macros on next token
    if( PragRecog( id ) ) {
        return( TRUE );
    }
    PPState = save;
    return( FALSE );
}


// forms: (1) #pragma read_only_file
//        (2) #pragma read_only_file "file"*
//
// (1) causes current file to be marked read-only
// (2) causes indicated file to be marked read-only
//      - file must have started inclusion (may have completed)
//
static void pragReadOnlyFile
    ( void )
{
    if( CurToken == T_STRING ) {
        do {
            SrcFileReadOnlyFile( Buffer );
            NextToken();
            if( CurToken == T_SEMI_COLON ) {
                NextToken();
            }
        } while( CurToken == T_STRING );
    } else {
        SrcFileReadOnlyFile( NULL );
    }
}


// form: #pragma read_only_directory "directory"*
//
// (1) causes all files within directory to be marked read-only
//
static void pragReadOnlyDir
    ( void )
{
    while( CurToken == T_STRING ) {
        SrcFileReadOnlyDir( Buffer );
        NextToken();
        if( CurToken == T_SEMI_COLON ) {
            NextToken();
        }
    }
}

// form: #pragma once
//
// (1) current source file will never be #include'd again
static void pragOnce( void )
{
    SrcFileOnceOnly();
}

static void pragLibs(           // #PRAGMA library ( lib ... lib )
    void )
{
    if( CurToken == T_LEFT_PAREN ) {
        NextToken();
        while( PragIdCurToken() || CurToken == T_STRING ) {
            CgInfoAddUserLib( Buffer );
            NextToken();
        }
        MustRecog( T_RIGHT_PAREN );
    } else {
        CompFlags.pragma_library = 1;
    }
}

// #pragma pack()
// #pragma pack( <number> )
// #pragma pack( pop )
// #pragma pack( push )
// #pragma pack( push, <number> )

static void pragPack(           // #PRAGMA PACK
    void )
{
    if( CurToken == T_LEFT_PAREN ) {
        PPState = PPS_EOL;
        NextToken();
        switch( CurToken ) {
        case T_ID:
            if( PragRecog( "pop" ) ) {
                popPrag( &HeadPacks, &PackAmount );
                MustRecog( T_RIGHT_PAREN );
            } else if( PragRecog( "push" ) ) {
                if( CurToken == T_RIGHT_PAREN ) {
                    pushPrag( &HeadPacks, PackAmount );
                    MustRecog( T_RIGHT_PAREN );
                } else {
                    MustRecog( T_COMMA );
                    if( CurToken != T_CONSTANT ) {
                        MustRecog( T_CONSTANT );
                    } else {
                        pushPrag( &HeadPacks, PackAmount );
                        PackAmount = VerifyPackAmount( U32Fetch( Constant64 ) );
                        NextToken();
                        MustRecog( T_RIGHT_PAREN );
                    }
                }
            } else {
                CErr( ERR_EXPECTING_BUT_FOUND, "pop", Buffer );
            }
            PPState = PPS_EOL | PPS_NO_EXPAND;
            break;
        case T_CONSTANT:
            PackAmount = VerifyPackAmount( U32Fetch( Constant64 ) );
            PPState = PPS_EOL | PPS_NO_EXPAND;
            NextToken();
            MustRecog( T_RIGHT_PAREN );
            break;
        case T_RIGHT_PAREN:
            PPState = PPS_EOL | PPS_NO_EXPAND;
            NextToken();
            PackAmount = GblPackAmount;
            break;
        default:
            PPState = PPS_EOL | PPS_NO_EXPAND;
            MustRecog( T_RIGHT_PAREN );
        }
    }
}

void CPragma()                  // PROCESS A PRAGMA
{
    boolean our_pragma;         // - TRUE ==> one of ours

    SrcFileGuardStateSig();
    if( CompFlags.cpp_output ) {
        if( ! CppPrinting() ) return;
        fprintf( CppFile, "#pragma" );
        PPState = PPS_EOL;
        CompFlags.in_pragma = 1;
        for(;;) {
            GetNextToken();
            if( CurToken == T_NULL ) break;
            PrtToken();
        }
        CompFlags.in_pragma = 0;
    } else {
        our_pragma = FALSE;
        NextToken();
        for(;;) {
            if( ! PragRecog( NULL ) ) break;
            if( PragRecog( "on" ) ) {
                pragFlag( 1 );
            } else if( PragRecog( "off" ) ) {
                pragFlag( 0 );
            } else if( startPrag( "aux" ) || startPrag( "linkage" ) ) {
                PragAux();
            } else if( PragRecog( "library" ) ) {
                pragLibs();
            } else if( PragRecog( "once" ) ) {
                pragOnce();
            } else if( PragRecog( "extref" ) ) {
                pragExtRef();
            } else if( PragRecog( "comment" ) ) {
                pragComment();
            } else if( PragRecog( "pack" ) ) {
                pragPack();
            } else if( PragRecog( "warning" ) ) {
                if( pragWarning() ) {
                    /* ignore #pragma warning */
                    break;
                }
            } else if( PragRecog( "code_seg" ) ) {
                pragCodeSeg();
            } else if( PragRecog( "data_seg" ) ) {
                pragDataSeg();
            } else if( PragRecog( "initialize" ) ) {
                pragInitialize();
            } else if( PragRecog( "init_seg" ) ) {
                pragInitSeg();
            } else if( PragRecog( "inline_depth" ) ) {
                pragInlineDepth();
            } else if( PragRecog( "template_depth" ) ) {
                pragTemplateDepth();
            } else if( PragRecog( "inline_recursion" ) ) {
                pragInlineRecursion();
            } else if( PragRecog( "intrinsic" ) ) {
                pragIntrinsic( TRUE );
            } else if( PragRecog( "function" ) ) {
                pragIntrinsic( FALSE );
            } else if( PragRecog( "destruct" ) ) {
                pragDestruct();
            } else if( PragRecog( "enum" ) ) {
                pragEnum();
            } else if( PragRecog( "dump_object_model" ) ) {
                pragDumpObjectModel();
            } else if( startPrag( "read_only_file" ) ) {
                pragReadOnlyFile();
            } else if( startPrag( "read_only_directory" ) ) {
                pragReadOnlyDir();
            } else if( PragRecog( "message" ) ) {
                pragMessage();
            } else if( PragRecog( "error" ) ) {
                pragError();
#ifndef NDEBUG
            } else if( PragRecog( "break" ) ) {
                pragBreak();
#endif
            } else {
                break;
            }
            our_pragma = TRUE;
        }
        if( our_pragma ) {
            endOfPragma();
        }
    }
}


void PragInit(
    void )
{
    WatcallInfo.use = 2;

    CdeclInfo    = WatcallInfo;
    PascalInfo   = WatcallInfo;
    FortranInfo  = WatcallInfo;
    SyscallInfo  = WatcallInfo;
    OptlinkInfo  = WatcallInfo;
    StdcallInfo  = WatcallInfo;
    FastcallInfo = WatcallInfo;

    CompInfo.init_priority = INIT_PRIORITY_PROGRAM;
}


typedef struct magic_word {
    char            *name;
    struct aux_info *info;
} MAGIC_WORD;

#ifdef pick
#undef pick
#endif
#define pick( a, b, c ) { b , c },

static MAGIC_WORD magicWords[] = {
#include "auxinfo.h"
};


static int lookupMagicKeyword(  // LOOKUP A MAGIC KEYWORD
    char *name )                // - name to be looked up
{
    int     i;

⌨️ 快捷键说明

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