* tic54x-opc.c: Add default initializers to avoid warnings.
[binutils.git] / bfd / vms-misc.c
blobce66a27678f05cabdbf71d87d9d889eaee42f4ec
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 /*-----------------------------------------------------------------------------*/
34 #if VMS_DEBUG
35 /* debug functions */
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
42 levels:
43 1 toplevel bfd calls (functions from the bfd vector)
44 2 functions called by bfd calls
45 ...
46 9 almost everything
48 level is also identation level. Indentation is performed
49 if level > 0
52 #if __STDC__
53 void
54 _bfd_vms_debug (int level, char *format, ...)
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;
62 if (min_level == -1)
64 if ((eptr = getenv("VMS_DEBUG")) != NULL)
66 min_level = atoi(eptr);
67 output = stderr;
69 else
70 min_level = 0;
72 if (output == NULL)
73 return;
74 if (abslvl > min_level)
75 return;
77 while (--level>0)
78 fprintf (output, " ");
79 va_start(args, format);
80 vfprintf (output, format, args);
81 fflush(output);
82 va_end(args);
84 return;
87 #else /* not __STDC__ */
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;
96 static int min_level = -1;
97 static FILE *output = NULL;
98 char *eptr;
100 if (min_level == -1)
102 if ((eptr = getenv("VMS_DEBUG")) != NULL)
104 min_level = atoi(eptr);
105 output = stderr;
107 else
108 min_level = 0;
110 if (output == NULL)
111 return;
112 if (level > min_level)
113 return;
115 while (--level>0)
116 fprintf (output, " ");
117 fprintf (output, format, a1, a2, a3, a4, a5, a6);
118 fflush(output);
120 return;
122 #endif /* __STDC__ */
124 /* a debug function
125 hex dump 'size' bytes starting at 'ptr' */
127 void
128 _bfd_hexdump (level, ptr, size, offset)
129 int level;
130 unsigned char *ptr;
131 int size;
132 int offset;
134 unsigned char *lptr = ptr;
135 int count = 0;
136 long start = offset;
138 while (size-- > 0)
140 if ((count%16) == 0)
141 vms_debug (level, "%08lx:", start);
142 vms_debug (-level, " %02x", *ptr++);
143 count++;
144 start++;
145 if (size == 0)
147 while ((count%16) != 0)
149 vms_debug (-level, " ");
150 count++;
153 if ((count%16) == 0)
155 vms_debug (-level, " ");
156 while (lptr < ptr)
158 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
159 lptr++;
161 vms_debug (-level, "\n");
164 if ((count%16) != 0)
165 vms_debug (-level, "\n");
167 return;
169 #endif
171 /* hash functions
173 These are needed when reading an object file. */
175 /* allocate new vms_hash_entry
176 keep the symbol name and a pointer to the bfd symbol in the table */
178 struct bfd_hash_entry *
179 _bfd_vms_hash_newfunc (entry, table, string)
180 struct bfd_hash_entry *entry;
181 struct bfd_hash_table *table;
182 const char *string;
184 vms_symbol_entry *ret;
186 #if VMS_DEBUG
187 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
188 #endif
190 if (entry == (struct bfd_hash_entry *)NULL)
192 ret = (vms_symbol_entry *)
193 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
194 if (ret == (vms_symbol_entry *) NULL)
196 bfd_set_error (bfd_error_no_memory);
197 return (struct bfd_hash_entry *)NULL;
199 entry = (struct bfd_hash_entry *) ret;
202 /* Call the allocation method of the base class. */
204 ret = (vms_symbol_entry *) bfd_hash_newfunc (entry, table, string);
205 #if VMS_DEBUG
206 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
207 #endif
209 ret->symbol = (asymbol *)NULL;
211 return (struct bfd_hash_entry *)ret;
214 /* object file input functions */
216 /* Return type and length from record header (buf) on Alpha. */
218 void
219 _bfd_vms_get_header_values (abfd, buf, type, length)
220 bfd *abfd ATTRIBUTE_UNUSED;
221 unsigned char *buf;
222 int *type;
223 int *length;
225 if (type != 0)
226 *type = bfd_getl16 (buf);
227 buf += 2;
228 if (length != 0)
229 *length = bfd_getl16 (buf);
231 #if VMS_DEBUG
232 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
233 #endif
235 return;
238 /* Get next record from object file to vms_buf
239 set PRIV(buf_size) and return it
241 this is a little tricky since it should be portable.
243 the openVMS object file has 'variable length' which means that
244 read() returns data in chunks of (hopefully) correct and expected
245 size. The linker (and other tools on vms) depend on that. Unix doesn't
246 know about 'formatted' files, so reading and writing such an object
247 file in a unix environment is not trivial.
249 With the tool 'file' (available on all vms ftp sites), one
250 can view and change the attributes of a file. Changing from
251 'variable length' to 'fixed length, 512 bytes' reveals the
252 record length at the first 2 bytes of every record. The same
253 happens during the transfer of object files from vms to unix,
254 at least with ucx, dec's implementation of tcp/ip.
256 The vms format repeats the length at bytes 2 & 3 of every record.
258 On the first call (file_format == FF_UNKNOWN) we check if
259 the first and the third byte pair (!) of the record match.
260 If they do it's an object file in an unix environment or with
261 wrong attributes (FF_FOREIGN), else we should be in a vms
262 environment where read() returns the record size (FF_NATIVE).
264 reading is always done in 2 steps.
265 first just the record header is read and the length extracted
266 by get_header_values
267 then the read buffer is adjusted and the remaining bytes are
268 read in.
270 all file i/o is always done on even file positions */
273 _bfd_vms_get_record (abfd)
274 bfd *abfd;
276 int test_len, test_start, remaining;
277 unsigned char *vms_buf;
279 #if VMS_DEBUG
280 vms_debug (8, "_bfd_vms_get_record\n");
281 #endif
283 /* minimum is 6 bytes on Alpha
284 (2 bytes length, 2 bytes record id, 2 bytes length repeated)
286 on VAX there's no length information in the record
287 so start with OBJ_S_C_MAXRECSIZ */
289 if (PRIV (buf_size) == 0)
291 if (PRIV (is_vax))
293 PRIV (vms_buf) = (unsigned char *) malloc (OBJ_S_C_MAXRECSIZ);
294 PRIV (buf_size) = OBJ_S_C_MAXRECSIZ;
295 PRIV (file_format) = FF_VAX;
297 else
298 PRIV (vms_buf) = (unsigned char *) malloc (6);
301 vms_buf = PRIV (vms_buf);
303 if (vms_buf == 0)
305 bfd_set_error (bfd_error_no_memory);
306 return -1;
309 switch (PRIV (file_format))
311 case FF_UNKNOWN:
312 case FF_FOREIGN:
313 test_len = 6; /* probe 6 bytes */
314 test_start = 2; /* where the record starts */
315 break;
317 case FF_NATIVE:
318 test_len = 4;
319 test_start = 0;
320 break;
322 default:
323 case FF_VAX:
324 test_len = 0;
325 test_start = 0;
326 break;
329 /* skip odd alignment byte */
331 if (bfd_tell (abfd) & 1)
333 if (bfd_read (PRIV (vms_buf), 1, 1, abfd) != 1)
335 bfd_set_error (bfd_error_file_truncated);
336 return 0;
340 /* read the record header on Alpha. */
342 if ((test_len != 0)
343 && (bfd_read (PRIV (vms_buf), 1, test_len, abfd)
344 != (bfd_size_type) test_len))
346 bfd_set_error (bfd_error_file_truncated);
347 return 0;
350 /* check file format on first call */
352 if (PRIV (file_format) == FF_UNKNOWN)
353 { /* record length repeats ? */
354 if ( (vms_buf[0] == vms_buf[4])
355 && (vms_buf[1] == vms_buf[5]))
357 PRIV (file_format) = FF_FOREIGN; /* Y: foreign environment */
358 test_start = 2;
360 else
362 PRIV (file_format) = FF_NATIVE; /* N: native environment */
363 test_start = 0;
367 if (PRIV (is_vax))
369 PRIV (rec_length) = bfd_read (vms_buf, 1, PRIV (buf_size), abfd);
370 if (PRIV (rec_length) <= 0)
372 bfd_set_error (bfd_error_file_truncated);
373 return 0;
375 PRIV (vms_rec) = vms_buf;
377 else /* Alpha */
379 /* extract vms record length */
381 _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
382 &PRIV (rec_length));
384 if (PRIV (rec_length) <= 0)
386 bfd_set_error (bfd_error_file_truncated);
387 return 0;
390 /* that's what the linker manual says */
392 if (PRIV (rec_length) > EOBJ_S_C_MAXRECSIZ)
394 bfd_set_error (bfd_error_file_truncated);
395 return 0;
398 /* adjust the buffer */
400 if (PRIV (rec_length) > PRIV (buf_size))
402 PRIV (vms_buf) = (unsigned char *) realloc (vms_buf, PRIV (rec_length));
403 vms_buf = PRIV (vms_buf);
404 if (vms_buf == 0)
406 bfd_set_error (bfd_error_no_memory);
407 return -1;
409 PRIV (buf_size) = PRIV (rec_length);
412 /* read the remaining record */
414 remaining = PRIV (rec_length) - test_len + test_start;
416 #if VMS_DEBUG
417 vms_debug (10, "bfd_read remaining %d\n", remaining);
418 #endif
419 if (bfd_read (vms_buf + test_len, 1, remaining, abfd) !=
420 (bfd_size_type) remaining)
422 bfd_set_error (bfd_error_file_truncated);
423 return 0;
425 PRIV (vms_rec) = vms_buf + test_start;
428 #if VMS_DEBUG
429 vms_debug (11, "bfd_read rec_length %d\n", PRIV (rec_length));
430 #endif
432 return PRIV (rec_length);
435 /* get next vms record from file
436 update vms_rec and rec_length to new (remaining) values */
439 _bfd_vms_next_record (abfd)
440 bfd *abfd;
442 #if VMS_DEBUG
443 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
444 PRIV (rec_length), PRIV (rec_size));
445 #endif
447 if (PRIV (rec_length) > 0)
449 PRIV (vms_rec) += PRIV (rec_size);
451 else
453 if (_bfd_vms_get_record (abfd) <= 0)
454 return -1;
457 if (!PRIV (vms_rec) || !PRIV (vms_buf)
458 || PRIV (vms_rec) >= (PRIV (vms_buf) + PRIV (buf_size)))
459 return -1;
461 if (PRIV (is_vax))
463 PRIV (rec_type) = *(PRIV (vms_rec));
464 PRIV (rec_size) = PRIV (rec_length);
466 else
468 _bfd_vms_get_header_values (abfd, PRIV (vms_rec), &PRIV (rec_type),
469 &PRIV (rec_size));
471 PRIV (rec_length) -= PRIV (rec_size);
473 #if VMS_DEBUG
474 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
475 PRIV (vms_rec), PRIV (rec_size), PRIV (rec_length),
476 PRIV (rec_type));
477 #endif
479 return PRIV (rec_type);
482 /* Copy sized string (string with fixed length) to new allocated area
483 size is string length (size of record) */
485 char *
486 _bfd_vms_save_sized_string (str, size)
487 unsigned char *str;
488 int size;
490 char *newstr = bfd_malloc (size + 1);
492 if (newstr == NULL)
493 return 0;
494 strncpy (newstr, (char *)str, size);
495 newstr[size] = 0;
497 return newstr;
500 /* Copy counted string (string with length at first byte) to new allocated area
501 ptr points to length byte on entry */
503 char *
504 _bfd_vms_save_counted_string (ptr)
505 unsigned char *ptr;
507 int len = *ptr++;
509 return _bfd_vms_save_sized_string (ptr, len);
512 /* stack routines for vms ETIR commands */
514 /* Push value and section index */
516 void
517 _bfd_vms_push (abfd, val, psect)
518 bfd *abfd;
519 uquad val;
520 int psect;
522 static int last_psect;
524 #if VMS_DEBUG
525 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV (stackptr));
526 #endif
528 if (psect >= 0)
529 last_psect = psect;
531 PRIV (stack[PRIV (stackptr)]).value = val;
532 PRIV (stack[PRIV (stackptr)]).psect = last_psect;
533 PRIV (stackptr)++;
534 if (PRIV (stackptr) >= STACKSIZE)
536 bfd_set_error (bfd_error_bad_value);
537 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
538 exit (1);
540 return;
543 /* Pop value and section index */
545 uquad
546 _bfd_vms_pop (abfd, psect)
547 bfd *abfd;
548 int *psect;
550 uquad value;
552 if (PRIV (stackptr) == 0)
554 bfd_set_error (bfd_error_bad_value);
555 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
556 exit (1);
558 PRIV (stackptr)--;
559 value = PRIV (stack[PRIV (stackptr)]).value;
560 if ((psect != NULL) && (PRIV (stack[PRIV (stackptr)]).psect >= 0))
561 *psect = PRIV (stack[PRIV (stackptr)]).psect;
563 #if VMS_DEBUG
564 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV (stack[PRIV (stackptr)]).psect);
565 #endif
567 return value;
570 /* object file output functions */
572 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
573 which we can't use directly. So we save the little chunks in linked
574 lists (one per section) and write them later. */
576 /* Add a new vms_section structure to vms_section_table
577 - forward chaining - */
579 static vms_section *
580 add_new_contents (abfd, section)
581 bfd *abfd;
582 sec_ptr section;
584 vms_section *sptr, *newptr;
586 sptr = PRIV (vms_section_table)[section->index];
587 if (sptr != NULL)
588 return sptr;
590 newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
591 if (newptr == (vms_section *) NULL)
592 return NULL;
593 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
594 if (newptr->contents == (unsigned char *)NULL)
595 return NULL;
596 newptr->offset = 0;
597 newptr->size = section->_raw_size;
598 newptr->next = 0;
599 PRIV (vms_section_table)[section->index] = newptr;
600 return newptr;
603 /* Save section data & offset to an vms_section structure
604 vms_section_table[] holds the vms_section chain */
606 boolean
607 _bfd_save_vms_section (abfd, section, data, offset, count)
608 bfd *abfd;
609 sec_ptr section;
610 PTR data;
611 file_ptr offset;
612 bfd_size_type count;
614 vms_section *sptr;
616 if (section->index >= VMS_SECTION_COUNT)
618 bfd_set_error (bfd_error_nonrepresentable_section);
619 return false;
621 if (count == (bfd_size_type)0)
622 return true;
623 sptr = add_new_contents (abfd, section);
624 if (sptr == NULL)
625 return false;
626 memcpy (sptr->contents + offset, data, (size_t) count);
628 return true;
631 /* Get vms_section pointer to saved contents for section # index */
633 vms_section *
634 _bfd_get_vms_section (abfd, index)
635 bfd *abfd;
636 int index;
638 if (index >= VMS_SECTION_COUNT)
640 bfd_set_error (bfd_error_nonrepresentable_section);
641 return NULL;
643 return PRIV (vms_section_table)[index];
646 /* Object output routines */
648 /* Begin new record or record header
649 write 2 bytes rectype
650 write 2 bytes record length (filled in at flush)
651 write 2 bytes header type (ommitted if rechead == -1) */
653 void
654 _bfd_vms_output_begin (abfd, rectype, rechead)
655 bfd *abfd;
656 int rectype;
657 int rechead;
659 #if VMS_DEBUG
660 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
661 rechead);
662 #endif
664 _bfd_vms_output_short (abfd,rectype);
666 /* save current output position to fill in lenght later */
668 if (PRIV (push_level) > 0)
669 PRIV (length_pos) = PRIV (output_size);
671 #if VMS_DEBUG
672 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
673 PRIV (length_pos));
674 #endif
676 _bfd_vms_output_short (abfd,0); /* placeholder for length */
678 if (rechead != -1)
679 _bfd_vms_output_short (abfd,rechead);
681 return;
684 /* Set record/subrecord alignment */
686 void
687 _bfd_vms_output_alignment (abfd, alignto)
688 bfd *abfd;
689 int alignto;
691 #if VMS_DEBUG
692 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
693 #endif
695 PRIV (output_alignment) = alignto;
696 return;
699 /* Prepare for subrecord fields */
701 void
702 _bfd_vms_output_push (abfd)
703 bfd *abfd;
705 #if VMS_DEBUG
706 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV (output_size));
707 #endif
709 PRIV (push_level)++;
710 PRIV (pushed_size) = PRIV (output_size);
711 return;
714 /* End of subrecord fields */
716 void
717 _bfd_vms_output_pop (abfd)
718 bfd *abfd;
720 #if VMS_DEBUG
721 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV (pushed_size));
722 #endif
724 _bfd_vms_output_flush (abfd);
725 PRIV (length_pos) = 2;
727 #if VMS_DEBUG
728 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV (length_pos));
729 #endif
731 PRIV (pushed_size) = 0;
732 PRIV (push_level)--;
733 return;
736 /* Flush unwritten output, ends current record */
738 void
739 _bfd_vms_output_flush (abfd)
740 bfd *abfd;
742 int real_size = PRIV (output_size);
743 int aligncount;
744 int length;
746 #if VMS_DEBUG
747 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
748 real_size, PRIV (pushed_size), PRIV (length_pos));
749 #endif
751 if (PRIV (push_level) > 0)
752 length = real_size - PRIV (pushed_size);
753 else
754 length = real_size;
756 if (length == 0)
757 return;
758 aligncount = (PRIV (output_alignment)
759 - (length % PRIV (output_alignment))) % PRIV (output_alignment);
761 #if VMS_DEBUG
762 vms_debug (6, "align: adding %d bytes\n", aligncount);
763 #endif
765 while (aligncount-- > 0)
767 PRIV (output_buf)[real_size++] = 0;
768 #if 0
769 /* this is why I *love* vms: inconsistency :-}
770 alignment is added to the subrecord length
771 but not to the record length */
772 if (PRIV (push_level) > 0)
773 #endif
774 length++;
777 /* put length to buffer */
778 PRIV (output_size) = PRIV (length_pos);
779 _bfd_vms_output_short (abfd, (unsigned int)length);
781 if (PRIV (push_level) == 0)
783 #ifndef VMS
784 /* write length first, see FF_FOREIGN in the input routines */
785 fwrite (PRIV (output_buf)+2, 2, 1, (FILE *)abfd->iostream);
786 #endif
787 fwrite (PRIV (output_buf), real_size, 1, (FILE *)abfd->iostream);
789 PRIV (output_size) = 0;
791 else
793 PRIV (output_size) = real_size;
794 PRIV (pushed_size) = PRIV (output_size);
797 return;
800 /* End record output */
802 void
803 _bfd_vms_output_end (abfd)
804 bfd *abfd;
806 #if VMS_DEBUG
807 vms_debug (6, "_bfd_vms_output_end\n");
808 #endif
810 _bfd_vms_output_flush (abfd);
812 return;
815 /* check remaining buffer size
817 return what's left. */
820 _bfd_vms_output_check (abfd, size)
821 bfd *abfd;
822 int size;
824 #if VMS_DEBUG
825 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
826 #endif
828 return (MAX_OUTREC_SIZE - (PRIV (output_size) + size + MIN_OUTREC_LUFT));
831 /* Output byte (8 bit) value */
833 void
834 _bfd_vms_output_byte (abfd, value)
835 bfd *abfd;
836 unsigned int value;
838 #if VMS_DEBUG
839 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
840 #endif
842 bfd_put_8 (abfd, value & 0xff, PRIV (output_buf) + PRIV (output_size));
843 PRIV (output_size) += 1;
844 return;
847 /* Output short (16 bit) value */
849 void
850 _bfd_vms_output_short (abfd, value)
851 bfd *abfd;
852 unsigned int value;
854 #if VMS_DEBUG
855 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
856 #endif
858 bfd_put_16 (abfd, value & 0xffff, PRIV (output_buf) + PRIV (output_size));
859 PRIV (output_size) += 2;
860 return;
863 /* Output long (32 bit) value */
865 void
866 _bfd_vms_output_long (abfd, value)
867 bfd *abfd;
868 unsigned long value;
870 #if VMS_DEBUG
871 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
872 #endif
874 bfd_put_32 (abfd, value, PRIV (output_buf) + PRIV (output_size));
875 PRIV (output_size) += 4;
876 return;
879 /* Output quad (64 bit) value */
881 void
882 _bfd_vms_output_quad (abfd, value)
883 bfd *abfd;
884 uquad value;
886 #if VMS_DEBUG
887 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
888 #endif
890 bfd_put_64(abfd, value, PRIV (output_buf) + PRIV (output_size));
891 PRIV (output_size) += 8;
892 return;
895 /* Output c-string as counted string */
897 void
898 _bfd_vms_output_counted (abfd, value)
899 bfd *abfd;
900 char *value;
902 int len;
904 #if VMS_DEBUG
905 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
906 #endif
908 len = strlen (value);
909 if (len == 0)
911 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
912 return;
914 if (len > 255)
916 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
917 return;
919 _bfd_vms_output_byte (abfd, len & 0xff);
920 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
923 /* Output character area */
925 void
926 _bfd_vms_output_dump (abfd, data, length)
927 bfd *abfd;
928 unsigned char *data;
929 int length;
931 #if VMS_DEBUG
932 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
933 #endif
935 if (length == 0)
936 return;
938 memcpy (PRIV (output_buf) + PRIV (output_size), data, length);
939 PRIV (output_size) += length;
941 return;
944 /* Output count bytes of value */
946 void
947 _bfd_vms_output_fill (abfd, value, count)
948 bfd *abfd;
949 int value;
950 int count;
952 #if VMS_DEBUG
953 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
954 #endif
956 if (count == 0)
957 return;
958 memset (PRIV (output_buf) + PRIV (output_size), value, count);
959 PRIV (output_size) += count;
961 return;
964 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
966 static int
967 hash_string (ptr)
968 const char *ptr;
970 register const unsigned char *p = (unsigned char *) ptr;
971 register const unsigned char *end = p + strlen (ptr);
972 register unsigned char c;
973 register int hash = 0;
975 while (p != end)
977 c = *p++;
978 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
980 return hash;
983 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
985 char *
986 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
987 bfd *abfd;
988 const char *in;
989 int maxlen;
991 long int result;
992 int in_len;
993 char *new_name;
994 const char *old_name;
995 int i;
996 static char outbuf[EOBJ_S_C_SYMSIZ+1];
997 char *out = outbuf;
999 #if VMS_DEBUG
1000 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1001 #endif
1003 if (maxlen > EOBJ_S_C_SYMSIZ)
1004 maxlen = EOBJ_S_C_SYMSIZ;
1006 new_name = out; /* save this for later. */
1008 /* We may need to truncate the symbol, save the hash for later. */
1010 in_len = strlen (in);
1012 result = (in_len > maxlen) ? hash_string (in) : 0;
1014 old_name = in;
1016 /* Do the length checking. */
1018 if (in_len <= maxlen)
1020 i = in_len;
1022 else
1024 if (PRIV (flag_hash_long_names))
1025 i = maxlen-9;
1026 else
1027 i = maxlen;
1030 strncpy (out, in, i);
1031 in += i;
1032 out += i;
1034 if ((in_len > maxlen)
1035 && PRIV (flag_hash_long_names))
1036 sprintf (out, "_%08lx", result);
1037 else
1038 *out = 0;
1040 #if VMS_DEBUG
1041 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1042 #endif
1044 if (in_len > maxlen
1045 && PRIV (flag_hash_long_names)
1046 && PRIV (flag_show_after_trunc))
1047 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1049 return outbuf;
1052 /* Allocate and initialize a new symbol. */
1054 static asymbol *
1055 new_symbol (abfd, name)
1056 bfd *abfd;
1057 char *name;
1059 asymbol *symbol;
1061 #if VMS_DEBUG
1062 _bfd_vms_debug (7, "new_symbol %s\n", name);
1063 #endif
1065 symbol = _bfd_vms_make_empty_symbol (abfd);
1066 if (symbol == 0)
1067 return symbol;
1068 symbol->name = name;
1069 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1071 return symbol;
1074 /* Allocate and enter a new private symbol. */
1076 vms_symbol_entry *
1077 _bfd_vms_enter_symbol (abfd, name)
1078 bfd *abfd;
1079 char *name;
1081 vms_symbol_entry *entry;
1083 #if VMS_DEBUG
1084 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1085 #endif
1087 entry = (vms_symbol_entry *)
1088 bfd_hash_lookup (PRIV (vms_symbol_table), name, false, false);
1089 if (entry == 0)
1091 #if VMS_DEBUG
1092 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1093 #endif
1094 entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV (vms_symbol_table), name, true, false);
1095 if (entry != 0)
1097 asymbol *symbol;
1098 symbol = new_symbol (abfd, name);
1099 if (symbol != 0)
1101 entry->symbol = symbol;
1102 PRIV (gsd_sym_count)++;
1103 abfd->symcount++;
1105 else
1106 entry = 0;
1108 else
1109 (*_bfd_error_handler) (_("failed to enter %s"), name);
1111 else
1113 #if VMS_DEBUG
1114 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1115 #endif
1118 #if VMS_DEBUG
1119 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1120 #endif
1121 return entry;