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