X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fvmsdbgout.c;h=2ad6ed23e998d9ef2c7a54fcf62730ceda7f8dd2;hp=7d0de2f2de1f815148d12195ff64ae5dd8819a48;hb=08803898f86ac4e22632737f1bd52668dbb4e663;hpb=e42f642381c6ba7bd12a81bfc23dccbb39797bc6 diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c index 7d0de2f2de1..2ad6ed23e99 100644 --- a/gcc/vmsdbgout.c +++ b/gcc/vmsdbgout.c @@ -1,13 +1,15 @@ -/* Output VMS debug format symbol table information from the GNU C compiler. +/* Output VMS debug format symbol table information from GCC. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Free Software Foundation, Inc. Contributed by Douglas B. Rupp (rupp@gnat.com). + Updated by Bernard W. Giroud (bgiroud@users.sourceforge.net). -This file is part of GNU CC. +This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,25 +18,31 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" #ifdef VMS_DEBUGGING_INFO -#include "system.h" #include "tree.h" +#include "version.h" #include "flags.h" #include "rtl.h" #include "output.h" #include "vmsdbg.h" #include "debug.h" #include "langhooks.h" +#include "function.h" +#include "target.h" /* Difference in seconds between the VMS Epoch and the Unix Epoch */ static const long long vms_epoch_offset = 3506716800ll; +int vms_file_stats_name (const char *, long long *, long *, char *, int *); + /* NOTE: In the comments in this file, many references are made to "Debug Symbol Table". This term is abbreviated as `DST' throughout the remainder of this file. */ @@ -83,7 +91,7 @@ dst_file_info_entry; #define PTR_SIZE 4 /* Must be 32 bits for VMS debug info */ #endif -/* Pointer to an structure of filenames referenced by this compilation unit. */ +/* Pointer to a structure of filenames referenced by this compilation unit. */ static dst_file_info_ref file_info_table; /* Total number of entries in the table (i.e. array) pointed to by @@ -98,13 +106,28 @@ static unsigned int file_info_table_in_use; table. */ #define FILE_TABLE_INCREMENT 64 -static char **func_table; +/* A structure to hold basic information for the VMS end + routine. */ + +typedef struct vms_func_struct +{ + const char *vms_func_name; + unsigned funcdef_number; +} +vms_func_node; + +typedef struct vms_func_struct *vms_func_ref; + static unsigned int func_table_allocated; static unsigned int func_table_in_use; #define FUNC_TABLE_INCREMENT 256 +/* A pointer to the base of a table that contains frame description + information for each routine. */ +static vms_func_ref func_table; + /* Local pointer to the name of the main input file. Initialized in - avmdbgout_init. */ + vmsdbgout_init. */ static const char *primary_filename; static char *module_producer; @@ -123,56 +146,52 @@ static unsigned int line_info_table_in_use; /* Size (in elements) of increments by which we may expand line_info_table. */ #define LINE_INFO_TABLE_INCREMENT 1024 -/* The number of the current function definition for which debugging - information is being generated. These numbers range from 1 up to the - maximum number of function definitions contained within the current - compilation unit. These numbers are used to create unique label id's unique - to each function definition. */ -static unsigned int current_funcdef_number = 0; - /* Forward declarations for functions defined in this file. */ -static char *full_name PARAMS ((const char *)); -static unsigned int lookup_filename PARAMS ((const char *)); -static void addr_const_to_string PARAMS ((char *, rtx)); -static int write_debug_header PARAMS ((DST_HEADER *, const char *, int)); -static int write_debug_addr PARAMS ((char *, const char *, int)); -static int write_debug_data1 PARAMS ((unsigned int, const char *, int)); -static int write_debug_data2 PARAMS ((unsigned int, const char *, int)); -static int write_debug_data4 PARAMS ((unsigned long, const char *, int)); -static int write_debug_data8 PARAMS ((unsigned long long, const char *, - int)); -static int write_debug_delta4 PARAMS ((char *, char *, const char *, int)); -static int write_debug_string PARAMS ((char *, const char *, int)); -static int write_modbeg PARAMS ((int)); -static int write_modend PARAMS ((int)); -static int write_rtnbeg PARAMS ((int, int)); -static int write_rtnend PARAMS ((int, int)); -static int write_pclines PARAMS ((int)); -static int write_srccorr PARAMS ((int, dst_file_info_entry, int)); -static int write_srccorrs PARAMS ((int)); - -static void vmsdbgout_init PARAMS ((const char *)); -static void vmsdbgout_finish PARAMS ((const char *)); -static void vmsdbgout_define PARAMS ((unsigned int, const char *)); -static void vmsdbgout_undef PARAMS ((unsigned int, const char *)); -static void vmsdbgout_start_source_file PARAMS ((unsigned int, const char *)); -static void vmsdbgout_end_source_file PARAMS ((unsigned int)); -static void vmsdbgout_begin_block PARAMS ((unsigned int, unsigned int)); -static void vmsdbgout_end_block PARAMS ((unsigned int, unsigned int)); -static bool vmsdbgout_ignore_block PARAMS ((tree)); -static void vmsdbgout_source_line PARAMS ((unsigned int, const char *)); -static void vmsdbgout_begin_prologue PARAMS ((unsigned int, const char *)); -static void vmsdbgout_end_epilogue PARAMS ((void)); -static void vmsdbgout_begin_function PARAMS ((tree)); -static void vmsdbgout_decl PARAMS ((tree)); -static void vmsdbgout_global_decl PARAMS ((tree)); -static void vmsdbgout_abstract_function PARAMS ((tree)); +static char *full_name (const char *); +static unsigned int lookup_filename (const char *); +static void addr_const_to_string (char *, rtx); +static int write_debug_header (DST_HEADER *, const char *, int); +static int write_debug_addr (const char *, const char *, int); +static int write_debug_data1 (unsigned int, const char *, int); +static int write_debug_data2 (unsigned int, const char *, int); +static int write_debug_data4 (unsigned long, const char *, int); +static int write_debug_data8 (unsigned long long, const char *, int); +static int write_debug_delta4 (const char *, const char *, const char *, int); +static int write_debug_string (const char *, const char *, int); +static int write_modbeg (int); +static int write_modend (int); +static int write_rtnbeg (int, int); +static int write_rtnend (int, int); +static int write_pclines (int); +static int write_srccorr (int, dst_file_info_entry, int); +static int write_srccorrs (int); + +static void vmsdbgout_init (const char *); +static void vmsdbgout_finish (const char *); +static void vmsdbgout_assembly_start (void); +static void vmsdbgout_define (unsigned int, const char *); +static void vmsdbgout_undef (unsigned int, const char *); +static void vmsdbgout_start_source_file (unsigned int, const char *); +static void vmsdbgout_end_source_file (unsigned int); +static void vmsdbgout_begin_block (unsigned int, unsigned int); +static void vmsdbgout_end_block (unsigned int, unsigned int); +static bool vmsdbgout_ignore_block (const_tree); +static void vmsdbgout_source_line (unsigned int, const char *, int, bool); +static void vmsdbgout_begin_prologue (unsigned int, const char *); +static void vmsdbgout_end_prologue (unsigned int, const char *); +static void vmsdbgout_end_function (unsigned int); +static void vmsdbgout_end_epilogue (unsigned int, const char *); +static void vmsdbgout_begin_function (tree); +static void vmsdbgout_decl (tree); +static void vmsdbgout_global_decl (tree); +static void vmsdbgout_abstract_function (tree); /* The debug hooks structure. */ const struct gcc_debug_hooks vmsdbg_debug_hooks = {vmsdbgout_init, vmsdbgout_finish, + vmsdbgout_assembly_start, vmsdbgout_define, vmsdbgout_undef, vmsdbgout_start_source_file, @@ -182,15 +201,26 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks vmsdbgout_ignore_block, vmsdbgout_source_line, vmsdbgout_begin_prologue, - debug_nothing_int, /* end_prologue */ - vmsdbgout_end_epilogue, /* end_epilogue */ - vmsdbgout_begin_function, /* begin_function */ - debug_nothing_int, /* end_function */ + vmsdbgout_end_prologue, + vmsdbgout_end_epilogue, + vmsdbgout_begin_function, + vmsdbgout_end_function, vmsdbgout_decl, vmsdbgout_global_decl, - debug_nothing_tree, /* deferred_inline_function */ + debug_nothing_tree_int, /* type_decl */ + debug_nothing_tree_tree_tree_bool, /* imported_module_or_decl */ + debug_nothing_tree, /* deferred_inline_function */ vmsdbgout_abstract_function, - debug_nothing_rtx /* label */ + debug_nothing_rtx, /* label */ + debug_nothing_int, /* handle_pch */ + debug_nothing_rtx, /* var_location */ + debug_nothing_void, /* switch_text_section */ + debug_nothing_tree, /* direct_call */ + debug_nothing_tree_int, /* virtual_call_token */ + debug_nothing_rtx_rtx, /* copy_call_info */ + debug_nothing_uid, /* virtual_call */ + debug_nothing_tree_tree, /* set_name */ + 0 /* start_end_main_source_file */ }; /* Definitions of defaults for assembler-dependent names of various @@ -238,11 +268,6 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks : (NUMBYTES(OFFSET) == 2 ? UNALIGNED_SHORT_ASM_OP : ASM_BYTE_OP)) #endif -/* Pseudo-op for defining a new section. */ -#ifndef SECTION_ASM_OP -#define SECTION_ASM_OP ".section" -#endif - /* Definitions of defaults for formats and names of various special (artificial) labels which may be generated within this file (when the -g options is used and VMS_DEBUGGING_INFO is in effect. If necessary, these @@ -358,14 +383,14 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; #endif /* This is similar to the default ASM_OUTPUT_ASCII, except that no trailing - newline is produced. When flag_verbose_asm is asserted, we add commnetary + newline is produced. When flag_verbose_asm is asserted, we add commentary at the end of the line, so we must avoid output of a newline here. */ #ifndef ASM_OUTPUT_DEBUG_STRING #define ASM_OUTPUT_DEBUG_STRING(FILE,P) \ do \ { \ register int slen = strlen(P); \ - register char *p = (P); \ + register const char *p = (P); \ register int i; \ fprintf (FILE, "\t.ascii \""); \ for (i = 0; i < slen; i++) \ @@ -387,7 +412,7 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; macro has the same effect as ASM_OUTPUT_LABELREF, but copies to a string rather than writing to a file. */ #ifndef ASM_NAME_TO_STRING -#define ASM_NAME_TO_STRING(STR, NAME) \ +#define ASM_NAME_TO_STRING(STR, NAME) \ do \ { \ if ((NAME)[0] == '*') \ @@ -408,22 +433,18 @@ static char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES]; directly, because it writes to a file. */ static void -addr_const_to_string (str, x) - char *str; - rtx x; +addr_const_to_string (char *str, rtx x) { char buf1[256]; char buf2[256]; -restart: + restart: str[0] = '\0'; switch (GET_CODE (x)) { case PC: - if (flag_pic) - strcat (str, ","); - else - abort (); + gcc_assert (flag_pic); + strcat (str, ","); break; case SYMBOL_REF: @@ -449,7 +470,7 @@ restart: break; case CONST: - /* This used to output parentheses around the expression, but that does + /* This used to output parentheses around the expression, but that does not work on the 386 (either ATT or BSD assembler). */ addr_const_to_string (buf1, XEXP (x, 0)); strcat (str, buf1); @@ -477,7 +498,7 @@ restart: case PLUS: /* Some assemblers need integer constants to appear last (eg masm). */ - if (GET_CODE (XEXP (x, 0)) == CONST_INT) + if (CONST_INT_P (XEXP (x, 0))) { addr_const_to_string (buf1, XEXP (x, 1)); strcat (str, buf1); @@ -507,7 +528,7 @@ restart: addr_const_to_string (buf1, XEXP (x, 0)); strcat (str, buf1); strcat (str, "-"); - if (GET_CODE (XEXP (x, 1)) == CONST_INT + if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) < 0) { strcat (str, "("); @@ -535,13 +556,10 @@ restart: /* Output the debug header HEADER. Also output COMMENT if flag_verbose_asm is set. Return the header size. Just return the size if DOSIZEONLY is - non-zero. */ + nonzero. */ static int -write_debug_header (header, comment, dosizeonly) - DST_HEADER *header; - const char *comment; - int dosizeonly; +write_debug_header (DST_HEADER *header, const char *comment, int dosizeonly) { if (!dosizeonly) { @@ -567,13 +585,10 @@ write_debug_header (header, comment, dosizeonly) /* Output the address of SYMBOL. Also output COMMENT if flag_verbose_asm is set. Return the address size. Just return the size if DOSIZEONLY is - non-zero. */ + nonzero. */ static int -write_debug_addr (symbol, comment, dosizeonly) - char *symbol; - const char *comment; - int dosizeonly; +write_debug_addr (const char *symbol, const char *comment, int dosizeonly) { if (!dosizeonly) { @@ -588,13 +603,10 @@ write_debug_addr (symbol, comment, dosizeonly) /* Output the single byte DATA1. Also output COMMENT if flag_verbose_asm is set. Return the data size. Just return the size if DOSIZEONLY is - non-zero. */ + nonzero. */ static int -write_debug_data1 (data1, comment, dosizeonly) - unsigned int data1; - const char *comment; - int dosizeonly; +write_debug_data1 (unsigned int data1, const char *comment, int dosizeonly) { if (!dosizeonly) { @@ -609,13 +621,10 @@ write_debug_data1 (data1, comment, dosizeonly) /* Output the single word DATA2. Also output COMMENT if flag_verbose_asm is set. Return the data size. Just return the size if DOSIZEONLY is - non-zero. */ + nonzero. */ static int -write_debug_data2 (data2, comment, dosizeonly) - unsigned int data2; - const char *comment; - int dosizeonly; +write_debug_data2 (unsigned int data2, const char *comment, int dosizeonly) { if (!dosizeonly) { @@ -629,13 +638,10 @@ write_debug_data2 (data2, comment, dosizeonly) } /* Output double word DATA4. Also output COMMENT if flag_verbose_asm is set. - Return the data size. Just return the size if DOSIZEONLY is non-zero. */ + Return the data size. Just return the size if DOSIZEONLY is nonzero. */ static int -write_debug_data4 (data4, comment, dosizeonly) - unsigned long data4; - const char *comment; - int dosizeonly; +write_debug_data4 (unsigned long data4, const char *comment, int dosizeonly) { if (!dosizeonly) { @@ -644,18 +650,16 @@ write_debug_data4 (data4, comment, dosizeonly) fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); fputc ('\n', asm_out_file); } - + return 4; } /* Output quad word DATA8. Also output COMMENT if flag_verbose_asm is set. - Return the data size. Just return the size if DOSIZEONLY is non-zero. */ + Return the data size. Just return the size if DOSIZEONLY is nonzero. */ static int -write_debug_data8 (data8, comment, dosizeonly) - unsigned long long data8; - const char *comment; - int dosizeonly; +write_debug_data8 (unsigned long long data8, const char *comment, + int dosizeonly) { if (!dosizeonly) { @@ -670,14 +674,11 @@ write_debug_data8 (data8, comment, dosizeonly) /* Output the difference between LABEL1 and LABEL2. Also output COMMENT if flag_verbose_asm is set. Return the data size. Just return the size if - DOSIZEONLY is non-zero. */ + DOSIZEONLY is nonzero. */ static int -write_debug_delta4 (label1, label2, comment, dosizeonly) - char *label1; - char *label2; - const char *comment; - int dosizeonly; +write_debug_delta4 (const char *label1, const char *label2, + const char *comment, int dosizeonly) { if (!dosizeonly) { @@ -692,13 +693,10 @@ write_debug_delta4 (label1, label2, comment, dosizeonly) /* Output a character string STRING. Also write COMMENT if flag_verbose_asm is set. Return the string length. Just return the length if DOSIZEONLY is - non-zero. */ + nonzero. */ static int -write_debug_string (string, comment, dosizeonly) - char *string; - const char *comment; - int dosizeonly; +write_debug_string (const char *string, const char *comment, int dosizeonly) { if (!dosizeonly) { @@ -707,16 +705,15 @@ write_debug_string (string, comment, dosizeonly) fprintf (asm_out_file, "\t%s %s", ASM_COMMENT_START, comment); fputc ('\n', asm_out_file); } - + return strlen (string); } /* Output a module begin header and return the header size. Just return the - size if DOSIZEONLY is non-zero. */ + size if DOSIZEONLY is nonzero. */ static int -write_modbeg (dosizeonly) - int dosizeonly; +write_modbeg (int dosizeonly) { DST_MODULE_BEGIN modbeg; DST_MB_TRLR mb_trlr; @@ -727,7 +724,7 @@ write_modbeg (dosizeonly) int totsize = 0; /* Assumes primary filename has Unix syntax file spec. */ - module_name = xstrdup (basename ((char *) primary_filename)); + module_name = xstrdup (lbasename (primary_filename)); m = strrchr (module_name, '.'); if (m) @@ -776,11 +773,10 @@ write_modbeg (dosizeonly) } /* Output a module end trailer and return the trailer size. Just return - the size if DOSIZEONLY is non-zero. */ + the size if DOSIZEONLY is nonzero. */ static int -write_modend (dosizeonly) - int dosizeonly; +write_modend (int dosizeonly) { DST_MODULE_END modend; int totsize = 0; @@ -796,27 +792,23 @@ write_modend (dosizeonly) } /* Output a routine begin header routine RTNNUM and return the header size. - Just return the size if DOSIZEONLY is non-zero. */ + Just return the size if DOSIZEONLY is nonzero. */ static int -write_rtnbeg (rtnnum, dosizeonly) - int rtnnum; - int dosizeonly; +write_rtnbeg (int rtnnum, int dosizeonly) { - char *rtnname; - int rtnnamelen, rtnentrynamelen; + const char *rtnname; + int rtnnamelen; char *rtnentryname; int totsize = 0; char label[MAX_ARTIFICIAL_LABEL_BYTES]; DST_ROUTINE_BEGIN rtnbeg; DST_PROLOG prolog; + vms_func_ref fde = &func_table[rtnnum]; - rtnname = func_table[rtnnum]; + rtnname = fde->vms_func_name; rtnnamelen = strlen (rtnname); - rtnentrynamelen = rtnnamelen + 4; /* "..en" */ - rtnentryname = (char *) xmalloc (rtnentrynamelen + 1); - strcpy (rtnentryname, rtnname); - strcat (rtnentryname, "..en"); + rtnentryname = concat (rtnname, "..en", NULL); if (!strcmp (rtnname, "main")) { @@ -829,7 +821,7 @@ write_rtnbeg (rtnnum, dosizeonly) /* header size - 1st byte + flag byte + STO_LW size + string count byte + string length */ header.dst__header_length.dst_w_length - = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go); + = DST_K_DST_HEADER_SIZE - 1 + 1 + 4 + 1 + strlen (go); header.dst__header_type.dst_w_type = 0x17; totsize += write_debug_header (&header, "transfer", dosizeonly); @@ -842,10 +834,10 @@ write_rtnbeg (rtnnum, dosizeonly) dosizeonly); totsize += write_debug_data1 (strlen (go), "length of main_name", dosizeonly); - totsize += write_debug_string ((char *) go, "main name", dosizeonly); + totsize += write_debug_string (go, "main name", dosizeonly); } - /* The header length never includes the length byte */ + /* The header length never includes the length byte. */ rtnbeg.dst_a_rtnbeg_header.dst__header_length.dst_w_length = DST_K_RTNBEG_SIZE + rtnnamelen - 1; rtnbeg.dst_a_rtnbeg_header.dst__header_type.dst_w_type = DST_K_RTNBEG; @@ -885,7 +877,7 @@ write_rtnbeg (rtnnum, dosizeonly) totsize += write_debug_header (&prolog.dst_a_prolog_header, "prolog", dosizeonly); - ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, rtnnum); + ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, fde->funcdef_number); totsize += write_debug_addr (label, "prolog breakpoint addr", dosizeonly); } @@ -894,17 +886,17 @@ write_rtnbeg (rtnnum, dosizeonly) } /* Output a routine end trailer for routine RTNNUM and return the header size. - Just return the size if DOSIZEONLY is non-zero. */ + Just return the size if DOSIZEONLY is nonzero. */ static int -write_rtnend (rtnnum, dosizeonly) - int rtnnum; - int dosizeonly; +write_rtnend (int rtnnum, int dosizeonly) { DST_ROUTINE_END rtnend; char label1[MAX_ARTIFICIAL_LABEL_BYTES]; char label2[MAX_ARTIFICIAL_LABEL_BYTES]; int totsize; + vms_func_ref fde = &func_table[rtnnum]; + int corrected_rtnnum = fde->funcdef_number; totsize = 0; @@ -919,8 +911,8 @@ write_rtnend (rtnnum, dosizeonly) totsize += write_debug_data1 (rtnend.dst_b_rtnend_unused, "unused", dosizeonly); - ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, rtnnum); - ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, rtnnum); + ASM_GENERATE_INTERNAL_LABEL (label1, FUNC_BEGIN_LABEL, corrected_rtnnum); + ASM_GENERATE_INTERNAL_LABEL (label2, FUNC_END_LABEL, corrected_rtnnum); totsize += write_debug_delta4 (label2, label1, "routine size", dosizeonly); return totsize; @@ -938,11 +930,10 @@ write_rtnend (rtnnum, dosizeonly) : (I) < 65536 ? DST_K_INCR_LINUM_W : DST_K_INCR_LINUM_L) /* Output the PC to line number correlations and return the size. Just return - the size if DOSIZEONLY is non-zero */ + the size if DOSIZEONLY is nonzero */ static int -write_pclines (dosizeonly) - int dosizeonly; +write_pclines (int dosizeonly) { unsigned i; int fn; @@ -967,7 +958,7 @@ write_pclines (dosizeonly) linestart = linestart + ((max_line / 10000) + 1) * 10000; } - /* Set starting address to beginning of text section */ + /* Set starting address to beginning of text section. */ line_num.dst_a_line_num_header.dst__header_length.dst_w_length = 8; line_num.dst_a_line_num_header.dst__header_type.dst_w_type = DST_K_LINE_NUM; pcline.dst_b_pcline_command = DST_K_SET_ABS_PC; @@ -998,8 +989,8 @@ write_pclines (dosizeonly) totsize += write_debug_data1 (pcline.dst_b_pcline_command, "line_num (SET LINUM LONG)", dosizeonly); - sprintf (buff, "line_num (%d)", ln - 1); - totsize += write_debug_data4 (ln - 1, buff, dosizeonly); + sprintf (buff, "line_num (%d)", ln ? ln - 1 : 0); + totsize += write_debug_data4 (ln ? ln - 1 : 0, buff, dosizeonly); lastln = ln; strcpy (lastlabel, TEXT_SECTION_ASM_OP); @@ -1069,13 +1060,11 @@ write_pclines (dosizeonly) /* Output a source correlation for file FILEID using information saved in FILE_INFO_ENTRY and return the size. Just return the size if DOSIZEONLY is - non-zero. */ + nonzero. */ static int -write_srccorr (fileid, file_info_entry, dosizeonly) - int fileid; - dst_file_info_entry file_info_entry; - int dosizeonly; +write_srccorr (int fileid, dst_file_info_entry file_info_entry, + int dosizeonly) { int src_command_size; int linesleft = file_info_entry.max_line; @@ -1133,7 +1122,7 @@ write_srccorr (fileid, file_info_entry, dosizeonly) = DST_K_SOURCE; src_cmdtrlr.dst_b_src_df_libmodname = 0; - + totsize += write_debug_header (&src_header.dst_a_source_corr_header, "source corr", dosizeonly); totsize += write_debug_data1 (src_command.dst_b_src_command, @@ -1153,7 +1142,7 @@ write_srccorr (fileid, file_info_entry, dosizeonly) totsize += write_debug_data8 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_q_src_df_rms_cdt, "source_corr (creation date)", dosizeonly); - + totsize += write_debug_data4 (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_l_src_df_rms_ebk, "source_corr (EOF block number)", dosizeonly); @@ -1170,7 +1159,8 @@ write_srccorr (fileid, file_info_entry, dosizeonly) (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename, "source_corr (filename length)", dosizeonly); - totsize += write_debug_string (file_info_entry.file_name, + totsize += write_debug_string (remap_debug_filename ( + file_info_entry.file_name), "source file name", dosizeonly); totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname, "source_corr (libmodname)", dosizeonly); @@ -1198,73 +1188,76 @@ write_srccorr (fileid, file_info_entry, dosizeonly) src_header.dst_a_source_corr_header.dst__header_type.dst_w_type = DST_K_SOURCE; - totsize += write_debug_header (&src_header.dst_a_source_corr_header, - "source corr", dosizeonly); - - totsize += write_debug_data1 (src_command_sf.dst_b_src_command, - "source_corr (src setfile)", dosizeonly); - - totsize += write_debug_data2 - (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword, - "source_corr (fileid)", dosizeonly); - - totsize += write_debug_data1 (src_command_sr.dst_b_src_command, - "source_corr (setrec)", dosizeonly); - - totsize += write_debug_data2 - (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword, - "source_corr (recnum)", dosizeonly); - - totsize += write_debug_data1 (src_command_sl.dst_b_src_command, - "source_corr (setlnum)", dosizeonly); + if (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword) + { + totsize += write_debug_header (&src_header.dst_a_source_corr_header, + "source corr", dosizeonly); - totsize += write_debug_data4 - (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong, - "source_corr (linenum)", dosizeonly); + totsize += write_debug_data1 (src_command_sf.dst_b_src_command, + "source_corr (src setfile)", dosizeonly); - totsize += write_debug_data1 (src_command_dl.dst_b_src_command, - "source_corr (deflines)", dosizeonly); + totsize += write_debug_data2 + (src_command_sf.dst_a_src_cmd_fields.dst_w_src_unsword, + "source_corr (fileid)", dosizeonly); - sprintf (buff, "source_corr (%d)", - src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword); - totsize += write_debug_data2 - (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly); + totsize += write_debug_data1 (src_command_sr.dst_b_src_command, + "source_corr (setrec)", dosizeonly); - while (linesleft > 0) - { - src_header.dst_a_source_corr_header.dst__header_length.dst_w_length - = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1; - src_header.dst_a_source_corr_header.dst__header_type.dst_w_type - = DST_K_SOURCE; - src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W; + totsize += write_debug_data2 + (src_command_sr.dst_a_src_cmd_fields.dst_w_src_unsword, + "source_corr (recnum)", dosizeonly); - if (linesleft > 65534) - linesleft = linesleft - 65534, linestodo = 65534; - else - linestodo = linesleft, linesleft = 0; + totsize += write_debug_data1 (src_command_sl.dst_b_src_command, + "source_corr (setlnum)", dosizeonly); - src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; + totsize += write_debug_data4 + (src_command_sl.dst_a_src_cmd_fields.dst_l_src_unslong, + "source_corr (linenum)", dosizeonly); - totsize += write_debug_header (&src_header.dst_a_source_corr_header, - "source corr", dosizeonly); totsize += write_debug_data1 (src_command_dl.dst_b_src_command, "source_corr (deflines)", dosizeonly); + sprintf (buff, "source_corr (%d)", src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword); totsize += write_debug_data2 (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, buff, dosizeonly); + + while (linesleft > 0) + { + src_header.dst_a_source_corr_header.dst__header_length.dst_w_length + = DST_K_SOURCE_CORR_HEADER_SIZE + 3 - 1; + src_header.dst_a_source_corr_header.dst__header_type.dst_w_type + = DST_K_SOURCE; + src_command_dl.dst_b_src_command = DST_K_SRC_DEFLINES_W; + + if (linesleft > 65534) + linesleft = linesleft - 65534, linestodo = 65534; + else + linestodo = linesleft, linesleft = 0; + + src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword = linestodo; + + totsize += write_debug_header (&src_header.dst_a_source_corr_header, + "source corr", dosizeonly); + totsize += write_debug_data1 (src_command_dl.dst_b_src_command, + "source_corr (deflines)", dosizeonly); + sprintf (buff, "source_corr (%d)", + src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword); + totsize += write_debug_data2 + (src_command_dl.dst_a_src_cmd_fields.dst_w_src_unsword, + buff, dosizeonly); + } } return totsize; } /* Output all the source correlation entries and return the size. Just return - the size if DOSIZEONLY is non-zero. */ + the size if DOSIZEONLY is nonzero. */ static int -write_srccorrs (dosizeonly) - int dosizeonly; +write_srccorrs (int dosizeonly) { unsigned int i; int totsize = 0; @@ -1273,15 +1266,13 @@ write_srccorrs (dosizeonly) totsize += write_srccorr (i, file_info_table[i], dosizeonly); return totsize; -} +} /* Output a marker (i.e. a label) for the beginning of a function, before the prologue. */ static void -vmsdbgout_begin_prologue (line, file) - unsigned int line; - const char *file; +vmsdbgout_begin_prologue (unsigned int line, const char *file) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; @@ -1290,9 +1281,8 @@ vmsdbgout_begin_prologue (line, file) if (debug_info_level > DINFO_LEVEL_NONE) { - current_funcdef_number++; ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, - current_funcdef_number); + current_function_funcdef_no); ASM_OUTPUT_LABEL (asm_out_file, label); } } @@ -1300,38 +1290,56 @@ vmsdbgout_begin_prologue (line, file) /* Output a marker (i.e. a label) for the beginning of a function, after the prologue. */ -void -vmsdbgout_after_prologue () +static void +vmsdbgout_end_prologue (unsigned int line, const char *file) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; + if (write_symbols == VMS_AND_DWARF2_DEBUG) + (*dwarf2_debug_hooks.end_prologue) (line, file); + if (debug_info_level > DINFO_LEVEL_TERSE) { ASM_GENERATE_INTERNAL_LABEL (label, FUNC_PROLOG_LABEL, - current_funcdef_number); + current_function_funcdef_no); ASM_OUTPUT_LABEL (asm_out_file, label); + + /* VMS PCA expects every PC range to correlate to some line and file. */ + vmsdbgout_source_line (line, file, 0, true); } } +/* No output for VMS debug, but make obligatory call to Dwarf2 debug */ + +static void +vmsdbgout_end_function (unsigned int line) +{ + if (write_symbols == VMS_AND_DWARF2_DEBUG) + (*dwarf2_debug_hooks.end_function) (line); +} + /* Output a marker (i.e. a label) for the absolute end of the generated code for a function definition. This gets called *after* the epilogue code has been generated. */ static void -vmsdbgout_end_epilogue () +vmsdbgout_end_epilogue (unsigned int line, const char *file) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; if (write_symbols == VMS_AND_DWARF2_DEBUG) - (*dwarf2_debug_hooks.end_epilogue) (); + (*dwarf2_debug_hooks.end_epilogue) (line, file); if (debug_info_level > DINFO_LEVEL_NONE) { /* Output a label to mark the endpoint of the code generated for this function. */ ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, - current_funcdef_number); + current_function_funcdef_no); ASM_OUTPUT_LABEL (asm_out_file, label); + + /* VMS PCA expects every PC range to correlate to some line and file. */ + vmsdbgout_source_line (line, file, 0, true); } } @@ -1339,37 +1347,32 @@ vmsdbgout_end_epilogue () a lexical block. */ static void -vmsdbgout_begin_block (line, blocknum) - register unsigned line; - register unsigned blocknum; +vmsdbgout_begin_block (register unsigned line, register unsigned blocknum) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.begin_block) (line, blocknum); if (debug_info_level > DINFO_LEVEL_TERSE) - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); + targetm.asm_out.internal_label (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); } /* Output a marker (i.e. a label) for the end of the generated code for a lexical block. */ static void -vmsdbgout_end_block (line, blocknum) - register unsigned line; - register unsigned blocknum; +vmsdbgout_end_block (register unsigned line, register unsigned blocknum) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.end_block) (line, blocknum); if (debug_info_level > DINFO_LEVEL_TERSE) - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); + targetm.asm_out.internal_label (asm_out_file, BLOCK_END_LABEL, blocknum); } /* Not implemented in VMS Debug. */ static bool -vmsdbgout_ignore_block (block) - tree block; +vmsdbgout_ignore_block (const_tree block) { bool retval = 0; @@ -1382,10 +1385,10 @@ vmsdbgout_ignore_block (block) /* Add an entry for function DECL into the func_table. */ static void -vmsdbgout_begin_function (decl) - tree decl; +vmsdbgout_begin_function (tree decl) { const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); + vms_func_ref fde; if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.begin_function) (decl); @@ -1393,12 +1396,16 @@ vmsdbgout_begin_function (decl) if (func_table_in_use == func_table_allocated) { func_table_allocated += FUNC_TABLE_INCREMENT; - func_table = (char **) xrealloc (func_table, - func_table_allocated * sizeof (char *)); + func_table + = (vms_func_ref) xrealloc (func_table, + func_table_allocated * sizeof (vms_func_node)); } /* Add the new entry to the end of the function name table. */ - func_table[func_table_in_use++] = xstrdup (name); + fde = &func_table[func_table_in_use++]; + fde->vms_func_name = xstrdup (name); + fde->funcdef_number = current_function_funcdef_no; + } static char fullname_buff [4096]; @@ -1407,8 +1414,7 @@ static char fullname_buff [4096]; in VMS syntax in order to be processed by VMS Debug. */ static char * -full_name (filename) - const char *filename; +full_name (const char *filename) { #ifdef VMS FILE *fp = fopen (filename, "r"); @@ -1439,54 +1445,22 @@ full_name (filename) all searches. */ static unsigned int -lookup_filename (file_name) - const char *file_name; +lookup_filename (const char *file_name) { static unsigned int last_file_lookup_index = 0; register char *fn; register unsigned i; - char *fnam; - long long cdt; - long ebk; - short ffb; - char rfo; + const char *fnam; char flen; - struct stat statbuf; - - if (stat (file_name, &statbuf) == 0) - { - long gmtoff; -#ifdef VMS - struct tm *ts; - - /* Adjust for GMT */ - ts = (struct tm *) localtime (&statbuf.st_ctime); - gmtoff = ts->tm_gmtoff; + long long cdt = 0; + long ebk = 0; + short ffb = 0; + char rfo = 0; + long siz = 0; + int ver = 0; - /* VMS has multiple file format types */ - rfo = statbuf.st_fab_rfm; -#else - /* Is GMT adjustment an issue with a cross-compiler? */ - gmtoff = 0; - - /* Assume stream LF type file */ - rfo = 2; -#endif - cdt = 10000000 * (statbuf.st_ctime + gmtoff + vms_epoch_offset); - ebk = statbuf.st_size / 512 + 1; - ffb = statbuf.st_size - ((statbuf.st_size / 512) * 512); - fnam = full_name (file_name); - flen = strlen (fnam); - } - else - { - cdt = 0; - ebk = 0; - ffb = 0; - rfo = 0; - fnam = (char *) ""; - flen = 0; - } + fnam = full_name (file_name); + flen = strlen (fnam); /* Check to see if the file name that was searched on the previous call matches this file name. If so, return the index. */ @@ -1508,16 +1482,20 @@ lookup_filename (file_name) } } - /* Prepare to add a new table entry by making sure there is enough space in + /* Prepare to add a new table entry by making sure there is enough space in the table to do so. If not, expand the current table. */ if (file_info_table_in_use == file_info_table_allocated) { file_info_table_allocated += FILE_TABLE_INCREMENT; - file_info_table - = (dst_file_info_ref) xrealloc (file_info_table, - (file_info_table_allocated - * sizeof (dst_file_info_entry))); + file_info_table = XRESIZEVEC (dst_file_info_entry, file_info_table, + file_info_table_allocated); + } + + if (vms_file_stats_name (file_name, &cdt, &siz, &rfo, &ver) == 0) + { + ebk = siz / 512 + 1; + ffb = siz - ((siz / 512) * 512); } /* Add the new entry to the end of the filename table. */ @@ -1538,29 +1516,26 @@ lookup_filename (file_name) 'line_info_table' for later output of the .debug_line section. */ static void -vmsdbgout_source_line (line, filename) - register unsigned line; - register const char *filename; +vmsdbgout_source_line (register unsigned line, register const char *filename, + int discriminator, bool is_stmt) { if (write_symbols == VMS_AND_DWARF2_DEBUG) - (*dwarf2_debug_hooks.source_line) (line, filename); + (*dwarf2_debug_hooks.source_line) (line, filename, discriminator, is_stmt); if (debug_info_level >= DINFO_LEVEL_TERSE) { dst_line_info_ref line_info; - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, - line_info_table_in_use); + targetm.asm_out.internal_label (asm_out_file, LINE_CODE_LABEL, + line_info_table_in_use); /* Expand the line info table if necessary. */ if (line_info_table_in_use == line_info_table_allocated) { line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; - line_info_table - = (dst_line_info_ref) xrealloc (line_info_table, - (line_info_table_allocated - * sizeof (dst_line_info_entry))); - } + line_info_table = XRESIZEVEC (dst_line_info_entry, line_info_table, + line_info_table_allocated); + } /* Add the new entry at the end of the line_info_table. */ line_info = &line_info_table[line_info_table_in_use++]; @@ -1575,9 +1550,7 @@ vmsdbgout_source_line (line, filename) At present, unimplemented. */ static void -vmsdbgout_start_source_file (lineno, filename) - unsigned int lineno; - const char *filename; +vmsdbgout_start_source_file (unsigned int lineno, const char *filename) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.start_source_file) (lineno, filename); @@ -1587,8 +1560,7 @@ vmsdbgout_start_source_file (lineno, filename) At present, unimplemented. */ static void -vmsdbgout_end_source_file (lineno) - unsigned int lineno ATTRIBUTE_UNUSED; +vmsdbgout_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.end_source_file) (lineno); @@ -1597,8 +1569,7 @@ vmsdbgout_end_source_file (lineno) /* Set up for Debug output at the start of compilation. */ static void -vmsdbgout_init (main_input_filename) - const char *main_input_filename; +vmsdbgout_init (const char *main_input_filename) { const char *language_string = lang_hooks.name; @@ -1612,22 +1583,18 @@ vmsdbgout_init (main_input_filename) primary_filename = main_input_filename; /* Allocate the initial hunk of the file_info_table. */ - file_info_table - = (dst_file_info_ref) xcalloc (FILE_TABLE_INCREMENT, - sizeof (dst_file_info_entry)); + file_info_table = XCNEWVEC (dst_file_info_entry, FILE_TABLE_INCREMENT); file_info_table_allocated = FILE_TABLE_INCREMENT; /* Skip the first entry - file numbers begin at 1 */ file_info_table_in_use = 1; - func_table = (char **) xcalloc (FUNC_TABLE_INCREMENT, sizeof (char *)); + func_table = (vms_func_ref) xcalloc (FUNC_TABLE_INCREMENT, sizeof (vms_func_node)); func_table_allocated = FUNC_TABLE_INCREMENT; func_table_in_use = 1; /* Allocate the initial hunk of the line_info_table. */ - line_info_table - = (dst_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT, - sizeof (dst_line_info_entry)); + line_info_table = XCNEWVEC (dst_line_info_entry, LINE_INFO_TABLE_INCREMENT); line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; /* zero-th entry is allocated, but unused */ line_info_table_in_use = 1; @@ -1645,10 +1612,7 @@ vmsdbgout_init (main_input_filename) else module_language = DST_K_UNKNOWN; - module_producer - = (char *) xmalloc (strlen (language_string) + 1 - + strlen (version_string) + 1); - sprintf (module_producer, "%s %s", language_string, version_string); + module_producer = concat (language_string, " ", version_string, NULL); ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); @@ -1657,9 +1621,16 @@ vmsdbgout_init (main_input_filename) /* Not implemented in VMS Debug. */ static void -vmsdbgout_define (lineno, buffer) - unsigned int lineno; - const char *buffer; +vmsdbgout_assembly_start (void) +{ + if (write_symbols == VMS_AND_DWARF2_DEBUG) + (*dwarf2_debug_hooks.assembly_start) (); +} + +/* Not implemented in VMS Debug. */ + +static void +vmsdbgout_define (unsigned int lineno, const char *buffer) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.define) (lineno, buffer); @@ -1668,9 +1639,7 @@ vmsdbgout_define (lineno, buffer) /* Not implemented in VMS Debug. */ static void -vmsdbgout_undef (lineno, buffer) - unsigned int lineno; - const char *buffer; +vmsdbgout_undef (unsigned int lineno, const char *buffer) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.undef) (lineno, buffer); @@ -1679,8 +1648,7 @@ vmsdbgout_undef (lineno, buffer) /* Not implemented in VMS Debug. */ static void -vmsdbgout_decl (decl) - tree decl; +vmsdbgout_decl (tree decl) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.function_decl) (decl); @@ -1689,8 +1657,7 @@ vmsdbgout_decl (decl) /* Not implemented in VMS Debug. */ static void -vmsdbgout_global_decl (decl) - tree decl; +vmsdbgout_global_decl (tree decl) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.global_decl) (decl); @@ -1699,8 +1666,7 @@ vmsdbgout_global_decl (decl) /* Not implemented in VMS Debug. */ static void -vmsdbgout_abstract_function (decl) - tree decl; +vmsdbgout_abstract_function (tree decl) { if (write_symbols == VMS_AND_DWARF2_DEBUG) (*dwarf2_debug_hooks.outlining_inline_function) (decl); @@ -1710,26 +1676,25 @@ vmsdbgout_abstract_function (decl) VMS Debug debugging info. */ static void -vmsdbgout_finish (input_filename) - const char *input_filename ATTRIBUTE_UNUSED; +vmsdbgout_finish (const char *main_input_filename ATTRIBUTE_UNUSED) { unsigned int i; int totsize; if (write_symbols == VMS_AND_DWARF2_DEBUG) - (*dwarf2_debug_hooks.finish) (input_filename); + (*dwarf2_debug_hooks.finish) (main_input_filename); if (debug_info_level == DINFO_LEVEL_NONE) return; /* Output a terminator label for the .text section. */ - text_section (); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0); + switch_to_section (text_section); + targetm.asm_out.internal_label (asm_out_file, TEXT_END_LABEL, 0); /* Output debugging information. Warning! Do not change the name of the .vmsdebug section without changing it in the assembler also. */ - named_section (NULL_TREE, ".vmsdebug", 0); + switch_to_section (get_named_section (NULL, ".vmsdebug", 0)); ASM_OUTPUT_ALIGN (asm_out_file, 0); totsize = write_modbeg (1); @@ -1757,4 +1722,237 @@ vmsdbgout_finish (input_filename) totsize = write_modend (1); write_modend (0); } -#endif /* VMS_DEBUGGING_INFO */ + +/* Need for both Dwarf2 on IVMS and VMS Debug on AVMS */ + +#ifdef VMS +#define __NEW_STARLET 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXPATH 256 + +/* descrip.h doesn't have everything ... */ +typedef struct fibdef* __fibdef_ptr32 __attribute__ (( mode (SI) )); +struct dsc$descriptor_fib +{ + unsigned int fib$l_len; + __fibdef_ptr32 fib$l_addr; +}; + +/* I/O Status Block. */ +struct IOSB +{ + unsigned short status, count; + unsigned int devdep; +}; + +static char *tryfile; + +/* Variable length string. */ +struct vstring +{ + short length; + char string[NAM$C_MAXRSS+1]; +}; + +static char filename_buff [MAXPATH]; +static char vms_filespec [MAXPATH]; + +/* Callback function for filespec style conversion. */ + +static int +translate_unix (char *name, int type ATTRIBUTE_UNUSED) +{ + strncpy (filename_buff, name, MAXPATH); + filename_buff [MAXPATH - 1] = (char) 0; + return 0; +} + +/* Wrapper for DECC function that converts a Unix filespec + to VMS style filespec. */ + +static char * +to_vms_file_spec (char *filespec) +{ + strncpy (vms_filespec, "", MAXPATH); + decc$to_vms (filespec, translate_unix, 1, 1); + strncpy (vms_filespec, filename_buff, MAXPATH); + + vms_filespec [MAXPATH - 1] = (char) 0; + + return vms_filespec; +} + +#else +#define VMS_EPOCH_OFFSET 35067168000000000 +#define VMS_GRANULARITY_FACTOR 10000000 +#endif + +/* Return VMS file date, size, format, version given a name. */ + +int +vms_file_stats_name (const char *filename, long long *cdt, long *siz, char *rfo, + int *ver) +{ +#ifdef VMS + struct FAB fab; + struct NAM nam; + + unsigned long long create; + FAT recattr; + char ascnamebuff [256]; + + ATRDEF atrlst[] + = { + { ATR$S_CREDATE, ATR$C_CREDATE, &create }, + { ATR$S_RECATTR, ATR$C_RECATTR, &recattr }, + { ATR$S_ASCNAME, ATR$C_ASCNAME, &ascnamebuff }, + { 0, 0, 0} + }; + + FIBDEF fib; + struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib}; + + struct IOSB iosb; + + long status; + unsigned short chan; + + struct vstring file; + struct dsc$descriptor_s filedsc + = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string}; + struct vstring device; + struct dsc$descriptor_s devicedsc + = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string}; + struct vstring result; + struct dsc$descriptor_s resultdsc + = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string}; + + if (strcmp (filename, "") == 0 + || strcmp (filename, "") == 0) + { + if (cdt) + *cdt = 0; + + if (siz) + *siz = 0; + + if (rfo) + *rfo = 0; + + if (ver) + *ver = 0; + + return 0; + } + + tryfile = to_vms_file_spec (filename); + + /* Allocate and initialize a FAB and NAM structures. */ + fab = cc$rms_fab; + nam = cc$rms_nam; + + nam.nam$l_esa = file.string; + nam.nam$b_ess = NAM$C_MAXRSS; + nam.nam$l_rsa = result.string; + nam.nam$b_rss = NAM$C_MAXRSS; + fab.fab$l_fna = tryfile; + fab.fab$b_fns = strlen (tryfile); + fab.fab$l_nam = &nam; + + /* Validate filespec syntax and device existence. */ + status = SYS$PARSE (&fab, 0, 0); + if ((status & 1) != 1) + return 1; + + file.string[nam.nam$b_esl] = 0; + + /* Find matching filespec. */ + status = SYS$SEARCH (&fab, 0, 0); + if ((status & 1) != 1) + return 1; + + file.string[nam.nam$b_esl] = 0; + result.string[result.length=nam.nam$b_rsl] = 0; + + /* Get the device name and assign an IO channel. */ + strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev); + devicedsc.dsc$w_length = nam.nam$b_dev; + chan = 0; + status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0); + if ((status & 1) != 1) + return 1; + + /* Initialize the FIB and fill in the directory id field. */ + memset (&fib, 0, sizeof (fib)); + fib.fib$w_did[0] = nam.nam$w_did[0]; + fib.fib$w_did[1] = nam.nam$w_did[1]; + fib.fib$w_did[2] = nam.nam$w_did[2]; + fib.fib$l_acctl = 0; + fib.fib$l_wcc = 0; + strcpy (file.string, (strrchr (result.string, ']') + 1)); + filedsc.dsc$w_length = strlen (file.string); + result.string[result.length = 0] = 0; + + /* Open and close the file to fill in the attributes. */ + status + = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0, + &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0); + if ((status & 1) != 1) + return 1; + if ((iosb.status & 1) != 1) + return 1; + + result.string[result.length] = 0; + status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0, + &atrlst, 0); + if ((status & 1) != 1) + return 1; + if ((iosb.status & 1) != 1) + return 1; + + /* Deassign the channel and exit. */ + status = SYS$DASSGN (chan); + if ((status & 1) != 1) + return 1; + + if (cdt) *cdt = create; + if (siz) *siz = (512 * 65536 * recattr.fat$w_efblkh) + + (512 * (recattr.fat$w_efblkl - 1)) + + recattr.fat$w_ffbyte; + if (rfo) *rfo = recattr.fat$v_rtype; + if (ver) *ver = strtol (strrchr (ascnamebuff, ';')+1, 0, 10); + + return 0; +#else + struct stat buff; + + if ((stat (filename, &buff)) != 0) + return 1; + + if (cdt) + *cdt = (long long) (buff.st_mtime * VMS_GRANULARITY_FACTOR) + + VMS_EPOCH_OFFSET; + + if (siz) + *siz = buff.st_size; + + if (rfo) + *rfo = 2; /* Stream LF format */ + + if (ver) + *ver = 1; + + return 0; +#endif +} +#endif