2001-02-18 Kazu Hirata <kazu@hxi.com>
[external/binutils.git] / bfd / vms-misc.c
1 /* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2    EVAX (openVMS/Alpha) files.
3    Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
4
5    Written by Klaus K"ampf (kkaempf@rmi.de)
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #if __STDC__
22 #include <stdarg.h>
23 #endif
24
25 #include "bfd.h"
26 #include "sysdep.h"
27 #include "bfdlink.h"
28 #include "libbfd.h"
29
30 #include "vms.h"
31
32 /*-----------------------------------------------------------------------------*/
33 #if VMS_DEBUG
34 /* debug functions */
35
36 /* debug function for all vms extensions
37    evaluates environment variable VMS_DEBUG for a
38    numerical value on the first call
39    all error levels below this value are printed
40
41    levels:
42    1    toplevel bfd calls (functions from the bfd vector)
43    2    functions called by bfd calls
44    ...
45    9    almost everything
46
47    level is also identation level. Indentation is performed
48    if level > 0
49         */
50
51 #if __STDC__
52 void
53 _bfd_vms_debug (int level, char *format, ...)
54 {
55   static int min_level = -1;
56   static FILE *output = NULL;
57   char *eptr;
58   va_list args;
59   int abslvl = (level > 0)?level:-level;
60
61   if (min_level == -1)
62     {
63       if ((eptr = getenv("VMS_DEBUG")) != NULL)
64         {
65           min_level = atoi(eptr);
66           output = stderr;
67         }
68       else
69         min_level = 0;
70     }
71   if (output == NULL)
72     return;
73   if (abslvl > min_level)
74     return;
75
76   while (--level>0)
77     fprintf (output, " ");
78   va_start(args, format);
79   vfprintf (output, format, args);
80   fflush(output);
81   va_end(args);
82
83   return;
84 }
85
86 #else /* not __STDC__ */
87
88 void
89 _bfd_vms_debug (level, format, a1, a2, a3, a4, a5, a6)
90      int level;
91      char *format;
92      long a1; long a2; long a3;
93      long a4; long a5; long a6;
94 {
95   static int min_level = -1;
96   static FILE *output = NULL;
97   char *eptr;
98
99   if (min_level == -1)
100     {
101       if ((eptr = getenv("VMS_DEBUG")) != NULL)
102         {
103           min_level = atoi(eptr);
104           output = stderr;
105         }
106       else
107         min_level = 0;
108     }
109   if (output == NULL)
110     return;
111   if (level > min_level)
112     return;
113
114   while (--level>0)
115     fprintf (output, " ");
116   fprintf (output, format, a1, a2, a3, a4, a5, a6);
117   fflush(output);
118
119   return;
120 }
121 #endif /* __STDC__ */
122
123 /* a debug function
124    hex dump 'size' bytes starting at 'ptr'  */
125
126 void
127 _bfd_hexdump (level, ptr, size, offset)
128      int level;
129      unsigned char *ptr;
130      int size;
131      int offset;
132 {
133   unsigned char *lptr = ptr;
134   int count = 0;
135   long start = offset;
136
137   while (size-- > 0)
138     {
139       if ((count%16) == 0)
140         vms_debug (level, "%08lx:", start);
141       vms_debug (-level, " %02x", *ptr++);
142       count++;
143       start++;
144       if (size == 0)
145         {
146           while ((count%16) != 0)
147             {
148               vms_debug (-level, "   ");
149               count++;
150             }
151         }
152       if ((count%16) == 0)
153         {
154           vms_debug (-level, " ");
155           while (lptr < ptr)
156             {
157               vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
158               lptr++;
159             }
160           vms_debug (-level, "\n");
161         }
162     }
163   if ((count%16) != 0)
164     vms_debug (-level, "\n");
165
166   return;
167 }
168 #endif
169 \f
170 /* hash functions
171
172    These are needed when reading an object file.  */
173
174 /* allocate new vms_hash_entry
175    keep the symbol name and a pointer to the bfd symbol in the table  */
176
177 struct bfd_hash_entry *
178 _bfd_vms_hash_newfunc (entry, table, string)
179      struct bfd_hash_entry *entry;
180      struct bfd_hash_table *table;
181      const char *string;
182 {
183   vms_symbol_entry *ret;
184
185 #if VMS_DEBUG
186   vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
187 #endif
188
189   if (entry == (struct bfd_hash_entry *)NULL)
190     {
191       ret = (vms_symbol_entry *)
192               bfd_hash_allocate (table, sizeof (vms_symbol_entry));
193       if (ret == (vms_symbol_entry *) NULL)
194         {
195           bfd_set_error (bfd_error_no_memory);
196           return (struct bfd_hash_entry *)NULL;
197         }
198       entry = (struct bfd_hash_entry *) ret;
199     }
200
201   /* Call the allocation method of the base class.  */
202
203   ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
204 #if VMS_DEBUG
205   vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
206 #endif
207
208   ret->symbol = (asymbol *)NULL;
209
210   return (struct bfd_hash_entry *)ret;
211 }
212 \f
213 /* object file input functions */
214
215 /* Return type and length from record header (buf) on Alpha.  */
216
217 void
218 _bfd_vms_get_header_values (abfd, buf, type, length)
219      bfd *abfd ATTRIBUTE_UNUSED;
220      unsigned char *buf;
221      int *type;
222      int *length;
223 {
224   if (type != 0)
225     *type = bfd_getl16 (buf);
226   buf += 2;
227   if (length != 0)
228     *length = bfd_getl16 (buf);
229
230 #if VMS_DEBUG
231   vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
232 #endif
233
234   return;
235 }
236
237 /* Get next record from object file to vms_buf
238    set PRIV(buf_size) and return it
239
240    this is a little tricky since it should be portable.
241
242    the openVMS object file has 'variable length' which means that
243    read() returns data in chunks of (hopefully) correct and expected
244    size. The linker (and other tools on vms) depend on that. Unix doesn't
245    know about 'formatted' files, so reading and writing such an object
246    file in a unix environment is not trivial.
247
248    With the tool 'file' (available on all vms ftp sites), one
249    can view and change the attributes of a file. Changing from
250    'variable length' to 'fixed length, 512 bytes' reveals the
251    record length at the first 2 bytes of every record. The same
252    happens during the transfer of object files from vms to unix,
253    at least with ucx, dec's implementation of tcp/ip.
254
255    The vms format repeats the length at bytes 2 & 3 of every record.
256
257    On the first call (file_format == FF_UNKNOWN) we check if
258    the first and the third byte pair (!) of the record match.
259    If they do it's an object file in an unix environment or with
260    wrong attributes (FF_FOREIGN), else we should be in a vms
261    environment where read() returns the record size (FF_NATIVE).
262
263    reading is always done in 2 steps.
264    first just the record header is read and the length extracted
265    by get_header_values
266    then the read buffer is adjusted and the remaining bytes are
267    read in.
268
269    all file i/o is always done on even file positions  */
270
271 int
272 _bfd_vms_get_record (abfd)
273      bfd *abfd;
274 {
275   int test_len, test_start, remaining;
276   unsigned char *vms_buf;
277
278 #if VMS_DEBUG
279   vms_debug (8, "_bfd_vms_get_record\n");
280 #endif
281
282   /* minimum is 6 bytes on Alpha
283      (2 bytes length, 2 bytes record id, 2 bytes length repeated)
284
285      on VAX there's no length information in the record
286      so start with OBJ_S_C_MAXRECSIZ  */
287
288   if (PRIV (buf_size) == 0)
289     {
290       if (PRIV (is_vax))
291         {
292           PRIV (vms_buf) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ);
293           PRIV (buf_size) = OBJ_S_C_MAXRECSIZ;
294           PRIV (file_format) = FF_VAX;
295         }
296       else
297         PRIV (vms_buf) = (unsigned char *) malloc (6);
298     }
299
300   vms_buf = PRIV (vms_buf);
301
302   if (vms_buf == 0)
303     {
304       bfd_set_error (bfd_error_no_memory);
305       return -1;
306     }
307
308   switch (PRIV (file_format))
309     {
310     case FF_UNKNOWN:
311     case FF_FOREIGN:
312       test_len = 6;                     /* probe 6 bytes */
313       test_start = 2;                   /* where the record starts */
314       break;
315
316     case FF_NATIVE:
317       test_len = 4;
318       test_start = 0;
319       break;
320
321     default:
322     case FF_VAX:
323       test_len = 0;
324       test_start = 0;
325       break;
326     }
327
328   /* skip odd alignment byte  */
329
330   if (bfd_tell (abfd) & 1)
331     {
332       if (bfd_read (PRIV (vms_buf), 1, 1, abfd) != 1)
333         {
334           bfd_set_error (bfd_error_file_truncated);
335           return 0;
336         }
337     }
338
339   /* read the record header on Alpha.  */
340
341   if ((test_len != 0)
342       && (bfd_read (PRIV (vms_buf), 1, test_len, abfd)
343           != (bfd_size_type) test_len))
344     {
345       bfd_set_error (bfd_error_file_truncated);
346       return 0;
347     }
348
349   /* check file format on first call  */
350
351   if (PRIV (file_format) == FF_UNKNOWN)
352     {                                           /* record length repeats ? */
353       if ( (vms_buf[0] == vms_buf[4])
354         && (vms_buf[1] == vms_buf[5]))
355         {
356           PRIV (file_format) = FF_FOREIGN;      /* Y: foreign environment */
357           test_start = 2;
358         }
359       else
360         {
361           PRIV (file_format) = FF_NATIVE;       /* N: native environment */
362           test_start = 0;
363         }
364     }
365
366   if (PRIV (is_vax))
367     {
368       PRIV (rec_length) = bfd_read (vms_buf, 1, PRIV (buf_size), abfd);
369       if (PRIV (rec_length) <= 0)
370         {
371           bfd_set_error (bfd_error_file_truncated);
372           return 0;
373         }
374       PRIV (vms_rec) = vms_buf;
375     }
376   else          /* Alpha  */
377     {
378       /* extract vms record length  */
379
380       _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
381                                   &PRIV (rec_length));
382
383       if (PRIV (rec_length) <= 0)
384         {
385           bfd_set_error (bfd_error_file_truncated);
386           return 0;
387         }
388
389       /* that's what the linker manual says  */
390
391       if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
392         {
393           bfd_set_error (bfd_error_file_truncated);
394           return 0;
395         }
396
397       /* adjust the buffer  */
398
399       if (PRIV (rec_length) > PRIV (buf_size))
400         {
401           PRIV (vms_buf) = (unsigned char *) realloc (vms_buf, PRIV (rec_length));
402           vms_buf = PRIV (vms_buf);
403           if (vms_buf == 0)
404             {
405               bfd_set_error (bfd_error_no_memory);
406               return -1;
407             }
408           PRIV (buf_size) = PRIV (rec_length);
409         }
410
411       /* read the remaining record  */
412
413       remaining = PRIV (rec_length) - test_len + test_start;
414
415 #if VMS_DEBUG
416       vms_debug (10, "bfd_read remaining %d\n", remaining);
417 #endif
418       if (bfd_read (vms_buf + test_len, 1, remaining, abfd) !=
419           (bfd_size_type) remaining)
420         {
421           bfd_set_error (bfd_error_file_truncated);
422           return 0;
423         }
424       PRIV (vms_rec) = vms_buf + test_start;
425     }
426
427 #if VMS_DEBUG
428   vms_debug (11, "bfd_read rec_length %d\n", PRIV (rec_length));
429 #endif
430
431   return PRIV (rec_length);
432 }
433
434 /* get next vms record from file
435    update vms_rec and rec_length to new (remaining) values  */
436
437 int
438 _bfd_vms_next_record (abfd)
439      bfd *abfd;
440 {
441 #if VMS_DEBUG
442   vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
443               PRIV (rec_length), PRIV (rec_size));
444 #endif
445
446   if (PRIV (rec_length) > 0)
447     {
448       PRIV (vms_rec) += PRIV (rec_size);
449     }
450   else
451     {
452       if (_bfd_vms_get_record (abfd) <= 0)
453         return -1;
454     }
455
456   if (!PRIV (vms_rec) || !PRIV (vms_buf)
457       || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
458     return -1;
459
460   if (PRIV (is_vax))
461     {
462       PRIV (rec_type) = *(PRIV (vms_rec));
463       PRIV (rec_size) = PRIV (rec_length);
464     }
465   else
466     {
467       _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
468                                   &PRIV (rec_size));
469     }
470   PRIV (rec_length) -= PRIV (rec_size);
471
472 #if VMS_DEBUG
473   vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
474               PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
475               PRIV (rec_type));
476 #endif
477
478   return PRIV (rec_type);
479 }
480 \f
481 /* Copy sized string (string with fixed length) to new allocated area
482    size is string length (size of record)  */
483
484 char *
485 _bfd_vms_save_sized_string (str, size)
486      unsigned char *str;
487      int size;
488 {
489   char *newstr = bfd_malloc (size + 1);
490
491   if (newstr == NULL)
492     return 0;
493   strncpy (newstr, (char *)str, size);
494   newstr[size] = 0;
495
496   return newstr;
497 }
498
499 /* Copy counted string (string with length at first byte) to new allocated area
500    ptr points to length byte on entry  */
501
502 char *
503 _bfd_vms_save_counted_string (ptr)
504      unsigned char *ptr;
505 {
506   int len = *ptr++;
507
508   return _bfd_vms_save_sized_string (ptr, len);
509 }
510 \f
511 /* stack routines for vms ETIR commands */
512
513 /* Push value and section index  */
514
515 void
516 _bfd_vms_push (abfd, val, psect)
517      bfd *abfd;
518      uquad val;
519      int psect;
520 {
521   static int last_psect;
522
523 #if VMS_DEBUG
524   vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr));
525 #endif
526
527   if (psect >= 0)
528     last_psect = psect;
529
530   PRIV (stack[PRIV (stackptr)]).value = val;
531   PRIV (stack[PRIV (stackptr)]).psect = last_psect;
532   PRIV (stackptr)++;
533   if (PRIV (stackptr) >= STACKSIZE)
534     {
535       bfd_set_error (bfd_error_bad_value);
536       (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
537       exit (1);
538     }
539   return;
540 }
541
542 /* Pop value and section index  */
543
544 uquad
545 _bfd_vms_pop (abfd, psect)
546      bfd *abfd;
547      int *psect;
548 {
549   uquad value;
550
551   if (PRIV (stackptr) == 0)
552     {
553       bfd_set_error (bfd_error_bad_value);
554       (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
555       exit (1);
556     }
557   PRIV (stackptr)--;
558   value = PRIV (stack[PRIV (stackptr)]).value;
559   if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
560     *psect = PRIV (stack[PRIV (stackptr)]).psect;
561
562 #if VMS_DEBUG
563   vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
564 #endif
565
566   return value;
567 }
568 \f
569 /* object file output functions */
570
571 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
572    which we can't use directly. So we save the little chunks in linked
573    lists (one per section) and write them later.  */
574
575 /* Add a new vms_section structure to vms_section_table
576    - forward chaining -  */
577
578 static vms_section *
579 add_new_contents (abfd, section)
580      bfd *abfd;
581      sec_ptr section;
582 {
583   vms_section *sptr, *newptr;
584
585   sptr = PRIV (vms_section_table)[section->index];
586   if (sptr != NULL)
587     return sptr;
588
589   newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
590   if (newptr == (vms_section *) NULL)
591     return NULL;
592   newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
593   if (newptr->contents == (unsigned char *)NULL)
594     return NULL;
595   newptr->offset = 0;
596   newptr->size = section->_raw_size;
597   newptr->next = 0;
598   PRIV (vms_section_table)[section->index] = newptr;
599   return newptr;
600 }
601
602 /* Save section data & offset to an vms_section structure
603    vms_section_table[] holds the vms_section chain  */
604
605 boolean
606 _bfd_save_vms_section (abfd, section, data, offset, count)
607      bfd *abfd;
608      sec_ptr section;
609      PTR data;
610      file_ptr offset;
611      bfd_size_type count;
612 {
613   vms_section *sptr;
614
615   if (section->index >= VMS_SECTION_COUNT)
616     {
617       bfd_set_error (bfd_error_nonrepresentable_section);
618       return false;
619     }
620   if (count == (bfd_size_type)0)
621     return true;
622   sptr = add_new_contents (abfd, section);
623   if (sptr == NULL)
624     return false;
625   memcpy (sptr->contents + offset, data, (size_t) count);
626
627   return true;
628 }
629
630 /* Get vms_section pointer to saved contents for section # index  */
631
632 vms_section *
633 _bfd_get_vms_section (abfd, index)
634      bfd *abfd;
635      int index;
636 {
637   if (index >=  VMS_SECTION_COUNT)
638     {
639       bfd_set_error (bfd_error_nonrepresentable_section);
640       return NULL;
641     }
642   return PRIV (vms_section_table)[index];
643 }
644 \f
645 /* Object output routines  */
646
647 /* Begin new record or record header
648    write 2 bytes rectype
649    write 2 bytes record length (filled in at flush)
650    write 2 bytes header type (ommitted if rechead == -1)  */
651
652 void
653 _bfd_vms_output_begin (abfd, rectype, rechead)
654      bfd *abfd;
655      int rectype;
656      int rechead;
657 {
658 #if VMS_DEBUG
659   vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
660               rechead);
661 #endif
662
663   _bfd_vms_output_short (abfd,rectype);
664
665   /* save current output position to fill in lenght later  */
666
667   if (PRIV (push_level) > 0)
668     PRIV (length_pos) = PRIV (output_size);
669
670 #if VMS_DEBUG
671   vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
672               PRIV (length_pos));
673 #endif
674
675   _bfd_vms_output_short (abfd,0);               /* placeholder for length */
676
677   if (rechead != -1)
678     _bfd_vms_output_short (abfd,rechead);
679
680   return;
681 }
682
683 /* Set record/subrecord alignment  */
684
685 void
686 _bfd_vms_output_alignment (abfd, alignto)
687      bfd *abfd;
688      int alignto;
689 {
690 #if VMS_DEBUG
691   vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
692 #endif
693
694   PRIV (output_alignment) = alignto;
695   return;
696 }
697
698 /* Prepare for subrecord fields  */
699
700 void
701 _bfd_vms_output_push (abfd)
702      bfd *abfd;
703 {
704 #if VMS_DEBUG
705   vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size));
706 #endif
707
708   PRIV (push_level)++;
709   PRIV (pushed_size) = PRIV (output_size);
710   return;
711 }
712
713 /* End of subrecord fields  */
714
715 void
716 _bfd_vms_output_pop (abfd)
717      bfd *abfd;
718 {
719 #if VMS_DEBUG
720   vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size));
721 #endif
722
723   _bfd_vms_output_flush (abfd);
724   PRIV (length_pos) = 2;
725
726 #if VMS_DEBUG
727   vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
728 #endif
729
730   PRIV (pushed_size) = 0;
731   PRIV (push_level)--;
732   return;
733 }
734
735 /* Flush unwritten output, ends current record  */
736
737 void
738 _bfd_vms_output_flush (abfd)
739      bfd *abfd;
740 {
741   int real_size = PRIV (output_size);
742   int aligncount;
743   int length;
744
745 #if VMS_DEBUG
746   vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
747               real_size, PRIV (pushed_size), PRIV (length_pos));
748 #endif
749
750   if (PRIV (push_level) > 0)
751     length = real_size - PRIV (pushed_size);
752   else
753     length = real_size;
754
755   if (length == 0)
756     return;
757   aligncount = (PRIV (output_alignment)
758                 - (length % PRIV (output_alignment))) % PRIV (output_alignment);
759
760 #if VMS_DEBUG
761   vms_debug (6, "align: adding %d bytes\n", aligncount);
762 #endif
763
764   while (aligncount-- > 0)
765     {
766       PRIV (output_buf)[real_size++] = 0;
767 #if 0
768       /* this is why I *love* vms: inconsistency :-}
769          alignment is added to the subrecord length
770          but not to the record length  */
771       if (PRIV (push_level) > 0)
772 #endif
773         length++;
774     }
775
776   /* put length to buffer  */
777   PRIV (output_size) = PRIV (length_pos);
778   _bfd_vms_output_short (abfd, (unsigned int)length);
779
780   if (PRIV (push_level) == 0)
781     {
782 #ifndef VMS
783         /* write length first, see FF_FOREIGN in the input routines */
784       fwrite (PRIV (output_buf)+2, 2, 1, (FILE *)abfd->iostream);
785 #endif
786       fwrite (PRIV (output_buf), real_size, 1, (FILE *)abfd->iostream);
787
788       PRIV (output_size) = 0;
789     }
790   else
791     {
792       PRIV (output_size) = real_size;
793       PRIV (pushed_size) = PRIV (output_size);
794     }
795
796   return;
797 }
798
799 /* End record output  */
800
801 void
802 _bfd_vms_output_end (abfd)
803      bfd *abfd;
804 {
805 #if VMS_DEBUG
806   vms_debug (6, "_bfd_vms_output_end\n");
807 #endif
808
809   _bfd_vms_output_flush (abfd);
810
811   return;
812 }
813
814 /* check remaining buffer size
815
816    return what's left.  */
817
818 int
819 _bfd_vms_output_check (abfd, size)
820     bfd *abfd;
821     int size;
822 {
823 #if VMS_DEBUG
824   vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
825 #endif
826
827   return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
828 }
829
830 /* Output byte (8 bit) value  */
831
832 void
833 _bfd_vms_output_byte (abfd, value)
834      bfd *abfd;
835      unsigned int value;
836 {
837 #if VMS_DEBUG
838   vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
839 #endif
840
841   bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
842   PRIV (output_size) += 1;
843   return;
844 }
845
846 /* Output short (16 bit) value  */
847
848 void
849 _bfd_vms_output_short (abfd, value)
850      bfd *abfd;
851      unsigned int value;
852 {
853 #if VMS_DEBUG
854   vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
855 #endif
856
857   bfd_put_16 (abfd, value & 0xffff, PRIV (output_buf) + PRIV (output_size));
858   PRIV (output_size) += 2;
859   return;
860 }
861
862 /* Output long (32 bit) value  */
863
864 void
865 _bfd_vms_output_long (abfd, value)
866      bfd *abfd;
867      unsigned long value;
868 {
869 #if VMS_DEBUG
870   vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
871 #endif
872
873   bfd_put_32 (abfd, value, PRIV (output_buf) + PRIV (output_size));
874   PRIV (output_size) += 4;
875   return;
876 }
877
878 /* Output quad (64 bit) value  */
879
880 void
881 _bfd_vms_output_quad (abfd, value)
882      bfd *abfd;
883      uquad value;
884 {
885 #if VMS_DEBUG
886   vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
887 #endif
888
889   bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
890   PRIV (output_size) += 8;
891   return;
892 }
893
894 /* Output c-string as counted string  */
895
896 void
897 _bfd_vms_output_counted (abfd, value)
898      bfd *abfd;
899      char *value;
900 {
901 int len;
902
903 #if VMS_DEBUG
904   vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
905 #endif
906
907   len = strlen (value);
908   if (len == 0)
909     {
910       (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
911       return;
912     }
913   if (len > 255)
914     {
915       (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
916       return;
917     }
918   _bfd_vms_output_byte (abfd, len & 0xff);
919   _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
920 }
921
922 /* Output character area  */
923
924 void
925 _bfd_vms_output_dump (abfd, data, length)
926      bfd *abfd;
927      unsigned char *data;
928      int length;
929 {
930 #if VMS_DEBUG
931   vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
932 #endif
933
934   if (length == 0)
935     return;
936
937   memcpy (PRIV (output_buf) + PRIV (output_size), data, length);
938   PRIV (output_size) += length;
939
940   return;
941 }
942
943 /* Output count bytes of value  */
944
945 void
946 _bfd_vms_output_fill (abfd, value, count)
947      bfd *abfd;
948      int value;
949      int count;
950 {
951 #if VMS_DEBUG
952   vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
953 #endif
954
955   if (count == 0)
956     return;
957   memset (PRIV (output_buf) + PRIV (output_size), value, count);
958   PRIV (output_size) += count;
959
960   return;
961 }
962
963 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly  ERY*/
964
965 static int
966 hash_string (ptr)
967      const char *ptr;
968 {
969   register const unsigned char *p = (unsigned char *) ptr;
970   register const unsigned char *end = p + strlen (ptr);
971   register unsigned char c;
972   register int hash = 0;
973
974   while (p != end)
975     {
976       c = *p++;
977       hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
978     }
979   return hash;
980 }
981
982 /* Generate a length-hashed VMS symbol name (limited to maxlen chars).  */
983
984 char *
985 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
986      bfd *abfd;
987      const char *in;
988      int maxlen;
989 {
990   long int result;
991   int in_len;
992   char *new_name;
993   const char *old_name;
994   int i;
995   static char outbuf[EOBJ_S_C_SYMSIZ+1];
996   char *out = outbuf;
997
998 #if VMS_DEBUG
999   vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1000 #endif
1001
1002   if (maxlen > EOBJ_S_C_SYMSIZ)
1003     maxlen = EOBJ_S_C_SYMSIZ;
1004
1005   new_name = out;               /* save this for later.  */
1006
1007   /* We may need to truncate the symbol, save the hash for later.  */
1008
1009   in_len = strlen (in);
1010
1011   result = (in_len > maxlen) ? hash_string (in) : 0;
1012
1013   old_name = in;
1014
1015   /* Do the length checking.  */
1016
1017   if (in_len <= maxlen)
1018     {
1019       i = in_len;
1020     }
1021   else
1022     {
1023       if (PRIV (flag_hash_long_names))
1024         i = maxlen-9;
1025       else
1026         i = maxlen;
1027     }
1028
1029   strncpy (out, in, i);
1030   in += i;
1031   out += i;
1032
1033   if ((in_len > maxlen)
1034       && PRIV (flag_hash_long_names))
1035     sprintf (out, "_%08lx", result);
1036   else
1037     *out = 0;
1038
1039 #if VMS_DEBUG
1040   vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1041 #endif
1042
1043   if (in_len > maxlen
1044         && PRIV (flag_hash_long_names)
1045         && PRIV (flag_show_after_trunc))
1046     printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1047
1048   return outbuf;
1049 }
1050
1051 /* Allocate and initialize a new symbol.  */
1052
1053 static asymbol *
1054 new_symbol (abfd, name)
1055      bfd *abfd;
1056      char *name;
1057 {
1058   asymbol *symbol;
1059
1060 #if VMS_DEBUG
1061   _bfd_vms_debug (7,  "new_symbol %s\n", name);
1062 #endif
1063
1064   symbol = _bfd_vms_make_empty_symbol (abfd);
1065   if (symbol == 0)
1066     return symbol;
1067   symbol->name = name;
1068   symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1069
1070   return symbol;
1071 }
1072
1073 /* Allocate and enter a new private symbol.  */
1074
1075 vms_symbol_entry *
1076 _bfd_vms_enter_symbol (abfd, name)
1077      bfd *abfd;
1078      char *name;
1079 {
1080   vms_symbol_entry *entry;
1081
1082 #if VMS_DEBUG
1083   _bfd_vms_debug (6,  "_bfd_vms_enter_symbol %s\n", name);
1084 #endif
1085
1086   entry = (vms_symbol_entry *)
1087           bfd_hash_lookup (PRIV (vms_symbol_table), name, false, false);
1088   if (entry == 0)
1089     {
1090 #if VMS_DEBUG
1091       _bfd_vms_debug (8,  "creating hash entry for %s\n", name);
1092 #endif
1093       entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV (vms_symbol_table), name, true, false);
1094       if (entry != 0)
1095         {
1096           asymbol *symbol;
1097           symbol = new_symbol (abfd, name);
1098           if (symbol != 0)
1099             {
1100               entry->symbol = symbol;
1101               PRIV (gsd_sym_count)++;
1102               abfd->symcount++;
1103             }
1104           else
1105             entry = 0;
1106         }
1107       else
1108         (*_bfd_error_handler) (_("failed to enter %s"), name);
1109     }
1110   else
1111     {
1112 #if VMS_DEBUG
1113       _bfd_vms_debug (8,  "found hash entry for %s\n", name);
1114 #endif
1115     }
1116
1117 #if VMS_DEBUG
1118   _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1119 #endif
1120   return entry;
1121 }