OSDN Git Service

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