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