This file contains all of the patches required to implement a globalref/globaldef/globalvalue facility in GNU-C. These patches are presented as a test version, and after a suitable period they will be included in the regular gas distribution, provided that no insurmountable problems crop up. Unfortunately, there is no way to match the syntax for the global* exactly, without extensive modifications to the compiler. What is possible is to pass information to the assembler by means of the PsectAttributes hack, which gives the assembler information about how the symbol attributes should be modified. An enclosed header file helps to establish the correct symtax, and hide most of the ugliness. I would be most intersted in hearing about any problems that anyone may or may not have with this. One note of caution: Do not use the "static" modifier with the globalref/def. If you do the assembler will (probably) ignore the globalref/def information. It would not make any sense to use "static" with this anyway. Finally, when you use the GLOBALDEF, the data is stored in a psect by the same name as the variable, which has the same name as the global definition (Note that regular global varialbes are also stored in psects with the same name as the variable). If you wish to use a psect with a name other than the name of the variable, you can try the GBLDEF_ALIAS macros. There is no way to have the data stored in a psect with a name different than the global symbol name. If someone can convince me that this is a serious limitation, I might implement a way of doing this. One problem with globalvalue as implemented is that the data type appears to the compiler to be a pointer to the declared data type. For example int GLOBALVALUEREF(ijk); will define "ijk" to be "int *" rather than "int". This is required in order to get the compiler to address the globalvalue correctly, but when you compile your program you may end up with warning messages when you use the globalvalues. If this annoys you too much, you can do: #define ijk ((int) ijk) to suppress the warning messages. Also, global* using enums is not implemented. This can easily be worked around, however, since the effect of a globaldef of an enum can be simulated by a globaldef of an integer variable, and a globalvalue of each of the various enumerated values. **********portion of revised GCC.TEXINFO that I sent to RMS **************** One common source of incompatibility between VAX-C and GNU CC are the @code{globalref}, @code{globaldef} and @code{globalvalue} specifiers that VAX-C provides. Although these specifiers are not recognized by GNU CC, equivalent functionality is available through an assembler hack involving symbol names. The following macros allow you to make use of this feature in a fairly natural way: @example #define GLOBALREF(NAME) \ NAME asm("_$$PsectAttributes_GLOBALSYMBOL$$" #NAME ) #define GLOBALDEF(NAME,VALUE) \ NAME asm("_$$PsectAttributes_GLOBALSYMBOL$$" #NAME ) = VALUE #define GLOBALVALUEREF(NAME) \ const NAME [1] asm("_$$PsectAttributes_GLOBALVALUE$$" #NAME ) #define GLOBALVALUEDEF(NAME,VALUE) \ const NAME [1] asm("_$$PsectAttributes_GLOBALVALUE$$" #NAME ) = @{VALUE@} @end example (The @code{_$$PsectAttributes_GLOBALSYMBOL} prefix at the start of the name is removed by the assembler, after it has modified the attributes of the symbol). These macros are provided in the VMS binaries distribution in a header file @file{GNU_HACKS.H}. An example of the usage is: @example int GLOBALREF(ijk); int GLOBALDEF(jkl,0); int GLOBALVALUEREF(ss$_normal); int GLOBALVALUEDEF(xyzzy,123); #ifdef __GNUC__ #define ss$_normal ((int) ss$_normal) #define xyzzy ((int) xyzzy) #endif @end example The only way for the assembler to tell the difference between the @code{GLOBALREF} and @code{GLOBALDEF} is that a @code{GLOBALDEF} is initialized and a @code{GLOBALREF} is not. These macros will break if you try to use them to assign global attributes to an array. You can use @code{typedef} to work around this, or you can expand the macro by hand in your code. It is possible to initialize only one element of an array with an initializer like: @code{@{0,@}} (Array and structure initializers will also break the macros - you can define the initializer to be a macro of its own, or you can expand the @code{GLOBALDEF} macro by hand). A shortcoming of this implementation is that a variable that has been declared as being globalvalue appears to the compiler to be an array of the type that you declare. For example, the declaration: @example int GLOBALVALUEREF(ijk); @end example will cause the variable @samp{ijk} to appear to the compiler to be @samp{int ijk[]} rather than @samp{int}. The fact that globalvalues are actually constants which are resolved by the linker (and thus do not occupy a memory location) is responsible for fact that the ``value'' of the globalvalued variable turns out to be what would normally be considered to be the address of the variable. The declaration of the variable as an array is a convenient hack to force the compiler to treat a reference to the variable as a ``pointer'', and you should never attempt to access an element of the array. Due to this difference in data type, you may get compiler warning messages when you use globalvalue variables. These warnings can be avoided through type casts, which can be provided with macro definitions such as those in the example above. It should be noted that a globaldef or globalref of an enumerated data type is not fully implemented. Equivalent functionality can be obtained with a globaldef or globalref declaration of an integer variable by the same name as the enumerated variable, and a globalvalue declaration of each of the various enumerated tags. /**************************GNU_HACKS.H*************************/ /* * This header file contains hacks that will simulate the effects of certain * parts of VAX-C that are not implemented in GNU-C. This header file is * written in such a way that there are macros for both GNU-C and VAX-C. * Thus if you use the macros defined here in your program, you should be * able to compile your program with either compiler with no source * modifications. * * Note: The globalvalue implementation is a little bit different than it is * on VAX-C. You can declare a data variable to be a globalvalue, but the * data type that the compiler will see will be a pointer to that data type, * not that data type. If you find the warning messages intollerable, you can * define a macro to type cast the globalvalue variable back to the expected * type. Since it is impossible to define a macro while expanding another * macro, this was not done here. * * Also, globaldef/ref/value of enum is not implemented. To simulate this in * GNU-C, you can globaldef an integer variable, and then define all of the * values that this variable can take to be globalvalue. * * The arguments to these macros are "fragile" (in the LaTeX sense). This means * that you cannot use type casts or expressions in the name field. * */ #ifdef __GNUC__ /* Store the data in a psect by the same name as the variable name */ #define GLOBALREF(NAME) \ NAME asm("_$$PsectAttributes_GLOBALSYMBOL$$" #NAME ) #define GLOBALDEF(NAME,VALUE) \ NAME asm("_$$PsectAttributes_GLOBALSYMBOL$$" #NAME ) = VALUE #define GLOBALVALUEREF(NAME) \ const NAME [1] asm("_$$PsectAttributes_GLOBALVALUE$$" #NAME ) #define GLOBALVALUEDEF(NAME,VALUE) \ const NAME [1] asm("_$$PsectAttributes_GLOBALVALUE$$" #NAME ) = {VALUE} /* Store the data in a psect by a different name than the variable name */ #define GBLDEF_ALIAS(NAME,ALIAS,VALUE) \ NAME asm("_$$PsectAttributes_GLOBALSYMBOL$$" #ALIAS ) = VALUE #define GBLREF_ALIAS(NAME,ALIAS) \ NAME asm("_$$PsectAttributes_GLOBALSYMBOL$$" #ALIAS ) #define NOSHARE(NAME) NAME asm("_$$PsectAttributes_NOSHR$$" #NAME ) #define readonly const #else /* These are the equivalent definitions that will work in VAX-C */ #define GLOBALREF(NAME) globalref NAME #define GLOBALDEF(NAME,VALUE) globaldef NAME = VALUE #define GLOBALVALUEDEF(NAME,VALUE) globalvalue NAME = VALUE #define GLOBALVALUEREF(NAME) globalvalue NAME #define NOSHARE(NAME) noshare NAME #define GBLDEF_ALIAS(NAME,ALIAS,VALUE) globaldef{#ALIAS} NAME = VALUE #endif /**************************EXAMPLE1.C*************************/ #include "gnu_hacks.h" int GLOBALREF(ijk); int GLOBALVALUEREF(ss$_normal); main(){ printf("%d",ijk); return ss$_normal; } /**************************EXAMPLE2.C*************************/ #include "gnu_hacks.h" int GLOBALDEF(ijk)=35; ************************** Diffs follow... *** vms.c;-0 --- vms.c ************** *** 291,296 register struct fix * fixP; register struct VMS_Symbol * vsp; int Local_Initialized_Data_Size = 0; int Psect_Number = 0; /* Psect Index Number */ int Text_Psect = -1; /* Text Psect Index */ int Data_Psect = -2; /* Data Psect Index JF: Was -1 */ --- 291,297 ----- register struct fix * fixP; register struct VMS_Symbol * vsp; int Local_Initialized_Data_Size = 0; + int Globalref; int Psect_Number = 0; /* Psect Index Number */ int Text_Psect = -1; /* Text Psect Index */ int Data_Psect = -2; /* Data Psect Index JF: Was -1 */ ************** *** 312,318 /******* Global Symbol Dictionary *******/ /* ! * Define the Text Psect */ if (text_siz > 0) { Text_Psect = Psect_Number++; --- 313,322 ----- /******* Global Symbol Dictionary *******/ /* ! * Emit globalvalues now. We must do this before the text psect ! * is defined, or we will get linker warnings about multiply defined ! * symbols. All of the globalvalues "reference" psect 0, although ! * it really does not have much to do with it. */ VMS_Emit_Globalvalues(text_siz,data_siz); /* ************** *** 314,323 /* * Define the Text Psect */ ! if (text_siz > 0) { ! Text_Psect = Psect_Number++; ! VMS_Psect_Spec("$code",text_siz,"TEXT"); ! } /* * Define the BSS Psect */ --- 318,324 ----- * symbols. All of the globalvalues "reference" psect 0, although * it really does not have much to do with it. */ ! VMS_Emit_Globalvalues(text_siz,data_siz); /* * Define the Text Psect */ ************** *** 319,324 VMS_Psect_Spec("$code",text_siz,"TEXT"); } /* * Define the BSS Psect */ if (local_bss_counter > 0) { --- 320,330 ----- */ VMS_Emit_Globalvalues(text_siz,data_siz); /* + * Define the Text Psect + */ + Text_Psect = Psect_Number++; + VMS_Psect_Spec("$code",text_siz,"TEXT",0); + /* * Define the BSS Psect */ if (local_bss_counter > 0) { ************** *** 323,329 */ if (local_bss_counter > 0) { Bss_Psect = Psect_Number++; ! VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA"); } /* * Now scan the symbols and emit the appropriate GSD records --- 329,336 ----- */ if (local_bss_counter > 0) { Bss_Psect = Psect_Number++; ! VMS_Psect_Spec("$uninitialized_data",local_bss_counter,"DATA", ! 0); } /* * Now scan the symbols and emit the appropriate GSD records ************** *** 353,359 * Make the psect for this data */ if(sp->sy_nlist.n_other) ! VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, "CONST"); else --- 360,367 ----- * Make the psect for this data */ if(sp->sy_nlist.n_other) ! Globalref = VMS_Psect_Spec( ! sp->sy_nlist.n_un.n_name, vsp->Size, "CONST", vsp); ************** *** 355,361 if(sp->sy_nlist.n_other) VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, ! "CONST"); else VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, --- 363,370 ----- Globalref = VMS_Psect_Spec( sp->sy_nlist.n_un.n_name, vsp->Size, ! "CONST", ! vsp); else Globalref = VMS_Psect_Spec( sp->sy_nlist.n_un.n_name, ************** *** 357,363 vsp->Size, "CONST"); else ! VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, "COMMON"); #ifdef NOT_VAX_11_C_COMPATIBLE --- 366,373 ----- "CONST", vsp); else ! Globalref = VMS_Psect_Spec( ! sp->sy_nlist.n_un.n_name, vsp->Size, "COMMON", vsp); ************** *** 359,365 else VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, ! "COMMON"); #ifdef NOT_VAX_11_C_COMPATIBLE /* * Place a global symbol at the --- 369,377 ----- Globalref = VMS_Psect_Spec( sp->sy_nlist.n_un.n_name, vsp->Size, ! "COMMON", ! vsp); ! if(Globalref) Psect_Number--; #ifdef NOT_VAX_11_C_COMPATIBLE /* * Place a global symbol at the ************** *** 411,417 * Make its psect */ if(sp->sy_nlist.n_other) ! VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, "CONST"); else --- 423,430 ----- * Make its psect */ if(sp->sy_nlist.n_other) ! Globalref = VMS_Psect_Spec( ! sp->sy_nlist.n_un.n_name, vsp->Size, "CONST", vsp); ************** *** 413,419 if(sp->sy_nlist.n_other) VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, ! "CONST"); else VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, --- 426,433 ----- Globalref = VMS_Psect_Spec( sp->sy_nlist.n_un.n_name, vsp->Size, ! "CONST", ! vsp); else Globalref = VMS_Psect_Spec( sp->sy_nlist.n_un.n_name, ************** *** 415,421 vsp->Size, "CONST"); else ! VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, "COMMON"); #ifdef NOT_VAX_11_C_COMPATIBLE --- 429,436 ----- "CONST", vsp); else ! Globalref = VMS_Psect_Spec( ! sp->sy_nlist.n_un.n_name, vsp->Size, "COMMON", vsp); ************** *** 417,423 else VMS_Psect_Spec(sp->sy_nlist.n_un.n_name, vsp->Size, ! "COMMON"); #ifdef NOT_VAX_11_C_COMPATIBLE /* * Place a global symbol at the --- 432,441 ----- Globalref = VMS_Psect_Spec( sp->sy_nlist.n_un.n_name, vsp->Size, ! "COMMON", ! vsp); ! if(Globalref) Psect_Number--; ! #ifdef NOT_VAX_11_C_COMPATIBLE /* * Place a global symbol at the ************** *** 533,539 Data_Psect = Psect_Number++; VMS_Psect_Spec("$data", Local_Initialized_Data_Size, ! "DATA"); /* * Scan the VMS symbols and fill in the data psect */ --- 551,557 ----- Data_Psect = Psect_Number++; VMS_Psect_Spec("$data", Local_Initialized_Data_Size, ! "DATA",0); /* * Scan the VMS symbols and fill in the data psect */ ************** *** 1596,1601 /* * Scan a symbol name for a psect attribute specification */ VMS_Modify_Psect_Attributes(Name, Attribute_Pointer) char *Name; int *Attribute_Pointer; --- 1614,1623 ----- /* * Scan a symbol name for a psect attribute specification */ + #define GLOBALSYMBOL_BIT 0x10000 + #define GLOBALVALUE_BIT 0x20000 + + VMS_Modify_Psect_Attributes(Name, Attribute_Pointer) char *Name; int *Attribute_Pointer; ************** *** 1617,1622 {"RD", GPS$M_RD}, {"WRT", GPS$M_WRT}, {"VEC", GPS$M_VEC}, {0, 0}}; /* --- 1639,1646 ----- {"RD", GPS$M_RD}, {"WRT", GPS$M_WRT}, {"VEC", GPS$M_VEC}, + {"GLOBALSYMBOL",GLOBALSYMBOL_BIT}, + {"GLOBALVALUE", GLOBALVALUE_BIT}, {0, 0}}; /* ************** *** 1693,1699 /* * Define a psect */ ! VMS_Psect_Spec(Name, Size, Type) char *Name; int Size; char *Type; --- 1717,1724 ----- /* * Define a psect */ ! int ! VMS_Psect_Spec(Name, Size, Type, vsp) char *Name; int Size; char *Type; ************** *** 1697,1702 char *Name; int Size; char *Type; { char Local[32]; int Psect_Attributes; --- 1722,1728 ----- char *Name; int Size; char *Type; + struct VMS_Symbol * vsp; { char Local[32]; int Psect_Attributes; ************** *** 1702,1723 int Psect_Attributes; /* - * We are writing a GSD record - */ - Set_VMS_Object_File_Record(OBJ$C_GSD); - /* - * If the buffer is empty we must insert the GSD record type - */ - if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD); - /* - * We are writing a PSECT definition subrecord - */ - PUT_CHAR(GSD$C_PSC); - /* - * Psects are always LONGWORD aligned - */ - PUT_CHAR(2); - /* * Generate the appropriate PSECT flags given the PSECT type */ if (strcmp(Type,"COMMON") == 0) { --- 1728,1733 ----- int Psect_Attributes; /* * Generate the appropriate PSECT flags given the PSECT type */ if (strcmp(Type,"COMMON") == 0) { ************** *** 1757,1763 if (HAS_PSECT_ATTRIBUTES(Name)) VMS_Modify_Psect_Attributes(Name,&Psect_Attributes); /* ! * Specify the psect attributes */ PUT_SHORT(Psect_Attributes); /* --- 1767,1773 ----- if (HAS_PSECT_ATTRIBUTES(Name)) VMS_Modify_Psect_Attributes(Name,&Psect_Attributes); /* ! * Check for globalref/def/val. */ if ( (Psect_Attributes & GLOBALVALUE_BIT) != 0) { /* ************** *** 1759,1764 /* * Specify the psect attributes */ PUT_SHORT(Psect_Attributes); /* * Specify the allocation --- 1769,1829 ----- /* * Check for globalref/def/val. */ + if ( (Psect_Attributes & GLOBALVALUE_BIT) != 0) { + /* + * globalvalue symbols were generated before. This code + * prevents unsightly psect buildup, and makes sure that + * fixup references are emitted correctly. + */ + vsp->Psect_Index = -1; /* to catch errors */ + vsp->Symbol->sy_type = N_UNDF; /* make refs work */ + return 1; /* decrement psect counter */ + }; + + if ( (Psect_Attributes & GLOBALSYMBOL_BIT) != 0) { + switch(vsp->Symbol->sy_type) { + case N_UNDF | N_EXT: + VMS_Global_Symbol_Spec(Name,vsp->Psect_Index, + vsp->Psect_Offset,0); + vsp->Psect_Index = -1; + vsp->Symbol->sy_type = N_UNDF; + return 1; /* return and indicate no psect */ + case N_DATA | N_EXT: + VMS_Global_Symbol_Spec(Name,vsp->Psect_Index, + vsp->Psect_Offset,1); + /* In this case we still generate the psect */ + break; + default: + { + char Error_Line[256]; + sprintf(Error_Line,"Globalsymbol attribute for" + " symbol %s was unexpected.\n",Name); + error(Error_Line); + break; + }; + }; /* switch */ + }; + + Psect_Attributes &= 0xffff; /* clear out the globalref/def stuff */ + /* + * We are writing a GSD record + */ + Set_VMS_Object_File_Record(OBJ$C_GSD); + /* + * If the buffer is empty we must insert the GSD record type + */ + if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_GSD); + /* + * We are writing a PSECT definition subrecord + */ + PUT_CHAR(GSD$C_PSC); + /* + * Psects are always LONGWORD aligned + */ + PUT_CHAR(2); + /* + * Specify the psect attributes + */ PUT_SHORT(Psect_Attributes); /* * Specify the allocation ************** *** 1775,1780 if (Object_Record_Offset > (sizeof(Object_Record_Buffer)*3/4)) Flush_VMS_Object_Record_Buffer(); } --- 1840,1846 ----- if (Object_Record_Offset > (sizeof(Object_Record_Buffer)*3/4)) Flush_VMS_Object_Record_Buffer(); + return 0; } ************** *** 1779,1785 /* ! * Define a global symbol */ VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined) char *Name; --- 1845,1852 ----- /* ! * Check symbol names for the Psect hack with a globalvalue, and then ! * generate globalvalues for those that have it. */ VMS_Emit_Globalvalues(text_siz, data_siz) unsigned text_siz; ************** *** 1781,1786 /* * Define a global symbol */ VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined) char *Name; int Psect_Number; --- 1848,1916 ----- * Check symbol names for the Psect hack with a globalvalue, and then * generate globalvalues for those that have it. */ + VMS_Emit_Globalvalues(text_siz, data_siz) + unsigned text_siz; + unsigned data_siz; + { + register symbolS *sp; + char *stripped_name, *Name; + int Size; + int Psect_Attributes; + int globalvalue; + + /* + * Scan the symbol table for globalvalues, and emit def/ref when + * required. These will be caught again later and converted to + * N_UNDF + */ + for (sp = symbol_rootP; sp; sp = sp->sy_next) { + /* + * See if this is something we want to look at. + */ + if(( sp->sy_type != (N_DATA | N_EXT)) && + ( sp->sy_type != (N_UNDF | N_EXT))) continue; + /* + * See if this has globalvalue specification. + */ + Name = sp->sy_nlist.n_un.n_name; + + if (!HAS_PSECT_ATTRIBUTES(Name)) continue; + + stripped_name = (char*) malloc(strlen(Name)+1); + strcpy(stripped_name,Name); + Psect_Attributes = 0; + VMS_Modify_Psect_Attributes(stripped_name,&Psect_Attributes); + + if ( (Psect_Attributes & GLOBALVALUE_BIT) != 0) { + switch(sp->sy_type) { + case N_UNDF | N_EXT: + VMS_Global_Symbol_Spec(stripped_name,0,0,2); + break; + case N_DATA | N_EXT: + Size = VMS_Initialized_Data_Size(sp,text_siz + data_siz); + if(Size > 4) error("Invalid data type for globalvalue"); + globalvalue = 0; + bcopy(sp->sy_frag->fr_literal,&globalvalue,Size); + /* Three times for good luck. The linker seems to get confused + if there are fewer than three */ + VMS_Global_Symbol_Spec(stripped_name,0,0,2); + VMS_Global_Symbol_Spec(stripped_name,0,globalvalue,3); + VMS_Global_Symbol_Spec(stripped_name,0,globalvalue,3); + break; + default: + printf(" Invalid globalvalue of %s\n",stripped_name); + break; + }; /* switch */ + }; /* if */ + free(stripped_name); /* clean up */ + }; /* for */ + + } + + + /* + * Define a global symbol + */ VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined) char *Name; int Psect_Number; ************** *** 1811,1817 /* * Switch on Definition/Reference */ ! if (Defined) { /* * Definition: * Flags = "RELOCATABLE" and "DEFINED" --- 1941,1947 ----- /* * Switch on Definition/Reference */ ! if ((Defined & 1) != 0) { /* * Definition: * Flags = "RELOCATABLE" and "DEFINED" for regular symbol ************** *** 1814,1820 if (Defined) { /* * Definition: ! * Flags = "RELOCATABLE" and "DEFINED" */ PUT_SHORT(GSY$M_DEF|GSY$M_REL); /* --- 1944,1951 ----- if ((Defined & 1) != 0) { /* * Definition: ! * Flags = "RELOCATABLE" and "DEFINED" for regular symbol ! * = "DEFINED" for globalvalue (Defined & 2 == 1) */ if((Defined & 2) == 0) { PUT_SHORT(GSY$M_DEF|GSY$M_REL); ************** *** 1816,1822 * Definition: * Flags = "RELOCATABLE" and "DEFINED" */ ! PUT_SHORT(GSY$M_DEF|GSY$M_REL); /* * Psect Number */ --- 1947,1956 ----- * Flags = "RELOCATABLE" and "DEFINED" for regular symbol * = "DEFINED" for globalvalue (Defined & 2 == 1) */ ! if((Defined & 2) == 0) { ! PUT_SHORT(GSY$M_DEF|GSY$M_REL); ! } else { ! PUT_SHORT(GSY$M_DEF);}; /* * Psect Number */ ************** *** 1832,1838 } else { /* * Reference: ! * Flags = "RELOCATABLE" */ PUT_SHORT(GSY$M_REL); } --- 1966,1973 ----- } else { /* * Reference: ! * Flags = "RELOCATABLE" for regular symbol, ! * = "" for globalvalue (Defined & 2 == 1) */ if((Defined & 2) == 0) { PUT_SHORT(GSY$M_REL); ************** *** 1834,1840 * Reference: * Flags = "RELOCATABLE" */ ! PUT_SHORT(GSY$M_REL); } /* * Finally, the global symbol name --- 1969,1978 ----- * Flags = "RELOCATABLE" for regular symbol, * = "" for globalvalue (Defined & 2 == 1) */ ! if((Defined & 2) == 0) { ! PUT_SHORT(GSY$M_REL); ! } else { ! PUT_SHORT(0);}; } /* * Finally, the global symbol name