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