OSDN Git Service

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