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