📄 vms.c
字号:
Entry_Point_Symbol->sy_nlist.n_value); /* * All done, close the object file */ Close_VMS_Object_File();} /****** VMS OBJECT FILE HACKING ROUTINES *******//* * Global data (Object records limited to 512 bytes by VAX-11 "C" runtime) */static int VMS_Object_File_FD; /* File Descriptor for object file */static char Object_Record_Buffer[512]; /* Buffer for object file records */static int Object_Record_Offset; /* Offset to end of data */static int Current_Object_Record_Type; /* Type of record in above *//* * Macros for placing data into the object record buffer */#define PUT_LONG(val) *((long *)(Object_Record_Buffer + \ Object_Record_Offset)) = val; \ Object_Record_Offset += sizeof(long)#define PUT_SHORT(val) *((short *)(Object_Record_Buffer + \ Object_Record_Offset)) = val; \ Object_Record_Offset += sizeof(short)#define PUT_CHAR(val) Object_Record_Buffer[Object_Record_Offset++] = val#define PUT_COUNTED_STRING(cp) {\ register char *p = cp; \ PUT_CHAR(strlen(p)); \ while(*p) PUT_CHAR(*p++);}/* * Macro for determining if a Name has psect attributes attached * to it. */#define PSECT_ATTRIBUTES_STRING "$$PsectAttributes_"#define PSECT_ATTRIBUTES_STRING_LENGTH 18#define HAS_PSECT_ATTRIBUTES(Name) \ (strncmp((Name[0] == '_' ? Name + 1 : Name), \ PSECT_ATTRIBUTES_STRING, \ PSECT_ATTRIBUTES_STRING_LENGTH) == 0)/* * Create the VMS object file */Create_VMS_Object_File(){#ifdef eunice VMS_Object_File_FD = creat(out_file_name, 0777, "var");#else eunice VMS_Object_File_FD = creat(out_file_name, 0, "rfm=var");#endif eunice /* * Deal with errors */ if (VMS_Object_File_FD < 0) { char Error_Line[256]; sprintf(Error_Line,"Couldn't create VMS object file \"%s\"", out_file_name); error(Error_Line); } /* * Initialize object file hacking variables */ Object_Record_Offset = 0; Current_Object_Record_Type = -1;}/* * Declare a particular type of object file record */Set_VMS_Object_File_Record(Type)int Type;{ /* * If the type matches, we are done */ if (Type == Current_Object_Record_Type) return; /* * Otherwise: flush the buffer */ Flush_VMS_Object_Record_Buffer(); /* * Set the new type */ Current_Object_Record_Type = Type;}/* * Flush the object record buffer to the object file */Flush_VMS_Object_Record_Buffer(){ int i; /* * If the buffer is empty, we are done */ if (Object_Record_Offset == 0) return; /* * Write the data to the file */ i= write(VMS_Object_File_FD, Object_Record_Buffer, Object_Record_Offset); if (i != Object_Record_Offset) error("I/O error writing VMS object file"); /* * The buffer is now empty */ Object_Record_Offset = 0;}/* * Close the VMS Object file */Close_VMS_Object_File(){ close(VMS_Object_File_FD);}/* * Write the MHD (Module Header) records */Write_VMS_MHD_Records(){ register char *cp,*cp1; register int i; struct {int Size; char *Ptr;} Descriptor; char Module_Name[256]; char Now[17]; /* * We are writing a module header record */ Set_VMS_Object_File_Record(OBJ$C_HDR); /* * *************************** * *MAIN MODULE HEADER RECORD* * *************************** * * Store record type and header type */ PUT_CHAR(OBJ$C_HDR); PUT_CHAR(MHD$C_MHD); /* * Structure level is 0 */ PUT_CHAR(OBJ$C_STRLVL); /* * Maximum record size is size of the object record buffer */ PUT_SHORT(sizeof(Object_Record_Buffer)); /* * Get module name (the FILENAME part of the object file) */ cp = out_file_name; cp1 = Module_Name; while(*cp) { if ((*cp == ']') || (*cp == '>') || (*cp == ':') || (*cp == '/')) { cp1 = Module_Name; cp++; continue; } *cp1++ = islower(*cp) ? toupper(*cp++) : *cp++; } *cp1 = 0; /* * Limit it to 31 characters and store in the object record */ while(--cp1 >= Module_Name) if (*cp1 == '.') *cp1 = 0; if (strlen(Module_Name) > 31) { if(flagseen['+']) printf("%s: Module name truncated: %s\n", myname, Module_Name); Module_Name[31] = 0; } PUT_COUNTED_STRING(Module_Name); /* * Module Version is "V1.0" */ PUT_COUNTED_STRING("V1.0"); /* * Creation time is "now" (17 chars of time string) */ Descriptor.Size = 17; Descriptor.Ptr = Now; sys$asctim(0,&Descriptor,0,0); for(i = 0; i < 17; i++) PUT_CHAR(Now[i]); /* * Patch time is "never" (17 zeros) */ for(i = 0; i < 17; i++) PUT_CHAR(0); /* * Flush the record */ Flush_VMS_Object_Record_Buffer(); /* * ************************* * *LANGUAGE PROCESSOR NAME* * ************************* * * Store record type and header type */ PUT_CHAR(OBJ$C_HDR); PUT_CHAR(MHD$C_LNM); /* * Store language processor name and version * (not a counted string!) */ cp = compiler_version_string; if (cp == 0) { cp ="GNU AS V"; while(*cp) PUT_CHAR(*cp++); cp = strchr(&version_string,'.'); while(*cp != ' ') cp--; cp++; }; while(*cp >= 32) PUT_CHAR(*cp++); /* * Flush the record */ Flush_VMS_Object_Record_Buffer();}/* * Write the EOM (End Of Module) record */Write_VMS_EOM_Record(Psect, Offset)int Psect;int Offset;{ /* * We are writing an end-of-module record */ Set_VMS_Object_File_Record(OBJ$C_EOM); /* * Store record Type */ PUT_CHAR(OBJ$C_EOM); /* * Store the error severity (0) */ PUT_CHAR(0); /* * Store the entry point, if it exists */ if (Psect >= 0) { /* * Store the entry point Psect */ PUT_CHAR(Psect); /* * Store the entry point Psect offset */ PUT_LONG(Offset); } /* * Flush the record */ Flush_VMS_Object_Record_Buffer();}/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/static inthash_string (ptr) unsigned char *ptr;{ register unsigned char *p = ptr; register unsigned char *end = p + strlen(ptr); register unsigned char c; register int hash = 0; while (p != end) { c = *p++; hash = ((hash<<3) + (hash<<15) + (hash>>28) + c); } return hash;}/* * Generate a Case-Hacked VMS symbol name (limited to 31 chars) */VMS_Case_Hack_Symbol(In,Out)register char *In;register char *Out;{ long int init = 0; long int result; char *pnt; char *new_name; char *old_name; register int i; int destructor = 0; /*hack to allow for case sens in a destructor*/ int truncate = 0; int Case_Hack_Bits = 0; int Saw_Dollar = 0; static char Hex_Table[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; /* * Kill any leading "_" */ if (*In == '_') In++; new_name=Out; /* save this for later*/ if((In[0]=='_')&&(In[1]=='$')&&(In[2]=='_')) destructor=1; /* We may need to truncate the symbol, save the hash for later*/ if(strlen(In)>23) result = hash_string(In); /* * Is there a Psect Attribute to skip?? */ if (HAS_PSECT_ATTRIBUTES(In)) { /* * Yes: Skip it */ In += PSECT_ATTRIBUTES_STRING_LENGTH; while(*In) { if ((In[0] == '$') && (In[1] == '$')) { In += 2; break; } In++; } } old_name=In;/* if(strlen(In) > 31 && flagseen['+']) printf("%s: Symbol name truncated: %s\n",myname,In);*/ /* * Do the case conversion */ i = 23; /* Maximum of 23 chars */ while(*In && (--i >= 0)) { Case_Hack_Bits <<= 1; if (*In == '$') Saw_Dollar = 1; if ((destructor==1)&&(i==21)) Saw_Dollar = 0; if (isupper(*In)) { *Out++ = *In++; Case_Hack_Bits |= 1; } else { *Out++ = islower(*In) ? toupper(*In++) : *In++; } } /* * If we saw a dollar sign, we don't do case hacking */ if(flagseen['h'] || Saw_Dollar) Case_Hack_Bits = 0; /* * If we have more than 23 characters and everything is lowercase * we can insert the full 31 characters */ if (*In) { /* * We have more than 23 characters * If we must add the case hack, then we have truncated the str */ pnt=Out; truncate=1; if (Case_Hack_Bits == 0) { /* * And so far they are all lower case: * Check up to 8 more characters * and ensure that they are lowercase */ if(flagseen['h']) i=8; else for(i = 0; (In[i] != 0) && (i < 8); i++) if (isupper(In[i]) && !Saw_Dollar) break; if(In[i]==0) truncate=0; if ((i >= 8) || (In[i] == 0)) { /* * They are: Copy up to 31 characters * to the output string */ i = 8; while((--i >= 0) && (*In)) *Out++ = islower(*In) ? toupper(*In++) : *In++; } } } /* * If there were any uppercase characters in the name we * take on the case hacking string */ /* Old behavior for regular GNU-C compiler */ if (!flagseen['+']) truncate=0; if ((Case_Hack_Bits != 0)||(truncate==1)) { if(truncate==0) { *Out++ = '_'; for(i = 0; i < 6; i++) { *Out++ = Hex_Table[Case_Hack_Bits & 0xf]; Case_Hack_Bits >>= 4; } *Out++ = 'X'; } else { Out=pnt; /*Cut back to 23 characters maximum */ *Out++ = '_'; for( i=0; i < 7; i++) { init = result & 0x01f; if (init < 10) *Out++='0'+init; else *Out++ = 'A'+init-10; result = result >> 5; } } } /*Case Hack */ /* * Done */ *Out = 0; if( truncate==1 && flagseen['+'] && flagseen['H']) printf("%s: Symbol %s replaced by %s\n",myname,old_name,new_name);}/* * Scan a symbol name for a psect attribute specification */VMS_Modify_Psect_Attributes(Name, Attribute_Pointer)char *Name;int *Attribute_Pointer;{ register int i; register char *cp; int Negate; static struct { char *Name; int Value; } Attributes[] = { {"PIC", GPS$M_PIC}, {"LIB", GPS$M_LIB}, {"OVR", GPS$M_OVR}, {"REL", GPS$M_REL}, {"GBL", GPS$M_GBL}, {"SHR", GPS$M_SHR}, {"EXE", GPS$M_EXE}, {"RD", GPS$M_RD}, {"WRT", GPS$M_WRT}, {"VEC", GPS$M_VEC}, {0, 0}}; /* * Kill leading "_" */ if (*Name == '_') Name++; /* * Check for a PSECT attribute list */ if (!HAS_PSECT_ATTRIBUTES(Name)) return; /* If not, return */ /* * Skip the attribute list indicator */ Name += PSECT_ATTRIBUTES_STRING_LENGTH; /* * Process the attributes ("_" separated, "$" terminated) */ while(*Name != '$') { /* * Assume not negating */ Negate = 0; /* * Check for "NO" */ if ((Name[0] == 'N') && (Name[1] == 'O')) { /* * We are negating (and skip the NO) */ Negate = 1; Name += 2; } /* * Find the token delimiter */ cp = Name; while(*cp && (*cp != '_') && (*cp != '$')) cp++; /* * Look for the token in the attribute list */ for(i = 0; Attributes[i].Name; i++) { /* * If the strings match, set/clear the attr. */ if (strncmp(Name, Attributes[i].Name, cp - Name) == 0) { /* * Set or clear */ if (Negate) *Attribute_Pointer &= ~Attributes[i].Value; else *Attribute_Pointer |= Attributes[i].Value; /* * Done */ break; } } /* * Now skip the attribute */ Name = cp; if (*Name == '_') Name++; } /* * Done */ return;}/* * Define a psect */VMS_Psect_Spec(Name, Size, Type)char *Name;int Size;char *Type;{ char Local[32]; 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -