2000-06-14 H.J. Lu <hjl@gnu.org>
[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       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
440 /* get next vms record from file
441    update vms_rec and rec_length to new (remaining) values  */
442
443 int
444 _bfd_vms_next_record (abfd)
445      bfd *abfd;
446 {
447 #if VMS_DEBUG
448   vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
449               PRIV(rec_length), PRIV(rec_size));
450 #endif
451
452   if (PRIV(rec_length) > 0)
453     {
454       PRIV(vms_rec) += PRIV(rec_size);
455     }
456   else
457     {
458       if (_bfd_vms_get_record (abfd) <= 0)
459         return -1;
460     }
461
462   if (!PRIV(vms_rec))
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
486
487 \f
488 /* Copy sized string (string with fixed length) to new allocated area
489    size is string length (size of record)  */
490
491 char *
492 _bfd_vms_save_sized_string (str, size)
493      unsigned char *str;
494      int size;
495 {
496   char *newstr = bfd_malloc (size + 1);
497
498   if (newstr == NULL)
499     return 0;
500   strncpy (newstr, (char *)str, size);
501   newstr[size] = 0;
502
503   return newstr;
504 }
505
506 /* Copy counted string (string with length at first byte) to new allocated area
507    ptr points to length byte on entry  */
508
509 char *
510 _bfd_vms_save_counted_string (ptr)
511      unsigned char *ptr;
512 {
513   int len = *ptr++;
514
515   return _bfd_vms_save_sized_string (ptr, len);
516 }
517
518 \f
519 /* stack routines for vms ETIR commands */
520
521 /* Push value and section index  */
522
523 void
524 _bfd_vms_push (abfd, val, psect)
525      bfd *abfd;
526      uquad val;
527      int psect;
528 {
529   static int last_psect;
530
531 #if VMS_DEBUG
532   vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV(stackptr));
533 #endif
534
535   if (psect >= 0)
536     last_psect = psect;
537
538   PRIV(stack[PRIV(stackptr)]).value = val;
539   PRIV(stack[PRIV(stackptr)]).psect = last_psect;
540   PRIV(stackptr)++;
541   if (PRIV(stackptr) >= STACKSIZE)
542     {
543       bfd_set_error (bfd_error_bad_value);
544       (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr));
545       exit (1);
546     }
547   return;
548 }
549
550
551 /* Pop value and section index  */
552
553 uquad
554 _bfd_vms_pop (abfd, psect)
555      bfd *abfd;
556      int *psect;
557 {
558   uquad value;
559
560   if (PRIV(stackptr) == 0)
561     {
562       bfd_set_error (bfd_error_bad_value);
563       (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
564       exit (1);
565     }
566   PRIV(stackptr)--;
567   value = PRIV(stack[PRIV(stackptr)]).value;
568   if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0))
569     *psect = PRIV(stack[PRIV(stackptr)]).psect;
570
571 #if VMS_DEBUG
572   vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV(stack[PRIV(stackptr)]).psect);
573 #endif
574
575   return value;
576 }
577
578 \f
579 /* object file output functions */
580
581 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
582    which we can't use directly. So we save the little chunks in linked
583    lists (one per section) and write them later.  */
584
585 /* Add a new vms_section structure to vms_section_table
586    - forward chaining -  */
587
588 static vms_section *
589 add_new_contents (abfd, section)
590      bfd *abfd;
591      sec_ptr section;
592 {
593   vms_section *sptr, *newptr;
594
595   sptr = PRIV(vms_section_table)[section->index];
596   if (sptr != NULL)
597     return sptr;
598
599   newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
600   if (newptr == (vms_section *) NULL)
601     return NULL;
602   newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
603   if (newptr->contents == (unsigned char *)NULL)
604     return NULL;
605   newptr->offset = 0;
606   newptr->size = section->_raw_size;
607   newptr->next = 0;
608   PRIV(vms_section_table)[section->index] = newptr;
609   return newptr;
610 }
611
612
613 /* Save section data & offset to an vms_section structure
614    vms_section_table[] holds the vms_section chain  */
615
616 boolean
617 _bfd_save_vms_section (abfd, section, data, offset, count)
618      bfd *abfd;
619      sec_ptr section;
620      PTR data;
621      file_ptr offset;
622      bfd_size_type count;
623 {
624   vms_section *sptr;
625
626   if (section->index >= VMS_SECTION_COUNT)
627     {
628       bfd_set_error (bfd_error_nonrepresentable_section);
629       return false;
630     }
631   if (count == (bfd_size_type)0)
632     return true;
633   sptr = add_new_contents (abfd, section);
634   if (sptr == NULL)
635     return false;
636   memcpy (sptr->contents + offset, data, (size_t) count);
637
638   return true;
639 }
640
641
642 /* Get vms_section pointer to saved contents for section # index  */
643
644 vms_section *
645 _bfd_get_vms_section (abfd, index)
646      bfd *abfd;
647      int index;
648 {
649   if (index >=  VMS_SECTION_COUNT)
650     {
651       bfd_set_error (bfd_error_nonrepresentable_section);
652       return NULL;
653     }
654   return PRIV(vms_section_table)[index];
655 }
656
657 \f
658 /* Object output routines  */
659
660 /* Begin new record or record header
661    write 2 bytes rectype
662    write 2 bytes record length (filled in at flush)
663    write 2 bytes header type (ommitted if rechead == -1)  */
664
665 void
666 _bfd_vms_output_begin (abfd, rectype, rechead)
667      bfd *abfd;
668      int rectype;
669      int rechead;
670 {
671 #if VMS_DEBUG
672   vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
673               rechead);
674 #endif
675
676   _bfd_vms_output_short (abfd,rectype);
677
678   /* save current output position to fill in lenght later  */
679
680   if (PRIV(push_level) > 0)
681     PRIV(length_pos) = PRIV(output_size);
682
683 #if VMS_DEBUG
684   vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
685               PRIV(length_pos));
686 #endif
687
688   _bfd_vms_output_short (abfd,0);               /* placeholder for length */
689
690   if (rechead != -1)
691     _bfd_vms_output_short (abfd,rechead);
692
693   return;
694 }
695
696
697 /* Set record/subrecord alignment  */
698
699 void
700 _bfd_vms_output_alignment (abfd, alignto)
701      bfd *abfd;
702      int alignto;
703 {
704 #if VMS_DEBUG
705   vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
706 #endif
707
708   PRIV(output_alignment) = alignto;
709   return;
710 }
711
712
713 /* Prepare for subrecord fields  */
714
715 void
716 _bfd_vms_output_push (abfd)
717      bfd *abfd;
718 {
719 #if VMS_DEBUG
720   vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size));
721 #endif
722
723   PRIV(push_level)++;
724   PRIV(pushed_size) = PRIV(output_size);
725   return;
726 }
727
728
729 /* End of subrecord fields  */
730
731 void
732 _bfd_vms_output_pop (abfd)
733      bfd *abfd;
734 {
735 #if VMS_DEBUG
736   vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
737 #endif
738
739   _bfd_vms_output_flush (abfd);
740   PRIV(length_pos) = 2;
741
742 #if VMS_DEBUG
743   vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos));
744 #endif
745
746   PRIV(pushed_size) = 0;
747   PRIV(push_level)--;
748   return;
749 }
750
751
752 /* Flush unwritten output, ends current record  */
753
754 void
755 _bfd_vms_output_flush (abfd)
756      bfd *abfd;
757 {
758   int real_size = PRIV(output_size);
759   int aligncount;
760   int length;
761
762 #if VMS_DEBUG
763   vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
764               real_size, PRIV(pushed_size), PRIV(length_pos));
765 #endif
766
767   if (PRIV(push_level) > 0)
768     length = real_size - PRIV(pushed_size);
769   else
770     length = real_size;
771
772   if (length == 0)
773     return;
774   aligncount = (PRIV(output_alignment)
775                 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
776
777 #if VMS_DEBUG
778   vms_debug (6, "align: adding %d bytes\n", aligncount);
779 #endif
780
781   while(aligncount-- > 0)
782     {
783       PRIV(output_buf)[real_size++] = 0;
784 #if 0
785       /* this is why I *love* vms: inconsistency :-}
786          alignment is added to the subrecord length
787          but not to the record length  */
788       if (PRIV(push_level) > 0)
789 #endif
790         length++;
791     }
792
793   /* put length to buffer  */
794   PRIV(output_size) = PRIV(length_pos);
795   _bfd_vms_output_short (abfd, (unsigned int)length);
796
797   if (PRIV(push_level) == 0)
798     {
799 #ifndef VMS
800         /* write length first, see FF_FOREIGN in the input routines */
801       fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
802 #endif
803       fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
804
805       PRIV(output_size) = 0;
806     }
807   else
808     {
809       PRIV(output_size) = real_size;
810       PRIV(pushed_size) = PRIV(output_size);
811     }
812
813   return;
814 }
815
816
817 /* End record output  */
818
819 void
820 _bfd_vms_output_end (abfd)
821      bfd *abfd;
822 {
823 #if VMS_DEBUG
824   vms_debug (6, "_bfd_vms_output_end\n");
825 #endif
826
827   _bfd_vms_output_flush (abfd);
828
829   return;
830 }
831
832
833 /* check remaining buffer size
834
835    return what's left.  */
836
837 int
838 _bfd_vms_output_check (abfd, size)
839     bfd *abfd;
840     int size;
841 {
842 #if VMS_DEBUG
843   vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
844 #endif
845
846   return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
847 }
848
849
850 /* Output byte (8 bit) value  */
851
852 void
853 _bfd_vms_output_byte (abfd, value)
854      bfd *abfd;
855      unsigned int value;
856 {
857 #if VMS_DEBUG
858   vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
859 #endif
860
861   bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
862   PRIV(output_size) += 1;
863   return;
864 }
865
866
867 /* Output short (16 bit) value  */
868
869 void
870 _bfd_vms_output_short (abfd, value)
871      bfd *abfd;
872      unsigned int value;
873 {
874 #if VMS_DEBUG
875   vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
876 #endif
877
878   bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
879   PRIV(output_size) += 2;
880   return;
881 }
882
883
884 /* Output long (32 bit) value  */
885
886 void
887 _bfd_vms_output_long (abfd, value)
888      bfd *abfd;
889      unsigned long value;
890 {
891 #if VMS_DEBUG
892   vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
893 #endif
894
895   bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
896   PRIV(output_size) += 4;
897   return;
898 }
899
900
901 /* Output quad (64 bit) value  */
902
903 void
904 _bfd_vms_output_quad (abfd, value)
905      bfd *abfd;
906      uquad value;
907 {
908 #if VMS_DEBUG
909   vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
910 #endif
911
912   bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
913   PRIV(output_size) += 8;
914   return;
915 }
916
917
918 /* Output c-string as counted string  */
919
920 void
921 _bfd_vms_output_counted (abfd, value)
922      bfd *abfd;
923      char *value;
924 {
925 int len;
926
927 #if VMS_DEBUG
928   vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
929 #endif
930
931   len = strlen (value);
932   if (len == 0)
933     {
934       (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
935       return;
936     }
937   if (len > 255)
938     {
939       (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
940       return;
941     }
942   _bfd_vms_output_byte (abfd, len & 0xff);
943   _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
944 }
945
946
947 /* Output character area  */
948
949 void
950 _bfd_vms_output_dump (abfd, data, length)
951      bfd *abfd;
952      unsigned char *data;
953      int length;
954 {
955 #if VMS_DEBUG
956   vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
957 #endif
958
959   if (length == 0)
960     return;
961
962   memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
963   PRIV(output_size) += length;
964
965   return;
966 }
967
968
969 /* Output count bytes of value  */
970
971 void
972 _bfd_vms_output_fill (abfd, value, count)
973      bfd *abfd;
974      int value;
975      int count;
976 {
977 #if VMS_DEBUG
978   vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
979 #endif
980
981   if (count == 0)
982     return;
983   memset (PRIV(output_buf) + PRIV(output_size), value, count);
984   PRIV(output_size) += count;
985
986   return;
987 }
988
989 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly  ERY*/
990
991 static int
992 hash_string (ptr)
993      const char *ptr;
994 {
995   register const unsigned char *p = (unsigned char *) ptr;
996   register const unsigned char *end = p + strlen (ptr);
997   register unsigned char c;
998   register int hash = 0;
999
1000   while (p != end)
1001     {
1002       c = *p++;
1003       hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
1004     }
1005   return hash;
1006 }
1007
1008 /* Generate a length-hashed VMS symbol name (limited to maxlen chars).  */
1009
1010 char *
1011 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
1012      bfd *abfd;
1013      const char *in;
1014      int maxlen;
1015 {
1016   long int result;
1017   int in_len;
1018   char *new_name;
1019   const char *old_name;
1020   int i;
1021   static char outbuf[EOBJ_S_C_SYMSIZ+1];
1022   char *out = outbuf;
1023
1024 #if VMS_DEBUG
1025   vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1026 #endif
1027
1028   if (maxlen > EOBJ_S_C_SYMSIZ)
1029     maxlen = EOBJ_S_C_SYMSIZ;
1030
1031   new_name = out;               /* save this for later.  */
1032
1033   /* We may need to truncate the symbol, save the hash for later.  */
1034
1035   in_len = strlen (in);
1036
1037   result = (in_len > maxlen) ? hash_string (in) : 0;
1038
1039   old_name = in;
1040
1041   /* Do the length checking.  */
1042
1043   if (in_len <= maxlen)
1044     {
1045       i = in_len;
1046     }
1047   else
1048     {
1049       if (PRIV(flag_hash_long_names))
1050         i = maxlen-9;
1051       else
1052         i = maxlen;
1053     }
1054
1055   strncpy (out, in, i);
1056   in += i;
1057   out += i;
1058
1059   if ((in_len > maxlen)
1060       && PRIV(flag_hash_long_names))
1061     sprintf (out, "_%08lx", result);
1062   else
1063     *out = 0;
1064
1065 #if VMS_DEBUG
1066   vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1067 #endif
1068
1069   if (in_len > maxlen
1070         && PRIV(flag_hash_long_names)
1071         && PRIV(flag_show_after_trunc))
1072     printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1073
1074   return outbuf;
1075 }
1076
1077
1078 /* Allocate and initialize a new symbol.  */
1079
1080 static asymbol *
1081 new_symbol (abfd, name)
1082      bfd *abfd;
1083      char *name;
1084 {
1085   asymbol *symbol;
1086
1087 #if VMS_DEBUG
1088   _bfd_vms_debug (7,  "new_symbol %s\n", name);
1089 #endif
1090
1091   symbol = _bfd_vms_make_empty_symbol (abfd);
1092   if (symbol == 0)
1093     return symbol;
1094   symbol->name = name;
1095   symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1096
1097   return symbol;
1098 }
1099
1100
1101 /* Allocate and enter a new private symbol.  */
1102
1103 vms_symbol_entry *
1104 _bfd_vms_enter_symbol (abfd, name)
1105      bfd *abfd;
1106      char *name;
1107 {
1108   vms_symbol_entry *entry;
1109
1110 #if VMS_DEBUG
1111   _bfd_vms_debug (6,  "_bfd_vms_enter_symbol %s\n", name);
1112 #endif
1113
1114   entry = (vms_symbol_entry *)
1115           bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);
1116   if (entry == 0)
1117     {
1118 #if VMS_DEBUG
1119       _bfd_vms_debug (8,  "creating hash entry for %s\n", name);
1120 #endif
1121       entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, true, false);
1122       if (entry != 0)
1123         {
1124           asymbol *symbol;
1125           symbol = new_symbol (abfd, name);
1126           if (symbol != 0)
1127             {
1128               entry->symbol = symbol;
1129               PRIV(gsd_sym_count)++;
1130               abfd->symcount++;
1131             }
1132           else
1133             entry = 0;
1134         }
1135       else
1136         (*_bfd_error_handler) (_("failed to enter %s"), name);
1137     }
1138   else
1139     {
1140 #if VMS_DEBUG
1141       _bfd_vms_debug (8,  "found hash entry for %s\n", name);
1142 #endif
1143     }
1144
1145 #if VMS_DEBUG
1146   _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1147 #endif
1148   return entry;
1149 }