Jump to 
content
HP.com Home Products and Services Support and Drivers Solutions How to Buy
»  Contact HP

 

HP C

HP C
User's Guide for OpenVMS Systems


Previous Contents Index

5.4.4 #pragma environment Directive

The #pragma environment directive offers a global way to set, save, or restore the states of context pragmas. This directive protects include files from contexts set by encompassing programs, and protects encompassing programs from contexts that could be set in header files that they include.

The #pragma environment directive affects the following context pragmas:

  • #pragma extern_model
  • #pragma extern_prefix
  • #pragma member_alignment
  • #pragma message
  • #pragma names
  • #pragma pointer_size
  • #pragma required_pointer_size

This pragma has the following syntax:

#pragma environment command_line 

#pragma environment header_defaults
#pragma environment restore
#pragma environment save

The command_line keyword sets the states of all the context pragmas as specified on the command line (by default or by explicit use of the /[NO]MEMBER_ALIGNMENT, /[NO]WARNINGS, /EXTERN_MODEL, and /POINTER_SIZE qualifiers). You can use #pragma environment command_line within header files to protect them from any context pragmas that take effect before the header file is included.

The header_defaults keyword sets the states of all the context pragmas to their default values. This is almost equivalent to the situation in which a program with no command-line options and no pragmas is compiled, except that this pragma sets the pragma message state to #pragma nostandard, as is appropriate for header files.

The save keyword saves the current state of every pragma that has an associated context.

The restore keyword restores the current state of every pragma that has an associated context.

Without requiring further changes to the source code, you can use #pragma environment to protect header files from things like language extensions and enhancements that might introduce additional contexts.

A header file can selectively inherit the state of a pragma from the including file and then use additional pragmas as needed to set the compilation to non-default states. For example:


#ifdef _environment 
#pragma (1)
#pragma _defaults (2)
#pragma member_alignment restore (3)
#pragma member_alignment save (4)
#endif 
. 
.  /* contents of header file */ 
. 
#ifdef _environment 
#pragma 
#endif 

In this example:

  1. Saves the state of all context pragmas
  2. Sets the default compilation environment
  3. Pops the member alignment context from the #pragma member_alignment stack that was pushed by #pragma __environment save [restoring the member alignment context to its pre-existing state]
  4. Pushes the member alignment context back onto the stack so that the #pragma __environment restore can pop the entry off.

Thus, the header file is protected from all pragmas, except for the member alignment context that the header file was meant to inherit.

5.4.5 #pragma extern_model Directive

The #pragma extern_model directive controls how the compiler interprets objects that have external linkage. With this pragma, you can choose one of the following global symbol models to be used for external objects:

  • Common block model
    All declarations are definitions, and the linker combines all definitions with the same name into one definition. This is the model traditionally used for extern data by VAX C on OpenVMS VAX systems.
  • Relaxed ref/def model
    Some declarations are references and some are definitions. Multiple uninitialized definitions for the same object are allowed and resolved into one by the linker. However, a reference requires that at least one definition exists. This model is used by C compilers on UNIX systems.
  • Strict ref/def model
    Some declarations are references and some are definitions. There must be exactly one definition in the program for any symbol referenced. This model is the only one guaranteed to be acceptable to all standard C implementations. It is also the one used by VAX C for globaldef and globalref data. The relaxed ref/def model is the default model on HP C.
  • Globalvalue model
    This is like the strict ref/def model, except that these global objects have no storage; they are, instead, link-time constant values. This model is used by VAX C globalvalue symbols.

After a global symbol model is selected with the extern_model pragma, all subsequent declarations of objects having external storage class are treated according to the specified model until another extern_model pragma is specified.

For example, consider the following pragma:


#pragma extern_model strict_refdef 

After this pragma is specified, the following file-level declarations are treated as declaring global symbols according to the strict ref/def model:


int x = 0; 
extern int y; 

Regardless of the external model, the compiler uses standard C rules to determine if a declaration is a definition or a reference, although that distinction is not used in the common block model. An external definition is a file-level declaration that has no storage-class keyword, or that contains the extern storage-class keyword, and is also initialized. A reference is a declaration that uses the extern storage-class keyword and is not initialized. In the previous example, the declaration of x is a global definition and the declaration of y is a global reference.

The extern_model pragma does not affect the processing of declarations that contain the VAX C keywords globaldef, globalref, or globalvalue.

HP C also supports the command-line qualifiers /EXTERN_MODEL and /SHARE_GLOBALS to set the external model when the program starts to compile. Pragmas in the program being compiled supersede the command-line qualifier.

A stack of the compiler's external model state is kept so that #pragma extern_model can be used transparently in header files and in small regions of program text. See Sections 5.4.5.6 and 5.4.5.7 for more information.

The compiler issues an error message if the same object has two different external models specified in the same compilation unit, as in the following example:


#pragma extern_model common_block 
int i = 0; 
#pragma extern_model strict_refdef 
extern int i; 

Notes

  • The global symbols and psect names generated under the control of this pragma obey the case-folding rules of the /NAME qualifier. This behavior is consistent with VAX C.
  • While #pragma extern_model can be used to allocate several variables in the same psect, the placement of variables relative to each other within that psect cannot be controlled: the compiler does not necessarily allocate distinct variables to memory locations according to the order of appearance in the source code.

    Furthermore, the order of allocation can change as a result of seemingly unrelated changes to the source code, command-line options, or from one version of the compiler to the next; it is essentially unpredictable. The only way to control the placement of variables relative to each other is to make them members of the same struct type or, on OpenVMS Alpha systems, by using the noreorder attribute on a named #pragma extern_model strict_refdef.

See Section 5.4.5.8 to determine what combinations of external models are compatible for successfully compiling and linking your programs.

The following sections describe the various forms of the #pragma extern_model directive.

5.4.5.1 Syntax

The #pragma extern_model directive has the following syntax:

#pragma extern_model model_spec [attr[,attr]...] 

model_spec is one of the following:

  • common_block
  • relaxed_refdef
  • strict_refdef "name"
  • strict_refdef (No attr specifications allowed)
  • globalvalue (No attr specifications allowed)

[attr[,attr]...] are optional psect attribute specifications chosen from the following (at most one from each line):

  • gbl lcl (Not allowed with relaxed_refdef)
  • shr noshr
  • wrt nowrt
  • pic nopic (Not meaningful for Alpha)
  • ovr con
  • rel abs
  • exe noexe
  • vec novec
  • For OpenVMS Alpha systems: 0 byte 1 word 2 long 3 quad 4 octa 5 6 7 8 9 10 11 12 13 14 15 16 page
  • For OpenVMS VAX systems: 2 long 3 quad 4 octa 9 page

The last line of attributes are numeric alignment values. When a numeric alignment value is specified on a section, the section is given an alignment of two raised to that power.

On OpenVMS Alpha and I64 systems, the strict_refdef "name" extern_model can also take the following psect attribute specifications:

  • noreorder --- causes variables in the section to be allocated in the order they are defined.
  • natalgn --- has no effect on OpenVMS systems.
    It does, however, change the behavior on Tru64 UNIX systems: when specified, natalgn causes the global variables defined within the section to be allocated on their natural boundary. Currently, all global variables on Tru64 UNIX systems are allocated on a quadword boundary. When the natalgn attribute is specified, the compiler instead allocates the variable on an alignment that is natural for its type (chars on byte boundaries, ints on longword boundaries, and so on).
    Specifying the natalgn attribute also enables the noreorder attribute.

    Note

    Use of the natalgn attribute can cause a program to violate the Tru64 UNIX Calling Standard. The calling standard states that all global variables must be aligned on a quadword boundary. Therefore, variables declared in a natalgn section should only be referenced in the module that defines them.

See Table 4-3 for a description of the other attributes. See the OpenVMS Linker Utility Manual for more complete information on each.

The default attributes are: noshr, rel, noexe, novec, nopic.

For strict_refdef, the default is con. For common_block and relaxed_refdef, the default is ovr.

The default for wrt/nowrt is determined by the first variable placed in the psect. If the variable has the const type qualifier (or the readonly modifier), the psect is set to nowrt. Otherwise, it is set to wrt.

Restrictions on Setting Psect Attributes

Be aware of the following restriction on setting psect attributes.

The #pragma extern_model directive does not set psect attributes for variables declared as tentative definitions in the relaxed_refdef model. A tentative definition is one that does not contain an initializer. For example, consider the following code:


#pragma extern_model relaxed_refdef long 
int a; 
int b = 6; 
#pragma extern_model common_block long 
int c; 

Psect A is given octaword alignment (the default) because a is a tentative definition. Psect B is correctly given longword alignment because it is initialized and is, therefore, not a tentative definition. Psect C is also given longword alignment because it is declared in an extern_model other than relaxed_refdef.

Note

The psect attributes are normally used by system programmers who need to perform declarations normally done in macro. Most of these attributes are not needed in normal C programs. Also, notice that the setting of attributes is supported only through the #pragma mechanism, and not through the /EXTERN_MODEL command-line qualifier.

5.4.5.2 #pragma extern_model common_block

This pragma sets the compiler's model of external data to the common block model, which is the one used by VAX C.

The #pragma extern_model common_block directive has the following format:

#pragma extern_model common_block [attr[,attr]...] 

In this model, every declaration of an object with the extern storage class causes a global overlaid psect to be created. Both standard C definition declarations and reference declarations create the same object file records.

The psect has the same name as the object itself. There is no global symbol in addition to the psect name.

The object file records generated are the same as those generated by VAX C for extern objects.

See Section 4.8 for a description of how definitions using each external model are interpreted, what psect they would reside in, and what psect attributes are assigned. Also note the effect of the const type specifier for these definitions.

Note

The C language permits objects declared with the const type qualifier to be allocated in read-only memory, and when the C compiler allocates a psect for a const object, it marks that section as read-only.

This is not compatible with the C++ conventions because the C++ language permits objects with static storage duration to be initialized with values computed at run-time (before the main function gains control). When the C++ compiler allocates a psect for such a declaration, it marks the psect writable. Normally, only one compilation (the one responsible for initialization) will allocate a psect for a const object, and there is no problem.

But under the common_block extern model, the compilers will always allocate a psect for such a declaration, leading to a "conflicting attributes" warning from the linker if the same const-qualified declaration is processed by both C and C++. It is best to avoid use of the common_block extern model when const objects with external linkage are shared between C and Keep>(C++). If the common_block model must be used, then the const type qualifier should be removed (for example, by preprocessor conditionals) from the declaration processed by the C compiler.

5.4.5.3 #pragma extern_model relaxed_refdef

This pragma sets the compiler's model of external data to the relaxed ref/def model, which is the one used by pcc on UNIX systems.

The #pragma extern_model relaxed_refdef directive has the following format:

#pragma extern_model relaxed_refdef [attr[,attr]...] 

Be aware that an attr keyword of gbl or lcl is not allowed on the relaxed_refdef model.

With this model, three different types of object-file records can be produced, depending on the declaration of the object:

  • If the declaration is a standard C reference, the same type of object records are produced as VAX C would produce for a globalref; that is, a global symbol reference subrecord.
  • If the declaration is a standard C definition that is initialized, a psect definition and global symbol definition subrecord are produced. The name of the psect and symbol is the same as the name of the data object. This is equivalent to what VAX C would produce for the declaration. For example:


    globaldef "FOO" int FOO = 1; 
    

  • If the declaration is a standard C definition that is not initialized, then a conditional global symbol definition subrecord and conditional psect definition subrecord are produced. Except for the conditional aspect and the omission of an initializer, these object records resemble those produced with the #pragma extern_model common_block directive.

See Section 4.8 for a description of how definitions using each external model are interpreted, what psect they would reside in, and what psect attributes are assigned. Also note the effect of the const type specifier for these definitions.

5.4.5.4 #pragma extern_model strict_refdef

This pragma is the preferred alternative to the nonstandard storage-class keywords globaldef and globalref.

This pragma sets the compiler's model of external data to the strict ref/def model. Use this model for a program that is to be a standard C strictly-conforming program.

The #pragma extern_model strict_refdef directive has the following formats:

#pragma extern_model strict_refdef 

#pragma extern_model strict_refdef "name" [attr[,attr]...]

The name in quotes, if specified, is the name of the psect for any definitions.

Note that attr keywords cannot be specified for the strict_refdef model unless a name is given for the psect.

This model provides two different cases:

  • If the declaration is a standard C reference, the same type of object records are produced as VAX C would produce for a globalref; that is, a global symbol reference subrecord.
  • If the declaration is a standard C definition, the same type of object records are produced as VAX C would produce for a globaldef; that is, a global symbol definition subrecord.

See Section 4.8 for a description of how definitions using each external model are interpreted, what psect they would reside in, and what psect attributes are assigned. Also note the effect of the const type specifier for these definitions.

Note

In VAX C, the globaldef and globalref keywords interact with enum definitions in the following way:
  • If an enum variable is declared with the globaldef keyword, the enum literals of the type of the variable automatically become globalvalue constant definitions.
  • If an enum variable is declared with the globalref keyword, the enum literals of the type of the variable automatically become globalvalue constant references.


This behavior, does not occur with #pragma extern_model strict_refdef.

5.4.5.5 #pragma extern_model globalvalue

This pragma sets the compiler's external model to the globalvalue model, and is the preferred alternative to the nonstandard storage-class keyword globalvalue.

This pragma has the following format:

#pragma extern_model globalvalue 

Notice that this model does not accept attr keywords.

This model provides two different cases:

  • If the declaration is a standard C reference, the same object file records are produced as VAX C would produce for an uninitialized globalvalue.
  • If the declaration is a standard C definition, the same object records are produced as VAX C would produce for an initialized globalvalue.

Note

Only objects with a type of integer, enum, or pointer can have this external model. If this external model is used and the compiler encounters a declaration of an external object whose type is not one these, an error message is issued.

5.4.5.6 #pragma extern_model save

This pragma pushes the current external model of the compiler onto a stack. The stack records all information associated with the external model, including the shr/noshr state and any quoted psect name.

This pragma has the following format:

#pragma extern_model save 

The number of entries allowed in the #pragma extern_model stack is limited only by the amount of memory available to the compiler.

5.4.5.7 #pragma extern_model restore

This pragma pops the external model stack of the compiler. The external model is set to the state popped off the stack. The stack records all information associated with the external model, including the shr/noshr state and any quoted psect name. This pragma has the following format:

#pragma extern_model restore 

On an attempt to pop an empty stack, a warning message is issued and the compiler's external model is not changed.

5.4.5.8 Effects on the HP C Run-Time Library and User Programs

Using different HP C external models can introduce mutually incompatible object files. An object file compiled with one extern model may not link against an object file compiled with a different model.

Table 5-1 compares what happens when a reference or definition in an object file compiled with one external model is linked against a reference or definition in an object file compiled with a different external model. Note that the table is symmetric about the diagonal. For example, to look up what happens when you mix a relaxed_refdef reference with a strict_refdef definition, you can locate either the relaxed_refdef reference row and the strict_refdef definition column or the relaxed_refdef reference column and the strict_refdef definition row.

Table 5-1 contains no entries for mixing globalvalue symbols with other external models because globalvalue symbols are used only in special cases; they are not used as a general-purpose external model. For the other external models, there is a row and column for every different case. The common_block model only has one case because all symbols are definitions in that model; the relaxed_refdef model has three cases because it distinguishes between references, uninitialized definitions, and initialized definitions.

Table 5-1 Comparison of Mixing Different extern_models
  common_block def relaxed_refdef ref relaxed_refdef def relaxed_refdef initialized def strict_refdef ref strict_refdef def
common_block def Works Fails Works Works Fails Fails
relaxed_refdef ref Fails Works Works Works Works Works
relaxed_refdef uninitialized def Works Works Works Works Works Works
relaxed_refdef initialized def Works Works Works Multi Works Multi
strict_refdef ref Fails Works Works Works Works Works
strict_refdef def Fails Works Works Multi Works Multi


Notes

ref means reference; def means definition. In the common_block model, all external symbols are considered to be defs. A ref works with a ref if they both refer to the same thing. A def works with a ref if the def fulfills the ref. A def works with a def if they are combined into one by the linker. Multi means that the linker issues a multiply defined symbol error. This indicates a user error, not a mismatch between external models.


As Table 5-1 shows, the common_block model mixes poorly with the strict_refdef model, but the relaxed_refdef model works well with the common_block model and the strict_refdef model. The relaxed_refdef model fails only when a relaxed_refdef reference is linked against a common_block definition.

The fact that the external models are not all compatible with each other can be an issue for providers of general-purpose object libraries. One goal for such a library should be to work when linked with client code compiled with any of the external models. Otherwise, the provider of the object library might be forced to provide one copy of the library compiled with /EXTERN_MODEL=COMMON_BLOCK, another compiled with /EXTERN_MODEL=STRICT_REFDEF, and another compiled with /EXTERN_MODEL=RELAXED_REFDEF to let anyone link with the library.

The best way to accomplish the goal of allowing an object library to be linked with any code regardless of the external model used, is to provide header files that describe the interface to the object library. The header files can declare the global variables used by the object library after using #pragma extern_model to set the external model to the one used by the library. Programmers who want to use the library could then include these header files to get the required declarations. In order to avoid altering the external model used by the including program, header files should start with a #pragma extern_model save directive and end with a #pragma extern_model restore directive. The HP C RTL uses this approach.


Previous Next Contents Index

Privacy statement Using this site means you accept its terms
© 2007 Hewlett-Packard Development Company, L.P.