5.4 Implementation-Specific Preprocessor Directive (#pragma)

The #pragma directive is a standard method for implementing features that vary from one compiler to the next. This section describes the implementation-specific pragmas that are available on the DEC C compiler for OpenVMS systems. Pragmas supported by all implementations of DEC C are described in the DEC C Language Reference Manual.

Note that some #pragma directives are subject to macro expansion. A macro reference can occur anywhere after the keyword pragma. The following example demonstrates this feature using the #pragma inline directive:

#define opt inline
#define f func
#pragma opt(f)

The #pragma directive becomes #pragma inline (func) after both macros are expanded.

The following pragmas are subject to macro expansion:

builtins            inline                 linkage       standard
dictionary          noinline               module        nostandard
extern_model        member_alignment       message       use_linkage
extern_prefix       nomember_alignment

The following sections describe the #pragma directives.

5.4.1 #pragma [no]builtins Directive

The #pragma [no]builtins directive is provided for VAX C compatibility. It disables or enables access to the DEC C built- in functions. When enabled through #pragma builtins, these functions do not result in a reference to a function in the run-time library or in your program. Instead, the compiler generates the machine instructions necessary to carry out the function directly at the call site. (For information on available built-in functions, see Section 6.2.)

The #pragma [no]builtins directive has the following formats:

#pragma builtins
#pragma nobuiltins

Note
DEC C supports #pragma builtins for compatibility with VAX C, but for compatibility with DEC C on other platforms Digital recommends using #include <builtins.h> instead. DEC C implements #pragma builtins as if it were #include <builtins.h>; if you get an error from #pragma builtins, it is the same kind of error you would get if you specified #include <builtins.h>.

5.4.2 #pragma dictionary Directive

The #pragma dictionary directive allows you to extract CDD/Repository data definitions and include these definitions in your program.

The ANSI C compliant #pragma dictionary directive is equivalent to the VAX C compatible #dictionary directive (Section 5.1), but is supported in all compiler modes. (The #dictionary directive is retained for compatibility and is supported only when compiling with the /STANDARD=VAXC qualifier.)

The #pragma dictionary directive has the following format:

#pragma dictionary CDD_path [null_terminate] [name
(structure_name)] [text1_to_array | text1_to_char]

The CDD_path is a character string that gives the path name of a CDD/Repository record, or a macro that expands to the path name of the record.

The optional null_terminate keyword can be used to specify that all string data types should be null-terminated.

The optional name() can be used to supply an alternate tag name or declarator(struct_name) for the outer level of a CDD/Repository structure.

The optional text1_to_char keyword forces the CDD/Repository type "text" to be translated to char, rather than "array of char" if the size is 1. This is the default when null_terminate is not specified.

The optional text1_to_array keyword forces the CDD/Repository type "text" to be translated to type "array of char" even when the size is 1. This is the default when null_terminate is specified.

Here's a sample #pragma dictionary directive:

#pragma dictionary "CDD$TOP.personnel.service.salary_record"

This path name describes all subdirectories, beginning with the root directory (CDD$TOP), that lead to the salary_record data definition.

You can use the logical name CDD$DEFAULT to define a default path name for a dictionary directory. This logical name can specify part of the path name for the dictionary object. For example, you can define CDD$DEFAULT as follows:

$ DEFINE CDD$DEFAULT CDD$TOP.PERSONNEL

When this definition is in effect, the #pragma dictionary directive can contain the following:

#pragma dictionary "service.salary_record"

Descriptions of data definitions are entered into the dictionary in a special-purpose language called CDO (Common Dictionary Operator), which replaces the older interface called CDDL (Common Data Dictionary Language).

CDD definitions written in CDDL are included in a dictionary with the CDDL command. For example, you can write the following definition for a structure containing someone's first and last name:

define record cdd$top.doc.cname_record.
   cname structure.
      first    datatype is text
               size is 20 characters.
      last     datatype is text
               size is 20 characters.
   end cname structure.
end cname_record record.

If a source file named CNAME.DDL needs to use this definition, you can include the definition in the CDD subdirectory named doc by entering the following command:

$ CDDL cname

After executing this command, a DEC C program can reference this definition with the #pragma dictionary directive. If the #pragma dictionary directive is not embedded in a DEC C structure declaration, then the resulting structure is declared with a tag name corresponding to the name of the CDD/Repository record. Consider the following example:

#pragma dictionary "cdd$top.doc.cname_record"

This DEC C preprocessor statement results in the following declarations:

struct cname
{
   char first [20];
   char last  [20];
};

You can also embed the #pragma dictionary directive in another DEC C structure declaration as follows:

struct
{
   int id;

#pragma dictionary "cname_record"

}  customer;

These lines of code result in the following declaration, which uses cname as an identifier for the embedded structure:

struct
{
   int id;
   struct
   {
      char first [20];
      char last [20];
   }  cname;
}  customer;

If you specify /LIST and either /SHOW=DICTIONARY or /SHOW=ALL in the compilation command line, then the translation of the CDD/Repository record description into DEC C is included in the listing file and marked with the letter D in the margin.

For information on DEC C support for CDD/Repository data types. see Section C.4.3.

5.4.3 #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 member_alignment
#pragma message
#pragma extern_model
#pragma extern_prefix
#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 __pragma_environment
#pragma __environment save  1
#pragma __environment header_defaults 2
#pragma member_alignment restore 3
#pragma member_alignment save 4
#endif
.
.  /* contents of header file */
.
#ifdef __pragma_environment
#pragma __environment restore
#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.4 #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:

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 ANSI 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.

DEC 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.4.6 and 5.4.4.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;

Note that 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.

See Section 5.4.4.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.4.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
0 byte 1 word 2 long 3 quad 4 octa 16 page

See Table 4-4 for a description of these 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 restrictions on setting psect attributes:


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.4.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 ANSI 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.

5.4.4.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:

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.4.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 an ANSI 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:

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: This behavior, does not occur with #pragma extern_model strict_ refdef.

5.4.4.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:


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.4.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.4.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.4.8 Effects on the DEC C Run-Time Library and User Programs

Using different DEC 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 DEC C RTL uses this approach.

If header files are not provided, an object library should use the relaxed_refdef external model since it will link successfully with either common_block compiled code or strict_refdef compiled code. The only restriction is that the library must not reference an external symbol that is not defined in the library but is defined only in the user program. This avoids the common_block case that fails. Note that the relaxed_refdef model allows both the library and the user code to contain definitions for any symbol, as long as both do not attempt to initialize the symbol.

5.4.4.9 Example

Example 5-1 shows the use of #pragma extern_model in a sample module. Assume that the module is compiled with the /EXTERN_MODEL=COMMON and /SHARE_GLOBALS qualifiers.

Example 5-1 #pragma extern_model Example

#pragma extern_model save
 globaldef "BAR1" int FOO1;          /* strict_refdef shr def  */
 extern int com1;                    /* common_block shr def   */
 int com2;                           /* common_block shr def   */
#pragma extern_model common_block noshr
 globaldef "BAR2" int FOO2;          /* strict_refdef shr def  */
 extern int com3 = 23;               /* common_block noshr def */
#pragma extern_model globalvalue
 int gv1;                            /* globalvalue def        */
 extern int gv2;                     /* globalvalue ref        */
 int gv3 = 5;                        /* globalvalue def        */
 extern int gv4 = 42;                /* globalvalue def        */
#pragma extern_model strict_refdef "BAR1" shr
int FOO1A;                           /* strict_refdef shr def  */
extern int FOO1B;                    /* strict_refdef ref      */
globaldef "BAR3" noshare int foo3;
#pragma extern_model relaxed_refdef
int rrd1;                            /* relaxed_refdef noshr def */
extern rrd2;                         /* relaxed_refdef ref     */
#pragma extern_model restore
int com4;                            /* common_block shr def   */

Key to Example 5-1:

  1. FOO1 has the strict_refdef model with the share attribute (because of /SHARE). It resides in psect BAR1.

  2. com1 has the common_block model with the share attribute. Like all common_block globals, com1 is a definition.

  3. com2 has the common_block model with the share attribute. Like all common_block globals, com2 is a definition.

  4. FOO2 has the strict_refdef model with the share attribute. The /SHARE qualifier overrides the noshr keyword on the preceding #pragma extern_model. FOO2 resides in psect BAR2.

  5. com3 has the common_block model with the noshare attribute.

  6. gv1 has the globalvalue model. It is a definition. Since it lacks an explicit initializer, gv1 is implicitly initialized to 0. Therefore, it is a globalvalue with a link-time value of 0.

  7. gv2 has the globalvalue model. It is a reference.

  8. gv3 has the globalvalue model. It is a definition with a link-time value of 5.

  9. gv4 has the globalvalue model. It is a definition with a link-time value of 42.

  10. FOO1A has the strict_refdef model with the noshare attribute. It is a definition and resides in the psect BAR1.

  11. FOO1B has the strict_refdef model and is a reference. Since it is a reference, it will reside in whatever psect is specified by the definition.

  12. foo3 has the strict_refdef model with the noshare attribute. It is a definition and resides in the psect BAR3.

  13. rrd1 has the relaxed_refdef model with the noshare attribute. It is a definition.

  14. rrd2 has the relaxed_refdef model and is a reference.

  15. com4 has the common_block model with the share attribute, because the preceding line popped the external model back to its command-line state.

5.4.5 #pragma extern_prefix Directive

The #pragma extern_prefix directive controls the compiler's synthesis of external names, which the linker uses to resolve external name requests.

When you specify #pragma extern_prefix with a string argument, the DEC C++ compiler attaches the string to the beginning of all external names produced by the declarations that follow the pragma specification.

This pragma is useful for creating libraries where the facility code can be attached to the external names in the library.

The #pragma intrinsic directive has the following format:

#pragma extern_prefix "string" #pragma extern_prefix save #pragma
extern_prefix restore

The quoted "string" is attached to external names in the declarations that follow the pragma specification.

The save and restore keywords can be used to save the current pragma prefix string and to restore the previously saved pragma prefix string, respectively.

The default external prefix, when none has been specified by a pragma, is the null string.

The recommended use is as follows:


#pragma extern_prefix save
#pragma extern_prefix "prefix-to-prepend-to-external- names"
. . . some declarations and definitions . . .
#pragma extern_prefix restore

When an extern_prefix is in effect and you are using #include to include header files, but do not want the extern_prefix to apply to extern declarations in the header files, use the following code sequence:


#pragma extern_prefix save
#pragma extern_prefix ""
#include . . .
#pragma extern_prefix restore

Otherwise, external prefix is attached to the beginning of external identifiers for definitions in the included files.

All external names prefixed with a nonnull string using #pragma extern_prefix are converted to uppercase letters regardless of the setting of the /NAMES qualifier.

The DEC C compiler treats #pragma extern_prefix independently of the /PREFIX_LIBRARY_ENTRIES qualifier. The /PREFIX_LIBRARY_ENTRIES qualifier affects only ANSI C and DEC C Run-Time Library (RTL) entries; the extern_prefix pragma affects external identifiers for any externally visible name that is explicitly declared.

5.4.6 #pragma [no]inline Directive

Function inlining is the inline expansion of function calls; it replaces the function call with the function code itself. Inline expansion of functions reduces execution time by eliminating function-call overhead and allowing the compiler's general optimization methods to apply across the expanded code. Compared with the use of function-like macros, function inlining has the following advantages:

Also, the semantics are exactly the same as if inline expansion had not occurred. You cannot get this behavior using macros.

Use the following preprocessor directives to control function inlining:

#pragma inline ( id, . . . )
#pragma noinline ( id, . . . )

The id is a function identifier.

If a function is named in an inline directive, calls to that function will be expanded as inline code, if possible.

If a function is named in a noinline directive, calls to that function will not be expanded as inline code.

If a function is named in both an inline and a noinline directive, an error message is issued.

For calls to functions named in neither an inline nor a noinline directive, DEC C expands the function as inline code whenever appropriate as determined by a platform- specific algorithm.

Use of the #pragma inline directive causes inline expansion regardless of the size or number of times the specified functions are called.

In the following example of function inlining, the functions push and pop are expanded inline throughout the module in which the #pragma inline appears:

void push(int);
int pop(void);

#pragma inline(push, pop)

int stack[100];
int *stackp = &stack;

void push(int x)
{
    if (stackp == &stack)
        *stackp = x;
    else
        *stackp++ = x;
}

int pop()
{
    return *stackp--;
}

main()
{

  push(1);
  printf("The top of stack is now %d \n",pop());
}

By default, DEC C for OpenVMS Systems attempts to provide inline expansion for all functions, and uses the following function characteristics to determine if it can provide inline expansion:

If a function is to be expanded inline, you must place the function definition in the same module as the function call. The definition can appear either before or after the function call.

5.4.7 #pragma intrinsic Directive (Alpha only)

The #pragma intrinsic preprocessor directive specifies that calls to the specified functions are intrinsic (UNIX equivalent to built-in function on OpenVMS systems).

The #pragma intrinsic directive has the following format:

#pragma intrinsic (function1[,function2, . . . ])

The following functions have intrinsic forms:

asm
fasm
dasm

For a description of these asm intrinsic functions, see Section 6.2.1.2.

5.4.8 #pragma linkage Directive (Alpha only)

The #pragma linkage preprocessor directive allows you to specify special linkage types for function calls. This pragma is used with the #pragma use_linkage directive, described in Section 5.4.16, to associate a previously defined special linkage with a function.

The #pragma linkage directive has the following format:

#pragma linkage linkage-name = (characteristics)

The linkage-name is the name to be given to the linkage type being defined. It has the form of a C identifier. Linkage types have their own name space, so their names will not conflict with other identifiers or keywords in the compilation unit.

The characteristics specify information about where parameters will be passed, where the results of the function are to be received, and what registers are modified by the function call. Specify these characteristics as a parenthesized list of comma-separated items of the following forms:

parameters (register-list)
result (simple-register-list)
preserved (simple-register-list)
nopreserve (simple-register-list)
notused (simple-register-list)
notneeded (ai, lp)

You can supply the parameters, result, preserved, nopreserve, notused, and notneeded keywords in any order.

A simple-register-list is a comma-separated list of register names, either Rn or Fn, where n is a valid register number. A register-list is similar to a simple-register- list except that it can contain parenthesized sublists.

Valid registers for the preserved, nopreserve, and notused options include general-purpose registers R0 through R30, and floating- point registers F0 through F30. Valid registers for the result and parameters options include general-purpose registers R0 through R25 and floating-point registers F0 through F30.

For example, the following characteristics specify a simple-register-list containing two elements, registers F3 and F4; and a register-list containing two elements, the register R0 and a sublist containing the registers F0 and F1:

nopreserve(f3, f4)
parameters(r0, (f0, f1))

The following example shows a linkage using such characteristics:

#pragma linkage my_link=(nopreserve(f3,f4), parameters(r0,(f0,f1)), notneeded (ai))

The parenthesized notation in a register-list is used to describe arguments and function return values of type struct, where each member of the struct is passed in a single register. In the following example, sample_linkage specifies two parameters: the first is passed in registers R0, R1, and R2; the second is passed in F1:

struct sample_struct_t {
    int A, B;
    short C;
    } sample_struct;

#pragma linkage sample_linkage = (parameters ((r0, r1, r2), f1))
void sub (struct sample_struct_t p1, double p2) { }

main()
{
    double d;

    sub (sample_struct, d);
}

You can pass arguments to the parameters of a routine in specific registers. To specify this information, use the following form, where each item in the register-list describes one parameter that is passed to the routine:

parameters (register-list)

You can pass structure arguments by value, with the restriction that each member of the structure is passed in a separate parameter location. Doing so, however, may produce code that is slower because of the large number of registers used. The compiler does not diagnose this condition.

DEC C does not support unions as parameters or function return types for a function with a special linkage.

When a function associated with a linkage type is declared or defined, the compiler checks that the size of any declared parameters is compatible with the number of registers specified for the corresponding parameter in the linkage definition.

The compiler needs to know the registers that will be used to return the value for the function. To specify this information use the following form, where the register-list must contain only a single register, or a parenthesized group of registers if the routine returns a struct:

result (register-list)

If a function does not return a value (that is, the function has a return type of void), then do not specify result as part of the linkage.

The compiler needs to know which registers are used by the function and which are not, and of those used, whether or not they are preserved across the function call. To specify this information, use the following forms:

preserved (register-list)
nopreserve (register-list)
notused (register-list)

A preserved register contains the same value after a call to the function as it did before the call.

A nopreserve register does not necessarily contain the same value after a call to the function as it did before the call.

A notused register is not used in any way by the called function.

The notneeded characteristic indicates that certain items are not needed by the routines using this linkage. You can specify one or both of the following keywords:

You must determine whether or not it is valid to specify that the ai or lp registers are not needed.

The #pragma linkage directive has the restriction that structures containing nested substructures are not supported as parameters or function return types with special linkages.

5.4.9 #pragma [no]member_alignment Directive

By default, DEC C for OpenVMS VAX systems does not align structure members on natural boundaries; they are stored on byte boundaries (with the exception of bit-field members).

By default, DEC C for OpenVMS Alpha systems does align structure members on natural boundaries.

The #pragma member_alignment preprocessor directive can be used to force natural-boundary alignment of structure members. The #pragma nomember_alignment preprocessor directive restores byte-alignment of structure members.

This pragma has the following formats:

#pragma member_alignment
#pragma member_alignment save
#pragma member_alignment restore
#pragma nomember_alignment [base_alignment]

When #pragma member_alignment is used, the compiler aligns structure members on the next boundary appropriate to the type of the member, rather than on the next byte. For example, a long variable is aligned on the next longword boundary; a short variable is aligned on the next word boundary.

Consider the following example:

#pragma nomember_alignment

struct x {
           char c;
           int b;
           };

#pragma member_alignment

struct y {
          char c;       /*3 bytes of filler follow c */
          int b;
          };

main ()

{
        printf( "The sizeof y is: %d\n", sizeof (struct y) );
        printf( "The sizeof x is: %d\n", sizeof (struct x) );
}

When this example is executed, it shows the difference between #pragma member_alignment and #pragma nomember_alignment.

Once used, the member_alignment pragma remains in effect until the nomember_alignment pragma is encountered; the reverse is also true.

The optional base_alignment parameter can be used to specify the base-alignment of the structure. Use one of the following keywords for the base_alignment:

The #pragma member_alignment save and #pragma member_alignment restore directives can be used to save the current state of the member_alignment and to restore the previous state, respectively. This feature is necessary for writing header files that require member_alignment or nomember_alignment, or that require inclusion in a member_alignment that is already set.

5.4.10 #pragma message Directive

The #pragma message directive controls the issuance of individual diagnostic messages or groups of messages. Use of this pragma overrides any command-line options that may affect the issuance of messages.

The #pragma message directive has the following formats:

#pragma message option1 (message-list)
#pragma message option2

The parameter option1 must be one of the following keywords:

The message-list can be any one of the following:

Only messages of severity Warning (W) or Information (I) can be disabled. If the message has severity of Error (E) or Fatal (F), it is issued regardless of any attempt to disable it.

The parameter option2 must be one of the following keywords:

The save and restore options are useful primarily within header files.

5.4.11 #pragma module Directive

When you compile source files to create an object file, the compiler assigns the first of the file names specified in the compilation unit to the name of the object file. The compiler adds the .OBJ file extension to the object file. Internally, the OpenVMS system (the debugger and the librarian) recognizes the object module by the file name; the compiler also gives the module a version number of 1. For example, given the object file EXAMPLE.OBJ, the debugger recognizes the EXAMPLE object module.

To change the system-recognized module name and version number, use the #pragma module directive. The #pragma module directive is specific to DEC C for OpenVMS systems and is not portable.

You can find the module name and the module version number listed in the compiler listing file and the linker load map.

The #pragma module directive is equivalent to the VAX C compatible #module directive. The #pragma module directive may be used when compiling in any mode. Use #module only when compiling with the /STANDARD=VAXC qualifier.

The #pragma module directive has the following formats:

#pragma module identifier identifier
#pragma module identifier string

The first parameter must be a valid DEC C identifier. It specifies the module name to be used by the linker. The second parameter specifies the optional identification that appears on listings and in the object file. It must be either a valid DEC C identifier of 31 characters or less, or a character-string constant of 31 characters or less.

Only one #pragma module directive can be processed per compilation unit, and that directive must appear before any C language text. The #pragma module directive can follow other directives, such as #define, but it must precede any function definitions or external data definitions.

The parameters in a #pragma module directive are subject to text replacement and can, therefore, contain references to identifiers defined in previous #define directives. The replacement occurs before the parameters are processed.

5.4.12 #pragma pack Directive

The #pragma pack preprocessor directive specifies the byte boundary for packing members of C structures.

The #pragma pack directive has the following format:

#pragma pack [n]

The n specifies the new alignment restriction in bytes:
align to byte 
align to word 
align to longword 
align to quadword 
16  align to octaword 

A structure member is aligned to either the alignment specified by #pragma pack or the alignment determined by the size of the structure member, whichever is smaller. For example, a short variable in a structure gets byte-aligned if #pragma pack 1 is specified. If #pragma pack 2, 4, or 8 is specified, the short variable in the structure gets aligned to word.

If #pragma pack is not used or if it is specified without the n, packing defaults to 16 on OpenVMS Alpha systems, and to 1 (byte alignment) on OpenVMS VAX systems.

5.4.13 #pragma pointer_size Directive (Alpha only)

The #pragma pointer_size preprocessor directive can be used throughout a program to control whether pointers are 32-bit pointers or 64-bit pointers.

This directive has the same effect as the #pragma required_pointer_ size directive, except that #pragma pointer_size is enabled only when the /POINTER_SIZE command-line qualifier is specified. If /POINTER_SIZE is omitted from the command line, #pragma pointer_ size is ignored. (The #pragma required_pointer_size directive always takes effect, whether or not /POINTER_SIZE is specified.)

The #pragma pointer_size directive has the following format:

#pragma pointer_size keyword

The keyword is one of the following:
{short|32}  32-bit pointer 
{long|64}  64-bit pointer 
system_default  32-bit pointers on OpenVMS systems; 64-bit pointers on Digital UNIX systems 
save  Saves the current pointer size 
restore  Restores the current pointer size to its last saved state 


Notes

5.4.14 #pragma required_pointer_size Directive (Alpha only)

The #pragma required_pointer_size preprocessor directive is intended for use by developers of header files to control the size of pointers within a header file in those cases where the pointers are architecturally required to be a particular size, and must not be altered by the user's use of pointer-size controls.

This directive has the same effect as the #pragma pointer_size directive, except that a #pragma required_pointer_size always takes effect, even if /POINTER_SIZE is omitted from the command line. (The #pragma pointer_size directive is ignored if /POINTER_SIZE is omitted.)

The #pragma required_pointer_size directive has the following format:

#pragma required_pointer_size keyword

The keyword is one of the following:
{short|32}  32-bit pointer 
{long|64}  64-bit pointer 
system_default  32-bit pointers on OpenVMS systems; 64-bit pointers on Digital UNIX systems 
save  Saves the current pointer size 
restore  Restores the current pointer size to its last saved state 


Notes

5.4.15 #pragma [no]standard Directive

Use the nostandard and standard pragmas together to define regions of source code where portability diagnostics are not to be issued.

This pragma has the following format:

#pragma [no]standard

Use #pragma nostandard to suppress diagnostics about non-ANSI extensions, regardless of the /STANDARD qualifier specified.

Use #pragma standard to direct the compiler to reinstate the setting of the /STANDARD qualifier that was in effect before the last #pragma nostandard was encountered. Every #pragma standard directive must be preceded by a corresponding #pragma nostandard directive.

The following example demonstrates the use of these pragmas:

#include <stdio.h>
#pragma nostandard
extern noshare FILE *stdin, *stdout, *stderr;
#pragma standard

In this example, nostandard prevents the NOSHAREEXT diagnostic from being issued against the noshare storage-class modifier, which is specific to DEC C for OpenVMS systems.


Note
This pragma does not change the current mode of the compiler or enable any extensions not already supported in that mode.

5.4.16 #pragma use_linkage Directive (Alpha only)

After defining a special linkage using the #pragma linkage directive, described in Section 5.4.8, use the #pragma use_linkage directive to associate the linkage with a function.

This pragma has the following format:

#pragma use_linkage linkage-name (routine1,
routine2, ...)

The linkage-name is the name of a linkage previously defined by the #pragma linkage directive.

routine1, routine2, ... are the names of functions that you want associated with the specified linkage.

The #pragma use_linkage directive must appear in the source file before any use or definition of the specified routines. Otherwise, the results are unpredictable.

The following example defines a special linkage and associates it with a routine that takes three integer parameters and returns a single integer result in the same location where the first parameter was passed:

#pragma linkage example_linkage (parameters(r16, r17, r19), result(r16))
#pragma use_linkage example_linkage (sub)
int sub (int p1, int p2, short p3);

main()
{
    int result;

    result = sub (1, 2, 3);
}

In this example, the result (r16) option indicates that the function result will be returned in R16 rather than the usual location (R0). The parameters option indicates that the three parameters passed to sub should be passed in R16, R17, and R19.


Previous Page | Next Page | Table of Contents | Index