OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [vmsdbgout.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.