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 + -
显示快捷键?