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