s390.c (s390_function_value): Rename to ...
[gcc.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 *filename)
1458 {
1459 const char *language_string = lang_hooks.name;
1460
1461 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1462 (*dwarf2_debug_hooks.init) (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 = 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 *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) (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