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