* vms-tir.c: Add missing prototypes.
[binutils.git] / bfd / vms-misc.c
blobf0ba28599991bdeb964ee751178410a2310a6b5c
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.
6 Written by Klaus K"ampf (kkaempf@rmi.de)
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.
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.
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. */
22 #if __STDC__
23 #include <stdarg.h>
24 #endif
26 #include "bfd.h"
27 #include "sysdep.h"
28 #include "bfdlink.h"
29 #include "libbfd.h"
31 #include "vms.h"
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 *));
37 /*-----------------------------------------------------------------------------*/
38 #if VMS_DEBUG
39 /* debug functions */
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
46 levels:
47 1 toplevel bfd calls (functions from the bfd vector)
48 2 functions called by bfd calls
49 ...
50 9 almost everything
52 level is also identation level. Indentation is performed
53 if level > 0
56 #if __STDC__
57 void
58 _bfd_vms_debug (int level, char *format, ...)
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;
66 if (min_level == -1)
68 if ((eptr = getenv("VMS_DEBUG")) != NULL)
70 min_level = atoi(eptr);
71 output = stderr;
73 else
74 min_level = 0;
76 if (output == NULL)
77 return;
78 if (abslvl > min_level)
79 return;
81 while (--level>0)
82 fprintf (output, " ");
83 va_start(args, format);
84 vfprintf (output, format, args);
85 fflush(output);
86 va_end(args);
88 return;
91 #else /* not __STDC__ */
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;
100 static int min_level = -1;
101 static FILE *output = NULL;
102 char *eptr;
104 if (min_level == -1)
106 if ((eptr = getenv("VMS_DEBUG")) != NULL)
108 min_level = atoi(eptr);
109 output = stderr;
111 else
112 min_level = 0;
114 if (output == NULL)
115 return;
116 if (level > min_level)
117 return;
119 while (--level>0)
120 fprintf (output, " ");
121 fprintf (output, format, a1, a2, a3, a4, a5, a6);
122 fflush(output);
124 return;
126 #endif /* __STDC__ */
128 /* a debug function
129 hex dump 'size' bytes starting at 'ptr' */
131 void
132 _bfd_hexdump (level, ptr, size, offset)
133 int level;
134 unsigned char *ptr;
135 int size;
136 int offset;
138 unsigned char *lptr = ptr;
139 int count = 0;
140 long start = offset;
142 while (size-- > 0)
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)
151 while ((count%16) != 0)
153 vms_debug (-level, " ");
154 count++;
157 if ((count%16) == 0)
159 vms_debug (-level, " ");
160 while (lptr < ptr)
162 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
163 lptr++;
165 vms_debug (-level, "\n");
168 if ((count%16) != 0)
169 vms_debug (-level, "\n");
171 return;
173 #endif
175 /* hash functions
177 These are needed when reading an object file. */
179 /* allocate new vms_hash_entry
180 keep the symbol name and a pointer to the bfd symbol in the table */
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;
188 vms_symbol_entry *ret;
190 #if VMS_DEBUG
191 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
192 #endif
194 if (entry == (struct bfd_hash_entry *)NULL)
196 ret = (vms_symbol_entry *)
197 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
198 if (ret == (vms_symbol_entry *) NULL)
200 bfd_set_error (bfd_error_no_memory);
201 return (struct bfd_hash_entry *)NULL;
203 entry = (struct bfd_hash_entry *) ret;
206 /* Call the allocation method of the base class. */
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
213 ret->symbol = (asymbol *)NULL;
215 return (struct bfd_hash_entry *)ret;
218 /* object file input functions */
220 /* Return type and length from record header (buf) on Alpha. */
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;
229 if (type != 0)
230 *type = bfd_getl16 (buf);
231 buf += 2;
232 if (length != 0)
233 *length = bfd_getl16 (buf);
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
239 return;
242 /* Get next record from object file to vms_buf
243 set PRIV(buf_size) and return it
245 this is a little tricky since it should be portable.
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.
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.
260 The vms format repeats the length at bytes 2 & 3 of every record.
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).
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.
274 all file i/o is always done on even file positions */
277 _bfd_vms_get_record (abfd)
278 bfd *abfd;
280 int test_len, test_start, remaining;
281 unsigned char *vms_buf;
283 #if VMS_DEBUG
284 vms_debug (8, "_bfd_vms_get_record\n");
285 #endif
287 /* minimum is 6 bytes on Alpha
288 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
290 on VAX there's no length information in the record
291 so start with OBJ_S_C_MAXRECSIZ */
293 if (PRIV (buf_size) == 0)
295 if (PRIV (is_vax))
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;
301 else
302 PRIV (vms_buf) = (unsigned char *) malloc (6);
305 vms_buf = PRIV (vms_buf);
307 if (vms_buf == 0)
309 bfd_set_error (bfd_error_no_memory);
310 return -1;
313 switch (PRIV (file_format))
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;
321 case FF_NATIVE:
322 test_len = 4;
323 test_start = 0;
324 break;
326 default:
327 case FF_VAX:
328 test_len = 0;
329 test_start = 0;
330 break;
333 /* skip odd alignment byte */
335 if (bfd_tell (abfd) & 1)
337 if (bfd_read (PRIV (vms_buf), 1, 1, abfd) != 1)
339 bfd_set_error (bfd_error_file_truncated);
340 return 0;
344 /* read the record header on Alpha. */
346 if ((test_len != 0)
347 && (bfd_read (PRIV (vms_buf), 1, test_len, abfd)
348 != (bfd_size_type) test_len))
350 bfd_set_error (bfd_error_file_truncated);
351 return 0;
354 /* check file format on first call */
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]))
361 PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment */
362 test_start = 2;
364 else
366 PRIV (file_format) = FF_NATIVE; /* N: native environment */
367 test_start = 0;
371 if (PRIV (is_vax))
373 PRIV (rec_length) = bfd_read (vms_buf, 1, PRIV (buf_size), abfd);
374 if (PRIV (rec_length) <= 0)
376 bfd_set_error (bfd_error_file_truncated);
377 return 0;
379 PRIV (vms_rec) = vms_buf;
381 else /* Alpha */
383 /* extract vms record length */
385 _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
386 &PRIV (rec_length));
388 if (PRIV (rec_length) <= 0)
390 bfd_set_error (bfd_error_file_truncated);
391 return 0;
394 /* that's what the linker manual says */
396 if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
398 bfd_set_error (bfd_error_file_truncated);
399 return 0;
402 /* adjust the buffer */
404 if (PRIV (rec_length) > PRIV (buf_size))
406 PRIV (vms_buf) = (unsigned char *) realloc (vms_buf, PRIV (rec_length));
407 vms_buf = PRIV (vms_buf);
408 if (vms_buf == 0)
410 bfd_set_error (bfd_error_no_memory);
411 return -1;
413 PRIV (buf_size) = PRIV (rec_length);
416 /* read the remaining record */
418 remaining = PRIV (rec_length) - test_len + test_start;
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)
426 bfd_set_error (bfd_error_file_truncated);
427 return 0;
429 PRIV (vms_rec) = vms_buf + test_start;
432 #if VMS_DEBUG
433 vms_debug (11, "bfd_read rec_length %d\n", PRIV (rec_length));
434 #endif
436 return PRIV (rec_length);
439 /* get next vms record from file
440 update vms_rec and rec_length to new (remaining) values */
443 _bfd_vms_next_record (abfd)
444 bfd *abfd;
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
451 if (PRIV (rec_length) > 0)
453 PRIV (vms_rec) += PRIV (rec_size);
455 else
457 if (_bfd_vms_get_record (abfd) <= 0)
458 return -1;
461 if (!PRIV (vms_rec) || !PRIV (vms_buf)
462 || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
463 return -1;
465 if (PRIV (is_vax))
467 PRIV (rec_type) = *(PRIV (vms_rec));
468 PRIV (rec_size) = PRIV (rec_length);
470 else
472 _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
473 &PRIV (rec_size));
475 PRIV (rec_length) -= PRIV (rec_size);
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
483 return PRIV (rec_type);
486 /* Copy sized string (string with fixed length) to new allocated area
487 size is string length (size of record) */
489 char *
490 _bfd_vms_save_sized_string (str, size)
491 unsigned char *str;
492 int size;
494 char *newstr = bfd_malloc (size + 1);
496 if (newstr == NULL)
497 return 0;
498 strncpy (newstr, (char *)str, size);
499 newstr[size] = 0;
501 return newstr;
504 /* Copy counted string (string with length at first byte) to new allocated area
505 ptr points to length byte on entry */
507 char *
508 _bfd_vms_save_counted_string (ptr)
509 unsigned char *ptr;
511 int len = *ptr++;
513 return _bfd_vms_save_sized_string (ptr, len);
516 /* stack routines for vms ETIR commands */
518 /* Push value and section index */
520 void
521 _bfd_vms_push (abfd, val, psect)
522 bfd *abfd;
523 uquad val;
524 int psect;
526 static int last_psect;
528 #if VMS_DEBUG
529 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr));
530 #endif
532 if (psect >= 0)
533 last_psect = psect;
535 PRIV (stack[PRIV (stackptr)]).value = val;
536 PRIV (stack[PRIV (stackptr)]).psect = last_psect;
537 PRIV (stackptr)++;
538 if (PRIV (stackptr) >= STACKSIZE)
540 bfd_set_error (bfd_error_bad_value);
541 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
542 exit (1);
544 return;
547 /* Pop value and section index */
549 uquad
550 _bfd_vms_pop (abfd, psect)
551 bfd *abfd;
552 int *psect;
554 uquad value;
556 if (PRIV (stackptr) == 0)
558 bfd_set_error (bfd_error_bad_value);
559 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
560 exit (1);
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;
567 #if VMS_DEBUG
568 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
569 #endif
571 return value;
574 /* object file output functions */
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. */
580 /* Add a new vms_section structure to vms_section_table
581 - forward chaining - */
583 static vms_section *
584 add_new_contents (abfd, section)
585 bfd *abfd;
586 sec_ptr section;
588 vms_section *sptr, *newptr;
590 sptr = PRIV (vms_section_table)[section->index];
591 if (sptr != NULL)
592 return sptr;
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;
607 /* Save section data & offset to an vms_section structure
608 vms_section_table[] holds the vms_section chain */
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;
618 vms_section *sptr;
620 if (section->index >= VMS_SECTION_COUNT)
622 bfd_set_error (bfd_error_nonrepresentable_section);
623 return false;
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);
632 return true;
635 /* Get vms_section pointer to saved contents for section # index */
637 vms_section *
638 _bfd_get_vms_section (abfd, index)
639 bfd *abfd;
640 int index;
642 if (index >= VMS_SECTION_COUNT)
644 bfd_set_error (bfd_error_nonrepresentable_section);
645 return NULL;
647 return PRIV (vms_section_table)[index];
650 /* Object output routines */
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) */
657 void
658 _bfd_vms_output_begin (abfd, rectype, rechead)
659 bfd *abfd;
660 int rectype;
661 int rechead;
663 #if VMS_DEBUG
664 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
665 rechead);
666 #endif
668 _bfd_vms_output_short (abfd,rectype);
670 /* save current output position to fill in lenght later */
672 if (PRIV (push_level) > 0)
673 PRIV (length_pos) = PRIV (output_size);
675 #if VMS_DEBUG
676 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
677 PRIV (length_pos));
678 #endif
680 _bfd_vms_output_short (abfd,0); /* placeholder for length */
682 if (rechead != -1)
683 _bfd_vms_output_short (abfd,rechead);
685 return;
688 /* Set record/subrecord alignment */
690 void
691 _bfd_vms_output_alignment (abfd, alignto)
692 bfd *abfd;
693 int alignto;
695 #if VMS_DEBUG
696 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
697 #endif
699 PRIV (output_alignment) = alignto;
700 return;
703 /* Prepare for subrecord fields */
705 void
706 _bfd_vms_output_push (abfd)
707 bfd *abfd;
709 #if VMS_DEBUG
710 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size));
711 #endif
713 PRIV (push_level)++;
714 PRIV (pushed_size) = PRIV (output_size);
715 return;
718 /* End of subrecord fields */
720 void
721 _bfd_vms_output_pop (abfd)
722 bfd *abfd;
724 #if VMS_DEBUG
725 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size));
726 #endif
728 _bfd_vms_output_flush (abfd);
729 PRIV (length_pos) = 2;
731 #if VMS_DEBUG
732 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
733 #endif
735 PRIV (pushed_size) = 0;
736 PRIV (push_level)--;
737 return;
740 /* Flush unwritten output, ends current record */
742 void
743 _bfd_vms_output_flush (abfd)
744 bfd *abfd;
746 int real_size = PRIV (output_size);
747 int aligncount;
748 int length;
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
755 if (PRIV (push_level) > 0)
756 length = real_size - PRIV (pushed_size);
757 else
758 length = real_size;
760 if (length == 0)
761 return;
762 aligncount = (PRIV (output_alignment)
763 - (length % PRIV (output_alignment))) % PRIV (output_alignment);
765 #if VMS_DEBUG
766 vms_debug (6, "align: adding %d bytes\n", aligncount);
767 #endif
769 while (aligncount-- > 0)
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++;
781 /* put length to buffer */
782 PRIV (output_size) = PRIV (length_pos);
783 _bfd_vms_output_short (abfd, (unsigned int)length);
785 if (PRIV (push_level) == 0)
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);
793 PRIV (output_size) = 0;
795 else
797 PRIV (output_size) = real_size;
798 PRIV (pushed_size) = PRIV (output_size);
801 return;
804 /* End record output */
806 void
807 _bfd_vms_output_end (abfd)
808 bfd *abfd;
810 #if VMS_DEBUG
811 vms_debug (6, "_bfd_vms_output_end\n");
812 #endif
814 _bfd_vms_output_flush (abfd);
816 return;
819 /* check remaining buffer size
821 return what's left. */
824 _bfd_vms_output_check (abfd, size)
825 bfd *abfd;
826 int size;
828 #if VMS_DEBUG
829 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
830 #endif
832 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
835 /* Output byte (8 bit) value */
837 void
838 _bfd_vms_output_byte (abfd, value)
839 bfd *abfd;
840 unsigned int value;
842 #if VMS_DEBUG
843 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
844 #endif
846 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
847 PRIV (output_size) += 1;
848 return;
851 /* Output short (16 bit) value */
853 void
854 _bfd_vms_output_short (abfd, value)
855 bfd *abfd;
856 unsigned int value;
858 #if VMS_DEBUG
859 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
860 #endif
862 bfd_put_16 (abfd, value & 0xffff, PRIV (output_buf) + PRIV (output_size));
863 PRIV (output_size) += 2;
864 return;
867 /* Output long (32 bit) value */
869 void
870 _bfd_vms_output_long (abfd, value)
871 bfd *abfd;
872 unsigned long value;
874 #if VMS_DEBUG
875 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
876 #endif
878 bfd_put_32 (abfd, value, PRIV (output_buf) + PRIV (output_size));
879 PRIV (output_size) += 4;
880 return;
883 /* Output quad (64 bit) value */
885 void
886 _bfd_vms_output_quad (abfd, value)
887 bfd *abfd;
888 uquad value;
890 #if VMS_DEBUG
891 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
892 #endif
894 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
895 PRIV (output_size) += 8;
896 return;
899 /* Output c-string as counted string */
901 void
902 _bfd_vms_output_counted (abfd, value)
903 bfd *abfd;
904 char *value;
906 int len;
908 #if VMS_DEBUG
909 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
910 #endif
912 len = strlen (value);
913 if (len == 0)
915 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
916 return;
918 if (len > 255)
920 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
921 return;
923 _bfd_vms_output_byte (abfd, len & 0xff);
924 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
927 /* Output character area */
929 void
930 _bfd_vms_output_dump (abfd, data, length)
931 bfd *abfd;
932 unsigned char *data;
933 int length;
935 #if VMS_DEBUG
936 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
937 #endif
939 if (length == 0)
940 return;
942 memcpy (PRIV (output_buf) + PRIV (output_size), data, length);
943 PRIV (output_size) += length;
945 return;
948 /* Output count bytes of value */
950 void
951 _bfd_vms_output_fill (abfd, value, count)
952 bfd *abfd;
953 int value;
954 int count;
956 #if VMS_DEBUG
957 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
958 #endif
960 if (count == 0)
961 return;
962 memset (PRIV (output_buf) + PRIV (output_size), value, count);
963 PRIV (output_size) += count;
965 return;
968 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
970 static int
971 hash_string (ptr)
972 const char *ptr;
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;
979 while (p != end)
981 c = *p++;
982 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
984 return hash;
987 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
989 char *
990 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
991 bfd *abfd;
992 const char *in;
993 int maxlen;
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;
1003 #if VMS_DEBUG
1004 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1005 #endif
1007 if (maxlen > EOBJ_S_C_SYMSIZ)
1008 maxlen = EOBJ_S_C_SYMSIZ;
1010 new_name = out; /* save this for later. */
1012 /* We may need to truncate the symbol, save the hash for later. */
1014 in_len = strlen (in);
1016 result = (in_len > maxlen) ? hash_string (in) : 0;
1018 old_name = in;
1020 /* Do the length checking. */
1022 if (in_len <= maxlen)
1024 i = in_len;
1026 else
1028 if (PRIV (flag_hash_long_names))
1029 i = maxlen-9;
1030 else
1031 i = maxlen;
1034 strncpy (out, in, i);
1035 in += i;
1036 out += i;
1038 if ((in_len > maxlen)
1039 && PRIV (flag_hash_long_names))
1040 sprintf (out, "_%08lx", result);
1041 else
1042 *out = 0;
1044 #if VMS_DEBUG
1045 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1046 #endif
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);
1053 return outbuf;
1056 /* Allocate and initialize a new symbol. */
1058 static asymbol *
1059 new_symbol (abfd, name)
1060 bfd *abfd;
1061 char *name;
1063 asymbol *symbol;
1065 #if VMS_DEBUG
1066 _bfd_vms_debug (7, "new_symbol %s\n", name);
1067 #endif
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);
1075 return symbol;
1078 /* Allocate and enter a new private symbol. */
1080 vms_symbol_entry *
1081 _bfd_vms_enter_symbol (abfd, name)
1082 bfd *abfd;
1083 char *name;
1085 vms_symbol_entry *entry;
1087 #if VMS_DEBUG
1088 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1089 #endif
1091 entry = (vms_symbol_entry *)
1092 bfd_hash_lookup (PRIV (vms_symbol_table), name, false, false);
1093 if (entry == 0)
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)
1101 asymbol *symbol;
1102 symbol = new_symbol (abfd, name);
1103 if (symbol != 0)
1105 entry->symbol = symbol;
1106 PRIV (gsd_sym_count)++;
1107 abfd->symcount++;
1109 else
1110 entry = 0;
1112 else
1113 (*_bfd_error_handler) (_("failed to enter %s"), name);
1115 else
1117 #if VMS_DEBUG
1118 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1119 #endif
1122 #if VMS_DEBUG
1123 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1124 #endif
1125 return entry;