OSDN Git Service

* config/xtensa/xtensa.c (xtensa_init_machine_status): Fix
[pf3gnuchains/gcc-fork.git] / gcc / vmsdbgout.c
1 /* Output VMS debug format symbol table information from the GNU C compiler.
2    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4    Contributed by Douglas B. Rupp (rupp@gnat.com).
5
6 This file is part of GNU CC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.  */
22
23 #include "config.h"
24
25 #ifdef VMS_DEBUGGING_INFO
26 #include "system.h"
27 #include "tree.h"
28 #include "flags.h"
29 #include "rtl.h"
30 #include "output.h"
31 #include "vmsdbg.h"
32 #include "debug.h"
33 #include "langhooks.h"
34
35 /* Difference in seconds between the VMS Epoch and the Unix Epoch */
36 static const long long vms_epoch_offset = 3506716800ll;
37
38 /* NOTE: In the comments in this file, many references are made to "Debug
39    Symbol Table".  This term is abbreviated as `DST' throughout the remainder
40    of this file.  */
41
42 typedef struct dst_line_info_struct *dst_line_info_ref;
43
44 /* Each entry in the line_info_table maintains the file and
45    line number associated with the label generated for that
46    entry.  The label gives the PC value associated with
47    the line number entry.  */
48 typedef struct dst_line_info_struct
49 {
50   unsigned long dst_file_num;
51   unsigned long dst_line_num;
52 }
53 dst_line_info_entry;
54
55 typedef struct dst_file_info_struct *dst_file_info_ref;
56
57 typedef struct dst_file_info_struct
58 {
59   char *file_name;
60   unsigned int max_line;
61   unsigned int listing_line_start;
62   long long cdt;
63   long ebk;
64   short ffb;
65   char rfo;
66   char flen;
67 }
68 dst_file_info_entry;
69
70 /* How to start an assembler comment.  */
71 #ifndef ASM_COMMENT_START
72 #define ASM_COMMENT_START ";#"
73 #endif
74
75 /* Maximum size (in bytes) of an artificially generated label.  */
76 #define MAX_ARTIFICIAL_LABEL_BYTES      30
77
78 /* Make sure we know the sizes of the various types debug can describe. These
79    are only defaults.  If the sizes are different for your target, you should
80    override these values by defining the appropriate symbols in your tm.h
81    file.  */
82 #ifndef PTR_SIZE
83 #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */
84 #endif
85
86 /* Pointer to an structure of filenames referenced by this compilation unit.  */
87 static dst_file_info_ref file_info_table;
88
89 /* Total number of entries in the table (i.e. array) pointed to by
90    `file_info_table'.  This is the *total* and includes both used and unused
91    slots.  */
92 static unsigned int file_info_table_allocated;
93
94 /* Number of entries in the file_info_table which are actually in use.  */
95 static unsigned int file_info_table_in_use;
96
97 /* Size (in elements) of increments by which we may expand the filename
98    table.  */
99 #define FILE_TABLE_INCREMENT 64
100
101 static char **func_table;
102 static unsigned int func_table_allocated;
103 static unsigned int func_table_in_use;
104 #define FUNC_TABLE_INCREMENT 256
105
106 /* Local pointer to the name of the main input file.  Initialized in
107    avmdbgout_init.  */
108 static const char *primary_filename;
109
110 static char *module_producer;
111 static unsigned int module_language;
112
113 /* A pointer to the base of a table that contains line information
114    for each source code line in .text in the compilation unit.  */
115 static dst_line_info_ref line_info_table;
116
117 /* Number of elements currently allocated for line_info_table.  */
118 static unsigned int line_info_table_allocated;
119
120 /* Number of elements in line_info_table currently in use.  */
121 static unsigned int line_info_table_in_use;
122
123 /* Size (in elements) of increments by which we may expand line_info_table.  */
124 #define LINE_INFO_TABLE_INCREMENT 1024
125
126 /* The number of the current function definition for which debugging
127    information is being generated.  These numbers range from 1 up to the
128    maximum number of function definitions contained within the current
129    compilation unit.  These numbers are used to create unique label id's unique
130    to each function definition.  */
131 static unsigned int current_funcdef_number = 0;
132
133 /* Forward declarations for functions defined in this file.  */
134 static char *full_name          PARAMS ((const char *));
135 static unsigned int lookup_filename PARAMS ((const char *));
136 static void addr_const_to_string PARAMS ((char *, rtx));
137 static int write_debug_header   PARAMS ((DST_HEADER *, const char *, int));
138 static int write_debug_addr     PARAMS ((char *, const char *, int));
139 static int write_debug_data1    PARAMS ((unsigned int, const char *, int));
140 static int write_debug_data2    PARAMS ((unsigned int, const char *, int));
141 static int write_debug_data4    PARAMS ((unsigned long, const char *, int));
142 static int write_debug_data8    PARAMS ((unsigned long long, const char *,
143                                          int));
144 static int write_debug_delta4   PARAMS ((char *, char *, const char *, int));
145 static int write_debug_string   PARAMS ((char *, const char *, int));
146 static int write_modbeg         PARAMS ((int));
147 static int write_modend         PARAMS ((int));
148 static int write_rtnbeg         PARAMS ((int, int));
149 static int write_rtnend         PARAMS ((int, int));
150 static int write_pclines        PARAMS ((int));
151 static int write_srccorr        PARAMS ((int, dst_file_info_entry, int));
152 static int write_srccorrs       PARAMS ((int));
153
154 static void vmsdbgout_init              PARAMS ((const char *));
155 static void vmsdbgout_finish            PARAMS ((const char *));
156 static void vmsdbgout_define            PARAMS ((unsigned int, const char *));
157 static void vmsdbgout_undef             PARAMS ((unsigned int, const char *));
158 static void vmsdbgout_start_source_file PARAMS ((unsigned int, const char *));
159 static void vmsdbgout_end_source_file   PARAMS ((unsigned int));
160 static void vmsdbgout_begin_block       PARAMS ((unsigned int, unsigned int));
161 static void vmsdbgout_end_block         PARAMS ((unsigned int, unsigned int));
162 static bool vmsdbgout_ignore_block      PARAMS ((tree));
163 static void vmsdbgout_source_line       PARAMS ((unsigned int, const char *));
164 static void vmsdbgout_begin_prologue    PARAMS ((unsigned int, const char *));
165 static void vmsdbgout_end_epilogue      PARAMS ((void));
166 static void vmsdbgout_begin_function    PARAMS ((tree));
167 static void vmsdbgout_decl              PARAMS ((tree));
168 static void vmsdbgout_global_decl       PARAMS ((tree));
169 static void vmsdbgout_abstract_function PARAMS ((tree));
170
171 /* The debug hooks structure.  */
172
173 const struct gcc_debug_hooks vmsdbg_debug_hooks
174 = {vmsdbgout_init,
175    vmsdbgout_finish,
176    vmsdbgout_define,
177    vmsdbgout_undef,
178    vmsdbgout_start_source_file,
179    vmsdbgout_end_source_file,
180    vmsdbgout_begin_block,
181    vmsdbgout_end_block,
182    vmsdbgout_ignore_block,
183    vmsdbgout_source_line,
184    vmsdbgout_begin_prologue,
185    debug_nothing_int,           /* end_prologue */
186    vmsdbgout_end_epilogue,      /* end_epilogue */
187    vmsdbgout_begin_function,    /* begin_function */
188    debug_nothing_int,           /* end_function */
189    vmsdbgout_decl,
190    vmsdbgout_global_decl,
191    debug_nothing_tree,          /* deferred_inline_function */
192    vmsdbgout_abstract_function,
193    debug_nothing_rtx            /* label */
194 };
195
196 /* Definitions of defaults for assembler-dependent names of various
197    pseudo-ops and section names.
198    Theses may be overridden in the tm.h file (if necessary) for a particular
199    assembler.  */
200 #ifdef UNALIGNED_SHORT_ASM_OP
201 #undef UNALIGNED_SHORT_ASM_OP
202 #endif
203 #define UNALIGNED_SHORT_ASM_OP  ".word"
204
205 #ifdef UNALIGNED_INT_ASM_OP
206 #undef UNALIGNED_INT_ASM_OP
207 #endif
208 #define UNALIGNED_INT_ASM_OP    ".long"
209
210 #ifdef UNALIGNED_LONG_ASM_OP
211 #undef UNALIGNED_LONG_ASM_OP
212 #endif
213 #define UNALIGNED_LONG_ASM_OP   ".long"
214
215 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
216 #undef UNALIGNED_DOUBLE_INT_ASM_OP
217 #endif
218 #define UNALIGNED_DOUBLE_INT_ASM_OP     ".quad"
219
220 #ifdef ASM_BYTE_OP
221 #undef ASM_BYTE_OP
222 #endif
223 #define ASM_BYTE_OP     ".byte"
224
225 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
226
227 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
228
229 #ifndef UNALIGNED_PTR_ASM_OP
230 #define UNALIGNED_PTR_ASM_OP \
231   (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
232 #endif
233
234 #ifndef UNALIGNED_OFFSET_ASM_OP
235 #define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
236   (NUMBYTES(OFFSET) == 4 \
237    ? UNALIGNED_LONG_ASM_OP \
238    : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
239 #endif
240
241 /* Pseudo-op for defining a new section.  */
242 #ifndef SECTION_ASM_OP
243 #define SECTION_ASM_OP  ".section"
244 #endif
245
246 /* Definitions of defaults for formats and names of various special
247    (artificial) labels which may be generated within this file (when the -g
248    options is used and VMS_DEBUGGING_INFO is in effect.  If necessary, these
249    may be overridden from within the tm.h file, but typically, overriding these
250    defaults is unnecessary.  */
251
252 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
253
254 #ifndef TEXT_END_LABEL
255 #define TEXT_END_LABEL          "Lvetext"
256 #endif
257 #ifndef FUNC_BEGIN_LABEL
258 #define FUNC_BEGIN_LABEL        "LVFB"
259 #endif
260 #ifndef FUNC_PROLOG_LABEL
261 #define FUNC_PROLOG_LABEL       "LVFP"
262 #endif
263 #ifndef FUNC_END_LABEL
264 #define FUNC_END_LABEL          "LVFE"
265 #endif
266 #ifndef BLOCK_BEGIN_LABEL
267 #define BLOCK_BEGIN_LABEL       "LVBB"
268 #endif
269 #ifndef BLOCK_END_LABEL
270 #define BLOCK_END_LABEL         "LVBE"
271 #endif
272 #ifndef LINE_CODE_LABEL
273 #define LINE_CODE_LABEL         "LVM"
274 #endif
275
276 #ifndef ASM_OUTPUT_DEBUG_DELTA2
277 #define ASM_OUTPUT_DEBUG_DELTA2(FILE,LABEL1,LABEL2)                      \
278   do                                                                     \
279     {                                                                    \
280       fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);                \
281       assemble_name (FILE, LABEL1);                                      \
282       fprintf (FILE, "-");                                               \
283       assemble_name (FILE, LABEL2);                                      \
284     }                                                                    \
285   while (0)
286 #endif
287
288 #ifndef ASM_OUTPUT_DEBUG_DELTA4
289 #define ASM_OUTPUT_DEBUG_DELTA4(FILE,LABEL1,LABEL2)                      \
290   do                                                                     \
291     {                                                                    \
292       fprintf ((FILE), "\t%s\t", UNALIGNED_INT_ASM_OP);                  \
293       assemble_name (FILE, LABEL1);                                      \
294       fprintf (FILE, "-");                                               \
295       assemble_name (FILE, LABEL2);                                      \
296     }                                                                    \
297   while (0)
298 #endif
299
300 #ifndef ASM_OUTPUT_DEBUG_ADDR_DELTA
301 #define ASM_OUTPUT_DEBUG_ADDR_DELTA(FILE,LABEL1,LABEL2)                  \
302   do                                                                     \
303     {                                                                    \
304       fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);                  \
305       assemble_name (FILE, LABEL1);                                      \
306       fprintf (FILE, "-");                                               \
307       assemble_name (FILE, LABEL2);                                      \
308     }                                                                    \
309   while (0)
310 #endif
311
312 #ifndef ASM_OUTPUT_DEBUG_ADDR
313 #define ASM_OUTPUT_DEBUG_ADDR(FILE,LABEL)                                \
314   do                                                                     \
315     {                                                                    \
316       fprintf ((FILE), "\t%s\t", UNALIGNED_PTR_ASM_OP);                  \
317       assemble_name (FILE, LABEL);                                       \
318     }                                                                    \
319   while (0)
320 #endif
321
322 #ifndef ASM_OUTPUT_DEBUG_ADDR_CONST
323 #define ASM_OUTPUT_DEBUG_ADDR_CONST(FILE,ADDR)                          \
324   fprintf ((FILE), "\t%s\t%s", UNALIGNED_PTR_ASM_OP, (ADDR))
325 #endif
326
327 #ifndef ASM_OUTPUT_DEBUG_DATA1
328 #define ASM_OUTPUT_DEBUG_DATA1(FILE,VALUE) \
329   fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned char) VALUE)
330 #endif
331
332 #ifndef ASM_OUTPUT_DEBUG_DATA2
333 #define ASM_OUTPUT_DEBUG_DATA2(FILE,VALUE) \
334   fprintf ((FILE), "\t%s\t0x%x", UNALIGNED_SHORT_ASM_OP, \
335            (unsigned short) VALUE)
336 #endif
337
338 #ifndef ASM_OUTPUT_DEBUG_DATA4
339 #define ASM_OUTPUT_DEBUG_DATA4(FILE,VALUE) \
340   fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_INT_ASM_OP, (unsigned long) VALUE)
341 #endif
342
343 #ifndef ASM_OUTPUT_DEBUG_DATA
344 #define ASM_OUTPUT_DEBUG_DATA(FILE,VALUE) \
345   fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_OFFSET_ASM_OP(VALUE), VALUE)
346 #endif
347
348 #ifndef ASM_OUTPUT_DEBUG_ADDR_DATA
349 #define ASM_OUTPUT_DEBUG_ADDR_DATA(FILE,VALUE) \
350   fprintf ((FILE), "\t%s\t0x%lx", UNALIGNED_PTR_ASM_OP, \
351            (unsigned long) VALUE)
352 #endif
353
354 #ifndef ASM_OUTPUT_DEBUG_DATA8
355 #define ASM_OUTPUT_DEBUG_DATA8(FILE,VALUE) \
356   fprintf ((FILE), "\t%s\t0x%llx", UNALIGNED_DOUBLE_INT_ASM_OP, \
357                                  (unsigned long long) VALUE)
358 #endif
359
360 /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing
361    newline is produced.  When flag_verbose_asm is asserted, we add commnetary
362    at the end of the line, so we must avoid output of a newline here.  */
363 #ifndef ASM_OUTPUT_DEBUG_STRING
364 #define ASM_OUTPUT_DEBUG_STRING(FILE,P)         \
365   do                                            \
366     {                                           \
367       register int slen = strlen(P);            \
368       register char *p = (P);                   \
369       register int i;                           \
370       fprintf (FILE, "\t.ascii \"");            \
371       for (i = 0; i < slen; i++)                \
372         {                                       \
373           register int c = p[i];                \
374           if (c == '\"' || c == '\\')           \
375             putc ('\\', FILE);                  \
376           if (c >= ' ' && c < 0177)             \
377             putc (c, FILE);                     \
378           else                                  \
379             fprintf (FILE, "\\%o", c);          \
380         }                                       \
381       fprintf (FILE, "\"");                     \
382     }                                           \
383   while (0)
384 #endif
385
386 /* Convert a reference to the assembler name of a C-level name.  This
387    macro has the same effect as ASM_OUTPUT_LABELREF, but copies to
388    a string rather than writing to a file.  */
389 #ifndef ASM_NAME_TO_STRING
390 #define ASM_NAME_TO_STRING(STR, NAME)           \
391   do                                            \
392     {                                           \
393       if ((NAME)[0] == '*')                     \
394         strcpy (STR, NAME+1);                   \
395       else                                      \
396         strcpy (STR, NAME);                     \
397     }                                           \
398   while (0)
399 #endif
400
401 \f
402 /* General utility functions.  */
403
404 /* Convert an integer constant expression into assembler syntax.  Addition and
405    subtraction are the only arithmetic that may appear in these expressions.
406    This is an adaptation of output_addr_const in final.c.  Here, the target
407    of the conversion is a string buffer.  We can't use output_addr_const
408    directly, because it writes to a file.  */
409
410 static void
411 addr_const_to_string (str, x)
412      char *str;
413      rtx x;
414 {
415   char buf1[256];
416   char buf2[256];
417
418 restart:
419   str[0] = '\0';
420   switch (GET_CODE (x))
421     {
422     case PC:
423       if (flag_pic)
424         strcat (str, ",");
425       else
426         abort ();
427       break;
428
429     case SYMBOL_REF:
430       ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
431       strcat (str, buf1);
432       break;
433
434     case LABEL_REF:
435       ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
436       ASM_NAME_TO_STRING (buf2, buf1);
437       strcat (str, buf2);
438       break;
439
440     case CODE_LABEL:
441       ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
442       ASM_NAME_TO_STRING (buf2, buf1);
443       strcat (str, buf2);
444       break;
445
446     case CONST_INT:
447       sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
448       strcat (str, buf1);
449       break;
450
451     case CONST:
452       /* This used to output parentheses around the expression, but that does
453          not work on the 386 (either ATT or BSD assembler).  */
454       addr_const_to_string (buf1, XEXP (x, 0));
455       strcat (str, buf1);
456       break;
457
458     case CONST_DOUBLE:
459       if (GET_MODE (x) == VOIDmode)
460         {
461           /* We can use %d if the number is one word and positive.  */
462           if (CONST_DOUBLE_HIGH (x))
463             sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
464                      CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
465           else if (CONST_DOUBLE_LOW (x) < 0)
466             sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
467           else
468             sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
469                      CONST_DOUBLE_LOW (x));
470           strcat (str, buf1);
471         }
472       else
473         /* We can't handle floating point constants; PRINT_OPERAND must
474            handle them.  */
475         output_operand_lossage ("floating constant misused");
476       break;
477
478     case PLUS:
479       /* Some assemblers need integer constants to appear last (eg masm).  */
480       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
481         {
482           addr_const_to_string (buf1, XEXP (x, 1));
483           strcat (str, buf1);
484           if (INTVAL (XEXP (x, 0)) >= 0)
485             strcat (str, "+");
486           addr_const_to_string (buf1, XEXP (x, 0));
487           strcat (str, buf1);
488         }
489       else
490         {
491           addr_const_to_string (buf1, XEXP (x, 0));
492           strcat (str, buf1);
493           if (INTVAL (XEXP (x, 1)) >= 0)
494             strcat (str, "+");
495           addr_const_to_string (buf1, XEXP (x, 1));
496           strcat (str, buf1);
497         }
498       break;
499
500     case MINUS:
501       /* Avoid outputting things like x-x or x+5-x, since some assemblers
502          can't handle that.  */
503       x = simplify_subtraction (x);
504       if (GET_CODE (x) != MINUS)
505         goto restart;
506
507       addr_const_to_string (buf1, XEXP (x, 0));
508       strcat (str, buf1);
509       strcat (str, "-");
510       if (GET_CODE (XEXP (x, 1)) == CONST_INT
511           && INTVAL (XEXP (x, 1)) < 0)
512         {
513           strcat (str, "(");
514           addr_const_to_string (buf1, XEXP (x, 1));
515           strcat (str, buf1);
516           strcat (str, ")");
517         }
518       else
519         {
520           addr_const_to_string (buf1, XEXP (x, 1));
521           strcat (str, buf1);
522         }
523       break;
524
525     case ZERO_EXTEND:
526     case SIGN_EXTEND:
527       addr_const_to_string (buf1, XEXP (x, 0));
528       strcat (str, buf1);
529       break;
530
531     default:
532       output_operand_lossage ("invalid expression as operand");
533     }
534 }
535
536 /* Output the debug header HEADER.  Also output COMMENT if flag_verbose_asm is
537    set.  Return the header size.  Just return the size if DOSIZEONLY is
538    non-zero.  */
539
540 static int
541 write_debug_header (header, comment, dosizeonly)
542      DST_HEADER *header;
543      const char *comment;
544      int dosizeonly;
545 {
546   if (!dosizeonly)
547     {
548       ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
549                               header->dst__header_length.dst_w_length);
550
551       if (flag_verbose_asm)
552         fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
553       fputc ('\n', asm_out_file);
554
555       ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
556                               header->dst__header_type.dst_w_type);
557
558       if (flag_verbose_asm)
559         fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
560                  comment);
561
562       fputc ('\n', asm_out_file);
563     }
564
565   return 4;
566 }
567
568 /* Output the address of SYMBOL.  Also output COMMENT if flag_verbose_asm is
569    set.  Return the address size.  Just return the size if DOSIZEONLY is
570    non-zero.  */
571
572 static int
573 write_debug_addr (symbol, comment, dosizeonly)
574      char *symbol;
575      const char *comment;
576      int dosizeonly;
577 {
578   if (!dosizeonly)
579     {
580       ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
581       if (flag_verbose_asm)
582         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
583       fputc ('\n', asm_out_file);
584     }
585
586   return PTR_SIZE;
587 }
588
589 /* Output the single byte DATA1.  Also output COMMENT if flag_verbose_asm is
590    set.  Return the data size.  Just return the size if DOSIZEONLY is
591    non-zero.  */
592
593 static int
594 write_debug_data1 (data1, comment, dosizeonly)
595      unsigned int data1;
596      const char *comment;
597      int dosizeonly;
598 {
599   if (!dosizeonly)
600     {
601       ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
602       if (flag_verbose_asm)
603         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
604       fputc ('\n', asm_out_file);
605     }
606
607   return 1;
608 }
609
610 /* Output the single word DATA2.  Also output COMMENT if flag_verbose_asm is
611    set.  Return the data size.  Just return the size if DOSIZEONLY is
612    non-zero.  */
613
614 static int
615 write_debug_data2 (data2, comment, dosizeonly)
616      unsigned int data2;
617      const char *comment;
618      int dosizeonly;
619 {
620   if (!dosizeonly)
621     {
622       ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
623       if (flag_verbose_asm)
624         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
625       fputc ('\n', asm_out_file);
626     }
627
628   return 2;
629 }
630
631 /* Output double word DATA4.  Also output COMMENT if flag_verbose_asm is set.
632    Return the data size.  Just return the size if DOSIZEONLY is non-zero.  */
633
634 static int
635 write_debug_data4 (data4, comment, dosizeonly)
636      unsigned long data4;
637      const char *comment;
638      int dosizeonly;
639 {
640   if (!dosizeonly)
641     {
642       ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
643       if (flag_verbose_asm)
644         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
645       fputc ('\n', asm_out_file);
646     }
647
648   return 4;
649 }
650
651 /* Output quad word DATA8.  Also output COMMENT if flag_verbose_asm is set.
652    Return the data size.  Just return the size if DOSIZEONLY is non-zero.  */
653
654 static int
655 write_debug_data8 (data8, comment, dosizeonly)
656      unsigned long long data8;
657      const char *comment;
658      int dosizeonly;
659 {
660   if (!dosizeonly)
661     {
662       ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
663       if (flag_verbose_asm)
664         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
665       fputc ('\n', asm_out_file);
666     }
667
668   return 8;
669 }
670
671 /* Output the difference between LABEL1 and LABEL2.  Also output COMMENT if
672    flag_verbose_asm is set.  Return the data size.  Just return the size if
673    DOSIZEONLY is non-zero.  */
674
675 static int
676 write_debug_delta4 (label1, label2, comment, dosizeonly)
677      char *label1;
678      char *label2;
679      const char *comment;
680      int dosizeonly;
681 {
682   if (!dosizeonly)
683     {
684       ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
685       if (flag_verbose_asm)
686         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
687       fputc ('\n', asm_out_file);
688     }
689
690   return 4;
691 }
692
693 /* Output a character string STRING.  Also write COMMENT if flag_verbose_asm is
694    set.  Return the string length.  Just return the length if DOSIZEONLY is
695    non-zero.  */
696
697 static int
698 write_debug_string (string, comment, dosizeonly)
699      char *string;
700      const char *comment;
701      int dosizeonly;
702 {
703   if (!dosizeonly)
704     {
705       ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
706       if (flag_verbose_asm)
707         fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
708       fputc ('\n', asm_out_file);
709     }
710
711   return strlen (string);
712 }
713
714 /* Output a module begin header and return the header size.  Just return the
715    size if DOSIZEONLY is non-zero.  */
716
717 static int
718 write_modbeg (dosizeonly)
719      int dosizeonly;
720 {
721   DST_MODULE_BEGIN modbeg;
722   DST_MB_TRLR mb_trlr;
723   int i;
724   char *module_name, *m;
725   int modnamelen;
726   int prodnamelen;
727   int totsize = 0;
728
729   /* Assumes primary filename has Unix syntax file spec.  */
730   module_name = xstrdup (basename ((char *) primary_filename));
731
732   m = strrchr (module_name, '.');
733   if (m)
734     *m = 0;
735
736   modnamelen = strlen (module_name);
737   for (i = 0; i < modnamelen; i++)
738     module_name[i] = TOUPPER (module_name[i]);
739
740   prodnamelen = strlen (module_producer);
741
742   modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
743     = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
744   modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
745   modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
746   modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
747   modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
748   modbeg.dst_b_modbeg_unused = 0;
749   modbeg.dst_l_modbeg_language = module_language;
750   modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
751   modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
752   modbeg.dst_b_modbeg_name = strlen (module_name);
753
754   mb_trlr.dst_b_compiler = strlen (module_producer);
755
756   totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
757                                  "modbeg", dosizeonly);
758   totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
759                                 "flags", dosizeonly);
760   totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
761                                 "unused", dosizeonly);
762   totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
763                                 "language", dosizeonly);
764   totsize += write_debug_data2 (modbeg.dst_w_version_major,
765                                 "DST major version", dosizeonly);
766   totsize += write_debug_data2 (modbeg.dst_w_version_minor,
767                                 "DST minor version", dosizeonly);
768   totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
769                                 "length of module name", dosizeonly);
770   totsize += write_debug_string (module_name, "module name", dosizeonly);
771   totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
772                                 "length of compiler name", dosizeonly);
773   totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
774
775   return totsize;
776 }
777
778 /* Output a module end trailer and return the trailer size.   Just return
779    the size if DOSIZEONLY is non-zero.  */
780
781 static int
782 write_modend (dosizeonly)
783      int dosizeonly;
784 {
785   DST_MODULE_END modend;
786   int totsize = 0;
787
788   modend.dst_a_modend_header.dst__header_length.dst_w_length
789    = DST_K_MODEND_SIZE - 1;
790   modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
791
792   totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
793                                  dosizeonly);
794
795   return totsize;
796 }
797
798 /* Output a routine begin header routine RTNNUM and return the header size.
799    Just return the size if DOSIZEONLY is non-zero.  */
800
801 static int
802 write_rtnbeg (rtnnum, dosizeonly)
803      int rtnnum;
804      int dosizeonly;
805 {
806   char *rtnname;
807   int rtnnamelen, rtnentrynamelen;
808   char *rtnentryname;
809   int totsize = 0;
810   char label[MAX_ARTIFICIAL_LABEL_BYTES];
811   DST_ROUTINE_BEGIN rtnbeg;
812   DST_PROLOG prolog;
813
814   rtnname = func_table[rtnnum];
815   rtnnamelen = strlen (rtnname);
816   rtnentrynamelen = rtnnamelen + 4; /* "..en" */
817   rtnentryname = (char *) xmalloc (rtnentrynamelen + 1);
818   strcpy (rtnentryname, rtnname);
819   strcat (rtnentryname, "..en");
820
821   if (!strcmp (rtnname, "main"))
822     {
823       DST_HEADER header;
824       const char *go = "TRANSFER$BREAK$GO";
825
826       /* This command isn't documented in DSTRECORDS, so it's made to
827          look like what DEC C does */
828
829       /* header size - 1st byte + flag byte + STO_LW size
830          + string count byte + string length */
831       header.dst__header_length.dst_w_length
832         = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
833       header.dst__header_type.dst_w_type = 0x17;
834
835       totsize += write_debug_header (&header, "transfer", dosizeonly);
836
837       /* I think this is a flag byte, but I don't know what this flag means */
838       totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
839
840       /* Routine Begin PD Address */
841       totsize += write_debug_addr (rtnname, "main procedure descriptor",
842                                    dosizeonly);
843       totsize += write_debug_data1 (strlen (go), "length of main_name",
844                                     dosizeonly);
845       totsize += write_debug_string ((char *) go, "main name", dosizeonly);
846     }
847
848   /* The header length never includes the length byte */
849   rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
850    = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
851   rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
852   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
853   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
854   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
855   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
856   rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
857   rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
858
859   totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
860                                  dosizeonly);
861   totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
862                                 "flags", dosizeonly);
863
864   /* Routine Begin Address */
865   totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
866
867   /* Routine Begin PD Address */
868   totsize += write_debug_addr (rtnname, "routine procedure descriptor",
869                                dosizeonly);
870
871   /* Routine Begin Name */
872   totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
873                                 "length of routine name", dosizeonly);
874
875   totsize += write_debug_string (rtnname, "routine name", dosizeonly);
876
877   free (rtnentryname);
878
879   if (debug_info_level > DINFO_LEVEL_TERSE)
880     {
881       prolog.dst_a_prolog_header.dst__header_length.dst_w_length
882         = DST_K_PROLOG_SIZE - 1;
883       prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
884
885       totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
886                                      dosizeonly);
887
888       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum);
889       totsize += write_debug_addr (label, "prolog breakpoint addr",
890                                    dosizeonly);
891     }
892
893   return totsize;
894 }
895
896 /* Output a routine end trailer for routine RTNNUM and return the header size.
897    Just return the size if DOSIZEONLY is non-zero.  */
898
899 static int
900 write_rtnend (rtnnum, dosizeonly)
901      int rtnnum;
902      int dosizeonly;
903 {
904   DST_ROUTINE_END rtnend;
905   char label1[MAX_ARTIFICIAL_LABEL_BYTES];
906   char label2[MAX_ARTIFICIAL_LABEL_BYTES];
907   int totsize;
908
909   totsize = 0;
910
911   rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
912    = DST_K_RTNEND_SIZE - 1;
913   rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
914   rtnend.dst_b_rtnend_unused = 0;
915   rtnend.dst_l_rtnend_size = 0; /* Calculated below.  */
916
917   totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
918                                  dosizeonly);
919   totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
920                                 dosizeonly);
921
922   ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum);
923   ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum);
924   totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
925
926   return totsize;
927 }
928
929 #define K_DELTA_PC(I) \
930  ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
931
932 #define K_SET_LINUM(I) \
933  ((I) < 256 ? DST_K_SET_LINUM_B \
934   : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
935
936 #define K_INCR_LINUM(I) \
937  ((I) < 256 ? DST_K_INCR_LINUM \
938   : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
939
940 /* Output the PC to line number correlations and return the size.  Just return
941    the size if DOSIZEONLY is non-zero */
942
943 static int
944 write_pclines (dosizeonly)
945      int dosizeonly;
946 {
947   unsigned i;
948   int fn;
949   int ln, lastln;
950   int linestart = 0;
951   int max_line;
952   DST_LINE_NUM_HEADER line_num;
953   DST_PCLINE_COMMANDS pcline;
954   char label[MAX_ARTIFICIAL_LABEL_BYTES];
955   char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
956   int totsize = 0;
957   char buff[256];
958
959   max_line = file_info_table[1].max_line;
960   file_info_table[1].listing_line_start = linestart;
961   linestart = linestart + ((max_line / 100000) + 1) * 100000;
962
963   for (i = 2; i < file_info_table_in_use; i++)
964     {
965       max_line = file_info_table[i].max_line;
966       file_info_table[i].listing_line_start = linestart;
967       linestart = linestart + ((max_line / 10000) + 1) * 10000;
968     }
969
970   /* Set starting address to beginning of text section */
971   line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
972   line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
973   pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
974
975   totsize += write_debug_header (&line_num.dst_a_line_num_header,
976                                  "line_num", dosizeonly);
977   totsize += write_debug_data1 (pcline.dst_b_pcline_command,
978                                 "line_num (SET ABS PC)", dosizeonly);
979
980   if (dosizeonly)
981     totsize += 4;
982   else
983     {
984       ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
985       if (flag_verbose_asm)
986         fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
987       fputc ('\n', asm_out_file);
988     }
989
990   fn = line_info_table[1].dst_file_num;
991   ln = (file_info_table[fn].listing_line_start
992         + line_info_table[1].dst_line_num);
993   line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
994   pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
995
996   totsize += write_debug_header (&line_num.dst_a_line_num_header,
997                                  "line_num", dosizeonly);
998   totsize += write_debug_data1 (pcline.dst_b_pcline_command,
999                                 "line_num (SET LINUM LONG)", dosizeonly);
1000
1001   sprintf (buff, "line_num (%d)", ln - 1);
1002   totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1003
1004   lastln = ln;
1005   strcpy (lastlabel, TEXT_SECTION_ASM_OP);
1006   for (i = 1; i < line_info_table_in_use; i++)
1007     {
1008       int extrabytes;
1009
1010       fn = line_info_table[i].dst_file_num;
1011       ln = (file_info_table[fn].listing_line_start
1012             + line_info_table[i].dst_line_num);
1013
1014       if (ln - lastln > 1)
1015         extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
1016       else if (ln <= lastln)
1017         extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
1018       else
1019         extrabytes = 0;
1020
1021       line_num.dst_a_line_num_header.dst__header_length.dst_w_length
1022         = 8 + extrabytes;
1023
1024       totsize += write_debug_header
1025         (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
1026
1027       if (ln - lastln > 1)
1028         {
1029           int lndif = ln - lastln - 1;
1030
1031           /* K_INCR_LINUM (lndif); */
1032           pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
1033
1034           totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1035                                         "line_num (INCR LINUM LONG)",
1036                                         dosizeonly);
1037
1038           sprintf (buff, "line_num (%d)", lndif);
1039           totsize += write_debug_data4 (lndif, buff, dosizeonly);
1040         }
1041       else if (ln <= lastln)
1042         {
1043           /* K_SET_LINUM (ln-1); */
1044           pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
1045
1046           totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1047                                         "line_num (SET LINUM LONG)",
1048                                         dosizeonly);
1049
1050           sprintf (buff, "line_num (%d)", ln - 1);
1051           totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1052         }
1053
1054       pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
1055
1056       totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1057                                     "line_num (DELTA PC LONG)", dosizeonly);
1058
1059       ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1060       totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1061                                      dosizeonly);
1062
1063       lastln = ln;
1064       strcpy (lastlabel, label);
1065     }
1066
1067   return totsize;
1068 }
1069
1070 /* Output a source correlation for file FILEID using information saved in
1071    FILE_INFO_ENTRY and return the size.  Just return the size if DOSIZEONLY is
1072    non-zero.  */
1073
1074 static int
1075 write_srccorr (fileid, file_info_entry, dosizeonly)
1076      int fileid;
1077      dst_file_info_entry file_info_entry;
1078      int dosizeonly;
1079 {
1080   int src_command_size;
1081   int linesleft = file_info_entry.max_line;
1082   int linestart = file_info_entry.listing_line_start;
1083   int flen = file_info_entry.flen;
1084   int linestodo = 0;
1085   DST_SOURCE_CORR src_header;
1086   DST_SRC_COMMAND src_command;
1087   DST_SRC_COMMAND src_command_sf;
1088   DST_SRC_COMMAND src_command_sl;
1089   DST_SRC_COMMAND src_command_sr;
1090   DST_SRC_COMMAND src_command_dl;
1091   DST_SRC_CMDTRLR src_cmdtrlr;
1092   char buff[256];
1093   int totsize = 0;
1094
1095   if (fileid == 1)
1096     {
1097       src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1098         = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1099       src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1100         = DST_K_SOURCE;
1101       src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1102
1103       totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1104                                      "source corr", dosizeonly);
1105
1106       totsize += write_debug_data1 (src_command.dst_b_src_command,
1107                                     "source_corr (SRC FORMFEED)",
1108                                     dosizeonly);
1109     }
1110
1111   src_command_size
1112     = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1113   src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1114   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1115     = src_command_size - 2;
1116   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1117   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1118     = fileid;
1119   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1120     = file_info_entry.cdt;
1121   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1122     = file_info_entry.ebk;
1123   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1124     = file_info_entry.ffb;
1125   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1126     = file_info_entry.rfo;
1127   src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1128     = file_info_entry.flen;
1129
1130   src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1131     = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1132   src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1133     = DST_K_SOURCE;
1134
1135   src_cmdtrlr.dst_b_src_df_libmodname = 0;
1136
1137   totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1138                                  "source corr", dosizeonly);
1139   totsize += write_debug_data1 (src_command.dst_b_src_command,
1140                                 "source_corr (DECL SRC FILE)", dosizeonly);
1141   totsize += write_debug_data1
1142     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1143      "source_corr (length)", dosizeonly);
1144
1145   totsize += write_debug_data1
1146     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1147      "source_corr (flags)", dosizeonly);
1148
1149   totsize += write_debug_data2
1150     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1151      "source_corr (fileid)", dosizeonly);
1152
1153   totsize += write_debug_data8
1154     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1155      "source_corr (creation date)", dosizeonly);
1156
1157   totsize += write_debug_data4
1158     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1159      "source_corr (EOF block number)", dosizeonly);
1160
1161   totsize += write_debug_data2
1162     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1163      "source_corr (first free byte)", dosizeonly);
1164
1165   totsize += write_debug_data1
1166     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1167      "source_corr (record and file organization)", dosizeonly);
1168
1169   totsize += write_debug_data1
1170     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1171      "source_corr (filename length)", dosizeonly);
1172
1173   totsize += write_debug_string (file_info_entry.file_name,
1174                                  "source file name", dosizeonly);
1175   totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1176                                 "source_corr (libmodname)", dosizeonly);
1177
1178   src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1179   src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1180
1181   src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1182   src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1183
1184   src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1185   src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1186
1187   src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1188
1189   if (linesleft > 65534)
1190     linesleft = linesleft - 65534, linestodo = 65534;
1191   else
1192     linestodo = linesleft, linesleft = 0;
1193
1194   src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1195
1196   src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1197     = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1198   src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1199     = DST_K_SOURCE;
1200
1201   totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1202                                  "source corr", dosizeonly);
1203
1204   totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1205                                 "source_corr (src setfile)", dosizeonly);
1206
1207   totsize += write_debug_data2
1208     (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1209      "source_corr (fileid)", dosizeonly);
1210
1211   totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1212                                 "source_corr (setrec)", dosizeonly);
1213
1214   totsize += write_debug_data2
1215     (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1216      "source_corr (recnum)", dosizeonly);
1217
1218   totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1219                                 "source_corr (setlnum)", dosizeonly);
1220
1221   totsize += write_debug_data4
1222     (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1223      "source_corr (linenum)", dosizeonly);
1224
1225   totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1226                                 "source_corr (deflines)", dosizeonly);
1227
1228   sprintf (buff, "source_corr (%d)",
1229            src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1230   totsize += write_debug_data2
1231     (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly);
1232
1233   while (linesleft > 0)
1234     {
1235       src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1236         = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1237       src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1238         = DST_K_SOURCE;
1239       src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1240
1241       if (linesleft > 65534)
1242         linesleft = linesleft - 65534, linestodo = 65534;
1243       else
1244         linestodo = linesleft, linesleft = 0;
1245
1246       src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1247
1248       totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1249                                      "source corr", dosizeonly);
1250       totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1251                                     "source_corr (deflines)", dosizeonly);
1252       sprintf (buff, "source_corr (%d)",
1253                src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1254       totsize += write_debug_data2
1255         (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1256          buff, dosizeonly);
1257     }
1258
1259   return totsize;
1260 }
1261
1262 /* Output all the source correlation entries and return the size.  Just return
1263    the size if DOSIZEONLY is non-zero.  */
1264
1265 static int
1266 write_srccorrs (dosizeonly)
1267      int dosizeonly;
1268 {
1269   unsigned int i;
1270   int totsize = 0;
1271
1272   for (i = 1; i < file_info_table_in_use; i++)
1273     totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1274
1275   return totsize;
1276 }
1277 \f
1278 /* Output a marker (i.e. a label) for the beginning of a function, before
1279    the prologue.  */
1280
1281 static void
1282 vmsdbgout_begin_prologue (line, file)
1283      unsigned int line;
1284      const char *file;
1285 {
1286   char label[MAX_ARTIFICIAL_LABEL_BYTES];
1287
1288   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1289     (*dwarf2_debug_hooks.begin_prologue) (line, file);
1290
1291   if (debug_info_level > DINFO_LEVEL_NONE)
1292     {
1293       current_funcdef_number++;
1294       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1295                                    current_funcdef_number);
1296       ASM_OUTPUT_LABEL (asm_out_file, label);
1297     }
1298 }
1299
1300 /* Output a marker (i.e. a label) for the beginning of a function, after
1301    the prologue.  */
1302
1303 void
1304 vmsdbgout_after_prologue ()
1305 {
1306   char label[MAX_ARTIFICIAL_LABEL_BYTES];
1307
1308   if (debug_info_level > DINFO_LEVEL_TERSE)
1309     {
1310       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1311                                    current_funcdef_number);
1312       ASM_OUTPUT_LABEL (asm_out_file, label);
1313     }
1314 }
1315
1316 /* Output a marker (i.e. a label) for the absolute end of the generated code
1317    for a function definition.  This gets called *after* the epilogue code has
1318    been generated.  */
1319
1320 static void
1321 vmsdbgout_end_epilogue ()
1322 {
1323   char label[MAX_ARTIFICIAL_LABEL_BYTES];
1324
1325   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1326     (*dwarf2_debug_hooks.end_epilogue) ();
1327
1328   if (debug_info_level > DINFO_LEVEL_NONE)
1329     {
1330       /* Output a label to mark the endpoint of the code generated for this
1331          function.  */
1332       ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1333                                    current_funcdef_number);
1334       ASM_OUTPUT_LABEL (asm_out_file, label);
1335     }
1336 }
1337
1338 /* Output a marker (i.e. a label) for the beginning of the generated code for
1339    a lexical block.  */
1340
1341 static void
1342 vmsdbgout_begin_block (line, blocknum)
1343      register unsigned line;
1344      register unsigned blocknum;
1345 {
1346   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1347     (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1348
1349   if (debug_info_level > DINFO_LEVEL_TERSE)
1350     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1351 }
1352
1353 /* Output a marker (i.e. a label) for the end of the generated code for a
1354    lexical block.  */
1355
1356 static void
1357 vmsdbgout_end_block (line, blocknum)
1358      register unsigned line;
1359      register unsigned blocknum;
1360 {
1361   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1362     (*dwarf2_debug_hooks.end_block) (line, blocknum);
1363
1364   if (debug_info_level > DINFO_LEVEL_TERSE)
1365     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum);
1366 }
1367
1368 /* Not implemented in VMS Debug.  */
1369
1370 static bool
1371 vmsdbgout_ignore_block (block)
1372      tree block;
1373 {
1374   bool retval = 0;
1375
1376   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1377     retval = (*dwarf2_debug_hooks.ignore_block) (block);
1378
1379   return retval;
1380 }
1381
1382 /* Add an entry for function DECL into the func_table.  */
1383
1384 static void
1385 vmsdbgout_begin_function (decl)
1386      tree decl;
1387 {
1388   const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1389
1390   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1391     (*dwarf2_debug_hooks.begin_function) (decl);
1392
1393   if (func_table_in_use == func_table_allocated)
1394     {
1395       func_table_allocated += FUNC_TABLE_INCREMENT;
1396       func_table = (char **) xrealloc (func_table,
1397                                        func_table_allocated * sizeof (char *));
1398     }
1399
1400   /* Add the new entry to the end of the function name table.  */
1401   func_table[func_table_in_use++] = xstrdup (name);
1402 }
1403
1404 static char fullname_buff [4096];
1405
1406 /* Return the full file specification for FILENAME.  The specification must be
1407    in VMS syntax in order to be processed by VMS Debug.  */
1408
1409 static char *
1410 full_name (filename)
1411      const char *filename;
1412 {
1413 #ifdef VMS
1414   FILE *fp = fopen (filename, "r");
1415
1416   fgetname (fp, fullname_buff, 1);
1417   fclose (fp);
1418 #else
1419   getcwd (fullname_buff, sizeof (fullname_buff));
1420
1421   strcat (fullname_buff, "/");
1422   strcat (fullname_buff, filename);
1423
1424   /* ??? Insert hairy code here to translate Unix style file specification
1425      to VMS style.  */
1426 #endif
1427
1428   return fullname_buff;
1429 }
1430
1431 /* Lookup a filename (in the list of filenames that we know about here in
1432    vmsdbgout.c) and return its "index".  The index of each (known) filename is
1433    just a unique number which is associated with only that one filename.  We
1434    need such numbers for the sake of generating labels  and references
1435    to those files numbers.  If the filename given as an argument is not
1436    found in our current list, add it to the list and assign it the next
1437    available unique index number.  In order to speed up searches, we remember
1438    the index of the filename was looked up last.  This handles the majority of
1439    all searches.  */
1440
1441 static unsigned int
1442 lookup_filename (file_name)
1443      const char *file_name;
1444 {
1445   static unsigned int last_file_lookup_index = 0;
1446   register char *fn;
1447   register unsigned i;
1448   char *fnam;
1449   long long cdt;
1450   long ebk;
1451   short ffb;
1452   char rfo;
1453   char flen;
1454   struct stat statbuf;
1455
1456   if (stat (file_name, &statbuf) == 0)
1457     {
1458       long gmtoff;
1459 #ifdef VMS
1460       struct tm *ts;
1461
1462       /* Adjust for GMT */
1463       ts = (struct tm *) localtime (&statbuf.st_ctime);
1464       gmtoff = ts->tm_gmtoff;
1465
1466       /* VMS has multiple file format types */
1467       rfo = statbuf.st_fab_rfm;
1468 #else
1469       /* Is GMT adjustment an issue with a cross-compiler? */
1470       gmtoff = 0;
1471
1472       /* Assume stream LF type file */
1473       rfo = 2;
1474 #endif
1475       cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset);
1476       ebk = statbuf.st_size / 512 + 1;
1477       ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512);
1478       fnam = full_name (file_name);
1479       flen = strlen (fnam);
1480     }
1481   else
1482     {
1483       cdt = 0;
1484       ebk = 0;
1485       ffb = 0;
1486       rfo = 0;
1487       fnam = (char *) "";
1488       flen = 0;
1489     }
1490
1491   /* Check to see if the file name that was searched on the previous call
1492      matches this file name. If so, return the index.  */
1493   if (last_file_lookup_index != 0)
1494     {
1495       fn = file_info_table[last_file_lookup_index].file_name;
1496       if (strcmp (fnam, fn) == 0)
1497         return last_file_lookup_index;
1498     }
1499
1500   /* Didn't match the previous lookup, search the table */
1501   for (i = 1; i < file_info_table_in_use; ++i)
1502     {
1503       fn = file_info_table[i].file_name;
1504       if (strcmp (fnam, fn) == 0)
1505         {
1506           last_file_lookup_index = i;
1507           return i;
1508         }
1509     }
1510
1511   /* Prepare to add a new table entry by making sure there is enough space in
1512      the table to do so.  If not, expand the current table.  */
1513   if (file_info_table_in_use == file_info_table_allocated)
1514     {
1515
1516       file_info_table_allocated += FILE_TABLE_INCREMENT;
1517       file_info_table
1518         = (dst_file_info_ref) xrealloc (file_info_table,
1519                                         (file_info_table_allocated
1520                                          * sizeof (dst_file_info_entry)));
1521     }
1522
1523   /* Add the new entry to the end of the filename table.  */
1524   file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1525   file_info_table[file_info_table_in_use].max_line = 0;
1526   file_info_table[file_info_table_in_use].cdt = cdt;
1527   file_info_table[file_info_table_in_use].ebk = ebk;
1528   file_info_table[file_info_table_in_use].ffb = ffb;
1529   file_info_table[file_info_table_in_use].rfo = rfo;
1530   file_info_table[file_info_table_in_use].flen = flen;
1531
1532   last_file_lookup_index = file_info_table_in_use++;
1533   return last_file_lookup_index;
1534 }
1535
1536 /* Output a label to mark the beginning of a source code line entry
1537    and record information relating to this source line, in
1538    'line_info_table' for later output of the .debug_line section.  */
1539
1540 static void
1541 vmsdbgout_source_line (line, filename)
1542      register unsigned line;
1543      register const char *filename;
1544 {
1545   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1546     (*dwarf2_debug_hooks.source_line) (line, filename);
1547
1548   if (debug_info_level >= DINFO_LEVEL_TERSE)
1549     {
1550       dst_line_info_ref line_info;
1551
1552       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL,
1553                                  line_info_table_in_use);
1554
1555       /* Expand the line info table if necessary.  */
1556       if (line_info_table_in_use == line_info_table_allocated)
1557         {
1558           line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1559           line_info_table
1560             = (dst_line_info_ref) xrealloc (line_info_table,
1561                                             (line_info_table_allocated
1562                                              * sizeof (dst_line_info_entry)));
1563         }
1564
1565       /* Add the new entry at the end of the line_info_table.  */
1566       line_info = &line_info_table[line_info_table_in_use++];
1567       line_info->dst_file_num = lookup_filename (filename);
1568       line_info->dst_line_num = line;
1569       if (line > file_info_table[line_info->dst_file_num].max_line)
1570         file_info_table[line_info->dst_file_num].max_line = line;
1571     }
1572 }
1573
1574 /* Record the beginning of a new source file, for later output.
1575    At present, unimplemented.  */
1576
1577 static void
1578 vmsdbgout_start_source_file (lineno, filename)
1579      unsigned int lineno;
1580      const char *filename;
1581 {
1582   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1583     (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1584 }
1585
1586 /* Record the end of a source file, for later output.
1587    At present, unimplemented.  */
1588
1589 static void
1590 vmsdbgout_end_source_file (lineno)
1591      unsigned int lineno ATTRIBUTE_UNUSED;
1592 {
1593   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1594     (*dwarf2_debug_hooks.end_source_file) (lineno);
1595 }
1596
1597 /* Set up for Debug output at the start of compilation.  */
1598
1599 static void
1600 vmsdbgout_init (main_input_filename)
1601      const char *main_input_filename;
1602 {
1603   const char *language_string = lang_hooks.name;
1604
1605   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1606     (*dwarf2_debug_hooks.init) (main_input_filename);
1607
1608   if (debug_info_level == DINFO_LEVEL_NONE)
1609     return;
1610
1611   /* Remember the name of the primary input file.  */
1612   primary_filename = main_input_filename;
1613
1614   /* Allocate the initial hunk of the file_info_table.  */
1615   file_info_table
1616     = (dst_file_info_ref) xcalloc (FILE_TABLE_INCREMENT,
1617                                    sizeof (dst_file_info_entry));
1618   file_info_table_allocated = FILE_TABLE_INCREMENT;
1619
1620   /* Skip the first entry - file numbers begin at 1 */
1621   file_info_table_in_use = 1;
1622
1623   func_table = (char **) xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *));
1624   func_table_allocated = FUNC_TABLE_INCREMENT;
1625   func_table_in_use = 1;
1626
1627   /* Allocate the initial hunk of the line_info_table.  */
1628   line_info_table
1629     = (dst_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT,
1630                                    sizeof (dst_line_info_entry));
1631   line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1632   /* zero-th entry is allocated, but unused */
1633   line_info_table_in_use = 1;
1634
1635   lookup_filename (primary_filename);
1636
1637   if (!strcmp (language_string, "GNU C"))
1638     module_language = DST_K_C;
1639   else if (!strcmp (language_string, "GNU C++"))
1640     module_language = DST_K_CXX;
1641   else if (!strcmp (language_string, "GNU Ada"))
1642     module_language = DST_K_ADA;
1643   else if (!strcmp (language_string, "GNU F77"))
1644     module_language = DST_K_FORTRAN;
1645   else
1646     module_language = DST_K_UNKNOWN;
1647
1648   module_producer
1649     = (char *) xmalloc (strlen (language_string) + 1
1650                         + strlen (version_string) + 1);
1651   sprintf (module_producer, "%s %s", language_string, version_string);
1652
1653   ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1654
1655 }
1656
1657 /* Not implemented in VMS Debug.  */
1658
1659 static void
1660 vmsdbgout_define (lineno, buffer)
1661      unsigned int lineno;
1662      const char *buffer;
1663 {
1664   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1665     (*dwarf2_debug_hooks.define) (lineno, buffer);
1666 }
1667
1668 /* Not implemented in VMS Debug.  */
1669
1670 static void
1671 vmsdbgout_undef (lineno, buffer)
1672      unsigned int lineno;
1673      const char *buffer;
1674 {
1675   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1676     (*dwarf2_debug_hooks.undef) (lineno, buffer);
1677 }
1678
1679 /* Not implemented in VMS Debug.  */
1680
1681 static void
1682 vmsdbgout_decl (decl)
1683      tree decl;
1684 {
1685   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1686     (*dwarf2_debug_hooks.function_decl) (decl);
1687 }
1688
1689 /* Not implemented in VMS Debug.  */
1690
1691 static void
1692 vmsdbgout_global_decl (decl)
1693      tree decl;
1694 {
1695   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1696     (*dwarf2_debug_hooks.global_decl) (decl);
1697 }
1698
1699 /* Not implemented in VMS Debug.  */
1700
1701 static void
1702 vmsdbgout_abstract_function (decl)
1703      tree decl;
1704 {
1705   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1706     (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1707 }
1708
1709 /* Output stuff that Debug requires at the end of every file and generate the
1710    VMS Debug debugging info.  */
1711
1712 static void
1713 vmsdbgout_finish (input_filename)
1714      const char *input_filename ATTRIBUTE_UNUSED;
1715 {
1716   unsigned int i;
1717   int totsize;
1718
1719   if (write_symbols == VMS_AND_DWARF2_DEBUG)
1720     (*dwarf2_debug_hooks.finish) (input_filename);
1721
1722   if (debug_info_level == DINFO_LEVEL_NONE)
1723     return;
1724
1725   /* Output a terminator label for the .text section.  */
1726   text_section ();
1727   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0);
1728
1729   /* Output debugging information.
1730      Warning! Do not change the name of the .vmsdebug section without
1731      changing it in the assembler also.  */
1732   named_section (NULL_TREE, ".vmsdebug", 0);
1733   ASM_OUTPUT_ALIGN (asm_out_file, 0);
1734
1735   totsize = write_modbeg (1);
1736   for (i = 1; i < func_table_in_use; i++)
1737     {
1738       totsize += write_rtnbeg (i, 1);
1739       totsize += write_rtnend (i, 1);
1740     }
1741   totsize += write_pclines (1);
1742
1743   write_modbeg (0);
1744   for (i = 1; i < func_table_in_use; i++)
1745     {
1746       write_rtnbeg (i, 0);
1747       write_rtnend (i, 0);
1748     }
1749   write_pclines (0);
1750
1751   if (debug_info_level > DINFO_LEVEL_TERSE)
1752     {
1753       totsize = write_srccorrs (1);
1754       write_srccorrs (0);
1755     }
1756
1757   totsize = write_modend (1);
1758   write_modend (0);
1759 }
1760 #endif /* VMS_DEBUGGING_INFO */