This commit was generated by cvs2svn to track changes on a CVS vendor
[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 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     }
202
203   /* Call the allocation method of the base class.  */
204
205   ret = (vms_symbol_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *)ret, table, string);
206 #if VMS_DEBUG
207   vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
208 #endif
209
210   ret->symbol = (asymbol *)NULL;
211
212   return (struct bfd_hash_entry *)ret;
213 }
214
215 \f
216 /* object file input functions */
217
218 /* Return type and length from record header (buf) on Alpha.  */
219
220 void
221 _bfd_vms_get_header_values (abfd, buf, type, length)
222      bfd *abfd;
223      unsigned char *buf;
224      int *type;
225      int *length;
226 {
227   if (type != 0)
228     *type = bfd_getl16 (buf);
229   buf += 2;
230   if (length != 0)
231     *length = bfd_getl16 (buf);
232
233 #if VMS_DEBUG
234   vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
235 #endif
236
237
238   return;
239 }
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       case FF_VAX:
327         test_len = 0;
328         test_start = 0;
329       break;
330   }
331
332   /* skip odd alignment byte  */
333
334   if (bfd_tell (abfd) & 1)
335     {
336       if (bfd_read (PRIV(vms_buf), 1, 1, abfd) != 1)
337         {
338           bfd_set_error (bfd_error_file_truncated);
339           return 0;
340         }
341     }
342
343   /* read the record header on Alpha.  */
344
345   if ((test_len != 0)
346       && (bfd_read (PRIV(vms_buf), 1, test_len, abfd) != test_len))
347     {
348       bfd_set_error (bfd_error_file_truncated);
349       return 0;
350     }
351
352   /* check file format on first call  */
353
354   if (PRIV(file_format) == FF_UNKNOWN)
355     {                                           /* record length repeats ? */
356       if ( (vms_buf[0] == vms_buf[4])
357         && (vms_buf[1] == vms_buf[5]))
358         {
359           PRIV(file_format) = FF_FOREIGN;       /* Y: foreign environment */
360           test_start = 2;
361         }
362       else
363         {
364           PRIV(file_format) = FF_NATIVE;        /* N: native environment */
365           test_start = 0;
366         }
367     }
368
369   if (PRIV(is_vax))
370     {
371       PRIV(rec_length) = bfd_read (vms_buf, 1, PRIV(buf_size), abfd);
372       if (PRIV(rec_length) <= 0)
373         {
374           bfd_set_error (bfd_error_file_truncated);
375           return 0;
376         }
377       PRIV(vms_rec) = vms_buf;
378     }
379   else          /* Alpha  */
380     {
381       /* extract vms record length  */
382
383       _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
384                                   &PRIV(rec_length));
385
386       if (PRIV(rec_length) <= 0)
387         {
388           bfd_set_error (bfd_error_file_truncated);
389           return 0;
390         }
391
392       /* that's what the linker manual says  */
393
394       if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ)
395         {
396           bfd_set_error (bfd_error_file_truncated);
397           return 0;
398         }
399
400       /* adjust the buffer  */
401
402       if (PRIV(rec_length) > PRIV(buf_size))
403         {
404           PRIV(vms_buf) = (unsigned char *) realloc (vms_buf, PRIV(rec_length));
405           vms_buf = PRIV(vms_buf);
406           if (vms_buf == 0)
407             {
408               bfd_set_error (bfd_error_no_memory);
409               return -1;
410             }
411           PRIV(buf_size) = PRIV(rec_length);
412         }
413
414       /* read the remaining record  */
415
416       remaining = PRIV(rec_length) - test_len + test_start;
417
418 #if VMS_DEBUG
419       vms_debug (10, "bfd_read remaining %d\n", remaining);
420 #endif
421       if (bfd_read (vms_buf + test_len, 1, remaining, abfd) != 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
437 /* get next vms record from file
438    update vms_rec and rec_length to new (remaining) values  */
439
440 int
441 _bfd_vms_next_record (abfd)
442      bfd *abfd;
443 {
444 #if VMS_DEBUG
445   vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
446               PRIV(rec_length), PRIV(rec_size));
447 #endif
448
449   if (PRIV(rec_length) > 0)
450     {
451       PRIV(vms_rec) += PRIV(rec_size);
452     }
453   else
454     {
455       if (_bfd_vms_get_record (abfd) <= 0)
456         return -1;
457     }
458
459   if (PRIV(is_vax))
460     {
461       PRIV(rec_type) = *(PRIV(vms_rec));
462       PRIV(rec_size) = PRIV(rec_length);
463     }
464   else
465     {
466       _bfd_vms_get_header_values (abfd, PRIV(vms_rec), &PRIV(rec_type),
467                                   &PRIV(rec_size));
468     }
469   PRIV(rec_length) -= PRIV(rec_size);
470
471 #if VMS_DEBUG
472   vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
473               PRIV(vms_rec), PRIV(rec_size), PRIV(rec_length),
474               PRIV(rec_type));
475 #endif
476
477   return PRIV(rec_type);
478 }
479
480
481 \f
482 /* Copy sized string (string with fixed length) to new allocated area
483    size is string length (size of record)  */
484
485 char *
486 _bfd_vms_save_sized_string (str, size)
487      unsigned char *str;
488      int size;
489 {
490   char *newstr = bfd_malloc (size + 1);
491
492   if (newstr == NULL)
493     return 0;
494   strncpy (newstr, (char *)str, size);
495   newstr[size] = 0;
496
497   return newstr;
498 }
499
500 /* Copy counted string (string with length at first byte) to new allocated area
501    ptr points to length byte on entry  */
502
503 char *
504 _bfd_vms_save_counted_string (ptr)
505      unsigned char *ptr;
506 {
507   int len = *ptr++;
508
509   return _bfd_vms_save_sized_string (ptr, len);
510 }
511
512 \f
513 /* stack routines for vms ETIR commands */
514
515 /* Push value and section index  */
516
517 void
518 _bfd_vms_push (abfd, val, psect)
519      bfd *abfd;
520      uquad val;
521      int psect;
522 {
523   static int last_psect;
524
525 #if VMS_DEBUG
526   vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV(stackptr));
527 #endif
528
529   if (psect >= 0)
530     last_psect = psect;
531
532   PRIV(stack[PRIV(stackptr)]).value = val;
533   PRIV(stack[PRIV(stackptr)]).psect = last_psect;
534   PRIV(stackptr)++;
535   if (PRIV(stackptr) >= STACKSIZE)
536     {
537       bfd_set_error (bfd_error_bad_value);
538       (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr));
539       exit (1);
540     }
541   return;
542 }
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
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
636 /* Get vms_section pointer to saved contents for section # index  */
637
638 vms_section *
639 _bfd_get_vms_section (abfd, index)
640      bfd *abfd;
641      int index;
642 {
643   if (index >=  VMS_SECTION_COUNT)
644     {
645       bfd_set_error (bfd_error_nonrepresentable_section);
646       return NULL;
647     }
648   return PRIV(vms_section_table)[index];
649 }
650
651 \f
652 /* Object output routines  */
653
654 /* Begin new record or record header
655    write 2 bytes rectype
656    write 2 bytes record length (filled in at flush)
657    write 2 bytes header type (ommitted if rechead == -1)  */
658
659 void
660 _bfd_vms_output_begin (abfd, rectype, rechead)
661      bfd *abfd;
662      int rectype;
663      int rechead;
664 {
665 #if VMS_DEBUG
666   vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
667               rechead);
668 #endif
669
670   _bfd_vms_output_short (abfd,rectype);
671
672   /* save current output position to fill in lenght later  */
673
674   if (PRIV(push_level) > 0)
675     PRIV(length_pos) = PRIV(output_size);
676
677 #if VMS_DEBUG
678   vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
679               PRIV(length_pos));
680 #endif
681
682   _bfd_vms_output_short (abfd,0);               /* placeholder for length */
683
684   if (rechead != -1)
685     _bfd_vms_output_short (abfd,rechead);
686
687   return;
688 }
689
690
691 /* Set record/subrecord alignment  */
692
693 void
694 _bfd_vms_output_alignment (abfd, alignto)
695      bfd *abfd;
696      int alignto;
697 {
698 #if VMS_DEBUG
699   vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
700 #endif
701
702   PRIV(output_alignment) = alignto;
703   return;
704 }
705
706
707 /* Prepare for subrecord fields  */
708
709 void
710 _bfd_vms_output_push (abfd)
711      bfd *abfd;
712 {
713 #if VMS_DEBUG
714   vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size));
715 #endif
716
717   PRIV(push_level)++;
718   PRIV(pushed_size) = PRIV(output_size);
719   return;
720 }
721
722
723 /* End of subrecord fields  */
724
725 void
726 _bfd_vms_output_pop (abfd)
727      bfd *abfd;
728 {
729 #if VMS_DEBUG
730   vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
731 #endif
732
733   _bfd_vms_output_flush (abfd);
734   PRIV(length_pos) = 2;
735
736 #if VMS_DEBUG
737   vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos));
738 #endif
739
740   PRIV(pushed_size) = 0;
741   PRIV(push_level)--;
742   return;
743 }
744
745
746 /* Flush unwritten output, ends current record  */
747
748 void
749 _bfd_vms_output_flush (abfd)
750      bfd *abfd;
751 {
752   int real_size = PRIV(output_size);
753   int aligncount;
754   int length;
755
756 #if VMS_DEBUG
757   vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
758               real_size, PRIV(pushed_size), PRIV(length_pos));
759 #endif
760
761   if (PRIV(push_level) > 0)
762     length = real_size - PRIV(pushed_size);
763   else
764     length = real_size;
765
766   if (length == 0)
767     return;
768   aligncount = (PRIV(output_alignment)
769                 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
770
771 #if VMS_DEBUG
772   vms_debug (6, "align: adding %d bytes\n", aligncount);
773 #endif
774
775   while(aligncount-- > 0)
776     {
777       PRIV(output_buf)[real_size++] = 0;
778 #if 0
779       /* this is why I *love* vms: inconsistency :-}
780          alignment is added to the subrecord length
781          but not to the record length  */
782       if (PRIV(push_level) > 0)
783 #endif
784         length++;
785     }
786
787   /* put length to buffer  */
788   PRIV(output_size) = PRIV(length_pos);
789   _bfd_vms_output_short (abfd, (unsigned int)length);
790
791   if (PRIV(push_level) == 0)
792     {
793 #ifndef VMS
794         /* write length first, see FF_FOREIGN in the input routines */
795       fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
796 #endif
797       fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
798
799       PRIV(output_size) = 0;
800     }
801   else
802     {
803       PRIV(output_size) = real_size;
804       PRIV(pushed_size) = PRIV(output_size);
805     }
806
807   return;
808 }
809
810
811 /* End record output  */
812
813 void
814 _bfd_vms_output_end (abfd)
815      bfd *abfd;
816 {
817 #if VMS_DEBUG
818   vms_debug (6, "_bfd_vms_output_end\n");
819 #endif
820
821   _bfd_vms_output_flush (abfd);
822
823   return;
824 }
825
826
827 /* check remaining buffer size
828
829    return what's left.  */
830
831 int
832 _bfd_vms_output_check (abfd, size)
833     bfd *abfd;
834     int size;
835 {
836 #if VMS_DEBUG
837   vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
838 #endif
839
840   return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
841 }
842
843
844 /* Output byte (8 bit) value  */
845
846 void
847 _bfd_vms_output_byte (abfd, value)
848      bfd *abfd;
849      unsigned int value;
850 {
851 #if VMS_DEBUG
852   vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
853 #endif
854
855   bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
856   PRIV(output_size) += 1;
857   return;
858 }
859
860
861 /* Output short (16 bit) value  */
862
863 void
864 _bfd_vms_output_short (abfd, value)
865      bfd *abfd;
866      unsigned int value;
867 {
868 #if VMS_DEBUG
869   vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
870 #endif
871
872   bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
873   PRIV(output_size) += 2;
874   return;
875 }
876
877
878 /* Output long (32 bit) value  */
879
880 void
881 _bfd_vms_output_long (abfd, value)
882      bfd *abfd;
883      unsigned long value;
884 {
885 #if VMS_DEBUG
886   vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
887 #endif
888
889   bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
890   PRIV(output_size) += 4;
891   return;
892 }
893
894
895 /* Output quad (64 bit) value  */
896
897 void
898 _bfd_vms_output_quad (abfd, value)
899      bfd *abfd;
900      uquad value;
901 {
902 #if VMS_DEBUG
903   vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
904 #endif
905
906   bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
907   PRIV(output_size) += 8;
908   return;
909 }
910
911
912 /* Output c-string as counted string  */
913
914 void
915 _bfd_vms_output_counted (abfd, value)
916      bfd *abfd;
917      char *value;
918 {
919 int len;
920
921 #if VMS_DEBUG
922   vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
923 #endif
924
925   len = strlen (value);
926   if (len == 0)
927     {
928       (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
929       return;
930     }
931   if (len > 255)
932     {
933       (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
934       return;
935     }
936   _bfd_vms_output_byte (abfd, len & 0xff);
937   _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
938 }
939
940
941 /* Output character area  */
942
943 void
944 _bfd_vms_output_dump (abfd, data, length)
945      bfd *abfd;
946      unsigned char *data;
947      int length;
948 {
949 #if VMS_DEBUG
950   vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
951 #endif
952
953   if (length == 0)
954     return;
955
956   memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
957   PRIV(output_size) += length;
958
959   return;
960 }
961
962
963 /* Output count bytes of value  */
964
965 void
966 _bfd_vms_output_fill (abfd, value, count)
967      bfd *abfd;
968      int value;
969      int count;
970 {
971 #if VMS_DEBUG
972   vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
973 #endif
974
975   if (count == 0)
976     return;
977   memset (PRIV(output_buf) + PRIV(output_size), value, count);
978   PRIV(output_size) += count;
979
980   return;
981 }
982
983 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly  ERY*/
984
985 static int
986 hash_string (ptr)
987      const char *ptr;
988 {
989   register const unsigned char *p = (unsigned char *) ptr;
990   register const unsigned char *end = p + strlen (ptr);
991   register unsigned char c;
992   register int hash = 0;
993
994   while (p != end)
995     {
996       c = *p++;
997       hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
998     }
999   return hash;
1000 }
1001
1002 /* Generate a length-hashed VMS symbol name (limited to maxlen chars).  */
1003
1004 char *
1005 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
1006      bfd *abfd;
1007      const char *in;
1008      int maxlen;
1009 {
1010   long int init;
1011   long int result;
1012   int in_len;
1013   char *pnt = 0;
1014   char *new_name;
1015   const char *old_name;
1016   int i;
1017   static char outbuf[EOBJ_S_C_SYMSIZ+1];
1018   char *out = outbuf;
1019
1020 #if VMS_DEBUG
1021   vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1022 #endif
1023
1024   if (maxlen > EOBJ_S_C_SYMSIZ)
1025     maxlen = EOBJ_S_C_SYMSIZ;
1026
1027   new_name = out;               /* save this for later.  */
1028
1029   /* We may need to truncate the symbol, save the hash for later.  */
1030
1031   in_len = strlen (in);
1032
1033   result = (in_len > maxlen) ? hash_string (in) : 0;
1034
1035   old_name = in;
1036
1037   /* Do the length checking.  */
1038
1039   if (in_len <= maxlen)
1040     {
1041       i = in_len;
1042     }
1043   else
1044     {
1045       if (PRIV(flag_hash_long_names))
1046         i = maxlen-9;
1047       else
1048         i = maxlen;
1049     }
1050
1051   strncpy (out, in, i);
1052   in += i;
1053   out += i;
1054
1055   if ((in_len > maxlen)
1056       && PRIV(flag_hash_long_names))
1057     sprintf (out, "_%08x", result);
1058   else
1059     *out = 0;
1060
1061 #if VMS_DEBUG
1062   vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1063 #endif
1064
1065   if (in_len > maxlen
1066         && PRIV(flag_hash_long_names)
1067         && PRIV(flag_show_after_trunc))
1068     printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1069
1070   return outbuf;
1071 }
1072
1073
1074 /* Allocate and initialize a new symbol.  */
1075
1076 static asymbol *
1077 new_symbol (abfd, name)
1078      bfd *abfd;
1079      char *name;
1080 {
1081   asymbol *symbol;
1082
1083 #if VMS_DEBUG
1084   _bfd_vms_debug (7,  "new_symbol %s\n", name);
1085 #endif
1086
1087   symbol = _bfd_vms_make_empty_symbol (abfd);
1088   if (symbol == 0)
1089     return symbol;
1090   symbol->name = name;
1091   symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1092
1093   return symbol;
1094 }
1095
1096
1097 /* Allocate and enter a new private symbol.  */
1098
1099 vms_symbol_entry *
1100 _bfd_vms_enter_symbol (abfd, name)
1101      bfd *abfd;
1102      char *name;
1103 {
1104   vms_symbol_entry *entry;
1105
1106 #if VMS_DEBUG
1107   _bfd_vms_debug (6,  "_bfd_vms_enter_symbol %s\n", name);
1108 #endif
1109
1110   entry = (vms_symbol_entry *)
1111           bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);
1112   if (entry == 0)
1113     {
1114 #if VMS_DEBUG
1115       _bfd_vms_debug (8,  "creating hash entry for %s\n", name);
1116 #endif
1117       entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, true, false);
1118       if (entry != 0)
1119         {
1120           asymbol *symbol;
1121           symbol = new_symbol (abfd, name);
1122           if (symbol != 0)
1123             {
1124               entry->symbol = symbol;
1125               PRIV(gsd_sym_count)++;
1126               abfd->symcount++;
1127             }
1128           else
1129             entry = 0;
1130         }
1131       else
1132         (*_bfd_error_handler) (_("failed to enter %s"), name);
1133     }
1134   else
1135     {
1136 #if VMS_DEBUG
1137       _bfd_vms_debug (8,  "found hash entry for %s\n", name);
1138 #endif
1139     }
1140
1141 #if VMS_DEBUG
1142   _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1143 #endif
1144   return entry;
1145 }