* gdb.texinfo: Add some credits, mention bug monitor.
[deliverable/binutils-gdb.git] / bfd / evax-misc.c
CommitLineData
8696b2db
ILT
1/* evax-misc.c -- Miscellaneous functions for ALPHA EVAX (openVMS/Alpha) files.
2 Copyright 1996, 1997 Free Software Foundation, Inc.
3
4 Written by Klaus K"ampf (kkaempf@progis.de)
c3d8e071
ILT
5 of proGIS Softwareentwicklung, Aachen, Germany
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21
22#if __STDC__
23#include <stdarg.h>
24#endif
25#include <stdio.h>
26
27#include "bfd.h"
28#include "sysdep.h"
29#include "bfdlink.h"
30#include "libbfd.h"
31
32#include "evax.h"
33
34/*-----------------------------------------------------------------------------*/
35#if EVAX_DEBUG
36/* debug functions */
37
38/* debug function for all evax extensions
39 evaluates environment variable EVAX_DEBUG for a
40 numerical value on the first call
41 all error levels below this value are printed
42
43 levels:
44 1 toplevel bfd calls (functions from the bfd vector)
45 2 functions called by bfd calls
46 ...
47 9 almost everything
48
49 level is also identation level. Indentation is performed
50 if level > 0
51 */
52
53#if __STDC__
54void
55_bfd_evax_debug (int level, char *format, ...)
56{
57 static int min_level = -1;
58 static FILE *output = NULL;
59 char *eptr;
60 va_list args;
61 int abslvl = (level > 0)?level:-level;
62
63 if (min_level == -1)
64 {
65 if ((eptr = getenv("EVAX_DEBUG")) != NULL)
66 {
67 min_level = atoi(eptr);
68 output = stderr;
69 }
70 else
71 min_level = 0;
72 }
73 if (output == NULL)
74 return;
75 if (abslvl > min_level)
76 return;
77
78 while(--level>0)
79 fprintf(output, " ");
80 va_start(args, format);
81 vfprintf(output, format, args);
82 fflush(output);
83 va_end(args);
84
85 return;
86}
87
88#else /* not __STDC__ */
89
90void
91_bfd_evax_debug (level, format, a1, a2, a3, a4, a5, a6)
92 int level;
93 char *format;
94 long a1; long a2; long a3;
95 long a4; long a5; long a6;
96{
97 static int min_level = -1;
98 static FILE *output = NULL;
99 char *eptr;
100
101 if (min_level == -1)
102 {
103 if ((eptr = getenv("EVAX_DEBUG")) != NULL)
104 {
105 min_level = atoi(eptr);
106 output = stderr;
107 }
108 else
109 min_level = 0;
110 }
111 if (output == NULL)
112 return;
113 if (level > min_level)
114 return;
115
116 while(--level>0)
117 fprintf(output, " ");
118 fprintf(output, format, a1, a2, a3, a4, a5, a6);
119 fflush(output);
120
121 return;
122}
123#endif /* __STDC__ */
124
125
126/* a debug function
127 hex dump 'size' bytes starting at 'ptr' */
128
129void
130_bfd_hexdump (level, ptr, size, offset)
131 int level;
132 unsigned char *ptr;
133 int size;
134 int offset;
135{
136 unsigned char *lptr = ptr;
137 int count = 0;
138 long start = offset;
139
140 while (size-- > 0)
141 {
142 if ((count%16) == 0)
143 evax_debug (level, "%08lx:", start);
144 evax_debug (-level, " %02x", *ptr++);
145 count++;
146 start++;
147 if (size == 0)
148 {
149 while ((count%16) != 0)
150 {
151 evax_debug (-level, " ");
152 count++;
153 }
154 }
155 if ((count%16) == 0)
156 {
157 evax_debug (-level, " ");
158 while (lptr < ptr)
159 {
160 evax_debug (-level, "%c", (*lptr < 32)?'.':*lptr);
161 lptr++;
162 }
163 evax_debug (-level, "\n");
164 }
165 }
166 if ((count%16) != 0)
167 evax_debug (-level, "\n");
168
169 return;
170}
171#endif
172
173\f
174/* hash functions
175
176 These are needed when reading an object file. */
177
178/* allocate new evax_hash_entry
179 keep the symbol name and a pointer to the bfd symbol in the table */
180
181struct bfd_hash_entry *
182_bfd_evax_hash_newfunc (entry, table, string)
183 struct bfd_hash_entry *entry;
184 struct bfd_hash_table *table;
185 const char *string;
186{
187 evax_symbol_entry *ret = (evax_symbol_entry *)entry;
188
189#if EVAX_DEBUG
190 evax_debug (5, "_bfd_evax_hash_newfunc(%p, %p, %s)\n", entry, table, string);
191#endif
192
193 if (ret == (evax_symbol_entry *)NULL)
194 ret = ((evax_symbol_entry *) bfd_hash_allocate (table, sizeof (evax_symbol_entry)));
195 if (ret == (evax_symbol_entry *)NULL)
196 {
197 bfd_set_error (bfd_error_no_memory);
198 return (struct bfd_hash_entry *)NULL;
199 }
200 ret = (evax_symbol_entry *) bfd_hash_newfunc ((struct bfd_hash_entry *)ret, table, string);
201
202 ret->symbol = (asymbol *)NULL;
203
204 return (struct bfd_hash_entry *)ret;
205}
206
207\f
208/* object file input functions */
209
210/* Return type and length from record header (buf) */
211
212void
213_bfd_evax_get_header_values (abfd, buf, type, length)
214 bfd *abfd;
215 unsigned char *buf;
216 int *type;
217 int *length;
218{
219 if (type != 0)
220 *type = bfd_getl16 (buf);
221 buf += 2;
222 if (length != 0)
223 *length = bfd_getl16 (buf);
224
225 return;
226}
227
228
229/* Get next record from object file to evax_buf
230 set PRIV(buf_size) and return it
231
232 this is a little tricky since it should be portable.
233
234 the openVMS/AXP object file has 'variable length' which means that
235 read() returns data in chunks of (hopefully) correct and expected
236 size. The linker (and other tools on vms) depend on that. Unix doesn't
237 know about 'formatted' files, so reading and writing such an object
238 file in a unix environment is not trivial.
239
240 With the tool 'file' (available on all vms ftp sites), one
241 can view and change the attributes of a file. Changing from
242 'variable length' to 'fixed length, 512 bytes' reveals the
243 record length at the first 2 bytes of every record. The same
244 happens during the transfer of object files from vms to unix,
245 at least with ucx, dec's implementation of tcp/ip.
246
247 The EVAX format repeats the length at bytes 2 & 3 of every record.
248
249 On the first call (file_format == FF_UNKNOWN) we check if
250 the first and the third byte pair (!) of the record match.
251 If they do it's an object file in an unix environment or with
252 wrong attributes (FF_FOREIGN), else we should be in a vms
253 environment where read() returns the record size (FF_NATIVE).
254
255 reading is always done in 2 steps.
256 first just the record header is read and the length extracted
257 by get_header_values
258 then the read buffer is adjusted and the remaining bytes are
259 read in.
260
261 all file i/o is always done on even file positions */
262
263int
264_bfd_evax_get_record (abfd)
265 bfd *abfd;
266{
267 int test_len, test_start, remaining;
268 unsigned char *evax_buf;
269
270#if EVAX_DEBUG
271 evax_debug (8, "_bfd_evax_get_record\n");
272#endif
273
274 /* minimum is 6 bytes
275 (2 bytes length, 2 bytes record id, 2 bytes length repeated) */
276
277 if (PRIV(buf_size) == 0)
278 {
279 PRIV(evax_buf) = (unsigned char *) malloc (6);
280#if EVAX_DEBUG
281 evax_debug (9, "PRIV(evax_buf) %p\n", PRIV(evax_buf));
282#endif
283 }
284
285 evax_buf = PRIV(evax_buf);
286
287 if (evax_buf == 0)
288 {
289#if EVAX_DEBUG
290 evax_debug (9, "can't alloc evax_buf\n");
291#endif
292 bfd_set_error (bfd_error_no_memory);
293 return -1;
294 }
295
296 switch (PRIV(file_format))
297 {
298 case FF_UNKNOWN:
299 case FF_FOREIGN:
300 test_len = 6; /* probe 6 bytes */
301 test_start = 2; /* where the record starts */
302 break;
303
304 case FF_NATIVE:
305 test_len = 4;
306 test_start = 0;
307 break;
308 }
309
310 /* skip odd alignment byte */
311#if 0
312 if (PRIV(file_format) == FF_FOREIGN)
313 {
314#endif
315 if (bfd_tell (abfd) & 1)
316 {
317#if EVAX_DEBUG
318 evax_debug (10, "skip odd\n");
319#endif
320 if (bfd_read (PRIV(evax_buf), 1, 1, abfd) != 1)
321 {
322#if EVAX_DEBUG
323 evax_debug (9, "skip odd failed\n");
324#endif
325 bfd_set_error (bfd_error_file_truncated);
326 return 0;
327 }
328 }
329#if 0
330 }
331#endif
332 /* read the record header */
333
334 if (bfd_read (PRIV(evax_buf), 1, test_len, abfd) != test_len)
335 {
336#if EVAX_DEBUG
337 evax_debug (9, "can't bfd_read test %d bytes\n", test_len);
338#endif
339 bfd_set_error (bfd_error_file_truncated);
340 return 0;
341 }
342
343 /* check file format on first call */
344
345 if (PRIV(file_format) == FF_UNKNOWN)
346 { /* record length repeats ? */
347 if ( (evax_buf[0] == evax_buf[4])
348 && (evax_buf[1] == evax_buf[5]))
349 {
350 PRIV(file_format) = FF_FOREIGN; /* Y: foreign environment */
351 test_start = 2;
352 }
353 else
354 {
355 PRIV(file_format) = FF_NATIVE; /* N: native environment */
356 test_start = 0;
357 }
358#if EVAX_DEBUG
359 evax_debug (10, "File format is %s\n", (PRIV(file_format) == FF_FOREIGN)?"foreign":"native");
360#endif
361 }
362
363 /* extract evax record length */
364
365 _bfd_evax_get_header_values (abfd, evax_buf+test_start, NULL,
366 &PRIV(rec_length));
367
368 if (PRIV(rec_length) <= 0)
369 {
370 bfd_set_error (bfd_error_file_truncated);
371 return 0;
372 }
373
374 /* that's what the linker manual says */
375
376 if (PRIV(rec_length) > EOBJ_S_C_MAXRECSIZ)
377 {
378 bfd_set_error (bfd_error_file_truncated);
379 return 0;
380 }
381
382 /* adjust the buffer */
383
384 if (PRIV(rec_length) > PRIV(buf_size))
385 {
386 PRIV(evax_buf) = (unsigned char *) realloc (evax_buf, PRIV(rec_length));
387#if EVAX_DEBUG
388 evax_debug (3, "adjusted the buffer (%p) from %d to %d\n", PRIV(evax_buf), PRIV(buf_size), PRIV(rec_length));
389#endif
390 evax_buf = PRIV(evax_buf);
391 if (evax_buf == 0)
392 {
393#if EVAX_DEBUG
394 evax_debug (9, "can't realloc evax_buf to %d bytes\n", PRIV(rec_length));
395#endif
396 bfd_set_error (bfd_error_no_memory);
397 return -1;
398 }
399 PRIV(buf_size) = PRIV(rec_length);
400 }
401
402 /* read the remaining record */
403
404 remaining = PRIV(rec_length) - test_len + test_start;
405
406 if (bfd_read (evax_buf + test_len, 1, remaining, abfd) != remaining)
407 {
408#if EVAX_DEBUG
409 evax_debug (9, "can't bfd_read remaining %d bytes\n", remaining);
410#endif
411 bfd_set_error (bfd_error_file_truncated);
412 return 0;
413 }
414
415 PRIV(evax_rec) = evax_buf + test_start;
416
417 return PRIV(rec_length);
418}
419
420
421/* get next EVAX record from file
422 update evax_rec and rec_length to new (remaining) values */
423
424int
425_bfd_evax_next_record (abfd)
426 bfd *abfd;
427{
428#if EVAX_DEBUG
429 evax_debug (8, "_bfd_evax_next_record (len %d, size %d)\n",
430 PRIV(rec_length), PRIV(rec_size));
431#endif
432
433 if (PRIV(rec_length) > 0)
434 {
435 PRIV(evax_rec) += PRIV(rec_size);
436 }
437 else
438 {
439 if (_bfd_evax_get_record (abfd) <= 0)
440 return -1;
441 }
442 _bfd_evax_get_header_values (abfd, PRIV(evax_rec), &PRIV(rec_type),
443 &PRIV(rec_size));
444 PRIV(rec_length) -= PRIV(rec_size);
445
446#if EVAX_DEBUG
447 evax_debug (8, "_bfd_evax_next_record: rec %p, size %d, length %d, type %d\n",
448 PRIV(evax_rec), PRIV(rec_size), PRIV(rec_length),
449 PRIV(rec_type));
450#endif
451
452 return PRIV(rec_type);
453}
454
455
456\f
457/* Copy sized string (string with fixed length) to new allocated area
458 size is string length (size of record) */
459
460char *
461_bfd_evax_save_sized_string (str, size)
462 char *str;
463 int size;
464{
465 char *newstr = bfd_malloc (size + 1);
466
467 if (newstr == NULL)
468 return 0;
469 strncpy (newstr, str, size);
470 newstr[size] = 0;
471
472 return newstr;
473}
474
475/* Copy counted string (string with length at first byte) to new allocated area
476 ptr points to length byte on entry */
477
478char *
479_bfd_evax_save_counted_string (ptr)
480 char *ptr;
481{
482 int len = *ptr++;
483
484 return _bfd_evax_save_sized_string (ptr, len);
485}
486
487\f
488/* stack routines for EVAX ETIR commands */
489
490/* Push value and section index */
491
492void
493_bfd_evax_push (abfd, val, psect)
494 bfd *abfd;
495 uquad val;
496 int psect;
497{
498 static int last_psect;
499
500#if EVAX_DEBUG
501 evax_debug (4, "<push %016lx(%d) at %d>\n", val, psect, PRIV(stackptr));
502#endif
503
504 if (psect >= 0)
505 last_psect = psect;
506
507 PRIV(stack[PRIV(stackptr)]).value = val;
508 PRIV(stack[PRIV(stackptr)]).psect = last_psect;
509 PRIV(stackptr)++;
510 if (PRIV(stackptr) >= STACKSIZE)
511 {
512 bfd_set_error (bfd_error_bad_value);
513 exit(1);
514 }
515 return;
516}
517
518
519/* Pop value and section index */
520
521uquad
522_bfd_evax_pop (abfd, psect)
523 bfd *abfd;
524 int *psect;
525{
526 uquad value;
527
528 if (PRIV(stackptr) == 0)
529 {
530 bfd_set_error (bfd_error_bad_value);
531 exit(1);
532 }
533 PRIV(stackptr)--;
534 value = PRIV(stack[PRIV(stackptr)]).value;
535 if ((psect != NULL) && (PRIV(stack[PRIV(stackptr)]).psect >= 0))
536 *psect = PRIV(stack[PRIV(stackptr)]).psect;
537
538#if EVAX_DEBUG
539 evax_debug (4, "<pop %016lx(%d)>\n", value, PRIV(stack[PRIV(stackptr)]).psect);
540#endif
541
542 return value;
543}
544
545\f
546/* object file output functions */
547
548/* GAS tends to write sections in little chunks (bfd_set_section_contents)
549 which we can't use directly. So we save the little chunks in linked
550 lists (one per section) and write them later. */
551
552/* Add a new evax_section structure to evax_section_table
553 - forward chaining - */
554
555static evax_section *
556add_new_contents (abfd, section)
557 bfd *abfd;
558 sec_ptr section;
559{
560 evax_section *sptr, *newptr;
561
c3d8e071 562 sptr = PRIV(evax_section_table)[section->index];
8612a388
ILT
563 if (sptr != NULL)
564 return sptr;
565
566 newptr = (evax_section *) bfd_malloc (sizeof (evax_section));
567 if (newptr == (evax_section *) NULL)
568 return NULL;
bf53bd9f 569 newptr->contents = (unsigned char *) bfd_alloc (abfd, (int)section->_raw_size);
8612a388
ILT
570 if (newptr->contents == (unsigned char *)NULL)
571 return NULL;
572 newptr->offset = 0;
573 newptr->size = section->_raw_size;
574 newptr->next = 0;
575 PRIV(evax_section_table)[section->index] = newptr;
c3d8e071
ILT
576 return newptr;
577}
578
579
580/* Save section data & offset to an evax_section structure
581 evax_section_table[] holds the evax_section chain */
582
583boolean
584_bfd_save_evax_section (abfd, section, data, offset, count)
585 bfd *abfd;
586 sec_ptr section;
587 PTR data;
588 file_ptr offset;
589 bfd_size_type count;
590{
591 evax_section *sptr;
592
593 if (section->index >= EVAX_SECTION_COUNT)
594 {
595 bfd_set_error (bfd_error_nonrepresentable_section);
596 return false;
597 }
598 if (count == (bfd_size_type)0)
599 return true;
600 sptr = add_new_contents (abfd, section);
601 if (sptr == NULL)
602 return false;
8612a388 603 memcpy (sptr->contents + offset, data, (size_t) count);
c3d8e071
ILT
604
605 return true;
606}
607
608
609/* Get evax_section pointer to saved contents for section # index */
610
611evax_section *
612_bfd_get_evax_section (abfd, index)
613 bfd *abfd;
614 int index;
615{
616 if (index >= EVAX_SECTION_COUNT)
617 {
618 bfd_set_error (bfd_error_nonrepresentable_section);
619 return NULL;
620 }
621 return PRIV(evax_section_table)[index];
622}
623
624\f
625/* Object output routines */
626
627/* Begin new record or record header
628 write 2 bytes rectype
629 write 2 bytes record length (filled in at flush)
630 write 2 bytes header type (ommitted if rechead == -1) */
631
632void
633_bfd_evax_output_begin (abfd, rectype, rechead)
634 bfd *abfd;
635 int rectype;
636 int rechead;
637{
638#if EVAX_DEBUG
639 evax_debug (6, "_bfd_evax_output_begin(type %d, head %d)\n", rectype,
640 rechead);
641#endif
642
643 _bfd_evax_output_short (abfd,rectype);
644
645 /* save current output position to fill in lenght later */
646
647 if (PRIV(push_level) > 0)
648 PRIV(length_pos) = PRIV(output_size);
649
650#if EVAX_DEBUG
651 evax_debug (6, "_bfd_evax_output_begin: length_pos = %d\n",
652 PRIV(length_pos));
653#endif
654
655 _bfd_evax_output_short (abfd,0); /* placeholder for length */
656
657 if (rechead != -1)
658 _bfd_evax_output_short (abfd,rechead);
659
660 return;
661}
662
663
664/* Set record/subrecord alignment */
665
666void
667_bfd_evax_output_alignment (abfd, alignto)
668 bfd *abfd;
669 int alignto;
670{
671#if EVAX_DEBUG
672 evax_debug (6, "_bfd_evax_output_alignment(%d)\n", alignto);
673#endif
674
675 PRIV(output_alignment) = alignto;
676 return;
677}
678
679
680/* Prepare for subrecord fields */
681
682void
683_bfd_evax_output_push (abfd)
684 bfd *abfd;
685{
686#if EVAX_DEBUG
687 evax_debug (6, "evax_output_push(pushed_size = %d)\n", PRIV(output_size));
688#endif
689
690 PRIV(push_level)++;
691 PRIV(pushed_size) = PRIV(output_size);
692 return;
693}
694
695
696/* End of subrecord fields */
697
698void
699_bfd_evax_output_pop (abfd)
700 bfd *abfd;
701{
702#if EVAX_DEBUG
703 evax_debug (6, "evax_output_pop(pushed_size = %d)\n", PRIV(pushed_size));
704#endif
705
706 _bfd_evax_output_flush (abfd);
707 PRIV(length_pos) = 2;
708
709#if EVAX_DEBUG
710 evax_debug (6, "evax_output_pop: length_pos = %d\n", PRIV(length_pos));
711#endif
712
713 PRIV(pushed_size) = 0;
714 PRIV(push_level)--;
715 return;
716}
717
718
719/* Flush unwritten output, ends current record */
720
721void
722_bfd_evax_output_flush (abfd)
723 bfd *abfd;
724{
725 int real_size = PRIV(output_size);
726 int aligncount;
727 int length;
728
729#if EVAX_DEBUG
730 evax_debug (6, "_bfd_evax_output_flush(real_size = %d, pushed_size %d at lenpos %d)\n",
731 real_size, PRIV(pushed_size), PRIV(length_pos));
732#endif
733
734 if (PRIV(push_level) > 0)
735 length = real_size - PRIV(pushed_size);
736 else
737 length = real_size;
738
739 if (length == 0)
740 return;
741 aligncount = (PRIV(output_alignment)
742 - (length % PRIV(output_alignment))) % PRIV(output_alignment);
743
744#if EVAX_DEBUG
745 evax_debug (6, "align: adding %d bytes\n", aligncount);
746#endif
747
748 while(aligncount-- > 0)
749 {
750 PRIV(output_buf)[real_size++] = 0;
751#if 0
752 /* this is why I *love* vms: inconsistency :-}
753 alignment is added to the subrecord length
754 but not to the record length */
755 if (PRIV(push_level) > 0)
756#endif
757 length++;
758 }
759
760 /* put length to buffer */
761 PRIV(output_size) = PRIV(length_pos);
762 _bfd_evax_output_short (abfd, (unsigned int)length);
763
764 if (PRIV(push_level) == 0)
765 {
766#ifndef VMS
767 /* write length first, see FF_FOREIGN in the input routines */
768 fwrite (PRIV(output_buf)+2, 2, 1, (FILE *)abfd->iostream);
769#endif
770 fwrite (PRIV(output_buf), real_size, 1, (FILE *)abfd->iostream);
771
772 PRIV(output_size) = 0;
773 }
774 else
775 {
776 PRIV(output_size) = real_size;
777 PRIV(pushed_size) = PRIV(output_size);
778 }
779
780 return;
781}
782
783
784/* End record output */
785
786void
787_bfd_evax_output_end (abfd)
788 bfd *abfd;
789{
790#if EVAX_DEBUG
791 evax_debug (6, "_bfd_evax_output_end\n");
792#endif
793
794 _bfd_evax_output_flush (abfd);
795
796 return;
797}
798
799
800/* check remaining buffer size
801
802 return what's left. */
803
804int
805_bfd_evax_output_check (abfd, size)
806 bfd *abfd;
807 int size;
808{
809#if EVAX_DEBUG
810 evax_debug (6, "_bfd_evax_output_check(%d)\n", size);
811#endif
812
813 return (MAX_OUTREC_SIZE - (PRIV(output_size) + size + MIN_OUTREC_LUFT));
814}
815
816
817/* Output byte (8 bit) value */
818
819void
820_bfd_evax_output_byte (abfd, value)
821 bfd *abfd;
822 unsigned int value;
823{
824#if EVAX_DEBUG
825 evax_debug (6, "_bfd_evax_output_byte(%02x)\n", value);
826#endif
827
828 bfd_put_8 (abfd, value & 0xff, PRIV(output_buf) + PRIV(output_size));
829 PRIV(output_size) += 1;
830 return;
831}
832
833
834/* Output short (16 bit) value */
835
836void
837_bfd_evax_output_short (abfd, value)
838 bfd *abfd;
839 unsigned int value;
840{
841#if EVAX_DEBUG
842 evax_debug (6, "_bfd_evax_output_short (%04x)\n", value);
843#endif
844
845 bfd_put_16 (abfd, value & 0xffff, PRIV(output_buf) + PRIV(output_size));
846 PRIV(output_size) += 2;
847 return;
848}
849
850
851/* Output long (32 bit) value */
852
853void
854_bfd_evax_output_long (abfd, value)
855 bfd *abfd;
856 unsigned long value;
857{
858#if EVAX_DEBUG
859 evax_debug (6, "_bfd_evax_output_long (%08lx)\n", value);
860#endif
861
862 bfd_put_32 (abfd, value, PRIV(output_buf) + PRIV(output_size));
863 PRIV(output_size) += 4;
864 return;
865}
866
867
868/* Output quad (64 bit) value */
869
870void
871_bfd_evax_output_quad (abfd, value)
872 bfd *abfd;
873 uquad value;
874{
875#if EVAX_DEBUG
876 evax_debug (6, "_bfd_evax_output_quad(%016lx)\n", value);
877#endif
878
879 bfd_put_64(abfd, value, PRIV(output_buf) + PRIV(output_size));
880 PRIV(output_size) += 8;
881 return;
882}
883
884
885/* Output c-string as counted string */
886
887void
888_bfd_evax_output_counted (abfd, value)
889 bfd *abfd;
890 char *value;
891{
892int len;
893
894#if EVAX_DEBUG
895 evax_debug (6, "_bfd_evax_output_counted(%s)\n", value);
896#endif
897
898 len = strlen (value);
899 if (len == 0)
900 {
901 (*_bfd_error_handler) ("_bfd_evax_output_counted called with zero bytes");
902 return;
903 }
904 if (len > 255)
905 {
906 (*_bfd_error_handler) ("_bfd_evax_output_counted called with too many bytes");
907 return;
908 }
909 _bfd_evax_output_byte (abfd, len & 0xff);
910 _bfd_evax_output_dump (abfd, (unsigned char *)value, len);
911}
912
913
914/* Output character area */
915
916void
917_bfd_evax_output_dump (abfd, data, length)
918 bfd *abfd;
919 unsigned char *data;
920 int length;
921{
922#if EVAX_DEBUG
923 evax_debug (6, "_bfd_evax_output_dump(%d)\n", length);
924#endif
925
926 if (length == 0)
927 return;
928
929 memcpy (PRIV(output_buf) + PRIV(output_size), data, length);
930 PRIV(output_size) += length;
931
932 return;
933}
934
935
936/* Output count bytes of value */
937
938void
939_bfd_evax_output_fill (abfd, value, count)
940 bfd *abfd;
941 int value;
942 int count;
943{
944#if EVAX_DEBUG
945 evax_debug (6, "_bfd_evax_output_fill(val %02x times %d)\n", value, count);
946#endif
947
948 if (count == 0)
949 return;
950 memset (PRIV(output_buf) + PRIV(output_size), value, count);
951 PRIV(output_size) += count;
952
953 return;
954}
955
bf53bd9f 956/* this hash routine borrowed from GNU-EMACS, and strengthened slightly ERY*/
c3d8e071 957
bf53bd9f
ILT
958static int
959hash_string (ptr)
960 const char *ptr;
961{
962 register const unsigned char *p = (unsigned char *) ptr;
963 register const unsigned char *end = p + strlen (ptr);
964 register unsigned char c;
965 register int hash = 0;
c3d8e071 966
bf53bd9f
ILT
967 while (p != end)
968 {
969 c = *p++;
970 hash = ((hash << 3) + (hash << 15) + (hash >> 28) + c);
971 }
972 return hash;
973}
974
412222d9 975/* Generate a length-hashed VMS symbol name (limited to maxlen chars). */
8696b2db 976
c3d8e071 977char *
412222d9 978_bfd_evax_length_hash_symbol (abfd, in, maxlen)
bf53bd9f
ILT
979 bfd *abfd;
980 const char *in;
412222d9 981 int maxlen;
c3d8e071 982{
bf53bd9f
ILT
983 long int init;
984 long int result;
8696b2db 985 int in_len;
bf53bd9f
ILT
986 char *pnt = 0;
987 char *new_name;
988 const char *old_name;
989 int i;
412222d9 990 static char outbuf[EOBJ_S_C_SYMSIZ+1];
bf53bd9f 991 char *out = outbuf;
c3d8e071
ILT
992
993#if EVAX_DEBUG
8696b2db 994 evax_debug(4, "_bfd_evax_length_hash_symbol \"%s\"\n", in);
bf53bd9f
ILT
995#endif
996
412222d9
ILT
997 if (maxlen > EOBJ_S_C_SYMSIZ)
998 maxlen = EOBJ_S_C_SYMSIZ;
999
bf53bd9f
ILT
1000 new_name = out; /* save this for later. */
1001
1002 /* We may need to truncate the symbol, save the hash for later. */
1003
8696b2db 1004 in_len = strlen (in);
bf53bd9f 1005
412222d9 1006 result = (in_len > maxlen) ? hash_string (in) : 0;
bf53bd9f 1007
8696b2db 1008 old_name = in;
c3d8e071 1009
8696b2db 1010 /* Do the length checking. */
bf53bd9f 1011
412222d9
ILT
1012 if (in_len <= maxlen)
1013 {
1014 i = in_len;
1015 }
1016 else
1017 {
1018 if (PRIV(flag_hash_long_names))
1019 i = maxlen-9;
bf53bd9f 1020 else
412222d9
ILT
1021 i = maxlen;
1022 }
bf53bd9f 1023
8696b2db
ILT
1024 strncpy (out, in, i);
1025 in += i;
1026 out += i;
1027
412222d9 1028 if ((in_len > maxlen)
8696b2db
ILT
1029 && PRIV(flag_hash_long_names))
1030 sprintf (out, "_%08x", result);
1031 else
412222d9 1032 *out = 0;
c3d8e071
ILT
1033
1034#if EVAX_DEBUG
bf53bd9f 1035 evax_debug(4, "--> [%d]\"%s\"\n", strlen (outbuf), outbuf);
c3d8e071
ILT
1036#endif
1037
412222d9 1038 if (in_len > maxlen
bf53bd9f
ILT
1039 && PRIV(flag_hash_long_names)
1040 && PRIV(flag_show_after_trunc))
1041 printf ("Symbol %s replaced by %s\n", old_name, new_name);
1042
1043 return outbuf;
c3d8e071 1044}
bf53bd9f 1045
This page took 0.134466 seconds and 4 git commands to generate.