1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572 |
- /* vms.c -- Write out a VAX/VMS object file
- Copyright (C) 1987, 1988 David L. Kashtan and Free Software Foundation, Inc.
- This file is part of GAS, the GNU Assembler.
- GAS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
- GAS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
- #include <ctype.h>
- #include <stdio.h>
- #include "as.h"
- #include "md.h"
- #include "subsegs.h"
- #include "obstack.h"
- #include "struc-symbol.h"
- #include "write.h"
- #include "symbols.h"
- #ifdef VMS /* THIS MODULE IS FOR VMS ONLY */
- #include <stab.h>
- #include "objrecdef.h" /* Define VMS Object record lang. */
- #include <vms/fabdef.h> /* Define File Access Block */
- #include <vms/namdef.h> /* Define NAM Block */
- #include <vms/xabdef.h> /* Define XAB */
- #include <vms/xabdatdef.h> /* Define Date XAB */
- #include <vms/xabfhcdef.h> /* Define File Header XAB */
- /*
- * Version string of the compiler that produced the code we are
- * assembling.
- */
- char *compiler_version_string;
- static symbolS *Entry_Point_Symbol = 0; /* Pointer to "_main" */
- /*
- * We augment the "gas" symbol structure with this
- */
- struct VMS_Symbol {
- struct VMS_Symbol *Next;
- struct symbol *Symbol;
- int Size;
- int Psect_Index;
- int Psect_Offset;
- };
- static struct VMS_Symbol *VMS_Symbols = 0;
- /*
- * If the procedure "main()" exists we have to add the instruction
- * "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
- */
- VMS_Check_For_Main()
- {
- register symbolS *symbolP;
- #ifdef HACK_DEC_C_STARTUP
- register struct frchain *frchainP;
- register fragS *fragP;
- register fragS **prev_fragPP;
- register struct fix *fixP;
- register fragS *New_Frag;
- int i;
- #endif HACK_DEC_C_STARTUP
- symbolP = (struct symbol *)symbol_find("_main");
- if (symbolP && (symbolP->sy_nlist.n_type == (N_TEXT | N_EXT))) {
- #ifndef HACK_DEC_C_STARTUP
- /*
- * Remember the entry point symbol
- */
- Entry_Point_Symbol = symbolP;
- #else HACK_DEC_C_STARTUP
- /*
- * Scan all the fragment chains for the one with "_main"
- * (Actually we know the fragment from the symbol, but we need
- * the previous fragment so we can change its pointer)
- */
- frchainP = frchain_root;
- while(frchainP) {
- /*
- * Scan all the fragments in this chain, remembering
- * the "previous fragment"
- */
- prev_fragPP = &frchainP->frch_root;
- fragP = frchainP->frch_root;
- while(fragP && (fragP != frchainP->frch_last)) {
- /*
- * Is this the fragment?
- */
- if (fragP == symbolP->sy_frag) {
- /*
- * Yes: Modify the fragment by replacing
- * it with a new fragment.
- */
- New_Frag = (fragS *)
- xmalloc(sizeof(*New_Frag) +
- fragP->fr_fix +
- fragP->fr_var +
- 5);
- /*
- * The fragments are the same except
- * that the "fixed" area is larger
- */
- *New_Frag = *fragP;
- New_Frag->fr_fix += 6;
- /*
- * Copy the literal data opening a hole
- * 2 bytes after "_main" (i.e. just after
- * the entry mask). Into which we place
- * the JSB instruction.
- */
- New_Frag->fr_literal[0] = fragP->fr_literal[0];
- New_Frag->fr_literal[1] = fragP->fr_literal[1];
- New_Frag->fr_literal[2] = 0x16; /* Jsb */
- New_Frag->fr_literal[3] = 0xef;
- New_Frag->fr_literal[4] = 0;
- New_Frag->fr_literal[5] = 0;
- New_Frag->fr_literal[6] = 0;
- New_Frag->fr_literal[7] = 0;
- for(i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
- New_Frag->fr_literal[i+6] =
- fragP->fr_literal[i];
- /*
- * Now replace the old fragment with the
- * newly generated one.
- */
- *prev_fragPP = New_Frag;
- /*
- * Remember the entry point symbol
- */
- Entry_Point_Symbol = symbolP;
- /*
- * Scan the text area fixup structures
- * as offsets in the fragment may have
- * changed
- */
- for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
- /*
- * Look for references to this
- * fragment.
- */
- if (fixP->fx_frag == fragP) {
- /*
- * Change the fragment
- * pointer
- */
- fixP->fx_frag = New_Frag;
- /*
- * If the offset is after
- * the entry mask we need
- * to account for the JSB
- * instruction we just
- * inserted.
- */
- if (fixP->fx_where >= 2)
- fixP->fx_where += 6;
- }
- }
- /*
- * Scan the symbols as offsets in the
- * fragment may have changed
- */
- for(symbolP = symbol_rootP;
- symbolP;
- symbolP = symbolP->sy_next) {
- /*
- * Look for references to this
- * fragment.
- */
- if (symbolP->sy_frag == fragP) {
- /*
- * Change the fragment
- * pointer
- */
- symbolP->sy_frag = New_Frag;
- /*
- * If the offset is after
- * the entry mask we need
- * to account for the JSB
- * instruction we just
- * inserted.
- */
- if (symbolP->sy_nlist.n_value >= 2)
- symbolP->sy_nlist.n_value += 6;
- }
- }
- /*
- * Make a symbol reference to
- * "_c$main_args" so we can get
- * its address inserted into the
- * JSB instruction.
- */
- symbolP = (symbolS *)xmalloc(sizeof(*symbolP));
- symbolP->sy_nlist.n_un.n_name = "_c$main_args";
- symbolP->sy_nlist.n_type = N_UNDF;
- symbolP->sy_nlist.n_other = 0;
- symbolP->sy_nlist.n_desc = 0;
- symbolP->sy_nlist.n_value = 0;
- symbolP->sy_name_offset = 0;
- symbolP->sy_number = 0;
- symbolP->sy_frag = New_Frag;
- symbolP->sy_forward = 0;
- symbolP->sy_next = symbol_rootP;
- symbol_rootP = symbolP;
- /*
- * Generate a text fixup structure
- * to get "_c$main_args" stored into the
- * JSB instruction.
- */
- fixP = (struct fix *)xmalloc(sizeof(*fixP));
- fixP->fx_frag = New_Frag;
- fixP->fx_where = 4;
- fixP->fx_addsy = symbolP;
- fixP->fx_subsy = 0;
- fixP->fx_offset = 0;
- fixP->fx_size = sizeof(long);
- fixP->fx_pcrel = 1;
- fixP->fx_next = text_fix_root;
- text_fix_root = fixP;
- /*
- * Now make sure we exit from the loop
- */
- frchainP = 0;
- break;
- }
- /*
- * Try the next fragment
- */
- prev_fragPP = &fragP->fr_next;
- fragP = fragP->fr_next;
- }
- /*
- * Try the next fragment chain
- */
- if (frchainP) frchainP=frchainP->frch_next;
- }
- #endif HACK_DEC_C_STARTUP
- }
- }
- /*
- * Write a VAX/VMS object file (everything else has been done!)
- */
- VMS_write_object_file(text_siz, data_siz, text_frag_root, data_frag_root)
- unsigned text_siz;
- unsigned data_siz;
- struct frag *text_frag_root;
- struct frag *data_frag_root;
- {
- register fragS * fragP;
- register symbolS * symbolP;
- register symbolS * sp;
- 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 = -1; /* Data Psect Index */
- int Bss_Psect = -1; /* Bss Psect Index */
- /*
- * Create the VMS object file
- */
- Create_VMS_Object_File();
- /*
- * Write the module header records
- */
- Write_VMS_MHD_Records();
- /*
- * Generate the VMS object file records
- * 1st GSD then TIR records
- */
- /******* Global Symbol Dictionary *******/
- /*
- * Define the Text Psect
- */
- if (text_siz > 0) {
- Text_Psect = Psect_Number++;
- VMS_Psect_Spec("$code",text_siz,"TEXT");
- }
- /*
- * Define the BSS Psect
- */
- 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
- */
- for (sp = symbol_rootP; sp; sp = sp->sy_next) {
- /*
- * Dispatch on symbol type
- */
- switch(sp->sy_type) {
- /*
- * Global uninitialized data
- */
- case N_UNDF | N_EXT:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = sp->sy_nlist.n_value;
- vsp->Psect_Index = Psect_Number++;
- vsp->Psect_Offset = 0;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- /*
- * Make the psect for this data
- */
- 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
- * beginning of the Psect
- */
- VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Psect_Index,
- 0,
- 1);
- #endif NOT_VAX_11_C_COMPATIBLE
- break;
- /*
- * Local uninitialized data
- */
- case N_BSS:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = 0;
- vsp->Psect_Index = Bss_Psect;
- vsp->Psect_Offset =
- sp->sy_nlist.n_value -
- bss_address_frag . fr_address;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- break;
- /*
- * Global initialized data
- */
- case N_DATA | N_EXT:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = VMS_Initialized_Data_Size(sp,
- text_siz + data_siz);
- vsp->Psect_Index = Psect_Number++;
- vsp->Psect_Offset = 0;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- /*
- * Make its psect
- */
- 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
- * beginning of the Psect
- */
- VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
- vsp->Psect_Index,
- 0,
- 1);
- #endif NOT_VAX_11_C_COMPATIBLE
- break;
- /*
- * Local initialized data
- */
- case N_DATA:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size =
- VMS_Initialized_Data_Size(sp,
- text_siz + data_siz);
- vsp->Psect_Index = Data_Psect;
- vsp->Psect_Offset =
- Local_Initialized_Data_Size;
- Local_Initialized_Data_Size += vsp->Size;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- break;
- /*
- * Global Text definition
- */
- case N_TEXT | N_EXT: {
- unsigned short Entry_Mask;
- /*
- * Get the entry mask
- */
- fragP = sp->sy_frag;
- Entry_Mask = (fragP->fr_literal[0] & 0xff) +
- ((fragP->fr_literal[1] & 0xff)
- << 8);
- /*
- * Define the Procedure entry pt.
- */
- VMS_Procedure_Entry_Pt(sp->sy_nlist.n_un.n_name,
- Text_Psect,
- sp->sy_nlist.n_value,
- Entry_Mask);
- break;
- }
- /*
- * Local Text definition
- */
- case N_TEXT:
- /*
- * Make a VMS data symbol entry
- */
- vsp = (struct VMS_Symbol *)
- xmalloc(sizeof(*vsp));
- vsp->Symbol = sp;
- vsp->Size = 0;
- vsp->Psect_Index = Text_Psect;
- vsp->Psect_Offset = sp->sy_nlist.n_value;
- vsp->Next = VMS_Symbols;
- VMS_Symbols = vsp;
- sp->sy_number = (int)vsp;
- break;
- /*
- * Global Reference
- */
- case N_UNDF:
- /*
- * Make a GSD global symbol reference
- * record.
- */
- VMS_Global_Symbol_Spec(sp->sy_nlist.n_un.n_name,
- 0,
- 0,
- 0);
- break;
- /*
- * Anything else
- */
- default:
- /*
- * Ignore STAB symbols
- */
- if ((sp->sy_type & N_STAB) != 0) break;
- /*
- * Error
- */
- printf(" ERROR, unknown type (%d)\n",
- sp->sy_nlist.n_type);
- break;
- }
- }
- /*
- * Define the Data Psect
- */
- if ((data_siz > 0) && (Local_Initialized_Data_Size > 0)) {
- /*
- * Do it
- */
- Data_Psect = Psect_Number++;
- VMS_Psect_Spec("$data",
- Local_Initialized_Data_Size,
- "DATA");
- /*
- * Scan the VMS symbols and fill in the data psect
- */
- for (vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
- /*
- * Only look for undefined psects
- */
- if (vsp->Psect_Index < 0) {
- /*
- * And only initialized data
- */
- if (vsp->Symbol->sy_nlist.n_type == N_DATA)
- vsp->Psect_Index = Data_Psect;
- }
- }
- }
- /******* Text Information and Relocation Records *******/
- /*
- * Write the text segment data
- */
- if (text_siz > 0) {
- /*
- * Scan the text fragments
- */
- for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
- /*
- * Stop if we get to the data fragments
- */
- if (fragP == data_frag_root) break;
- /*
- * Ignore fragments with no data
- */
- if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
- continue;
- /*
- * Go the the appropriate offset in the
- * Text Psect.
- */
- VMS_Set_Psect(Text_Psect,fragP->fr_address,OBJ$C_TIR);
- /*
- * Store the "fixed" part
- */
- if (fragP->fr_fix)
- VMS_Store_Immediate_Data(fragP->fr_literal,
- fragP->fr_fix,
- OBJ$C_TIR);
- /*
- * Store the "variable" part
- */
- if (fragP->fr_var && fragP->fr_offset)
- VMS_Store_Repeated_Data(fragP->fr_offset,
- fragP->fr_literal+
- fragP->fr_fix,
- fragP->fr_var,
- OBJ$C_TIR);
- }
- /*
- * Now we go through the text segment fixups and
- * generate TIR records to fix up addresses within
- * the Text Psect
- */
- for(fixP = text_fix_root; fixP; fixP = fixP->fx_next) {
- /*
- * We DO handle the case of "Symbol - Symbol" as
- * long as it is in the same segment.
- */
- if (fixP->fx_subsy && fixP->fx_addsy) {
- int i;
- /*
- * They need to be in the same segment
- */
- if (fixP->fx_subsy->sy_type !=
- fixP->fx_addsy->sy_type)
- error("Fixup data addsy and subsy didn't have the same type");
- /*
- * And they need to be in one that we
- * can check the psect on
- */
- if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
- ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
- error("Fixup data addsy and subsy didn't have an appropriate type");
- /*
- * This had better not be PC relative!
- */
- if (fixP->fx_pcrel)
- error("Fixup data was erroneously \"pcrel\"");
- /*
- * Subtract their values to get the
- * difference.
- */
- i = fixP->fx_addsy->sy_value -
- fixP->fx_subsy->sy_value;
- /*
- * Now generate the fixup object records
- * Set the psect and store the data
- */
- VMS_Set_Psect(Text_Psect,
- fixP->fx_where +
- fixP->fx_frag->fr_address,
- OBJ$C_TIR);
- VMS_Store_Immediate_Data(&i,
- fixP->fx_size,
- OBJ$C_TIR);
- /*
- * Done
- */
- continue;
- }
- /*
- * Size will HAVE to be "long"
- */
- if (fixP->fx_size != sizeof(long))
- error("Fixup datum was not a longword");
- /*
- * Symbol must be "added" (if it is ever
- * subtracted we can
- * fix this assumption)
- */
- if (fixP->fx_addsy == 0)
- error("Fixup datum was not \"fixP->fx_addsy\"");
- /*
- * Store the symbol value in a PIC fashion
- */
- VMS_Store_PIC_Symbol_Reference(fixP->fx_addsy,
- fixP->fx_offset,
- fixP->fx_pcrel,
- Text_Psect,
- fixP->fx_where +
- fixP->fx_frag->fr_address,
- OBJ$C_TIR);
- /*
- * Check for indirect address reference,
- * which has to be fixed up (as the linker
- * will screw it up with TIR$C_STO_PICR).
- */
- if (fixP->fx_pcrel)
- VMS_Fix_Indirect_Reference(Text_Psect,
- fixP->fx_where +
- fixP->fx_frag->fr_address,
- fixP->fx_frag,
- text_frag_root);
- }
- }
- /*
- * Store the Data segment:
- *
- * Since this is REALLY hard to do any other way,
- * we actually manufacture the data segment and
- * the store the appropriate values out of it.
- */
- if (data_siz > 0) {
- char *Data_Segment;
- /*
- * Allocate the data segment
- */
- Data_Segment = (char *)xmalloc(data_siz);
- /*
- * Run through the data fragments, filling in the segment
- */
- for(fragP = data_frag_root; fragP; fragP = fragP->fr_next) {
- register long int count;
- register char * fill_literal;
- register long int fill_size;
- int i;
- i = fragP->fr_address - text_siz;
- if (fragP->fr_fix)
- bcopy(fragP->fr_literal,
- Data_Segment + i,
- fragP->fr_fix);
- i += fragP->fr_fix;
- fill_literal= fragP -> fr_literal + fragP -> fr_fix;
- fill_size = fragP -> fr_var;
- for (count = fragP -> fr_offset; count; count --) {
- if (fill_size)
- bcopy(fill_literal,
- Data_Segment + i,
- fill_size);
- i += fill_size;
- }
- }
- /*
- * Now we can run through all the data symbols
- * and store the data
- */
- for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
- /*
- * Ignore anything other than data symbols
- */
- if ((vsp->Symbol->sy_nlist.n_type & ~N_EXT) != N_DATA)
- continue;
- /*
- * Set the Psect + Offset
- */
- VMS_Set_Psect(vsp->Psect_Index,
- vsp->Psect_Offset,
- OBJ$C_TIR);
- /*
- * Store the data
- */
- VMS_Store_Immediate_Data(Data_Segment +
- vsp->Symbol->sy_nlist.n_value -
- text_siz,
- vsp->Size,
- OBJ$C_TIR);
- }
- /*
- * Now we go through the data segment fixups and
- * generate TIR records to fix up addresses within
- * the Data Psects
- */
- for(fixP = data_fix_root; fixP; fixP = fixP->fx_next) {
- /*
- * Find the symbol for the containing datum
- */
- for(vsp = VMS_Symbols; vsp; vsp = vsp->Next) {
- /*
- * Only bother with Data symbols
- */
- sp = vsp->Symbol;
- if ((sp->sy_nlist.n_type & ~N_EXT) != N_DATA)
- continue;
- /*
- * Ignore symbol if After fixup
- */
- if (sp->sy_nlist.n_value >
- (fixP->fx_where +
- fixP->fx_frag->fr_address))
- continue;
- /*
- * See if the datum is here
- */
- if ((sp->sy_nlist.n_value + vsp->Size) <=
- (fixP->fx_where +
- fixP->fx_frag->fr_address))
- continue;
- /*
- * We DO handle the case of "Symbol - Symbol" as
- * long as it is in the same segment.
- */
- if (fixP->fx_subsy && fixP->fx_addsy) {
- int i;
- /*
- * They need to be in the same segment
- */
- if (fixP->fx_subsy->sy_type !=
- fixP->fx_addsy->sy_type)
- error("Fixup data addsy and subsy didn't have the same type");
- /*
- * And they need to be in one that we
- * can check the psect on
- */
- if (((fixP->fx_addsy->sy_type & ~N_EXT) != N_DATA) &&
- ((fixP->fx_addsy->sy_type & ~N_EXT) != N_TEXT))
- error("Fixup data addsy and subsy didn't have an appropriate type");
- /*
- * This had better not be PC relative!
- */
- if (fixP->fx_pcrel)
- error("Fixup data was erroneously \"pcrel\"");
- /*
- * Subtract their values to get the
- * difference.
- */
- i = fixP->fx_addsy->sy_value -
- fixP->fx_subsy->sy_value;
- /*
- * Now generate the fixup object records
- * Set the psect and store the data
- */
- VMS_Set_Psect(vsp->Psect_Index,
- fixP->fx_frag->fr_address +
- fixP->fx_where -
- vsp->Symbol->sy_value +
- vsp->Psect_Offset,
- OBJ$C_TIR);
- VMS_Store_Immediate_Data(&i,
- fixP->fx_size,
- OBJ$C_TIR);
- /*
- * Done
- */
- break;
- }
- /*
- * Size will HAVE to be "long"
- */
- if (fixP->fx_size != sizeof(long))
- error("Fixup datum was not a longword");
- /*
- * Symbol must be "added" (if it is ever
- * subtracted we can
- * fix this assumption)
- */
- if (fixP->fx_addsy == 0)
- error("Fixup datum was not \"fixP->fx_addsy\"");
- /*
- * Store the symbol value in a PIC fashion
- */
- VMS_Store_PIC_Symbol_Reference(
- fixP->fx_addsy,
- fixP->fx_offset,
- fixP->fx_pcrel,
- vsp->Psect_Index,
- fixP->fx_frag->fr_address +
- fixP->fx_where -
- vsp->Symbol->sy_value +
- vsp->Psect_Offset,
- OBJ$C_TIR);
- /*
- * Done
- */
- break;
- }
-
- }
- }
- /*
- * Write the Traceback Begin Module record
- */
- VMS_TBT_Module_Begin();
- /*
- * Scan the symbols and write out the routines
- * (this makes the assumption that symbols are in
- * order of ascending text segment offset)
- */
- {
- struct symbol *Current_Routine = 0;
- int Current_Line_Number = 0;
- int Current_Offset = -1;
- int Has_Source_File = 0;
- int Largest_Line_Number = 0;
- for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next) {
- /*
- * Deal with text symbols
- */
- if ((symbolP->sy_nlist.n_type & ~N_EXT) == N_TEXT) {
- /*
- * Ignore symbols starting with "L",
- * as they are local symbols
- */
- if (symbolP->sy_nlist.n_un.n_name[0] == 'L') continue;
- /*
- * If there is a routine start defined,
- * terminate it.
- */
- if (Current_Routine) {
- /*
- * End the routine
- */
- VMS_TBT_Routine_End(
- symbolP->sy_nlist.n_value -
- Current_Routine->sy_nlist.n_value);
- }
- /*
- * Store the routine begin traceback info
- */
- VMS_TBT_Routine_Begin(symbolP,Text_Psect);
- Current_Routine = symbolP;
- /*
- * Done
- */
- continue;
- }
- /*
- * Deal with STAB symbols
- */
- if ((symbolP->sy_nlist.n_type & N_STAB) != 0) {
- /*
- * Dispatch on STAB type
- */
- switch(symbolP->sy_nlist.n_type) {
- /*
- * Line number
- */
- case N_SLINE:
- /*
- * If this is the 1st N_SLINE, setup
- * PC/Line correlation. Otherwise
- * do the delta PC/Line. If the offset
- * for the line number is not +ve we need
- * to do another PC/Line correlation
- * setup
- */
- if (Current_Offset == -1) {
- VMS_TBT_Line_PC_Correlation(
- symbolP->sy_nlist.n_desc,
- symbolP->sy_nlist.n_value,
- Text_Psect,
- 0);
- } else {
- if ((symbolP->sy_nlist.n_desc -
- Current_Line_Number) <= 0) {
- /*
- * Line delta is not +ve, we
- * need to close the line and
- * start a new PC/Line
- * correlation.
- */
- VMS_TBT_Line_PC_Correlation(0,
- symbolP->sy_nlist.n_value -
- Current_Offset,
- 0,
- -1);
- VMS_TBT_Line_PC_Correlation(
- symbolP->sy_nlist.n_desc,
- symbolP->sy_nlist.n_value,
- Text_Psect,
- 0);
- } else {
- /*
- * Line delta is +ve, all is well
- */
- VMS_TBT_Line_PC_Correlation(
- symbolP->sy_nlist.n_desc -
- Current_Line_Number,
- symbolP->sy_nlist.n_value -
- Current_Offset,
- 0,
- 1);
- }
- }
- /*
- * Update the current line/PC
- */
- Current_Line_Number = symbolP->sy_nlist.n_desc;
- if (Current_Line_Number > Largest_Line_Number)
- Largest_Line_Number =
- Current_Line_Number;
- Current_Offset = symbolP->sy_nlist.n_value;
- /*
- * Done
- */
- break;
- /*
- * Source file
- */
- case N_SO:
- /*
- * Remember that we had a source file
- * and emit the source file debugger
- * record
- */
- Has_Source_File =
- VMS_TBT_Source_File(
- symbolP->sy_nlist.n_un.n_name,
- 1);
- break;
- }
- }
- }
- /*
- * If there is a routine start defined,
- * terminate it (and the line numbers)
- */
- if (Current_Routine) {
- /*
- * Terminate the line numbers
- */
- VMS_TBT_Line_PC_Correlation(0,
- text_siz - Current_Routine->sy_nlist.n_value,
- 0,
- -1);
- /*
- * If there is a source file write out the number
- * of source lines to correlate
- */
- if (Has_Source_File)
- VMS_TBT_Source_Lines(Largest_Line_Number);
- /*
- * Terminate the routine
- */
- VMS_TBT_Routine_End(text_siz -
- Current_Routine->sy_nlist.n_value);
- }
- }
- /*
- * Write the Traceback End Module TBT record
- */
- VMS_TBT_Module_End();
- /*
- * Write the End Of Module record
- */
- if (Entry_Point_Symbol == 0)
- Write_VMS_EOM_Record(-1,0);
- else
- Write_VMS_EOM_Record(Text_Psect,
- 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) 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 V1.0";
- while(*cp) 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();
- }
- /*
- * Generate a Case-Hacked VMS symbol name (limited to 31 chars)
- */
- VMS_Case_Hack_Symbol(In,Out)
- register char *In;
- register char *Out;
- {
- register int i;
- 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++;
- /*
- * 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++;
- }
- }
- /*
- * Do the case conversion
- */
- i = 23; /* Maximum of 23 chars */
- while(*In && (--i >= 0)) {
- Case_Hack_Bits <<= 1;
- if (*In == '$') Saw_Dollar = 1;
- 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 (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 (Case_Hack_Bits == 0) {
- /*
- * And so far they are all lower case:
- * Check up to 8 more characters
- * and ensure that they are lowercase
- */
- for(i = 0; (In[i] != 0) && (i < 8); i++)
- if (isupper(In[i]) && !Saw_Dollar) break;
- 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
- */
- if (Case_Hack_Bits != 0) {
- *Out++ = '_';
- for(i = 0; i < 6; i++) {
- *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
- Case_Hack_Bits >>= 4;
- }
- *Out++ = 'X';
- }
- /*
- * Done
- */
- *Out = 0;
- }
- /*
- * 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
- */
- if (strcmp(Type,"COMMON") == 0) {
- /*
- * Common block psects are: PIC,OVR,REL,GBL,SHR,RD,WRT
- */
- Psect_Attributes = (GPS$M_PIC|GPS$M_OVR|GPS$M_REL|GPS$M_GBL|
- GPS$M_SHR|GPS$M_RD|GPS$M_WRT);
- } else {
- if (strcmp(Type,"DATA") == 0) {
- /*
- * The Data psects are PIC,REL,RD,WRT
- */
- Psect_Attributes =
- (GPS$M_PIC|GPS$M_REL|GPS$M_RD|GPS$M_WRT);
- } else {
- if (strcmp(Type,"TEXT") == 0) {
- /*
- * The Text psects are PIC,REL,SHR,EXE,RD
- */
- Psect_Attributes =
- (GPS$M_PIC|GPS$M_REL|GPS$M_SHR|
- GPS$M_EXE|GPS$M_RD);
- } else {
- /*
- * Error: Unknown psect type
- */
- error("Unknown VMS psect type");
- }
- }
- }
- /*
- * Modify the psect attributes according to any attribute string
- */
- if (HAS_PSECT_ATTRIBUTES(Name))
- VMS_Modify_Psect_Attributes(Name,&Psect_Attributes);
- /*
- * Specify the psect attributes
- */
- PUT_SHORT(Psect_Attributes);
- /*
- * Specify the allocation
- */
- PUT_LONG(Size);
- /*
- * Finally, the psect name
- */
- VMS_Case_Hack_Symbol(Name,Local);
- PUT_COUNTED_STRING(Local);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
- /*
- * Define a global symbol
- */
- VMS_Global_Symbol_Spec(Name, Psect_Number, Psect_Offset, Defined)
- char *Name;
- int Psect_Number;
- int Psect_Offset;
- {
- char Local[32];
- /*
- * 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 Global symbol definition subrecord
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(GSD$C_SYM);
- } else {
- PUT_CHAR(GSD$C_SYMW);
- }
- /*
- * Data type is undefined
- */
- PUT_CHAR(0);
- /*
- * Switch on Definition/Reference
- */
- if (Defined) {
- /*
- * Definition:
- * Flags = "RELOCATABLE" and "DEFINED"
- */
- PUT_SHORT(GSY$M_DEF|GSY$M_REL);
- /*
- * Psect Number
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(Psect_Number);
- } else {
- PUT_SHORT(Psect_Number);
- }
- /*
- * Offset
- */
- PUT_LONG(Psect_Offset);
- } else {
- /*
- * Reference:
- * Flags = "RELOCATABLE"
- */
- PUT_SHORT(GSY$M_REL);
- }
- /*
- * Finally, the global symbol name
- */
- VMS_Case_Hack_Symbol(Name,Local);
- PUT_COUNTED_STRING(Local);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
- /*
- * Define a procedure entry pt/mask
- */
- VMS_Procedure_Entry_Pt(Name, Psect_Number, Psect_Offset, Entry_Mask)
- char *Name;
- int Psect_Number;
- int Psect_Offset;
- int Entry_Mask;
- {
- char Local[32];
- /*
- * 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 Procedure Entry Pt/Mask subrecord
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(GSD$C_EPM);
- } else {
- PUT_CHAR(GSD$C_EPMW);
- }
- /*
- * Data type is undefined
- */
- PUT_CHAR(0);
- /*
- * Flags = "RELOCATABLE" and "DEFINED"
- */
- PUT_SHORT(GSY$M_DEF|GSY$M_REL);
- /*
- * Psect Number
- */
- if (Psect_Number <= 255) {
- PUT_CHAR(Psect_Number);
- } else {
- PUT_SHORT(Psect_Number);
- }
- /*
- * Offset
- */
- PUT_LONG(Psect_Offset);
- /*
- * Entry mask
- */
- PUT_SHORT(Entry_Mask);
- /*
- * Finally, the global symbol name
- */
- VMS_Case_Hack_Symbol(Name,Local);
- PUT_COUNTED_STRING(Local);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
- /*
- * Set the current location counter to a particular Psect and Offset
- */
- VMS_Set_Psect(Psect_Index, Offset, Record_Type)
- int Psect_Index;
- int Offset;
- int Record_Type;
- {
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * If the buffer is empty we must insert the record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Stack the Psect base + Longword Offset
- */
- if (Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect_Index);
- }
- PUT_LONG(Offset);
- /*
- * Set relocation base
- */
- PUT_CHAR(TIR$C_CTL_SETRB);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
- /*
- * Store immediate data in current Psect
- */
- VMS_Store_Immediate_Data(Pointer, Size, Record_Type)
- register char *Pointer;
- int Size;
- int Record_Type;
- {
- register int i;
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * We can only store 128 bytes at a time
- */
- while(Size > 0) {
- /*
- * Store a maximum of 128 bytes
- */
- i = (Size > 128) ? 128 : Size;
- Size -= i;
- /*
- * If we cannot accommodate this record, flush the
- * buffer.
- */
- if ((Object_Record_Offset + i + 1) >=
- sizeof(Object_Record_Buffer))
- Flush_VMS_Object_Record_Buffer();
- /*
- * If the buffer is empty we must insert record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Store the count
- */
- PUT_CHAR(-i & 0xff);
- /*
- * Store the data
- */
- while(--i >= 0) PUT_CHAR(*Pointer++);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
- }
- /*
- * Store repeated immediate data in current Psect
- */
- VMS_Store_Repeated_Data(Repeat_Count,Pointer, Size, Record_Type)
- int Repeat_Count;
- register char *Pointer;
- int Size;
- int Record_Type;
- {
- /*
- * Ignore zero bytes/words/longwords
- */
- if ((Size == sizeof(char)) && (*Pointer == 0)) return;
- if ((Size == sizeof(short)) && (*(short *)Pointer == 0)) return;
- if ((Size == sizeof(long)) && (*(long *)Pointer == 0)) return;
- /*
- * If the data is too big for a TIR$C_STO_RIVB sub-record
- * then we do it manually
- */
- if (Size > 255) {
- while(--Repeat_Count >= 0)
- VMS_Store_Immediate_Data(Pointer,Size,Record_Type);
- return;
- }
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * If the buffer is empty we must insert record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Stack the repeat count
- */
- PUT_CHAR(TIR$C_STA_LW);
- PUT_LONG(Repeat_Count);
- /*
- * And now the command and its data
- */
- PUT_CHAR(TIR$C_STO_RIVB);
- PUT_CHAR(Size);
- while(--Size >= 0) PUT_CHAR(*Pointer++);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
- /*
- * Store a Position Independent Reference
- */
- VMS_Store_PIC_Symbol_Reference(Symbol, Offset, PC_Relative,
- Psect, Psect_Offset, Record_Type)
- struct symbol *Symbol;
- int Offset;
- int PC_Relative;
- int Psect;
- int Psect_Offset;
- int Record_Type;
- {
- register struct VMS_Symbol *vsp =
- (struct VMS_Symbol *)(Symbol->sy_number);
- char Local[32];
- /*
- * We are writing a "Record_Type" record
- */
- Set_VMS_Object_File_Record(Record_Type);
- /*
- * If the buffer is empty we must insert record type
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Set to the appropriate offset in the Psect
- */
- if (PC_Relative) {
- /*
- * For a Code reference we need to fix the operand
- * specifier as well (so back up 1 byte)
- */
- VMS_Set_Psect(Psect, Psect_Offset - 1, Record_Type);
- } else {
- /*
- * For a Data reference we just store HERE
- */
- VMS_Set_Psect(Psect, Psect_Offset, Record_Type);
- }
- /*
- * Make sure we are still generating a "Record Type" record
- */
- if (Object_Record_Offset == 0) PUT_CHAR(Record_Type);
- /*
- * Dispatch on symbol type (so we can stack its value)
- */
- switch(Symbol->sy_nlist.n_type) {
- /*
- * Global symbol
- */
- #ifdef NOT_VAX_11_C_COMPATIBLE
- case N_UNDF | N_EXT:
- case N_DATA | N_EXT:
- #endif NOT_VAX_11_C_COMPATIBLE
- case N_UNDF:
- case N_TEXT | N_EXT:
- /*
- * Get the symbol name (case hacked)
- */
- VMS_Case_Hack_Symbol(Symbol->sy_nlist.n_un.n_name,Local);
- /*
- * Stack the global symbol value
- */
- PUT_CHAR(TIR$C_STA_GBL);
- PUT_COUNTED_STRING(Local);
- if (Offset) {
- /*
- * Stack the longword offset
- */
- PUT_CHAR(TIR$C_STA_LW);
- PUT_LONG(Offset);
- /*
- * Add the two, leaving the result on the stack
- */
- PUT_CHAR(TIR$C_OPR_ADD);
- }
- break;
- /*
- * Uninitialized local data
- */
- case N_BSS:
- /*
- * Stack the Psect (+offset)
- */
- if (vsp->Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(vsp->Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(vsp->Psect_Index);
- }
- PUT_LONG(vsp->Psect_Offset + Offset);
- break;
- /*
- * Local text
- */
- case N_TEXT:
- /*
- * Stack the Psect (+offset)
- */
- if (vsp->Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(vsp->Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(vsp->Psect_Index);
- }
- PUT_LONG(Symbol->sy_nlist.n_value);
- break;
- /*
- * Initialized local or global data
- */
- case N_DATA:
- #ifndef NOT_VAX_11_C_COMPATIBLE
- case N_UNDF | N_EXT:
- case N_DATA | N_EXT:
- #endif NOT_VAX_11_C_COMPATIBLE
- /*
- * Stack the Psect (+offset)
- */
- if (vsp->Psect_Index < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(vsp->Psect_Index);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(vsp->Psect_Index);
- }
- PUT_LONG(vsp->Psect_Offset + Offset);
- break;
- }
- /*
- * Store either a code or data reference
- */
- PUT_CHAR(PC_Relative ? TIR$C_STO_PICR : TIR$C_STO_PIDR);
- /*
- * Flush the buffer if it is more than 75% full
- */
- if (Object_Record_Offset >
- (sizeof(Object_Record_Buffer)*3/4))
- Flush_VMS_Object_Record_Buffer();
- }
- /*
- * Check in the text area for an indirect pc-relative reference
- * and fix it up with addressing mode 0xff [PC indirect]
- *
- * THIS SHOULD BE REPLACED BY THE USE OF TIR$C_STO_PIRR IN THE
- * PIC CODE GENERATING FIXUP ROUTINE.
- */
- VMS_Fix_Indirect_Reference(Text_Psect, Offset, fragP, text_frag_root)
- int Text_Psect;
- int Offset;
- register fragS *fragP;
- struct frag *text_frag_root;
- {
- /*
- * The addressing mode byte is 1 byte before the address
- */
- Offset--;
- /*
- * Is it in THIS frag??
- */
- if ((Offset < fragP->fr_address) ||
- (Offset >= (fragP->fr_address + fragP->fr_fix))) {
- /*
- * We need to search for the fragment containing this
- * Offset
- */
- for(fragP = text_frag_root; fragP; fragP = fragP->fr_next) {
- if ((Offset >= fragP->fr_address) &&
- (Offset < (fragP->fr_address + fragP->fr_fix)))
- break;
- }
- /*
- * If we couldn't find the frag, things are BAD!!
- */
- if (fragP == 0)
- error("Couldn't find fixup fragment when checking for indirect reference");
- }
- /*
- * Check for indirect PC relative addressing mode
- */
- if (fragP->fr_literal[Offset - fragP->fr_address] == (char)0xff) {
- static char Address_Mode = 0xff;
- /*
- * Yes: Store the indirect mode back into the image
- * to fix up the damage done by STO_PICR
- */
- VMS_Set_Psect(Text_Psect,Offset,OBJ$C_TIR);
- VMS_Store_Immediate_Data(&Address_Mode,1,OBJ$C_TIR);
- }
- }
- /*
- * Write the Traceback Module Begin record
- */
- VMS_TBT_Module_Begin()
- {
- register char *cp,*cp1;
- int Size;
- char Module_Name[256];
- char Local[256];
- /*
- * 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
- */
- while(--cp1 >= Module_Name)
- if (*cp1 == '.') *cp1 = 0;
- if (strlen(Module_Name) > 31) Module_Name[31] = 0;
- /*
- * Arrange to store the data locally (leave room for size byte)
- */
- cp = Local+1;
- /*
- * Begin module
- */
- *cp++ = DST$C_MODBEG;
- /*
- * Unused
- */
- *cp++ = 0;
- /*
- * Language type == "C"
- */
- *(long *)cp = DST$C_C;
- cp += sizeof(long);
- /*
- * Store the module name
- */
- *cp++ = strlen(Module_Name);
- cp1 = Module_Name;
- while(*cp1) *cp++ = *cp1++;
- /*
- * Now we can store the record size
- */
- Size = (cp - Local);
- Local[0] = Size-1;
- /*
- * Put it into the object record
- */
- VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
- }
- /*
- * Write the Traceback Module End record
- */
- VMS_TBT_Module_End()
- {
- char Local[2];
- /*
- * End module
- */
- Local[0] = 1;
- Local[1] = DST$C_MODEND;
- /*
- * Put it into the object record
- */
- VMS_Store_Immediate_Data(Local, 2, OBJ$C_TBT);
- }
- /*
- * Write the Traceback Routine Begin record
- */
- VMS_TBT_Routine_Begin(symbolP, Psect)
- struct symbol *symbolP;
- int Psect;
- {
- register char *cp,*cp1;
- char *Name;
- int Offset;
- int Size;
- char Local[512];
- /*
- * Strip the leading "_" from the name
- */
- Name = symbolP->sy_nlist.n_un.n_name;
- if (*Name == '_') Name++;
- /*
- * Get the text psect offset
- */
- Offset = symbolP->sy_nlist.n_value;
- /*
- * Calculate the record size
- */
- Size = 1+1+4+1+strlen(Name);
- /*
- * Record Size
- */
- Local[0] = Size;
- /*
- * Begin Routine
- */
- Local[1] = DST$C_RTNBEG;
- /*
- * Uses CallS/CallG
- */
- Local[2] = 0;
- /*
- * Store the data so far
- */
- VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
- /*
- * Make sure we are still generating a OBJ$C_TBT record
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
- /*
- * Now get the symbol address
- */
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect);
- PUT_LONG(Offset);
- /*
- * Store the data reference
- */
- PUT_CHAR(TIR$C_STO_PIDR);
- /*
- * Store the counted string as data
- */
- cp = Local;
- cp1 = Name;
- Size = strlen(cp1) + 1;
- *cp++ = Size - 1;
- while(*cp1) *cp++ = *cp1++;
- VMS_Store_Immediate_Data(Local, Size, OBJ$C_TBT);
- }
- /*
- * Write the Traceback Routine End record
- */
- VMS_TBT_Routine_End(Size)
- {
- char Local[16];
- /*
- * Record Size
- */
- Local[0] = 6;
- /*
- * End of Routine
- */
- Local[1] = DST$C_RTNEND;
- /*
- * Unused
- */
- Local[2] = 0;
- /*
- * Size of routine
- */
- *((long *)(Local+3)) = Size;
- /*
- * Store the record
- */
- VMS_Store_Immediate_Data(Local,7, OBJ$C_TBT);
- }
- /*
- * Write a Line number / PC correlation record
- */
- VMS_TBT_Line_PC_Correlation(Line_Number, Offset, Psect, Do_Delta)
- int Line_Number;
- int Offset;
- int Psect;
- int Do_Delta;
- {
- register char *cp;
- char Local[64];
- /*
- * If not delta, set our PC/Line number correlation
- */
- if (Do_Delta == 0) {
- /*
- * Size
- */
- Local[0] = 1+1+2+1+4;
- /*
- * Line Number/PC correlation
- */
- Local[1] = DST$C_LINE_NUM;
- /*
- * Set Line number
- */
- Local[2] = DST$C_SET_LINE_NUM;
- *((unsigned short *)(Local+3)) = Line_Number-1;
- /*
- * Set PC
- */
- Local[5] = DST$C_SET_ABS_PC;
- VMS_Store_Immediate_Data(Local, 6, OBJ$C_TBT);
- /*
- * Make sure we are still generating a OBJ$C_TBT record
- */
- if (Object_Record_Offset == 0) PUT_CHAR(OBJ$C_TBT);
- if (Psect < 255) {
- PUT_CHAR(TIR$C_STA_PL);
- PUT_CHAR(Psect);
- } else {
- PUT_CHAR(TIR$C_STA_WPL);
- PUT_SHORT(Psect);
- }
- PUT_LONG(Offset);
- PUT_CHAR(TIR$C_STO_PIDR);
- /*
- * Do a PC offset of 0 to register the line number
- */
- Local[0] = 2;
- Local[1] = DST$C_LINE_NUM;
- Local[2] = 0; /* Increment PC by 0 and register line # */
- VMS_Store_Immediate_Data(Local, 3, OBJ$C_TBT);
- } else {
- /*
- * If Delta is negative, terminate the line numbers
- */
- if (Do_Delta < 0) {
- Local[0] = 1+1+4;
- Local[1] = DST$C_LINE_NUM;
- Local[2] = DST$C_TERM_L;
- *((long *)(Local+3)) = Offset;
- VMS_Store_Immediate_Data(Local, 7, OBJ$C_TBT);
- /*
- * Done
- */
- return;
- }
- /*
- * Do a PC/Line delta
- */
- cp = Local+1;
- *cp++ = DST$C_LINE_NUM;
- if (Line_Number > 1) {
- /*
- * We need to increment the line number
- */
- if (Line_Number-1 <= 255) {
- *cp++ = DST$C_INCR_LINUM;
- *cp++ = Line_Number-1;
- } else {
- *cp++ = DST$C_INCR_LINUM_W;
- *(short *)cp = Line_Number-1;
- cp += sizeof(short);
- }
- }
- /*
- * Increment the PC
- */
- if (Offset <= 128) {
- *cp++ = -Offset;
- } else {
- if (Offset < 0x10000) {
- *cp++ = DST$C_DELTA_PC_W;
- *(short *)cp = Offset;
- cp += sizeof(short);
- } else {
- *cp++ = DST$C_DELTA_PC_L;
- *(long *)cp = Offset;
- cp += sizeof(long);
- }
- }
- Local[0] = cp - (Local+1);
- VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
- }
- }
- /*
- * Describe a source file to the debugger
- */
- VMS_TBT_Source_File(Filename, ID_Number)
- char *Filename;
- int ID_Number;
- {
- register char *cp,*cp1;
- int Status,i;
- char Local[512];
- static struct FAB Fab;
- static struct NAM Nam;
- static struct XABDAT Date_Xab;
- static struct XABFHC File_Header_Xab;
- char Es_String[255],Rs_String[255];
- /*
- * Setup the Fab
- */
- Fab.fab$b_bid = FAB$C_BID;
- Fab.fab$b_bln = sizeof(Fab);
- Fab.fab$l_nam = (&Nam);
- Fab.fab$l_xab = (struct XAB *)&Date_Xab;
- /*
- * Setup the Nam block so we can find out the FULL name
- * of the source file.
- */
- Nam.nam$b_bid = NAM$C_BID;
- Nam.nam$b_bln = sizeof(Nam);
- Nam.nam$l_rsa = Rs_String;
- Nam.nam$b_rss = sizeof(Rs_String);
- Nam.nam$l_esa = Es_String;
- Nam.nam$b_ess = sizeof(Es_String);
- /*
- * Setup the Date and File Header Xabs
- */
- ((struct XAB *)&Date_Xab)->xab$b_cod = XAB$C_DAT;
- ((struct XAB *)&Date_Xab)->xab$b_bln = sizeof(Date_Xab);
- ((struct XAB *)&Date_Xab)->xab$l_nxt = (struct XAB *)&File_Header_Xab;
- ((struct XAB *)&File_Header_Xab)->xab$b_cod = XAB$C_FHC;
- ((struct XAB *)&File_Header_Xab)->xab$b_bln = sizeof(File_Header_Xab);
- /*
- * Get the file information
- */
- Fab.fab$l_fna = Filename;
- Fab.fab$b_fns = strlen(Filename);
- Status = sys$open(&Fab);
- if (!(Status & 1)) {
- printf("gas: Couldn't find source file \"%s\", Error = %%X%x\n",
- Filename, Status);
- return(0);
- }
- sys$close(&Fab);
- /*
- * Calculate the size of the resultant string
- */
- i = Nam.nam$b_rsl;
- /*
- * Size of record
- */
- Local[0] = 1+1+1+1+1+2+8+4+2+1+1+i+1+1+2+1+4;
- /*
- * Source declaration
- */
- Local[1] = DST$C_SOURCE;
- /*
- * Make formfeeds count as source records
- */
- Local[2] = DST$C_SRC_FORMFEED;
- /*
- * Declare source file
- */
- Local[3] = DST$C_SRC_DECLFILE;
- Local[4] = 1+2+8+4+2+1+1+i+1;
- cp = Local+5;
- /*
- * Flags
- */
- *cp++ = 0;
- /*
- * File ID
- */
- *(short *)cp = ID_Number;
- cp += sizeof(short);
- /*
- * Creation Date
- */
- *(long *)cp = Date_Xab.xab$q_cdt[0];
- cp += sizeof(long);
- *(long *)cp = Date_Xab.xab$q_cdt[1];
- cp += sizeof(long);
- /*
- * End of file block
- */
- *(long *)cp = File_Header_Xab.xab$l_ebk;
- cp += sizeof(long);
- /*
- * First free byte
- */
- *(short *)cp = File_Header_Xab.xab$w_ffb;
- cp += sizeof(short);
- /*
- * Record format
- */
- *cp++ = File_Header_Xab.xab$b_rfo;
- /*
- * Filename
- */
- *cp++ = i;
- cp1 = Rs_String;
- while(--i >= 0) *cp++ = *cp1++;
- /*
- * Library module name (none)
- */
- *cp++ = 0;
- /*
- * Set Source File
- */
- *cp++ = DST$C_SRC_SETFILE;
- /*
- * File ID Number
- */
- *(short *)cp = ID_Number;
- cp += sizeof(short);
- /*
- * Set record number
- */
- *cp++ = DST$C_SRC_SETREC_L;
- *(long *)cp = 1;
- cp += sizeof(long);
- /*
- * Done
- */
- VMS_Store_Immediate_Data(Local,cp - Local, OBJ$C_TBT);
- }
- /*
- * Give the number of source lines to the debugger
- */
- VMS_TBT_Source_Lines(Number_Of_Lines)
- int Number_Of_Lines;
- {
- char Local[8];
- /*
- * Size of record
- */
- Local[0] = 1+1+2;
- /*
- * Source declaration
- */
- Local[1] = DST$C_SOURCE;
- /*
- * Define lines
- */
- Local[2] = DST$C_SRC_DEFLINES_W;
- *(short *)(Local+3) = Number_Of_Lines;
- /*
- * Done
- */
- VMS_Store_Immediate_Data(Local, 5, OBJ$C_TBT);
- }
- /*
- * Given the pointer to a symbol we calculate how big the data at the
- * symbol is. We do this by looking for the next symbol (local or
- * global) which will indicate the start of another datum.
- */
- int VMS_Initialized_Data_Size(sp, End_Of_Data)
- register struct symbol *sp;
- int End_Of_Data;
- {
- register struct symbol *sp1,*Next_Symbol;
- /*
- * Find the next symbol
- * it delimits this datum
- */
- Next_Symbol = 0;
- for (sp1 = symbol_rootP; sp1; sp1 = sp1->sy_next) {
- /*
- * The data type must match
- */
- if ((sp1->sy_nlist.n_type & ~N_EXT) != N_DATA) continue;
- /*
- * The symbol must be AFTER this symbol
- */
- if (sp1->sy_nlist.n_value <= sp->sy_nlist.n_value) continue;
- /*
- * We ignore THIS symbol
- */
- if (sp1 == sp) continue;
- /*
- * If there is already a candidate selected for the
- * next symbol, see if we are a better candidate
- */
- if (Next_Symbol) {
- /*
- * We are a better candidate if we are "closer"
- * to the symbol
- */
- if (sp1->sy_nlist.n_value >
- Next_Symbol->sy_nlist.n_value)
- continue;
- /*
- * Win: Make this the candidate
- */
- Next_Symbol = sp1;
- } else {
- /*
- * This is the 1st candidate
- */
- Next_Symbol = sp1;
- }
- }
- /*
- * Calculate its size
- */
- return(Next_Symbol ?
- (Next_Symbol->sy_nlist.n_value -
- sp->sy_nlist.n_value) :
- (End_Of_Data - sp->sy_nlist.n_value));
- }
- /*
- * This is a hacked _doprnt() for VAX-11 "C". It understands that
- * it is ONLY called by as_fatal(Format, Args) with a pointer to the
- * "Args" argument. From this we can make it all work right!
- */
- #ifndef eunice
- _doprnt(Format, a, f)
- char *Format;
- FILE *f;
- char **a;
- {
- int Nargs = ((int *)a)[-2]; /* This understands as_fatal() */
- switch(Nargs) {
- default: fprintf(f,"_doprnt error on \"%s\"!!",Format); break;
- case 1: fprintf(f,Format); break;
- case 2: fprintf(f,Format,a[0]); break;
- case 3: fprintf(f,Format,a[0],a[1]); break;
- case 4: fprintf(f,Format,a[0],a[1],a[2]); break;
- case 5: fprintf(f,Format,a[0],a[1],a[2],a[3]); break;
- case 6: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4]); break;
- case 7: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5]); break;
- case 8: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6]); break;
- case 9: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7]); break;
- case 10: fprintf(f,Format,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]); break;
- }
- }
- #endif /* eunice */
- #endif /* VMS */
|