cpragma.c

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

C
1,622
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Target independent pragma processing.
*
****************************************************************************/


#include "plusplus.h"
#include "preproc.h"
#include "errdefns.h"
#include "memmgr.h"
#include "cgdata.h"
#include "cgback.h"
#include "cmdline.h"
#include "pragdefn.h"
#include "pdefn2.h"
#include "template.h"
#include "pcheader.h"
#include "name.h"
#include "stack.h"
#include "ring.h"
#include "fnovload.h"
#include "cginlibs.h"
#include "cginimps.h"
#include "initdefs.h"
#include "asmstmt.h"

// from \watcom\h
#include "rtinit.h"


typedef struct {                // PRAG_EXT_REF -- extref's pragma'd
    void* next;                 // - next in ring
    SYMBOL extref;              // - extref symbol
} PRAG_EXT_REF;

static PRAG_EXT_REF* pragmaExtrefs; // ring of pragma'd extref symbols

extern  void    PragAux();

static void init                // MODULE INITIALIZATION
    ( INITFINI* defn )
{
    defn = defn;
    pragmaExtrefs = NULL;
}

static void fini                // MODULE COMPLETION
    ( INITFINI* defn )
{
    defn = defn;
    RingFree( &pragmaExtrefs );
}

INITDEFN( pragma_extref, init, fini );

static boolean grabNum( unsigned *val )
{
    if( CurToken == T_CONSTANT ) {
        *val = U32Fetch( Constant64 );
        NextToken();
        return( TRUE );
    }
    if( CurToken == T_LEFT_PAREN ) {
        NextToken();
        if( CurToken == T_CONSTANT ) {
            *val = U32Fetch( Constant64 );
            NextToken();
            MustRecog( T_RIGHT_PAREN );
            return( TRUE );
        }
    }
    NextToken();
    return( FALSE );
}

// #pragma template_depth n
// #pragma template_depth( n )
//
// Used to set the depth, up to which, function templates will be expanded
static void pragTemplateDepth(    // PROCESS #pragma template_depth
    void )
{
    unsigned num;

    if( grabNum( &num ) ) {
        TemplateSetDepth( num );
    } else {
        CErr1( ERR_PRAG_TEMPLATE_DEPTH );
    }
}

// #pragma inline_depth n
// #pragma inline_depth( n )    -- MS compatible
//
// Used to set the depth, up to which, inlining of functions will take place.
// "n" must be number 0:255
//
static void pragInlineDepth(    // PROCESS #pragma inline_depth
    void )
{
    unsigned num;

    if( grabNum( &num ) && num <= MAX_INLINE_DEPTH ) {
        CgBackSetInlineDepth( num );
    } else {
        CErr1( ERR_PRAG_INLINE_DEPTH );
    }
}

// #pragma comment( lib, "libname.lib" )

static void pragComment(        // #PRAGMA COMMENT
    void )
{
    if( CurToken == T_LEFT_PAREN ) {
        PPState = PPS_EOL;
        NextToken();
        if( PragRecog( "lib" ) ) {
            MustRecog( T_COMMA );
            if( CurToken != T_STRING ) {
                MustRecog( T_STRING );
            } else {
                do {
                    CgInfoAddUserLib( Buffer );
                    NextToken();
                } while( CurToken == T_STRING );
            }
        } else {
            while( CurToken != T_RIGHT_PAREN ) {
                NextToken();
            }
        }
        PPState = PPS_EOL | PPS_NO_EXPAND;
        MustRecog( T_RIGHT_PAREN );
    }
}

static void collectStrings( VBUF *vinfo )
{
    VbufInit( vinfo );
    VStrNull( vinfo );
    while( CurToken == T_STRING ) {
        VStrConcStr( vinfo, Buffer );
        NextToken();
    }
}

// #pragma message( "message" " string" );

static void pragMessage(        // #PRAGMA MESSAGE
    void )
{
    VBUF str;

    if( CurToken == T_LEFT_PAREN ) {
        PPState = PPS_EOL;
        NextToken();
        if( CurToken == T_STRING ) {
            collectStrings( &str );
            CErr2p( WARN_USER_WARNING_MSG, str.buf );
            VbufFree( &str );
        }
        PPState = PPS_EOL | PPS_NO_EXPAND;
        MustRecog( T_RIGHT_PAREN );
    }
}

// #pragma error "message string" ;

static void pragError(          // #PRAGMA ERROR
    void )
{
    VBUF str;

    if( CurToken == T_STRING ) {
        PPState = PPS_EOL;
        collectStrings( &str );
        CErr2p( ERR_USER_ERROR_MSG, str.buf );
        VbufFree( &str );
        PPState = PPS_EOL | PPS_NO_EXPAND;
    }
}


// #pragma inline_recursion on
// #pragma inline_recursion off
// #pragma inline_recursion(on)         -- MS compatible
// #pragma inline_recursion(off)        -- MS compatible
//
// Used to indicate whether recursive inlining is permitted or not
//
static void pragInlineRecursion(// PROCESS #pragma inline_recusrion
    void )
{
    if( PragRecog( "on" ) ) {
        CgBackSetInlineRecursion( TRUE );
    } else if( PragRecog( "off" ) ) {
        CgBackSetInlineRecursion( FALSE );
    } else {
        if( CurToken == T_LEFT_PAREN ) {
            NextToken();
            if( PragRecog( "on" ) ) {
                CgBackSetInlineRecursion( TRUE );
            } else if( PragRecog( "off" ) ) {
                CgBackSetInlineRecursion( FALSE );
            } else {
                MustRecog( T_ID );
            }
            MustRecog( T_RIGHT_PAREN );
        }
    }
}


// #pragma code_seg ( segment [, class] )
// #pragma code_seg segment
//
// "segment" sets the default code segment for remaining functions
// "class" is ignored
//
static void pragCodeSeg(        // SET NEW CODE SEGMENT
    void )
{
    char *seg_name;
    char *seg_class;

    if( CurToken == T_LEFT_PAREN ) {
        PPState = PPS_EOL;
        NextToken();
        if( (CurToken == T_STRING) || (CurToken == T_ID) ) {
            seg_name = strsave( Buffer );
            seg_class = NULL;
            NextToken();
            if( CurToken == T_COMMA ) {
                NextToken();
                if( (CurToken == T_STRING) || (CurToken == T_ID) ) {
                    seg_class = strsave( Buffer );
                    NextToken();
                } else {
                    MustRecog( T_STRING );
                }
            }
            SegmentCode( seg_name, seg_class );
            CMemFree( seg_name );
            CMemFree( seg_class );
        } else if( CurToken == T_RIGHT_PAREN ) {
            // restore back to default behaviour
            SegmentCode( NULL, NULL );
        }
        PPState = PPS_EOL | PPS_NO_EXPAND;
        MustRecog( T_RIGHT_PAREN );
    } else if( CurToken == T_STRING ) {
        SegmentCode( Buffer, NULL );
        NextToken();
    }
}


// #pragma data_seg ( segment [, class] )
// #pragma data_seg segment
//
// "segment" sets the default data segment for remaining objects
// "class" is ignored
//
static void pragDataSeg(        // SET NEW DATA SEGMENT
    void )
{
    char *seg_name;
    char *seg_class;

    if( CurToken == T_LEFT_PAREN ) {
        PPState = PPS_EOL;
        NextToken();
        if( (CurToken == T_STRING) || (CurToken == T_ID) ) {
            seg_name = strsave( Buffer );
            seg_class = NULL;
            NextToken();
            if( CurToken == T_COMMA ) {
                NextToken();
                if( (CurToken == T_STRING) || (CurToken == T_ID) ) {
                    seg_class = strsave( Buffer );
                    NextToken();
                } else {
                    MustRecog( T_STRING );
                }
            }
            SegmentData( seg_name, seg_class );
            CMemFree( seg_name );
            CMemFree( seg_class );
        } else if( CurToken == T_RIGHT_PAREN ) {
            // restore back to default behaviour
            SegmentData( NULL, NULL );
        }
        PPState = PPS_EOL | PPS_NO_EXPAND;
        MustRecog( T_RIGHT_PAREN );
    } else if( CurToken == T_STRING ) {
        SegmentData( Buffer, NULL );
        NextToken();
    }
}


// forms: #pragma warning # level   (change message # to have level "level)
//      : #pragma warning * level   (change all messages to have level "level)
//
// - "level" must be digit (0-9)
// - "level==0" implies warning will be treated as an error
//
static boolean pragWarning(     // PROCESS #PRAGMA WARNING
    void )
{
    int msgnum;                 // - message number
    int level;                  // - new level
    boolean change_all;         // - TRUE ==> change all levels
    boolean error_occurred;     // - TRUE ==> error has occurred

    error_occurred = FALSE;
    if( CurToken == T_TIMES ) {
        change_all = TRUE;
    } else if( CurToken == T_CONSTANT ) {
        msgnum = U32Fetch( Constant64 );
        change_all = FALSE;
    } else {
        // ignore; MS or other vendor's #pragma
        return( TRUE );
    }
    NextToken();
    if( CurToken == T_CONSTANT ) {
        level = U32Fetch( Constant64 );
    } else {
        CErr1( ERR_PRAG_WARNING_BAD_LEVEL );
        error_occurred = TRUE;
    }
    NextToken();
    if( ! error_occurred ) {
        if( change_all ) {
            WarnChangeLevels( level );
        } else {
            WarnChangeLevel( level, msgnum );
        }
    }
    return( FALSE );
}


static void endOfPragma(
    void )
{
    if( CurToken == T_SEMI_COLON ) NextToken();
    if( CurToken != T_NULL ) Expecting( Tokens[ T_NULL ] );
    while( CurToken != T_NULL && CurToken != T_EOF ) {
        NextToken();
    }
}

void PragmaSetToggle(           // SET TOGGLE
    boolean set_flag )          // - TRUE ==> set flag
{
    #define toggle_pick( x ) \
        if( strcmp( Buffer, #x ) == 0 ) {       \
            PragDbgToggle.x = set_flag;         \
            return;                             \
        }
    #include "dbgtogg.h"

    #define toggle_pick( x ) \
        if( strcmp( Buffer, #x ) == 0 ) {       \
            PragToggle.x = set_flag;            \
            return;                             \
        }
    #include "tognam.h"
}

static void pragFlag(           // SET TOGGLES
    boolean set_flag )          // - TRUE ==> set flag
{
    if( CurToken == T_LEFT_PAREN ) {
        NextToken();
        while( PragIdCurToken() ) {
            PragmaSetToggle( set_flag );
            NextToken();
        }
        MustRecog( T_RIGHT_PAREN );
    }
}


// forms: #pragma initialize [before/after]* priority
//
//  where priority is:
//      - number 0 - 255
//      - library (32)
//      - program (64)
//
// The pragma is used to set the initialize priority for the module ( when
// it occurs at file scope) or to specify an initialization function to
// be called (when it occurs within a function).
//
// The function must be previously declared to have no parameters and to
// be static.
//
static void pragInitialize(     // #pragma initialize ...
    void )
{
    int adjust;                 // - before/after adjustment
    unsigned priority;          // - initialization priority
    unsigned test;

    adjust = 0;
    for(;;) {
        /* allow "before before library" */
        if( PragRecog( "after" ) ) {
            ++adjust;
        } else if( PragRecog( "before" ) ) {
            --adjust;
        } else {
            break;
        }
    }
    priority = INIT_PRIORITY_PROGRAM;
    if( CurToken == T_CONSTANT ) {
        test = U32Fetch( Constant64 );
        if( test <= 255 ) {
            priority = test;
        } else {
            CErr1( ERR_PRAG_INITIALIZE_PRIORITY );
        }
    } else if( PragRecog( "library" ) ) {
        priority = INIT_PRIORITY_LIBRARY;
    } else if( PragRecog( "program" ) ) {
        priority = INIT_PRIORITY_PROGRAM;
    } else {
        CErr1( ERR_PRAG_INITIALIZE_PRIORITY );
    }
    NextToken();
    priority += adjust;
    if( priority > 255 ) {
        CErr1( ERR_PRAG_INITIALIZE_PRIORITY );
        priority = INIT_PRIORITY_PROGRAM;
    }
    CompInfo.init_priority = priority;
}

static void pushPrag( PRAG_STACK **h, unsigned value )
{
    PRAG_STACK *stack_entry;

    stack_entry = StackPop( &FreePrags );
    if( stack_entry == NULL ) {
        stack_entry = CPermAlloc( sizeof( *stack_entry ) );
    }
    stack_entry->value = value;
    StackPush( h, stack_entry );
}

static boolean popPrag( PRAG_STACK **h, unsigned *pvalue )
{
    PRAG_STACK *pack_entry;

    pack_entry = StackPop( h );
    if( pack_entry != NULL ) {
        if( pvalue != NULL ) {
            *pvalue = pack_entry->value;
        }
        StackPush( &FreePrags, pack_entry );
        return( TRUE );
    }
    return( FALSE );
}

// forms: (1) #pragma enum int
//        (2) #pragma enum minimum
//        (3) #pragma enum original
//        (4) #pragma enum pop
//
// The pragma affects the underlying storage-definition for subsequent
// enum declarations.
//
// (1) make int the underlying storage definition (same as -ei)
// (2) minimize the underlying storage definition (same as no -ei)
// (3) reset back to result of command-line parsing
// (4) restore previous value
//
// 1-3 all push previous value before affecting value
//
static void pragEnum            // #pragma enum PARSING
    ( void )
{
    unsigned make_enums_an_int;

    if( PragRecog( "int" ) ) {
        pushPrag( &HeadEnums, CompFlags.make_enums_an_int );
        CompFlags.make_enums_an_int = 1;
    } else if( PragRecog( "minimum" ) ) {
        pushPrag( &HeadEnums, CompFlags.make_enums_an_int );
        CompFlags.make_enums_an_int = 0;
    } else if( PragRecog( "original" ) ) {
        pushPrag( &HeadEnums, CompFlags.make_enums_an_int );
        CompFlags.make_enums_an_int = CompFlags.original_enum_setting;
    } else if( PragRecog( "pop" ) ) {
        if( popPrag( &HeadEnums, &make_enums_an_int ) ) {
            CompFlags.make_enums_an_int = make_enums_an_int;
        }
    }
}


// forms: #pragma init_seg({compiler|lib|user})
//
//      - compiler (16)
//      - library (32)
//      - user (64)
//
static void pragInitSeg(     // #pragma init_seg ...
    void )
{

⌨️ 快捷键说明

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