fold-const.c (maybe_lvalue_p): Return false for M(IN|AX)_EXPR.
[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
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 /* A structure to hold basic information for the VMS end
110 routine. */
111
112 typedef struct vms_func_struct
113 {
114 const char *vms_func_name;
115 unsigned funcdef_number;
116 }
117 vms_func_node;
118
119 typedef struct vms_func_struct *vms_func_ref;
120
121 static unsigned int func_table_allocated;
122 static unsigned int func_table_in_use;
123 #define FUNC_TABLE_INCREMENT 256
124
125 /* A pointer to the base of a table that contains frame description
126 information for each routine. */
127 static vms_func_ref func_table;
128
129 /* Local pointer to the name of the main input file. Initialized in
130 vmsdbgout_init. */
131 static const char *primary_filename;
132
133 static char *module_producer;
134 static unsigned int module_language;
135
136 /* A pointer to the base of a table that contains line information
137 for each source code line in .text in the compilation unit. */
138 static dst_line_info_ref line_info_table;
139
140 /* Number of elements currently allocated for line_info_table. */
141 static unsigned int line_info_table_allocated;
142
143 /* Number of elements in line_info_table currently in use. */
144 static unsigned int line_info_table_in_use;
145
146 /* Size (in elements) of increments by which we may expand line_info_table. */
147 #define LINE_INFO_TABLE_INCREMENT 1024
148
149 /* Forward declarations for functions defined in this file. */
150 static char *full_name (const char *);
151 static unsigned int lookup_filename (const char *);
152 static void addr_const_to_string (char *, rtx);
153 static int write_debug_header (DST_HEADER *, const char *, int);
154 static int write_debug_addr (const char *, const char *, int);
155 static int write_debug_data1 (unsigned int, const char *, int);
156 static int write_debug_data2 (unsigned int, const char *, int);
157 static int write_debug_data4 (unsigned long, const char *, int);
158 static int write_debug_data8 (unsigned long long, const char *, int);
159 static int write_debug_delta4 (const char *, const char *, const char *, int);
160 static int write_debug_string (const char *, const char *, int);
161 static int write_modbeg (int);
162 static int write_modend (int);
163 static int write_rtnbeg (int, int);
164 static int write_rtnend (int, int);
165 static int write_pclines (int);
166 static int write_srccorr (int, dst_file_info_entry, int);
167 static int write_srccorrs (int);
168
169 static void vmsdbgout_init (const char *);
170 static void vmsdbgout_finish (const char *);
171 static void vmsdbgout_define (unsigned int, const char *);
172 static void vmsdbgout_undef (unsigned int, const char *);
173 static void vmsdbgout_start_source_file (unsigned int, const char *);
174 static void vmsdbgout_end_source_file (unsigned int);
175 static void vmsdbgout_begin_block (unsigned int, unsigned int);
176 static void vmsdbgout_end_block (unsigned int, unsigned int);
177 static bool vmsdbgout_ignore_block (const_tree);
178 static void vmsdbgout_source_line (unsigned int, const char *, int, bool);
179 static void vmsdbgout_begin_prologue (unsigned int, const char *);
180 static void vmsdbgout_end_prologue (unsigned int, const char *);
181 static void vmsdbgout_end_function (unsigned int);
182 static void vmsdbgout_end_epilogue (unsigned int, const char *);
183 static void vmsdbgout_begin_function (tree);
184 static void vmsdbgout_decl (tree);
185 static void vmsdbgout_global_decl (tree);
186 static void vmsdbgout_abstract_function (tree);
187
188 /* The debug hooks structure. */
189
190 const struct gcc_debug_hooks vmsdbg_debug_hooks
191 = {vmsdbgout_init,
192 vmsdbgout_finish,
193 vmsdbgout_define,
194 vmsdbgout_undef,
195 vmsdbgout_start_source_file,
196 vmsdbgout_end_source_file,
197 vmsdbgout_begin_block,
198 vmsdbgout_end_block,
199 vmsdbgout_ignore_block,
200 vmsdbgout_source_line,
201 vmsdbgout_begin_prologue,
202 vmsdbgout_end_prologue,
203 vmsdbgout_end_epilogue,
204 vmsdbgout_begin_function,
205 vmsdbgout_end_function,
206 vmsdbgout_decl,
207 vmsdbgout_global_decl,
208 debug_nothing_tree_int, /* type_decl */
209 debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */
210 debug_nothing_tree, /* deferred_inline_function */
211 vmsdbgout_abstract_function,
212 debug_nothing_rtx, /* label */
213 debug_nothing_int, /* handle_pch */
214 debug_nothing_rtx, /* var_location */
215 debug_nothing_void, /* switch_text_section */
216 debug_nothing_tree_tree, /* set_name */
217 0 /* start_end_main_source_file */
218 };
219
220 /* Definitions of defaults for assembler-dependent names of various
221 pseudo-ops and section names.
222 Theses may be overridden in the tm.h file (if necessary) for a particular
223 assembler. */
224 #ifdef UNALIGNED_SHORT_ASM_OP
225 #undef UNALIGNED_SHORT_ASM_OP
226 #endif
227 #define UNALIGNED_SHORT_ASM_OP ".word"
228
229 #ifdef UNALIGNED_INT_ASM_OP
230 #undef UNALIGNED_INT_ASM_OP
231 #endif
232 #define UNALIGNED_INT_ASM_OP ".long"
233
234 #ifdef UNALIGNED_LONG_ASM_OP
235 #undef UNALIGNED_LONG_ASM_OP
236 #endif
237 #define UNALIGNED_LONG_ASM_OP ".long"
238
239 #ifdef UNALIGNED_DOUBLE_INT_ASM_OP
240 #undef UNALIGNED_DOUBLE_INT_ASM_OP
241 #endif
242 #define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
243
244 #ifdef ASM_BYTE_OP
245 #undef ASM_BYTE_OP
246 #endif
247 #define ASM_BYTE_OP ".byte"
248
249 #define NUMBYTES(I) ((I) < 256 ? 1 : (I) < 65536 ? 2 : 4)
250
251 #define NUMBYTES0(I) ((I) < 128 ? 0 : (I) < 65536 ? 2 : 4)
252
253 #ifndef UNALIGNED_PTR_ASM_OP
254 #define UNALIGNED_PTR_ASM_OP \
255 (PTR_SIZE == 8 ? UNALIGNED_DOUBLE_INT_ASM_OP : UNALIGNED_INT_ASM_OP)
256 #endif
257
258 #ifndef UNALIGNED_OFFSET_ASM_OP
259 #define UNALIGNED_OFFSET_ASM_OP(OFFSET) \
260 (NUMBYTES(OFFSET) == 4 \
261 ? UNALIGNED_LONG_ASM_OP \
262 : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP))
263 #endif
264
265 /* Definitions of defaults for formats and names of various special
266 (artificial) labels which may be generated within this file (when the -g
267 options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these
268 may be overridden from within the tm.h file, but typically, overriding these
269 defaults is unnecessary. */
270
271 static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
272
273 #ifndef TEXT_END_LABEL
274 #define TEXT_END_LABEL "Lvetext"
275 #endif
276 #ifndef FUNC_BEGIN_LABEL
277 #define FUNC_BEGIN_LABEL "LVFB"
278 #endif
279 #ifndef FUNC_PROLOG_LABEL
280 #define FUNC_PROLOG_LABEL "LVFP"
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\t0x%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\t0x%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\t0x%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\t0x%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\t0x%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\t0x%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 /* General utility functions. */
422
423 /* Convert an integer constant expression into assembler syntax. Addition and
424 subtraction are the only arithmetic that may appear in these expressions.
425 This is an adaptation of output_addr_const in final.c. Here, the target
426 of the conversion is a string buffer. We can't use output_addr_const
427 directly, because it writes to a file. */
428
429 static void
430 addr_const_to_string (char *str, rtx x)
431 {
432 char buf1[256];
433 char buf2[256];
434
435 restart:
436 str[0] = '\0';
437 switch (GET_CODE (x))
438 {
439 case PC:
440 gcc_assert (flag_pic);
441 strcat (str, ",");
442 break;
443
444 case SYMBOL_REF:
445 ASM_NAME_TO_STRING (buf1, XSTR (x, 0));
446 strcat (str, buf1);
447 break;
448
449 case LABEL_REF:
450 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
451 ASM_NAME_TO_STRING (buf2, buf1);
452 strcat (str, buf2);
453 break;
454
455 case CODE_LABEL:
456 ASM_GENERATE_INTERNAL_LABEL (buf1, "L", CODE_LABEL_NUMBER (x));
457 ASM_NAME_TO_STRING (buf2, buf1);
458 strcat (str, buf2);
459 break;
460
461 case CONST_INT:
462 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
463 strcat (str, buf1);
464 break;
465
466 case CONST:
467 /* This used to output parentheses around the expression, but that does
468 not work on the 386 (either ATT or BSD assembler). */
469 addr_const_to_string (buf1, XEXP (x, 0));
470 strcat (str, buf1);
471 break;
472
473 case CONST_DOUBLE:
474 if (GET_MODE (x) == VOIDmode)
475 {
476 /* We can use %d if the number is one word and positive. */
477 if (CONST_DOUBLE_HIGH (x))
478 sprintf (buf1, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
479 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
480 else if (CONST_DOUBLE_LOW (x) < 0)
481 sprintf (buf1, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
482 else
483 sprintf (buf1, HOST_WIDE_INT_PRINT_DEC,
484 CONST_DOUBLE_LOW (x));
485 strcat (str, buf1);
486 }
487 else
488 /* We can't handle floating point constants; PRINT_OPERAND must
489 handle them. */
490 output_operand_lossage ("floating constant misused");
491 break;
492
493 case PLUS:
494 /* Some assemblers need integer constants to appear last (eg masm). */
495 if (CONST_INT_P (XEXP (x, 0)))
496 {
497 addr_const_to_string (buf1, XEXP (x, 1));
498 strcat (str, buf1);
499 if (INTVAL (XEXP (x, 0)) >= 0)
500 strcat (str, "+");
501 addr_const_to_string (buf1, XEXP (x, 0));
502 strcat (str, buf1);
503 }
504 else
505 {
506 addr_const_to_string (buf1, XEXP (x, 0));
507 strcat (str, buf1);
508 if (INTVAL (XEXP (x, 1)) >= 0)
509 strcat (str, "+");
510 addr_const_to_string (buf1, XEXP (x, 1));
511 strcat (str, buf1);
512 }
513 break;
514
515 case MINUS:
516 /* Avoid outputting things like x-x or x+5-x, since some assemblers
517 can't handle that. */
518 x = simplify_subtraction (x);
519 if (GET_CODE (x) != MINUS)
520 goto restart;
521
522 addr_const_to_string (buf1, XEXP (x, 0));
523 strcat (str, buf1);
524 strcat (str, "-");
525 if (CONST_INT_P (XEXP (x, 1))
526 && INTVAL (XEXP (x, 1)) < 0)
527 {
528 strcat (str, "(");
529 addr_const_to_string (buf1, XEXP (x, 1));
530 strcat (str, buf1);
531 strcat (str, ")");
532 }
533 else
534 {
535 addr_const_to_string (buf1, XEXP (x, 1));
536 strcat (str, buf1);
537 }
538 break;
539
540 case ZERO_EXTEND:
541 case SIGN_EXTEND:
542 addr_const_to_string (buf1, XEXP (x, 0));
543 strcat (str, buf1);
544 break;
545
546 default:
547 output_operand_lossage ("invalid expression as operand");
548 }
549 }
550
551 /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is
552 set. Return the header size. Just return the size if DOSIZEONLY is
553 nonzero. */
554
555 static int
556 write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly)
557 {
558 if (!dosizeonly)
559 {
560 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
561 header->dst__header_length.dst_w_length);
562
563 if (flag_verbose_asm)
564 fprintf (asm_out_file, "\t%s record length", ASM_COMMENT_START);
565 fputc ('\n', asm_out_file);
566
567 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file,
568 header->dst__header_type.dst_w_type);
569
570 if (flag_verbose_asm)
571 fprintf (asm_out_file, "\t%s record type (%s)", ASM_COMMENT_START,
572 comment);
573
574 fputc ('\n', asm_out_file);
575 }
576
577 return 4;
578 }
579
580 /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is
581 set. Return the address size. Just return the size if DOSIZEONLY is
582 nonzero. */
583
584 static int
585 write_debug_addr (const char *symbol, const char *comment, int dosizeonly)
586 {
587 if (!dosizeonly)
588 {
589 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, symbol);
590 if (flag_verbose_asm)
591 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
592 fputc ('\n', asm_out_file);
593 }
594
595 return PTR_SIZE;
596 }
597
598 /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is
599 set. Return the data size. Just return the size if DOSIZEONLY is
600 nonzero. */
601
602 static int
603 write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly)
604 {
605 if (!dosizeonly)
606 {
607 ASM_OUTPUT_DEBUG_DATA1 (asm_out_file, data1);
608 if (flag_verbose_asm)
609 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
610 fputc ('\n', asm_out_file);
611 }
612
613 return 1;
614 }
615
616 /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is
617 set. Return the data size. Just return the size if DOSIZEONLY is
618 nonzero. */
619
620 static int
621 write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly)
622 {
623 if (!dosizeonly)
624 {
625 ASM_OUTPUT_DEBUG_DATA2 (asm_out_file, data2);
626 if (flag_verbose_asm)
627 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
628 fputc ('\n', asm_out_file);
629 }
630
631 return 2;
632 }
633
634 /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set.
635 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
636
637 static int
638 write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly)
639 {
640 if (!dosizeonly)
641 {
642 ASM_OUTPUT_DEBUG_DATA4 (asm_out_file, data4);
643 if (flag_verbose_asm)
644 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
645 fputc ('\n', asm_out_file);
646 }
647
648 return 4;
649 }
650
651 /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set.
652 Return the data size. Just return the size if DOSIZEONLY is nonzero. */
653
654 static int
655 write_debug_data8 (unsigned long long data8, const char *comment,
656 int dosizeonly)
657 {
658 if (!dosizeonly)
659 {
660 ASM_OUTPUT_DEBUG_DATA8 (asm_out_file, data8);
661 if (flag_verbose_asm)
662 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
663 fputc ('\n', asm_out_file);
664 }
665
666 return 8;
667 }
668
669 /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if
670 flag_verbose_asm is set. Return the data size. Just return the size if
671 DOSIZEONLY is nonzero. */
672
673 static int
674 write_debug_delta4 (const char *label1, const char *label2,
675 const char *comment, int dosizeonly)
676 {
677 if (!dosizeonly)
678 {
679 ASM_OUTPUT_DEBUG_DELTA4 (asm_out_file, label1, label2);
680 if (flag_verbose_asm)
681 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
682 fputc ('\n', asm_out_file);
683 }
684
685 return 4;
686 }
687
688 /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is
689 set. Return the string length. Just return the length if DOSIZEONLY is
690 nonzero. */
691
692 static int
693 write_debug_string (const char *string, const char *comment, int dosizeonly)
694 {
695 if (!dosizeonly)
696 {
697 ASM_OUTPUT_DEBUG_STRING (asm_out_file, string);
698 if (flag_verbose_asm)
699 fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment);
700 fputc ('\n', asm_out_file);
701 }
702
703 return strlen (string);
704 }
705
706 /* Output a module begin header and return the header size. Just return the
707 size if DOSIZEONLY is nonzero. */
708
709 static int
710 write_modbeg (int dosizeonly)
711 {
712 DST_MODULE_BEGIN modbeg;
713 DST_MB_TRLR mb_trlr;
714 int i;
715 char *module_name, *m;
716 int modnamelen;
717 int prodnamelen;
718 int totsize = 0;
719
720 /* Assumes primary filename has Unix syntax file spec. */
721 module_name = xstrdup (lbasename (primary_filename));
722
723 m = strrchr (module_name, '.');
724 if (m)
725 *m = 0;
726
727 modnamelen = strlen (module_name);
728 for (i = 0; i < modnamelen; i++)
729 module_name[i] = TOUPPER (module_name[i]);
730
731 prodnamelen = strlen (module_producer);
732
733 modbeg.dst_a_modbeg_header.dst__header_length.dst_w_length
734 = DST_K_MODBEG_SIZE + modnamelen + DST_K_MB_TRLR_SIZE + prodnamelen - 1;
735 modbeg.dst_a_modbeg_header.dst__header_type.dst_w_type = DST_K_MODBEG;
736 modbeg.dst_b_modbeg_flags.dst_v_modbeg_hide = 0;
737 modbeg.dst_b_modbeg_flags.dst_v_modbeg_version = 1;
738 modbeg.dst_b_modbeg_flags.dst_v_modbeg_unused = 0;
739 modbeg.dst_b_modbeg_unused = 0;
740 modbeg.dst_l_modbeg_language = module_language;
741 modbeg.dst_w_version_major = DST_K_VERSION_MAJOR;
742 modbeg.dst_w_version_minor = DST_K_VERSION_MINOR;
743 modbeg.dst_b_modbeg_name = strlen (module_name);
744
745 mb_trlr.dst_b_compiler = strlen (module_producer);
746
747 totsize += write_debug_header (&modbeg.dst_a_modbeg_header,
748 "modbeg", dosizeonly);
749 totsize += write_debug_data1 (*((char *) &modbeg.dst_b_modbeg_flags),
750 "flags", dosizeonly);
751 totsize += write_debug_data1 (modbeg.dst_b_modbeg_unused,
752 "unused", dosizeonly);
753 totsize += write_debug_data4 (modbeg.dst_l_modbeg_language,
754 "language", dosizeonly);
755 totsize += write_debug_data2 (modbeg.dst_w_version_major,
756 "DST major version", dosizeonly);
757 totsize += write_debug_data2 (modbeg.dst_w_version_minor,
758 "DST minor version", dosizeonly);
759 totsize += write_debug_data1 (modbeg.dst_b_modbeg_name,
760 "length of module name", dosizeonly);
761 totsize += write_debug_string (module_name, "module name", dosizeonly);
762 totsize += write_debug_data1 (mb_trlr.dst_b_compiler,
763 "length of compiler name", dosizeonly);
764 totsize += write_debug_string (module_producer, "compiler name", dosizeonly);
765
766 return totsize;
767 }
768
769 /* Output a module end trailer and return the trailer size. Just return
770 the size if DOSIZEONLY is nonzero. */
771
772 static int
773 write_modend (int dosizeonly)
774 {
775 DST_MODULE_END modend;
776 int totsize = 0;
777
778 modend.dst_a_modend_header.dst__header_length.dst_w_length
779 = DST_K_MODEND_SIZE - 1;
780 modend.dst_a_modend_header.dst__header_type.dst_w_type = DST_K_MODEND;
781
782 totsize += write_debug_header (&modend.dst_a_modend_header, "modend",
783 dosizeonly);
784
785 return totsize;
786 }
787
788 /* Output a routine begin header routine RTNNUM and return the header size.
789 Just return the size if DOSIZEONLY is nonzero. */
790
791 static int
792 write_rtnbeg (int rtnnum, int dosizeonly)
793 {
794 const char *rtnname;
795 int rtnnamelen;
796 char *rtnentryname;
797 int totsize = 0;
798 char label[MAX_ARTIFICIAL_LABEL_BYTES];
799 DST_ROUTINE_BEGIN rtnbeg;
800 DST_PROLOG prolog;
801 vms_func_ref fde = &func_table[rtnnum];
802
803 rtnname = fde->vms_func_name;
804 rtnnamelen = strlen (rtnname);
805 rtnentryname = concat (rtnname, "..en", NULL);
806
807 if (!strcmp (rtnname, "main"))
808 {
809 DST_HEADER header;
810 const char *go = "TRANSFER$BREAK$GO";
811
812 /* This command isn't documented in DSTRECORDS, so it's made to
813 look like what DEC C does */
814
815 /* header size - 1st byte + flag byte + STO_LW size
816 + string count byte + string length */
817 header.dst__header_length.dst_w_length
818 = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go);
819 header.dst__header_type.dst_w_type = 0x17;
820
821 totsize += write_debug_header (&header, "transfer", dosizeonly);
822
823 /* I think this is a flag byte, but I don't know what this flag means */
824 totsize += write_debug_data1 (0x1, "flags ???", dosizeonly);
825
826 /* Routine Begin PD Address */
827 totsize += write_debug_addr (rtnname, "main procedure descriptor",
828 dosizeonly);
829 totsize += write_debug_data1 (strlen (go), "length of main_name",
830 dosizeonly);
831 totsize += write_debug_string (go, "main name", dosizeonly);
832 }
833
834 /* The header length never includes the length byte. */
835 rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length
836 = DST_K_RTNBEG_SIZE + rtnnamelen - 1;
837 rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG;
838 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unused = 0;
839 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_unalloc = 0;
840 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_prototype = 0;
841 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_inlined = 0;
842 rtnbeg.dst_b_rtnbeg_flags.dst_v_rtnbeg_no_call = 1;
843 rtnbeg.dst_b_rtnbeg_name = rtnnamelen;
844
845 totsize += write_debug_header (&rtnbeg.dst_a_rtnbeg_header, "rtnbeg",
846 dosizeonly);
847 totsize += write_debug_data1 (*((char *) &rtnbeg.dst_b_rtnbeg_flags),
848 "flags", dosizeonly);
849
850 /* Routine Begin Address */
851 totsize += write_debug_addr (rtnentryname, "routine entry name", dosizeonly);
852
853 /* Routine Begin PD Address */
854 totsize += write_debug_addr (rtnname, "routine procedure descriptor",
855 dosizeonly);
856
857 /* Routine Begin Name */
858 totsize += write_debug_data1 (rtnbeg.dst_b_rtnbeg_name,
859 "length of routine name", dosizeonly);
860
861 totsize += write_debug_string (rtnname, "routine name", dosizeonly);
862
863 free (rtnentryname);
864
865 if (debug_info_level > DINFO_LEVEL_TERSE)
866 {
867 prolog.dst_a_prolog_header.dst__header_length.dst_w_length
868 = DST_K_PROLOG_SIZE - 1;
869 prolog.dst_a_prolog_header.dst__header_type.dst_w_type = DST_K_PROLOG;
870
871 totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog",
872 dosizeonly);
873
874 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, fde->funcdef_number);
875 totsize += write_debug_addr (label, "prolog breakpoint addr",
876 dosizeonly);
877 }
878
879 return totsize;
880 }
881
882 /* Output a routine end trailer for routine RTNNUM and return the header size.
883 Just return the size if DOSIZEONLY is nonzero. */
884
885 static int
886 write_rtnend (int rtnnum, int dosizeonly)
887 {
888 DST_ROUTINE_END rtnend;
889 char label1[MAX_ARTIFICIAL_LABEL_BYTES];
890 char label2[MAX_ARTIFICIAL_LABEL_BYTES];
891 int totsize;
892 vms_func_ref fde = &func_table[rtnnum];
893 int corrected_rtnnum = fde->funcdef_number;
894
895 totsize = 0;
896
897 rtnend.dst_a_rtnend_header.dst__header_length.dst_w_length
898 = DST_K_RTNEND_SIZE - 1;
899 rtnend.dst_a_rtnend_header.dst__header_type.dst_w_type = DST_K_RTNEND;
900 rtnend.dst_b_rtnend_unused = 0;
901 rtnend.dst_l_rtnend_size = 0; /* Calculated below. */
902
903 totsize += write_debug_header (&rtnend.dst_a_rtnend_header, "rtnend",
904 dosizeonly);
905 totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused",
906 dosizeonly);
907
908 ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, corrected_rtnnum);
909 ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, corrected_rtnnum);
910 totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly);
911
912 return totsize;
913 }
914
915 #define K_DELTA_PC(I) \
916 ((I) < 128 ? -(I) : (I) < 65536 ? DST_K_DELTA_PC_W : DST_K_DELTA_PC_L)
917
918 #define K_SET_LINUM(I) \
919 ((I) < 256 ? DST_K_SET_LINUM_B \
920 : (I) < 65536 ? DST_K_SET_LINUM : DST_K_SET_LINUM_L)
921
922 #define K_INCR_LINUM(I) \
923 ((I) < 256 ? DST_K_INCR_LINUM \
924 : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L)
925
926 /* Output the PC to line number correlations and return the size. Just return
927 the size if DOSIZEONLY is nonzero */
928
929 static int
930 write_pclines (int dosizeonly)
931 {
932 unsigned i;
933 int fn;
934 int ln, lastln;
935 int linestart = 0;
936 int max_line;
937 DST_LINE_NUM_HEADER line_num;
938 DST_PCLINE_COMMANDS pcline;
939 char label[MAX_ARTIFICIAL_LABEL_BYTES];
940 char lastlabel[MAX_ARTIFICIAL_LABEL_BYTES];
941 int totsize = 0;
942 char buff[256];
943
944 max_line = file_info_table[1].max_line;
945 file_info_table[1].listing_line_start = linestart;
946 linestart = linestart + ((max_line / 100000) + 1) * 100000;
947
948 for (i = 2; i < file_info_table_in_use; i++)
949 {
950 max_line = file_info_table[i].max_line;
951 file_info_table[i].listing_line_start = linestart;
952 linestart = linestart + ((max_line / 10000) + 1) * 10000;
953 }
954
955 /* Set starting address to beginning of text section. */
956 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8;
957 line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM;
958 pcline.dst_b_pcline_command = DST_K_SET_ABS_PC;
959
960 totsize += write_debug_header (&line_num.dst_a_line_num_header,
961 "line_num", dosizeonly);
962 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
963 "line_num (SET ABS PC)", dosizeonly);
964
965 if (dosizeonly)
966 totsize += 4;
967 else
968 {
969 ASM_OUTPUT_DEBUG_ADDR (asm_out_file, TEXT_SECTION_ASM_OP);
970 if (flag_verbose_asm)
971 fprintf (asm_out_file, "\t%s line_num", ASM_COMMENT_START);
972 fputc ('\n', asm_out_file);
973 }
974
975 fn = line_info_table[1].dst_file_num;
976 ln = (file_info_table[fn].listing_line_start
977 + line_info_table[1].dst_line_num);
978 line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 4 + 4;
979 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
980
981 totsize += write_debug_header (&line_num.dst_a_line_num_header,
982 "line_num", dosizeonly);
983 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
984 "line_num (SET LINUM LONG)", dosizeonly);
985
986 sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0);
987 totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly);
988
989 lastln = ln;
990 strcpy (lastlabel, TEXT_SECTION_ASM_OP);
991 for (i = 1; i < line_info_table_in_use; i++)
992 {
993 int extrabytes;
994
995 fn = line_info_table[i].dst_file_num;
996 ln = (file_info_table[fn].listing_line_start
997 + line_info_table[i].dst_line_num);
998
999 if (ln - lastln > 1)
1000 extrabytes = 5; /* NUMBYTES (ln - lastln - 1) + 1; */
1001 else if (ln <= lastln)
1002 extrabytes = 5; /* NUMBYTES (ln - 1) + 1; */
1003 else
1004 extrabytes = 0;
1005
1006 line_num.dst_a_line_num_header.dst__header_length.dst_w_length
1007 = 8 + extrabytes;
1008
1009 totsize += write_debug_header
1010 (&line_num.dst_a_line_num_header, "line_num", dosizeonly);
1011
1012 if (ln - lastln > 1)
1013 {
1014 int lndif = ln - lastln - 1;
1015
1016 /* K_INCR_LINUM (lndif); */
1017 pcline.dst_b_pcline_command = DST_K_INCR_LINUM_L;
1018
1019 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1020 "line_num (INCR LINUM LONG)",
1021 dosizeonly);
1022
1023 sprintf (buff, "line_num (%d)", lndif);
1024 totsize += write_debug_data4 (lndif, buff, dosizeonly);
1025 }
1026 else if (ln <= lastln)
1027 {
1028 /* K_SET_LINUM (ln-1); */
1029 pcline.dst_b_pcline_command = DST_K_SET_LINUM_L;
1030
1031 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1032 "line_num (SET LINUM LONG)",
1033 dosizeonly);
1034
1035 sprintf (buff, "line_num (%d)", ln - 1);
1036 totsize += write_debug_data4 (ln - 1, buff, dosizeonly);
1037 }
1038
1039 pcline.dst_b_pcline_command = DST_K_DELTA_PC_L;
1040
1041 totsize += write_debug_data1 (pcline.dst_b_pcline_command,
1042 "line_num (DELTA PC LONG)", dosizeonly);
1043
1044 ASM_GENERATE_INTERNAL_LABEL (label, LINE_CODE_LABEL, i);
1045 totsize += write_debug_delta4 (label, lastlabel, "increment line_num",
1046 dosizeonly);
1047
1048 lastln = ln;
1049 strcpy (lastlabel, label);
1050 }
1051
1052 return totsize;
1053 }
1054
1055 /* Output a source correlation for file FILEID using information saved in
1056 FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is
1057 nonzero. */
1058
1059 static int
1060 write_srccorr (int fileid, dst_file_info_entry file_info_entry,
1061 int dosizeonly)
1062 {
1063 int src_command_size;
1064 int linesleft = file_info_entry.max_line;
1065 int linestart = file_info_entry.listing_line_start;
1066 int flen = file_info_entry.flen;
1067 int linestodo = 0;
1068 DST_SOURCE_CORR src_header;
1069 DST_SRC_COMMAND src_command;
1070 DST_SRC_COMMAND src_command_sf;
1071 DST_SRC_COMMAND src_command_sl;
1072 DST_SRC_COMMAND src_command_sr;
1073 DST_SRC_COMMAND src_command_dl;
1074 DST_SRC_CMDTRLR src_cmdtrlr;
1075 char buff[256];
1076 int totsize = 0;
1077
1078 if (fileid == 1)
1079 {
1080 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1081 = DST_K_SOURCE_CORR_HEADER_SIZE + 1 - 1;
1082 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1083 = DST_K_SOURCE;
1084 src_command.dst_b_src_command = DST_K_SRC_FORMFEED;
1085
1086 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1087 "source corr", dosizeonly);
1088
1089 totsize += write_debug_data1 (src_command.dst_b_src_command,
1090 "source_corr (SRC FORMFEED)",
1091 dosizeonly);
1092 }
1093
1094 src_command_size
1095 = DST_K_SRC_COMMAND_SIZE + flen + DST_K_SRC_CMDTRLR_SIZE;
1096 src_command.dst_b_src_command = DST_K_SRC_DECLFILE;
1097 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length
1098 = src_command_size - 2;
1099 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags = 0;
1100 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid
1101 = fileid;
1102 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt
1103 = file_info_entry.cdt;
1104 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk
1105 = file_info_entry.ebk;
1106 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb
1107 = file_info_entry.ffb;
1108 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo
1109 = file_info_entry.rfo;
1110 src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename
1111 = file_info_entry.flen;
1112
1113 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1114 = DST_K_SOURCE_CORR_HEADER_SIZE + src_command_size - 1;
1115 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1116 = DST_K_SOURCE;
1117
1118 src_cmdtrlr.dst_b_src_df_libmodname = 0;
1119
1120 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1121 "source corr", dosizeonly);
1122 totsize += write_debug_data1 (src_command.dst_b_src_command,
1123 "source_corr (DECL SRC FILE)", dosizeonly);
1124 totsize += write_debug_data1
1125 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_length,
1126 "source_corr (length)", dosizeonly);
1127
1128 totsize += write_debug_data1
1129 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_flags,
1130 "source_corr (flags)", dosizeonly);
1131
1132 totsize += write_debug_data2
1133 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_fileid,
1134 "source_corr (fileid)", dosizeonly);
1135
1136 totsize += write_debug_data8
1137 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt,
1138 "source_corr (creation date)", dosizeonly);
1139
1140 totsize += write_debug_data4
1141 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk,
1142 "source_corr (EOF block number)", dosizeonly);
1143
1144 totsize += write_debug_data2
1145 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_w_src_df_rms_ffb,
1146 "source_corr (first free byte)", dosizeonly);
1147
1148 totsize += write_debug_data1
1149 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_rms_rfo,
1150 "source_corr (record and file organization)", dosizeonly);
1151
1152 totsize += write_debug_data1
1153 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
1154 "source_corr (filename length)", dosizeonly);
1155
1156 totsize += write_debug_string (remap_debug_filename (
1157 file_info_entry.file_name),
1158 "source file name", dosizeonly);
1159 totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
1160 "source_corr (libmodname)", dosizeonly);
1161
1162 src_command_sf.dst_b_src_command = DST_K_SRC_SETFILE;
1163 src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword = fileid;
1164
1165 src_command_sr.dst_b_src_command = DST_K_SRC_SETREC_W;
1166 src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword = 1;
1167
1168 src_command_sl.dst_b_src_command = DST_K_SRC_SETLNUM_L;
1169 src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong = linestart + 1;
1170
1171 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1172
1173 if (linesleft > 65534)
1174 linesleft = linesleft - 65534, linestodo = 65534;
1175 else
1176 linestodo = linesleft, linesleft = 0;
1177
1178 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1179
1180 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1181 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 + 3 + 5 + 3 - 1;
1182 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1183 = DST_K_SOURCE;
1184
1185 if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword)
1186 {
1187 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1188 "source corr", dosizeonly);
1189
1190 totsize += write_debug_data1 (src_command_sf.dst_b_src_command,
1191 "source_corr (src setfile)", dosizeonly);
1192
1193 totsize += write_debug_data2
1194 (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword,
1195 "source_corr (fileid)", dosizeonly);
1196
1197 totsize += write_debug_data1 (src_command_sr.dst_b_src_command,
1198 "source_corr (setrec)", dosizeonly);
1199
1200 totsize += write_debug_data2
1201 (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword,
1202 "source_corr (recnum)", dosizeonly);
1203
1204 totsize += write_debug_data1 (src_command_sl.dst_b_src_command,
1205 "source_corr (setlnum)", dosizeonly);
1206
1207 totsize += write_debug_data4
1208 (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong,
1209 "source_corr (linenum)", dosizeonly);
1210
1211 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1212 "source_corr (deflines)", dosizeonly);
1213
1214 sprintf (buff, "source_corr (%d)",
1215 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1216 totsize += write_debug_data2
1217 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1218 buff, dosizeonly);
1219
1220 while (linesleft > 0)
1221 {
1222 src_header.dst_a_source_corr_header.dst__header_length.dst_w_length
1223 = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1;
1224 src_header.dst_a_source_corr_header.dst__header_type.dst_w_type
1225 = DST_K_SOURCE;
1226 src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W;
1227
1228 if (linesleft > 65534)
1229 linesleft = linesleft - 65534, linestodo = 65534;
1230 else
1231 linestodo = linesleft, linesleft = 0;
1232
1233 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo;
1234
1235 totsize += write_debug_header (&src_header.dst_a_source_corr_header,
1236 "source corr", dosizeonly);
1237 totsize += write_debug_data1 (src_command_dl.dst_b_src_command,
1238 "source_corr (deflines)", dosizeonly);
1239 sprintf (buff, "source_corr (%d)",
1240 src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword);
1241 totsize += write_debug_data2
1242 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword,
1243 buff, dosizeonly);
1244 }
1245 }
1246
1247 return totsize;
1248 }
1249
1250 /* Output all the source correlation entries and return the size. Just return
1251 the size if DOSIZEONLY is nonzero. */
1252
1253 static int
1254 write_srccorrs (int dosizeonly)
1255 {
1256 unsigned int i;
1257 int totsize = 0;
1258
1259 for (i = 1; i < file_info_table_in_use; i++)
1260 totsize += write_srccorr (i, file_info_table[i], dosizeonly);
1261
1262 return totsize;
1263 }
1264 \f
1265 /* Output a marker (i.e. a label) for the beginning of a function, before
1266 the prologue. */
1267
1268 static void
1269 vmsdbgout_begin_prologue (unsigned int line, const char *file)
1270 {
1271 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1272
1273 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1274 (*dwarf2_debug_hooks.begin_prologue) (line, file);
1275
1276 if (debug_info_level > DINFO_LEVEL_NONE)
1277 {
1278 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL,
1279 current_function_funcdef_no);
1280 ASM_OUTPUT_LABEL (asm_out_file, label);
1281 }
1282 }
1283
1284 /* Output a marker (i.e. a label) for the beginning of a function, after
1285 the prologue. */
1286
1287 static void
1288 vmsdbgout_end_prologue (unsigned int line, const char *file)
1289 {
1290 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1291
1292 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1293 (*dwarf2_debug_hooks.end_prologue) (line, file);
1294
1295 if (debug_info_level > DINFO_LEVEL_TERSE)
1296 {
1297 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL,
1298 current_function_funcdef_no);
1299 ASM_OUTPUT_LABEL (asm_out_file, label);
1300
1301 /* VMS PCA expects every PC range to correlate to some line and file. */
1302 vmsdbgout_source_line (line, file, 0, true);
1303 }
1304 }
1305
1306 /* No output for VMS debug, but make obligatory call to Dwarf2 debug */
1307
1308 static void
1309 vmsdbgout_end_function (unsigned int line)
1310 {
1311 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1312 (*dwarf2_debug_hooks.end_function) (line);
1313 }
1314
1315 /* Output a marker (i.e. a label) for the absolute end of the generated code
1316 for a function definition. This gets called *after* the epilogue code has
1317 been generated. */
1318
1319 static void
1320 vmsdbgout_end_epilogue (unsigned int line, const char *file)
1321 {
1322 char label[MAX_ARTIFICIAL_LABEL_BYTES];
1323
1324 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1325 (*dwarf2_debug_hooks.end_epilogue) (line, file);
1326
1327 if (debug_info_level > DINFO_LEVEL_NONE)
1328 {
1329 /* Output a label to mark the endpoint of the code generated for this
1330 function. */
1331 ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL,
1332 current_function_funcdef_no);
1333 ASM_OUTPUT_LABEL (asm_out_file, label);
1334
1335 /* VMS PCA expects every PC range to correlate to some line and file. */
1336 vmsdbgout_source_line (line, file, 0, true);
1337 }
1338 }
1339
1340 /* Output a marker (i.e. a label) for the beginning of the generated code for
1341 a lexical block. */
1342
1343 static void
1344 vmsdbgout_begin_block (register unsigned line, register unsigned blocknum)
1345 {
1346 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1347 (*dwarf2_debug_hooks.begin_block) (line, blocknum);
1348
1349 if (debug_info_level > DINFO_LEVEL_TERSE)
1350 targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum);
1351 }
1352
1353 /* Output a marker (i.e. a label) for the end of the generated code for a
1354 lexical block. */
1355
1356 static void
1357 vmsdbgout_end_block (register unsigned line, register unsigned blocknum)
1358 {
1359 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1360 (*dwarf2_debug_hooks.end_block) (line, blocknum);
1361
1362 if (debug_info_level > DINFO_LEVEL_TERSE)
1363 targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum);
1364 }
1365
1366 /* Not implemented in VMS Debug. */
1367
1368 static bool
1369 vmsdbgout_ignore_block (const_tree block)
1370 {
1371 bool retval = 0;
1372
1373 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1374 retval = (*dwarf2_debug_hooks.ignore_block) (block);
1375
1376 return retval;
1377 }
1378
1379 /* Add an entry for function DECL into the func_table. */
1380
1381 static void
1382 vmsdbgout_begin_function (tree decl)
1383 {
1384 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
1385 vms_func_ref fde;
1386
1387 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1388 (*dwarf2_debug_hooks.begin_function) (decl);
1389
1390 if (func_table_in_use == func_table_allocated)
1391 {
1392 func_table_allocated += FUNC_TABLE_INCREMENT;
1393 func_table
1394 = (vms_func_ref) xrealloc (func_table,
1395 func_table_allocated * sizeof (vms_func_node));
1396 }
1397
1398 /* Add the new entry to the end of the function name table. */
1399 fde = &func_table[func_table_in_use++];
1400 fde->vms_func_name = xstrdup (name);
1401 fde->funcdef_number = current_function_funcdef_no;
1402
1403 }
1404
1405 static char fullname_buff [4096];
1406
1407 /* Return the full file specification for FILENAME. The specification must be
1408 in VMS syntax in order to be processed by VMS Debug. */
1409
1410 static char *
1411 full_name (const char *filename)
1412 {
1413 #ifdef VMS
1414 FILE *fp = fopen (filename, "r");
1415
1416 fgetname (fp, fullname_buff, 1);
1417 fclose (fp);
1418 #else
1419 getcwd (fullname_buff, sizeof (fullname_buff));
1420
1421 strcat (fullname_buff, "/");
1422 strcat (fullname_buff, filename);
1423
1424 /* ??? Insert hairy code here to translate Unix style file specification
1425 to VMS style. */
1426 #endif
1427
1428 return fullname_buff;
1429 }
1430
1431 /* Lookup a filename (in the list of filenames that we know about here in
1432 vmsdbgout.c) and return its "index". The index of each (known) filename is
1433 just a unique number which is associated with only that one filename. We
1434 need such numbers for the sake of generating labels and references
1435 to those files numbers. If the filename given as an argument is not
1436 found in our current list, add it to the list and assign it the next
1437 available unique index number. In order to speed up searches, we remember
1438 the index of the filename was looked up last. This handles the majority of
1439 all searches. */
1440
1441 static unsigned int
1442 lookup_filename (const char *file_name)
1443 {
1444 static unsigned int last_file_lookup_index = 0;
1445 register char *fn;
1446 register unsigned i;
1447 const char *fnam;
1448 char flen;
1449 long long cdt = 0;
1450 long ebk = 0;
1451 short ffb = 0;
1452 char rfo = 0;
1453 long siz = 0;
1454 int ver = 0;
1455
1456 fnam = full_name (file_name);
1457 flen = strlen (fnam);
1458
1459 /* Check to see if the file name that was searched on the previous call
1460 matches this file name. If so, return the index. */
1461 if (last_file_lookup_index != 0)
1462 {
1463 fn = file_info_table[last_file_lookup_index].file_name;
1464 if (strcmp (fnam, fn) == 0)
1465 return last_file_lookup_index;
1466 }
1467
1468 /* Didn't match the previous lookup, search the table */
1469 for (i = 1; i < file_info_table_in_use; ++i)
1470 {
1471 fn = file_info_table[i].file_name;
1472 if (strcmp (fnam, fn) == 0)
1473 {
1474 last_file_lookup_index = i;
1475 return i;
1476 }
1477 }
1478
1479 /* Prepare to add a new table entry by making sure there is enough space in
1480 the table to do so. If not, expand the current table. */
1481 if (file_info_table_in_use == file_info_table_allocated)
1482 {
1483
1484 file_info_table_allocated += FILE_TABLE_INCREMENT;
1485 file_info_table = XRESIZEVEC (dst_file_info_entry, file_info_table,
1486 file_info_table_allocated);
1487 }
1488
1489 if (vms_file_stats_name (file_name, &cdt, &siz, &rfo, &ver) == 0)
1490 {
1491 ebk = siz / 512 + 1;
1492 ffb = siz - ((siz / 512) * 512);
1493 }
1494
1495 /* Add the new entry to the end of the filename table. */
1496 file_info_table[file_info_table_in_use].file_name = xstrdup (fnam);
1497 file_info_table[file_info_table_in_use].max_line = 0;
1498 file_info_table[file_info_table_in_use].cdt = cdt;
1499 file_info_table[file_info_table_in_use].ebk = ebk;
1500 file_info_table[file_info_table_in_use].ffb = ffb;
1501 file_info_table[file_info_table_in_use].rfo = rfo;
1502 file_info_table[file_info_table_in_use].flen = flen;
1503
1504 last_file_lookup_index = file_info_table_in_use++;
1505 return last_file_lookup_index;
1506 }
1507
1508 /* Output a label to mark the beginning of a source code line entry
1509 and record information relating to this source line, in
1510 'line_info_table' for later output of the .debug_line section. */
1511
1512 static void
1513 vmsdbgout_source_line (register unsigned line, register const char *filename,
1514 int discriminator, bool is_stmt)
1515 {
1516 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1517 (*dwarf2_debug_hooks.source_line) (line, filename, discriminator, is_stmt);
1518
1519 if (debug_info_level >= DINFO_LEVEL_TERSE)
1520 {
1521 dst_line_info_ref line_info;
1522
1523 targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL,
1524 line_info_table_in_use);
1525
1526 /* Expand the line info table if necessary. */
1527 if (line_info_table_in_use == line_info_table_allocated)
1528 {
1529 line_info_table_allocated += LINE_INFO_TABLE_INCREMENT;
1530 line_info_table = XRESIZEVEC (dst_line_info_entry, line_info_table,
1531 line_info_table_allocated);
1532 }
1533
1534 /* Add the new entry at the end of the line_info_table. */
1535 line_info = &line_info_table[line_info_table_in_use++];
1536 line_info->dst_file_num = lookup_filename (filename);
1537 line_info->dst_line_num = line;
1538 if (line > file_info_table[line_info->dst_file_num].max_line)
1539 file_info_table[line_info->dst_file_num].max_line = line;
1540 }
1541 }
1542
1543 /* Record the beginning of a new source file, for later output.
1544 At present, unimplemented. */
1545
1546 static void
1547 vmsdbgout_start_source_file (unsigned int lineno, const char *filename)
1548 {
1549 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1550 (*dwarf2_debug_hooks.start_source_file) (lineno, filename);
1551 }
1552
1553 /* Record the end of a source file, for later output.
1554 At present, unimplemented. */
1555
1556 static void
1557 vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED)
1558 {
1559 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1560 (*dwarf2_debug_hooks.end_source_file) (lineno);
1561 }
1562
1563 /* Set up for Debug output at the start of compilation. */
1564
1565 static void
1566 vmsdbgout_init (const char *main_input_filename)
1567 {
1568 const char *language_string = lang_hooks.name;
1569
1570 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1571 (*dwarf2_debug_hooks.init) (main_input_filename);
1572
1573 if (debug_info_level == DINFO_LEVEL_NONE)
1574 return;
1575
1576 /* Remember the name of the primary input file. */
1577 primary_filename = main_input_filename;
1578
1579 /* Allocate the initial hunk of the file_info_table. */
1580 file_info_table = XCNEWVEC (dst_file_info_entry, FILE_TABLE_INCREMENT);
1581 file_info_table_allocated = FILE_TABLE_INCREMENT;
1582
1583 /* Skip the first entry - file numbers begin at 1 */
1584 file_info_table_in_use = 1;
1585
1586 func_table = (vms_func_ref) xcalloc (FUNC_TABLE_INCREMENT, sizeof (vms_func_node));
1587 func_table_allocated = FUNC_TABLE_INCREMENT;
1588 func_table_in_use = 1;
1589
1590 /* Allocate the initial hunk of the line_info_table. */
1591 line_info_table = XCNEWVEC (dst_line_info_entry, LINE_INFO_TABLE_INCREMENT);
1592 line_info_table_allocated = LINE_INFO_TABLE_INCREMENT;
1593 /* zero-th entry is allocated, but unused */
1594 line_info_table_in_use = 1;
1595
1596 lookup_filename (primary_filename);
1597
1598 if (!strcmp (language_string, "GNU C"))
1599 module_language = DST_K_C;
1600 else if (!strcmp (language_string, "GNU C++"))
1601 module_language = DST_K_CXX;
1602 else if (!strcmp (language_string, "GNU Ada"))
1603 module_language = DST_K_ADA;
1604 else if (!strcmp (language_string, "GNU F77"))
1605 module_language = DST_K_FORTRAN;
1606 else
1607 module_language = DST_K_UNKNOWN;
1608
1609 module_producer = concat (language_string, " ", version_string, NULL);
1610
1611 ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
1612
1613 }
1614
1615 /* Not implemented in VMS Debug. */
1616
1617 static void
1618 vmsdbgout_define (unsigned int lineno, const char *buffer)
1619 {
1620 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1621 (*dwarf2_debug_hooks.define) (lineno, buffer);
1622 }
1623
1624 /* Not implemented in VMS Debug. */
1625
1626 static void
1627 vmsdbgout_undef (unsigned int lineno, const char *buffer)
1628 {
1629 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1630 (*dwarf2_debug_hooks.undef) (lineno, buffer);
1631 }
1632
1633 /* Not implemented in VMS Debug. */
1634
1635 static void
1636 vmsdbgout_decl (tree decl)
1637 {
1638 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1639 (*dwarf2_debug_hooks.function_decl) (decl);
1640 }
1641
1642 /* Not implemented in VMS Debug. */
1643
1644 static void
1645 vmsdbgout_global_decl (tree decl)
1646 {
1647 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1648 (*dwarf2_debug_hooks.global_decl) (decl);
1649 }
1650
1651 /* Not implemented in VMS Debug. */
1652
1653 static void
1654 vmsdbgout_abstract_function (tree decl)
1655 {
1656 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1657 (*dwarf2_debug_hooks.outlining_inline_function) (decl);
1658 }
1659
1660 /* Output stuff that Debug requires at the end of every file and generate the
1661 VMS Debug debugging info. */
1662
1663 static void
1664 vmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED)
1665 {
1666 unsigned int i;
1667 int totsize;
1668
1669 if (write_symbols == VMS_AND_DWARF2_DEBUG)
1670 (*dwarf2_debug_hooks.finish) (main_input_filename);
1671
1672 if (debug_info_level == DINFO_LEVEL_NONE)
1673 return;
1674
1675 /* Output a terminator label for the .text section. */
1676 switch_to_section (text_section);
1677 targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0);
1678
1679 /* Output debugging information.
1680 Warning! Do not change the name of the .vmsdebug section without
1681 changing it in the assembler also. */
1682 switch_to_section (get_named_section (NULL, ".vmsdebug", 0));
1683 ASM_OUTPUT_ALIGN (asm_out_file, 0);
1684
1685 totsize = write_modbeg (1);
1686 for (i = 1; i < func_table_in_use; i++)
1687 {
1688 totsize += write_rtnbeg (i, 1);
1689 totsize += write_rtnend (i, 1);
1690 }
1691 totsize += write_pclines (1);
1692
1693 write_modbeg (0);
1694 for (i = 1; i < func_table_in_use; i++)
1695 {
1696 write_rtnbeg (i, 0);
1697 write_rtnend (i, 0);
1698 }
1699 write_pclines (0);
1700
1701 if (debug_info_level > DINFO_LEVEL_TERSE)
1702 {
1703 totsize = write_srccorrs (1);
1704 write_srccorrs (0);
1705 }
1706
1707 totsize = write_modend (1);
1708 write_modend (0);
1709 }
1710
1711 /* Need for both Dwarf2 on IVMS and VMS Debug on AVMS */
1712
1713 #ifdef VMS
1714 #define __NEW_STARLET 1
1715 #include <vms/rms.h>
1716 #include <vms/atrdef.h>
1717 #include <vms/fibdef.h>
1718 #include <vms/stsdef.h>
1719 #include <vms/iodef.h>
1720 #include <vms/fatdef.h>
1721 #include <errno.h>
1722 #include <vms/descrip.h>
1723 #include <string.h>
1724 #include <unixlib.h>
1725
1726 #define MAXPATH 256
1727
1728 /* descrip.h doesn't have everything ... */
1729 typedef struct fibdef* __fibdef_ptr32 __attribute__ (( mode (SI) ));
1730 struct dsc$descriptor_fib
1731 {
1732 unsigned int fib$l_len;
1733 __fibdef_ptr32 fib$l_addr;
1734 };
1735
1736 /* I/O Status Block. */
1737 struct IOSB
1738 {
1739 unsigned short status, count;
1740 unsigned int devdep;
1741 };
1742
1743 static char *tryfile;
1744
1745 /* Variable length string. */
1746 struct vstring
1747 {
1748 short length;
1749 char string[NAM$C_MAXRSS+1];
1750 };
1751
1752 static char filename_buff [MAXPATH];
1753 static char vms_filespec [MAXPATH];
1754
1755 /* Callback function for filespec style conversion. */
1756
1757 static int
1758 translate_unix (char *name, int type ATTRIBUTE_UNUSED)
1759 {
1760 strncpy (filename_buff, name, MAXPATH);
1761 filename_buff [MAXPATH - 1] = (char) 0;
1762 return 0;
1763 }
1764
1765 /* Wrapper for DECC function that converts a Unix filespec
1766 to VMS style filespec. */
1767
1768 static char *
1769 to_vms_file_spec (char *filespec)
1770 {
1771 strncpy (vms_filespec, "", MAXPATH);
1772 decc$to_vms (filespec, translate_unix, 1, 1);
1773 strncpy (vms_filespec, filename_buff, MAXPATH);
1774
1775 vms_filespec [MAXPATH - 1] = (char) 0;
1776
1777 return vms_filespec;
1778 }
1779
1780 #else
1781 #define VMS_EPOCH_OFFSET 35067168000000000
1782 #define VMS_GRANULARITY_FACTOR 10000000
1783 #endif
1784
1785 /* Return VMS file date, size, format, version given a name. */
1786
1787 int
1788 vms_file_stats_name (const char *filename, long long *cdt, long *siz, char *rfo,
1789 int *ver)
1790 {
1791 #ifdef VMS
1792 struct FAB fab;
1793 struct NAM nam;
1794
1795 unsigned long long create;
1796 FAT recattr;
1797 char ascnamebuff [256];
1798
1799 ATRDEF atrlst[]
1800 = {
1801 { ATR$S_CREDATE, ATR$C_CREDATE, &create },
1802 { ATR$S_RECATTR, ATR$C_RECATTR, &recattr },
1803 { ATR$S_ASCNAME, ATR$C_ASCNAME, &ascnamebuff },
1804 { 0, 0, 0}
1805 };
1806
1807 FIBDEF fib;
1808 struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};
1809
1810 struct IOSB iosb;
1811
1812 long status;
1813 unsigned short chan;
1814
1815 struct vstring file;
1816 struct dsc$descriptor_s filedsc
1817 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
1818 struct vstring device;
1819 struct dsc$descriptor_s devicedsc
1820 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
1821 struct vstring result;
1822 struct dsc$descriptor_s resultdsc
1823 = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};
1824
1825 if (strcmp (filename, "<internal>") == 0
1826 || strcmp (filename, "<built-in>") == 0)
1827 {
1828 if (cdt)
1829 *cdt = 0;
1830
1831 if (siz)
1832 *siz = 0;
1833
1834 if (rfo)
1835 *rfo = 0;
1836
1837 if (ver)
1838 *ver = 0;
1839
1840 return 0;
1841 }
1842
1843 tryfile = to_vms_file_spec (filename);
1844
1845 /* Allocate and initialize a FAB and NAM structures. */
1846 fab = cc$rms_fab;
1847 nam = cc$rms_nam;
1848
1849 nam.nam$l_esa = file.string;
1850 nam.nam$b_ess = NAM$C_MAXRSS;
1851 nam.nam$l_rsa = result.string;
1852 nam.nam$b_rss = NAM$C_MAXRSS;
1853 fab.fab$l_fna = tryfile;
1854 fab.fab$b_fns = strlen (tryfile);
1855 fab.fab$l_nam = &nam;
1856
1857 /* Validate filespec syntax and device existence. */
1858 status = SYS$PARSE (&fab, 0, 0);
1859 if ((status & 1) != 1)
1860 return 1;
1861
1862 file.string[nam.nam$b_esl] = 0;
1863
1864 /* Find matching filespec. */
1865 status = SYS$SEARCH (&fab, 0, 0);
1866 if ((status & 1) != 1)
1867 return 1;
1868
1869 file.string[nam.nam$b_esl] = 0;
1870 result.string[result.length=nam.nam$b_rsl] = 0;
1871
1872 /* Get the device name and assign an IO channel. */
1873 strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
1874 devicedsc.dsc$w_length = nam.nam$b_dev;
1875 chan = 0;
1876 status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
1877 if ((status & 1) != 1)
1878 return 1;
1879
1880 /* Initialize the FIB and fill in the directory id field. */
1881 memset (&fib, 0, sizeof (fib));
1882 fib.fib$w_did[0] = nam.nam$w_did[0];
1883 fib.fib$w_did[1] = nam.nam$w_did[1];
1884 fib.fib$w_did[2] = nam.nam$w_did[2];
1885 fib.fib$l_acctl = 0;
1886 fib.fib$l_wcc = 0;
1887 strcpy (file.string, (strrchr (result.string, ']') + 1));
1888 filedsc.dsc$w_length = strlen (file.string);
1889 result.string[result.length = 0] = 0;
1890
1891 /* Open and close the file to fill in the attributes. */
1892 status
1893 = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
1894 &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
1895 if ((status & 1) != 1)
1896 return 1;
1897 if ((iosb.status & 1) != 1)
1898 return 1;
1899
1900 result.string[result.length] = 0;
1901 status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
1902 &atrlst, 0);
1903 if ((status & 1) != 1)
1904 return 1;
1905 if ((iosb.status & 1) != 1)
1906 return 1;
1907
1908 /* Deassign the channel and exit. */
1909 status = SYS$DASSGN (chan);
1910 if ((status & 1) != 1)
1911 return 1;
1912
1913 if (cdt) *cdt = create;
1914 if (siz) *siz = (512 * 65536 * recattr.fat$w_efblkh) +
1915 (512 * (recattr.fat$w_efblkl - 1)) +
1916 recattr.fat$w_ffbyte;
1917 if (rfo) *rfo = recattr.fat$v_rtype;
1918 if (ver) *ver = strtol (strrchr (ascnamebuff, ';')+1, 0, 10);
1919
1920 return 0;
1921 #else
1922 struct stat buff;
1923
1924 if ((stat (filename, &buff)) != 0)
1925 return 1;
1926
1927 if (cdt)
1928 *cdt = (long long) (buff.st_mtime * VMS_GRANULARITY_FACTOR)
1929 + VMS_EPOCH_OFFSET;
1930
1931 if (siz)
1932 *siz = buff.st_size;
1933
1934 if (rfo)
1935 *rfo = 2; /* Stream LF format */
1936
1937 if (ver)
1938 *ver = 1;
1939
1940 return 0;
1941 #endif
1942 }
1943 #endif