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