12159047fSniklas /* vms.c -- Write out a VAX/VMS object file
2*007c2a45Smiod    Copyright 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001,
3*007c2a45Smiod    2002, 2003
4b55d4692Sfgsch    Free Software Foundation, Inc.
52159047fSniklas 
62159047fSniklas    This file is part of GAS, the GNU Assembler.
72159047fSniklas 
82159047fSniklas    GAS is free software; you can redistribute it and/or modify
92159047fSniklas    it under the terms of the GNU General Public License as published by
102159047fSniklas    the Free Software Foundation; either version 2, or (at your option)
112159047fSniklas    any later version.
122159047fSniklas 
132159047fSniklas    GAS is distributed in the hope that it will be useful,
142159047fSniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas    GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas    You should have received a copy of the GNU General Public License
19f7cc78ecSespie    along with GAS; see the file COPYING.  If not, write to the Free
20f7cc78ecSespie    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21f7cc78ecSespie    02111-1307, USA.  */
222159047fSniklas 
232159047fSniklas /* Written by David L. Kashtan */
242159047fSniklas /* Modified by Eric Youngdale to write VMS debug records for program
252159047fSniklas    variables */
262159047fSniklas 
272159047fSniklas /* Want all of obj-vms.h (as obj-format.h, via targ-env.h, via as.h).  */
282159047fSniklas #define WANT_VMS_OBJ_DEFS
292159047fSniklas 
302159047fSniklas #include "as.h"
312159047fSniklas #include "config.h"
32c074d1c9Sdrahn #include "safe-ctype.h"
332159047fSniklas #include "subsegs.h"
342159047fSniklas #include "obstack.h"
35c074d1c9Sdrahn #include <fcntl.h>
362159047fSniklas 
372159047fSniklas /* What we do if there is a goof.  */
382159047fSniklas #define error as_fatal
392159047fSniklas 
402159047fSniklas #ifdef VMS			/* These are of no use if we are cross assembling.  */
41*007c2a45Smiod #include <fab.h>		/* Define File Access Block.  */
42*007c2a45Smiod #include <nam.h>		/* Define NAM Block.  */
43*007c2a45Smiod #include <xab.h>		/* Define XAB - all different types.  */
442159047fSniklas extern int sys$open(), sys$close(), sys$asctim();
452159047fSniklas #endif
462159047fSniklas 
47*007c2a45Smiod /* Version string of the compiler that produced the code we are
48*007c2a45Smiod    assembling.  (And this assembler, if we do not have compiler info).  */
492159047fSniklas char *compiler_version_string;
502159047fSniklas 
512159047fSniklas extern int flag_hash_long_names;	/* -+ */
522159047fSniklas extern int flag_one;			/* -1; compatibility with gcc 1.x */
532159047fSniklas extern int flag_show_after_trunc;	/* -H */
542159047fSniklas extern int flag_no_hash_mixed_case;	/* -h NUM */
552159047fSniklas 
562159047fSniklas /* Flag that determines how we map names.  This takes several values, and
57*007c2a45Smiod    is set with the -h switch.  A value of zero implies names should be
58*007c2a45Smiod    upper case, and the presence of the -h switch inhibits the case hack.
59*007c2a45Smiod    No -h switch at all sets vms_name_mapping to 0, and allows case hacking.
60*007c2a45Smiod    A value of 2 (set with -h2) implies names should be
61*007c2a45Smiod    all lower case, with no case hack.  A value of 3 (set with -h3) implies
62*007c2a45Smiod    that case should be preserved.  */
632159047fSniklas 
642159047fSniklas /* If the -+ switch is given, then the hash is appended to any name that is
65*007c2a45Smiod    longer than 31 characters, regardless of the setting of the -h switch.  */
662159047fSniklas 
672159047fSniklas char vms_name_mapping = 0;
682159047fSniklas 
692159047fSniklas static symbolS *Entry_Point_Symbol = 0;	/* Pointer to "_main" */
702159047fSniklas 
71*007c2a45Smiod /* We augment the "gas" symbol structure with this.  */
72*007c2a45Smiod 
732159047fSniklas struct VMS_Symbol
742159047fSniklas {
752159047fSniklas   struct VMS_Symbol *Next;
762159047fSniklas   symbolS *Symbol;
772159047fSniklas   int Size;
782159047fSniklas   int Psect_Index;
792159047fSniklas   int Psect_Offset;
802159047fSniklas };
812159047fSniklas 
822159047fSniklas struct VMS_Symbol *VMS_Symbols = 0;
83f7cc78ecSespie struct VMS_Symbol *Ctors_Symbols = 0;
84f7cc78ecSespie struct VMS_Symbol *Dtors_Symbols = 0;
852159047fSniklas 
862159047fSniklas /* We need this to keep track of the various input files, so that we can
87*007c2a45Smiod    give the debugger the correct source line.  */
882159047fSniklas 
892159047fSniklas struct input_file
902159047fSniklas {
912159047fSniklas   struct input_file *next;
922159047fSniklas   struct input_file *same_file_fpnt;
932159047fSniklas   int file_number;
942159047fSniklas   int max_line;
952159047fSniklas   int min_line;
962159047fSniklas   int offset;
972159047fSniklas   char flag;
982159047fSniklas   char *name;
992159047fSniklas   symbolS *spnt;
1002159047fSniklas };
1012159047fSniklas 
1022159047fSniklas static struct input_file *file_root = (struct input_file *) NULL;
1032159047fSniklas 
104*007c2a45Smiod /* Styles of PSECTS (program sections) that we generate; just shorthand
105*007c2a45Smiod    to avoid lists of section attributes.  Used by VMS_Psect_Spec().  */
1062159047fSniklas enum ps_type
1072159047fSniklas {
108f7cc78ecSespie   ps_TEXT, ps_DATA, ps_COMMON, ps_CONST, ps_CTORS, ps_DTORS
1092159047fSniklas };
1102159047fSniklas 
111*007c2a45Smiod /* This enum is used to keep track of the various types of variables that
112*007c2a45Smiod    may be present.  */
1132159047fSniklas 
1142159047fSniklas enum advanced_type
1152159047fSniklas {
1162159047fSniklas   BASIC, POINTER, ARRAY, ENUM, STRUCT, UNION, FUNCTION, VOID, ALIAS, UNKNOWN
1172159047fSniklas };
1182159047fSniklas 
119*007c2a45Smiod /* This structure contains the information from the stabs directives, and the
120*007c2a45Smiod    information is filled in by VMS_typedef_parse.  Everything that is needed
121*007c2a45Smiod    to generate the debugging record for a given symbol is present here.
122*007c2a45Smiod    This could be done more efficiently, using nested struct/unions, but for
123*007c2a45Smiod    now I am happy that it works.  */
124*007c2a45Smiod 
1252159047fSniklas struct VMS_DBG_Symbol
1262159047fSniklas {
1272159047fSniklas   struct VMS_DBG_Symbol *next;
128*007c2a45Smiod   /* Description of what this is.  */
1292159047fSniklas   enum advanced_type advanced;
130*007c2a45Smiod   /* This record is for this type.  */
1312159047fSniklas   int dbx_type;
1322159047fSniklas   /* For advanced types this is the type referred to.  I.e., the type
1332159047fSniklas      a pointer points to, or the type of object that makes up an
1342159047fSniklas      array.  */
1352159047fSniklas   int type2;
136*007c2a45Smiod   /* Use this type when generating a variable def.  */
1372159047fSniklas   int VMS_type;
138*007c2a45Smiod   /* Used for arrays - this will be present for all.  */
1392159047fSniklas   int index_min;
140*007c2a45Smiod   /* Entries, but will be meaningless for non-arrays.  */
1412159047fSniklas   int index_max;
1422159047fSniklas   /* Size in bytes of the data type.  For an array, this is the size
143*007c2a45Smiod      of one element in the array.  */
1442159047fSniklas   int data_size;
145*007c2a45Smiod   /* Number of the structure/union/enum - used for ref.  */
1462159047fSniklas   int struc_numb;
1472159047fSniklas };
1482159047fSniklas 
149*007c2a45Smiod #define SYMTYPLST_SIZE (1<<4)	/* 16; Must be power of two.  */
1502159047fSniklas #define SYMTYP_HASH(x) ((unsigned) (x) & (SYMTYPLST_SIZE - 1))
151*007c2a45Smiod 
1522159047fSniklas struct VMS_DBG_Symbol *VMS_Symbol_type_list[SYMTYPLST_SIZE];
1532159047fSniklas 
154*007c2a45Smiod /* We need this structure to keep track of forward references to
155*007c2a45Smiod    struct/union/enum that have not been defined yet.  When they are
156*007c2a45Smiod    ultimately defined, then we can go back and generate the TIR
157*007c2a45Smiod    commands to make a back reference.  */
1582159047fSniklas 
1592159047fSniklas struct forward_ref
1602159047fSniklas {
1612159047fSniklas   struct forward_ref *next;
1622159047fSniklas   int dbx_type;
1632159047fSniklas   int struc_numb;
1642159047fSniklas   char resolved;
1652159047fSniklas };
1662159047fSniklas 
1672159047fSniklas struct forward_ref *f_ref_root = (struct forward_ref *) NULL;
1682159047fSniklas 
169*007c2a45Smiod /* This routine is used to compare the names of certain types to various
170*007c2a45Smiod    fixed types that are known by the debugger.  */
171*007c2a45Smiod 
1722159047fSniklas #define type_check(X)  !strcmp (symbol_name, X)
1732159047fSniklas 
174*007c2a45Smiod /* This variable is used to keep track of the name of the symbol we are
175*007c2a45Smiod    working on while we are parsing the stabs directives.  */
176*007c2a45Smiod 
1772159047fSniklas static const char *symbol_name;
1782159047fSniklas 
1792159047fSniklas /* We use this counter to assign numbers to all of the structures, unions
180*007c2a45Smiod    and enums that we define.  When we actually declare a variable to the
181*007c2a45Smiod    debugger, we can simply do it by number, rather than describing the
182*007c2a45Smiod    whole thing each time.  */
1832159047fSniklas 
184c074d1c9Sdrahn static int structure_count = 0;
1852159047fSniklas 
1862159047fSniklas /* This variable is used to indicate that we are making the last attempt to
1872159047fSniklas    parse the stabs, and that we should define as much as we can, and ignore
188*007c2a45Smiod    the rest.  */
1892159047fSniklas 
1902159047fSniklas static int final_pass;
1912159047fSniklas 
1922159047fSniklas /* This variable is used to keep track of the current structure number
193*007c2a45Smiod    for a given variable.  If this is < 0, that means that the structure
194*007c2a45Smiod    has not yet been defined to the debugger.  This is still cool, since
195*007c2a45Smiod    the VMS object language has ways of fixing things up after the fact,
196*007c2a45Smiod    so we just make a note of this, and generate fixups at the end.  */
197*007c2a45Smiod 
1982159047fSniklas static int struct_number;
1992159047fSniklas 
2002159047fSniklas /* This is used to distinguish between D_float and G_float for telling
2012159047fSniklas    the debugger about doubles.  gcc outputs the same .stabs regardless
2022159047fSniklas    of whether -mg is used to select alternate doubles.  */
2032159047fSniklas 
2042159047fSniklas static int vax_g_doubles = 0;
2052159047fSniklas 
2062159047fSniklas /* Local symbol references (used to handle N_ABS symbols; gcc does not
2072159047fSniklas    generate those, but they're possible with hand-coded assembler input)
2082159047fSniklas    are always made relative to some particular environment.  If the current
2092159047fSniklas    input has any such symbols, then we expect this to get incremented
2102159047fSniklas    exactly once and end up having all of them be in environment #0.  */
2112159047fSniklas 
2122159047fSniklas static int Current_Environment = -1;
2132159047fSniklas 
2142159047fSniklas /* Every object file must specify an module name, which is also used by
2152159047fSniklas    traceback records.  Set in Write_VMS_MHD_Records().  */
2162159047fSniklas 
2172159047fSniklas static char Module_Name[255+1];
2182159047fSniklas 
219*007c2a45Smiod /* Variable descriptors are used tell the debugger the data types of certain
220*007c2a45Smiod    more complicated variables (basically anything involving a structure,
221*007c2a45Smiod    union, enum, array or pointer).  Some non-pointer variables of the
222*007c2a45Smiod    basic types that the debugger knows about do not require a variable
223*007c2a45Smiod    descriptor.
224*007c2a45Smiod 
225*007c2a45Smiod    Since it is impossible to have a variable descriptor longer than 128
226*007c2a45Smiod    bytes by virtue of the way that the VMS object language is set up,
227*007c2a45Smiod    it makes not sense to make the arrays any longer than this, or worrying
228*007c2a45Smiod    about dynamic sizing of the array.
229*007c2a45Smiod 
230*007c2a45Smiod    These are the arrays and counters that we use to build a variable
231*007c2a45Smiod    descriptor.  */
2322159047fSniklas 
2332159047fSniklas #define MAX_DEBUG_RECORD 128
234*007c2a45Smiod static char Local[MAX_DEBUG_RECORD];	/* Buffer for variable descriptor.  */
235*007c2a45Smiod static char Asuffix[MAX_DEBUG_RECORD];	/* Buffer for array descriptor.  */
236*007c2a45Smiod static int Lpnt;		/* Index into Local.  */
237*007c2a45Smiod static int Apoint;		/* Index into Asuffix.  */
238*007c2a45Smiod static char overflow;		/* Flag to indicate we have written too much.  */
239*007c2a45Smiod static int total_len;		/* Used to calculate the total length of
240*007c2a45Smiod 				   variable descriptor plus array descriptor
241*007c2a45Smiod 				   - used for len byte.  */
2422159047fSniklas 
2432159047fSniklas /* Flag if we have told user about finding global constants in the text
2442159047fSniklas    section.  */
2452159047fSniklas static int gave_compiler_message = 0;
2462159047fSniklas 
247*007c2a45Smiod /* Global data (Object records limited to 512 bytes by VAX-11 "C" runtime).  */
2482159047fSniklas 
249*007c2a45Smiod static int VMS_Object_File_FD;		/* File Descriptor for object file.  */
250*007c2a45Smiod static char Object_Record_Buffer[512];	/* Buffer for object file records.  */
251*007c2a45Smiod static size_t Object_Record_Offset;	/* Offset to end of data.  */
252*007c2a45Smiod static int Current_Object_Record_Type;	/* Type of record in above.  */
253*007c2a45Smiod 
254*007c2a45Smiod /* Macros for moving data around.  Must work on big-endian systems.  */
255*007c2a45Smiod 
256*007c2a45Smiod #ifdef VMS  /* These are more efficient for VMS->VMS systems.  */
2572159047fSniklas #define COPY_LONG(dest,val)	( *(long *) (dest) = (val) )
2582159047fSniklas #define COPY_SHORT(dest,val)	( *(short *) (dest) = (val) )
2592159047fSniklas #else
2602159047fSniklas #define COPY_LONG(dest,val)	md_number_to_chars ((dest), (val), 4)
2612159047fSniklas #define COPY_SHORT(dest,val)	md_number_to_chars ((dest), (val), 2)
2622159047fSniklas #endif
263*007c2a45Smiod 
264*007c2a45Smiod /* Macros for placing data into the object record buffer.  */
265*007c2a45Smiod 
2662159047fSniklas #define PUT_LONG(val) \
2672159047fSniklas 	( COPY_LONG (&Object_Record_Buffer[Object_Record_Offset], (val)), \
2682159047fSniklas 	  Object_Record_Offset += 4 )
2692159047fSniklas 
2702159047fSniklas #define PUT_SHORT(val) \
2712159047fSniklas 	( COPY_SHORT (&Object_Record_Buffer[Object_Record_Offset], (val)), \
2722159047fSniklas 	  Object_Record_Offset += 2 )
2732159047fSniklas 
2742159047fSniklas #define PUT_CHAR(val) (Object_Record_Buffer[Object_Record_Offset++] = (val))
2752159047fSniklas 
276*007c2a45Smiod #define PUT_COUNTED_STRING(cp)			\
277*007c2a45Smiod   do 						\
278*007c2a45Smiod     { 						\
279*007c2a45Smiod       const char *p = (cp);			\
280*007c2a45Smiod       						\
2812159047fSniklas       PUT_CHAR ((char) strlen (p)); 		\
282*007c2a45Smiod       while (*p)				\
283*007c2a45Smiod 	PUT_CHAR (*p++);			\
284*007c2a45Smiod     }						\
285*007c2a45Smiod   while (0)
2862159047fSniklas 
287*007c2a45Smiod /* Macro for determining if a Name has psect attributes attached
288*007c2a45Smiod    to it.   */
289*007c2a45Smiod 
2902159047fSniklas #define PSECT_ATTRIBUTES_STRING		"$$PsectAttributes_"
2912159047fSniklas #define PSECT_ATTRIBUTES_STRING_LENGTH	18
2922159047fSniklas 
2932159047fSniklas #define HAS_PSECT_ATTRIBUTES(Name) \
2942159047fSniklas 		(strncmp ((*Name == '_' ? Name + 1 : Name), \
2952159047fSniklas 			  PSECT_ATTRIBUTES_STRING, \
2962159047fSniklas 			  PSECT_ATTRIBUTES_STRING_LENGTH) == 0)
2972159047fSniklas 
2982159047fSniklas 
2992159047fSniklas  /* in: segT   out: N_TYPE bits */
3002159047fSniklas const short seg_N_TYPE[] =
3012159047fSniklas {
3022159047fSniklas   N_ABS,
3032159047fSniklas   N_TEXT,
3042159047fSniklas   N_DATA,
3052159047fSniklas   N_BSS,
3062159047fSniklas   N_UNDF,			/* unknown */
3072159047fSniklas   N_UNDF,			/* error */
3082159047fSniklas   N_UNDF,			/* expression */
3092159047fSniklas   N_UNDF,			/* debug */
3102159047fSniklas   N_UNDF,			/* ntv */
3112159047fSniklas   N_UNDF,			/* ptv */
3122159047fSniklas   N_REGISTER,			/* register */
3132159047fSniklas };
3142159047fSniklas 
3152159047fSniklas const segT N_TYPE_seg[N_TYPE + 2] =
3162159047fSniklas {				/* N_TYPE == 0x1E = 32-2 */
3172159047fSniklas   SEG_UNKNOWN,			/* N_UNDF == 0 */
3182159047fSniklas   SEG_GOOF,
3192159047fSniklas   SEG_ABSOLUTE,			/* N_ABS == 2 */
3202159047fSniklas   SEG_GOOF,
3212159047fSniklas   SEG_TEXT,			/* N_TEXT == 4 */
3222159047fSniklas   SEG_GOOF,
3232159047fSniklas   SEG_DATA,			/* N_DATA == 6 */
3242159047fSniklas   SEG_GOOF,
3252159047fSniklas   SEG_BSS,			/* N_BSS == 8 */
3262159047fSniklas   SEG_GOOF,
3272159047fSniklas   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
3282159047fSniklas   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
3292159047fSniklas   SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
3302159047fSniklas   SEG_REGISTER,			/* dummy N_REGISTER for regs = 30 */
3312159047fSniklas   SEG_GOOF,
3322159047fSniklas };
3332159047fSniklas 
3342159047fSniklas 
3352159047fSniklas /* The following code defines the special types of pseudo-ops that we
3362159047fSniklas    use with VMS.  */
3372159047fSniklas 
3382159047fSniklas unsigned char const_flag = IN_DEFAULT_SECTION;
3392159047fSniklas 
3402159047fSniklas static void
s_const(int arg)341*007c2a45Smiod s_const (int arg)
3422159047fSniklas {
3432159047fSniklas   /* Since we don't need `arg', use it as our scratch variable so that
3442159047fSniklas      we won't get any "not used" warnings about it.  */
3452159047fSniklas   arg = get_absolute_expression ();
3462159047fSniklas   subseg_set (SEG_DATA, (subsegT) arg);
3472159047fSniklas   const_flag = 1;
3482159047fSniklas   demand_empty_rest_of_line ();
3492159047fSniklas }
3502159047fSniklas 
3512159047fSniklas const pseudo_typeS obj_pseudo_table[] =
3522159047fSniklas {
3532159047fSniklas   {"const", s_const, 0},
3542159047fSniklas   {0, 0, 0},
3552159047fSniklas };				/* obj_pseudo_table */
3562159047fSniklas 
3572159047fSniklas /* Routine to perform RESOLVE_SYMBOL_REDEFINITION().  */
3582159047fSniklas 
3592159047fSniklas int
vms_resolve_symbol_redef(symbolS * sym)360*007c2a45Smiod vms_resolve_symbol_redef (symbolS *sym)
3612159047fSniklas {
362*007c2a45Smiod   /* If the new symbol is .comm AND it has a size of zero,
363*007c2a45Smiod      we ignore it (i.e. the old symbol overrides it).  */
3642159047fSniklas   if (SEGMENT_TO_SYMBOL_TYPE ((int) now_seg) == (N_UNDF | N_EXT)
3652159047fSniklas       && frag_now_fix () == 0)
3662159047fSniklas     {
367f7cc78ecSespie       as_warn (_("compiler emitted zero-size common symbol `%s' already defined"),
3682159047fSniklas 	       S_GET_NAME (sym));
3692159047fSniklas       return 1;
3702159047fSniklas     }
371*007c2a45Smiod   /* If the old symbol is .comm and it has a size of zero,
372*007c2a45Smiod      we override it with the new symbol value.  */
3732159047fSniklas   if (S_IS_EXTERNAL (sym) && S_IS_DEFINED (sym) && S_GET_VALUE (sym) == 0)
3742159047fSniklas     {
375f7cc78ecSespie       as_warn (_("compiler redefined zero-size common symbol `%s'"),
3762159047fSniklas 	       S_GET_NAME (sym));
3772159047fSniklas       sym->sy_frag  = frag_now;
3782159047fSniklas       S_SET_OTHER (sym, const_flag);
3792159047fSniklas       S_SET_VALUE (sym, frag_now_fix ());
3802159047fSniklas       /* Keep N_EXT bit.  */
3812159047fSniklas       sym->sy_symbol.n_type |= SEGMENT_TO_SYMBOL_TYPE ((int) now_seg);
3822159047fSniklas       return 1;
3832159047fSniklas     }
3842159047fSniklas 
3852159047fSniklas   return 0;
3862159047fSniklas }
3872159047fSniklas 
3882159047fSniklas /* `tc_frob_label' handler for colon(symbols.c), used to examine the
3892159047fSniklas    dummy label(s) gcc inserts at the beginning of each file it generates.
3902159047fSniklas    gcc 1.x put "gcc_compiled."; gcc 2.x (as of 2.7) puts "gcc2_compiled."
3912159047fSniklas    and "__gnu_language_<name>" and possibly "__vax_<type>_doubles".  */
3922159047fSniklas 
3932159047fSniklas void
vms_check_for_special_label(symbolS * symbolP)394*007c2a45Smiod vms_check_for_special_label (symbolS *symbolP)
3952159047fSniklas {
3962159047fSniklas   /* Special labels only occur prior to explicit section directives.  */
3972159047fSniklas   if ((const_flag & IN_DEFAULT_SECTION) != 0)
3982159047fSniklas     {
3992159047fSniklas       char *sym_name = S_GET_NAME (symbolP);
4002159047fSniklas 
4012159047fSniklas       if (*sym_name == '_')
4022159047fSniklas 	++sym_name;
4032159047fSniklas 
4042159047fSniklas       if (!strcmp (sym_name, "__vax_g_doubles"))
4052159047fSniklas 	vax_g_doubles = 1;
4062159047fSniklas #if 0	/* not necessary */
4072159047fSniklas       else if (!strcmp (sym_name, "__vax_d_doubles"))
4082159047fSniklas 	vax_g_doubles = 0;
4092159047fSniklas #endif
410*007c2a45Smiod #if 0	/* These are potential alternatives to tc-vax.c's md_parse_options().  */
4112159047fSniklas       else if (!strcmp (sym_name, "gcc_compiled."))
4122159047fSniklas 	flag_one = 1;
4132159047fSniklas       else if (!strcmp (sym_name, "__gnu_language_cplusplus"))
4142159047fSniklas 	flag_hash_long_names = 1;
4152159047fSniklas #endif
4162159047fSniklas     }
4172159047fSniklas }
4182159047fSniklas 
4192159047fSniklas void
obj_read_begin_hook(void)420*007c2a45Smiod obj_read_begin_hook (void)
4212159047fSniklas {
4222159047fSniklas }
4232159047fSniklas 
4242159047fSniklas void
obj_crawl_symbol_chain(object_headers * headers)425*007c2a45Smiod obj_crawl_symbol_chain (object_headers *headers)
4262159047fSniklas {
4272159047fSniklas   symbolS *symbolP;
4282159047fSniklas   symbolS **symbolPP;
4292159047fSniklas   int symbol_number = 0;
4302159047fSniklas 
4312159047fSniklas   symbolPP = &symbol_rootP;	/* -> last symbol chain link.  */
4322159047fSniklas   while ((symbolP = *symbolPP) != NULL)
4332159047fSniklas     {
434c074d1c9Sdrahn       resolve_symbol_value (symbolP);
4352159047fSniklas 
4362159047fSniklas      /* OK, here is how we decide which symbols go out into the
4372159047fSniklas 	brave new symtab.  Symbols that do are:
4382159047fSniklas 
4392159047fSniklas 	* symbols with no name (stabd's?)
4402159047fSniklas 	* symbols with debug info in their N_TYPE
4412159047fSniklas 	* symbols with \1 as their 3rd character (numeric labels)
4422159047fSniklas 	* "local labels" needed for PIC fixups
4432159047fSniklas 
4442159047fSniklas 	Symbols that don't are:
4452159047fSniklas 	* symbols that are registers
4462159047fSniklas 
4472159047fSniklas 	All other symbols are output.  We complain if a deleted
4482159047fSniklas 	symbol was marked external.  */
4492159047fSniklas 
4502159047fSniklas       if (!S_IS_REGISTER (symbolP))
4512159047fSniklas 	{
4522159047fSniklas 	  symbolP->sy_number = symbol_number++;
4532159047fSniklas 	  symbolP->sy_name_offset = 0;
454b55d4692Sfgsch 	  symbolPP = &symbolP->sy_next;
4552159047fSniklas 	}
4562159047fSniklas       else
4572159047fSniklas 	{
4582159047fSniklas 	  if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
459*007c2a45Smiod 	    as_bad (_("Local symbol %s never defined"),
460*007c2a45Smiod 		    S_GET_NAME (symbolP));
4612159047fSniklas 
4622159047fSniklas 	  /* Unhook it from the chain.  */
4632159047fSniklas 	  *symbolPP = symbol_next (symbolP);
464*007c2a45Smiod 	}
465*007c2a45Smiod     }
4662159047fSniklas 
4672159047fSniklas   H_SET_STRING_SIZE (headers, string_byte_count);
4682159047fSniklas   H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
469*007c2a45Smiod }
4702159047fSniklas 
4712159047fSniklas 
472*007c2a45Smiod /* VMS OBJECT FILE HACKING ROUTINES.  */
4732159047fSniklas 
4742159047fSniklas /* Create the VMS object file.  */
4752159047fSniklas 
4762159047fSniklas static void
Create_VMS_Object_File(void)477*007c2a45Smiod Create_VMS_Object_File (void)
4782159047fSniklas {
479c074d1c9Sdrahn #ifdef eunice
4802159047fSniklas   VMS_Object_File_FD = creat (out_file_name, 0777, "var");
481c074d1c9Sdrahn #else
482c074d1c9Sdrahn #ifndef VMS
483c074d1c9Sdrahn   VMS_Object_File_FD = creat (out_file_name, 0777);
484c074d1c9Sdrahn #else	/* VMS */
4852159047fSniklas   VMS_Object_File_FD = creat (out_file_name, 0, "rfm=var",
486f7cc78ecSespie 			      "ctx=bin", "mbc=16", "deq=64", "fop=tef",
487f7cc78ecSespie 			      "shr=nil");
488c074d1c9Sdrahn #endif	/* !VMS */
489c074d1c9Sdrahn #endif	/* !eunice */
4902159047fSniklas   /* Deal with errors.  */
4912159047fSniklas   if (VMS_Object_File_FD < 0)
492f7cc78ecSespie     as_fatal (_("Couldn't create VMS object file \"%s\""), out_file_name);
4932159047fSniklas   /* Initialize object file hacking variables.  */
4942159047fSniklas   Object_Record_Offset = 0;
4952159047fSniklas   Current_Object_Record_Type = -1;
4962159047fSniklas }
4972159047fSniklas 
4982159047fSniklas /* Flush the object record buffer to the object file.  */
4992159047fSniklas 
5002159047fSniklas static void
Flush_VMS_Object_Record_Buffer(void)501*007c2a45Smiod Flush_VMS_Object_Record_Buffer (void)
5022159047fSniklas {
5032159047fSniklas   /* If the buffer is empty, there's nothing to do.  */
5042159047fSniklas   if (Object_Record_Offset == 0)
5052159047fSniklas     return;
5062159047fSniklas 
5072159047fSniklas #ifndef VMS			/* For cross-assembly purposes.  */
5082159047fSniklas   {
5092159047fSniklas     char RecLen[2];
5102159047fSniklas 
5112159047fSniklas     /* "Variable-length record" files have a two byte length field
5122159047fSniklas        prepended to each record.  It's normally out-of-band, and native
5132159047fSniklas        VMS output will insert it automatically for this type of file.
5142159047fSniklas        When cross-assembling, we must write it explicitly.  */
5152159047fSniklas     md_number_to_chars (RecLen, Object_Record_Offset, 2);
5162159047fSniklas     if (write (VMS_Object_File_FD, RecLen, 2) != 2)
517f7cc78ecSespie       error (_("I/O error writing VMS object file (length prefix)"));
5182159047fSniklas     /* We also need to force the actual record to be an even number of
5192159047fSniklas        bytes.  For native output, that's automatic; when cross-assembling,
5202159047fSniklas        pad with a NUL byte if length is odd.  Do so _after_ writing the
5212159047fSniklas        pre-padded length.  Since our buffer is defined with even size,
5222159047fSniklas        an odd offset implies that it has some room left.  */
5232159047fSniklas     if ((Object_Record_Offset & 1) != 0)
5242159047fSniklas       Object_Record_Buffer[Object_Record_Offset++] = '\0';
5252159047fSniklas   }
5262159047fSniklas #endif /* not VMS */
5272159047fSniklas 
5282159047fSniklas   /* Write the data to the file.  */
529c074d1c9Sdrahn   if ((size_t) write (VMS_Object_File_FD, Object_Record_Buffer,
530c074d1c9Sdrahn 		      Object_Record_Offset) != Object_Record_Offset)
531f7cc78ecSespie     error (_("I/O error writing VMS object file"));
5322159047fSniklas 
5332159047fSniklas   /* The buffer is now empty.  */
5342159047fSniklas   Object_Record_Offset = 0;
5352159047fSniklas }
5362159047fSniklas 
5372159047fSniklas /* Declare a particular type of object file record.  */
5382159047fSniklas 
5392159047fSniklas static void
Set_VMS_Object_File_Record(int Type)540*007c2a45Smiod Set_VMS_Object_File_Record (int Type)
5412159047fSniklas {
5422159047fSniklas   /* If the type matches, we are done.  */
5432159047fSniklas   if (Type == Current_Object_Record_Type)
5442159047fSniklas     return;
5452159047fSniklas   /* Otherwise: flush the buffer.  */
5462159047fSniklas   Flush_VMS_Object_Record_Buffer ();
5472159047fSniklas   /* Remember the new type.  */
5482159047fSniklas   Current_Object_Record_Type = Type;
5492159047fSniklas }
5502159047fSniklas 
5512159047fSniklas /* Close the VMS Object file.  */
5522159047fSniklas 
5532159047fSniklas static void
Close_VMS_Object_File(void)554*007c2a45Smiod Close_VMS_Object_File (void)
5552159047fSniklas {
5562159047fSniklas   /* Flush (should never be necessary) and reset saved record-type context.  */
5572159047fSniklas   Set_VMS_Object_File_Record (-1);
5582159047fSniklas 
5592159047fSniklas #ifndef VMS			/* For cross-assembly purposes.  */
5602159047fSniklas   {
5612159047fSniklas     char RecLen[2];
5622159047fSniklas     int minus_one = -1;
5632159047fSniklas 
5642159047fSniklas     /* Write a 2 byte record-length field of -1 into the file, which
5652159047fSniklas        means end-of-block when read, hence end-of-file when occurring
5662159047fSniklas        in the file's last block.  It is only needed for variable-length
5672159047fSniklas        record files transferred to VMS as fixed-length record files
5682159047fSniklas        (typical for binary FTP; NFS shouldn't need it, but it won't hurt).  */
5692159047fSniklas     md_number_to_chars (RecLen, minus_one, 2);
5702159047fSniklas     write (VMS_Object_File_FD, RecLen, 2);
5712159047fSniklas   }
5722159047fSniklas #else
5732159047fSniklas     /* When written on a VMS system, the file header (cf inode) will record
5742159047fSniklas        the actual end-of-file position and no inline marker is needed.  */
5752159047fSniklas #endif
5762159047fSniklas 
5772159047fSniklas   close (VMS_Object_File_FD);
5782159047fSniklas }
5792159047fSniklas 
580*007c2a45Smiod /* Text Information and Relocation routines. */
5812159047fSniklas 
5822159047fSniklas /* Stack Psect base followed by signed, varying-sized offset.
5832159047fSniklas    Common to several object records.  */
5842159047fSniklas 
5852159047fSniklas static void
vms_tir_stack_psect(int Psect_Index,int Offset,int Force)586*007c2a45Smiod vms_tir_stack_psect (int Psect_Index, int Offset, int Force)
5872159047fSniklas {
5882159047fSniklas   int psect_width, offset_width;
5892159047fSniklas 
5902159047fSniklas   psect_width = ((unsigned) Psect_Index > 255) ? 2 : 1;
5912159047fSniklas   offset_width = (Force || Offset > 32767 || Offset < -32768) ? 4
5922159047fSniklas 		 : (Offset > 127 || Offset < -128) ? 2 : 1;
5932159047fSniklas #define Sta_P(p,o) (((o)<<1) | ((p)-1))
594*007c2a45Smiod   /* Byte or word psect; byte, word, or longword offset.  */
5952159047fSniklas   switch (Sta_P(psect_width,offset_width))
5962159047fSniklas     {
5972159047fSniklas       case Sta_P(1,1):	PUT_CHAR (TIR_S_C_STA_PB);
5982159047fSniklas 			PUT_CHAR ((char) (unsigned char) Psect_Index);
5992159047fSniklas 			PUT_CHAR ((char) Offset);
6002159047fSniklas 			break;
6012159047fSniklas       case Sta_P(1,2):	PUT_CHAR (TIR_S_C_STA_PW);
6022159047fSniklas 			PUT_CHAR ((char) (unsigned char) Psect_Index);
6032159047fSniklas 			PUT_SHORT (Offset);
6042159047fSniklas 			break;
6052159047fSniklas       case Sta_P(1,4):	PUT_CHAR (TIR_S_C_STA_PL);
6062159047fSniklas 			PUT_CHAR ((char) (unsigned char) Psect_Index);
6072159047fSniklas 			PUT_LONG (Offset);
6082159047fSniklas 			break;
6092159047fSniklas       case Sta_P(2,1):	PUT_CHAR (TIR_S_C_STA_WPB);
6102159047fSniklas 			PUT_SHORT (Psect_Index);
6112159047fSniklas 			PUT_CHAR ((char) Offset);
6122159047fSniklas 			break;
6132159047fSniklas       case Sta_P(2,2):	PUT_CHAR (TIR_S_C_STA_WPW);
6142159047fSniklas 			PUT_SHORT (Psect_Index);
6152159047fSniklas 			PUT_SHORT (Offset);
6162159047fSniklas 			break;
6172159047fSniklas       case Sta_P(2,4):	PUT_CHAR (TIR_S_C_STA_WPL);
6182159047fSniklas 			PUT_SHORT (Psect_Index);
6192159047fSniklas 			PUT_LONG (Offset);
6202159047fSniklas 			break;
6212159047fSniklas     }
6222159047fSniklas #undef Sta_P
6232159047fSniklas }
6242159047fSniklas 
6252159047fSniklas /* Store immediate data in current Psect.  */
6262159047fSniklas 
6272159047fSniklas static void
VMS_Store_Immediate_Data(const char * Pointer,int Size,int Record_Type)628*007c2a45Smiod VMS_Store_Immediate_Data (const char *Pointer, int Size, int Record_Type)
6292159047fSniklas {
630*007c2a45Smiod   int i;
6312159047fSniklas 
6322159047fSniklas   Set_VMS_Object_File_Record (Record_Type);
6332159047fSniklas   /* We can only store as most 128 bytes at a time due to the way that
6342159047fSniklas      TIR commands are encoded.  */
6352159047fSniklas   while (Size > 0)
6362159047fSniklas     {
6372159047fSniklas       i = (Size > 128) ? 128 : Size;
6382159047fSniklas       Size -= i;
6392159047fSniklas       /* If we cannot accommodate this record, flush the buffer.  */
6402159047fSniklas       if ((Object_Record_Offset + i + 1) >= sizeof Object_Record_Buffer)
6412159047fSniklas 	Flush_VMS_Object_Record_Buffer ();
6422159047fSniklas       /* If the buffer is empty we must insert record type.  */
6432159047fSniklas       if (Object_Record_Offset == 0)
6442159047fSniklas 	PUT_CHAR (Record_Type);
6452159047fSniklas       /* Store the count.  The Store Immediate TIR command is implied by
6462159047fSniklas          a negative command byte, and the length of the immediate data
6472159047fSniklas          is abs(command_byte).  So, we write the negated length value.  */
6482159047fSniklas       PUT_CHAR ((char) (-i & 0xff));
6492159047fSniklas       /* Now store the data.  */
6502159047fSniklas       while (--i >= 0)
6512159047fSniklas 	PUT_CHAR (*Pointer++);
6522159047fSniklas     }
6532159047fSniklas   /* Flush the buffer if it is more than 75% full.  */
6542159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
6552159047fSniklas     Flush_VMS_Object_Record_Buffer ();
6562159047fSniklas }
6572159047fSniklas 
6582159047fSniklas /* Make a data reference.  */
6592159047fSniklas 
6602159047fSniklas static void
VMS_Set_Data(int Psect_Index,int Offset,int Record_Type,int Force)661*007c2a45Smiod VMS_Set_Data (int Psect_Index, int Offset, int Record_Type, int Force)
6622159047fSniklas {
6632159047fSniklas   Set_VMS_Object_File_Record (Record_Type);
6642159047fSniklas   /* If the buffer is empty we must insert the record type.  */
6652159047fSniklas   if (Object_Record_Offset == 0)
6662159047fSniklas     PUT_CHAR (Record_Type);
6672159047fSniklas   /* Stack the Psect base with its offset.  */
6682159047fSniklas   vms_tir_stack_psect (Psect_Index, Offset, Force);
6692159047fSniklas   /* Set relocation base.  */
6702159047fSniklas   PUT_CHAR (TIR_S_C_STO_PIDR);
6712159047fSniklas   /* Flush the buffer if it is more than 75% full.  */
6722159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
6732159047fSniklas     Flush_VMS_Object_Record_Buffer ();
6742159047fSniklas }
6752159047fSniklas 
6762159047fSniklas /* Make a debugger reference to a struct, union or enum.  */
6772159047fSniklas 
6782159047fSniklas static void
VMS_Store_Struct(int Struct_Index)679*007c2a45Smiod VMS_Store_Struct (int Struct_Index)
6802159047fSniklas {
6812159047fSniklas   /* We are writing a debug record.  */
6822159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_DBG);
6832159047fSniklas   /* If the buffer is empty we must insert the record type.  */
6842159047fSniklas   if (Object_Record_Offset == 0)
6852159047fSniklas     PUT_CHAR (OBJ_S_C_DBG);
6862159047fSniklas   PUT_CHAR (TIR_S_C_STA_UW);
6872159047fSniklas   PUT_SHORT (Struct_Index);
6882159047fSniklas   PUT_CHAR (TIR_S_C_CTL_STKDL);
6892159047fSniklas   PUT_CHAR (TIR_S_C_STO_L);
6902159047fSniklas   /* Flush the buffer if it is more than 75% full.  */
6912159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
6922159047fSniklas     Flush_VMS_Object_Record_Buffer ();
6932159047fSniklas }
6942159047fSniklas 
6952159047fSniklas /* Make a debugger reference to partially define a struct, union or enum.  */
6962159047fSniklas 
6972159047fSniklas static void
VMS_Def_Struct(int Struct_Index)698*007c2a45Smiod VMS_Def_Struct (int Struct_Index)
6992159047fSniklas {
7002159047fSniklas   /* We are writing a debug record.  */
7012159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_DBG);
7022159047fSniklas   /* If the buffer is empty we must insert the record type.  */
7032159047fSniklas   if (Object_Record_Offset == 0)
7042159047fSniklas     PUT_CHAR (OBJ_S_C_DBG);
7052159047fSniklas   PUT_CHAR (TIR_S_C_STA_UW);
7062159047fSniklas   PUT_SHORT (Struct_Index);
7072159047fSniklas   PUT_CHAR (TIR_S_C_CTL_DFLOC);
7082159047fSniklas   /* Flush the buffer if it is more than 75% full.  */
7092159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
7102159047fSniklas     Flush_VMS_Object_Record_Buffer ();
7112159047fSniklas }
7122159047fSniklas 
7132159047fSniklas static void
VMS_Set_Struct(int Struct_Index)714*007c2a45Smiod VMS_Set_Struct (int Struct_Index)
715*007c2a45Smiod {
7162159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_DBG);
7172159047fSniklas   if (Object_Record_Offset == 0)
7182159047fSniklas     PUT_CHAR (OBJ_S_C_DBG);
7192159047fSniklas   PUT_CHAR (TIR_S_C_STA_UW);
7202159047fSniklas   PUT_SHORT (Struct_Index);
7212159047fSniklas   PUT_CHAR (TIR_S_C_CTL_STLOC);
7222159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
7232159047fSniklas     Flush_VMS_Object_Record_Buffer ();
7242159047fSniklas }
7252159047fSniklas 
726*007c2a45Smiod /* Traceback Information routines.  */
7272159047fSniklas 
7282159047fSniklas /* Write the Traceback Module Begin record.  */
7292159047fSniklas 
7302159047fSniklas static void
VMS_TBT_Module_Begin(void)731*007c2a45Smiod VMS_TBT_Module_Begin (void)
7322159047fSniklas {
733*007c2a45Smiod   char *cp, *cp1;
7342159047fSniklas   int Size;
7352159047fSniklas   char Local[256];
7362159047fSniklas 
7372159047fSniklas   /* Arrange to store the data locally (leave room for size byte).  */
7382159047fSniklas   cp = &Local[1];
7392159047fSniklas   /* Begin module.  */
7402159047fSniklas   *cp++ = DST_S_C_MODBEG;
7412159047fSniklas   *cp++ = 0;		/* flags; not used */
742*007c2a45Smiod   /* Language type == "C"
743*007c2a45Smiod     (FIXME:  this should be based on the input...)  */
7442159047fSniklas   COPY_LONG (cp, DST_S_C_C);
7452159047fSniklas   cp += 4;
7462159047fSniklas   /* Store the module name.  */
7472159047fSniklas   *cp++ = (char) strlen (Module_Name);
7482159047fSniklas   cp1 = Module_Name;
7492159047fSniklas   while (*cp1)
7502159047fSniklas     *cp++ = *cp1++;
7512159047fSniklas   /* Now we can store the record size.  */
7522159047fSniklas   Size = (cp - Local);
7532159047fSniklas   Local[0] = Size - 1;
7542159047fSniklas   /* Put it into the object record.  */
7552159047fSniklas   VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
7562159047fSniklas }
7572159047fSniklas 
7582159047fSniklas /* Write the Traceback Module End record.  */
7592159047fSniklas 
7602159047fSniklas static void
VMS_TBT_Module_End(void)761*007c2a45Smiod VMS_TBT_Module_End (void)
7622159047fSniklas {
7632159047fSniklas   char Local[2];
7642159047fSniklas 
7652159047fSniklas   /* End module.  */
7662159047fSniklas   Local[0] = 1;
7672159047fSniklas   Local[1] = DST_S_C_MODEND;
7682159047fSniklas   /* Put it into the object record.  */
7692159047fSniklas   VMS_Store_Immediate_Data (Local, 2, OBJ_S_C_TBT);
7702159047fSniklas }
7712159047fSniklas 
7722159047fSniklas /* Write a Traceback Routine Begin record.  */
7732159047fSniklas 
7742159047fSniklas static void
VMS_TBT_Routine_Begin(symbolS * symbolP,int Psect)775*007c2a45Smiod VMS_TBT_Routine_Begin (symbolS *symbolP, int Psect)
7762159047fSniklas {
777*007c2a45Smiod   char *cp, *cp1;
7782159047fSniklas   char *Name;
7792159047fSniklas   int Offset;
7802159047fSniklas   int Size;
7812159047fSniklas   char Local[512];
7822159047fSniklas 
7832159047fSniklas   /* Strip the leading "_" from the name.  */
7842159047fSniklas   Name = S_GET_NAME (symbolP);
7852159047fSniklas   if (*Name == '_')
7862159047fSniklas     Name++;
7872159047fSniklas   /* Get the text psect offset.  */
7882159047fSniklas   Offset = S_GET_VALUE (symbolP);
7892159047fSniklas   /* Set the record size.  */
7902159047fSniklas   Size = 1 + 1 + 4 + 1 + strlen (Name);
7912159047fSniklas   Local[0] = Size;
7922159047fSniklas   /* DST type "routine begin".  */
7932159047fSniklas   Local[1] = DST_S_C_RTNBEG;
7942159047fSniklas   /* Uses CallS/CallG.  */
7952159047fSniklas   Local[2] = 0;
7962159047fSniklas   /* Store the data so far.  */
7972159047fSniklas   VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
7982159047fSniklas   /* Make sure we are still generating a OBJ_S_C_TBT record.  */
7992159047fSniklas   if (Object_Record_Offset == 0)
8002159047fSniklas     PUT_CHAR (OBJ_S_C_TBT);
8012159047fSniklas   /* Stack the address.  */
8022159047fSniklas   vms_tir_stack_psect (Psect, Offset, 0);
8032159047fSniklas   /* Store the data reference.  */
8042159047fSniklas   PUT_CHAR (TIR_S_C_STO_PIDR);
8052159047fSniklas   /* Store the counted string as data.  */
8062159047fSniklas   cp = Local;
8072159047fSniklas   cp1 = Name;
8082159047fSniklas   Size = strlen (cp1) + 1;
8092159047fSniklas   *cp++ = Size - 1;
8102159047fSniklas   while (*cp1)
8112159047fSniklas     *cp++ = *cp1++;
8122159047fSniklas   VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_TBT);
8132159047fSniklas }
8142159047fSniklas 
8152159047fSniklas /* Write a Traceback Routine End record.
8162159047fSniklas 
8172159047fSniklas    We *must* search the symbol table to find the next routine, since the
818*007c2a45Smiod    assembler has a way of reassembling the symbol table OUT OF ORDER Thus
8192159047fSniklas    the next routine in the symbol list is not necessarily the next one in
8202159047fSniklas    memory.  For debugging to work correctly we must know the size of the
8212159047fSniklas    routine.  */
8222159047fSniklas 
8232159047fSniklas static void
VMS_TBT_Routine_End(int Max_Size,symbolS * sp)824*007c2a45Smiod VMS_TBT_Routine_End (int Max_Size, symbolS *sp)
8252159047fSniklas {
8262159047fSniklas   symbolS *symbolP;
827c074d1c9Sdrahn   unsigned long Size = 0x7fffffff;
8282159047fSniklas   char Local[16];
8292159047fSniklas   valueT sym_value, sp_value = S_GET_VALUE (sp);
8302159047fSniklas 
8312159047fSniklas   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
8322159047fSniklas     {
8332159047fSniklas       if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
8342159047fSniklas 	{
8352159047fSniklas 	  if (*S_GET_NAME (symbolP) == 'L')
8362159047fSniklas 	    continue;
8372159047fSniklas 	  sym_value = S_GET_VALUE (symbolP);
8382159047fSniklas 	  if (sym_value > sp_value && sym_value < Size)
8392159047fSniklas 	    Size = sym_value;
8402159047fSniklas 
841*007c2a45Smiod 	  /* Dummy labels like "gcc_compiled." should no longer reach here.  */
8422159047fSniklas #if 0
8432159047fSniklas 	  else
844*007c2a45Smiod 	    /* Check if gcc_compiled. has size of zero.  */
8452159047fSniklas 	    if (sym_value == sp_value &&
8462159047fSniklas 		sp != symbolP &&
8472159047fSniklas 		(!strcmp (S_GET_NAME (sp), "gcc_compiled.") ||
8482159047fSniklas 		 !strcmp (S_GET_NAME (sp), "gcc2_compiled.")))
8492159047fSniklas 	      Size = sym_value;
8502159047fSniklas #endif
8512159047fSniklas 	}
8522159047fSniklas     }
8532159047fSniklas   if (Size == 0x7fffffff)
8542159047fSniklas     Size = Max_Size;
8552159047fSniklas   Size -= sp_value;		/* and get the size of the routine */
8562159047fSniklas   /* Record Size.  */
8572159047fSniklas   Local[0] = 6;
8582159047fSniklas   /* DST type is "routine end".  */
8592159047fSniklas   Local[1] = DST_S_C_RTNEND;
8602159047fSniklas   Local[2] = 0;		/* unused */
8612159047fSniklas   /* Size of routine.  */
8622159047fSniklas   COPY_LONG (&Local[3], Size);
8632159047fSniklas   /* Store the record.  */
8642159047fSniklas   VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
8652159047fSniklas }
8662159047fSniklas 
8672159047fSniklas /* Write a Traceback Block Begin record.  */
8682159047fSniklas 
8692159047fSniklas static void
VMS_TBT_Block_Begin(symbolS * symbolP,int Psect,char * Name)870*007c2a45Smiod VMS_TBT_Block_Begin (symbolS *symbolP, int Psect, char *Name)
8712159047fSniklas {
872*007c2a45Smiod   char *cp, *cp1;
8732159047fSniklas   int Offset;
8742159047fSniklas   int Size;
8752159047fSniklas   char Local[512];
8762159047fSniklas 
8772159047fSniklas   /* Set the record size.  */
8782159047fSniklas   Size = 1 + 1 + 4 + 1 + strlen (Name);
8792159047fSniklas   Local[0] = Size;
8802159047fSniklas   /* DST type is "begin block"; we simulate with a phony routine.  */
8812159047fSniklas   Local[1] = DST_S_C_BLKBEG;
8822159047fSniklas   /* Uses CallS/CallG.  */
8832159047fSniklas   Local[2] = 0;
8842159047fSniklas   /* Store the data so far.  */
8852159047fSniklas   VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_DBG);
8862159047fSniklas   /* Make sure we are still generating a debug record.  */
8872159047fSniklas   if (Object_Record_Offset == 0)
8882159047fSniklas     PUT_CHAR (OBJ_S_C_DBG);
8892159047fSniklas   /* Now get the symbol address.  */
8902159047fSniklas   PUT_CHAR (TIR_S_C_STA_WPL);
8912159047fSniklas   PUT_SHORT (Psect);
8922159047fSniklas   /* Get the text psect offset.  */
8932159047fSniklas   Offset = S_GET_VALUE (symbolP);
8942159047fSniklas   PUT_LONG (Offset);
8952159047fSniklas   /* Store the data reference.  */
8962159047fSniklas   PUT_CHAR (TIR_S_C_STO_PIDR);
8972159047fSniklas   /* Store the counted string as data.  */
8982159047fSniklas   cp = Local;
8992159047fSniklas   cp1 = Name;
9002159047fSniklas   Size = strlen (cp1) + 1;
9012159047fSniklas   *cp++ = Size - 1;
9022159047fSniklas   while (*cp1)
9032159047fSniklas     *cp++ = *cp1++;
9042159047fSniklas   VMS_Store_Immediate_Data (Local, Size, OBJ_S_C_DBG);
9052159047fSniklas }
9062159047fSniklas 
9072159047fSniklas /* Write a Traceback Block End record.  */
9082159047fSniklas 
9092159047fSniklas static void
VMS_TBT_Block_End(valueT Size)910*007c2a45Smiod VMS_TBT_Block_End (valueT Size)
9112159047fSniklas {
9122159047fSniklas   char Local[16];
9132159047fSniklas 
9142159047fSniklas   Local[0] = 6;		/* record length */
9152159047fSniklas   /* DST type is "block end"; simulate with a phony end routine.  */
9162159047fSniklas   Local[1] = DST_S_C_BLKEND;
9172159047fSniklas   Local[2] = 0;		/* unused, must be zero */
9182159047fSniklas   COPY_LONG (&Local[3], Size);
9192159047fSniklas   VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_DBG);
9202159047fSniklas }
9212159047fSniklas 
9222159047fSniklas 
9232159047fSniklas /* Write a Line number <-> Program Counter correlation record.  */
9242159047fSniklas 
9252159047fSniklas static void
VMS_TBT_Line_PC_Correlation(int Line_Number,int Offset,int Psect,int Do_Delta)926*007c2a45Smiod VMS_TBT_Line_PC_Correlation (int Line_Number, int Offset,
927*007c2a45Smiod 			     int Psect, int Do_Delta)
9282159047fSniklas {
929*007c2a45Smiod   char *cp;
9302159047fSniklas   char Local[64];
9312159047fSniklas 
9322159047fSniklas   if (Do_Delta == 0)
9332159047fSniklas     {
934*007c2a45Smiod       /* If not delta, set our PC/Line number correlation.  */
9352159047fSniklas       cp = &Local[1];	/* Put size in Local[0] later.  */
9362159047fSniklas       /* DST type is "Line Number/PC correlation".  */
9372159047fSniklas       *cp++ = DST_S_C_LINE_NUM;
9382159047fSniklas       /* Set Line number.  */
9392159047fSniklas       if (Line_Number - 1 <= 255)
9402159047fSniklas 	{
9412159047fSniklas 	  *cp++ = DST_S_C_SET_LINUM_B;
9422159047fSniklas 	  *cp++ = (char) (Line_Number - 1);
9432159047fSniklas 	}
9442159047fSniklas       else if (Line_Number - 1 <= 65535)
9452159047fSniklas 	{
9462159047fSniklas 	  *cp++ = DST_S_C_SET_LINE_NUM;
9472159047fSniklas 	  COPY_SHORT (cp, Line_Number - 1),  cp += 2;
9482159047fSniklas 	}
9492159047fSniklas       else
9502159047fSniklas 	{
9512159047fSniklas 	  *cp++ = DST_S_C_SET_LINUM_L;
9522159047fSniklas 	  COPY_LONG (cp, Line_Number - 1),  cp += 4;
9532159047fSniklas 	}
9542159047fSniklas       /* Set PC.  */
9552159047fSniklas       *cp++ = DST_S_C_SET_ABS_PC;
9562159047fSniklas       /* Store size now that we know it, then output the data.  */
9572159047fSniklas       Local[0] = cp - &Local[1];
9582159047fSniklas 	/* Account for the space that TIR_S_C_STO_PIDR will use for the PC.  */
9592159047fSniklas 	Local[0] += 4;		/* size includes length of another longword */
9602159047fSniklas       VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
9612159047fSniklas       /* Make sure we are still generating a OBJ_S_C_TBT record.  */
9622159047fSniklas       if (Object_Record_Offset == 0)
9632159047fSniklas 	PUT_CHAR (OBJ_S_C_TBT);
9642159047fSniklas       vms_tir_stack_psect (Psect, Offset, 0);
9652159047fSniklas       PUT_CHAR (TIR_S_C_STO_PIDR);
9662159047fSniklas       /* Do a PC offset of 0 to register the line number.  */
9672159047fSniklas       Local[0] = 2;
9682159047fSniklas       Local[1] = DST_S_C_LINE_NUM;
9692159047fSniklas       Local[2] = 0;		/* Increment PC by 0 and register line # */
9702159047fSniklas       VMS_Store_Immediate_Data (Local, 3, OBJ_S_C_TBT);
9712159047fSniklas     }
9722159047fSniklas   else
9732159047fSniklas     {
9742159047fSniklas       if (Do_Delta < 0)
9752159047fSniklas 	{
976*007c2a45Smiod 	  /* When delta is negative, terminate the line numbers.  */
9772159047fSniklas 	  Local[0] = 1 + 1 + 4;
9782159047fSniklas 	  Local[1] = DST_S_C_LINE_NUM;
9792159047fSniklas 	  Local[2] = DST_S_C_TERM_L;
9802159047fSniklas 	  COPY_LONG (&Local[3], Offset);
9812159047fSniklas 	  VMS_Store_Immediate_Data (Local, 7, OBJ_S_C_TBT);
9822159047fSniklas 	  return;
9832159047fSniklas 	}
984*007c2a45Smiod       /* Do a PC/Line delta.  */
9852159047fSniklas       cp = &Local[1];
9862159047fSniklas       *cp++ = DST_S_C_LINE_NUM;
9872159047fSniklas       if (Line_Number > 1)
9882159047fSniklas 	{
9892159047fSniklas 	  /* We need to increment the line number.  */
9902159047fSniklas 	  if (Line_Number - 1 <= 255)
9912159047fSniklas 	    {
9922159047fSniklas 	      *cp++ = DST_S_C_INCR_LINUM;
9932159047fSniklas 	      *cp++ = Line_Number - 1;
9942159047fSniklas 	    }
9952159047fSniklas 	  else if (Line_Number - 1 <= 65535)
9962159047fSniklas 	    {
9972159047fSniklas 	      *cp++ = DST_S_C_INCR_LINUM_W;
9982159047fSniklas 	      COPY_SHORT (cp, Line_Number - 1),  cp += 2;
9992159047fSniklas 	    }
10002159047fSniklas 	  else
10012159047fSniklas 	    {
10022159047fSniklas 	      *cp++ = DST_S_C_INCR_LINUM_L;
10032159047fSniklas 	      COPY_LONG (cp, Line_Number - 1),  cp += 4;
10042159047fSniklas 	    }
10052159047fSniklas 	}
1006*007c2a45Smiod       /* Increment the PC.  */
10072159047fSniklas       if (Offset <= 128)
10082159047fSniklas 	{
10092159047fSniklas 	  /* Small offsets are encoded as negative numbers, rather than the
10102159047fSniklas 	     usual non-negative type code followed by another data field.  */
10112159047fSniklas 	  *cp++ = (char) -Offset;
10122159047fSniklas 	}
10132159047fSniklas       else if (Offset <= 65535)
10142159047fSniklas 	{
10152159047fSniklas 	  *cp++ = DST_S_C_DELTA_PC_W;
10162159047fSniklas 	  COPY_SHORT (cp, Offset),  cp += 2;
10172159047fSniklas 	}
10182159047fSniklas       else
10192159047fSniklas 	{
10202159047fSniklas 	  *cp++ = DST_S_C_DELTA_PC_L;
10212159047fSniklas 	  COPY_LONG (cp, Offset),  cp += 4;
10222159047fSniklas 	}
10232159047fSniklas       /* Set size now that be know it, then output the data.  */
10242159047fSniklas       Local[0] = cp - &Local[1];
10252159047fSniklas       VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
10262159047fSniklas     }
10272159047fSniklas }
10282159047fSniklas 
10292159047fSniklas 
10302159047fSniklas /* Describe a source file to the debugger.  */
10312159047fSniklas 
10322159047fSniklas static int
VMS_TBT_Source_File(char * Filename,int ID_Number)1033*007c2a45Smiod VMS_TBT_Source_File (char *Filename, int ID_Number)
10342159047fSniklas {
1035*007c2a45Smiod   char *cp;
10362159047fSniklas   int len, rfo, ffb, ebk;
10372159047fSniklas   char cdt[8];
10382159047fSniklas   char Local[512];
10392159047fSniklas #ifdef VMS			/* Used for native assembly */
10402159047fSniklas   unsigned Status;
10412159047fSniklas   struct FAB fab;		/* RMS file access block */
10422159047fSniklas   struct NAM nam;		/* file name information */
10432159047fSniklas   struct XABDAT xabdat;		/* date+time fields */
10442159047fSniklas   struct XABFHC xabfhc;		/* file header characteristics */
10452159047fSniklas   char resultant_string_buffer[255 + 1];
10462159047fSniklas 
1047*007c2a45Smiod   /* Set up RMS structures:  */
10482159047fSniklas   /* FAB -- file access block */
10492159047fSniklas   memset ((char *) &fab, 0, sizeof fab);
10502159047fSniklas   fab.fab$b_bid = FAB$C_BID;
10512159047fSniklas   fab.fab$b_bln = (unsigned char) sizeof fab;
10522159047fSniklas   fab.fab$l_fna = Filename;
10532159047fSniklas   fab.fab$b_fns = (unsigned char) strlen (Filename);
10542159047fSniklas   fab.fab$l_nam = (char *) &nam;
10552159047fSniklas   fab.fab$l_xab = (char *) &xabdat;
1056*007c2a45Smiod   /* NAM -- file name block.  */
10572159047fSniklas   memset ((char *) &nam, 0, sizeof nam);
10582159047fSniklas   nam.nam$b_bid = NAM$C_BID;
10592159047fSniklas   nam.nam$b_bln = (unsigned char) sizeof nam;
10602159047fSniklas   nam.nam$l_rsa = resultant_string_buffer;
10612159047fSniklas   nam.nam$b_rss = (unsigned char) (sizeof resultant_string_buffer - 1);
1062*007c2a45Smiod   /* XABs -- extended attributes blocks.  */
10632159047fSniklas   memset ((char *) &xabdat, 0, sizeof xabdat);
10642159047fSniklas   xabdat.xab$b_cod = XAB$C_DAT;
10652159047fSniklas   xabdat.xab$b_bln = (unsigned char) sizeof xabdat;
10662159047fSniklas   xabdat.xab$l_nxt = (char *) &xabfhc;
10672159047fSniklas   memset ((char *) &xabfhc, 0, sizeof xabfhc);
10682159047fSniklas   xabfhc.xab$b_cod = XAB$C_FHC;
10692159047fSniklas   xabfhc.xab$b_bln = (unsigned char) sizeof xabfhc;
10702159047fSniklas   xabfhc.xab$l_nxt = 0;
1071*007c2a45Smiod 
1072*007c2a45Smiod   /* Get the file information.  */
10732159047fSniklas   Status = sys$open (&fab);
10742159047fSniklas   if (!(Status & 1))
10752159047fSniklas     {
1076f7cc78ecSespie       as_tsktsk (_("Couldn't find source file \"%s\", status=%%X%x"),
10772159047fSniklas 		 Filename, Status);
10782159047fSniklas       return 0;
10792159047fSniklas     }
10802159047fSniklas   sys$close (&fab);
10812159047fSniklas   /* Now extract fields of interest.  */
10822159047fSniklas   memcpy (cdt, (char *) &xabdat.xab$q_cdt, 8);	/* creation date */
10832159047fSniklas   ebk = xabfhc.xab$l_ebk;		/* end-of-file block */
10842159047fSniklas   ffb = xabfhc.xab$w_ffb;		/* first free byte of last block */
10852159047fSniklas   rfo = xabfhc.xab$b_rfo;		/* record format */
10862159047fSniklas   len = nam.nam$b_rsl;			/* length of Filename */
10872159047fSniklas   resultant_string_buffer[len] = '\0';
10882159047fSniklas   Filename = resultant_string_buffer;	/* full filename */
10892159047fSniklas #else				/* Cross-assembly */
10902159047fSniklas   /* [Perhaps we ought to use actual values derived from stat() here?]  */
10912159047fSniklas   memset (cdt, 0, 8);			/* null VMS quadword binary time */
10922159047fSniklas   ebk = ffb = rfo = 0;
10932159047fSniklas   len = strlen (Filename);
10942159047fSniklas   if (len > 255)	/* a single byte is used as count prefix */
10952159047fSniklas     {
10962159047fSniklas       Filename += (len - 255);		/* tail end is more significant */
10972159047fSniklas       len = 255;
10982159047fSniklas     }
10992159047fSniklas #endif /* VMS */
11002159047fSniklas 
11012159047fSniklas   cp = &Local[1];			/* fill in record length later */
11022159047fSniklas   *cp++ = DST_S_C_SOURCE;		/* DST type is "source file" */
11032159047fSniklas   *cp++ = DST_S_C_SRC_FORMFEED;		/* formfeeds count as source records */
11042159047fSniklas   *cp++ = DST_S_C_SRC_DECLFILE;		/* declare source file */
11052159047fSniklas   know (cp == &Local[4]);
11062159047fSniklas   *cp++ = 0;				/* fill in this length below */
11072159047fSniklas   *cp++ = 0;				/* flags; must be zero */
11082159047fSniklas   COPY_SHORT (cp, ID_Number),  cp += 2;	/* file ID number */
11092159047fSniklas   memcpy (cp, cdt, 8),  cp += 8;	/* creation date+time */
11102159047fSniklas   COPY_LONG (cp, ebk),  cp += 4;	/* end-of-file block */
11112159047fSniklas   COPY_SHORT (cp, ffb),  cp += 2;	/* first free byte of last block */
11122159047fSniklas   *cp++ = (char) rfo;			/* RMS record format */
11132159047fSniklas   /* Filename.  */
11142159047fSniklas   *cp++ = (char) len;
11152159047fSniklas   while (--len >= 0)
11162159047fSniklas     *cp++ = *Filename++;
11172159047fSniklas   /* Library module name (none).  */
11182159047fSniklas   *cp++ = 0;
11192159047fSniklas   /* Now that size is known, fill it in and write out the record.  */
11202159047fSniklas   Local[4] = cp - &Local[5];		/* source file declaration size */
11212159047fSniklas   Local[0] = cp - &Local[1];		/* TBT record size */
11222159047fSniklas   VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
11232159047fSniklas   return 1;
11242159047fSniklas }
11252159047fSniklas 
11262159047fSniklas /* Traceback information is described in terms of lines from compiler
11272159047fSniklas    listing files, not lines from source files.  We need to set up the
11282159047fSniklas    correlation between listing line numbers and source line numbers.
11292159047fSniklas    Since gcc's .stabn directives refer to the source lines, we just
11302159047fSniklas    need to describe a one-to-one correspondence.  */
11312159047fSniklas 
11322159047fSniklas static void
VMS_TBT_Source_Lines(int ID_Number,int Starting_Line_Number,int Number_Of_Lines)1133*007c2a45Smiod VMS_TBT_Source_Lines (int ID_Number, int Starting_Line_Number,
1134*007c2a45Smiod 		      int Number_Of_Lines)
11352159047fSniklas {
11362159047fSniklas   char *cp;
11372159047fSniklas   int chunk_limit;
11382159047fSniklas   char Local[128];	/* room enough to describe 1310700 lines...  */
11392159047fSniklas 
11402159047fSniklas   cp = &Local[1];	/* Put size in Local[0] later.  */
11412159047fSniklas   *cp++ = DST_S_C_SOURCE;		/* DST type is "source file".  */
11422159047fSniklas   *cp++ = DST_S_C_SRC_SETFILE;		/* Set Source File.  */
11432159047fSniklas   COPY_SHORT (cp, ID_Number),  cp += 2;	/* File ID Number.  */
11442159047fSniklas   /* Set record number and define lines.  Since no longword form of
11452159047fSniklas      SRC_DEFLINES is available, we need to be able to cope with any huge
11462159047fSniklas      files a chunk at a time.  It doesn't matter for tracebacks, since
11472159047fSniklas      unspecified lines are mapped one-to-one and work out right, but it
11482159047fSniklas      does matter within the debugger.  Without this explicit mapping,
11492159047fSniklas      it will complain about lines not existing in the module.  */
11502159047fSniklas   chunk_limit = (sizeof Local - 5) / 6;
11512159047fSniklas   if (Number_Of_Lines > 65535 * chunk_limit)	/* avoid buffer overflow */
11522159047fSniklas     Number_Of_Lines = 65535 * chunk_limit;
11532159047fSniklas   while (Number_Of_Lines > 65535)
11542159047fSniklas     {
11552159047fSniklas       *cp++ = DST_S_C_SRC_SETREC_L;
11562159047fSniklas       COPY_LONG (cp, Starting_Line_Number),  cp += 4;
11572159047fSniklas       *cp++ = DST_S_C_SRC_DEFLINES_W;
11582159047fSniklas       COPY_SHORT (cp, 65535),  cp += 2;
11592159047fSniklas       Starting_Line_Number += 65535;
11602159047fSniklas       Number_Of_Lines -= 65535;
11612159047fSniklas     }
11622159047fSniklas   /* Set record number and define lines, normal case.  */
11632159047fSniklas   if (Starting_Line_Number <= 65535)
11642159047fSniklas     {
11652159047fSniklas       *cp++ = DST_S_C_SRC_SETREC_W;
11662159047fSniklas       COPY_SHORT (cp, Starting_Line_Number),  cp += 2;
11672159047fSniklas     }
11682159047fSniklas   else
11692159047fSniklas     {
11702159047fSniklas       *cp++ = DST_S_C_SRC_SETREC_L;
11712159047fSniklas       COPY_LONG (cp, Starting_Line_Number),  cp += 4;
11722159047fSniklas     }
11732159047fSniklas   *cp++ = DST_S_C_SRC_DEFLINES_W;
11742159047fSniklas   COPY_SHORT (cp, Number_Of_Lines),  cp += 2;
11752159047fSniklas   /* Set size now that be know it, then output the data.  */
11762159047fSniklas   Local[0] = cp - &Local[1];
11772159047fSniklas   VMS_Store_Immediate_Data (Local, cp - Local, OBJ_S_C_TBT);
11782159047fSniklas }
11792159047fSniklas 
11802159047fSniklas 
1181*007c2a45Smiod /* Debugger Information support routines. */
11822159047fSniklas 
11832159047fSniklas /* This routine locates a file in the list of files.  If an entry does
11842159047fSniklas    not exist, one is created.  For include files, a new entry is always
11852159047fSniklas    created such that inline functions can be properly debugged.  */
11862159047fSniklas 
11872159047fSniklas static struct input_file *
find_file(symbolS * sp)1188*007c2a45Smiod find_file (symbolS *sp)
11892159047fSniklas {
11902159047fSniklas   struct input_file *same_file = 0;
11912159047fSniklas   struct input_file *fpnt, *last = 0;
11922159047fSniklas   char *sp_name;
11932159047fSniklas 
11942159047fSniklas   for (fpnt = file_root; fpnt; fpnt = fpnt->next)
11952159047fSniklas     {
11962159047fSniklas       if (fpnt->spnt == sp)
11972159047fSniklas 	return fpnt;
11982159047fSniklas       last = fpnt;
11992159047fSniklas     }
12002159047fSniklas   sp_name = S_GET_NAME (sp);
12012159047fSniklas   for (fpnt = file_root; fpnt; fpnt = fpnt->next)
12022159047fSniklas     {
12032159047fSniklas       if (strcmp (sp_name, fpnt->name) == 0)
12042159047fSniklas 	{
12052159047fSniklas 	  if (fpnt->flag == 1)
12062159047fSniklas 	    return fpnt;
12072159047fSniklas 	  same_file = fpnt;
12082159047fSniklas 	  break;
12092159047fSniklas 	}
12102159047fSniklas     }
1211*007c2a45Smiod   fpnt = xmalloc (sizeof (struct input_file));
12122159047fSniklas   if (!file_root)
12132159047fSniklas     file_root = fpnt;
12142159047fSniklas   else
12152159047fSniklas     last->next = fpnt;
12162159047fSniklas   fpnt->next = 0;
12172159047fSniklas   fpnt->name = sp_name;
12182159047fSniklas   fpnt->min_line = 0x7fffffff;
12192159047fSniklas   fpnt->max_line = 0;
12202159047fSniklas   fpnt->offset = 0;
12212159047fSniklas   fpnt->flag = 0;
12222159047fSniklas   fpnt->file_number = 0;
12232159047fSniklas   fpnt->spnt = sp;
12242159047fSniklas   fpnt->same_file_fpnt = same_file;
12252159047fSniklas   return fpnt;
12262159047fSniklas }
12272159047fSniklas 
12282159047fSniklas /* This routine converts a number string into an integer, and stops when
12292159047fSniklas    it sees an invalid character.  The return value is the address of the
12302159047fSniklas    character just past the last character read.  No error is generated.  */
12312159047fSniklas 
12322159047fSniklas static char *
cvt_integer(char * str,int * rtn)1233*007c2a45Smiod cvt_integer (char *str, int *rtn)
12342159047fSniklas {
12352159047fSniklas   int ival = 0, sgn = 1;
12362159047fSniklas 
12372159047fSniklas   if (*str == '-')
12382159047fSniklas     sgn = -1,  ++str;
12392159047fSniklas   while (*str >= '0' && *str <= '9')
12402159047fSniklas     ival = 10 * ival + *str++ - '0';
12412159047fSniklas   *rtn = sgn * ival;
12422159047fSniklas   return str;
12432159047fSniklas }
12442159047fSniklas 
12452159047fSniklas 
1246*007c2a45Smiod /* The following functions and definitions are used to generate object
1247*007c2a45Smiod    records that will describe program variables to the VMS debugger.
1248*007c2a45Smiod 
1249*007c2a45Smiod    This file contains many of the routines needed to output debugging info
1250*007c2a45Smiod    into the object file that the VMS debugger needs to understand symbols.
1251*007c2a45Smiod    These routines are called very late in the assembly process, and thus
1252*007c2a45Smiod    we can be fairly lax about changing things, since the GSD and the TIR
1253*007c2a45Smiod    sections have already been output.  */
12542159047fSniklas 
12552159047fSniklas /* This routine fixes the names that are generated by C++, ".this" is a good
12562159047fSniklas    example.  The period does not work for the debugger, since it looks like
12572159047fSniklas    the syntax for a structure element, and thus it gets mightily confused.
12582159047fSniklas 
12592159047fSniklas    We also use this to strip the PsectAttribute hack from the name before we
12602159047fSniklas    write a debugger record.  */
12612159047fSniklas 
12622159047fSniklas static char *
fix_name(char * pnt)1263*007c2a45Smiod fix_name (char *pnt)
12642159047fSniklas {
12652159047fSniklas   char *pnt1;
12662159047fSniklas 
12672159047fSniklas   /* Kill any leading "_".  */
12682159047fSniklas   if (*pnt == '_')
12692159047fSniklas     pnt++;
12702159047fSniklas 
12712159047fSniklas   /* Is there a Psect Attribute to skip??  */
12722159047fSniklas   if (HAS_PSECT_ATTRIBUTES (pnt))
12732159047fSniklas     {
12742159047fSniklas       /* Yes: Skip it.  */
12752159047fSniklas       pnt += PSECT_ATTRIBUTES_STRING_LENGTH;
12762159047fSniklas       while (*pnt)
12772159047fSniklas 	{
12782159047fSniklas 	  if ((pnt[0] == '$') && (pnt[1] == '$'))
12792159047fSniklas 	    {
12802159047fSniklas 	      pnt += 2;
12812159047fSniklas 	      break;
12822159047fSniklas 	    }
12832159047fSniklas 	  pnt++;
12842159047fSniklas 	}
12852159047fSniklas     }
12862159047fSniklas 
12872159047fSniklas   /* Here we fix the .this -> $this conversion.  */
12882159047fSniklas   for (pnt1 = pnt; *pnt1 != 0; pnt1++)
12892159047fSniklas     if (*pnt1 == '.')
12902159047fSniklas       *pnt1 = '$';
12912159047fSniklas 
12922159047fSniklas   return pnt;
12932159047fSniklas }
12942159047fSniklas 
12952159047fSniklas /* When defining a structure, this routine is called to find the name of
12962159047fSniklas    the actual structure.  It is assumed that str points to the equal sign
12972159047fSniklas    in the definition, and it moves backward until it finds the start of the
12982159047fSniklas    name.  If it finds a 0, then it knows that this structure def is in the
12992159047fSniklas    outermost level, and thus symbol_name points to the symbol name.  */
13002159047fSniklas 
13012159047fSniklas static char *
get_struct_name(char * str)1302*007c2a45Smiod get_struct_name (char *str)
13032159047fSniklas {
13042159047fSniklas   char *pnt;
13052159047fSniklas   pnt = str;
13062159047fSniklas   while ((*pnt != ':') && (*pnt != '\0'))
13072159047fSniklas     pnt--;
13082159047fSniklas   if (*pnt == '\0')
13092159047fSniklas     return (char *) symbol_name;
13102159047fSniklas   *pnt-- = '\0';
13112159047fSniklas   while ((*pnt != ';') && (*pnt != '='))
13122159047fSniklas     pnt--;
13132159047fSniklas   if (*pnt == ';')
13142159047fSniklas     return pnt + 1;
13152159047fSniklas   while ((*pnt < '0') || (*pnt > '9'))
13162159047fSniklas     pnt++;
13172159047fSniklas   while ((*pnt >= '0') && (*pnt <= '9'))
13182159047fSniklas     pnt++;
13192159047fSniklas   return pnt;
13202159047fSniklas }
13212159047fSniklas 
13222159047fSniklas /* Search symbol list for type number dbx_type.
13232159047fSniklas    Return a pointer to struct.  */
13242159047fSniklas 
13252159047fSniklas static struct VMS_DBG_Symbol *
find_symbol(int dbx_type)1326*007c2a45Smiod find_symbol (int dbx_type)
13272159047fSniklas {
13282159047fSniklas   struct VMS_DBG_Symbol *spnt;
13292159047fSniklas 
13302159047fSniklas   spnt = VMS_Symbol_type_list[SYMTYP_HASH (dbx_type)];
13312159047fSniklas   while (spnt)
13322159047fSniklas     {
13332159047fSniklas       if (spnt->dbx_type == dbx_type)
13342159047fSniklas 	break;
13352159047fSniklas       spnt = spnt->next;
13362159047fSniklas     }
13372159047fSniklas   if (!spnt || spnt->advanced != ALIAS)
13382159047fSniklas     return spnt;
13392159047fSniklas   return find_symbol (spnt->type2);
13402159047fSniklas }
13412159047fSniklas 
13422159047fSniklas #if 0		/* obsolete */
1343*007c2a45Smiod /* This routine puts info into either Local or Asuffix, depending on the sign
1344*007c2a45Smiod    of size.  The reason is that it is easier to build the variable descriptor
1345*007c2a45Smiod    backwards, while the array descriptor is best built forwards.  In the end
1346*007c2a45Smiod    they get put together, if there is not a struct/union/enum along the way.  */
1347*007c2a45Smiod 
13482159047fSniklas static void
1349*007c2a45Smiod push (int value, int size1)
13502159047fSniklas {
13512159047fSniklas   if (size1 < 0)
13522159047fSniklas     {
13532159047fSniklas       size1 = -size1;
13542159047fSniklas       if (Lpnt < size1)
13552159047fSniklas 	{
13562159047fSniklas 	  overflow = 1;
13572159047fSniklas 	  Lpnt = 1;
13582159047fSniklas 	  return;
13592159047fSniklas 	}
13602159047fSniklas       Lpnt -= size1;
13612159047fSniklas       md_number_to_chars (&Local[Lpnt + 1], value, size1);
13622159047fSniklas     }
13632159047fSniklas   else
13642159047fSniklas     {
13652159047fSniklas       if (Apoint + size1 >= MAX_DEBUG_RECORD)
13662159047fSniklas 	{
13672159047fSniklas 	  overflow = 1;
13682159047fSniklas 	  Apoint = MAX_DEBUG_RECORD - 1;
13692159047fSniklas 	  return;
13702159047fSniklas 	}
13712159047fSniklas       md_number_to_chars (&Asuffix[Apoint], value, size1);
13722159047fSniklas       Apoint += size1;
13732159047fSniklas     }
13742159047fSniklas }
13752159047fSniklas #endif
13762159047fSniklas 
13772159047fSniklas static void
fpush(int value,int size)1378*007c2a45Smiod fpush (int value, int size)
13792159047fSniklas {
13802159047fSniklas   if (Apoint + size >= MAX_DEBUG_RECORD)
13812159047fSniklas     {
13822159047fSniklas       overflow = 1;
13832159047fSniklas       Apoint = MAX_DEBUG_RECORD - 1;
13842159047fSniklas       return;
13852159047fSniklas     }
13862159047fSniklas   if (size == 1)
13872159047fSniklas     Asuffix[Apoint++] = (char) value;
13882159047fSniklas   else
13892159047fSniklas     {
13902159047fSniklas       md_number_to_chars (&Asuffix[Apoint], value, size);
13912159047fSniklas       Apoint += size;
13922159047fSniklas     }
13932159047fSniklas }
13942159047fSniklas 
13952159047fSniklas static void
rpush(int value,int size)1396*007c2a45Smiod rpush (int value, int size)
13972159047fSniklas {
13982159047fSniklas   if (Lpnt < size)
13992159047fSniklas     {
14002159047fSniklas       overflow = 1;
14012159047fSniklas       Lpnt = 1;
14022159047fSniklas       return;
14032159047fSniklas     }
14042159047fSniklas   if (size == 1)
14052159047fSniklas       Local[Lpnt--] = (char) value;
14062159047fSniklas   else
14072159047fSniklas     {
14082159047fSniklas       Lpnt -= size;
14092159047fSniklas       md_number_to_chars (&Local[Lpnt + 1], value, size);
14102159047fSniklas     }
14112159047fSniklas }
14122159047fSniklas 
14132159047fSniklas /* This routine generates the array descriptor for a given array.  */
14142159047fSniklas 
14152159047fSniklas static void
array_suffix(struct VMS_DBG_Symbol * spnt2)1416*007c2a45Smiod array_suffix (struct VMS_DBG_Symbol *spnt2)
14172159047fSniklas {
14182159047fSniklas   struct VMS_DBG_Symbol *spnt;
14192159047fSniklas   struct VMS_DBG_Symbol *spnt1;
14202159047fSniklas   int rank;
14212159047fSniklas   int total_size;
14222159047fSniklas 
14232159047fSniklas   rank = 0;
14242159047fSniklas   spnt = spnt2;
14252159047fSniklas   while (spnt->advanced != ARRAY)
14262159047fSniklas     {
14272159047fSniklas       spnt = find_symbol (spnt->type2);
14282159047fSniklas       if (!spnt)
14292159047fSniklas 	return;
14302159047fSniklas     }
14312159047fSniklas   spnt1 = spnt;
14322159047fSniklas   total_size = 1;
14332159047fSniklas   while (spnt1->advanced == ARRAY)
14342159047fSniklas     {
14352159047fSniklas       rank++;
14362159047fSniklas       total_size *= (spnt1->index_max - spnt1->index_min + 1);
14372159047fSniklas       spnt1 = find_symbol (spnt1->type2);
14382159047fSniklas     }
14392159047fSniklas   total_size = total_size * spnt1->data_size;
14402159047fSniklas   fpush (spnt1->data_size, 2);	/* element size */
14412159047fSniklas   if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
14422159047fSniklas     fpush (0, 1);
14432159047fSniklas   else
14442159047fSniklas     fpush (spnt1->VMS_type, 1);	/* element type */
14452159047fSniklas   fpush (DSC_K_CLASS_A, 1);	/* descriptor class */
14462159047fSniklas   fpush (0, 4);			/* base address */
14472159047fSniklas   fpush (0, 1);			/* scale factor -- not applicable */
14482159047fSniklas   fpush (0, 1);			/* digit count -- not applicable */
14492159047fSniklas   fpush (0xc0, 1);		/* flags: multiplier block & bounds present */
14502159047fSniklas   fpush (rank, 1);		/* number of dimensions */
14512159047fSniklas   fpush (total_size, 4);
14522159047fSniklas   fpush (0, 4);			/* pointer to element [0][0]...[0] */
14532159047fSniklas   spnt1 = spnt;
14542159047fSniklas   while (spnt1->advanced == ARRAY)
14552159047fSniklas     {
14562159047fSniklas       fpush (spnt1->index_max - spnt1->index_min + 1, 4);
14572159047fSniklas       spnt1 = find_symbol (spnt1->type2);
14582159047fSniklas     }
14592159047fSniklas   spnt1 = spnt;
14602159047fSniklas   while (spnt1->advanced == ARRAY)
14612159047fSniklas     {
14622159047fSniklas       fpush (spnt1->index_min, 4);
14632159047fSniklas       fpush (spnt1->index_max, 4);
14642159047fSniklas       spnt1 = find_symbol (spnt1->type2);
14652159047fSniklas     }
14662159047fSniklas }
14672159047fSniklas 
14682159047fSniklas /* This routine generates the start of a variable descriptor based upon
14692159047fSniklas    a struct/union/enum that has yet to be defined.  We define this spot as
14702159047fSniklas    a new location, and save four bytes for the address.  When the struct is
14712159047fSniklas    finally defined, then we can go back and plug in the correct address.  */
14722159047fSniklas 
14732159047fSniklas static void
new_forward_ref(int dbx_type)1474*007c2a45Smiod new_forward_ref (int dbx_type)
14752159047fSniklas {
14762159047fSniklas   struct forward_ref *fpnt;
1477*007c2a45Smiod 
1478*007c2a45Smiod   fpnt = xmalloc (sizeof (struct forward_ref));
14792159047fSniklas   fpnt->next = f_ref_root;
14802159047fSniklas   f_ref_root = fpnt;
14812159047fSniklas   fpnt->dbx_type = dbx_type;
14822159047fSniklas   fpnt->struc_numb = ++structure_count;
14832159047fSniklas   fpnt->resolved = 'N';
14842159047fSniklas   rpush (DST_K_TS_IND, 1);	/* indirect type specification */
14852159047fSniklas   total_len = 5;
14862159047fSniklas   rpush (total_len, 2);
14872159047fSniklas   struct_number = -fpnt->struc_numb;
14882159047fSniklas }
14892159047fSniklas 
14902159047fSniklas /* This routine generates the variable descriptor used to describe non-basic
14912159047fSniklas    variables.  It calls itself recursively until it gets to the bottom of it
14922159047fSniklas    all, and then builds the descriptor backwards.  It is easiest to do it
14932159047fSniklas    this way since we must periodically write length bytes, and it is easiest
14942159047fSniklas    if we know the value when it is time to write it.  */
14952159047fSniklas 
14962159047fSniklas static int
gen1(struct VMS_DBG_Symbol * spnt,int array_suffix_len)1497*007c2a45Smiod gen1 (struct VMS_DBG_Symbol *spnt, int array_suffix_len)
14982159047fSniklas {
14992159047fSniklas   struct VMS_DBG_Symbol *spnt1;
15002159047fSniklas   int i;
15012159047fSniklas 
15022159047fSniklas   switch (spnt->advanced)
15032159047fSniklas     {
15042159047fSniklas     case VOID:
15052159047fSniklas       rpush (DBG_S_C_VOID, 1);
15062159047fSniklas       total_len += 1;
15072159047fSniklas       rpush (total_len, 2);
15082159047fSniklas       return 0;
15092159047fSniklas     case BASIC:
15102159047fSniklas     case FUNCTION:
15112159047fSniklas       if (array_suffix_len == 0)
15122159047fSniklas 	{
15132159047fSniklas 	  rpush (spnt->VMS_type, 1);
15142159047fSniklas 	  rpush (DBG_S_C_BASIC, 1);
15152159047fSniklas 	  total_len = 2;
15162159047fSniklas 	  rpush (total_len, 2);
15172159047fSniklas 	  return 1;
15182159047fSniklas 	}
15192159047fSniklas       rpush (0, 4);
15202159047fSniklas       rpush (DST_K_VFLAGS_DSC, 1);
1521*007c2a45Smiod       rpush (DST_K_TS_DSC, 1);	/* Descriptor type specification.  */
15222159047fSniklas       total_len = -2;
15232159047fSniklas       return 1;
15242159047fSniklas     case STRUCT:
15252159047fSniklas     case UNION:
15262159047fSniklas     case ENUM:
15272159047fSniklas       struct_number = spnt->struc_numb;
15282159047fSniklas       if (struct_number < 0)
15292159047fSniklas 	{
15302159047fSniklas 	  new_forward_ref (spnt->dbx_type);
15312159047fSniklas 	  return 1;
15322159047fSniklas 	}
15332159047fSniklas       rpush (DBG_S_C_STRUCT, 1);
15342159047fSniklas       total_len = 5;
15352159047fSniklas       rpush (total_len, 2);
15362159047fSniklas       return 1;
15372159047fSniklas     case POINTER:
15382159047fSniklas       spnt1 = find_symbol (spnt->type2);
15392159047fSniklas       i = 1;
15402159047fSniklas       if (!spnt1)
15412159047fSniklas 	new_forward_ref (spnt->type2);
15422159047fSniklas       else
15432159047fSniklas 	i = gen1 (spnt1, 0);
15442159047fSniklas       if (i)
1545*007c2a45Smiod 	{
1546*007c2a45Smiod 	  /* (*void) is a special case, do not put pointer suffix.  */
15472159047fSniklas 	  rpush (DBG_S_C_POINTER, 1);
15482159047fSniklas 	  total_len += 3;
15492159047fSniklas 	  rpush (total_len, 2);
15502159047fSniklas 	}
15512159047fSniklas       return 1;
15522159047fSniklas     case ARRAY:
15532159047fSniklas       spnt1 = spnt;
15542159047fSniklas       while (spnt1->advanced == ARRAY)
15552159047fSniklas 	{
15562159047fSniklas 	  spnt1 = find_symbol (spnt1->type2);
15572159047fSniklas 	  if (!spnt1)
15582159047fSniklas 	    {
1559f7cc78ecSespie 	      as_tsktsk (_("debugger forward reference error, dbx type %d"),
15602159047fSniklas 			 spnt->type2);
15612159047fSniklas 	      return 0;
15622159047fSniklas 	    }
15632159047fSniklas 	}
1564*007c2a45Smiod       /* It is too late to generate forward references, so the user
1565*007c2a45Smiod 	 gets a message.  This should only happen on a compiler error.  */
15662159047fSniklas       (void) gen1 (spnt1, 1);
15672159047fSniklas       i = Apoint;
15682159047fSniklas       array_suffix (spnt);
15692159047fSniklas       array_suffix_len = Apoint - i;
15702159047fSniklas       switch (spnt1->advanced)
15712159047fSniklas 	{
15722159047fSniklas 	case BASIC:
15732159047fSniklas 	case FUNCTION:
15742159047fSniklas 	  break;
15752159047fSniklas 	default:
15762159047fSniklas 	  rpush (0, 2);
15772159047fSniklas 	  total_len += 2;
15782159047fSniklas 	  rpush (total_len, 2);
15792159047fSniklas 	  rpush (DST_K_VFLAGS_DSC, 1);
1580*007c2a45Smiod 	  rpush (1, 1);		/* Flags: element value spec included.  */
1581*007c2a45Smiod 	  rpush (1, 1);		/* One dimension.  */
15822159047fSniklas 	  rpush (DBG_S_C_COMPLEX_ARRAY, 1);
15832159047fSniklas 	}
15842159047fSniklas       total_len += array_suffix_len + 8;
15852159047fSniklas       rpush (total_len, 2);
15862159047fSniklas       break;
1587*007c2a45Smiod     default:
15882159047fSniklas       break;
15892159047fSniklas     }
15902159047fSniklas   return 0;
15912159047fSniklas }
15922159047fSniklas 
15932159047fSniklas /* This generates a suffix for a variable.  If it is not a defined type yet,
15942159047fSniklas    then dbx_type contains the type we are expecting so we can generate a
15952159047fSniklas    forward reference.  This calls gen1 to build most of the descriptor, and
15962159047fSniklas    then it puts the icing on at the end.  It then dumps whatever is needed
15972159047fSniklas    to get a complete descriptor (i.e. struct reference, array suffix).  */
15982159047fSniklas 
15992159047fSniklas static void
generate_suffix(struct VMS_DBG_Symbol * spnt,int dbx_type)1600*007c2a45Smiod generate_suffix (struct VMS_DBG_Symbol *spnt, int dbx_type)
16012159047fSniklas {
1602*007c2a45Smiod   static const char pvoid[6] =
1603*007c2a45Smiod     {
16042159047fSniklas       5,		/* record.length == 5 */
16052159047fSniklas       DST_K_TYPSPEC,	/* record.type == 1 (type specification) */
16062159047fSniklas       0,		/* name.length == 0, no name follows */
16072159047fSniklas       1, 0,		/* type.length == 1 {2 bytes, little endian} */
16082159047fSniklas       DBG_S_C_VOID	/* type.type == 5 (pointer to unspecified) */
16092159047fSniklas     };
16102159047fSniklas   int i;
16112159047fSniklas 
16122159047fSniklas   Apoint = 0;
16132159047fSniklas   Lpnt = MAX_DEBUG_RECORD - 1;
16142159047fSniklas   total_len = 0;
16152159047fSniklas   struct_number = 0;
16162159047fSniklas   overflow = 0;
16172159047fSniklas   if (!spnt)
16182159047fSniklas     new_forward_ref (dbx_type);
16192159047fSniklas   else
16202159047fSniklas     {
16212159047fSniklas       if (spnt->VMS_type != DBG_S_C_ADVANCED_TYPE)
16222159047fSniklas 	return;		/* no suffix needed */
16232159047fSniklas       gen1 (spnt, 0);
16242159047fSniklas     }
16252159047fSniklas   rpush (0, 1);		/* no name (len==0) */
16262159047fSniklas   rpush (DST_K_TYPSPEC, 1);
16272159047fSniklas   total_len += 4;
16282159047fSniklas   rpush (total_len, 1);
16292159047fSniklas   /* If the variable descriptor overflows the record, output a descriptor
16302159047fSniklas      for a pointer to void.  */
16312159047fSniklas   if ((total_len >= MAX_DEBUG_RECORD) || overflow)
16322159047fSniklas     {
1633f7cc78ecSespie       as_warn (_("Variable descriptor %d too complicated.  Defined as `void *'."),
16342159047fSniklas 		spnt->dbx_type);
16352159047fSniklas       VMS_Store_Immediate_Data (pvoid, 6, OBJ_S_C_DBG);
16362159047fSniklas       return;
16372159047fSniklas     }
16382159047fSniklas   i = 0;
16392159047fSniklas   while (Lpnt < MAX_DEBUG_RECORD - 1)
16402159047fSniklas     Local[i++] = Local[++Lpnt];
16412159047fSniklas   Lpnt = i;
1642*007c2a45Smiod   /* We use this for reference to structure that has already been defined.  */
16432159047fSniklas   if (struct_number > 0)
16442159047fSniklas     {
16452159047fSniklas       VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
16462159047fSniklas       Lpnt = 0;
16472159047fSniklas       VMS_Store_Struct (struct_number);
16482159047fSniklas     }
16492159047fSniklas   /* We use this for a forward reference to a structure that has yet to
16502159047fSniklas      be defined.  We store four bytes of zero to make room for the actual
16512159047fSniklas      address once it is known.  */
16522159047fSniklas   if (struct_number < 0)
16532159047fSniklas     {
16542159047fSniklas       struct_number = -struct_number;
16552159047fSniklas       VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
16562159047fSniklas       Lpnt = 0;
16572159047fSniklas       VMS_Def_Struct (struct_number);
16582159047fSniklas       COPY_LONG (&Local[Lpnt], 0L);
16592159047fSniklas       Lpnt += 4;
16602159047fSniklas       VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
16612159047fSniklas       Lpnt = 0;
16622159047fSniklas     }
16632159047fSniklas   i = 0;
16642159047fSniklas   while (i < Apoint)
16652159047fSniklas     Local[Lpnt++] = Asuffix[i++];
16662159047fSniklas   if (Lpnt != 0)
16672159047fSniklas     VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
16682159047fSniklas   Lpnt = 0;
16692159047fSniklas }
16702159047fSniklas 
1671*007c2a45Smiod /* "novel length" type doesn't work for simple atomic types.  */
16722159047fSniklas #define USE_BITSTRING_DESCRIPTOR(t) ((t)->advanced == BASIC)
16732159047fSniklas #undef SETUP_BASIC_TYPES
16742159047fSniklas 
16752159047fSniklas /* This routine generates a type description for a bitfield.  */
16762159047fSniklas 
16772159047fSniklas static void
bitfield_suffix(struct VMS_DBG_Symbol * spnt,int width)1678*007c2a45Smiod bitfield_suffix (struct VMS_DBG_Symbol *spnt, int width)
16792159047fSniklas {
16802159047fSniklas   Local[Lpnt++] = 13;			/* rec.len==13 */
16812159047fSniklas   Local[Lpnt++] = DST_K_TYPSPEC;	/* a type specification record */
16822159047fSniklas   Local[Lpnt++] = 0;			/* not named */
16832159047fSniklas   COPY_SHORT (&Local[Lpnt], 9);		/* typ.len==9 */
16842159047fSniklas   Lpnt += 2;
16852159047fSniklas   Local[Lpnt++] = DST_K_TS_NOV_LENG;	/* This type is a "novel length"
16862159047fSniklas 					   incarnation of some other type.  */
16872159047fSniklas   COPY_LONG (&Local[Lpnt], width);	/* size in bits == novel length */
16882159047fSniklas   Lpnt += 4;
16892159047fSniklas   VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
16902159047fSniklas   Lpnt = 0;
16912159047fSniklas   /* assert( spnt->struc_numb > 0 ); */
16922159047fSniklas   VMS_Store_Struct (spnt->struc_numb);	/* output 4 more bytes */
16932159047fSniklas }
16942159047fSniklas 
16952159047fSniklas /* Formally define a builtin type, so that it can serve as the target of
16962159047fSniklas    an indirect reference.  It makes bitfield_suffix() easier by avoiding
16972159047fSniklas    the need to use a forward reference for the first occurrence of each
16982159047fSniklas    type used in a bitfield.  */
16992159047fSniklas 
17002159047fSniklas static void
setup_basic_type(struct VMS_DBG_Symbol * spnt ATTRIBUTE_UNUSED)1701*007c2a45Smiod setup_basic_type (struct VMS_DBG_Symbol *spnt ATTRIBUTE_UNUSED)
17022159047fSniklas {
17032159047fSniklas #ifdef SETUP_BASIC_TYPES
17042159047fSniklas   /* This would be very useful if "novel length" fields actually worked
17052159047fSniklas      with basic types like they do with enumerated types.  However,
17062159047fSniklas      they do not, so this isn't worth doing just so that you can use
17072159047fSniklas      EXAMINE/TYPE=(__long_long_int) instead of EXAMINE/QUAD.  */
17082159047fSniklas   char *p;
17092159047fSniklas #ifndef SETUP_SYNONYM_TYPES
17102159047fSniklas   /* This determines whether compatible things like `int' and `long int'
17112159047fSniklas      ought to have distinct type records rather than sharing one.  */
17122159047fSniklas   struct VMS_DBG_Symbol *spnt2;
17132159047fSniklas 
1714*007c2a45Smiod   /* First check whether this type has already been seen by another name.  */
17152159047fSniklas   for (spnt2 = VMS_Symbol_type_list[SYMTYP_HASH (spnt->VMS_type)];
17162159047fSniklas        spnt2;
17172159047fSniklas        spnt2 = spnt2->next)
17182159047fSniklas     if (spnt2 != spnt && spnt2->VMS_type == spnt->VMS_type)
17192159047fSniklas       {
17202159047fSniklas 	spnt->struc_numb = spnt2->struc_numb;
17212159047fSniklas 	return;
17222159047fSniklas       }
17232159047fSniklas #endif
17242159047fSniklas 
17252159047fSniklas   /* `structure number' doesn't really mean `structure'; it means an index
17262159047fSniklas      into a linker maintained set of saved locations which can be referenced
17272159047fSniklas      again later.  */
17282159047fSniklas   spnt->struc_numb = ++structure_count;
17292159047fSniklas   VMS_Def_Struct (spnt->struc_numb);	/* remember where this type lives */
17302159047fSniklas   /* define the simple scalar type */
17312159047fSniklas   Local[Lpnt++] = 6 + strlen (symbol_name) + 2;	/* rec.len */
17322159047fSniklas   Local[Lpnt++] = DST_K_TYPSPEC;	/* rec.typ==type specification */
17332159047fSniklas   Local[Lpnt++] = strlen (symbol_name) + 2;
17342159047fSniklas   Local[Lpnt++] = '_';			/* prefix name with "__" */
17352159047fSniklas   Local[Lpnt++] = '_';
17362159047fSniklas   for (p = symbol_name; *p; p++)
17372159047fSniklas     Local[Lpnt++] = *p == ' ' ? '_' : *p;
17382159047fSniklas   COPY_SHORT (&Local[Lpnt], 2);		/* typ.len==2 */
17392159047fSniklas   Lpnt += 2;
17402159047fSniklas   Local[Lpnt++] = DST_K_TS_ATOM;	/* typ.kind is simple type */
17412159047fSniklas   Local[Lpnt++] = spnt->VMS_type;	/* typ.type */
17422159047fSniklas   VMS_Store_Immediate_Data (Local, Lpnt, OBJ_S_C_DBG);
17432159047fSniklas   Lpnt = 0;
17442159047fSniklas #endif	/* SETUP_BASIC_TYPES */
17452159047fSniklas }
17462159047fSniklas 
1747*007c2a45Smiod /* This routine generates a symbol definition for a C symbol for the
1748*007c2a45Smiod    debugger.  It takes a psect and offset for global symbols; if psect < 0,
1749*007c2a45Smiod    then this is a local variable and the offset is relative to FP.  In this
1750*007c2a45Smiod    case it can be either a variable (Offset < 0) or a parameter (Offset > 0).  */
17512159047fSniklas 
17522159047fSniklas static void
VMS_DBG_record(struct VMS_DBG_Symbol * spnt,int Psect,int Offset,char * Name)1753*007c2a45Smiod VMS_DBG_record (struct VMS_DBG_Symbol *spnt, int Psect,
1754*007c2a45Smiod 		int Offset, char *Name)
17552159047fSniklas {
17562159047fSniklas   char *Name_pnt;
17572159047fSniklas   int len;
17582159047fSniklas   int i = 0;
17592159047fSniklas 
1760*007c2a45Smiod   /* If there are bad characters in name, convert them.  */
17612159047fSniklas   Name_pnt = fix_name (Name);
17622159047fSniklas 
17632159047fSniklas   len = strlen (Name_pnt);
17642159047fSniklas   if (Psect < 0)
1765*007c2a45Smiod     {
1766*007c2a45Smiod       /* This is a local variable, referenced to SP.  */
17672159047fSniklas       Local[i++] = 7 + len;
17682159047fSniklas       Local[i++] = spnt->VMS_type;
17692159047fSniklas       Local[i++] = (Offset > 0) ? DBG_C_FUNCTION_PARAM : DBG_C_LOCAL_SYM;
17702159047fSniklas       COPY_LONG (&Local[i], Offset);
17712159047fSniklas       i += 4;
17722159047fSniklas     }
17732159047fSniklas   else
17742159047fSniklas     {
17752159047fSniklas       Local[i++] = 7 + len;
17762159047fSniklas       Local[i++] = spnt->VMS_type;
17772159047fSniklas       Local[i++] = DST_K_VALKIND_ADDR;
17782159047fSniklas       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
17792159047fSniklas       i = 0;
17802159047fSniklas       VMS_Set_Data (Psect, Offset, OBJ_S_C_DBG, 0);
17812159047fSniklas     }
17822159047fSniklas   Local[i++] = len;
17832159047fSniklas   while (*Name_pnt != '\0')
17842159047fSniklas     Local[i++] = *Name_pnt++;
17852159047fSniklas   VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
17862159047fSniklas   if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
17872159047fSniklas     generate_suffix (spnt, 0);
17882159047fSniklas }
17892159047fSniklas 
17902159047fSniklas /* This routine parses the stabs entries in order to make the definition
17912159047fSniklas    for the debugger of local symbols and function parameters.  */
17922159047fSniklas 
17932159047fSniklas static void
VMS_local_stab_Parse(symbolS * sp)1794*007c2a45Smiod VMS_local_stab_Parse (symbolS *sp)
17952159047fSniklas {
17962159047fSniklas   struct VMS_DBG_Symbol *spnt;
17972159047fSniklas   char *pnt;
17982159047fSniklas   char *pnt1;
17992159047fSniklas   char *str;
18002159047fSniklas   int dbx_type;
18012159047fSniklas 
18022159047fSniklas   dbx_type = 0;
18032159047fSniklas   str = S_GET_NAME (sp);
18042159047fSniklas   pnt = (char *) strchr (str, ':');
18052159047fSniklas   if (!pnt)
1806*007c2a45Smiod     return;
18072159047fSniklas 
1808*007c2a45Smiod   /* Save this for later, and skip colon.  */
1809*007c2a45Smiod   pnt1 = pnt++;
1810*007c2a45Smiod 
1811*007c2a45Smiod   /* Ignore static constants.  */
1812*007c2a45Smiod   if (*pnt == 'c')
1813*007c2a45Smiod     return;
1814*007c2a45Smiod 
1815*007c2a45Smiod   /* There is one little catch that we must be aware of.  Sometimes function
1816*007c2a45Smiod      parameters are optimized into registers, and the compiler, in its
1817*007c2a45Smiod      infiite wisdom outputs stabs records for *both*.  In general we want to
1818*007c2a45Smiod      use the register if it is present, so we must search the rest of the
1819*007c2a45Smiod      symbols for this function to see if this parameter is assigned to a
1820*007c2a45Smiod      register.  */
18212159047fSniklas   {
18222159047fSniklas     symbolS *sp1;
18232159047fSniklas     char *str1;
18242159047fSniklas     char *pnt2;
18252159047fSniklas 
18262159047fSniklas     if (*pnt == 'p')
18272159047fSniklas       {
18282159047fSniklas 	for (sp1 = symbol_next (sp); sp1; sp1 = symbol_next (sp1))
18292159047fSniklas 	  {
18302159047fSniklas 	    if (!S_IS_DEBUG (sp1))
18312159047fSniklas 	      continue;
18322159047fSniklas 	    if (S_GET_RAW_TYPE (sp1) == N_FUN)
18332159047fSniklas 	      {
18342159047fSniklas 		pnt2 = (char *) strchr (S_GET_NAME (sp1), ':') + 1;
18352159047fSniklas 		if (*pnt2 == 'F' || *pnt2 == 'f')
18362159047fSniklas 		  break;
18372159047fSniklas 	      }
18382159047fSniklas 	    if (S_GET_RAW_TYPE (sp1) != N_RSYM)
18392159047fSniklas 	      continue;
18402159047fSniklas 	    str1 = S_GET_NAME (sp1);	/* and get the name */
18412159047fSniklas 	    pnt2 = str;
18422159047fSniklas 	    while (*pnt2 != ':')
18432159047fSniklas 	      {
18442159047fSniklas 		if (*pnt2 != *str1)
18452159047fSniklas 		  break;
18462159047fSniklas 		pnt2++;
18472159047fSniklas 		str1++;
18482159047fSniklas 	      }
18492159047fSniklas 	    if (*str1 == ':' && *pnt2 == ':')
1850b55d4692Sfgsch 	      return;	/* They are the same!  Let's skip this one.  */
1851*007c2a45Smiod 	  }
1852*007c2a45Smiod 
1853*007c2a45Smiod 	/* Skip p in case no register.  */
1854*007c2a45Smiod 	pnt++;
1855*007c2a45Smiod       }
1856*007c2a45Smiod   }
18572159047fSniklas 
18582159047fSniklas   pnt = cvt_integer (pnt, &dbx_type);
1859*007c2a45Smiod 
18602159047fSniklas   spnt = find_symbol (dbx_type);
18612159047fSniklas   if (!spnt)
1862*007c2a45Smiod     /* Dunno what this is.  */
1863*007c2a45Smiod     return;
1864*007c2a45Smiod 
18652159047fSniklas   *pnt1 = '\0';
18662159047fSniklas   VMS_DBG_record (spnt, -1, S_GET_VALUE (sp), str);
1867*007c2a45Smiod 
1868*007c2a45Smiod   /* ...and restore the string.  */
1869*007c2a45Smiod   *pnt1 = ':';
18702159047fSniklas }
18712159047fSniklas 
18722159047fSniklas /* This routine parses a stabs entry to find the information required
18732159047fSniklas    to define a variable.  It is used for global and static variables.
18742159047fSniklas    Basically we need to know the address of the symbol.  With older
18752159047fSniklas    versions of the compiler, const symbols are treated differently, in
18762159047fSniklas    that if they are global they are written into the text psect.  The
18772159047fSniklas    global symbol entry for such a const is actually written as a program
18782159047fSniklas    entry point (Yuk!!), so if we cannot find a symbol in the list of
18792159047fSniklas    psects, we must search the entry points as well.  static consts are
18802159047fSniklas    even harder, since they are never assigned a memory address.  The
18812159047fSniklas    compiler passes a stab to tell us the value, but I am not sure what
18822159047fSniklas    to do with it.  */
18832159047fSniklas 
18842159047fSniklas static void
VMS_stab_parse(symbolS * sp,int expected_type,int type1,int type2,int Text_Psect)1885*007c2a45Smiod VMS_stab_parse (symbolS *sp, int expected_type,
1886*007c2a45Smiod 		int type1, int type2, int Text_Psect)
18872159047fSniklas {
18882159047fSniklas   char *pnt;
18892159047fSniklas   char *pnt1;
18902159047fSniklas   char *str;
18912159047fSniklas   symbolS *sp1;
18922159047fSniklas   struct VMS_DBG_Symbol *spnt;
18932159047fSniklas   struct VMS_Symbol *vsp;
18942159047fSniklas   int dbx_type;
18952159047fSniklas 
18962159047fSniklas   dbx_type = 0;
18972159047fSniklas   str = S_GET_NAME (sp);
1898*007c2a45Smiod 
18992159047fSniklas   pnt = (char *) strchr (str, ':');
19002159047fSniklas   if (!pnt)
1901*007c2a45Smiod     /* No colon present.  */
1902*007c2a45Smiod     return;
1903*007c2a45Smiod 
1904*007c2a45Smiod   /* Save this for later. */
1905*007c2a45Smiod   pnt1 = pnt;
19062159047fSniklas   pnt++;
19072159047fSniklas   if (*pnt == expected_type)
19082159047fSniklas     {
19092159047fSniklas       pnt = cvt_integer (pnt + 1, &dbx_type);
19102159047fSniklas       spnt = find_symbol (dbx_type);
19112159047fSniklas       if (!spnt)
19122159047fSniklas 	return;		/*Dunno what this is*/
1913*007c2a45Smiod       /* Now we need to search the symbol table to find the psect and
1914*007c2a45Smiod          offset for this variable.  */
19152159047fSniklas       *pnt1 = '\0';
19162159047fSniklas       vsp = VMS_Symbols;
19172159047fSniklas       while (vsp)
19182159047fSniklas 	{
19192159047fSniklas 	  pnt = S_GET_NAME (vsp->Symbol);
19202159047fSniklas 	  if (pnt && *pnt++ == '_'
19212159047fSniklas 	      /* make sure name is the same and symbol type matches */
19222159047fSniklas 	      && strcmp (pnt, str) == 0
19232159047fSniklas 	      && (S_GET_RAW_TYPE (vsp->Symbol) == type1
19242159047fSniklas 		  || S_GET_RAW_TYPE (vsp->Symbol) == type2))
19252159047fSniklas 	    break;
19262159047fSniklas 	  vsp = vsp->Next;
19272159047fSniklas 	}
19282159047fSniklas       if (vsp)
19292159047fSniklas 	{
19302159047fSniklas 	  VMS_DBG_record (spnt, vsp->Psect_Index, vsp->Psect_Offset, str);
19312159047fSniklas 	  *pnt1 = ':';		/* and restore the string */
19322159047fSniklas 	  return;
19332159047fSniklas 	}
19342159047fSniklas       /* The symbol was not in the symbol list, but it may be an
19352159047fSniklas          "entry point" if it was a constant.  */
19362159047fSniklas       for (sp1 = symbol_rootP; sp1; sp1 = symbol_next (sp1))
19372159047fSniklas 	{
1938*007c2a45Smiod 	  /* Dispatch on STAB type.  */
19392159047fSniklas 	  if (S_IS_DEBUG (sp1) || (S_GET_TYPE (sp1) != N_TEXT))
19402159047fSniklas 	    continue;
19412159047fSniklas 	  pnt = S_GET_NAME (sp1);
19422159047fSniklas 	  if (*pnt == '_')
19432159047fSniklas 	    pnt++;
19442159047fSniklas 	  if (strcmp (pnt, str) == 0)
19452159047fSniklas 	    {
19462159047fSniklas 	      if (!gave_compiler_message && expected_type == 'G')
19472159047fSniklas 		{
1948f7cc78ecSespie 		  char *long_const_msg = _("\
19492159047fSniklas ***Warning - the assembly code generated by the compiler has placed \n\
19502159047fSniklas  global constant(s) in the text psect.  These will not be available to \n\
19512159047fSniklas  other modules, since this is not the correct way to handle this. You \n\
19522159047fSniklas  have two options: 1) get a patched compiler that does not put global \n\
19532159047fSniklas  constants in the text psect, or 2) remove the 'const' keyword from \n\
19542159047fSniklas  definitions of global variables in your source module(s).  Don't say \n\
1955f7cc78ecSespie  I didn't warn you! \n");
19562159047fSniklas 
19572159047fSniklas 		  as_tsktsk (long_const_msg);
19582159047fSniklas 		  gave_compiler_message = 1;
19592159047fSniklas 		}
19602159047fSniklas 	      VMS_DBG_record (spnt,
19612159047fSniklas 			      Text_Psect,
19622159047fSniklas 			      S_GET_VALUE (sp1),
19632159047fSniklas 			      str);
19642159047fSniklas 	      *pnt1 = ':';
1965*007c2a45Smiod 	      /* Fool assembler to not output this as a routine in the TBT.  */
19662159047fSniklas 	      pnt1 = S_GET_NAME (sp1);
19672159047fSniklas 	      *pnt1 = 'L';
19682159047fSniklas 	      S_SET_NAME (sp1, pnt1);
19692159047fSniklas 	      return;
19702159047fSniklas 	    }
19712159047fSniklas 	}
19722159047fSniklas     }
1973*007c2a45Smiod 
1974*007c2a45Smiod   /* ...and restore the string.  */
1975*007c2a45Smiod   *pnt1 = ':';
19762159047fSniklas }
19772159047fSniklas 
19782159047fSniklas /* Simpler interfaces into VMS_stab_parse().  */
19792159047fSniklas 
19802159047fSniklas static void
VMS_GSYM_Parse(symbolS * sp,int Text_Psect)1981*007c2a45Smiod VMS_GSYM_Parse (symbolS *sp, int Text_Psect)
19822159047fSniklas {				/* Global variables */
19832159047fSniklas   VMS_stab_parse (sp, 'G', (N_UNDF | N_EXT), (N_DATA | N_EXT), Text_Psect);
19842159047fSniklas }
19852159047fSniklas 
19862159047fSniklas static void
VMS_LCSYM_Parse(symbolS * sp,int Text_Psect)1987*007c2a45Smiod VMS_LCSYM_Parse (symbolS *sp, int Text_Psect)
1988*007c2a45Smiod {
19892159047fSniklas   VMS_stab_parse (sp, 'S', N_BSS, -1, Text_Psect);
19902159047fSniklas }
19912159047fSniklas 
19922159047fSniklas static void
VMS_STSYM_Parse(symbolS * sp,int Text_Psect)1993*007c2a45Smiod VMS_STSYM_Parse (symbolS *sp, int Text_Psect)
1994*007c2a45Smiod {
19952159047fSniklas   VMS_stab_parse (sp, 'S', N_DATA, -1, Text_Psect);
19962159047fSniklas }
19972159047fSniklas 
19982159047fSniklas /* For register symbols, we must figure out what range of addresses
19992159047fSniklas    within the psect are valid.  We will use the brackets in the stab
20002159047fSniklas    directives to give us guidance as to the PC range that this variable
20012159047fSniklas    is in scope.  I am still not completely comfortable with this but
20022159047fSniklas    as I learn more, I seem to get a better handle on what is going on.
20032159047fSniklas    Caveat Emptor.  */
20042159047fSniklas 
20052159047fSniklas static void
VMS_RSYM_Parse(symbolS * sp,symbolS * Current_Routine ATTRIBUTE_UNUSED,int Text_Psect)2006*007c2a45Smiod VMS_RSYM_Parse (symbolS *sp, symbolS *Current_Routine ATTRIBUTE_UNUSED,
2007*007c2a45Smiod 		int Text_Psect)
20082159047fSniklas {
20092159047fSniklas   symbolS *symbolP;
20102159047fSniklas   struct VMS_DBG_Symbol *spnt;
20112159047fSniklas   char *pnt;
20122159047fSniklas   char *pnt1;
20132159047fSniklas   char *str;
20142159047fSniklas   int dbx_type;
20152159047fSniklas   int len;
20162159047fSniklas   int i = 0;
20172159047fSniklas   int bcnt = 0;
20182159047fSniklas   int Min_Offset = -1;		/* min PC of validity */
20192159047fSniklas   int Max_Offset = 0;		/* max PC of validity */
20202159047fSniklas 
20212159047fSniklas   for (symbolP = sp; symbolP; symbolP = symbol_next (symbolP))
20222159047fSniklas     {
2023*007c2a45Smiod       /* Dispatch on STAB type.  */
20242159047fSniklas       switch (S_GET_RAW_TYPE (symbolP))
20252159047fSniklas 	{
20262159047fSniklas 	case N_LBRAC:
20272159047fSniklas 	  if (bcnt++ == 0)
20282159047fSniklas 	    Min_Offset = S_GET_VALUE (symbolP);
20292159047fSniklas 	  break;
20302159047fSniklas 	case N_RBRAC:
20312159047fSniklas 	  if (--bcnt == 0)
20322159047fSniklas 	    Max_Offset = S_GET_VALUE (symbolP) - 1;
20332159047fSniklas 	  break;
20342159047fSniklas 	}
20352159047fSniklas       if ((Min_Offset != -1) && (bcnt == 0))
20362159047fSniklas 	break;
20372159047fSniklas       if (S_GET_RAW_TYPE (symbolP) == N_FUN)
20382159047fSniklas 	{
20392159047fSniklas 	  pnt = (char *) strchr (S_GET_NAME (symbolP), ':') + 1;
20402159047fSniklas 	  if (*pnt == 'F' || *pnt == 'f') break;
20412159047fSniklas 	}
20422159047fSniklas     }
20432159047fSniklas 
20442159047fSniklas   /* Check to see that the addresses were defined.  If not, then there
20452159047fSniklas      were no brackets in the function, and we must try to search for
20462159047fSniklas      the next function.  Since functions can be in any order, we should
20472159047fSniklas      search all of the symbol list to find the correct ending address.  */
20482159047fSniklas   if (Min_Offset == -1)
20492159047fSniklas     {
20502159047fSniklas       int Max_Source_Offset;
20512159047fSniklas       int This_Offset;
20522159047fSniklas 
20532159047fSniklas       Min_Offset = S_GET_VALUE (sp);
20542159047fSniklas       Max_Source_Offset = Min_Offset;	/* just in case no N_SLINEs found */
20552159047fSniklas       for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
20562159047fSniklas 	switch (S_GET_RAW_TYPE (symbolP))
20572159047fSniklas 	  {
20582159047fSniklas 	  case N_TEXT | N_EXT:
20592159047fSniklas 	    This_Offset = S_GET_VALUE (symbolP);
20602159047fSniklas 	    if (This_Offset > Min_Offset && This_Offset < Max_Offset)
20612159047fSniklas 	      Max_Offset = This_Offset;
20622159047fSniklas 	    break;
20632159047fSniklas 	  case N_SLINE:
20642159047fSniklas 	    This_Offset = S_GET_VALUE (symbolP);
20652159047fSniklas 	    if (This_Offset > Max_Source_Offset)
20662159047fSniklas 	      Max_Source_Offset = This_Offset;
20672159047fSniklas 	    break;
20682159047fSniklas 	  }
20692159047fSniklas       /* If this is the last routine, then we use the PC of the last source
20702159047fSniklas          line as a marker of the max PC for which this reg is valid.  */
20712159047fSniklas       if (Max_Offset == 0x7fffffff)
20722159047fSniklas 	Max_Offset = Max_Source_Offset;
20732159047fSniklas     }
20742159047fSniklas 
20752159047fSniklas   dbx_type = 0;
20762159047fSniklas   str = S_GET_NAME (sp);
20772159047fSniklas   if ((pnt = (char *) strchr (str, ':')) == 0)
20782159047fSniklas     return;			/* no colon present */
20792159047fSniklas   pnt1 = pnt;			/* save this for later*/
20802159047fSniklas   pnt++;
20812159047fSniklas   if (*pnt != 'r')
20822159047fSniklas     return;
20832159047fSniklas   pnt = cvt_integer (pnt + 1, &dbx_type);
20842159047fSniklas   spnt = find_symbol (dbx_type);
20852159047fSniklas   if (!spnt)
20862159047fSniklas     return;			/*Dunno what this is yet*/
20872159047fSniklas   *pnt1 = '\0';
20882159047fSniklas   pnt = fix_name (S_GET_NAME (sp));	/* if there are bad characters in name, convert them */
20892159047fSniklas   len = strlen (pnt);
20902159047fSniklas   Local[i++] = 25 + len;
20912159047fSniklas   Local[i++] = spnt->VMS_type;
20922159047fSniklas   Local[i++] = DST_K_VFLAGS_TVS;	/* trailing value specified */
20932159047fSniklas   COPY_LONG (&Local[i], 1 + len);	/* relative offset, beyond name */
20942159047fSniklas   i += 4;
20952159047fSniklas   Local[i++] = len;			/* name length (ascic prefix) */
20962159047fSniklas   while (*pnt != '\0')
20972159047fSniklas     Local[i++] = *pnt++;
20982159047fSniklas   Local[i++] = DST_K_VS_FOLLOWS;	/* value specification follows */
20992159047fSniklas   COPY_SHORT (&Local[i], 15);		/* length of rest of record */
21002159047fSniklas   i += 2;
21012159047fSniklas   Local[i++] = DST_K_VS_ALLOC_SPLIT;	/* split lifetime */
21022159047fSniklas   Local[i++] = 1;			/* one binding follows */
21032159047fSniklas   VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
21042159047fSniklas   i = 0;
21052159047fSniklas   VMS_Set_Data (Text_Psect, Min_Offset, OBJ_S_C_DBG, 1);
21062159047fSniklas   VMS_Set_Data (Text_Psect, Max_Offset, OBJ_S_C_DBG, 1);
21072159047fSniklas   Local[i++] = DST_K_VALKIND_REG;		/* nested value spec */
21082159047fSniklas   COPY_LONG (&Local[i], S_GET_VALUE (sp));
21092159047fSniklas   i += 4;
21102159047fSniklas   VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
21112159047fSniklas   *pnt1 = ':';
21122159047fSniklas   if (spnt->VMS_type == DBG_S_C_ADVANCED_TYPE)
21132159047fSniklas     generate_suffix (spnt, 0);
21142159047fSniklas }
21152159047fSniklas 
21162159047fSniklas /* This function examines a structure definition, checking all of the elements
21172159047fSniklas    to make sure that all of them are fully defined.  The only thing that we
21182159047fSniklas    kick out are arrays of undefined structs, since we do not know how big
21192159047fSniklas    they are.  All others we can handle with a normal forward reference.  */
21202159047fSniklas 
21212159047fSniklas static int
forward_reference(char * pnt)2122*007c2a45Smiod forward_reference (char *pnt)
21232159047fSniklas {
21242159047fSniklas   struct VMS_DBG_Symbol *spnt, *spnt1;
21252159047fSniklas   int i;
21262159047fSniklas 
21272159047fSniklas   pnt = cvt_integer (pnt + 1, &i);
21282159047fSniklas   if (*pnt == ';')
21292159047fSniklas     return 0;			/* no forward references */
21302159047fSniklas   do
21312159047fSniklas     {
21322159047fSniklas       pnt = (char *) strchr (pnt, ':');
21332159047fSniklas       pnt = cvt_integer (pnt + 1, &i);
21342159047fSniklas       spnt = find_symbol (i);
21352159047fSniklas       while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY))
21362159047fSniklas 	{
21372159047fSniklas 	  spnt1 = find_symbol (spnt->type2);
21382159047fSniklas 	  if (spnt->advanced == ARRAY && !spnt1)
21392159047fSniklas 	    return 1;
21402159047fSniklas 	  spnt = spnt1;
21412159047fSniklas 	}
21422159047fSniklas       pnt = cvt_integer (pnt + 1, &i);
21432159047fSniklas       pnt = cvt_integer (pnt + 1, &i);
21442159047fSniklas     } while (*++pnt != ';');
2145*007c2a45Smiod   return 0;			/* no forward references found */
21462159047fSniklas }
21472159047fSniklas 
21482159047fSniklas /* Used to check a single element of a structure on the final pass.  */
21492159047fSniklas 
21502159047fSniklas static int
final_forward_reference(struct VMS_DBG_Symbol * spnt)2151*007c2a45Smiod final_forward_reference (struct VMS_DBG_Symbol *spnt)
21522159047fSniklas {
21532159047fSniklas   struct VMS_DBG_Symbol *spnt1;
21542159047fSniklas 
21552159047fSniklas   while (spnt && (spnt->advanced == POINTER || spnt->advanced == ARRAY))
21562159047fSniklas     {
21572159047fSniklas       spnt1 = find_symbol (spnt->type2);
21582159047fSniklas       if (spnt->advanced == ARRAY && !spnt1)
21592159047fSniklas 	return 1;
21602159047fSniklas       spnt = spnt1;
21612159047fSniklas     }
2162*007c2a45Smiod   return 0;	/* no forward references found */
21632159047fSniklas }
21642159047fSniklas 
21652159047fSniklas /* This routine parses the stabs directives to find any definitions of dbx
21662159047fSniklas    type numbers.  It makes a note of all of them, creating a structure
21672159047fSniklas    element of VMS_DBG_Symbol that describes it.  This also generates the
21682159047fSniklas    info for the debugger that describes the struct/union/enum, so that
21692159047fSniklas    further references to these data types will be by number
21702159047fSniklas 
21712159047fSniklas    We have to process pointers right away, since there can be references
21722159047fSniklas    to them later in the same stabs directive.  We cannot have forward
21732159047fSniklas    references to pointers, (but we can have a forward reference to a
21742159047fSniklas    pointer to a structure/enum/union) and this is why we process them
21752159047fSniklas    immediately.  After we process the pointer, then we search for defs
21762159047fSniklas    that are nested even deeper.
21772159047fSniklas 
21782159047fSniklas    8/15/92: We have to process arrays right away too, because there can
21792159047fSniklas    be multiple references to identical array types in one structure
21802159047fSniklas    definition, and only the first one has the definition.  */
21812159047fSniklas 
21822159047fSniklas static int
VMS_typedef_parse(char * str)2183*007c2a45Smiod VMS_typedef_parse (char *str)
21842159047fSniklas {
21852159047fSniklas   char *pnt;
21862159047fSniklas   char *pnt1;
21872159047fSniklas   const char *pnt2;
21882159047fSniklas   int i;
21892159047fSniklas   int dtype;
21902159047fSniklas   struct forward_ref *fpnt;
21912159047fSniklas   int i1, i2, i3, len;
21922159047fSniklas   struct VMS_DBG_Symbol *spnt;
21932159047fSniklas   struct VMS_DBG_Symbol *spnt1;
21942159047fSniklas 
21952159047fSniklas   /* check for any nested def's */
21962159047fSniklas   pnt = (char *) strchr (str + 1, '=');
21972159047fSniklas   if (pnt && str[1] != '*' && (str[1] != 'a' || str[2] != 'r')
21982159047fSniklas       && VMS_typedef_parse (pnt) == 1)
21992159047fSniklas     return 1;
22002159047fSniklas   /* now find dbx_type of entry */
22012159047fSniklas   pnt = str - 1;
22022159047fSniklas   if (*pnt == 'c')
22032159047fSniklas     {				/* check for static constants */
22042159047fSniklas       *str = '\0';		/* for now we ignore them */
22052159047fSniklas       return 0;
22062159047fSniklas     }
22072159047fSniklas   while ((*pnt <= '9') && (*pnt >= '0'))
22082159047fSniklas     pnt--;
22092159047fSniklas   pnt++;			/* and get back to the number */
22102159047fSniklas   cvt_integer (pnt, &i1);
22112159047fSniklas   spnt = find_symbol (i1);
2212*007c2a45Smiod   /* First see if this has been defined already, due to forward reference.  */
22132159047fSniklas   if (!spnt)
22142159047fSniklas     {
22152159047fSniklas       i2 = SYMTYP_HASH (i1);
2216*007c2a45Smiod       spnt = xmalloc (sizeof (struct VMS_DBG_Symbol));
22172159047fSniklas       spnt->next = VMS_Symbol_type_list[i2];
22182159047fSniklas       VMS_Symbol_type_list[i2] = spnt;
22192159047fSniklas       spnt->dbx_type = i1;	/* and save the type */
22202159047fSniklas       spnt->type2 = spnt->VMS_type = spnt->data_size = 0;
22212159047fSniklas       spnt->index_min = spnt->index_max = spnt->struc_numb = 0;
22222159047fSniklas     }
2223*007c2a45Smiod 
2224*007c2a45Smiod   /* For structs and unions, do a partial parse, otherwise we sometimes get
2225*007c2a45Smiod      circular definitions that are impossible to resolve.  We read enough
2226*007c2a45Smiod      info so that any reference to this type has enough info to be resolved.  */
2227*007c2a45Smiod 
2228*007c2a45Smiod   /* Point to character past equal sign.  */
2229*007c2a45Smiod   pnt = str + 1;
2230*007c2a45Smiod 
22312159047fSniklas   if (*pnt >= '0' && *pnt <= '9')
22322159047fSniklas     {
22332159047fSniklas       if (type_check ("void"))
22342159047fSniklas 	{			/* this is the void symbol */
22352159047fSniklas 	  *str = '\0';
22362159047fSniklas 	  spnt->advanced = VOID;
22372159047fSniklas 	  return 0;
22382159047fSniklas 	}
22392159047fSniklas       if (type_check ("unknown type"))
22402159047fSniklas 	{
22412159047fSniklas 	  *str = '\0';
22422159047fSniklas 	  spnt->advanced = UNKNOWN;
22432159047fSniklas 	  return 0;
22442159047fSniklas 	}
22452159047fSniklas       pnt1 = cvt_integer (pnt, &i1);
22462159047fSniklas       if (i1 != spnt->dbx_type)
22472159047fSniklas 	{
22482159047fSniklas 	  spnt->advanced = ALIAS;
22492159047fSniklas 	  spnt->type2 = i1;
22502159047fSniklas 	  strcpy (str, pnt1);
22512159047fSniklas 	  return 0;
22522159047fSniklas 	}
2253f7cc78ecSespie       as_tsktsk (_("debugginer output: %d is an unknown untyped variable."),
22542159047fSniklas 		 spnt->dbx_type);
22552159047fSniklas       return 1;			/* do not know what this is */
22562159047fSniklas     }
22572159047fSniklas 
2258*007c2a45Smiod   /* Point to character past equal sign.  */
2259*007c2a45Smiod   pnt = str + 1;
2260*007c2a45Smiod 
22612159047fSniklas   switch (*pnt)
22622159047fSniklas     {
22632159047fSniklas     case 'r':
22642159047fSniklas       spnt->advanced = BASIC;
22652159047fSniklas       if (type_check ("int"))
22662159047fSniklas 	{
22672159047fSniklas 	  spnt->VMS_type = DBG_S_C_SLINT;
22682159047fSniklas 	  spnt->data_size = 4;
22692159047fSniklas 	}
22702159047fSniklas       else if (type_check ("long int"))
22712159047fSniklas 	{
22722159047fSniklas 	  spnt->VMS_type = DBG_S_C_SLINT;
22732159047fSniklas 	  spnt->data_size = 4;
22742159047fSniklas 	}
22752159047fSniklas       else if (type_check ("unsigned int"))
22762159047fSniklas 	{
22772159047fSniklas 	  spnt->VMS_type = DBG_S_C_ULINT;
22782159047fSniklas 	  spnt->data_size = 4;
22792159047fSniklas 	}
22802159047fSniklas       else if (type_check ("long unsigned int"))
22812159047fSniklas 	{
22822159047fSniklas 	  spnt->VMS_type = DBG_S_C_ULINT;
22832159047fSniklas 	  spnt->data_size = 4;
22842159047fSniklas 	}
22852159047fSniklas       else if (type_check ("short int"))
22862159047fSniklas 	{
22872159047fSniklas 	  spnt->VMS_type = DBG_S_C_SSINT;
22882159047fSniklas 	  spnt->data_size = 2;
22892159047fSniklas 	}
22902159047fSniklas       else if (type_check ("short unsigned int"))
22912159047fSniklas 	{
22922159047fSniklas 	  spnt->VMS_type = DBG_S_C_USINT;
22932159047fSniklas 	  spnt->data_size = 2;
22942159047fSniklas 	}
22952159047fSniklas       else if (type_check ("char"))
22962159047fSniklas 	{
22972159047fSniklas 	  spnt->VMS_type = DBG_S_C_SCHAR;
22982159047fSniklas 	  spnt->data_size = 1;
22992159047fSniklas 	}
23002159047fSniklas       else if (type_check ("signed char"))
23012159047fSniklas 	{
23022159047fSniklas 	  spnt->VMS_type = DBG_S_C_SCHAR;
23032159047fSniklas 	  spnt->data_size = 1;
23042159047fSniklas 	}
23052159047fSniklas       else if (type_check ("unsigned char"))
23062159047fSniklas 	{
23072159047fSniklas 	  spnt->VMS_type = DBG_S_C_UCHAR;
23082159047fSniklas 	  spnt->data_size = 1;
23092159047fSniklas 	}
23102159047fSniklas       else if (type_check ("float"))
23112159047fSniklas 	{
23122159047fSniklas 	  spnt->VMS_type = DBG_S_C_REAL4;
23132159047fSniklas 	  spnt->data_size = 4;
23142159047fSniklas 	}
23152159047fSniklas       else if (type_check ("double"))
23162159047fSniklas 	{
23172159047fSniklas 	  spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8;
23182159047fSniklas 	  spnt->data_size = 8;
23192159047fSniklas 	}
23202159047fSniklas       else if (type_check ("long double"))
23212159047fSniklas 	{
23222159047fSniklas 	  /* same as double, at least for now */
23232159047fSniklas 	  spnt->VMS_type = vax_g_doubles ? DBG_S_C_REAL8_G : DBG_S_C_REAL8;
23242159047fSniklas 	  spnt->data_size = 8;
23252159047fSniklas 	}
23262159047fSniklas       else if (type_check ("long long int"))
23272159047fSniklas 	{
23282159047fSniklas 	  spnt->VMS_type = DBG_S_C_SQUAD;	/* signed quadword */
23292159047fSniklas 	  spnt->data_size = 8;
23302159047fSniklas 	}
23312159047fSniklas       else if (type_check ("long long unsigned int"))
23322159047fSniklas 	{
23332159047fSniklas 	  spnt->VMS_type = DBG_S_C_UQUAD;	/* unsigned quadword */
23342159047fSniklas 	  spnt->data_size = 8;
23352159047fSniklas 	}
23362159047fSniklas       else if (type_check ("complex float"))
23372159047fSniklas 	{
23382159047fSniklas 	  spnt->VMS_type = DBG_S_C_COMPLX4;
23392159047fSniklas 	  spnt->data_size = 2 * 4;
23402159047fSniklas 	}
23412159047fSniklas       else if (type_check ("complex double"))
23422159047fSniklas 	{
23432159047fSniklas 	  spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8;
23442159047fSniklas 	  spnt->data_size = 2 * 8;
23452159047fSniklas 	}
23462159047fSniklas       else if (type_check ("complex long double"))
23472159047fSniklas 	{
23482159047fSniklas 	  /* same as complex double, at least for now */
23492159047fSniklas 	  spnt->VMS_type = vax_g_doubles ? DBG_S_C_COMPLX8_G : DBG_S_C_COMPLX8;
23502159047fSniklas 	  spnt->data_size = 2 * 8;
23512159047fSniklas 	}
23522159047fSniklas       else
23532159047fSniklas 	{
2354*007c2a45Smiod 	  /* Shouldn't get here, but if we do, something
2355*007c2a45Smiod 	     more substantial ought to be done...  */
23562159047fSniklas 	  spnt->VMS_type = 0;
23572159047fSniklas 	  spnt->data_size = 0;
23582159047fSniklas 	}
23592159047fSniklas       if (spnt->VMS_type != 0)
23602159047fSniklas 	setup_basic_type (spnt);
23612159047fSniklas       pnt1 = (char *) strchr (str, ';') + 1;
23622159047fSniklas       break;
23632159047fSniklas     case 's':
23642159047fSniklas     case 'u':
23652159047fSniklas       spnt->advanced = (*pnt == 's') ? STRUCT : UNION;
23662159047fSniklas       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
23672159047fSniklas       pnt1 = cvt_integer (pnt + 1, &spnt->data_size);
23682159047fSniklas       if (!final_pass && forward_reference (pnt))
23692159047fSniklas 	{
23702159047fSniklas 	  spnt->struc_numb = -1;
23712159047fSniklas 	  return 1;
23722159047fSniklas 	}
23732159047fSniklas       spnt->struc_numb = ++structure_count;
23742159047fSniklas       pnt1--;
23752159047fSniklas       pnt = get_struct_name (str);
23762159047fSniklas       VMS_Def_Struct (spnt->struc_numb);
23772159047fSniklas       i = 0;
23782159047fSniklas       for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next)
23792159047fSniklas 	if (fpnt->dbx_type == spnt->dbx_type)
23802159047fSniklas 	  {
23812159047fSniklas 	    fpnt->resolved = 'Y';
23822159047fSniklas 	    VMS_Set_Struct (fpnt->struc_numb);
23832159047fSniklas 	    VMS_Store_Struct (spnt->struc_numb);
23842159047fSniklas 	    i++;
23852159047fSniklas 	  }
23862159047fSniklas       if (i > 0)
23872159047fSniklas 	VMS_Set_Struct (spnt->struc_numb);
23882159047fSniklas       i = 0;
23892159047fSniklas       Local[i++] = 11 + strlen (pnt);
23902159047fSniklas       Local[i++] = DBG_S_C_STRUCT_START;
23912159047fSniklas       Local[i++] = DST_K_VFLAGS_NOVAL;	/* structure definition only */
23922159047fSniklas       COPY_LONG (&Local[i], 0L);	/* hence value is unused */
23932159047fSniklas       i += 4;
23942159047fSniklas       Local[i++] = strlen (pnt);
23952159047fSniklas       pnt2 = pnt;
23962159047fSniklas       while (*pnt2 != '\0')
23972159047fSniklas 	Local[i++] = *pnt2++;
23982159047fSniklas       i2 = spnt->data_size * 8;	/* number of bits */
23992159047fSniklas       COPY_LONG (&Local[i], i2);
24002159047fSniklas       i += 4;
24012159047fSniklas       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
24022159047fSniklas       i = 0;
24032159047fSniklas       if (pnt != symbol_name)
24042159047fSniklas 	{
24052159047fSniklas 	  pnt += strlen (pnt);
2406*007c2a45Smiod 	  /* Replace colon for later.  */
24072159047fSniklas 	  *pnt = ':';
2408*007c2a45Smiod 	}
2409*007c2a45Smiod 
24102159047fSniklas       while (*++pnt1 != ';')
24112159047fSniklas 	{
24122159047fSniklas 	  pnt = (char *) strchr (pnt1, ':');
24132159047fSniklas 	  *pnt = '\0';
24142159047fSniklas 	  pnt2 = pnt1;
24152159047fSniklas 	  pnt1 = cvt_integer (pnt + 1, &dtype);
24162159047fSniklas 	  pnt1 = cvt_integer (pnt1 + 1, &i2);
24172159047fSniklas 	  pnt1 = cvt_integer (pnt1 + 1, &i3);
24182159047fSniklas 	  spnt1 = find_symbol (dtype);
24192159047fSniklas 	  len = strlen (pnt2);
24202159047fSniklas 	  if (spnt1 && (spnt1->advanced == BASIC || spnt1->advanced == ENUM)
24212159047fSniklas 	      && ((i3 != spnt1->data_size * 8) || (i2 % 8 != 0)))
24222159047fSniklas 	    {			/* bitfield */
24232159047fSniklas 	      if (USE_BITSTRING_DESCRIPTOR (spnt1))
24242159047fSniklas 		{
24252159047fSniklas 		  /* This uses a type descriptor, which doesn't work if
24262159047fSniklas 		     the enclosing structure has been placed in a register.
24272159047fSniklas 		     Also, enum bitfields degenerate to simple integers.  */
24282159047fSniklas 		  int unsigned_type = (spnt1->VMS_type == DBG_S_C_ULINT
24292159047fSniklas 				    || spnt1->VMS_type == DBG_S_C_USINT
24302159047fSniklas 				    || spnt1->VMS_type == DBG_S_C_UCHAR
24312159047fSniklas 				    || spnt1->VMS_type == DBG_S_C_UQUAD
2432*007c2a45Smiod 				    || spnt1->advanced == ENUM);
24332159047fSniklas 		  Apoint = 0;
24342159047fSniklas 		  fpush (19 + len, 1);
24352159047fSniklas 		  fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1);
24362159047fSniklas 		  fpush (DST_K_VFLAGS_DSC, 1);	/* specified by descriptor */
24372159047fSniklas 		  fpush (1 + len, 4);	/* relative offset to descriptor */
24382159047fSniklas 		  fpush (len, 1);		/* length byte (ascic prefix) */
24392159047fSniklas 		  while (*pnt2 != '\0')	/* name bytes */
24402159047fSniklas 		    fpush (*pnt2++, 1);
24412159047fSniklas 		  fpush (i3, 2);	/* dsc length == size of bitfield */
24422159047fSniklas 					/* dsc type == un?signed bitfield */
24432159047fSniklas 		  fpush (unsigned_type ? DBG_S_C_UBITU : DBG_S_C_SBITU, 1);
24442159047fSniklas 		  fpush (DSC_K_CLASS_UBS, 1);	/* dsc class == unaligned bitstring */
24452159047fSniklas 		  fpush (0x00, 4);		/* dsc pointer == zeroes */
24462159047fSniklas 		  fpush (i2, 4);	/* start position */
24472159047fSniklas 		  VMS_Store_Immediate_Data (Asuffix, Apoint, OBJ_S_C_DBG);
24482159047fSniklas 		  Apoint = 0;
24492159047fSniklas 		}
24502159047fSniklas 	      else
24512159047fSniklas 		{
24522159047fSniklas 		  /* Use a "novel length" type specification, which works
24532159047fSniklas 		     right for register structures and for enum bitfields
24542159047fSniklas 		     but results in larger object modules.  */
24552159047fSniklas 		  Local[i++] = 7 + len;
24562159047fSniklas 		  Local[i++] = DBG_S_C_ADVANCED_TYPE;	/* type spec follows */
24572159047fSniklas 		  Local[i++] = DBG_S_C_STRUCT_ITEM;	/* value is a bit offset */
24582159047fSniklas 		  COPY_LONG (&Local[i], i2);		/* bit offset */
24592159047fSniklas 		  i += 4;
24602159047fSniklas 		  Local[i++] = strlen (pnt2);
24612159047fSniklas 		  while (*pnt2 != '\0')
24622159047fSniklas 		    Local[i++] = *pnt2++;
24632159047fSniklas 		  VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
24642159047fSniklas 		  i = 0;
24652159047fSniklas 		  bitfield_suffix (spnt1, i3);
24662159047fSniklas 	     }
24672159047fSniklas 	    }
2468*007c2a45Smiod 	  else /* Not a bitfield.  */
2469*007c2a45Smiod 	    {
2470*007c2a45Smiod 	      /* Check if this is a forward reference.  */
24712159047fSniklas 	      if (final_pass && final_forward_reference (spnt1))
24722159047fSniklas 		{
2473f7cc78ecSespie 		  as_tsktsk (_("debugger output: structure element `%s' has undefined type"),
24742159047fSniklas 			   pnt2);
24752159047fSniklas 		  continue;
24762159047fSniklas 		}
24772159047fSniklas 	      Local[i++] = 7 + len;
24782159047fSniklas 	      Local[i++] = spnt1 ? spnt1->VMS_type : DBG_S_C_ADVANCED_TYPE;
24792159047fSniklas 	      Local[i++] = DBG_S_C_STRUCT_ITEM;
24802159047fSniklas 	      COPY_LONG (&Local[i], i2);		/* bit offset */
24812159047fSniklas 	      i += 4;
24822159047fSniklas 	      Local[i++] = strlen (pnt2);
24832159047fSniklas 	      while (*pnt2 != '\0')
24842159047fSniklas 		Local[i++] = *pnt2++;
24852159047fSniklas 	      VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
24862159047fSniklas 	      i = 0;
24872159047fSniklas 	      if (!spnt1)
24882159047fSniklas 		generate_suffix (spnt1, dtype);
24892159047fSniklas 	      else if (spnt1->VMS_type == DBG_S_C_ADVANCED_TYPE)
24902159047fSniklas 		generate_suffix (spnt1, 0);
24912159047fSniklas 	    }
24922159047fSniklas 	}
24932159047fSniklas       pnt1++;
24942159047fSniklas       Local[i++] = 0x01;	/* length byte */
24952159047fSniklas       Local[i++] = DBG_S_C_STRUCT_END;
24962159047fSniklas       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
24972159047fSniklas       i = 0;
24982159047fSniklas       break;
24992159047fSniklas     case 'e':
25002159047fSniklas       spnt->advanced = ENUM;
25012159047fSniklas       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
25022159047fSniklas       spnt->struc_numb = ++structure_count;
25032159047fSniklas       spnt->data_size = 4;
25042159047fSniklas       VMS_Def_Struct (spnt->struc_numb);
25052159047fSniklas       i = 0;
25062159047fSniklas       for (fpnt = f_ref_root; fpnt; fpnt = fpnt->next)
25072159047fSniklas 	if (fpnt->dbx_type == spnt->dbx_type)
25082159047fSniklas 	  {
25092159047fSniklas 	    fpnt->resolved = 'Y';
25102159047fSniklas 	    VMS_Set_Struct (fpnt->struc_numb);
25112159047fSniklas 	    VMS_Store_Struct (spnt->struc_numb);
25122159047fSniklas 	    i++;
25132159047fSniklas 	  }
25142159047fSniklas       if (i > 0)
25152159047fSniklas 	VMS_Set_Struct (spnt->struc_numb);
25162159047fSniklas       i = 0;
25172159047fSniklas       len = strlen (symbol_name);
25182159047fSniklas       Local[i++] = 3 + len;
25192159047fSniklas       Local[i++] = DBG_S_C_ENUM_START;
25202159047fSniklas       Local[i++] = 4 * 8;		/* enum values are 32 bits */
25212159047fSniklas       Local[i++] = len;
25222159047fSniklas       pnt2 = symbol_name;
25232159047fSniklas       while (*pnt2 != '\0')
25242159047fSniklas 	Local[i++] = *pnt2++;
25252159047fSniklas       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
25262159047fSniklas       i = 0;
25272159047fSniklas       while (*++pnt != ';')
25282159047fSniklas 	{
25292159047fSniklas 	  pnt1 = (char *) strchr (pnt, ':');
25302159047fSniklas 	  *pnt1++ = '\0';
25312159047fSniklas 	  pnt1 = cvt_integer (pnt1, &i1);
25322159047fSniklas 	  len = strlen (pnt);
25332159047fSniklas 	  Local[i++] = 7 + len;
25342159047fSniklas 	  Local[i++] = DBG_S_C_ENUM_ITEM;
25352159047fSniklas 	  Local[i++] = DST_K_VALKIND_LITERAL;
25362159047fSniklas 	  COPY_LONG (&Local[i], i1);
25372159047fSniklas 	  i += 4;
25382159047fSniklas 	  Local[i++] = len;
25392159047fSniklas 	  pnt2 = pnt;
25402159047fSniklas 	  while (*pnt != '\0')
25412159047fSniklas 	    Local[i++] = *pnt++;
25422159047fSniklas 	  VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
25432159047fSniklas 	  i = 0;
25442159047fSniklas 	  pnt = pnt1;		/* Skip final semicolon */
25452159047fSniklas 	}
25462159047fSniklas       Local[i++] = 0x01;	/* len byte */
25472159047fSniklas       Local[i++] = DBG_S_C_ENUM_END;
25482159047fSniklas       VMS_Store_Immediate_Data (Local, i, OBJ_S_C_DBG);
25492159047fSniklas       i = 0;
25502159047fSniklas       pnt1 = pnt + 1;
25512159047fSniklas       break;
25522159047fSniklas     case 'a':
25532159047fSniklas       spnt->advanced = ARRAY;
25542159047fSniklas       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
25552159047fSniklas       pnt = (char *) strchr (pnt, ';');
25562159047fSniklas       if (!pnt)
25572159047fSniklas 	return 1;
25582159047fSniklas       pnt1 = cvt_integer (pnt + 1, &spnt->index_min);
25592159047fSniklas       pnt1 = cvt_integer (pnt1 + 1, &spnt->index_max);
25602159047fSniklas       pnt1 = cvt_integer (pnt1 + 1, &spnt->type2);
25612159047fSniklas       pnt = (char *) strchr (str + 1, '=');
25622159047fSniklas       if (pnt && VMS_typedef_parse (pnt) == 1)
25632159047fSniklas 	return 1;
25642159047fSniklas       break;
25652159047fSniklas     case 'f':
25662159047fSniklas       spnt->advanced = FUNCTION;
25672159047fSniklas       spnt->VMS_type = DBG_S_C_FUNCTION_ADDR;
25682159047fSniklas       /* this masquerades as a basic type*/
25692159047fSniklas       spnt->data_size = 4;
25702159047fSniklas       pnt1 = cvt_integer (pnt + 1, &spnt->type2);
25712159047fSniklas       break;
25722159047fSniklas     case '*':
25732159047fSniklas       spnt->advanced = POINTER;
25742159047fSniklas       spnt->VMS_type = DBG_S_C_ADVANCED_TYPE;
25752159047fSniklas       spnt->data_size = 4;
25762159047fSniklas       pnt1 = cvt_integer (pnt + 1, &spnt->type2);
25772159047fSniklas       pnt = (char *) strchr (str + 1, '=');
25782159047fSniklas       if (pnt && VMS_typedef_parse (pnt) == 1)
25792159047fSniklas 	return 1;
25802159047fSniklas       break;
25812159047fSniklas     default:
25822159047fSniklas       spnt->advanced = UNKNOWN;
25832159047fSniklas       spnt->VMS_type = 0;
2584f7cc78ecSespie       as_tsktsk (_("debugger output: %d is an unknown type of variable."),
25852159047fSniklas 		 spnt->dbx_type);
25862159047fSniklas       return 1;			/* unable to decipher */
25872159047fSniklas     }
25882159047fSniklas   /* This removes the evidence of the definition so that the outer levels
25892159047fSniklas      of parsing do not have to worry about it.  */
25902159047fSniklas   pnt = str;
25912159047fSniklas   while (*pnt1 != '\0')
25922159047fSniklas     *pnt++ = *pnt1++;
25932159047fSniklas   *pnt = '\0';
25942159047fSniklas   return 0;
25952159047fSniklas }
25962159047fSniklas 
25972159047fSniklas /* This is the root routine that parses the stabs entries for definitions.
25982159047fSniklas    it calls VMS_typedef_parse, which can in turn call itself.  We need to
25992159047fSniklas    be careful, since sometimes there are forward references to other symbol
26002159047fSniklas    types, and these cannot be resolved until we have completed the parse.
26012159047fSniklas 
26022159047fSniklas    Also check and see if we are using continuation stabs, if we are, then
26032159047fSniklas    paste together the entire contents of the stab before we pass it to
26042159047fSniklas    VMS_typedef_parse.  */
26052159047fSniklas 
26062159047fSniklas static void
VMS_LSYM_Parse(void)2607*007c2a45Smiod VMS_LSYM_Parse (void)
26082159047fSniklas {
26092159047fSniklas   char *pnt;
26102159047fSniklas   char *pnt1;
26112159047fSniklas   char *pnt2;
26122159047fSniklas   char *str;
26132159047fSniklas   char *parse_buffer = 0;
26142159047fSniklas   char fixit[10];
26152159047fSniklas   int incomplete, pass, incom1;
26162159047fSniklas   struct forward_ref *fpnt;
26172159047fSniklas   symbolS *sp;
26182159047fSniklas 
26192159047fSniklas   pass = 0;
26202159047fSniklas   final_pass = 0;
26212159047fSniklas   incomplete = 0;
26222159047fSniklas   do
26232159047fSniklas     {
26242159047fSniklas       incom1 = incomplete;
26252159047fSniklas       incomplete = 0;
26262159047fSniklas       for (sp = symbol_rootP; sp; sp = symbol_next (sp))
26272159047fSniklas 	{
2628*007c2a45Smiod 	  /* Deal with STAB symbols.  */
26292159047fSniklas 	  if (S_IS_DEBUG (sp))
26302159047fSniklas 	    {
2631*007c2a45Smiod 	      /* Dispatch on STAB type.  */
26322159047fSniklas 	      switch (S_GET_RAW_TYPE (sp))
26332159047fSniklas 		{
26342159047fSniklas 		case N_GSYM:
26352159047fSniklas 		case N_LCSYM:
26362159047fSniklas 		case N_STSYM:
26372159047fSniklas 		case N_PSYM:
26382159047fSniklas 		case N_RSYM:
26392159047fSniklas 		case N_LSYM:
2640*007c2a45Smiod 		case N_FUN:	/* Sometimes these contain typedefs. */
26412159047fSniklas 		  str = S_GET_NAME (sp);
26422159047fSniklas 		  symbol_name = str;
26432159047fSniklas 		  pnt = str + strlen (str) - 1;
26442159047fSniklas 		  if (*pnt == '?')  /* Continuation stab.  */
26452159047fSniklas 		    {
26462159047fSniklas 		      symbolS *spnext;
26472159047fSniklas 		      int tlen = 0;
26482159047fSniklas 
26492159047fSniklas 		      spnext = sp;
2650*007c2a45Smiod 		      do
2651*007c2a45Smiod 			{
26522159047fSniklas 			  tlen += strlen (str) - 1;
26532159047fSniklas 			  spnext = symbol_next (spnext);
26542159047fSniklas 			  str = S_GET_NAME (spnext);
26552159047fSniklas 			  pnt = str + strlen (str) - 1;
2656*007c2a45Smiod 			}
2657*007c2a45Smiod 		      while (*pnt == '?');
2658*007c2a45Smiod 
26592159047fSniklas 		      tlen += strlen (str);
2660*007c2a45Smiod 		      parse_buffer = xmalloc (tlen + 1);
26612159047fSniklas 		      strcpy (parse_buffer, S_GET_NAME (sp));
26622159047fSniklas 		      pnt2 = parse_buffer + strlen (parse_buffer) - 1;
26632159047fSniklas 		      *pnt2 = '\0';
26642159047fSniklas 		      spnext = sp;
2665*007c2a45Smiod 
2666*007c2a45Smiod 		      do
2667*007c2a45Smiod 			{
26682159047fSniklas 			  spnext = symbol_next (spnext);
26692159047fSniklas 			  str = S_GET_NAME (spnext);
26702159047fSniklas 			  strcat (pnt2, str);
26712159047fSniklas 			  pnt2 +=  strlen (str) - 1;
26722159047fSniklas 			  *str = '\0';  /* Erase this string  */
26732159047fSniklas 			  /* S_SET_NAME (spnext, str); */
26742159047fSniklas 			  if (*pnt2 != '?') break;
26752159047fSniklas 			  *pnt2 = '\0';
2676*007c2a45Smiod 			}
2677*007c2a45Smiod 		      while (1);
2678*007c2a45Smiod 
26792159047fSniklas 		      str = parse_buffer;
26802159047fSniklas 		      symbol_name = str;
26812159047fSniklas 		    }
2682*007c2a45Smiod 
26832159047fSniklas 		  if ((pnt = (char *) strchr (str, ':')) != 0)
26842159047fSniklas 		    {
26852159047fSniklas 		      *pnt = '\0';
26862159047fSniklas 		      pnt1 = pnt + 1;
26872159047fSniklas 		      if ((pnt2 = (char *) strchr (pnt1, '=')) != 0)
26882159047fSniklas 			incomplete += VMS_typedef_parse (pnt2);
26892159047fSniklas 		      if (parse_buffer)
26902159047fSniklas 			{
26912159047fSniklas 			  /*  At this point the parse buffer should just
26922159047fSniklas 			      contain name:nn.  If it does not, then we
26932159047fSniklas 			      are in real trouble.  Anyway, this is always
26942159047fSniklas 			      shorter than the original line.  */
26952159047fSniklas 			  pnt2 = S_GET_NAME (sp);
26962159047fSniklas 			  strcpy (pnt2, parse_buffer);
26972159047fSniklas 			  /* S_SET_NAME (sp, pnt2); */
26982159047fSniklas 			  free (parse_buffer),  parse_buffer = 0;
26992159047fSniklas 			}
2700*007c2a45Smiod 		      /* Put back colon to restore dbx_type.  */
2701*007c2a45Smiod 		      *pnt = ':';
27022159047fSniklas 		    }
27032159047fSniklas 		  break;
2704*007c2a45Smiod 		}
2705*007c2a45Smiod 	    }
2706*007c2a45Smiod 	}
27072159047fSniklas       pass++;
2708*007c2a45Smiod 
2709*007c2a45Smiod       /* Make one last pass, if needed, and define whatever we can
2710*007c2a45Smiod          that is left.  */
27112159047fSniklas       if (final_pass == 0 && incomplete == incom1)
27122159047fSniklas 	{
27132159047fSniklas 	  final_pass = 1;
2714*007c2a45Smiod 	  incom1++;	/* Force one last pass through.  */
27152159047fSniklas 	}
2716*007c2a45Smiod     }
2717*007c2a45Smiod   while (incomplete != 0 && incomplete != incom1);
2718*007c2a45Smiod 
27192159047fSniklas   if (incomplete != 0)
2720f7cc78ecSespie     as_tsktsk (_("debugger output: Unable to resolve %d circular references."),
27212159047fSniklas 	       incomplete);
2722*007c2a45Smiod 
27232159047fSniklas   fpnt = f_ref_root;
27242159047fSniklas   symbol_name = "\0";
27252159047fSniklas   while (fpnt)
27262159047fSniklas     {
27272159047fSniklas       if (fpnt->resolved != 'Y')
27282159047fSniklas 	{
27292159047fSniklas 	  if (find_symbol (fpnt->dbx_type))
27302159047fSniklas 	    {
2731f7cc78ecSespie 	      as_tsktsk (_("debugger forward reference error, dbx type %d"),
27322159047fSniklas 			 fpnt->dbx_type);
27332159047fSniklas 	      break;
27342159047fSniklas 	    }
27352159047fSniklas 	  fixit[0] = 0;
27362159047fSniklas 	  sprintf (&fixit[1], "%d=s4;", fpnt->dbx_type);
27372159047fSniklas 	  pnt2 = (char *) strchr (&fixit[1], '=');
27382159047fSniklas 	  VMS_typedef_parse (pnt2);
27392159047fSniklas 	}
27402159047fSniklas       fpnt = fpnt->next;
27412159047fSniklas     }
27422159047fSniklas }
27432159047fSniklas 
27442159047fSniklas static void
Define_Local_Symbols(symbolS * s0P,symbolS * s2P,symbolS * Current_Routine,int Text_Psect)2745*007c2a45Smiod Define_Local_Symbols (symbolS *s0P, symbolS *s2P, symbolS *Current_Routine,
2746*007c2a45Smiod 		      int Text_Psect)
27472159047fSniklas {
2748*007c2a45Smiod   symbolS *s1P;		/* Each symbol from s0P .. s2P (exclusive).  */
27492159047fSniklas 
27502159047fSniklas   for (s1P = symbol_next (s0P); s1P != s2P; s1P = symbol_next (s1P))
27512159047fSniklas     {
27522159047fSniklas       if (!s1P)
27532159047fSniklas 	break;		/* and return */
27542159047fSniklas       if (S_GET_RAW_TYPE (s1P) == N_FUN)
27552159047fSniklas 	{
27562159047fSniklas 	  char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1;
27572159047fSniklas 	  if (*pnt == 'F' || *pnt == 'f') break;
27582159047fSniklas 	}
27592159047fSniklas       if (!S_IS_DEBUG (s1P))
27602159047fSniklas 	continue;
2761*007c2a45Smiod       /* Dispatch on STAB type.  */
27622159047fSniklas       switch (S_GET_RAW_TYPE (s1P))
27632159047fSniklas 	{
27642159047fSniklas 	default:
2765*007c2a45Smiod 	  /* Not left or right brace.  */
2766*007c2a45Smiod 	  continue;
27672159047fSniklas 
27682159047fSniklas 	case N_LSYM:
27692159047fSniklas 	case N_PSYM:
27702159047fSniklas 	  VMS_local_stab_Parse (s1P);
27712159047fSniklas 	  break;
27722159047fSniklas 
27732159047fSniklas 	case N_RSYM:
27742159047fSniklas 	  VMS_RSYM_Parse (s1P, Current_Routine, Text_Psect);
27752159047fSniklas 	  break;
2776*007c2a45Smiod 	}
2777*007c2a45Smiod     }
27782159047fSniklas }
27792159047fSniklas 
27802159047fSniklas /* This function crawls the symbol chain searching for local symbols that
27812159047fSniklas    need to be described to the debugger.  When we enter a new scope with
27822159047fSniklas    a "{", it creates a new "block", which helps the debugger keep track
27832159047fSniklas    of which scope we are currently in.  */
27842159047fSniklas 
27852159047fSniklas static symbolS *
Define_Routine(symbolS * s0P,int Level,symbolS * Current_Routine,int Text_Psect)2786*007c2a45Smiod Define_Routine (symbolS *s0P, int Level, symbolS *Current_Routine,
2787*007c2a45Smiod 		int Text_Psect)
27882159047fSniklas {
27892159047fSniklas   symbolS *s1P;
27902159047fSniklas   valueT Offset;
27912159047fSniklas   int rcount = 0;
27922159047fSniklas 
27932159047fSniklas   for (s1P = symbol_next (s0P); s1P != 0; s1P = symbol_next (s1P))
27942159047fSniklas     {
27952159047fSniklas       if (S_GET_RAW_TYPE (s1P) == N_FUN)
27962159047fSniklas 	{
27972159047fSniklas 	  char *pnt = (char *) strchr (S_GET_NAME (s1P), ':') + 1;
27982159047fSniklas 	  if (*pnt == 'F' || *pnt == 'f') break;
27992159047fSniklas 	}
28002159047fSniklas       if (!S_IS_DEBUG (s1P))
28012159047fSniklas 	continue;
2802*007c2a45Smiod       /* Dispatch on STAB type.  */
28032159047fSniklas       switch (S_GET_RAW_TYPE (s1P))
28042159047fSniklas 	{
28052159047fSniklas 	default:
2806*007c2a45Smiod 	  continue;
28072159047fSniklas 
28082159047fSniklas 	case N_LBRAC:
28092159047fSniklas 	  if (Level != 0)
28102159047fSniklas 	    {
28112159047fSniklas 	      char str[10];
28122159047fSniklas 	      sprintf (str, "$%d", rcount++);
28132159047fSniklas 	      VMS_TBT_Block_Begin (s1P, Text_Psect, str);
28142159047fSniklas 	    }
2815*007c2a45Smiod 	  /* Side-effect: fully resolve symbol.  */
2816*007c2a45Smiod 	  Offset = S_GET_VALUE (s1P);
28172159047fSniklas 	  Define_Local_Symbols (s0P, s1P, Current_Routine, Text_Psect);
28182159047fSniklas 	  s1P = Define_Routine (s1P, Level + 1, Current_Routine, Text_Psect);
28192159047fSniklas 	  if (Level != 0)
28202159047fSniklas 	    VMS_TBT_Block_End (S_GET_VALUE (s1P) - Offset);
28212159047fSniklas 	  s0P = s1P;
28222159047fSniklas 	  break;
28232159047fSniklas 
28242159047fSniklas 	case N_RBRAC:
28252159047fSniklas 	  return s1P;
2826*007c2a45Smiod 	}
2827*007c2a45Smiod     }
28282159047fSniklas 
28292159047fSniklas   /* We end up here if there were no brackets in this function.
28302159047fSniklas      Define everything.  */
28312159047fSniklas   Define_Local_Symbols (s0P, (symbolS *)0, Current_Routine, Text_Psect);
28322159047fSniklas   return s1P;
28332159047fSniklas }
28342159047fSniklas 
28352159047fSniklas 
28362159047fSniklas #ifndef VMS
28372159047fSniklas #include <sys/types.h>
28382159047fSniklas #include <time.h>
2839*007c2a45Smiod static void get_VMS_time_on_unix (char *);
28402159047fSniklas 
28412159047fSniklas /* Manufacture a VMS-like time string on a Unix based system.  */
28422159047fSniklas static void
get_VMS_time_on_unix(char * Now)2843*007c2a45Smiod get_VMS_time_on_unix (char *Now)
28442159047fSniklas {
28452159047fSniklas   char *pnt;
28462159047fSniklas   time_t timeb;
28472159047fSniklas 
28482159047fSniklas   time (&timeb);
28492159047fSniklas   pnt = ctime (&timeb);
28502159047fSniklas   pnt[3] = 0;
28512159047fSniklas   pnt[7] = 0;
28522159047fSniklas   pnt[10] = 0;
28532159047fSniklas   pnt[16] = 0;
28542159047fSniklas   pnt[24] = 0;
28552159047fSniklas   sprintf (Now, "%2s-%3s-%s %s", pnt + 8, pnt + 4, pnt + 20, pnt + 11);
28562159047fSniklas }
28572159047fSniklas #endif /* not VMS */
28582159047fSniklas 
28592159047fSniklas /* Write the MHD (Module Header) records.  */
28602159047fSniklas 
28612159047fSniklas static void
Write_VMS_MHD_Records(void)2862*007c2a45Smiod Write_VMS_MHD_Records (void)
28632159047fSniklas {
2864*007c2a45Smiod   const char *cp;
2865*007c2a45Smiod   char *cp1;
2866*007c2a45Smiod   int i;
28672159047fSniklas #ifdef VMS
28682159047fSniklas   struct { unsigned short len, mbz; char *ptr; } Descriptor;
28692159047fSniklas #endif
28702159047fSniklas   char Now[17+1];
28712159047fSniklas 
28722159047fSniklas   /* We are writing a module header record.  */
28732159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_HDR);
2874*007c2a45Smiod   /* MAIN MODULE HEADER RECORD.  */
28752159047fSniklas   /* Store record type and header type.  */
28762159047fSniklas   PUT_CHAR (OBJ_S_C_HDR);
28772159047fSniklas   PUT_CHAR (MHD_S_C_MHD);
28782159047fSniklas   /* Structure level is 0.  */
28792159047fSniklas   PUT_CHAR (OBJ_S_C_STRLVL);
28802159047fSniklas   /* Maximum record size is size of the object record buffer.  */
28812159047fSniklas   PUT_SHORT (sizeof (Object_Record_Buffer));
28822159047fSniklas 
2883*007c2a45Smiod   /* FIXME:  module name and version should be user
2884*007c2a45Smiod 	     specifiable via `.ident' and/or `#pragma ident'.  */
28852159047fSniklas 
28862159047fSniklas   /* Get module name (the FILENAME part of the object file).  */
28872159047fSniklas   cp = out_file_name;
28882159047fSniklas   cp1 = Module_Name;
28892159047fSniklas   while (*cp)
28902159047fSniklas     {
28912159047fSniklas       if (*cp == ']' || *cp == '>' || *cp == ':' || *cp == '/')
28922159047fSniklas 	{
28932159047fSniklas 	  cp1 = Module_Name;
28942159047fSniklas 	  cp++;
28952159047fSniklas 	  continue;
28962159047fSniklas 	}
2897c074d1c9Sdrahn       *cp1++ = TOUPPER (*cp++);
28982159047fSniklas     }
28992159047fSniklas   *cp1 = '\0';
29002159047fSniklas 
29012159047fSniklas   /* Limit it to 31 characters and store in the object record.  */
29022159047fSniklas   while (--cp1 >= Module_Name)
29032159047fSniklas     if (*cp1 == '.')
29042159047fSniklas       *cp1 = '\0';
29052159047fSniklas   if (strlen (Module_Name) > 31)
29062159047fSniklas     {
29072159047fSniklas       if (flag_hash_long_names)
2908f7cc78ecSespie 	as_tsktsk (_("Module name truncated: %s\n"), Module_Name);
29092159047fSniklas       Module_Name[31] = '\0';
29102159047fSniklas     }
29112159047fSniklas   PUT_COUNTED_STRING (Module_Name);
29122159047fSniklas   /* Module Version is "V1.0".  */
29132159047fSniklas   PUT_COUNTED_STRING ("V1.0");
29142159047fSniklas   /* Creation time is "now" (17 chars of time string): "dd-MMM-yyyy hh:mm".  */
29152159047fSniklas #ifndef VMS
29162159047fSniklas   get_VMS_time_on_unix (Now);
29172159047fSniklas #else /* VMS */
29182159047fSniklas   Descriptor.len = sizeof Now - 1;
29192159047fSniklas   Descriptor.mbz = 0;		/* type & class unspecified */
29202159047fSniklas   Descriptor.ptr = Now;
29212159047fSniklas   (void) sys$asctim ((unsigned short *)0, &Descriptor, (long *)0, 0);
29222159047fSniklas #endif /* VMS */
29232159047fSniklas   for (i = 0; i < 17; i++)
29242159047fSniklas     PUT_CHAR (Now[i]);
29252159047fSniklas   /* Patch time is "never" (17 zeros).  */
29262159047fSniklas   for (i = 0; i < 17; i++)
29272159047fSniklas     PUT_CHAR (0);
29282159047fSniklas   /* Force this to be a separate output record.  */
29292159047fSniklas   Flush_VMS_Object_Record_Buffer ();
29302159047fSniklas 
2931*007c2a45Smiod   /* LANGUAGE PROCESSOR NAME.  */
2932*007c2a45Smiod 
29332159047fSniklas   /* Store record type and header type.  */
29342159047fSniklas   PUT_CHAR (OBJ_S_C_HDR);
29352159047fSniklas   PUT_CHAR (MHD_S_C_LNM);
2936*007c2a45Smiod 
2937*007c2a45Smiod   /* Store language processor name and version (not a counted string!).
2938*007c2a45Smiod      This is normally supplied by the gcc driver for the command line
2939*007c2a45Smiod      which invokes gas.  If absent, we fall back to gas's version.  */
2940*007c2a45Smiod 
29412159047fSniklas   cp = compiler_version_string;
29422159047fSniklas   if (cp == 0)
29432159047fSniklas     {
29442159047fSniklas       cp = "GNU AS  V";
29452159047fSniklas       while (*cp)
29462159047fSniklas 	PUT_CHAR (*cp++);
2947f7cc78ecSespie       cp = VERSION;
29482159047fSniklas     }
29492159047fSniklas   while (*cp >= ' ')
29502159047fSniklas     PUT_CHAR (*cp++);
29512159047fSniklas   /* Force this to be a separate output record.  */
29522159047fSniklas   Flush_VMS_Object_Record_Buffer ();
29532159047fSniklas }
29542159047fSniklas 
29552159047fSniklas /* Write the EOM (End Of Module) record.  */
29562159047fSniklas 
29572159047fSniklas static void
Write_VMS_EOM_Record(int Psect,valueT Offset)2958*007c2a45Smiod Write_VMS_EOM_Record (int Psect, valueT Offset)
29592159047fSniklas {
2960*007c2a45Smiod   /* We are writing an end-of-module record
2961*007c2a45Smiod      (this assumes that the entry point will always be in a psect
2962*007c2a45Smiod      represented by a single byte, which is the case for code in
2963*007c2a45Smiod      Text_Psect==0).  */
2964*007c2a45Smiod 
29652159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_EOM);
29662159047fSniklas   PUT_CHAR (OBJ_S_C_EOM);	/* Record type.  */
29672159047fSniklas   PUT_CHAR (0);			/* Error severity level (we ignore it).  */
2968*007c2a45Smiod   /* Store the entry point, if it exists.  */
29692159047fSniklas   if (Psect >= 0)
29702159047fSniklas     {
29712159047fSniklas       PUT_CHAR (Psect);
29722159047fSniklas       PUT_LONG (Offset);
29732159047fSniklas     }
29742159047fSniklas   /* Flush the record; this will be our final output.  */
29752159047fSniklas   Flush_VMS_Object_Record_Buffer ();
29762159047fSniklas }
29772159047fSniklas 
29782159047fSniklas 
2979*007c2a45Smiod /* This hash routine borrowed from GNU-EMACS, and strengthened slightly
2980*007c2a45Smiod    ERY.  */
29812159047fSniklas 
29822159047fSniklas static int
hash_string(const char * ptr)2983*007c2a45Smiod hash_string (const char *ptr)
29842159047fSniklas {
2985*007c2a45Smiod   const unsigned char *p = (unsigned char *) ptr;
2986*007c2a45Smiod   const unsigned char *end = p + strlen (ptr);
2987*007c2a45Smiod   unsigned char c;
2988*007c2a45Smiod   int hash = 0;
29892159047fSniklas 
29902159047fSniklas   while (p != end)
29912159047fSniklas     {
29922159047fSniklas       c = *p++;
29932159047fSniklas       hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
29942159047fSniklas     }
29952159047fSniklas   return hash;
29962159047fSniklas }
29972159047fSniklas 
2998*007c2a45Smiod /* Generate a Case-Hacked VMS symbol name (limited to 31 chars).  */
2999*007c2a45Smiod 
30002159047fSniklas static void
VMS_Case_Hack_Symbol(const char * In,char * Out)3001*007c2a45Smiod VMS_Case_Hack_Symbol (const char *In, char *Out)
30022159047fSniklas {
30032159047fSniklas   long int init;
30042159047fSniklas   long int result;
30052159047fSniklas   char *pnt = 0;
30062159047fSniklas   char *new_name;
30072159047fSniklas   const char *old_name;
3008*007c2a45Smiod   int i;
3009*007c2a45Smiod   int destructor = 0;		/* Hack to allow for case sens in a destructor.  */
30102159047fSniklas   int truncate = 0;
30112159047fSniklas   int Case_Hack_Bits = 0;
30122159047fSniklas   int Saw_Dollar = 0;
30132159047fSniklas   static char Hex_Table[16] =
30142159047fSniklas   {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
30152159047fSniklas 
3016*007c2a45Smiod   /* Kill any leading "_".  */
30172159047fSniklas   if ((In[0] == '_') && ((In[1] > '9') || (In[1] < '0')))
30182159047fSniklas     In++;
30192159047fSniklas 
3020*007c2a45Smiod   new_name = Out;		/* Save this for later.  */
30212159047fSniklas 
3022*007c2a45Smiod #if 0
30232159047fSniklas   if ((In[0] == '_') && (In[1] == '$') && (In[2] == '_'))
30242159047fSniklas     destructor = 1;
30252159047fSniklas #endif
30262159047fSniklas 
3027*007c2a45Smiod   /* We may need to truncate the symbol, save the hash for later.  */
30282159047fSniklas   result = (strlen (In) > 23) ? hash_string (In) : 0;
3029*007c2a45Smiod   /* Is there a Psect Attribute to skip?  */
30302159047fSniklas   if (HAS_PSECT_ATTRIBUTES (In))
30312159047fSniklas     {
3032*007c2a45Smiod       /* Yes: Skip it.  */
30332159047fSniklas       In += PSECT_ATTRIBUTES_STRING_LENGTH;
30342159047fSniklas       while (*In)
30352159047fSniklas 	{
30362159047fSniklas 	  if ((In[0] == '$') && (In[1] == '$'))
30372159047fSniklas 	    {
30382159047fSniklas 	      In += 2;
30392159047fSniklas 	      break;
30402159047fSniklas 	    }
30412159047fSniklas 	  In++;
30422159047fSniklas 	}
30432159047fSniklas     }
30442159047fSniklas 
30452159047fSniklas   old_name = In;
3046*007c2a45Smiod #if 0
3047*007c2a45Smiod   if (strlen (In) > 31 && flag_hash_long_names)
3048*007c2a45Smiod     as_tsktsk ("Symbol name truncated: %s\n", In);
3049*007c2a45Smiod #endif
3050*007c2a45Smiod   /* Do the case conversion.  */
3051*007c2a45Smiod   /* Maximum of 23 chars */
3052*007c2a45Smiod   i = 23;
30532159047fSniklas   while (*In && (--i >= 0))
30542159047fSniklas     {
30552159047fSniklas       Case_Hack_Bits <<= 1;
30562159047fSniklas       if (*In == '$')
30572159047fSniklas 	Saw_Dollar = 1;
30582159047fSniklas       if ((destructor == 1) && (i == 21))
30592159047fSniklas 	Saw_Dollar = 0;
3060*007c2a45Smiod 
30612159047fSniklas       switch (vms_name_mapping)
30622159047fSniklas 	{
30632159047fSniklas 	case 0:
3064*007c2a45Smiod 	  if (ISUPPER (*In))
3065*007c2a45Smiod 	    {
30662159047fSniklas 	      *Out++ = *In++;
30672159047fSniklas 	      Case_Hack_Bits |= 1;
3068*007c2a45Smiod 	    }
3069*007c2a45Smiod 	  else
3070c074d1c9Sdrahn 	    *Out++ = TOUPPER (*In++);
30712159047fSniklas 	  break;
3072*007c2a45Smiod 
3073*007c2a45Smiod 	case 3:
30742159047fSniklas 	  *Out++ = *In++;
3075*007c2a45Smiod 	  break;
3076*007c2a45Smiod 
3077*007c2a45Smiod 	case 2:
3078*007c2a45Smiod 	  if (ISLOWER (*In))
3079*007c2a45Smiod 	    *Out++ = *In++;
3080*007c2a45Smiod 	  else
3081c074d1c9Sdrahn 	    *Out++ = TOLOWER (*In++);
30822159047fSniklas 	  break;
30832159047fSniklas 	}
30842159047fSniklas     }
3085*007c2a45Smiod   /* If we saw a dollar sign, we don't do case hacking.  */
30862159047fSniklas   if (flag_no_hash_mixed_case || Saw_Dollar)
30872159047fSniklas     Case_Hack_Bits = 0;
30882159047fSniklas 
3089*007c2a45Smiod   /* If we have more than 23 characters and everything is lowercase
3090*007c2a45Smiod      we can insert the full 31 characters.  */
30912159047fSniklas   if (*In)
30922159047fSniklas     {
3093*007c2a45Smiod       /* We have more than 23 characters
3094*007c2a45Smiod          If we must add the case hack, then we have truncated the str.  */
30952159047fSniklas       pnt = Out;
30962159047fSniklas       truncate = 1;
30972159047fSniklas       if (Case_Hack_Bits == 0)
30982159047fSniklas 	{
3099*007c2a45Smiod 	  /* And so far they are all lower case:
3100*007c2a45Smiod 	     Check up to 8 more characters
3101*007c2a45Smiod 	     and ensure that they are lowercase.  */
31022159047fSniklas 	  for (i = 0; (In[i] != 0) && (i < 8); i++)
3103c074d1c9Sdrahn 	    if (ISUPPER (In[i]) && !Saw_Dollar && !flag_no_hash_mixed_case)
31042159047fSniklas 	      break;
31052159047fSniklas 
31062159047fSniklas 	  if (In[i] == 0)
31072159047fSniklas 	    truncate = 0;
31082159047fSniklas 
31092159047fSniklas 	  if ((i == 8) || (In[i] == 0))
31102159047fSniklas 	    {
3111*007c2a45Smiod 	      /* They are:  Copy up to 31 characters
3112*007c2a45Smiod 	         to the output string.  */
31132159047fSniklas 	      i = 8;
31142159047fSniklas 	      while ((--i >= 0) && (*In))
31152159047fSniklas 		switch (vms_name_mapping){
3116c074d1c9Sdrahn 		case 0: *Out++ = TOUPPER (*In++);
31172159047fSniklas 		  break;
31182159047fSniklas 		case 3: *Out++ = *In++;
31192159047fSniklas 		  break;
3120c074d1c9Sdrahn 		case 2: *Out++ = TOLOWER (*In++);
31212159047fSniklas 		  break;
31222159047fSniklas 		}
31232159047fSniklas 	    }
31242159047fSniklas 	}
31252159047fSniklas     }
3126*007c2a45Smiod   /* If there were any uppercase characters in the name we
3127*007c2a45Smiod      take on the case hacking string.  */
31282159047fSniklas 
3129*007c2a45Smiod   /* Old behavior for regular GNU-C compiler.  */
31302159047fSniklas   if (!flag_hash_long_names)
31312159047fSniklas     truncate = 0;
31322159047fSniklas   if ((Case_Hack_Bits != 0) || (truncate == 1))
31332159047fSniklas     {
31342159047fSniklas       if (truncate == 0)
31352159047fSniklas 	{
31362159047fSniklas 	  *Out++ = '_';
31372159047fSniklas 	  for (i = 0; i < 6; i++)
31382159047fSniklas 	    {
31392159047fSniklas 	      *Out++ = Hex_Table[Case_Hack_Bits & 0xf];
31402159047fSniklas 	      Case_Hack_Bits >>= 4;
31412159047fSniklas 	    }
31422159047fSniklas 	  *Out++ = 'X';
31432159047fSniklas 	}
31442159047fSniklas       else
31452159047fSniklas 	{
3146*007c2a45Smiod 	  Out = pnt;		/* Cut back to 23 characters maximum.  */
31472159047fSniklas 	  *Out++ = '_';
31482159047fSniklas 	  for (i = 0; i < 7; i++)
31492159047fSniklas 	    {
31502159047fSniklas 	      init = result & 0x01f;
31512159047fSniklas 	      *Out++ = (init < 10) ? ('0' + init) : ('A' + init - 10);
31522159047fSniklas 	      result = result >> 5;
31532159047fSniklas 	    }
31542159047fSniklas 	}
3155*007c2a45Smiod     }
3156*007c2a45Smiod   /* Done.  */
31572159047fSniklas   *Out = 0;
31582159047fSniklas   if (truncate == 1 && flag_hash_long_names && flag_show_after_trunc)
3159f7cc78ecSespie     as_tsktsk (_("Symbol %s replaced by %s\n"), old_name, new_name);
31602159047fSniklas }
31612159047fSniklas 
31622159047fSniklas 
3163*007c2a45Smiod /* Scan a symbol name for a psect attribute specification.  */
3164*007c2a45Smiod 
31652159047fSniklas #define GLOBALSYMBOL_BIT	0x10000
31662159047fSniklas #define GLOBALVALUE_BIT		0x20000
31672159047fSniklas 
31682159047fSniklas static void
VMS_Modify_Psect_Attributes(const char * Name,int * Attribute_Pointer)3169*007c2a45Smiod VMS_Modify_Psect_Attributes (const char *Name, int *Attribute_Pointer)
31702159047fSniklas {
3171*007c2a45Smiod   int i;
3172*007c2a45Smiod   const char *cp;
31732159047fSniklas   int Negate;
31742159047fSniklas   static const struct
31752159047fSniklas   {
31762159047fSniklas     const char *Name;
31772159047fSniklas     int Value;
31782159047fSniklas   } Attributes[] =
31792159047fSniklas   {
31802159047fSniklas     {"PIC", GPS_S_M_PIC},
31812159047fSniklas     {"LIB", GPS_S_M_LIB},
31822159047fSniklas     {"OVR", GPS_S_M_OVR},
31832159047fSniklas     {"REL", GPS_S_M_REL},
31842159047fSniklas     {"GBL", GPS_S_M_GBL},
31852159047fSniklas     {"SHR", GPS_S_M_SHR},
31862159047fSniklas     {"EXE", GPS_S_M_EXE},
31872159047fSniklas     {"RD", GPS_S_M_RD},
31882159047fSniklas     {"WRT", GPS_S_M_WRT},
31892159047fSniklas     {"VEC", GPS_S_M_VEC},
31902159047fSniklas     {"GLOBALSYMBOL", GLOBALSYMBOL_BIT},
31912159047fSniklas     {"GLOBALVALUE", GLOBALVALUE_BIT},
31922159047fSniklas     {0, 0}
31932159047fSniklas   };
31942159047fSniklas 
3195*007c2a45Smiod   /* Kill leading "_".  */
31962159047fSniklas   if (*Name == '_')
31972159047fSniklas     Name++;
3198*007c2a45Smiod   /* Check for a PSECT attribute list.  */
31992159047fSniklas   if (!HAS_PSECT_ATTRIBUTES (Name))
3200*007c2a45Smiod     return;
3201*007c2a45Smiod   /* Skip the attribute list indicator.  */
32022159047fSniklas   Name += PSECT_ATTRIBUTES_STRING_LENGTH;
3203*007c2a45Smiod   /* Process the attributes ("_" separated, "$" terminated).  */
32042159047fSniklas   while (*Name != '$')
32052159047fSniklas     {
3206*007c2a45Smiod       /* Assume not negating.  */
32072159047fSniklas       Negate = 0;
3208*007c2a45Smiod       /* Check for "NO".  */
32092159047fSniklas       if ((Name[0] == 'N') && (Name[1] == 'O'))
32102159047fSniklas 	{
3211*007c2a45Smiod 	  /* We are negating (and skip the NO).  */
32122159047fSniklas 	  Negate = 1;
32132159047fSniklas 	  Name += 2;
32142159047fSniklas 	}
3215*007c2a45Smiod       /* Find the token delimiter.  */
32162159047fSniklas       cp = Name;
32172159047fSniklas       while (*cp && (*cp != '_') && (*cp != '$'))
32182159047fSniklas 	cp++;
3219*007c2a45Smiod       /* Look for the token in the attribute list.  */
32202159047fSniklas       for (i = 0; Attributes[i].Name; i++)
32212159047fSniklas 	{
3222*007c2a45Smiod 	  /* If the strings match, set/clear the attr.  */
32232159047fSniklas 	  if (strncmp (Name, Attributes[i].Name, cp - Name) == 0)
32242159047fSniklas 	    {
3225*007c2a45Smiod 	      /* Set or clear.  */
32262159047fSniklas 	      if (Negate)
32272159047fSniklas 		*Attribute_Pointer &=
32282159047fSniklas 		  ~Attributes[i].Value;
32292159047fSniklas 	      else
32302159047fSniklas 		*Attribute_Pointer |=
32312159047fSniklas 		  Attributes[i].Value;
3232*007c2a45Smiod 	      /* Done.  */
32332159047fSniklas 	      break;
32342159047fSniklas 	    }
32352159047fSniklas 	}
3236*007c2a45Smiod       /* Now skip the attribute.  */
32372159047fSniklas       Name = cp;
32382159047fSniklas       if (*Name == '_')
32392159047fSniklas 	Name++;
32402159047fSniklas     }
32412159047fSniklas }
32422159047fSniklas 
32432159047fSniklas 
32442159047fSniklas #define GBLSYM_REF 0
32452159047fSniklas #define GBLSYM_DEF 1
32462159047fSniklas #define GBLSYM_VAL 2
32472159047fSniklas #define GBLSYM_LCL 4	/* not GBL after all...  */
3248f7cc78ecSespie #define GBLSYM_WEAK 8
32492159047fSniklas 
3250*007c2a45Smiod /* Define a global symbol (or possibly a local one).  */
3251*007c2a45Smiod 
32522159047fSniklas static void
VMS_Global_Symbol_Spec(const char * Name,int Psect_Number,int Psect_Offset,int Flags)3253*007c2a45Smiod VMS_Global_Symbol_Spec (const char *Name, int Psect_Number, int Psect_Offset, int Flags)
32542159047fSniklas {
32552159047fSniklas   char Local[32];
32562159047fSniklas 
3257*007c2a45Smiod   /* We are writing a GSD record.  */
32582159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_GSD);
3259*007c2a45Smiod 
3260*007c2a45Smiod   /* If the buffer is empty we must insert the GSD record type.  */
32612159047fSniklas   if (Object_Record_Offset == 0)
32622159047fSniklas     PUT_CHAR (OBJ_S_C_GSD);
3263*007c2a45Smiod 
3264*007c2a45Smiod   /* We are writing a Global (or local) symbol definition subrecord.  */
32652159047fSniklas   PUT_CHAR ((Flags & GBLSYM_LCL) != 0 ? GSD_S_C_LSY :
32662159047fSniklas 	    ((unsigned) Psect_Number <= 255) ? GSD_S_C_SYM : GSD_S_C_SYMW);
3267*007c2a45Smiod 
3268*007c2a45Smiod   /* Data type is undefined.  */
32692159047fSniklas   PUT_CHAR (0);
3270*007c2a45Smiod 
3271*007c2a45Smiod   /* Switch on Definition/Reference.  */
32722159047fSniklas   if ((Flags & GBLSYM_DEF) == 0)
32732159047fSniklas     {
3274*007c2a45Smiod       /* Reference.  */
32752159047fSniklas       PUT_SHORT (((Flags & GBLSYM_VAL) == 0) ? GSY_S_M_REL : 0);
32762159047fSniklas       if ((Flags & GBLSYM_LCL) != 0)	/* local symbols have extra field */
32772159047fSniklas 	PUT_SHORT (Current_Environment);
32782159047fSniklas     }
32792159047fSniklas   else
32802159047fSniklas     {
3281f7cc78ecSespie       int sym_flags;
3282f7cc78ecSespie 
3283*007c2a45Smiod       /* Definition
3284*007c2a45Smiod          [ assert (LSY_S_M_DEF == GSY_S_M_DEF && LSY_S_M_REL == GSY_S_M_REL); ].  */
3285f7cc78ecSespie       sym_flags = GSY_S_M_DEF;
3286f7cc78ecSespie       if (Flags & GBLSYM_WEAK)
3287f7cc78ecSespie 	sym_flags |= GSY_S_M_WEAK;
3288f7cc78ecSespie       if ((Flags & GBLSYM_VAL) == 0)
3289f7cc78ecSespie 	sym_flags |= GSY_S_M_REL;
3290f7cc78ecSespie       PUT_SHORT (sym_flags);
32912159047fSniklas       if ((Flags & GBLSYM_LCL) != 0)	/* local symbols have extra field */
32922159047fSniklas 	PUT_SHORT (Current_Environment);
3293*007c2a45Smiod 
3294*007c2a45Smiod       /* Psect Number.  */
32952159047fSniklas       if ((Flags & GBLSYM_LCL) == 0 && (unsigned) Psect_Number <= 255)
32962159047fSniklas 	PUT_CHAR (Psect_Number);
32972159047fSniklas       else
32982159047fSniklas 	PUT_SHORT (Psect_Number);
3299*007c2a45Smiod 
3300*007c2a45Smiod       /* Offset.  */
33012159047fSniklas       PUT_LONG (Psect_Offset);
33022159047fSniklas     }
3303*007c2a45Smiod 
3304*007c2a45Smiod   /* Finally, the global symbol name.  */
33052159047fSniklas   VMS_Case_Hack_Symbol (Name, Local);
33062159047fSniklas   PUT_COUNTED_STRING (Local);
3307*007c2a45Smiod 
3308*007c2a45Smiod   /* Flush the buffer if it is more than 75% full.  */
33092159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
33102159047fSniklas     Flush_VMS_Object_Record_Buffer ();
33112159047fSniklas }
33122159047fSniklas 
3313*007c2a45Smiod /* Define an environment to support local symbol references.
3314*007c2a45Smiod    This is just to mollify the linker; we don't actually do
3315*007c2a45Smiod    anything useful with it.  */
3316*007c2a45Smiod 
33172159047fSniklas static void
VMS_Local_Environment_Setup(const char * Env_Name)3318*007c2a45Smiod VMS_Local_Environment_Setup (const char *Env_Name)
33192159047fSniklas {
33202159047fSniklas   /* We are writing a GSD record.  */
33212159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_GSD);
33222159047fSniklas   /* If the buffer is empty we must insert the GSD record type.  */
33232159047fSniklas   if (Object_Record_Offset == 0)
33242159047fSniklas     PUT_CHAR (OBJ_S_C_GSD);
33252159047fSniklas   /* We are writing an ENV subrecord.  */
33262159047fSniklas   PUT_CHAR (GSD_S_C_ENV);
33272159047fSniklas 
33282159047fSniklas   ++Current_Environment;	/* index of environment being defined */
33292159047fSniklas 
33302159047fSniklas   /* ENV$W_FLAGS:  we are defining the next environment.  It's not nested.  */
33312159047fSniklas   PUT_SHORT (ENV_S_M_DEF);
33322159047fSniklas   /* ENV$W_ENVINDX:  index is always 0 for non-nested definitions.  */
33332159047fSniklas   PUT_SHORT (0);
33342159047fSniklas 
33352159047fSniklas   /* ENV$B_NAMLNG + ENV$T_NAME:  environment name in ASCIC format.  */
33362159047fSniklas   if (!Env_Name) Env_Name = "";
33372159047fSniklas   PUT_COUNTED_STRING ((char *)Env_Name);
33382159047fSniklas 
33392159047fSniklas   /* Flush the buffer if it is more than 75% full.  */
33402159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
33412159047fSniklas     Flush_VMS_Object_Record_Buffer ();
33422159047fSniklas }
33432159047fSniklas 
33442159047fSniklas 
3345*007c2a45Smiod /* Define a psect.  */
3346*007c2a45Smiod 
33472159047fSniklas static int
VMS_Psect_Spec(const char * Name,int Size,enum ps_type Type,struct VMS_Symbol * vsp)3348*007c2a45Smiod VMS_Psect_Spec (const char *Name, int Size, enum ps_type Type, struct VMS_Symbol *vsp)
33492159047fSniklas {
33502159047fSniklas   char Local[32];
33512159047fSniklas   int Psect_Attributes;
33522159047fSniklas 
3353*007c2a45Smiod   /* Generate the appropriate PSECT flags given the PSECT type.  */
33542159047fSniklas   switch (Type)
33552159047fSniklas     {
33562159047fSniklas     case ps_TEXT:
33572159047fSniklas       /* Text psects are PIC,noOVR,REL,noGBL,SHR,EXE,RD,noWRT.  */
33582159047fSniklas       Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_SHR|GPS_S_M_EXE
33592159047fSniklas 			  |GPS_S_M_RD);
33602159047fSniklas       break;
33612159047fSniklas     case ps_DATA:
33622159047fSniklas       /* Data psects are PIC,noOVR,REL,noGBL,noSHR,noEXE,RD,WRT.  */
33632159047fSniklas       Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_RD|GPS_S_M_WRT);
33642159047fSniklas       break;
33652159047fSniklas     case ps_COMMON:
3366f7cc78ecSespie       /* Common block psects are:  PIC,OVR,REL,GBL,noSHR,noEXE,RD,WRT.  */
33672159047fSniklas       Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL
3368f7cc78ecSespie 			  |GPS_S_M_RD|GPS_S_M_WRT);
33692159047fSniklas       break;
33702159047fSniklas     case ps_CONST:
3371f7cc78ecSespie       /* Const data psects are:  PIC,OVR,REL,GBL,noSHR,noEXE,RD,noWRT.  */
33722159047fSniklas       Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_OVR|GPS_S_M_REL|GPS_S_M_GBL
3373f7cc78ecSespie 			  |GPS_S_M_RD);
3374f7cc78ecSespie       break;
3375f7cc78ecSespie     case ps_CTORS:
3376f7cc78ecSespie       /* Ctor psects are PIC,noOVR,REL,GBL,noSHR,noEXE,RD,noWRT.  */
3377f7cc78ecSespie       Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD);
3378f7cc78ecSespie       break;
3379f7cc78ecSespie     case ps_DTORS:
3380f7cc78ecSespie       /* Dtor psects are PIC,noOVR,REL,GBL,noSHR,noEXE,RD,noWRT.  */
3381f7cc78ecSespie       Psect_Attributes = (GPS_S_M_PIC|GPS_S_M_REL|GPS_S_M_GBL|GPS_S_M_RD);
33822159047fSniklas       break;
33832159047fSniklas     default:
33842159047fSniklas       /* impossible */
3385f7cc78ecSespie       error (_("Unknown VMS psect type (%ld)"), (long) Type);
33862159047fSniklas       break;
33872159047fSniklas     }
3388*007c2a45Smiod   /* Modify the psect attributes according to any attribute string.  */
33892159047fSniklas   if (vsp && S_GET_TYPE (vsp->Symbol) == N_ABS)
33902159047fSniklas     Psect_Attributes |= GLOBALVALUE_BIT;
33912159047fSniklas   else if (HAS_PSECT_ATTRIBUTES (Name))
33922159047fSniklas     VMS_Modify_Psect_Attributes (Name, &Psect_Attributes);
3393*007c2a45Smiod   /* Check for globalref/def/val.  */
33942159047fSniklas   if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
33952159047fSniklas     {
3396*007c2a45Smiod       /* globalvalue symbols were generated before. This code
3397*007c2a45Smiod          prevents unsightly psect buildup, and makes sure that
3398*007c2a45Smiod          fixup references are emitted correctly.  */
33992159047fSniklas       vsp->Psect_Index = -1;	/* to catch errors */
34002159047fSniklas       S_SET_TYPE (vsp->Symbol, N_UNDF);		/* make refs work */
34012159047fSniklas       return 1;			/* decrement psect counter */
34022159047fSniklas     }
34032159047fSniklas 
34042159047fSniklas   if ((Psect_Attributes & GLOBALSYMBOL_BIT) != 0)
34052159047fSniklas     {
34062159047fSniklas       switch (S_GET_RAW_TYPE (vsp->Symbol))
34072159047fSniklas 	{
34082159047fSniklas 	case N_UNDF | N_EXT:
34092159047fSniklas 	  VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
34102159047fSniklas 				  vsp->Psect_Offset, GBLSYM_REF);
34112159047fSniklas 	  vsp->Psect_Index = -1;
34122159047fSniklas 	  S_SET_TYPE (vsp->Symbol, N_UNDF);
3413*007c2a45Smiod 	  /* Return and indicate no psect.  */
3414*007c2a45Smiod 	  return 1;
3415*007c2a45Smiod 
34162159047fSniklas 	case N_DATA | N_EXT:
34172159047fSniklas 	  VMS_Global_Symbol_Spec (Name, vsp->Psect_Index,
34182159047fSniklas 				  vsp->Psect_Offset, GBLSYM_DEF);
3419*007c2a45Smiod 	  /* In this case we still generate the psect. */
34202159047fSniklas 	  break;
3421*007c2a45Smiod 
34222159047fSniklas 	default:
3423f7cc78ecSespie 	  as_fatal (_("Globalsymbol attribute for symbol %s was unexpected."),
34242159047fSniklas 		    Name);
34252159047fSniklas 	  break;
3426*007c2a45Smiod 	}
34272159047fSniklas     }
34282159047fSniklas 
3429*007c2a45Smiod   /* Clear out the globalref/def stuff.  */
3430*007c2a45Smiod   Psect_Attributes &= 0xffff;
3431*007c2a45Smiod   /* We are writing a GSD record.  */
34322159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_GSD);
3433*007c2a45Smiod   /* If the buffer is empty we must insert the GSD record type.  */
34342159047fSniklas   if (Object_Record_Offset == 0)
34352159047fSniklas     PUT_CHAR (OBJ_S_C_GSD);
3436*007c2a45Smiod   /* We are writing a PSECT definition subrecord.  */
34372159047fSniklas   PUT_CHAR (GSD_S_C_PSC);
3438*007c2a45Smiod   /* Psects are always LONGWORD aligned.  */
34392159047fSniklas   PUT_CHAR (2);
3440*007c2a45Smiod   /* Specify the psect attributes.  */
34412159047fSniklas   PUT_SHORT (Psect_Attributes);
3442*007c2a45Smiod   /* Specify the allocation.  */
34432159047fSniklas   PUT_LONG (Size);
3444*007c2a45Smiod   /* Finally, the psect name.  */
34452159047fSniklas   VMS_Case_Hack_Symbol (Name, Local);
34462159047fSniklas   PUT_COUNTED_STRING (Local);
3447*007c2a45Smiod   /* Flush the buffer if it is more than 75% full.  */
34482159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
34492159047fSniklas     Flush_VMS_Object_Record_Buffer ();
34502159047fSniklas   return 0;
34512159047fSniklas }
34522159047fSniklas 
34532159047fSniklas 
34542159047fSniklas /* Given the pointer to a symbol we calculate how big the data at the
34552159047fSniklas    symbol is.  We do this by looking for the next symbol (local or global)
34562159047fSniklas    which will indicate the start of another datum.  */
34572159047fSniklas 
34582159047fSniklas static offsetT
VMS_Initialized_Data_Size(symbolS * s0P,unsigned End_Of_Data)3459*007c2a45Smiod VMS_Initialized_Data_Size (symbolS *s0P, unsigned End_Of_Data)
34602159047fSniklas {
34612159047fSniklas   symbolS *s1P;
34622159047fSniklas   valueT s0P_val = S_GET_VALUE (s0P), s1P_val,
34632159047fSniklas 	 nearest_val = (valueT) End_Of_Data;
34642159047fSniklas 
34652159047fSniklas   /* Find the nearest symbol what follows this one.  */
34662159047fSniklas   for (s1P = symbol_rootP; s1P; s1P = symbol_next (s1P))
34672159047fSniklas     {
34682159047fSniklas       /* The data type must match.  */
34692159047fSniklas       if (S_GET_TYPE (s1P) != N_DATA)
34702159047fSniklas 	continue;
34712159047fSniklas       s1P_val = S_GET_VALUE (s1P);
34722159047fSniklas       if (s1P_val > s0P_val && s1P_val < nearest_val)
34732159047fSniklas 	nearest_val = s1P_val;
34742159047fSniklas     }
34752159047fSniklas   /* Calculate its size.  */
34762159047fSniklas   return (offsetT) (nearest_val - s0P_val);
34772159047fSniklas }
34782159047fSniklas 
34792159047fSniklas /* Check symbol names for the Psect hack with a globalvalue, and then
34802159047fSniklas    generate globalvalues for those that have it.  */
34812159047fSniklas 
34822159047fSniklas static void
VMS_Emit_Globalvalues(unsigned text_siz,unsigned data_siz,char * Data_Segment)3483*007c2a45Smiod VMS_Emit_Globalvalues (unsigned text_siz, unsigned data_siz,
3484*007c2a45Smiod 		       char *Data_Segment)
34852159047fSniklas {
3486*007c2a45Smiod   symbolS *sp;
34872159047fSniklas   char *stripped_name, *Name;
34882159047fSniklas   int Size;
34892159047fSniklas   int Psect_Attributes;
34902159047fSniklas   int globalvalue;
34912159047fSniklas   int typ, abstyp;
34922159047fSniklas 
3493*007c2a45Smiod   /* Scan the symbol table for globalvalues, and emit def/ref when
3494*007c2a45Smiod      required.  These will be caught again later and converted to
3495*007c2a45Smiod      N_UNDF.  */
34962159047fSniklas   for (sp = symbol_rootP; sp; sp = sp->sy_next)
34972159047fSniklas     {
34982159047fSniklas       typ = S_GET_RAW_TYPE (sp);
34992159047fSniklas       abstyp = ((typ & ~N_EXT) == N_ABS);
3500*007c2a45Smiod       /* See if this is something we want to look at.  */
35012159047fSniklas       if (!abstyp &&
35022159047fSniklas 	  typ != (N_DATA | N_EXT) &&
35032159047fSniklas 	  typ != (N_UNDF | N_EXT))
35042159047fSniklas 	continue;
3505*007c2a45Smiod       /* See if this has globalvalue specification.  */
35062159047fSniklas       Name = S_GET_NAME (sp);
35072159047fSniklas 
35082159047fSniklas       if (abstyp)
35092159047fSniklas 	{
35102159047fSniklas 	  stripped_name = 0;
35112159047fSniklas 	  Psect_Attributes = GLOBALVALUE_BIT;
35122159047fSniklas 	}
35132159047fSniklas       else if (HAS_PSECT_ATTRIBUTES (Name))
35142159047fSniklas 	{
3515*007c2a45Smiod 	  stripped_name = xmalloc (strlen (Name) + 1);
35162159047fSniklas 	  strcpy (stripped_name, Name);
35172159047fSniklas 	  Psect_Attributes = 0;
35182159047fSniklas 	  VMS_Modify_Psect_Attributes (stripped_name, &Psect_Attributes);
35192159047fSniklas 	}
35202159047fSniklas       else
35212159047fSniklas 	continue;
35222159047fSniklas 
35232159047fSniklas       if ((Psect_Attributes & GLOBALVALUE_BIT) != 0)
35242159047fSniklas 	{
35252159047fSniklas 	  switch (typ)
35262159047fSniklas 	    {
35272159047fSniklas 	    case N_ABS:
35282159047fSniklas 	      /* Local symbol references will want
35292159047fSniklas 		 to have an environment defined.  */
35302159047fSniklas 	      if (Current_Environment < 0)
35312159047fSniklas 		VMS_Local_Environment_Setup (".N_ABS");
35322159047fSniklas 	      VMS_Global_Symbol_Spec (Name, 0,
35332159047fSniklas 				      S_GET_VALUE (sp),
35342159047fSniklas 				      GBLSYM_DEF|GBLSYM_VAL|GBLSYM_LCL);
35352159047fSniklas 	      break;
35362159047fSniklas 	    case N_ABS | N_EXT:
35372159047fSniklas 	      VMS_Global_Symbol_Spec (Name, 0,
35382159047fSniklas 				      S_GET_VALUE (sp),
35392159047fSniklas 				      GBLSYM_DEF|GBLSYM_VAL);
35402159047fSniklas 	      break;
35412159047fSniklas 	    case N_UNDF | N_EXT:
35422159047fSniklas 	      VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL);
35432159047fSniklas 	      break;
35442159047fSniklas 	    case N_DATA | N_EXT:
35452159047fSniklas 	      Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
35462159047fSniklas 	      if (Size > 4)
3547f7cc78ecSespie 		error (_("Invalid data type for globalvalue"));
35482159047fSniklas 	      globalvalue = md_chars_to_number (Data_Segment +
35492159047fSniklas 		     S_GET_VALUE (sp) - text_siz , Size);
35502159047fSniklas 	      /* Three times for good luck.  The linker seems to get confused
35512159047fSniklas 	         if there are fewer than three */
35522159047fSniklas 	      VMS_Global_Symbol_Spec (stripped_name, 0, 0, GBLSYM_VAL);
35532159047fSniklas 	      VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue,
35542159047fSniklas 				      GBLSYM_DEF|GBLSYM_VAL);
35552159047fSniklas 	      VMS_Global_Symbol_Spec (stripped_name, 0, globalvalue,
35562159047fSniklas 				      GBLSYM_DEF|GBLSYM_VAL);
35572159047fSniklas 	      break;
35582159047fSniklas 	    default:
3559f7cc78ecSespie 	      as_warn (_("Invalid globalvalue of %s"), stripped_name);
35602159047fSniklas 	      break;
3561*007c2a45Smiod 	    }
3562*007c2a45Smiod 	}
3563*007c2a45Smiod 
3564*007c2a45Smiod       if (stripped_name)
3565*007c2a45Smiod 	free (stripped_name);
3566*007c2a45Smiod     }
35672159047fSniklas 
35682159047fSniklas }
35692159047fSniklas 
35702159047fSniklas 
3571*007c2a45Smiod /* Define a procedure entry pt/mask.  */
3572*007c2a45Smiod 
35732159047fSniklas static void
VMS_Procedure_Entry_Pt(char * Name,int Psect_Number,int Psect_Offset,int Entry_Mask)3574*007c2a45Smiod VMS_Procedure_Entry_Pt (char *Name, int Psect_Number, int Psect_Offset,
3575*007c2a45Smiod 			int Entry_Mask)
35762159047fSniklas {
35772159047fSniklas   char Local[32];
35782159047fSniklas 
3579*007c2a45Smiod   /* We are writing a GSD record.  */
35802159047fSniklas   Set_VMS_Object_File_Record (OBJ_S_C_GSD);
3581*007c2a45Smiod   /* If the buffer is empty we must insert the GSD record type.  */
35822159047fSniklas   if (Object_Record_Offset == 0)
35832159047fSniklas     PUT_CHAR (OBJ_S_C_GSD);
3584*007c2a45Smiod   /* We are writing a Procedure Entry Pt/Mask subrecord.  */
35852159047fSniklas   PUT_CHAR (((unsigned) Psect_Number <= 255) ? GSD_S_C_EPM : GSD_S_C_EPMW);
3586*007c2a45Smiod   /* Data type is undefined.  */
35872159047fSniklas   PUT_CHAR (0);
3588*007c2a45Smiod   /* Flags = "RELOCATABLE" and "DEFINED".  */
35892159047fSniklas   PUT_SHORT (GSY_S_M_DEF | GSY_S_M_REL);
3590*007c2a45Smiod   /* Psect Number.  */
35912159047fSniklas   if ((unsigned) Psect_Number <= 255)
35922159047fSniklas     PUT_CHAR (Psect_Number);
35932159047fSniklas   else
35942159047fSniklas     PUT_SHORT (Psect_Number);
3595*007c2a45Smiod   /* Offset.  */
35962159047fSniklas   PUT_LONG (Psect_Offset);
3597*007c2a45Smiod   /* Entry mask.  */
35982159047fSniklas   PUT_SHORT (Entry_Mask);
3599*007c2a45Smiod   /* Finally, the global symbol name.  */
36002159047fSniklas   VMS_Case_Hack_Symbol (Name, Local);
36012159047fSniklas   PUT_COUNTED_STRING (Local);
3602*007c2a45Smiod   /* Flush the buffer if it is more than 75% full.  */
36032159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
36042159047fSniklas     Flush_VMS_Object_Record_Buffer ();
36052159047fSniklas }
36062159047fSniklas 
36072159047fSniklas 
3608*007c2a45Smiod /* Set the current location counter to a particular Psect and Offset.  */
3609*007c2a45Smiod 
36102159047fSniklas static void
VMS_Set_Psect(int Psect_Index,int Offset,int Record_Type)3611*007c2a45Smiod VMS_Set_Psect (int Psect_Index, int Offset, int Record_Type)
36122159047fSniklas {
3613*007c2a45Smiod   /* We are writing a "Record_Type" record.  */
36142159047fSniklas   Set_VMS_Object_File_Record (Record_Type);
3615*007c2a45Smiod   /* If the buffer is empty we must insert the record type.  */
36162159047fSniklas   if (Object_Record_Offset == 0)
36172159047fSniklas     PUT_CHAR (Record_Type);
3618*007c2a45Smiod   /* Stack the Psect base + Offset.  */
36192159047fSniklas   vms_tir_stack_psect (Psect_Index, Offset, 0);
3620*007c2a45Smiod   /* Set relocation base.  */
36212159047fSniklas   PUT_CHAR (TIR_S_C_CTL_SETRB);
3622*007c2a45Smiod   /* Flush the buffer if it is more than 75% full.  */
36232159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
36242159047fSniklas     Flush_VMS_Object_Record_Buffer ();
36252159047fSniklas }
36262159047fSniklas 
36272159047fSniklas 
3628*007c2a45Smiod /* Store repeated immediate data in current Psect.  */
36292159047fSniklas 
3630*007c2a45Smiod static void
VMS_Store_Repeated_Data(int Repeat_Count,char * Pointer,int Size,int Record_Type)3631*007c2a45Smiod VMS_Store_Repeated_Data (int Repeat_Count, char *Pointer, int Size,
3632*007c2a45Smiod 			 int Record_Type)
3633*007c2a45Smiod {
3634*007c2a45Smiod   /* Ignore zero bytes/words/longwords.  */
36352159047fSniklas   switch (Size)
36362159047fSniklas     {
36372159047fSniklas     case 4:
36382159047fSniklas       if (Pointer[3] != 0 || Pointer[2] != 0) break;
36392159047fSniklas       /* else FALLTHRU */
36402159047fSniklas     case 2:
36412159047fSniklas       if (Pointer[1] != 0) break;
36422159047fSniklas       /* else FALLTHRU */
36432159047fSniklas     case 1:
36442159047fSniklas       if (Pointer[0] != 0) break;
36452159047fSniklas       /* zero value */
36462159047fSniklas       return;
36472159047fSniklas     default:
36482159047fSniklas       break;
36492159047fSniklas     }
3650*007c2a45Smiod   /* If the data is too big for a TIR_S_C_STO_RIVB sub-record
3651*007c2a45Smiod      then we do it manually.  */
36522159047fSniklas   if (Size > 255)
36532159047fSniklas     {
36542159047fSniklas       while (--Repeat_Count >= 0)
36552159047fSniklas 	VMS_Store_Immediate_Data (Pointer, Size, Record_Type);
36562159047fSniklas       return;
36572159047fSniklas     }
3658*007c2a45Smiod   /* We are writing a "Record_Type" record.  */
36592159047fSniklas   Set_VMS_Object_File_Record (Record_Type);
3660*007c2a45Smiod   /* If the buffer is empty we must insert record type.  */
36612159047fSniklas   if (Object_Record_Offset == 0)
36622159047fSniklas     PUT_CHAR (Record_Type);
3663*007c2a45Smiod   /* Stack the repeat count.  */
36642159047fSniklas   PUT_CHAR (TIR_S_C_STA_LW);
36652159047fSniklas   PUT_LONG (Repeat_Count);
3666*007c2a45Smiod   /* And now the command and its data.  */
36672159047fSniklas   PUT_CHAR (TIR_S_C_STO_RIVB);
36682159047fSniklas   PUT_CHAR (Size);
36692159047fSniklas   while (--Size >= 0)
36702159047fSniklas     PUT_CHAR (*Pointer++);
3671*007c2a45Smiod   /* Flush the buffer if it is more than 75% full.  */
36722159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
36732159047fSniklas     Flush_VMS_Object_Record_Buffer ();
36742159047fSniklas }
36752159047fSniklas 
36762159047fSniklas 
3677*007c2a45Smiod /* Store a Position Independent Reference.  */
3678*007c2a45Smiod 
36792159047fSniklas static void
VMS_Store_PIC_Symbol_Reference(symbolS * Symbol,int Offset,int PC_Relative,int Psect,int Psect_Offset,int Record_Type)3680*007c2a45Smiod VMS_Store_PIC_Symbol_Reference (symbolS *Symbol, int Offset, int PC_Relative,
3681*007c2a45Smiod 				int Psect, int Psect_Offset, int Record_Type)
36822159047fSniklas {
3683*007c2a45Smiod   struct VMS_Symbol *vsp = Symbol->sy_obj;
36842159047fSniklas   char Local[32];
36852159047fSniklas   int local_sym = 0;
36862159047fSniklas 
3687*007c2a45Smiod   /* We are writing a "Record_Type" record.  */
36882159047fSniklas   Set_VMS_Object_File_Record (Record_Type);
3689*007c2a45Smiod   /* If the buffer is empty we must insert record type.  */
36902159047fSniklas   if (Object_Record_Offset == 0)
36912159047fSniklas     PUT_CHAR (Record_Type);
3692*007c2a45Smiod   /* Set to the appropriate offset in the Psect.
3693*007c2a45Smiod      For a Code reference we need to fix the operand
3694*007c2a45Smiod      specifier as well, so back up 1 byte;
3695*007c2a45Smiod      for a Data reference we just store HERE.  */
36962159047fSniklas   VMS_Set_Psect (Psect,
36972159047fSniklas 		 PC_Relative ? Psect_Offset - 1 : Psect_Offset,
36982159047fSniklas 		 Record_Type);
3699*007c2a45Smiod   /* Make sure we are still generating a "Record Type" record.  */
37002159047fSniklas   if (Object_Record_Offset == 0)
37012159047fSniklas     PUT_CHAR (Record_Type);
3702*007c2a45Smiod   /* Dispatch on symbol type (so we can stack its value).  */
37032159047fSniklas   switch (S_GET_RAW_TYPE (Symbol))
37042159047fSniklas     {
3705*007c2a45Smiod       /* Global symbol.  */
37062159047fSniklas     case N_ABS:
37072159047fSniklas       local_sym = 1;
37082159047fSniklas       /*FALLTHRU*/
37092159047fSniklas     case N_ABS | N_EXT:
37102159047fSniklas #ifdef	NOT_VAX_11_C_COMPATIBLE
37112159047fSniklas     case N_UNDF | N_EXT:
37122159047fSniklas     case N_DATA | N_EXT:
37132159047fSniklas #endif	/* NOT_VAX_11_C_COMPATIBLE */
37142159047fSniklas     case N_UNDF:
37152159047fSniklas     case N_TEXT | N_EXT:
3716*007c2a45Smiod       /* Get the symbol name (case hacked).  */
37172159047fSniklas       VMS_Case_Hack_Symbol (S_GET_NAME (Symbol), Local);
3718*007c2a45Smiod       /* Stack the global symbol value.  */
37192159047fSniklas       if (!local_sym)
37202159047fSniklas 	{
37212159047fSniklas 	  PUT_CHAR (TIR_S_C_STA_GBL);
37222159047fSniklas 	}
37232159047fSniklas       else
37242159047fSniklas 	{
37252159047fSniklas 	  /* Local symbols have an extra field.  */
37262159047fSniklas 	  PUT_CHAR (TIR_S_C_STA_LSY);
37272159047fSniklas 	  PUT_SHORT (Current_Environment);
37282159047fSniklas 	}
37292159047fSniklas       PUT_COUNTED_STRING (Local);
37302159047fSniklas       if (Offset)
37312159047fSniklas 	{
3732*007c2a45Smiod 	  /* Stack the longword offset.  */
37332159047fSniklas 	  PUT_CHAR (TIR_S_C_STA_LW);
37342159047fSniklas 	  PUT_LONG (Offset);
3735*007c2a45Smiod 	  /* Add the two, leaving the result on the stack.  */
37362159047fSniklas 	  PUT_CHAR (TIR_S_C_OPR_ADD);
37372159047fSniklas 	}
37382159047fSniklas       break;
3739*007c2a45Smiod       /* Uninitialized local data.  */
37402159047fSniklas     case N_BSS:
3741*007c2a45Smiod       /* Stack the Psect (+offset).  */
37422159047fSniklas       vms_tir_stack_psect (vsp->Psect_Index,
37432159047fSniklas 			   vsp->Psect_Offset + Offset,
37442159047fSniklas 			   0);
37452159047fSniklas       break;
3746*007c2a45Smiod       /* Local text.  */
37472159047fSniklas     case N_TEXT:
3748*007c2a45Smiod       /* Stack the Psect (+offset).  */
37492159047fSniklas       vms_tir_stack_psect (vsp->Psect_Index,
37502159047fSniklas 			   S_GET_VALUE (Symbol) + Offset,
37512159047fSniklas 			   0);
37522159047fSniklas       break;
3753*007c2a45Smiod       /* Initialized local or global data.  */
37542159047fSniklas     case N_DATA:
37552159047fSniklas #ifndef	NOT_VAX_11_C_COMPATIBLE
37562159047fSniklas     case N_UNDF | N_EXT:
37572159047fSniklas     case N_DATA | N_EXT:
37582159047fSniklas #endif	/* NOT_VAX_11_C_COMPATIBLE */
3759*007c2a45Smiod       /* Stack the Psect (+offset).  */
37602159047fSniklas       vms_tir_stack_psect (vsp->Psect_Index,
37612159047fSniklas 			   vsp->Psect_Offset + Offset,
37622159047fSniklas 			   0);
37632159047fSniklas       break;
37642159047fSniklas     }
3765*007c2a45Smiod   /* Store either a code or data reference.  */
37662159047fSniklas   PUT_CHAR (PC_Relative ? TIR_S_C_STO_PICR : TIR_S_C_STO_PIDR);
3767*007c2a45Smiod   /* Flush the buffer if it is more than 75% full.  */
37682159047fSniklas   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
37692159047fSniklas     Flush_VMS_Object_Record_Buffer ();
37702159047fSniklas }
37712159047fSniklas 
37722159047fSniklas 
3773*007c2a45Smiod /* Check in the text area for an indirect pc-relative reference
3774*007c2a45Smiod    and fix it up with addressing mode 0xff [PC indirect]
3775*007c2a45Smiod 
3776*007c2a45Smiod    THIS SHOULD BE REPLACED BY THE USE OF TIR_S_C_STO_PIRR IN THE
3777*007c2a45Smiod    PIC CODE GENERATING FIXUP ROUTINE.  */
3778*007c2a45Smiod 
37792159047fSniklas static void
VMS_Fix_Indirect_Reference(int Text_Psect,addressT Offset,fragS * fragP,fragS * text_frag_root)3780*007c2a45Smiod VMS_Fix_Indirect_Reference (int Text_Psect, addressT Offset,
3781*007c2a45Smiod 			    fragS *fragP, fragS *text_frag_root)
37822159047fSniklas {
3783*007c2a45Smiod   /* The addressing mode byte is 1 byte before the address.  */
37842159047fSniklas   Offset--;
3785*007c2a45Smiod   /* Is it in THIS frag?  */
37862159047fSniklas   if ((Offset < fragP->fr_address) ||
37872159047fSniklas       (Offset >= (fragP->fr_address + fragP->fr_fix)))
37882159047fSniklas     {
3789*007c2a45Smiod       /* We need to search for the fragment containing this
3790*007c2a45Smiod          Offset.  */
37912159047fSniklas       for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
37922159047fSniklas 	{
37932159047fSniklas 	  if ((Offset >= fragP->fr_address) &&
37942159047fSniklas 	      (Offset < (fragP->fr_address + fragP->fr_fix)))
37952159047fSniklas 	    break;
37962159047fSniklas 	}
3797*007c2a45Smiod       /* If we couldn't find the frag, things are BAD!  */
37982159047fSniklas       if (fragP == 0)
3799f7cc78ecSespie 	error (_("Couldn't find fixup fragment when checking for indirect reference"));
38002159047fSniklas     }
3801*007c2a45Smiod   /* Check for indirect PC relative addressing mode.  */
38022159047fSniklas   if (fragP->fr_literal[Offset - fragP->fr_address] == (char) 0xff)
38032159047fSniklas     {
38042159047fSniklas       static char Address_Mode = (char) 0xff;
38052159047fSniklas 
3806*007c2a45Smiod       /* Yes: Store the indirect mode back into the image
3807*007c2a45Smiod          to fix up the damage done by STO_PICR.  */
38082159047fSniklas       VMS_Set_Psect (Text_Psect, Offset, OBJ_S_C_TIR);
38092159047fSniklas       VMS_Store_Immediate_Data (&Address_Mode, 1, OBJ_S_C_TIR);
38102159047fSniklas     }
38112159047fSniklas }
38122159047fSniklas 
38132159047fSniklas 
3814*007c2a45Smiod /* If the procedure "main()" exists we have to add the instruction
3815*007c2a45Smiod    "jsb c$main_args" at the beginning to be compatible with VAX-11 "C".
3816*007c2a45Smiod 
3817*007c2a45Smiod    FIXME:  the macro name `HACK_DEC_C_STARTUP' should be renamed
3818*007c2a45Smiod 	   to `HACK_VAXCRTL_STARTUP' because Digital's compiler
3819*007c2a45Smiod  	   named "DEC C" uses run-time library "DECC$SHR", but this
3820*007c2a45Smiod  	   startup code is for "VAXCRTL", the library for Digital's
3821*007c2a45Smiod  	   older "VAX C".  Also, this extra code isn't needed for
3822*007c2a45Smiod  	   supporting gcc because it already generates the VAXCRTL
3823*007c2a45Smiod  	   startup call when compiling main().  The reference to
3824*007c2a45Smiod  	   `flag_hash_long_names' looks very suspicious too;
3825*007c2a45Smiod  	   probably an old-style command line option was inadvertently
3826*007c2a45Smiod  	   overloaded here, then blindly converted into the new one.  */
38272159047fSniklas void
vms_check_for_main(void)3828*007c2a45Smiod vms_check_for_main (void)
38292159047fSniklas {
3830*007c2a45Smiod   symbolS *symbolP;
38312159047fSniklas #ifdef	HACK_DEC_C_STARTUP	/* JF */
3832*007c2a45Smiod   struct frchain *frchainP;
3833*007c2a45Smiod   fragS *fragP;
3834*007c2a45Smiod   fragS **prev_fragPP;
3835*007c2a45Smiod   struct fix *fixP;
3836*007c2a45Smiod   fragS *New_Frag;
38372159047fSniklas   int i;
38382159047fSniklas #endif	/* HACK_DEC_C_STARTUP */
38392159047fSniklas 
38402159047fSniklas   symbolP = (symbolS *) symbol_find ("_main");
38412159047fSniklas   if (symbolP && !S_IS_DEBUG (symbolP) &&
38422159047fSniklas       S_IS_EXTERNAL (symbolP) && (S_GET_TYPE (symbolP) == N_TEXT))
38432159047fSniklas     {
38442159047fSniklas #ifdef	HACK_DEC_C_STARTUP
38452159047fSniklas       if (!flag_hash_long_names)
38462159047fSniklas 	{
38472159047fSniklas #endif
3848*007c2a45Smiod 	  /* Remember the entry point symbol.  */
38492159047fSniklas 	  Entry_Point_Symbol = symbolP;
38502159047fSniklas #ifdef HACK_DEC_C_STARTUP
38512159047fSniklas 	}
38522159047fSniklas       else
38532159047fSniklas 	{
3854*007c2a45Smiod 	  /* Scan all the fragment chains for the one with "_main"
3855*007c2a45Smiod 	     (Actually we know the fragment from the symbol, but we need
3856*007c2a45Smiod 	     the previous fragment so we can change its pointer).  */
38572159047fSniklas 	  frchainP = frchain_root;
38582159047fSniklas 	  while (frchainP)
38592159047fSniklas 	    {
3860*007c2a45Smiod 	      /* Scan all the fragments in this chain, remembering
3861*007c2a45Smiod 	         the "previous fragment".  */
38622159047fSniklas 	      prev_fragPP = &frchainP->frch_root;
38632159047fSniklas 	      fragP = frchainP->frch_root;
38642159047fSniklas 	      while (fragP && (fragP != frchainP->frch_last))
38652159047fSniklas 		{
3866*007c2a45Smiod 		  /* Is this the fragment ?  */
38672159047fSniklas 		  if (fragP == symbolP->sy_frag)
38682159047fSniklas 		    {
3869*007c2a45Smiod 		      /* Yes: Modify the fragment by replacing
3870*007c2a45Smiod 		         it with a new fragment.  */
3871*007c2a45Smiod 		      New_Frag =
38722159047fSniklas 			xmalloc (sizeof (*New_Frag) +
38732159047fSniklas 				 fragP->fr_fix +
38742159047fSniklas 				 fragP->fr_var +
38752159047fSniklas 				 5);
3876*007c2a45Smiod 		      /* The fragments are the same except
3877*007c2a45Smiod 		        	that the "fixed" area is larger.  */
38782159047fSniklas 		      *New_Frag = *fragP;
38792159047fSniklas 		      New_Frag->fr_fix += 6;
3880*007c2a45Smiod 		      /* Copy the literal data opening a hole
3881*007c2a45Smiod 		         2 bytes after "_main" (i.e. just after
3882*007c2a45Smiod 		         the entry mask).  Into which we place
3883*007c2a45Smiod 		         the JSB instruction.  */
38842159047fSniklas 		      New_Frag->fr_literal[0] = fragP->fr_literal[0];
38852159047fSniklas 		      New_Frag->fr_literal[1] = fragP->fr_literal[1];
38862159047fSniklas 		      New_Frag->fr_literal[2] = 0x16;	/* Jsb */
38872159047fSniklas 		      New_Frag->fr_literal[3] = 0xef;
38882159047fSniklas 		      New_Frag->fr_literal[4] = 0;
38892159047fSniklas 		      New_Frag->fr_literal[5] = 0;
38902159047fSniklas 		      New_Frag->fr_literal[6] = 0;
38912159047fSniklas 		      New_Frag->fr_literal[7] = 0;
38922159047fSniklas 		      for (i = 2; i < fragP->fr_fix + fragP->fr_var; i++)
38932159047fSniklas 			New_Frag->fr_literal[i + 6] =
38942159047fSniklas 			  fragP->fr_literal[i];
3895*007c2a45Smiod 		      /* Now replace the old fragment with the
3896*007c2a45Smiod 		         newly generated one.  */
38972159047fSniklas 		      *prev_fragPP = New_Frag;
3898*007c2a45Smiod 		      /* Remember the entry point symbol.  */
38992159047fSniklas 		      Entry_Point_Symbol = symbolP;
3900*007c2a45Smiod 		      /* Scan the text area fixup structures
3901*007c2a45Smiod 		         as offsets in the fragment may have changed.  */
39022159047fSniklas 		      for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
39032159047fSniklas 			{
3904*007c2a45Smiod 			  /* Look for references to this fragment.  */
39052159047fSniklas 			  if (fixP->fx_frag == fragP)
39062159047fSniklas 			    {
3907*007c2a45Smiod 			      /* Change the fragment pointer.  */
39082159047fSniklas 			      fixP->fx_frag = New_Frag;
3909*007c2a45Smiod 			      /* If the offset is after	the entry mask we need
3910*007c2a45Smiod 			         to account for the JSB	instruction we just
3911*007c2a45Smiod 			         inserted.  */
39122159047fSniklas 			      if (fixP->fx_where >= 2)
39132159047fSniklas 				fixP->fx_where += 6;
39142159047fSniklas 			    }
39152159047fSniklas 			}
3916*007c2a45Smiod 		      /* Scan the symbols as offsets in the
3917*007c2a45Smiod 		        fragment may have changed.  */
39182159047fSniklas 		      for (symbolP = symbol_rootP;
39192159047fSniklas 			   symbolP;
39202159047fSniklas 			   symbolP = symbol_next (symbolP))
39212159047fSniklas 			{
3922*007c2a45Smiod 			  /* Look for references to this fragment.  */
39232159047fSniklas 			  if (symbolP->sy_frag == fragP)
39242159047fSniklas 			    {
3925*007c2a45Smiod 			      /* Change the fragment pointer.  */
39262159047fSniklas 			      symbolP->sy_frag = New_Frag;
3927*007c2a45Smiod 			      /* If the offset is after	the entry mask we need
3928*007c2a45Smiod 			         to account for the JSB	instruction we just
3929*007c2a45Smiod 			         inserted.  */
39302159047fSniklas 			      if (S_GET_VALUE (symbolP) >= 2)
39312159047fSniklas 				S_SET_VALUE (symbolP,
39322159047fSniklas 					     S_GET_VALUE (symbolP) + 6);
39332159047fSniklas 			    }
39342159047fSniklas 			}
3935*007c2a45Smiod 		      /*  Make a symbol reference to "_c$main_args" so we
3936*007c2a45Smiod 			  can get its address inserted into the	JSB
3937*007c2a45Smiod 			  instruction.  */
3938*007c2a45Smiod 		      symbolP = xmalloc (sizeof (*symbolP));
39392159047fSniklas 		      S_SET_NAME (symbolP, "_C$MAIN_ARGS");
39402159047fSniklas 		      S_SET_TYPE (symbolP, N_UNDF);
39412159047fSniklas 		      S_SET_OTHER (symbolP, 0);
39422159047fSniklas 		      S_SET_DESC (symbolP, 0);
39432159047fSniklas 		      S_SET_VALUE (symbolP, 0);
39442159047fSniklas 		      symbolP->sy_name_offset = 0;
39452159047fSniklas 		      symbolP->sy_number = 0;
39462159047fSniklas 		      symbolP->sy_obj = 0;
39472159047fSniklas 		      symbolP->sy_frag = New_Frag;
39482159047fSniklas 		      symbolP->sy_resolved = 0;
39492159047fSniklas 		      symbolP->sy_resolving = 0;
3950*007c2a45Smiod 		      /* This actually inserts at the beginning of the list.  */
39512159047fSniklas 		      symbol_append (symbol_rootP, symbolP,
39522159047fSniklas 				     &symbol_rootP, &symbol_lastP);
39532159047fSniklas 
39542159047fSniklas 		      symbol_rootP = symbolP;
3955*007c2a45Smiod 		      /* Generate a text fixup structure
3956*007c2a45Smiod 		         to get "_c$main_args" stored into the
3957*007c2a45Smiod 		         JSB instruction.  */
3958*007c2a45Smiod 		      fixP = xmalloc (sizeof (*fixP));
39592159047fSniklas 		      fixP->fx_frag = New_Frag;
39602159047fSniklas 		      fixP->fx_where = 4;
39612159047fSniklas 		      fixP->fx_addsy = symbolP;
39622159047fSniklas 		      fixP->fx_subsy = 0;
39632159047fSniklas 		      fixP->fx_offset = 0;
39642159047fSniklas 		      fixP->fx_size = 4;
39652159047fSniklas 		      fixP->fx_pcrel = 1;
39662159047fSniklas 		      fixP->fx_next = text_fix_root;
39672159047fSniklas 		      text_fix_root = fixP;
3968*007c2a45Smiod 		      /* Now make sure we exit from the loop.  */
39692159047fSniklas 		      frchainP = 0;
39702159047fSniklas 		      break;
39712159047fSniklas 		    }
3972*007c2a45Smiod 		  /* Try the next fragment.  */
39732159047fSniklas 		  prev_fragPP = &fragP->fr_next;
39742159047fSniklas 		  fragP = fragP->fr_next;
39752159047fSniklas 		}
3976*007c2a45Smiod 	      /* Try the next fragment chain.  */
39772159047fSniklas 	      if (frchainP)
39782159047fSniklas 		frchainP = frchainP->frch_next;
39792159047fSniklas 	    }
39802159047fSniklas 	}
39812159047fSniklas #endif /* HACK_DEC_C_STARTUP */
39822159047fSniklas     }
39832159047fSniklas }
39842159047fSniklas 
39852159047fSniklas 
3986*007c2a45Smiod /* Beginning of vms_write_object_file().  */
39872159047fSniklas 
39882159047fSniklas static
3989*007c2a45Smiod struct vms_obj_state
3990*007c2a45Smiod {
39912159047fSniklas   /* Next program section index to use.  */
39922159047fSniklas   int	psect_number;
39932159047fSniklas 
39942159047fSniklas   /* Psect index for code.  Always ends up #0.  */
39952159047fSniklas   int	text_psect;
39962159047fSniklas 
39972159047fSniklas   /* Psect index for initialized static variables.  */
39982159047fSniklas   int	data_psect;
39992159047fSniklas 
40002159047fSniklas   /* Psect index for uninitialized static variables.  */
40012159047fSniklas   int	bss_psect;
40022159047fSniklas 
4003f7cc78ecSespie   /* Psect index for static constructors.  */
4004f7cc78ecSespie   int	ctors_psect;
4005f7cc78ecSespie 
4006f7cc78ecSespie   /* Psect index for static destructors.  */
4007f7cc78ecSespie   int	dtors_psect;
4008f7cc78ecSespie 
40092159047fSniklas   /* Number of bytes used for local symbol data.  */
40102159047fSniklas   int	local_initd_data_size;
40112159047fSniklas 
40122159047fSniklas   /* Dynamic buffer for initialized data.  */
40132159047fSniklas   char *data_segment;
40142159047fSniklas 
40152159047fSniklas } vms_obj_state;
40162159047fSniklas 
40172159047fSniklas #define Psect_Number		vms_obj_state.psect_number
40182159047fSniklas #define Text_Psect		vms_obj_state.text_psect
40192159047fSniklas #define Data_Psect		vms_obj_state.data_psect
40202159047fSniklas #define Bss_Psect		vms_obj_state.bss_psect
4021f7cc78ecSespie #define Ctors_Psect		vms_obj_state.ctors_psect
4022f7cc78ecSespie #define Dtors_Psect		vms_obj_state.dtors_psect
40232159047fSniklas #define Local_Initd_Data_Size	vms_obj_state.local_initd_data_size
40242159047fSniklas #define Data_Segment		vms_obj_state.data_segment
40252159047fSniklas 
40262159047fSniklas #define IS_GXX_VTABLE(symP) (strncmp (S_GET_NAME (symP), "__vt.", 5) == 0)
4027f7cc78ecSespie #define IS_GXX_XTOR(symP) (strncmp (S_GET_NAME (symP), "__GLOBAL_.", 10) == 0)
4028f7cc78ecSespie #define XTOR_SIZE 4
40292159047fSniklas 
40302159047fSniklas 
40312159047fSniklas /* Perform text segment fixups.  */
40322159047fSniklas 
40332159047fSniklas static void
vms_fixup_text_section(unsigned text_siz ATTRIBUTE_UNUSED,struct frag * text_frag_root,struct frag * data_frag_root)4034*007c2a45Smiod vms_fixup_text_section (unsigned text_siz ATTRIBUTE_UNUSED,
4035*007c2a45Smiod 			struct frag *text_frag_root,
4036*007c2a45Smiod 			struct frag *data_frag_root)
40372159047fSniklas {
4038*007c2a45Smiod   fragS *fragP;
4039*007c2a45Smiod   struct fix *fixP;
40402159047fSniklas   offsetT dif;
40412159047fSniklas 
40422159047fSniklas   /* Scan the text fragments.  */
40432159047fSniklas   for (fragP = text_frag_root; fragP; fragP = fragP->fr_next)
40442159047fSniklas     {
40452159047fSniklas       /* Stop if we get to the data fragments.  */
40462159047fSniklas       if (fragP == data_frag_root)
40472159047fSniklas 	break;
40482159047fSniklas       /* Ignore fragments with no data.  */
40492159047fSniklas       if ((fragP->fr_fix == 0) && (fragP->fr_var == 0))
40502159047fSniklas 	continue;
4051*007c2a45Smiod       /* Go to the appropriate offset in the Text Psect.  */
40522159047fSniklas       VMS_Set_Psect (Text_Psect, fragP->fr_address, OBJ_S_C_TIR);
40532159047fSniklas       /* Store the "fixed" part.  */
40542159047fSniklas       if (fragP->fr_fix)
40552159047fSniklas 	VMS_Store_Immediate_Data (fragP->fr_literal,
40562159047fSniklas 				  fragP->fr_fix,
40572159047fSniklas 				  OBJ_S_C_TIR);
40582159047fSniklas       /* Store the "variable" part.  */
40592159047fSniklas       if (fragP->fr_var && fragP->fr_offset)
40602159047fSniklas 	VMS_Store_Repeated_Data (fragP->fr_offset,
40612159047fSniklas 				 fragP->fr_literal + fragP->fr_fix,
40622159047fSniklas 				 fragP->fr_var,
40632159047fSniklas 				 OBJ_S_C_TIR);
4064*007c2a45Smiod     }
40652159047fSniklas 
4066*007c2a45Smiod   /* Now we go through the text segment fixups and generate
4067*007c2a45Smiod      TIR records to fix up addresses within the Text Psect.  */
40682159047fSniklas   for (fixP = text_fix_root; fixP; fixP = fixP->fx_next)
40692159047fSniklas     {
40702159047fSniklas       /* We DO handle the case of "Symbol - Symbol" as
40712159047fSniklas 	 long as it is in the same segment.  */
40722159047fSniklas       if (fixP->fx_subsy && fixP->fx_addsy)
40732159047fSniklas 	{
40742159047fSniklas 	  /* They need to be in the same segment.  */
40752159047fSniklas 	  if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
40762159047fSniklas 	      S_GET_RAW_TYPE (fixP->fx_addsy))
4077f7cc78ecSespie 	    error (_("Fixup data addsy and subsy don't have the same type"));
40782159047fSniklas 	  /* And they need to be in one that we can check the psect on.  */
40792159047fSniklas 	  if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
40802159047fSniklas 		    (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
4081f7cc78ecSespie 	    error (_("Fixup data addsy and subsy don't have an appropriate type"));
40822159047fSniklas 	  /* This had better not be PC relative!  */
40832159047fSniklas 	  if (fixP->fx_pcrel)
4084f7cc78ecSespie 	    error (_("Fixup data is erroneously \"pcrel\""));
40852159047fSniklas 	  /* Subtract their values to get the difference.  */
40862159047fSniklas 	  dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
40872159047fSniklas 	  md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
40882159047fSniklas 	  /* Now generate the fixup object records;
40892159047fSniklas 	     set the psect and store the data.  */
40902159047fSniklas 	  VMS_Set_Psect (Text_Psect,
40912159047fSniklas 			 fixP->fx_where + fixP->fx_frag->fr_address,
40922159047fSniklas 			 OBJ_S_C_TIR);
40932159047fSniklas 	  VMS_Store_Immediate_Data (Local,
40942159047fSniklas 				    fixP->fx_size,
40952159047fSniklas 				    OBJ_S_C_TIR);
4096*007c2a45Smiod 	  continue;
4097*007c2a45Smiod 	}
40982159047fSniklas       /* Size will HAVE to be "long".  */
40992159047fSniklas       if (fixP->fx_size != 4)
4100f7cc78ecSespie 	error (_("Fixup datum is not a longword"));
41012159047fSniklas       /* Symbol must be "added" (if it is ever
41022159047fSniklas 	 subtracted we can fix this assumption).  */
41032159047fSniklas       if (fixP->fx_addsy == 0)
4104f7cc78ecSespie 	error (_("Fixup datum is not \"fixP->fx_addsy\""));
41052159047fSniklas       /* Store the symbol value in a PIC fashion.  */
41062159047fSniklas       VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
41072159047fSniklas 				      fixP->fx_offset,
41082159047fSniklas 				      fixP->fx_pcrel,
41092159047fSniklas 				      Text_Psect,
41102159047fSniklas 				    fixP->fx_where + fixP->fx_frag->fr_address,
41112159047fSniklas 				      OBJ_S_C_TIR);
4112*007c2a45Smiod 	  /* Check for indirect address reference, which has to be fixed up
4113*007c2a45Smiod 	     (as the linker will screw it up with TIR_S_C_STO_PICR).  */
41142159047fSniklas       if (fixP->fx_pcrel)
41152159047fSniklas 	VMS_Fix_Indirect_Reference (Text_Psect,
41162159047fSniklas 				    fixP->fx_where + fixP->fx_frag->fr_address,
41172159047fSniklas 				    fixP->fx_frag,
41182159047fSniklas 				    text_frag_root);
4119*007c2a45Smiod     }
41202159047fSniklas }
41212159047fSniklas 
41222159047fSniklas 
41232159047fSniklas /* Create a buffer holding the data segment.  */
41242159047fSniklas 
41252159047fSniklas static void
synthesize_data_segment(unsigned data_siz,unsigned text_siz,struct frag * data_frag_root)4126*007c2a45Smiod synthesize_data_segment (unsigned data_siz, unsigned text_siz,
4127*007c2a45Smiod 			 struct frag *data_frag_root)
41282159047fSniklas {
4129*007c2a45Smiod   fragS *fragP;
41302159047fSniklas   char *fill_literal;
41312159047fSniklas   long fill_size, count, i;
41322159047fSniklas 
41332159047fSniklas   /* Allocate the data segment.  */
4134*007c2a45Smiod   Data_Segment = xmalloc (data_siz);
4135*007c2a45Smiod 
41362159047fSniklas   /* Run through the data fragments, filling in the segment.  */
41372159047fSniklas   for (fragP = data_frag_root; fragP; fragP = fragP->fr_next)
41382159047fSniklas     {
41392159047fSniklas       i = fragP->fr_address - text_siz;
41402159047fSniklas       if (fragP->fr_fix)
41412159047fSniklas 	memcpy (Data_Segment + i, fragP->fr_literal, fragP->fr_fix);
41422159047fSniklas       i += fragP->fr_fix;
41432159047fSniklas 
41442159047fSniklas       if ((fill_size = fragP->fr_var) != 0)
41452159047fSniklas 	{
41462159047fSniklas 	  fill_literal = fragP->fr_literal + fragP->fr_fix;
41472159047fSniklas 	  for (count = fragP->fr_offset; count; count--)
41482159047fSniklas 	    {
41492159047fSniklas 	      memcpy (Data_Segment + i, fill_literal, fill_size);
41502159047fSniklas 	      i += fill_size;
41512159047fSniklas 	    }
41522159047fSniklas 	}
4153*007c2a45Smiod     }
41542159047fSniklas }
41552159047fSniklas 
41562159047fSniklas /* Perform data segment fixups.  */
41572159047fSniklas 
41582159047fSniklas static void
vms_fixup_data_section(unsigned int data_siz ATTRIBUTE_UNUSED,unsigned int text_siz)4159*007c2a45Smiod vms_fixup_data_section (unsigned int data_siz ATTRIBUTE_UNUSED,
4160*007c2a45Smiod 			unsigned int text_siz)
41612159047fSniklas {
4162*007c2a45Smiod   struct VMS_Symbol *vsp;
4163*007c2a45Smiod   struct fix *fixP;
4164*007c2a45Smiod   symbolS *sp;
41652159047fSniklas   addressT fr_address;
41662159047fSniklas   offsetT dif;
41672159047fSniklas   valueT val;
41682159047fSniklas 
41692159047fSniklas   /* Run through all the data symbols and store the data.  */
41702159047fSniklas   for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
41712159047fSniklas     {
41722159047fSniklas       /* Ignore anything other than data symbols.  */
41732159047fSniklas       if (S_GET_TYPE (vsp->Symbol) != N_DATA)
41742159047fSniklas 	continue;
41752159047fSniklas       /* Set the Psect + Offset.  */
41762159047fSniklas       VMS_Set_Psect (vsp->Psect_Index,
41772159047fSniklas 		       vsp->Psect_Offset,
41782159047fSniklas 		       OBJ_S_C_TIR);
41792159047fSniklas       /* Store the data.  */
41802159047fSniklas       val = S_GET_VALUE (vsp->Symbol);
41812159047fSniklas       VMS_Store_Immediate_Data (Data_Segment + val - text_siz,
41822159047fSniklas 				vsp->Size,
41832159047fSniklas 				OBJ_S_C_TIR);
41842159047fSniklas     }			/* N_DATA symbol loop */
41852159047fSniklas 
4186*007c2a45Smiod   /* Now we go through the data segment fixups and generate
4187*007c2a45Smiod      TIR records to fix up addresses within the Data Psects.  */
41882159047fSniklas   for (fixP = data_fix_root; fixP; fixP = fixP->fx_next)
41892159047fSniklas     {
41902159047fSniklas       /* Find the symbol for the containing datum.  */
41912159047fSniklas       for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
41922159047fSniklas 	{
41932159047fSniklas 	  /* Only bother with Data symbols.  */
41942159047fSniklas 	  sp = vsp->Symbol;
41952159047fSniklas 	  if (S_GET_TYPE (sp) != N_DATA)
41962159047fSniklas 	    continue;
41972159047fSniklas 	  /* Ignore symbol if After fixup.  */
41982159047fSniklas 	  val = S_GET_VALUE (sp);
41992159047fSniklas 	  fr_address = fixP->fx_frag->fr_address;
42002159047fSniklas 	  if (val > fixP->fx_where + fr_address)
42012159047fSniklas 	    continue;
42022159047fSniklas 	  /* See if the datum is here.  */
42032159047fSniklas 	  if (val + vsp->Size <= fixP->fx_where + fr_address)
42042159047fSniklas 	    continue;
42052159047fSniklas 	  /* We DO handle the case of "Symbol - Symbol" as
42062159047fSniklas 	     long as it is in the same segment.  */
42072159047fSniklas 	  if (fixP->fx_subsy && fixP->fx_addsy)
42082159047fSniklas 	    {
42092159047fSniklas 	      /* They need to be in the same segment.  */
42102159047fSniklas 	      if (S_GET_RAW_TYPE (fixP->fx_subsy) !=
42112159047fSniklas 		  S_GET_RAW_TYPE (fixP->fx_addsy))
4212f7cc78ecSespie 		error (_("Fixup data addsy and subsy don't have the same type"));
42132159047fSniklas 	      /* And they need to be in one that we can check the psect on.  */
42142159047fSniklas 	      if ((S_GET_TYPE (fixP->fx_addsy) != N_DATA) &&
42152159047fSniklas 		  (S_GET_TYPE (fixP->fx_addsy) != N_TEXT))
4216f7cc78ecSespie 		error (_("Fixup data addsy and subsy don't have an appropriate type"));
42172159047fSniklas 	      /* This had better not be PC relative!  */
42182159047fSniklas 	      if (fixP->fx_pcrel)
4219f7cc78ecSespie 		error (_("Fixup data is erroneously \"pcrel\""));
42202159047fSniklas 	      /* Subtract their values to get the difference.  */
42212159047fSniklas 	      dif = S_GET_VALUE (fixP->fx_addsy) - S_GET_VALUE (fixP->fx_subsy);
42222159047fSniklas 	      md_number_to_chars (Local, (valueT)dif, fixP->fx_size);
4223*007c2a45Smiod 	      /* Now generate the fixup object records;
4224*007c2a45Smiod 	         set the psect and store the data.  */
42252159047fSniklas 	      VMS_Set_Psect (vsp->Psect_Index,
42262159047fSniklas 			     fr_address + fixP->fx_where
42272159047fSniklas 				 - val + vsp->Psect_Offset,
42282159047fSniklas 			     OBJ_S_C_TIR);
42292159047fSniklas 	      VMS_Store_Immediate_Data (Local,
42302159047fSniklas 					fixP->fx_size,
42312159047fSniklas 					OBJ_S_C_TIR);
42322159047fSniklas 		  break;	/* done with this fixup */
42332159047fSniklas 		}
42342159047fSniklas 	  /* Size will HAVE to be "long".  */
42352159047fSniklas 	  if (fixP->fx_size != 4)
4236f7cc78ecSespie 	    error (_("Fixup datum is not a longword"));
42372159047fSniklas 	  /* Symbol must be "added" (if it is ever
42382159047fSniklas 	     subtracted we can fix this assumption).  */
42392159047fSniklas 	  if (fixP->fx_addsy == 0)
4240f7cc78ecSespie 	    error (_("Fixup datum is not \"fixP->fx_addsy\""));
42412159047fSniklas 	  /* Store the symbol value in a PIC fashion.  */
42422159047fSniklas 	  VMS_Store_PIC_Symbol_Reference (fixP->fx_addsy,
42432159047fSniklas 					  fixP->fx_offset,
42442159047fSniklas 					  fixP->fx_pcrel,
42452159047fSniklas 					  vsp->Psect_Index,
42462159047fSniklas 					  fr_address + fixP->fx_where
42472159047fSniklas 					      - val + vsp->Psect_Offset,
42482159047fSniklas 					  OBJ_S_C_TIR);
42492159047fSniklas 	  /* Done with this fixup.  */
42502159047fSniklas 	  break;
4251*007c2a45Smiod 	}
4252*007c2a45Smiod     }
42532159047fSniklas }
4254f7cc78ecSespie 
4255f7cc78ecSespie /* Perform ctors/dtors segment fixups.  */
4256f7cc78ecSespie 
4257f7cc78ecSespie static void
vms_fixup_xtors_section(struct VMS_Symbol * symbols,int sect_no ATTRIBUTE_UNUSED)4258*007c2a45Smiod vms_fixup_xtors_section (struct VMS_Symbol *symbols,
4259*007c2a45Smiod 			 int sect_no ATTRIBUTE_UNUSED)
4260f7cc78ecSespie {
4261*007c2a45Smiod   struct VMS_Symbol *vsp;
4262f7cc78ecSespie 
4263f7cc78ecSespie   /* Run through all the symbols and store the data.  */
4264f7cc78ecSespie   for (vsp = symbols; vsp; vsp = vsp->Next)
4265f7cc78ecSespie     {
4266*007c2a45Smiod       symbolS *sp;
4267f7cc78ecSespie 
4268f7cc78ecSespie       /* Set relocation base.  */
4269f7cc78ecSespie       VMS_Set_Psect (vsp->Psect_Index, vsp->Psect_Offset, OBJ_S_C_TIR);
4270f7cc78ecSespie 
4271f7cc78ecSespie       sp = vsp->Symbol;
4272f7cc78ecSespie       /* Stack the Psect base with its offset.  */
4273f7cc78ecSespie       VMS_Set_Data (Text_Psect, S_GET_VALUE (sp), OBJ_S_C_TIR, 0);
4274f7cc78ecSespie     }
4275f7cc78ecSespie   /* Flush the buffer if it is more than 75% full.  */
4276f7cc78ecSespie   if (Object_Record_Offset > (sizeof (Object_Record_Buffer) * 3 / 4))
4277f7cc78ecSespie     Flush_VMS_Object_Record_Buffer ();
4278f7cc78ecSespie }
42792159047fSniklas 
42802159047fSniklas 
42812159047fSniklas /* Define symbols for the linker.  */
42822159047fSniklas 
42832159047fSniklas static void
global_symbol_directory(unsigned text_siz,unsigned data_siz)4284*007c2a45Smiod global_symbol_directory (unsigned text_siz, unsigned data_siz)
42852159047fSniklas {
4286*007c2a45Smiod   fragS *fragP;
4287*007c2a45Smiod   symbolS *sp;
4288*007c2a45Smiod   struct VMS_Symbol *vsp;
42892159047fSniklas   int Globalref, define_as_global_symbol;
42902159047fSniklas 
4291f7cc78ecSespie #if 0
4292f7cc78ecSespie   /* The g++ compiler does not write out external references to
4293f7cc78ecSespie      vtables correctly.  Check for this and holler if we see it
4294f7cc78ecSespie      happening.  If that compiler bug is ever fixed we can remove
4295f7cc78ecSespie      this.
4296f7cc78ecSespie 
4297f7cc78ecSespie      (Jun'95: gcc 2.7.0's cc1plus still exhibits this behavior.)
4298f7cc78ecSespie 
4299f7cc78ecSespie      This was reportedly fixed as of June 2, 1998.   */
4300f7cc78ecSespie 
43012159047fSniklas   for (sp = symbol_rootP; sp; sp = symbol_next (sp))
43022159047fSniklas     if (S_GET_RAW_TYPE (sp) == N_UNDF && IS_GXX_VTABLE (sp))
43032159047fSniklas       {
43042159047fSniklas 	S_SET_TYPE (sp, N_UNDF | N_EXT);
43052159047fSniklas 	S_SET_OTHER (sp, 1);
4306f7cc78ecSespie 	as_warn (_("g++ wrote an extern reference to `%s' as a routine.\nI will fix it, but I hope that it was note really a routine."),
4307f7cc78ecSespie 		 S_GET_NAME (sp));
43082159047fSniklas       }
4309f7cc78ecSespie #endif
43102159047fSniklas 
4311*007c2a45Smiod   /* Now scan the symbols and emit the appropriate GSD records.  */
43122159047fSniklas   for (sp = symbol_rootP; sp; sp = symbol_next (sp))
43132159047fSniklas     {
43142159047fSniklas       define_as_global_symbol = 0;
43152159047fSniklas       vsp = 0;
43162159047fSniklas       /* Dispatch on symbol type.  */
43172159047fSniklas       switch (S_GET_RAW_TYPE (sp))
43182159047fSniklas 	{
43192159047fSniklas 
43202159047fSniklas 	/* Global uninitialized data.  */
43212159047fSniklas 	case N_UNDF | N_EXT:
43222159047fSniklas 	  /* Make a VMS data symbol entry.  */
4323*007c2a45Smiod 	  vsp = xmalloc (sizeof *vsp);
43242159047fSniklas 	  vsp->Symbol = sp;
43252159047fSniklas 	  vsp->Size = S_GET_VALUE (sp);
43262159047fSniklas 	  vsp->Psect_Index = Psect_Number++;
43272159047fSniklas 	  vsp->Psect_Offset = 0;
43282159047fSniklas 	  vsp->Next = VMS_Symbols;
43292159047fSniklas 	  VMS_Symbols = vsp;
43302159047fSniklas 	  sp->sy_obj = vsp;
43312159047fSniklas 	  /* Make the psect for this data.  */
43322159047fSniklas 	  Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
43332159047fSniklas 				      vsp->Size,
43342159047fSniklas 				      S_GET_OTHER (sp) ? ps_CONST : ps_COMMON,
43352159047fSniklas 				      vsp);
43362159047fSniklas 	  if (Globalref)
43372159047fSniklas 	    Psect_Number--;
43382159047fSniklas #ifdef	NOT_VAX_11_C_COMPATIBLE
43392159047fSniklas 	  define_as_global_symbol = 1;
43402159047fSniklas #else
43412159047fSniklas 	  /* See if this is an external vtable.  We want to help the
43422159047fSniklas 	     linker find these things in libraries, so we make a symbol
43432159047fSniklas 	     reference.  This is not compatible with VAX-C usage for
43442159047fSniklas 	     variables, but since vtables are only used internally by
43452159047fSniklas 	     g++, we can get away with this hack.  */
43462159047fSniklas 	  define_as_global_symbol = IS_GXX_VTABLE (sp);
43472159047fSniklas #endif
43482159047fSniklas 	  break;
43492159047fSniklas 
43502159047fSniklas 	/* Local uninitialized data.  */
43512159047fSniklas 	case N_BSS:
43522159047fSniklas 	  /* Make a VMS data symbol entry.  */
4353*007c2a45Smiod 	  vsp = xmalloc (sizeof *vsp);
43542159047fSniklas 	  vsp->Symbol = sp;
43552159047fSniklas 	  vsp->Size = 0;
43562159047fSniklas 	  vsp->Psect_Index = Bss_Psect;
43572159047fSniklas 	  vsp->Psect_Offset = S_GET_VALUE (sp) - bss_address_frag.fr_address;
43582159047fSniklas 	  vsp->Next = VMS_Symbols;
43592159047fSniklas 	  VMS_Symbols = vsp;
43602159047fSniklas 	  sp->sy_obj = vsp;
43612159047fSniklas 	  break;
43622159047fSniklas 
43632159047fSniklas 	/* Global initialized data.  */
43642159047fSniklas 	case N_DATA | N_EXT:
43652159047fSniklas 	  /* Make a VMS data symbol entry.  */
4366*007c2a45Smiod 	  vsp = xmalloc (sizeof *vsp);
43672159047fSniklas 	  vsp->Symbol = sp;
43682159047fSniklas 	  vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
43692159047fSniklas 	  vsp->Psect_Index = Psect_Number++;
43702159047fSniklas 	  vsp->Psect_Offset = 0;
43712159047fSniklas 	  vsp->Next = VMS_Symbols;
43722159047fSniklas 	  VMS_Symbols = vsp;
43732159047fSniklas 	  sp->sy_obj = vsp;
43742159047fSniklas 	  /* Make its psect.  */
43752159047fSniklas 	  Globalref = VMS_Psect_Spec (S_GET_NAME (sp),
43762159047fSniklas 				      vsp->Size,
43772159047fSniklas 				      S_GET_OTHER (sp) ? ps_CONST : ps_COMMON,
43782159047fSniklas 				      vsp);
43792159047fSniklas 	  if (Globalref)
43802159047fSniklas 	    Psect_Number--;
43812159047fSniklas #ifdef	NOT_VAX_11_C_COMPATIBLE
43822159047fSniklas 	  define_as_global_symbol = 1;
43832159047fSniklas #else
43842159047fSniklas 	  /* See N_UNDF|N_EXT above for explanation.  */
43852159047fSniklas 	  define_as_global_symbol = IS_GXX_VTABLE (sp);
43862159047fSniklas #endif
43872159047fSniklas 	  break;
43882159047fSniklas 
43892159047fSniklas 	/* Local initialized data.  */
43902159047fSniklas 	case N_DATA:
43912159047fSniklas 	  {
43922159047fSniklas 	    char *sym_name = S_GET_NAME (sp);
43932159047fSniklas 
43942159047fSniklas 	    /* Always suppress local numeric labels.  */
43952159047fSniklas 	    if (sym_name && strcmp (sym_name, FAKE_LABEL_NAME) == 0)
43962159047fSniklas 	      break;
43972159047fSniklas 
43982159047fSniklas 	    /* Make a VMS data symbol entry.  */
4399*007c2a45Smiod 	    vsp = xmalloc (sizeof *vsp);
44002159047fSniklas 	    vsp->Symbol = sp;
44012159047fSniklas 	    vsp->Size = VMS_Initialized_Data_Size (sp, text_siz + data_siz);
44022159047fSniklas 	    vsp->Psect_Index = Data_Psect;
44032159047fSniklas 	    vsp->Psect_Offset = Local_Initd_Data_Size;
44042159047fSniklas 	    Local_Initd_Data_Size += vsp->Size;
44052159047fSniklas 	    vsp->Next = VMS_Symbols;
44062159047fSniklas 	    VMS_Symbols = vsp;
44072159047fSniklas 	    sp->sy_obj = vsp;
44082159047fSniklas 	  }
44092159047fSniklas 	  break;
44102159047fSniklas 
44112159047fSniklas 	/* Global Text definition.  */
44122159047fSniklas 	case N_TEXT | N_EXT:
44132159047fSniklas 	  {
4414f7cc78ecSespie 
4415f7cc78ecSespie 	    if (IS_GXX_XTOR (sp))
4416f7cc78ecSespie 	      {
4417*007c2a45Smiod 		vsp = xmalloc (sizeof *vsp);
4418f7cc78ecSespie 		vsp->Symbol = sp;
4419f7cc78ecSespie 		vsp->Size = XTOR_SIZE;
4420f7cc78ecSespie 		sp->sy_obj = vsp;
4421f7cc78ecSespie 		switch ((S_GET_NAME (sp))[10])
4422f7cc78ecSespie 		  {
4423f7cc78ecSespie 		    case 'I':
4424f7cc78ecSespie 		      vsp->Psect_Index = Ctors_Psect;
4425f7cc78ecSespie 		      vsp->Psect_Offset = (Ctors_Symbols==0)?0:(Ctors_Symbols->Psect_Offset+XTOR_SIZE);
4426f7cc78ecSespie 		      vsp->Next = Ctors_Symbols;
4427f7cc78ecSespie 		      Ctors_Symbols = vsp;
4428f7cc78ecSespie 		      break;
4429f7cc78ecSespie 		    case 'D':
4430f7cc78ecSespie 		      vsp->Psect_Index = Dtors_Psect;
4431f7cc78ecSespie 		      vsp->Psect_Offset = (Dtors_Symbols==0)?0:(Dtors_Symbols->Psect_Offset+XTOR_SIZE);
4432f7cc78ecSespie 		      vsp->Next = Dtors_Symbols;
4433f7cc78ecSespie 		      Dtors_Symbols = vsp;
4434f7cc78ecSespie 		      break;
4435f7cc78ecSespie 		    case 'G':
4436f7cc78ecSespie 		      as_warn (_("Can't handle global xtors symbols yet."));
4437f7cc78ecSespie 		      break;
4438f7cc78ecSespie 		    default:
4439f7cc78ecSespie 		      as_warn (_("Unknown %s"), S_GET_NAME (sp));
4440f7cc78ecSespie 		      break;
4441f7cc78ecSespie 		  }
4442f7cc78ecSespie 	      }
4443f7cc78ecSespie 	    else
4444f7cc78ecSespie 	      {
44452159047fSniklas 		unsigned short Entry_Mask;
44462159047fSniklas 
44472159047fSniklas 		/* Get the entry mask.  */
44482159047fSniklas 		fragP = sp->sy_frag;
44492159047fSniklas 		/* First frag might be empty if we're generating listings.
44502159047fSniklas 		   So skip empty rs_fill frags.  */
44512159047fSniklas 		while (fragP && fragP->fr_type == rs_fill && fragP->fr_fix == 0)
44522159047fSniklas 		  fragP = fragP->fr_next;
44532159047fSniklas 
44542159047fSniklas 		/* If first frag doesn't contain the data, what do we do?
44552159047fSniklas 		   If it's possibly smaller than two bytes, that would
44562159047fSniklas 		   imply that the entry mask is not stored where we're
44572159047fSniklas 		   expecting it.
44582159047fSniklas 
44592159047fSniklas 		   If you can find a test case that triggers this, report
44602159047fSniklas 		   it (and tell me what the entry mask field ought to be),
44612159047fSniklas 		   and I'll try to fix it.  KR */
44622159047fSniklas 		if (fragP->fr_fix < 2)
44632159047fSniklas 		  abort ();
44642159047fSniklas 
44652159047fSniklas 		Entry_Mask = (fragP->fr_literal[0] & 0x00ff) |
44662159047fSniklas 			     ((fragP->fr_literal[1] & 0x00ff) << 8);
44672159047fSniklas 		/* Define the procedure entry point.  */
44682159047fSniklas 		VMS_Procedure_Entry_Pt (S_GET_NAME (sp),
44692159047fSniklas 				    Text_Psect,
44702159047fSniklas 				    S_GET_VALUE (sp),
44712159047fSniklas 				    Entry_Mask);
4472f7cc78ecSespie 	      }
44732159047fSniklas 	    break;
44742159047fSniklas 	  }
44752159047fSniklas 
44762159047fSniklas 	/* Local Text definition.  */
44772159047fSniklas 	case N_TEXT:
44782159047fSniklas 	  /* Make a VMS data symbol entry.  */
44792159047fSniklas 	  if (Text_Psect != -1)
44802159047fSniklas 	    {
4481*007c2a45Smiod 	      vsp = xmalloc (sizeof *vsp);
44822159047fSniklas 	      vsp->Symbol = sp;
44832159047fSniklas 	      vsp->Size = 0;
44842159047fSniklas 	      vsp->Psect_Index = Text_Psect;
44852159047fSniklas 	      vsp->Psect_Offset = S_GET_VALUE (sp);
44862159047fSniklas 	      vsp->Next = VMS_Symbols;
44872159047fSniklas 	      VMS_Symbols = vsp;
44882159047fSniklas 	      sp->sy_obj = vsp;
44892159047fSniklas 	    }
44902159047fSniklas 	  break;
44912159047fSniklas 
44922159047fSniklas 	/* Global Reference.  */
44932159047fSniklas 	case N_UNDF:
44942159047fSniklas 	  /* Make a GSD global symbol reference record.  */
44952159047fSniklas 	  VMS_Global_Symbol_Spec (S_GET_NAME (sp),
44962159047fSniklas 				  0,
44972159047fSniklas 				  0,
44982159047fSniklas 				  GBLSYM_REF);
44992159047fSniklas 	  break;
45002159047fSniklas 
45012159047fSniklas 	/* Absolute symbol.  */
45022159047fSniklas 	case N_ABS:
45032159047fSniklas 	case N_ABS | N_EXT:
45042159047fSniklas 	  /* gcc doesn't generate these;
45052159047fSniklas 	     VMS_Emit_Globalvalue handles them though.	*/
4506*007c2a45Smiod 	  vsp = xmalloc (sizeof *vsp);
45072159047fSniklas 	  vsp->Symbol = sp;
45082159047fSniklas 	  vsp->Size = 4;		/* always assume 32 bits */
45092159047fSniklas 	  vsp->Psect_Index = 0;
45102159047fSniklas 	  vsp->Psect_Offset = S_GET_VALUE (sp);
45112159047fSniklas 	  vsp->Next = VMS_Symbols;
45122159047fSniklas 	  VMS_Symbols = vsp;
45132159047fSniklas 	  sp->sy_obj = vsp;
45142159047fSniklas 	  break;
45152159047fSniklas 
45162159047fSniklas 	/* Anything else.  */
45172159047fSniklas 	default:
45182159047fSniklas 	  /* Ignore STAB symbols, including .stabs emitted by g++.  */
45192159047fSniklas 	  if (S_IS_DEBUG (sp) || (S_GET_TYPE (sp) == 22))
45202159047fSniklas 	    break;
45212159047fSniklas 	  /*
45222159047fSniklas 	   *	Error otherwise.
45232159047fSniklas 	   */
4524f7cc78ecSespie 	  as_tsktsk (_("unhandled stab type %d"), S_GET_TYPE (sp));
45252159047fSniklas 	  break;
45262159047fSniklas 	}
45272159047fSniklas 
45282159047fSniklas       /* Global symbols have different linkage than external variables.  */
45292159047fSniklas       if (define_as_global_symbol)
45302159047fSniklas 	VMS_Global_Symbol_Spec (S_GET_NAME (sp),
45312159047fSniklas 				vsp->Psect_Index,
45322159047fSniklas 				0,
45332159047fSniklas 				GBLSYM_DEF);
45342159047fSniklas     }
45352159047fSniklas }
45362159047fSniklas 
45372159047fSniklas 
45382159047fSniklas /* Output debugger symbol table information for symbols which
45392159047fSniklas    are local to a specific routine.  */
45402159047fSniklas 
45412159047fSniklas static void
local_symbols_DST(symbolS * s0P,symbolS * Current_Routine)4542*007c2a45Smiod local_symbols_DST (symbolS *s0P, symbolS *Current_Routine)
45432159047fSniklas {
45442159047fSniklas   symbolS *s1P;
45452159047fSniklas   char *s0P_name, *pnt0, *pnt1;
45462159047fSniklas 
45472159047fSniklas   s0P_name = S_GET_NAME (s0P);
45482159047fSniklas   if (*s0P_name++ != '_')
45492159047fSniklas     return;
45502159047fSniklas 
45512159047fSniklas   for (s1P = Current_Routine; s1P; s1P = symbol_next (s1P))
45522159047fSniklas     {
45532159047fSniklas #if 0		/* redundant; RAW_TYPE != N_FUN suffices */
45542159047fSniklas       if (!S_IS_DEBUG (s1P))
45552159047fSniklas 	continue;
45562159047fSniklas #endif
45572159047fSniklas       if (S_GET_RAW_TYPE (s1P) != N_FUN)
45582159047fSniklas 	continue;
45592159047fSniklas       pnt0 = s0P_name;
45602159047fSniklas       pnt1 = S_GET_NAME (s1P);
45612159047fSniklas       /* We assume the two strings are never exactly equal...  */
45622159047fSniklas       while (*pnt0++ == *pnt1++)
45632159047fSniklas 	{
45642159047fSniklas 	}
45652159047fSniklas       /* Found it if s0P name is exhausted and s1P name has ":F" or ":f" next.
45662159047fSniklas 	 Note:  both pointers have advanced one past the non-matching char.  */
45672159047fSniklas       if ((*pnt1 == 'F' || *pnt1 == 'f') && *--pnt1 == ':' && *--pnt0 == '\0')
45682159047fSniklas 	{
45692159047fSniklas 	  Define_Routine (s1P, 0, Current_Routine, Text_Psect);
45702159047fSniklas 	  return;
45712159047fSniklas 	}
45722159047fSniklas     }
45732159047fSniklas }
45742159047fSniklas 
45752159047fSniklas /* Construct and output the debug symbol table.  */
45762159047fSniklas 
45772159047fSniklas static void
vms_build_DST(unsigned text_siz)4578*007c2a45Smiod vms_build_DST (unsigned text_siz)
45792159047fSniklas {
4580*007c2a45Smiod   symbolS *symbolP;
45812159047fSniklas   symbolS *Current_Routine = 0;
45822159047fSniklas   struct input_file *Cur_File = 0;
45832159047fSniklas   offsetT Cur_Offset = -1;
45842159047fSniklas   int Cur_Line_Number = 0;
45852159047fSniklas   int File_Number = 0;
45862159047fSniklas   int Debugger_Offset = 0;
45872159047fSniklas   int file_available;
45882159047fSniklas   int dsc;
45892159047fSniklas   offsetT val;
45902159047fSniklas 
45912159047fSniklas   /* Write the Traceback Begin Module record.  */
45922159047fSniklas   VMS_TBT_Module_Begin ();
45932159047fSniklas 
4594*007c2a45Smiod   /* Output debugging info for global variables and static variables
4595*007c2a45Smiod      that are not specific to one routine.  We also need to examine
4596*007c2a45Smiod      all stabs directives, to find the definitions to all of the
4597*007c2a45Smiod      advanced data types, and this is done by VMS_LSYM_Parse.  This
4598*007c2a45Smiod      needs to be done before any definitions are output to the object
4599*007c2a45Smiod      file, since there can be forward references in the stabs
4600*007c2a45Smiod      directives.  When through with parsing, the text of the stabs
4601*007c2a45Smiod      directive is altered, with the definitions removed, so that later
4602*007c2a45Smiod      passes will see directives as they would be written if the type
4603*007c2a45Smiod      were already defined.
4604*007c2a45Smiod 
4605*007c2a45Smiod      We also look for files and include files, and make a list of
4606*007c2a45Smiod      them.  We examine the source file numbers to establish the actual
4607*007c2a45Smiod      lines that code was generated from, and then generate offsets.  */
46082159047fSniklas   VMS_LSYM_Parse ();
46092159047fSniklas   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
46102159047fSniklas     {
46112159047fSniklas       /* Only deal with STAB symbols here.  */
46122159047fSniklas       if (!S_IS_DEBUG (symbolP))
46132159047fSniklas 	continue;
4614*007c2a45Smiod       /* Dispatch on STAB type.  */
46152159047fSniklas       switch (S_GET_RAW_TYPE (symbolP))
46162159047fSniklas 	{
46172159047fSniklas 	case N_SLINE:
46182159047fSniklas 	  dsc = S_GET_DESC (symbolP);
46192159047fSniklas 	  if (dsc > Cur_File->max_line)
46202159047fSniklas 	    Cur_File->max_line = dsc;
46212159047fSniklas 	  if (dsc < Cur_File->min_line)
46222159047fSniklas 	    Cur_File->min_line = dsc;
46232159047fSniklas 	  break;
46242159047fSniklas 	case N_SO:
46252159047fSniklas 	  Cur_File = find_file (symbolP);
46262159047fSniklas 	  Cur_File->flag = 1;
46272159047fSniklas 	  Cur_File->min_line = 1;
46282159047fSniklas 	  break;
46292159047fSniklas 	case N_SOL:
46302159047fSniklas 	  Cur_File = find_file (symbolP);
46312159047fSniklas 	  break;
46322159047fSniklas 	case N_GSYM:
46332159047fSniklas 	  VMS_GSYM_Parse (symbolP, Text_Psect);
46342159047fSniklas 	  break;
46352159047fSniklas 	case N_LCSYM:
46362159047fSniklas 	  VMS_LCSYM_Parse (symbolP, Text_Psect);
46372159047fSniklas 	  break;
46382159047fSniklas 	case N_FUN:		/* For static constant symbols */
46392159047fSniklas 	case N_STSYM:
46402159047fSniklas 	  VMS_STSYM_Parse (symbolP, Text_Psect);
46412159047fSniklas 	  break;
46422159047fSniklas 	default:
46432159047fSniklas 	  break;
4644*007c2a45Smiod 	}
4645*007c2a45Smiod     }
46462159047fSniklas 
4647*007c2a45Smiod   /* Now we take a quick sweep through the files and assign offsets
4648*007c2a45Smiod      to each one.  This will essentially be the starting line number to
4649*007c2a45Smiod      the debugger for each file.  Output the info for the debugger to
4650*007c2a45Smiod      specify the files, and then tell it how many lines to use.  */
46512159047fSniklas   for (Cur_File = file_root; Cur_File; Cur_File = Cur_File->next)
46522159047fSniklas     {
46532159047fSniklas       if (Cur_File->max_line == 0)
46542159047fSniklas 	continue;
46552159047fSniklas       if ((strncmp (Cur_File->name, "GNU_GXX_INCLUDE:", 16) == 0) &&
46562159047fSniklas 	  !flag_debug)
46572159047fSniklas 	continue;
46582159047fSniklas       if ((strncmp (Cur_File->name, "GNU_CC_INCLUDE:", 15) == 0) &&
46592159047fSniklas 	  !flag_debug)
46602159047fSniklas 	continue;
46612159047fSniklas       /* show a few extra lines at the start of the region selected */
46622159047fSniklas       if (Cur_File->min_line > 2)
46632159047fSniklas 	Cur_File->min_line -= 2;
46642159047fSniklas       Cur_File->offset = Debugger_Offset - Cur_File->min_line + 1;
46652159047fSniklas       Debugger_Offset += Cur_File->max_line - Cur_File->min_line + 1;
46662159047fSniklas       if (Cur_File->same_file_fpnt)
46672159047fSniklas 	{
46682159047fSniklas 	  Cur_File->file_number = Cur_File->same_file_fpnt->file_number;
46692159047fSniklas 	}
46702159047fSniklas       else
46712159047fSniklas 	{
46722159047fSniklas 	  Cur_File->file_number = ++File_Number;
46732159047fSniklas 	  file_available = VMS_TBT_Source_File (Cur_File->name,
46742159047fSniklas 						Cur_File->file_number);
46752159047fSniklas 	  if (!file_available)
46762159047fSniklas 	    {
46772159047fSniklas 	      Cur_File->file_number = 0;
46782159047fSniklas 	      File_Number--;
46792159047fSniklas 	      continue;
46802159047fSniklas 	    }
46812159047fSniklas 	}
46822159047fSniklas       VMS_TBT_Source_Lines (Cur_File->file_number,
46832159047fSniklas 			    Cur_File->min_line,
46842159047fSniklas 			    Cur_File->max_line - Cur_File->min_line + 1);
46852159047fSniklas   }			/* for */
46862159047fSniklas   Cur_File = (struct input_file *) NULL;
46872159047fSniklas 
4688*007c2a45Smiod   /* Scan the symbols and write out the routines
4689*007c2a45Smiod      (this makes the assumption that symbols are in
4690*007c2a45Smiod      order of ascending text segment offset).  */
46912159047fSniklas   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
46922159047fSniklas     {
4693*007c2a45Smiod       /* Deal with text symbols.  */
46942159047fSniklas       if (!S_IS_DEBUG (symbolP) && S_GET_TYPE (symbolP) == N_TEXT)
46952159047fSniklas 	{
4696*007c2a45Smiod 	  /* Ignore symbols starting with "L", as they are local symbols.  */
46972159047fSniklas 	  if (*S_GET_NAME (symbolP) == 'L')
46982159047fSniklas 	    continue;
4699*007c2a45Smiod 	  /* If there is a routine start defined, terminate it.  */
47002159047fSniklas 	  if (Current_Routine)
47012159047fSniklas 	    VMS_TBT_Routine_End (text_siz, Current_Routine);
47022159047fSniklas 
4703*007c2a45Smiod 	  /* Check for & skip dummy labels like "gcc_compiled.".
4704*007c2a45Smiod 	   * They're identified by the IN_DEFAULT_SECTION flag.  */
47052159047fSniklas 	  if ((S_GET_OTHER (symbolP) & IN_DEFAULT_SECTION) != 0 &&
47062159047fSniklas 	      S_GET_VALUE (symbolP) == 0)
47072159047fSniklas 	    continue;
4708*007c2a45Smiod 	  /* Store the routine begin traceback info.  */
47092159047fSniklas 	  VMS_TBT_Routine_Begin (symbolP, Text_Psect);
47102159047fSniklas 	  Current_Routine = symbolP;
4711*007c2a45Smiod 	  /* Define symbols local to this routine.  */
47122159047fSniklas 	  local_symbols_DST (symbolP, Current_Routine);
4713*007c2a45Smiod 	  /* Done.  */
47142159047fSniklas 	  continue;
47152159047fSniklas 
47162159047fSniklas 	}
4717*007c2a45Smiod       /* Deal with STAB symbols.  */
47182159047fSniklas       else if (S_IS_DEBUG (symbolP))
47192159047fSniklas 	{
4720*007c2a45Smiod 	  /* Dispatch on STAB type.  */
47212159047fSniklas 	  switch (S_GET_RAW_TYPE (symbolP))
47222159047fSniklas 	    {
4723*007c2a45Smiod 	      /* Line number.  */
47242159047fSniklas 	    case N_SLINE:
47252159047fSniklas 	      /* Offset the line into the correct portion of the file.  */
47262159047fSniklas 	      if (Cur_File->file_number == 0)
47272159047fSniklas 		break;
47282159047fSniklas 	      val = S_GET_VALUE (symbolP);
47292159047fSniklas 	      /* Sometimes the same offset gets several source lines
47302159047fSniklas 		 assigned to it.  We should be selective about which
47312159047fSniklas 		 lines we allow, we should prefer lines that are in
47322159047fSniklas 		 the main source file when debugging inline functions.  */
47332159047fSniklas 	      if (val == Cur_Offset && Cur_File->file_number != 1)
47342159047fSniklas 		break;
47352159047fSniklas 
4736*007c2a45Smiod 	      /* Calculate actual debugger source line.  */
47372159047fSniklas 	      dsc = S_GET_DESC (symbolP) + Cur_File->offset;
47382159047fSniklas 	      S_SET_DESC (symbolP, dsc);
4739*007c2a45Smiod 	      /* Define PC/Line correlation.  */
47402159047fSniklas 	      if (Cur_Offset == -1)
47412159047fSniklas 		{
4742*007c2a45Smiod 		  /* First N_SLINE; set up initial correlation.  */
47432159047fSniklas 		  VMS_TBT_Line_PC_Correlation (dsc,
47442159047fSniklas 					       val,
47452159047fSniklas 					       Text_Psect,
47462159047fSniklas 					       0);
47472159047fSniklas 		}
47482159047fSniklas 	      else if ((dsc - Cur_Line_Number) <= 0)
47492159047fSniklas 		{
4750*007c2a45Smiod 		  /* Line delta is not +ve, we need to close the line and
4751*007c2a45Smiod 		     start a new PC/Line correlation.  */
47522159047fSniklas 		  VMS_TBT_Line_PC_Correlation (0,
47532159047fSniklas 					       val - Cur_Offset,
47542159047fSniklas 					       0,
47552159047fSniklas 					       -1);
47562159047fSniklas 		  VMS_TBT_Line_PC_Correlation (dsc,
47572159047fSniklas 					       val,
47582159047fSniklas 					       Text_Psect,
47592159047fSniklas 					       0);
47602159047fSniklas 		}
47612159047fSniklas 	      else
47622159047fSniklas 		{
4763*007c2a45Smiod 		  /* Line delta is +ve, all is well.  */
47642159047fSniklas 		  VMS_TBT_Line_PC_Correlation (dsc - Cur_Line_Number,
47652159047fSniklas 					       val - Cur_Offset,
47662159047fSniklas 					       0,
47672159047fSniklas 					       1);
47682159047fSniklas 		}
47692159047fSniklas 	      /* Update the current line/PC info.  */
47702159047fSniklas 	      Cur_Line_Number = dsc;
47712159047fSniklas 	      Cur_Offset = val;
47722159047fSniklas 	      break;
47732159047fSniklas 
4774*007c2a45Smiod 		/* Source file.  */
47752159047fSniklas 	    case N_SO:
47762159047fSniklas 	      /* Remember that we had a source file and emit
47772159047fSniklas 		 the source file debugger record.  */
47782159047fSniklas 	      Cur_File = find_file (symbolP);
47792159047fSniklas 	      break;
47802159047fSniklas 
47812159047fSniklas 	    case N_SOL:
47822159047fSniklas 	      /* We need to make sure that we are really in the actual
47832159047fSniklas 		 source file when we compute the maximum line number.
47842159047fSniklas 		 Otherwise the debugger gets really confused.  */
47852159047fSniklas 	      Cur_File = find_file (symbolP);
47862159047fSniklas 	      break;
47872159047fSniklas 
47882159047fSniklas 	    default:
47892159047fSniklas 	      break;
4790*007c2a45Smiod 	    }
4791*007c2a45Smiod 	}
4792*007c2a45Smiod     }
47932159047fSniklas 
4794*007c2a45Smiod     /* If there is a routine start defined, terminate it
4795*007c2a45Smiod        (and the line numbers).  */
47962159047fSniklas     if (Current_Routine)
47972159047fSniklas       {
47982159047fSniklas 	/* Terminate the line numbers.  */
47992159047fSniklas 	VMS_TBT_Line_PC_Correlation (0,
48002159047fSniklas 				     text_siz - S_GET_VALUE (Current_Routine),
48012159047fSniklas 				     0,
48022159047fSniklas 				     -1);
48032159047fSniklas 	/* Terminate the routine.  */
48042159047fSniklas 	VMS_TBT_Routine_End (text_siz, Current_Routine);
48052159047fSniklas       }
48062159047fSniklas 
48072159047fSniklas   /* Write the Traceback End Module TBT record.  */
48082159047fSniklas   VMS_TBT_Module_End ();
48092159047fSniklas }
48102159047fSniklas 
48112159047fSniklas 
48122159047fSniklas /* Write a VAX/VMS object file (everything else has been done!).  */
48132159047fSniklas 
48142159047fSniklas void
vms_write_object_file(unsigned text_siz,unsigned data_siz,unsigned bss_siz,fragS * text_frag_root,fragS * data_frag_root)4815*007c2a45Smiod vms_write_object_file (unsigned text_siz, unsigned data_siz, unsigned bss_siz,
4816*007c2a45Smiod 		       fragS *text_frag_root, fragS *data_frag_root)
48172159047fSniklas {
4818*007c2a45Smiod   struct VMS_Symbol *vsp;
48192159047fSniklas 
4820*007c2a45Smiod   /* Initialize program section indices; values get updated later.  */
48212159047fSniklas   Psect_Number = 0;		/* next Psect Index to use */
48222159047fSniklas   Text_Psect = -1;		/* Text Psect Index   */
48232159047fSniklas   Data_Psect = -2;		/* Data Psect Index   JF: Was -1 */
48242159047fSniklas   Bss_Psect = -3;		/* Bss Psect Index    JF: Was -1 */
4825f7cc78ecSespie   Ctors_Psect = -4;		/* Ctors Psect Index  */
4826f7cc78ecSespie   Dtors_Psect = -5;		/* Dtors Psect Index  */
48272159047fSniklas   /* Initialize other state variables.  */
48282159047fSniklas   Data_Segment = 0;
48292159047fSniklas   Local_Initd_Data_Size = 0;
48302159047fSniklas 
4831*007c2a45Smiod   /* Create the actual output file and populate it with required
4832*007c2a45Smiod      "module header" information.  */
48332159047fSniklas   Create_VMS_Object_File ();
48342159047fSniklas   Write_VMS_MHD_Records ();
48352159047fSniklas 
4836*007c2a45Smiod   /* Create the Data segment:
4837*007c2a45Smiod 
4838*007c2a45Smiod      Since this is REALLY hard to do any other way,
4839*007c2a45Smiod      we actually manufacture the data segment and
4840*007c2a45Smiod      then store the appropriate values out of it.
4841*007c2a45Smiod      We need to generate this early, so that globalvalues
4842*007c2a45Smiod      can be properly emitted.  */
48432159047fSniklas   if (data_siz > 0)
48442159047fSniklas     synthesize_data_segment (data_siz, text_siz, data_frag_root);
48452159047fSniklas 
4846*007c2a45Smiod   /* Global Symbol Directory.  */
48472159047fSniklas 
4848*007c2a45Smiod   /* Emit globalvalues now.  We must do this before the text psect is
4849*007c2a45Smiod      defined, or we will get linker warnings about multiply defined
4850*007c2a45Smiod      symbols.  All of the globalvalues "reference" psect 0, although
4851*007c2a45Smiod      it really does not have anything to do with it.  */
48522159047fSniklas   VMS_Emit_Globalvalues (text_siz, data_siz, Data_Segment);
4853*007c2a45Smiod   /* Define the Text Psect.  */
48542159047fSniklas   Text_Psect = Psect_Number++;
48552159047fSniklas   VMS_Psect_Spec ("$code", text_siz, ps_TEXT, 0);
4856*007c2a45Smiod   /* Define the BSS Psect.  */
48572159047fSniklas   if (bss_siz > 0)
48582159047fSniklas     {
48592159047fSniklas       Bss_Psect = Psect_Number++;
48602159047fSniklas       VMS_Psect_Spec ("$uninitialized_data", bss_siz, ps_DATA, 0);
48612159047fSniklas     }
4862*007c2a45Smiod   /* Define symbols to the linker.  */
48632159047fSniklas   global_symbol_directory (text_siz, data_siz);
4864*007c2a45Smiod   /* Define the Data Psect.  */
48652159047fSniklas   if (data_siz > 0 && Local_Initd_Data_Size > 0)
48662159047fSniklas     {
48672159047fSniklas       Data_Psect = Psect_Number++;
48682159047fSniklas       VMS_Psect_Spec ("$data", Local_Initd_Data_Size, ps_DATA, 0);
4869*007c2a45Smiod       /* Local initialized data (N_DATA) symbols need to be updated to the
4870*007c2a45Smiod          proper value of Data_Psect now that it's actually been defined.
4871*007c2a45Smiod          (A dummy value was used in global_symbol_directory() above.)  */
48722159047fSniklas       for (vsp = VMS_Symbols; vsp; vsp = vsp->Next)
48732159047fSniklas 	if (vsp->Psect_Index < 0 && S_GET_RAW_TYPE (vsp->Symbol) == N_DATA)
48742159047fSniklas 	  vsp->Psect_Index = Data_Psect;
48752159047fSniklas     }
48762159047fSniklas 
4877f7cc78ecSespie   if (Ctors_Symbols != 0)
4878f7cc78ecSespie     {
4879f7cc78ecSespie       char *ps_name = "$ctors";
4880f7cc78ecSespie       Ctors_Psect = Psect_Number++;
4881f7cc78ecSespie       VMS_Psect_Spec (ps_name, Ctors_Symbols->Psect_Offset + XTOR_SIZE,
4882f7cc78ecSespie 		      ps_CTORS, 0);
4883f7cc78ecSespie       VMS_Global_Symbol_Spec (ps_name, Ctors_Psect,
4884f7cc78ecSespie 				  0, GBLSYM_DEF|GBLSYM_WEAK);
4885f7cc78ecSespie       for (vsp = Ctors_Symbols; vsp; vsp = vsp->Next)
4886f7cc78ecSespie 	vsp->Psect_Index = Ctors_Psect;
4887f7cc78ecSespie     }
4888f7cc78ecSespie 
4889f7cc78ecSespie   if (Dtors_Symbols != 0)
4890f7cc78ecSespie     {
4891f7cc78ecSespie       char *ps_name = "$dtors";
4892f7cc78ecSespie       Dtors_Psect = Psect_Number++;
4893f7cc78ecSespie       VMS_Psect_Spec (ps_name, Dtors_Symbols->Psect_Offset + XTOR_SIZE,
4894f7cc78ecSespie 		      ps_DTORS, 0);
4895f7cc78ecSespie       VMS_Global_Symbol_Spec (ps_name, Dtors_Psect,
4896f7cc78ecSespie 				  0, GBLSYM_DEF|GBLSYM_WEAK);
4897f7cc78ecSespie       for (vsp = Dtors_Symbols; vsp; vsp = vsp->Next)
4898f7cc78ecSespie 	vsp->Psect_Index = Dtors_Psect;
4899f7cc78ecSespie     }
4900f7cc78ecSespie 
4901*007c2a45Smiod   /* Text Information and Relocation Records.  */
49022159047fSniklas 
4903*007c2a45Smiod   /* Write the text segment data.  */
49042159047fSniklas   if (text_siz > 0)
49052159047fSniklas     vms_fixup_text_section (text_siz, text_frag_root, data_frag_root);
4906*007c2a45Smiod   /* Write the data segment data, then discard it.  */
49072159047fSniklas   if (data_siz > 0)
49082159047fSniklas     {
49092159047fSniklas       vms_fixup_data_section (data_siz, text_siz);
49102159047fSniklas       free (Data_Segment),  Data_Segment = 0;
49112159047fSniklas     }
49122159047fSniklas 
4913f7cc78ecSespie   if (Ctors_Symbols != 0)
4914f7cc78ecSespie     vms_fixup_xtors_section (Ctors_Symbols, Ctors_Psect);
4915f7cc78ecSespie 
4916f7cc78ecSespie   if (Dtors_Symbols != 0)
4917f7cc78ecSespie     vms_fixup_xtors_section (Dtors_Symbols, Dtors_Psect);
4918f7cc78ecSespie 
4919*007c2a45Smiod   /* Debugger Symbol Table Records.  */
49202159047fSniklas 
49212159047fSniklas   vms_build_DST (text_siz);
49222159047fSniklas 
4923*007c2a45Smiod   /* Wrap things up.  */
49242159047fSniklas 
4925*007c2a45Smiod   /* Write the End Of Module record.  */
49262159047fSniklas   if (Entry_Point_Symbol)
49272159047fSniklas     Write_VMS_EOM_Record (Text_Psect, S_GET_VALUE (Entry_Point_Symbol));
49282159047fSniklas   else
49292159047fSniklas     Write_VMS_EOM_Record (-1, (valueT) 0);
49302159047fSniklas 
4931*007c2a45Smiod   /* All done, close the object file.  */
49322159047fSniklas   Close_VMS_Object_File ();
49332159047fSniklas }
4934