Initial revision
[binutils.git] / bfd / vms-misc.c
bloba5fdae4cc28108faf4f672a697bd16e63caabd03
1 /* vms-misc.c -- Miscellaneous functions for VAX (openVMS/VAX) and
2 EVAX (openVMS/Alpha) files.
3 Copyright 1996, 1997, 1998 Free Software Foundation, Inc.
5 Written by Klaus K"ampf (kkaempf@rmi.de)
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.
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.
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. */
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__ */
125 /* a debug function
126 hex dump 'size' bytes starting at 'ptr' */
128 void
129 _bfd_hexdump (level, ptr, size, offset)
130 int level;
131 unsigned char *ptr;
132 int size;
133 int offset;
135 unsigned char *lptr = ptr;
136 int count = 0;
137 long start = offset;
139 while (size-- > 0)
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)
148 while ((count%16) != 0)
150 vms_debug (-level, " ");
151 count++;
154 if ((count%16) == 0)
156 vms_debug (-level, " ");
157 while (lptr < ptr)
159 vms_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
160 lptr++;
162 vms_debug (-level, "\n");
165 if ((count%16) != 0)
166 vms_debug (-level, "\n");
168 return;
170 #endif
173 /* hash functions
175 These are needed when reading an object file. */
177 /* allocate new vms_hash_entry
178 keep the symbol name and a pointer to the bfd symbol in the table */
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;
186 vms_symbol_entry *ret;
188 #if VMS_DEBUG
189 vms_debug (5, "_bfd_vms_hash_newfunc(%p, %p, %s)\n", entry, table, string);
190 #endif
192 if (entry == (struct bfd_hash_entry *)NULL)
194 ret = (vms_symbol_entry *)
195 bfd_hash_allocate (table, sizeof (vms_symbol_entry));
196 if (ret == (vms_symbol_entry *) NULL)
198 bfd_set_error (bfd_error_no_memory);
199 return (struct bfd_hash_entry *)NULL;
203 /* Call the allocation method of the base class. */
205 ret = (vms_symbol_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *)ret, table, string);
206 #if VMS_DEBUG
207 vms_debug (6, "_bfd_vms_hash_newfunc ret %p\n", ret);
208 #endif
210 ret->symbol = (asymbol *)NULL;
212 return (struct bfd_hash_entry *)ret;
216 /* object file input functions */
218 /* Return type and length from record header (buf) on Alpha. */
220 void
221 _bfd_vms_get_header_values (abfd, buf, type, length)
222 bfd *abfd;
223 unsigned char *buf;
224 int *type;
225 int *length;
227 if (type != 0)
228 *type = bfd_getl16 (buf);
229 buf += 2;
230 if (length != 0)
231 *length = bfd_getl16 (buf);
233 #if VMS_DEBUG
234 vms_debug (10, "_bfd_vms_get_header_values type %x, length %x\n", (type?*type:0), (length?*length:0));
235 #endif
238 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 case FF_VAX:
327 test_len = 0;
328 test_start = 0;
329 break;
332 /* skip odd alignment byte */
334 if (bfd_tell (abfd) & 1)
336 if (bfd_read (PRIV(vms_buf), 1, 1, abfd) != 1)
338 bfd_set_error (bfd_error_file_truncated);
339 return 0;
343 /* read the record header on Alpha. */
345 if ((test_len != 0)
346 && (bfd_read (PRIV(vms_buf), 1, test_len, abfd) != test_len))
348 bfd_set_error (bfd_error_file_truncated);
349 return 0;
352 /* check file format on first call */
354 if (PRIV(file_format) == FF_UNKNOWN)
355 { /* record length repeats ? */
356 if ( (vms_buf[0] == vms_buf[4])
357 && (vms_buf[1] == vms_buf[5]))
359 PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */
360 test_start = 2;
362 else
364 PRIV(file_format) = FF_NATIVE; /* N: native environment */
365 test_start = 0;
369 if (PRIV(is_vax))
371 PRIV(rec_length) = bfd_read (vms_buf, 1, PRIV(buf_size), abfd);
372 if (PRIV(rec_length) <= 0)
374 bfd_set_error (bfd_error_file_truncated);
375 return 0;
377 PRIV(vms_rec) = vms_buf;
379 else /* Alpha */
381 /* extract vms record length */
383 _bfd_vms_get_header_values (abfd, vms_buf+test_start, NULL,
384 &PRIV(rec_length));
386 if (PRIV(rec_length) <= 0)
388 bfd_set_error (bfd_error_file_truncated);
389 return 0;
392 /* that's what the linker manual says */
394 if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ)
396 bfd_set_error (bfd_error_file_truncated);
397 return 0;
400 /* adjust the buffer */
402 if (PRIV(rec_length) > PRIV(buf_size))
404 PRIV(vms_buf) = (unsigned char *) realloc (vms_buf, PRIV(rec_length));
405 vms_buf = PRIV(vms_buf);
406 if (vms_buf == 0)
408 bfd_set_error (bfd_error_no_memory);
409 return -1;
411 PRIV(buf_size) = PRIV(rec_length);
414 /* read the remaining record */
416 remaining = PRIV(rec_length) - test_len + test_start;
418 #if VMS_DEBUG
419 vms_debug (10, "bfd_read remaining %d\n", remaining);
420 #endif
421 if (bfd_read (vms_buf + test_len, 1, remaining, abfd) != remaining)
423 bfd_set_error (bfd_error_file_truncated);
424 return 0;
426 PRIV(vms_rec) = vms_buf + test_start;
429 #if VMS_DEBUG
430 vms_debug (11, "bfd_read rec_length %d\n", PRIV(rec_length));
431 #endif
433 return PRIV(rec_length);
437 /* get next vms record from file
438 update vms_rec and rec_length to new (remaining) values */
441 _bfd_vms_next_record (abfd)
442 bfd *abfd;
444 #if VMS_DEBUG
445 vms_debug (8, "_bfd_vms_next_record (len %d, size %d)\n",
446 PRIV(rec_length), PRIV(rec_size));
447 #endif
449 if (PRIV(rec_length) > 0)
451 PRIV(vms_rec) += PRIV(rec_size);
453 else
455 if (_bfd_vms_get_record (abfd) <= 0)
456 return -1;
459 if (PRIV(is_vax))
461 PRIV(rec_type) = *(PRIV(vms_rec));
462 PRIV(rec_size) = PRIV(rec_length);
464 else
466 _bfd_vms_get_header_values (abfd, PRIV(vms_rec), &PRIV(rec_type),
467 &PRIV(rec_size));
469 PRIV(rec_length) -= PRIV(rec_size);
471 #if VMS_DEBUG
472 vms_debug (8, "_bfd_vms_next_record: rec %p, size %d, length %d, type %d\n",
473 PRIV(vms_rec), PRIV(rec_size), PRIV(rec_length),
474 PRIV(rec_type));
475 #endif
477 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);
513 /* stack routines for vms ETIR commands */
515 /* Push value and section index */
517 void
518 _bfd_vms_push (abfd, val, psect)
519 bfd *abfd;
520 uquad val;
521 int psect;
523 static int last_psect;
525 #if VMS_DEBUG
526 vms_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV(stackptr));
527 #endif
529 if (psect >= 0)
530 last_psect = psect;
532 PRIV(stack[PRIV(stackptr)]).value = val;
533 PRIV(stack[PRIV(stackptr)]).psect = last_psect;
534 PRIV(stackptr)++;
535 if (PRIV(stackptr) >= STACKSIZE)
537 bfd_set_error (bfd_error_bad_value);
538 (*_bfd_error_handler) (_("Stack overflow (%d) in _bfd_vms_push"), PRIV(stackptr));
539 exit (1);
541 return;
545 /* Pop value and section index */
547 uquad
548 _bfd_vms_pop (abfd, psect)
549 bfd *abfd;
550 int *psect;
552 uquad value;
554 if (PRIV(stackptr) == 0)
556 bfd_set_error (bfd_error_bad_value);
557 (*_bfd_error_handler) (_("Stack underflow in _bfd_vms_pop"));
558 exit (1);
560 PRIV(stackptr)--;
561 value = PRIV(stack[PRIV(stackptr)]).value;
562 if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0))
563 *psect = PRIV(stack[PRIV(stackptr)]).psect;
565 #if VMS_DEBUG
566 vms_debug (4, "<pop %016lx(%d)>\n", value, PRIV(stack[PRIV(stackptr)]).psect);
567 #endif
569 return value;
573 /* object file output functions */
575 /* GAS tends to write sections in little chunks (bfd_set_section_contents)
576 which we can't use directly. So we save the little chunks in linked
577 lists (one per section) and write them later. */
579 /* Add a new vms_section structure to vms_section_table
580 - forward chaining - */
582 static vms_section *
583 add_new_contents (abfd, section)
584 bfd *abfd;
585 sec_ptr section;
587 vms_section *sptr, *newptr;
589 sptr = PRIV(vms_section_table)[section->index];
590 if (sptr != NULL)
591 return sptr;
593 newptr = (vms_section *) bfd_malloc (sizeof (vms_section));
594 if (newptr == (vms_section *) NULL)
595 return NULL;
596 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
597 if (newptr->contents == (unsigned char *)NULL)
598 return NULL;
599 newptr->offset = 0;
600 newptr->size = section->_raw_size;
601 newptr->next = 0;
602 PRIV(vms_section_table)[section->index] = newptr;
603 return newptr;
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;
636 /* Get vms_section pointer to saved contents for section # index */
638 vms_section *
639 _bfd_get_vms_section (abfd, index)
640 bfd *abfd;
641 int index;
643 if (index >= VMS_SECTION_COUNT)
645 bfd_set_error (bfd_error_nonrepresentable_section);
646 return NULL;
648 return PRIV(vms_section_table)[index];
652 /* Object output routines */
654 /* Begin new record or record header
655 write 2 bytes rectype
656 write 2 bytes record length (filled in at flush)
657 write 2 bytes header type (ommitted if rechead == -1) */
659 void
660 _bfd_vms_output_begin (abfd, rectype, rechead)
661 bfd *abfd;
662 int rectype;
663 int rechead;
665 #if VMS_DEBUG
666 vms_debug (6, "_bfd_vms_output_begin(type %d, head %d)\n", rectype,
667 rechead);
668 #endif
670 _bfd_vms_output_short (abfd,rectype);
672 /* save current output position to fill in lenght later */
674 if (PRIV(push_level) > 0)
675 PRIV(length_pos) = PRIV(output_size);
677 #if VMS_DEBUG
678 vms_debug (6, "_bfd_vms_output_begin: length_pos = %d\n",
679 PRIV(length_pos));
680 #endif
682 _bfd_vms_output_short (abfd,0); /* placeholder for length */
684 if (rechead != -1)
685 _bfd_vms_output_short (abfd,rechead);
687 return;
691 /* Set record/subrecord alignment */
693 void
694 _bfd_vms_output_alignment (abfd, alignto)
695 bfd *abfd;
696 int alignto;
698 #if VMS_DEBUG
699 vms_debug (6, "_bfd_vms_output_alignment(%d)\n", alignto);
700 #endif
702 PRIV(output_alignment) = alignto;
703 return;
707 /* Prepare for subrecord fields */
709 void
710 _bfd_vms_output_push (abfd)
711 bfd *abfd;
713 #if VMS_DEBUG
714 vms_debug (6, "vms_output_push(pushed_size = %d)\n", PRIV(output_size));
715 #endif
717 PRIV(push_level)++;
718 PRIV(pushed_size) = PRIV(output_size);
719 return;
723 /* End of subrecord fields */
725 void
726 _bfd_vms_output_pop (abfd)
727 bfd *abfd;
729 #if VMS_DEBUG
730 vms_debug (6, "vms_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
731 #endif
733 _bfd_vms_output_flush (abfd);
734 PRIV(length_pos) = 2;
736 #if VMS_DEBUG
737 vms_debug (6, "vms_output_pop: length_pos = %d\n", PRIV(length_pos));
738 #endif
740 PRIV(pushed_size) = 0;
741 PRIV(push_level)--;
742 return;
746 /* Flush unwritten output, ends current record */
748 void
749 _bfd_vms_output_flush (abfd)
750 bfd *abfd;
752 int real_size = PRIV(output_size);
753 int aligncount;
754 int length;
756 #if VMS_DEBUG
757 vms_debug (6, "_bfd_vms_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
758 real_size, PRIV(pushed_size), PRIV(length_pos));
759 #endif
761 if (PRIV(push_level) > 0)
762 length = real_size - PRIV(pushed_size);
763 else
764 length = real_size;
766 if (length == 0)
767 return;
768 aligncount = (PRIV(output_alignment)
769 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
771 #if VMS_DEBUG
772 vms_debug (6, "align: adding %d bytes\n", aligncount);
773 #endif
775 while(aligncount-- > 0)
777 PRIV(output_buf)[real_size++] = 0;
778 #if 0
779 /* this is why I *love* vms: inconsistency :-}
780 alignment is added to the subrecord length
781 but not to the record length */
782 if (PRIV(push_level) > 0)
783 #endif
784 length++;
787 /* put length to buffer */
788 PRIV(output_size) = PRIV(length_pos);
789 _bfd_vms_output_short (abfd, (unsigned int)length);
791 if (PRIV(push_level) == 0)
793 #ifndef VMS
794 /* write length first, see FF_FOREIGN in the input routines */
795 fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
796 #endif
797 fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
799 PRIV(output_size) = 0;
801 else
803 PRIV(output_size) = real_size;
804 PRIV(pushed_size) = PRIV(output_size);
807 return;
811 /* End record output */
813 void
814 _bfd_vms_output_end (abfd)
815 bfd *abfd;
817 #if VMS_DEBUG
818 vms_debug (6, "_bfd_vms_output_end\n");
819 #endif
821 _bfd_vms_output_flush (abfd);
823 return;
827 /* check remaining buffer size
829 return what's left. */
832 _bfd_vms_output_check (abfd, size)
833 bfd *abfd;
834 int size;
836 #if VMS_DEBUG
837 vms_debug (6, "_bfd_vms_output_check(%d)\n", size);
838 #endif
840 return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
844 /* Output byte (8 bit) value */
846 void
847 _bfd_vms_output_byte (abfd, value)
848 bfd *abfd;
849 unsigned int value;
851 #if VMS_DEBUG
852 vms_debug (6, "_bfd_vms_output_byte(%02x)\n", value);
853 #endif
855 bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
856 PRIV(output_size) += 1;
857 return;
861 /* Output short (16 bit) value */
863 void
864 _bfd_vms_output_short (abfd, value)
865 bfd *abfd;
866 unsigned int value;
868 #if VMS_DEBUG
869 vms_debug (6, "_bfd_vms_output_short (%04x)\n", value);
870 #endif
872 bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
873 PRIV(output_size) += 2;
874 return;
878 /* Output long (32 bit) value */
880 void
881 _bfd_vms_output_long (abfd, value)
882 bfd *abfd;
883 unsigned long value;
885 #if VMS_DEBUG
886 vms_debug (6, "_bfd_vms_output_long (%08lx)\n", value);
887 #endif
889 bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
890 PRIV(output_size) += 4;
891 return;
895 /* Output quad (64 bit) value */
897 void
898 _bfd_vms_output_quad (abfd, value)
899 bfd *abfd;
900 uquad value;
902 #if VMS_DEBUG
903 vms_debug (6, "_bfd_vms_output_quad(%016lx)\n", value);
904 #endif
906 bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
907 PRIV(output_size) += 8;
908 return;
912 /* Output c-string as counted string */
914 void
915 _bfd_vms_output_counted (abfd, value)
916 bfd *abfd;
917 char *value;
919 int len;
921 #if VMS_DEBUG
922 vms_debug (6, "_bfd_vms_output_counted(%s)\n", value);
923 #endif
925 len = strlen (value);
926 if (len == 0)
928 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with zero bytes"));
929 return;
931 if (len > 255)
933 (*_bfd_error_handler) (_("_bfd_vms_output_counted called with too many bytes"));
934 return;
936 _bfd_vms_output_byte (abfd, len & 0xff);
937 _bfd_vms_output_dump (abfd, (unsigned char *)value, len);
941 /* Output character area */
943 void
944 _bfd_vms_output_dump (abfd, data, length)
945 bfd *abfd;
946 unsigned char *data;
947 int length;
949 #if VMS_DEBUG
950 vms_debug (6, "_bfd_vms_output_dump(%d)\n", length);
951 #endif
953 if (length == 0)
954 return;
956 memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
957 PRIV(output_size) += length;
959 return;
963 /* Output count bytes of value */
965 void
966 _bfd_vms_output_fill (abfd, value, count)
967 bfd *abfd;
968 int value;
969 int count;
971 #if VMS_DEBUG
972 vms_debug (6, "_bfd_vms_output_fill(val %02x times %d)\n", value, count);
973 #endif
975 if (count == 0)
976 return;
977 memset (PRIV(output_buf) + PRIV(output_size), value, count);
978 PRIV(output_size) += count;
980 return;
983 /* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
985 static int
986 hash_string (ptr)
987 const char *ptr;
989 register const unsigned char *p = (unsigned char *) ptr;
990 register const unsigned char *end = p + strlen (ptr);
991 register unsigned char c;
992 register int hash = 0;
994 while (p != end)
996 c = *p++;
997 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
999 return hash;
1002 /* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
1004 char *
1005 _bfd_vms_length_hash_symbol (abfd, in, maxlen)
1006 bfd *abfd;
1007 const char *in;
1008 int maxlen;
1010 long int init;
1011 long int result;
1012 int in_len;
1013 char *pnt = 0;
1014 char *new_name;
1015 const char *old_name;
1016 int i;
1017 static char outbuf[EOBJ_S_C_SYMSIZ+1];
1018 char *out = outbuf;
1020 #if VMS_DEBUG
1021 vms_debug(4, "_bfd_vms_length_hash_symbol \"%s\"\n", in);
1022 #endif
1024 if (maxlen > EOBJ_S_C_SYMSIZ)
1025 maxlen = EOBJ_S_C_SYMSIZ;
1027 new_name = out; /* save this for later. */
1029 /* We may need to truncate the symbol, save the hash for later. */
1031 in_len = strlen (in);
1033 result = (in_len > maxlen) ? hash_string (in) : 0;
1035 old_name = in;
1037 /* Do the length checking. */
1039 if (in_len <= maxlen)
1041 i = in_len;
1043 else
1045 if (PRIV(flag_hash_long_names))
1046 i = maxlen-9;
1047 else
1048 i = maxlen;
1051 strncpy (out, in, i);
1052 in += i;
1053 out += i;
1055 if ((in_len > maxlen)
1056 && PRIV(flag_hash_long_names))
1057 sprintf (out, "_%08x", result);
1058 else
1059 *out = 0;
1061 #if VMS_DEBUG
1062 vms_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
1063 #endif
1065 if (in_len > maxlen
1066 && PRIV(flag_hash_long_names)
1067 && PRIV(flag_show_after_trunc))
1068 printf (_("Symbol %s replaced by %s\n"), old_name, new_name);
1070 return outbuf;
1074 /* Allocate and initialize a new symbol. */
1076 static asymbol *
1077 new_symbol (abfd, name)
1078 bfd *abfd;
1079 char *name;
1081 asymbol *symbol;
1083 #if VMS_DEBUG
1084 _bfd_vms_debug (7, "new_symbol %s\n", name);
1085 #endif
1087 symbol = _bfd_vms_make_empty_symbol (abfd);
1088 if (symbol == 0)
1089 return symbol;
1090 symbol->name = name;
1091 symbol->section = bfd_make_section (abfd, BFD_UND_SECTION_NAME);
1093 return symbol;
1097 /* Allocate and enter a new private symbol. */
1099 vms_symbol_entry *
1100 _bfd_vms_enter_symbol (abfd, name)
1101 bfd *abfd;
1102 char *name;
1104 vms_symbol_entry *entry;
1106 #if VMS_DEBUG
1107 _bfd_vms_debug (6, "_bfd_vms_enter_symbol %s\n", name);
1108 #endif
1110 entry = (vms_symbol_entry *)
1111 bfd_hash_lookup (PRIV(vms_symbol_table), name, false, false);
1112 if (entry == 0)
1114 #if VMS_DEBUG
1115 _bfd_vms_debug (8, "creating hash entry for %s\n", name);
1116 #endif
1117 entry = (vms_symbol_entry *)bfd_hash_lookup (PRIV(vms_symbol_table), name, true, false);
1118 if (entry != 0)
1120 asymbol *symbol;
1121 symbol = new_symbol (abfd, name);
1122 if (symbol != 0)
1124 entry->symbol = symbol;
1125 PRIV(gsd_sym_count)++;
1126 abfd->symcount++;
1128 else
1129 entry = 0;
1131 else
1132 (*_bfd_error_handler) (_("failed to enter %s"), name);
1134 else
1136 #if VMS_DEBUG
1137 _bfd_vms_debug (8, "found hash entry for %s\n", name);
1138 #endif
1141 #if VMS_DEBUG
1142 _bfd_vms_debug (7, "-> entry %p, entry->symbol %p\n", entry, entry->symbol);
1143 #endif
1144 return entry;