OSDN Git Service

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