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