* vms-tir.c: Add missing prototypes.
[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, 2000, 2001
4    Free Software Foundation, Inc.
5
6    Written by Klaus K"ampf (kkaempf@rmi.de)
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
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 static vms_section *add_new_contents PARAMS ((bfd *, sec_ptr));
34 static int hash_string PARAMS ((const char *));
35 static asymbol *new_symbol PARAMS ((bfd *, char *));
36   
37 /*-----------------------------------------------------------------------------*/
38 #if VMS_DEBUG
39 /* debug functions */
40
41 /* debug function for all vms extensions
42    evaluates environment variable VMS_DEBUG for a
43    numerical value on the first call
44    all error levels below this value are printed
45
46    levels:
47    1    toplevel bfd calls (functions from the bfd vector)
48    2    functions called by bfd calls
49    ...
50    9    almost everything
51
52    level is also identation level. Indentation is performed
53    if level > 0
54         */
55
56 #if __STDC__
57 void
58 _bfd_vms_debug (int level, char *format, ...)
59 {
60   static int min_level = -1;
61   static FILE *output = NULL;
62   char *eptr;
63   va_list args;
64   int abslvl = (level > 0)?level:-level;
65
66   if (min_level == -1)
67     {
68       if ((eptr = getenv("VMS_DEBUG")) != NULL)
69         {
70           min_level = atoi(eptr);
71           output = stderr;
72         }
73       else
74         min_level = 0;
75     }
76   if (output == NULL)
77     return;
78   if (abslvl > min_level)
79     return;
80
81   while (--level>0)
82     fprintf (output, " ");
83   va_start(args, format);
84   vfprintf (output, format, args);
85   fflush(output);
86   va_end(args);
87
88   return;
89 }
90
91 #else /* not __STDC__ */
92
93 void
94 _bfd_vms_debug (level, format, a1, a2, a3, a4, a5, a6)
95      int level;
96      char *format;
97      long a1; long a2; long a3;
98      long a4; long a5; long a6;
99 {
100   static int min_level = -1;
101   static FILE *output = NULL;
102   char *eptr;
103
104   if (min_level == -1)
105     {
106       if ((eptr = getenv("VMS_DEBUG")) != NULL)
107         {
108           min_level = atoi(eptr);
109           output = stderr;
110         }
111       else
112         min_level = 0;
113     }
114   if (output == NULL)
115     return;
116   if (level > min_level)
117     return;
118
119   while (--level>0)
120     fprintf (output, " ");
121   fprintf (output, format, a1, a2, a3, a4, a5, a6);
122   fflush(output);
123
124   return;
125 }
126 #endif /* __STDC__ */
127
128 /* a debug function
129    hex dump 'size' bytes starting at 'ptr'  */
130
131 void
132 _bfd_hexdump (level, ptr, size, offset)
133      int level;
134      unsigned char *ptr;
135      int size;
136      int offset;
137 {
138   unsigned char *lptr = ptr;
139   int count = 0;
140   long start = offset;
141
142   while (size-- > 0)
143     {
144       if ((count%16) == 0)
145         vms_debug (level, "%08lx:", start);
146       vms_debug (-level, " %02x", *ptr++);
147       count++;
148       start++;
149       if (size == 0)
150         {
151           while ((count%16) != 0)
152             {
153               vms_debug (-level, "   ");
154               count++;
155             }
156         }
157       if ((count%16) == 0)
158         {
159           vms_debug (-level, " ");
160           while (lptr < ptr)
161             {
162               vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
163               lptr++;
164             }
165           vms_debug (-level, "\n");
166         }
167     }
168   if ((count%16) != 0)
169     vms_debug (-level, "\n");
170
171   return;
172 }
173 #endif
174 \f
175 /* hash functions
176
177    These are needed when reading an object file.  */
178
179 /* allocate new vms_hash_entry
180    keep the symbol name and a pointer to the bfd symbol in the table  */
181
182 struct bfd_hash_entry *
183 _bfd_vms_hash_newfunc (entry, table, string)
184      struct bfd_hash_entry *entry;
185      struct bfd_hash_table *table;
186      const char *string;
187 {
188   vms_symbol_entry *ret;
189
190 #if VMS_DEBUG
191   vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
192 #endif
193
194   if (entry == (struct bfd_hash_entry *)NULL)
195     {
196       ret = (vms_symbol_entry *)
197               bfd_hash_allocate (table, sizeof (vms_symbol_entry));
198       if (ret == (vms_symbol_entry *) NULL)
199         {
200           bfd_set_error (bfd_error_no_memory);
201           return (struct bfd_hash_entry *)NULL;
202         }
203       entry = (struct bfd_hash_entry *) ret;
204     }
205
206   /* Call the allocation method of the base class.  */
207
208   ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
209 #if VMS_DEBUG
210   vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
211 #endif
212
213   ret->symbol = (asymbol *)NULL;
214
215   return (struct bfd_hash_entry *)ret;
216 }
217 \f
218 /* object file input functions */
219
220 /* Return type and length from record header (buf) on Alpha.  */
221
222 void
223 _bfd_vms_get_header_values (abfd, buf, type, length)
224      bfd *abfd ATTRIBUTE_UNUSED;
225      unsigned char *buf;
226      int *type;
227      int *length;
228 {
229   if (type != 0)
230     *type = bfd_getl16 (buf);
231   buf += 2;
232   if (length != 0)
233     *length = bfd_getl16 (buf);
234
235 #if VMS_DEBUG
236   vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
237 #endif
238
239   return;
240 }
241
242 /* Get next record from object file to vms_buf
243    set PRIV(buf_size) and return it
244
245    this is a little tricky since it should be portable.
246
247    the openVMS object file has 'variable length' which means that
248    read() returns data in chunks of (hopefully) correct and expected
249    size. The linker (and other tools on vms) depend on that. Unix doesn't
250    know about 'formatted' files, so reading and writing such an object
251    file in a unix environment is not trivial.
252
253    With the tool 'file' (available on all vms ftp sites), one
254    can view and change the attributes of a file. Changing from
255    'variable length' to 'fixed length, 512 bytes' reveals the
256    record length at the first 2 bytes of every record. The same
257    happens during the transfer of object files from vms to unix,
258    at least with ucx, dec's implementation of tcp/ip.
259
260    The vms format repeats the length at bytes 2 & 3 of every record.
261
262    On the first call (file_format == FF_UNKNOWN) we check if
263    the first and the third byte pair (!) of the record match.
264    If they do it's an object file in an unix environment or with
265    wrong attributes (FF_FOREIGN), else we should be in a vms
266    environment where read() returns the record size (FF_NATIVE).
267
268    reading is always done in 2 steps.
269    first just the record header is read and the length extracted
270    by get_header_values
271    then the read buffer is adjusted and the remaining bytes are
272    read in.
273
274    all file i/o is always done on even file positions  */
275
276 int
277 _bfd_vms_get_record (abfd)
278      bfd *abfd;
279 {
280   int test_len, test_start, remaining;
281   unsigned char *vms_buf;
282
283 #if VMS_DEBUG
284   vms_debug (8, "_bfd_vms_get_record\n");
285 #endif
286
287   /* minimum is 6 bytes on Alpha
288      (2 bytes length, 2 bytes record id, 2 bytes length repeated)
289
290      on VAX there's no length information in the record
291      so start with OBJ_S_C_MAXRECSIZ  */
292
293   if (PRIV (buf_size) == 0)
294     {
295       if (PRIV (is_vax))
296         {
297           PRIV (vms_buf) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ);
298           PRIV (buf_size) = OBJ_S_C_MAXRECSIZ;
299           PRIV (file_format) = FF_VAX;
300         }
301       else
302         PRIV (vms_buf) = (unsigned char *) malloc (6);
303     }
304
305   vms_buf = PRIV (vms_buf);
306
307   if (vms_buf == 0)
308     {
309       bfd_set_error (bfd_error_no_memory);
310       return -1;
311     }
312
313   switch (PRIV (file_format))
314     {
315     case FF_UNKNOWN:
316     case FF_FOREIGN:
317       test_len = 6;                     /* probe 6 bytes */
318       test_start = 2;                   /* where the record starts */
319       break;
320
321     case FF_NATIVE:
322       test_len = 4;
323       test_start = 0;
324       break;
325
326     default:
327     case FF_VAX:
328       test_len = 0;
329       test_start = 0;
330       break;
331     }
332
333   /* skip odd alignment byte  */
334
335   if (bfd_tell (abfd) & 1)
336     {
337       if (bfd_read (PRIV (vms_buf), 1, 1, abfd) != 1)
338         {
339           bfd_set_error (bfd_error_file_truncated);
340           return 0;
341         }
342     }
343
344   /* read the record header on Alpha.  */
345
346   if ((test_len != 0)
347       && (bfd_read (PRIV (vms_buf), 1, test_len, abfd)
348           != (bfd_size_type) test_len))
349     {
350       bfd_set_error (bfd_error_file_truncated);
351       return 0;
352     }
353
354   /* check file format on first call  */
355
356   if (PRIV (file_format) == FF_UNKNOWN)
357     {                                           /* record length repeats ? */
358       if ( (vms_buf[0] == vms_buf[4])
359         && (vms_buf[1] == vms_buf[5]))
360         {
361           PRIV (file_format) = FF_FOREIGN;      /* Y: foreign environment */
362           test_start = 2;
363         }
364       else
365         {
366           PRIV (file_format) = FF_NATIVE;       /* N: native environment */
367           test_start = 0;
368         }
369     }
370
371   if (PRIV (is_vax))
372     {
373       PRIV (rec_length) = bfd_read (vms_buf, 1, PRIV (buf_size), abfd);
374       if (PRIV (rec_length) <= 0)
375         {
376           bfd_set_error (bfd_error_file_truncated);
377           return 0;
378         }
379       PRIV (vms_rec) = vms_buf;
380     }
381   else          /* Alpha  */
382     {
383       /* extract vms record length  */
384
385       _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
386                                   &PRIV (rec_length));
387
388       if (PRIV (rec_length) <= 0)
389         {
390           bfd_set_error (bfd_error_file_truncated);
391           return 0;
392         }
393
394       /* that's what the linker manual says  */
395
396       if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
397         {
398           bfd_set_error (bfd_error_file_truncated);
399           return 0;
400         }
401
402       /* adjust the buffer  */
403
404       if (PRIV (rec_length) > PRIV (buf_size))
405         {
406           PRIV (vms_buf) = (unsigned char *) realloc (vms_buf, PRIV (rec_length));
407           vms_buf = PRIV (vms_buf);
408           if (vms_buf == 0)
409             {
410               bfd_set_error (bfd_error_no_memory);
411               return -1;
412             }
413           PRIV (buf_size) = PRIV (rec_length);
414         }
415
416       /* read the remaining record  */
417
418       remaining = PRIV (rec_length) - test_len + test_start;
419
420 #if VMS_DEBUG
421       vms_debug (10, "bfd_read remaining %d\n", remaining);
422 #endif
423       if (bfd_read (vms_buf + test_len, 1, remaining, abfd) !=
424           (bfd_size_type) remaining)
425         {
426           bfd_set_error (bfd_error_file_truncated);
427           return 0;
428         }
429       PRIV (vms_rec) = vms_buf + test_start;
430     }
431
432 #if VMS_DEBUG
433   vms_debug (11, "bfd_read rec_length %d\n", PRIV (rec_length));
434 #endif
435
436   return PRIV (rec_length);
437 }
438
439 /* get next vms record from file
440    update vms_rec and rec_length to new (remaining) values  */
441
442 int
443 _bfd_vms_next_record (abfd)
444      bfd *abfd;
445 {
446 #if VMS_DEBUG
447   vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
448               PRIV (rec_length), PRIV (rec_size));
449 #endif
450
451   if (PRIV (rec_length) > 0)
452     {
453       PRIV (vms_rec) += PRIV (rec_size);
454     }
455   else
456     {
457       if (_bfd_vms_get_record (abfd) <= 0)
458         return -1;
459     }
460
461   if (!PRIV (vms_rec) || !PRIV (vms_buf)
462       || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
463     return -1;
464
465   if (PRIV (is_vax))
466     {
467       PRIV (rec_type) = *(PRIV (vms_rec));
468       PRIV (rec_size) = PRIV (rec_length);
469     }
470   else
471     {
472       _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
473                                   &PRIV (rec_size));
474     }
475   PRIV (rec_length) -= PRIV (rec_size);
476
477 #if VMS_DEBUG
478   vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
479               PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
480               PRIV (rec_type));
481 #endif
482
483   return PRIV (rec_type);
484 }
485 \f
486 /* Copy sized string (string with fixed length) to new allocated area
487    size is string length (size of record)  */
488
489 char *
490 _bfd_vms_save_sized_string (str, size)
491      unsigned char *str;
492      int size;
493 {
494   char *newstr = bfd_malloc (size + 1);
495
496   if (newstr == NULL)
497     return 0;
498   strncpy (newstr, (char *)str, size);
499   newstr[size] = 0;
500
501   return newstr;
502 }
503
504 /* Copy counted string (string with length at first byte) to new allocated area
505    ptr points to length byte on entry  */
506
507 char *
508 _bfd_vms_save_counted_string (ptr)
509      unsigned char *ptr;
510 {
511   int len = *ptr++;
512
513   return _bfd_vms_save_sized_string (ptr, len);
514 }
515 \f
516 /* stack routines for vms ETIR commands */
517
518 /* Push value and section index  */
519
520 void
521 _bfd_vms_push (abfd, val, psect)
522      bfd *abfd;
523      uquad val;
524      int psect;
525 {
526   static int last_psect;
527
528 #if VMS_DEBUG
529   vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr));
530 #endif
531
532   if (psect >= 0)
533     last_psect = psect;
534
535   PRIV (stack[PRIV (stackptr)]).value = val;
536   PRIV (stack[PRIV (stackptr)]).psect = last_psect;
537   PRIV (stackptr)++;
538   if (PRIV (stackptr) >= STACKSIZE)
539     {
540       bfd_set_error (bfd_error_bad_value);
541       (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
542       exit (1);
543     }
544   return;
545 }
546
547 /* Pop value and section index  */
548
549 uquad
550 _bfd_vms_pop (abfd, psect)
551      bfd *abfd;
552      int *psect;
553 {
554   uquad value;
555
556   if (PRIV (stackptr) == 0)
557     {
558       bfd_set_error (bfd_error_bad_value);
559       (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
560       exit (1);
561     }
562   PRIV (stackptr)--;
563   value = PRIV (stack[PRIV (stackptr)]).value;
564   if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
565     *psect = PRIV (stack[PRIV (stackptr)]).psect;
566
567 #if VMS_DEBUG
568   vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
569 #endif
570
571   return value;
572 }
573 \f
574 /* object file output functions */
575
576 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
577    which we can't use directly. So we save the little chunks in linked
578    lists (one per section) and write them later.  */
579
580 /* Add a new vms_section structure to vms_section_table
581    - forward chaining -  */
582
583 static vms_section *
584 add_new_contents (abfd, section)
585      bfd *abfd;
586      sec_ptr section;
587 {
588   vms_section *sptr, *newptr;
589
590   sptr = PRIV (vms_section_table)[section->index];
591   if (sptr != NULL)
592     return sptr;
593
594   newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
595   if (newptr == (vms_section *) NULL)
596     return NULL;
597   newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
598   if (newptr->contents == (unsigned char *)NULL)
599     return NULL;
600   newptr->offset = 0;
601   newptr->size = section->_raw_size;
602   newptr->next = 0;
603   PRIV (vms_section_table)[section->index] = newptr;
604   return newptr;
605 }
606
607 /* Save section data & offset to an vms_section structure
608    vms_section_table[] holds the vms_section chain  */
609
610 boolean
611 _bfd_save_vms_section (abfd, section, data, offset, count)
612      bfd *abfd;
613      sec_ptr section;
614      PTR data;
615      file_ptr offset;
616      bfd_size_type count;
617 {
618   vms_section *sptr;
619
620   if (section->index >= VMS_SECTION_COUNT)
621     {
622       bfd_set_error (bfd_error_nonrepresentable_section);
623       return false;
624     }
625   if (count == (bfd_size_type)0)
626     return true;
627   sptr = add_new_contents (abfd, section);
628   if (sptr == NULL)
629     return false;
630   memcpy (sptr->contents + offset, data, (size_t) count);
631
632   return true;
633 }
634
635 /* Get vms_section pointer to saved contents for section # index  */
636
637 vms_section *
638 _bfd_get_vms_section (abfd, index)
639      bfd *abfd;
640      int index;
641 {
642   if (index >=  VMS_SECTION_COUNT)
643     {
644       bfd_set_error (bfd_error_nonrepresentable_section);
645       return NULL;
646     }
647   return PRIV (vms_section_table)[index];
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 }