|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T h
Length: 29001 (0x7149) Types: TextFile Names: »hpxt.c«
└─⟦a05ed705a⟧ Bits:30007078 DKUUG GNU 2/12/89 └─⟦4ef0278ca⟧ »./binutils.tar.Z« └─⟦3761b9c35⟧ └─⟦this⟧ »binutils/hp-bin/hpxt.c«
/* Program to translate binary format files from HP-UX to GNU. Input formats for HP 9000 series 200/300 only. Copyright (C) 1988 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <varargs.h> #include <fcntl.h> #include <sys/file.h> #include <string.h> #define index(s, c) strchr (s, c) #define bzero(p, n) memset (p, 0, n) #include "ioutil.h" #define forward extern \f /* IO primitives */ void xread (input_file, buffer, length) int input_file; char *buffer; int length; { if ((iou_read (input_file, buffer, length)) != length) iou_error ("read failed to complete"); return; } \f /* HP-UX data structure descriptions */ struct hp_magic { unsigned short system_id; unsigned short file_type; }; #define HP_SYSID_98x6 0x020A #define HP_SYSID_9000S200 0x020C #define HP_SYSID_OK(sysid) \ (((sysid) == HP_SYSID_9000S200) \ || ((sysid) == HP_SYSID_98x6)) #define HP_FILETYPE_RELOC 0x0106 /* relocatable only */ #define HP_FILETYPE_EXEC 0x0107 /* normal executable */ #define HP_FILETYPE_SHARE 0x0108 /* shared executable */ #define HP_FILETYPE_DEMAND 0x010B /* demand-load executable */ #define HP_FILETYPE_OK(filetype) \ (((filetype) == HP_FILETYPE_EXEC) \ || ((filetype) == HP_FILETYPE_SHARE) \ || ((filetype) == HP_FILETYPE_DEMAND) \ || ((filetype) == HP_FILETYPE_RELOC)) #define HP_MAGIC_OK(magic) \ ((HP_SYSID_OK ((magic) . system_id)) \ && (HP_FILETYPE_OK ((magic) . file_type))) struct hp_exec { struct hp_magic a_magic; short a_stamp; /* version id */ short a_unused; long a_sparehp; long a_text; /* size of text segment */ long a_data; /* size of data segment */ long a_bss; /* size of bss segment */ long a_trsize; /* text relocation size */ long a_drsize; /* data relocation size */ long a_pasint; /* pascal interface size */ long a_lesyms; /* symbol table size */ long a_dnttsize; /* debug name table size */ long a_entry; /* entry point */ long a_sltsize; /* source line table size */ long a_vtsize; /* value table size */ long a_spare3; long a_spare4; }; #define HP_EXEC_MAGIC(header) (((header) . a_magic) . file_type) #define HP_PAGE_SIZE 0x1000 #define HP_PAGE_SEEK(descriptor, header, offset) \ { \ if ((HP_EXEC_MAGIC (header)) == HP_FILETYPE_DEMAND) \ { \ int HP_PAGE_SEEK_remainder; \ \ HP_PAGE_SEEK_remainder = ((offset) % HP_PAGE_SIZE); \ if (HP_PAGE_SEEK_remainder != 0) \ iou_lseek \ ((descriptor), (HP_PAGE_SIZE - HP_PAGE_SEEK_remainder), 1); \ } \ } struct hp_nlist { long n_value; unsigned char n_type; unsigned char n_length; /* length of ascii symbol name */ short n_almod; /* alignment mod */ short n_unused; }; #define HP_SYMTYPE_UNDEFINED 0x00 #define HP_SYMTYPE_ABSOLUTE 0x01 #define HP_SYMTYPE_TEXT 0x02 #define HP_SYMTYPE_DATA 0x03 #define HP_SYMTYPE_BSS 0x04 #define HP_SYMTYPE_COMMON 0x05 #define HP_SYMTYPE_FILENAME 0x1F #define HP_SYMTYPE_ALIGN 0x10 #define HP_SYMTYPE_EXTERNAL 0x20 #define HP_SYMTYPE_TYPE 0x0F struct hp_relocation_info { long r_address; /* position of relocation in segment */ short r_symbolnum; /* id of the symbol of external relocations */ char r_segment; char r_length; }; #define HP_RSEGMENT_TEXT 0x00 #define HP_RSEGMENT_DATA 0x01 #define HP_RSEGMENT_BSS 0x02 #define HP_RSEGMENT_EXTERNAL 0x03 #define HP_RSEGMENT_NOOP 0x3F #define HP_RLENGTH_BYTE 0x00 #define HP_RLENGTH_WORD 0x01 #define HP_RLENGTH_LONG 0x02 #define HP_RLENGTH_ALIGN 0x03 #define HP_ARMAG "!<arch>\n" #define HP_SARMAG 8 #define HP_ARFMAG "`\n" struct hp_ar_hdr { char ar_name [16]; /* file member name - `/' terminated */ char ar_date [12]; /* file member date - decimal */ char ar_uid [6]; /* file member user id - decimal */ char ar_gid [6]; /* file member group id - decimal */ char ar_mode [8]; /* file member mode - octal */ char ar_size [10]; /* file member size - decimal */ char ar_fmag [2]; /* ARFMAG - string to end header */ }; struct hp_ar_symtab_hdr { unsigned short n_entries; long string_table_size; }; struct hp_ar_symtab_entry { long string_index; long file_index; }; \f /* GNU data structure descriptions */ #ifdef hpux /* The `exec' structure and overall layout must be close to HP's when we are running on an HP system, otherwise we will not be able to execute the resulting file. */ #define GNU_OMAGIC HP_FILETYPE_EXEC #define GNU_NMAGIC HP_FILETYPE_SHARE #define GNU_ZMAGIC HP_FILETYPE_SHARE struct gnu_exec { struct hp_magic a_magic; unsigned long a_spare1; unsigned long a_spare2; unsigned long a_text; /* size of text segment */ unsigned long a_data; /* size of data segment */ unsigned long a_bss; /* size of bss segment */ unsigned long a_trsize; /* text relocation size */ unsigned long a_drsize; /* data relocation size */ unsigned long a_spare3; /* HP = pascal interface size */ unsigned long a_spare4; /* HP = symbol table size */ unsigned long a_spare5; /* HP = debug name table size */ unsigned long a_entry; /* entry point */ unsigned long a_spare6; /* HP = source line table size */ unsigned long a_spare7; /* HP = value table size */ unsigned long a_syms; /* symbol table size */ unsigned long a_spare8; }; #define GNU_EXEC_MAGIC(header) (((header) . a_magic) . file_type) #define GNU_EXEC_SET_MAGIC(header, magic) \ { \ (((header) . a_magic) . system_id) = HP_SYSID_9000S200; \ (((header) . a_magic) . file_type) = (magic); \ } #define GNU_PAGE_SEEK_HEADER HP_PAGE_SEEK #define GNU_PAGE_SEEK_TEXT HP_PAGE_SEEK #else /* not hpux */ #define GNU_OMAGIC 0407 /* old impure format */ #define GNU_NMAGIC 0410 /* read-only text */ #define GNU_ZMAGIC 0413 /* demand load format */ struct gnu_exec { unsigned long a_magic; /* magic number */ unsigned long a_text; /* size of text segment */ unsigned long a_data; /* size of initialized data */ unsigned long a_bss; /* size of uninitialized data */ unsigned long a_syms; /* size of symbol table */ unsigned long a_entry; /* entry point */ unsigned long a_trsize; /* size of text relocation */ unsigned long a_drsize; /* size of data relocation */ }; #define GNU_EXEC_MAGIC(header) ((header) . a_magic) #define GNU_EXEC_SET_MAGIC(header, magic) ((header) . a_magic) = (magic) #define GNU_PAGE_SIZE 0x400 #define GNU_PAGE_SEEK_HEADER(descriptor, header, offset) \ { \ if ((GNU_EXEC_MAGIC (header)) == GNU_ZMAGIC) \ { \ int GNU_PAGE_SEEK_remainder; \ \ GNU_PAGE_SEEK_remainder = ((offset) % GNU_PAGE_SIZE); \ if (GNU_PAGE_SEEK_remainder != 0) \ iou_lseek \ ((descriptor), (GNU_PAGE_SIZE - GNU_PAGE_SEEK_remainder), 1); \ } \ } #define GNU_PAGE_SEEK_TEXT(descriptor, header, offset) #endif /* hpux */ struct gnu_nlist { union { char *n_name; /* for use when in-core */ long n_strx; /* index into file string table */ } n_un; unsigned char n_type; /* type flag (N_TEXT,..) */ char n_other; /* unused */ short n_desc; /* see <stab.h> */ unsigned long n_value; /* value of symbol (or sdb offset) */ }; #define GNU_SYMTYPE_UNDEFINED 0x0 #define GNU_SYMTYPE_ABSOLUTE 0x2 #define GNU_SYMTYPE_TEXT 0x4 #define GNU_SYMTYPE_DATA 0x6 #define GNU_SYMTYPE_BSS 0x8 #define GNU_SYMTYPE_COMMON 0x12 #define GNU_SYMTYPE_FILENAME 0x1F #define GNU_SYMTYPE_EXTERNAL 0x01 struct gnu_relocation_info { long r_address; /* address which is relocated */ unsigned int r_symbolnum : 24, /* local symbol ordinal */ r_pcrel : 1, /* was relocated pc relative already */ r_length : 2, /* BYTE, WORD, or LONG */ r_extern : 1, /* does not include value of sym referenced */ : 4; /* nothing, yet */ }; #define GNU_RLENGTH_BYTE 0x00 #define GNU_RLENGTH_WORD 0x01 #define GNU_RLENGTH_LONG 0x02 #define GNU_ARMAG "!<arch>\n" #define GNU_SARMAG 8 #define GNU_ARFMAG "`\n" struct gnu_ar_hdr { char ar_name [16]; char ar_date [12]; char ar_uid [6]; char ar_gid [6]; char ar_mode [8]; char ar_size [10]; char ar_fmag [2]; }; struct gnu_symdef { int symbol_name_string_index; int library_member_offset; }; \f /* List abstraction */ struct pair { char *car; char *cdr; }; struct pair * pair_cons (car, cdr) char *car; char *cdr; { register struct pair *result; result = ((struct pair *) (iou_malloc (sizeof (struct pair)))); (result -> car) = car; (result -> cdr) = cdr; return (result); } #define LIST_CDR(list) ((struct pair *) ((list) -> cdr)) #define LIST_SET_CDR(list, newcdr) (list -> cdr) = ((char *) newcdr) struct pair * list_reverse (list) register struct pair *list; { register struct pair *previous; register struct pair *next; previous = NULL; while (list != NULL) { next = (LIST_CDR (list)); LIST_SET_CDR (list, previous); previous = list; list = next; } return (previous); } struct pair * read_list (input_file, n_bytes, field_name, read_item, length) int input_file; int n_bytes; char * field_name; char * (* read_item) (); register int * length; /* return value */ { register struct pair *result; result = NULL; (* length) = 0; while (n_bytes > 0) { result = (pair_cons (((* read_item) (input_file, (& n_bytes))), result)); (* length) += 1; } if (n_bytes != 0) iou_error ("%s field size incorrect", field_name); return (list_reverse (result)); } \f /* Symbol Table */ struct gnu_nlist * read_symbol (input_file, n_bytes) int input_file; int *n_bytes; /* return value */ { struct hp_nlist input_nlist; register struct gnu_nlist *output_nlist; register char *name; { register int name_length; xread (input_file, (& input_nlist), (sizeof (input_nlist))); name_length = (input_nlist . n_length); name = (iou_malloc (name_length + 1)); xread (input_file, name, name_length); (name [name_length]) = '\0'; (* n_bytes) -= ((sizeof (input_nlist)) + name_length); } output_nlist = ((struct gnu_nlist *) (iou_malloc (sizeof (struct gnu_nlist)))); ((output_nlist -> n_un) . n_name) = name; (output_nlist -> n_other) = 0; (output_nlist -> n_desc) = 0; (output_nlist -> n_value) = (input_nlist . n_value); { register int name_type; name_type = (input_nlist . n_type); if ((name_type & HP_SYMTYPE_ALIGN) != 0) iou_error ("aligned symbol encountered: %s", name); if (name_type == HP_SYMTYPE_FILENAME) (output_nlist -> n_type) = GNU_SYMTYPE_FILENAME; else { switch (name_type & HP_SYMTYPE_TYPE) { case HP_SYMTYPE_UNDEFINED: (output_nlist -> n_type) = GNU_SYMTYPE_UNDEFINED; break; case HP_SYMTYPE_ABSOLUTE: (output_nlist -> n_type) = GNU_SYMTYPE_ABSOLUTE; break; case HP_SYMTYPE_TEXT: (output_nlist -> n_type) = GNU_SYMTYPE_TEXT; break; case HP_SYMTYPE_DATA: (output_nlist -> n_type) = GNU_SYMTYPE_DATA; break; case HP_SYMTYPE_BSS: (output_nlist -> n_type) = GNU_SYMTYPE_BSS; break; case HP_SYMTYPE_COMMON: (output_nlist -> n_type) = GNU_SYMTYPE_COMMON; break; default: iou_error ("unknown symbol type encountered: %x", name_type); } if ((name_type & HP_SYMTYPE_EXTERNAL) != 0) (output_nlist -> n_type) |= GNU_SYMTYPE_EXTERNAL; } } return (output_nlist); } struct pair * read_symbol_table (input_file, n_bytes, length) int input_file; int n_bytes; int * length; /* return value */ { return (read_list (input_file, n_bytes, "symbol table", read_symbol, length)); } void write_symbol_table (output_file, symbol_table, length) int output_file; struct pair *symbol_table; int length; { register struct pair *scan; register char *name; struct gnu_nlist output_nlist; int string_table_index; (output_nlist . n_other) = 0; (output_nlist . n_desc) = 0; string_table_index = (sizeof (string_table_index)); for (scan = symbol_table; (scan != NULL); scan = (LIST_CDR (scan))) { register struct gnu_nlist *symbol; symbol = ((struct gnu_nlist *) (scan -> car)); name = ((symbol -> n_un) . n_name); ((output_nlist . n_un) . n_strx) = string_table_index; (output_nlist . n_type) = (symbol -> n_type); (output_nlist . n_value) = (symbol -> n_value); iou_write (output_file, (& output_nlist), (sizeof (output_nlist))); string_table_index += ((strlen (name)) + 1); (scan -> car) = name; iou_free (symbol); } iou_write (output_file, (& string_table_index), (sizeof (string_table_index))); scan = symbol_table; while (scan != NULL) { register struct pair *cdr; name = (scan -> car); iou_write (output_file, name, ((strlen (name)) + 1)); iou_free (name); cdr = (LIST_CDR (scan)); iou_free (scan); scan = cdr; } return; } \f /* Relocation Info */ struct gnu_relocation_info * read_relocation_info_1 (input_file, n_bytes) int input_file; register int * n_bytes; /* return value */ { struct hp_relocation_info input_info; register struct gnu_relocation_info *output_info; xread (input_file, (& input_info), (sizeof (input_info))); (* n_bytes) -= (sizeof (input_info)); output_info = ((struct gnu_relocation_info *) (iou_malloc (sizeof (struct gnu_relocation_info)))); (output_info -> r_pcrel) = 0; (output_info -> r_address) = (input_info . r_address); switch (input_info . r_segment) { case HP_RSEGMENT_TEXT: (output_info -> r_symbolnum) = GNU_SYMTYPE_TEXT; (output_info -> r_extern) = 0; break; case HP_RSEGMENT_DATA: (output_info -> r_symbolnum) = GNU_SYMTYPE_DATA; (output_info -> r_extern) = 0; break; case HP_RSEGMENT_BSS: (output_info -> r_symbolnum) = GNU_SYMTYPE_BSS; (output_info -> r_extern) = 0; break; case HP_RSEGMENT_EXTERNAL: (output_info -> r_symbolnum) = (input_info . r_symbolnum); (output_info -> r_extern) = 1; break; default: iou_error ("illegal relocation segment type: %x", (input_info . r_segment)); } switch (input_info . r_length) { case HP_RLENGTH_BYTE: (output_info -> r_length) = GNU_RLENGTH_BYTE; break; case HP_RLENGTH_WORD: (output_info -> r_length) = GNU_RLENGTH_WORD; break; case HP_RLENGTH_LONG: (output_info -> r_length) = GNU_RLENGTH_LONG; break; default: iou_error ("illegal relocation length: %x", (input_info . r_length)); } return (output_info); } struct pair * read_relocation_info (input_file, n_bytes, length) int input_file; int n_bytes; int * length; { return (read_list (input_file, n_bytes, "relocation info", read_relocation_info_1, length)); } void write_relocation_info (output_file, relocation_info, length) int output_file; struct pair *relocation_info; int length; { register struct pair *this; register struct gnu_relocation_info *car; register struct pair *cdr; this = relocation_info; while (this != NULL) { car = ((struct gnu_relocation_info *) (this -> car)); iou_write (output_file, car, (sizeof (struct gnu_relocation_info))); iou_free (car); cdr = (LIST_CDR (this)); iou_free (this); this = cdr; } return; } \f /* Convert an executable (or relocatable) file. */ void process_executable_file (input_file, output_file) int input_file; int output_file; { struct hp_exec input_exec; struct gnu_exec output_exec; char *text_segment; char *data_segment; struct pair *symbol_table; int symbol_table_length; struct pair *text_relocation_info; int text_relocation_info_length; struct pair *data_relocation_info; int data_relocation_info_length; xread (input_file, (& input_exec), (sizeof (input_exec))); HP_PAGE_SEEK (input_file, input_exec, (sizeof (input_exec))); if ((input_exec . a_text) != 0) { text_segment = (iou_malloc (input_exec . a_text)); xread (input_file, text_segment, (input_exec . a_text)); HP_PAGE_SEEK (input_file, input_exec, (input_exec . a_text)); } else text_segment = NULL; if ((input_exec . a_data) != 0) { data_segment = (iou_malloc (input_exec . a_data)); xread (input_file, data_segment, (input_exec . a_data)); HP_PAGE_SEEK (input_file, input_exec, (input_exec . a_data)); } else data_segment = NULL; /* Skip the pascal interface text */ iou_lseek (input_file, (input_exec . a_pasint), 1); symbol_table = (read_symbol_table (input_file, (input_exec . a_lesyms), (& symbol_table_length))); /* Skip the debugging tables */ iou_lseek (input_file, ((input_exec . a_dnttsize) + (input_exec . a_sltsize) + (input_exec . a_vtsize)), 1); text_relocation_info = (read_relocation_info (input_file, (input_exec . a_trsize), (& text_relocation_info_length))); data_relocation_info = (read_relocation_info (input_file, (input_exec . a_drsize), (& data_relocation_info_length))); bzero ((& output_exec), (sizeof (output_exec))); switch (HP_EXEC_MAGIC (input_exec)) { case HP_FILETYPE_RELOC: case HP_FILETYPE_EXEC: GNU_EXEC_SET_MAGIC (output_exec, GNU_OMAGIC); break; case HP_FILETYPE_SHARE: GNU_EXEC_SET_MAGIC (output_exec, GNU_NMAGIC); break; case HP_FILETYPE_DEMAND: GNU_EXEC_SET_MAGIC (output_exec, GNU_ZMAGIC); break; default: iou_error ("unknown magic type: %x", (HP_EXEC_MAGIC (input_exec))); } (output_exec . a_text) = (input_exec . a_text); (output_exec . a_data) = (input_exec . a_data); (output_exec . a_bss) = (input_exec . a_bss); (output_exec . a_syms) = (symbol_table_length * (sizeof (struct gnu_nlist))); (output_exec . a_entry) = (input_exec . a_entry); (output_exec . a_trsize) = (input_exec . a_trsize); (output_exec . a_drsize) = (input_exec . a_drsize); iou_write (output_file, (& output_exec), (sizeof (output_exec))); GNU_PAGE_SEEK_HEADER (output_file, output_exec, (sizeof (output_exec))); if (text_segment != NULL) { iou_write (output_file, text_segment, (output_exec . a_text)); iou_free (text_segment); GNU_PAGE_SEEK_TEXT (output_file, output_exec, (output_exec . a_text)); } if (data_segment != NULL) { iou_write (output_file, data_segment, (output_exec . a_data)); iou_free (data_segment); GNU_PAGE_SEEK_TEXT (output_file, output_exec, (output_exec . a_data)); } write_relocation_info (output_file, text_relocation_info, text_relocation_info_length); write_relocation_info (output_file, data_relocation_info, data_relocation_info_length); write_symbol_table (output_file, symbol_table, symbol_table_length); return; } \f /* Convert an archive file. */ /* These procedures take advantage of the fact that the HP and GNU formats for struct ar_hdr are virtually identical. */ long symtab_start_position; char *symtab_member_data; struct hp_ar_symtab_entry *hp_symtab_entries; struct gnu_symdef *gnu_symtab_entries; long symtab_entries_length; long symtab_names_length; void process_archive_file (input_file, output_file) int input_file; int output_file; { int start_position; int length; struct hp_ar_hdr input_header; int member_length; forward void process_archive_symtab (); forward void update_symtab_entries (); forward void output_symtab_entries (); forward void process_archive_entry (); gnu_symtab_entries = NULL; while (1) { start_position = (iou_lseek (input_file, 0, 1)); length = (read (input_file, (& input_header), (sizeof (input_header)))); if (length == 0) break; if (length != (sizeof (input_header))) iou_error ("input archive ends prematurely"); if (((strncmp ((input_header . ar_fmag), HP_ARFMAG, (sizeof (input_header . ar_fmag)))) != 0) || ((sscanf ((input_header . ar_size), "%d", (& member_length))) != 1)) iou_error ("malformatted header of archive member"); if (((input_header . ar_name) [0]) == '/') process_archive_symtab (input_file, output_file, (& input_header), member_length); else { if (gnu_symtab_entries != NULL) update_symtab_entries (start_position, (iou_lseek (output_file, 0, 1))); process_archive_entry (input_file, output_file, (& input_header), member_length); } } if (gnu_symtab_entries != NULL) output_symtab_entries (output_file, (& input_header)); return; } \f #ifdef DEBUG_SYMTAB void dump_symtab_data () { register struct hp_ar_symtab_entry *symtab_entries; register char *symtab_names; register int i; symtab_names = (symtab_member_data + (sizeof (struct hp_ar_symtab_hdr))); symtab_entries = ((struct hp_ar_symtab_entry *) (symtab_names + symtab_names_length)); for (i = 0; (i < symtab_entries_length); i += 1) { fprintf (stdout, "Entry %d: string_index = %d; file_index = %d; name = %s\n", i, ((symtab_entries [i]) . string_index), ((symtab_entries [i]) . file_index), (symtab_names + ((symtab_entries [i]) . string_index))); } fflush (stdout); return; } #endif /* DEBUG_SYMTAB */ void process_archive_symtab (input_file, output_file, input_header, member_length) int input_file; int output_file; struct hp_ar_hdr *input_header; int member_length; { long symtab_entries_bytes; void initialize_symtab_entries (); symtab_member_data = (iou_malloc (member_length)); xread (input_file, symtab_member_data, member_length); symtab_entries_length = (((struct hp_ar_symtab_hdr *) symtab_member_data) -> n_entries); symtab_entries_bytes = (symtab_entries_length * (sizeof (struct hp_ar_symtab_entry))); symtab_names_length = (((struct hp_ar_symtab_hdr *) symtab_member_data) -> string_table_size); #ifdef DEBUG_SYMTAB dump_symtab_data (); #endif { char string_buffer [((sizeof (input_header -> ar_name)) + 1)]; sprintf (string_buffer, "%-*s", (sizeof (input_header -> ar_name)), "__.SYMDEF"); strncpy ((input_header -> ar_name), string_buffer, (sizeof (input_header -> ar_name))); } { char string_buffer [((sizeof (input_header -> ar_size)) + 1)]; sprintf (string_buffer, "%-*d", (sizeof (input_header -> ar_size)), (symtab_entries_bytes + symtab_names_length + (2 * (sizeof (long))))); strncpy ((input_header -> ar_size), string_buffer, (sizeof (input_header -> ar_size))); } iou_write (output_file, input_header, (sizeof (* input_header))); iou_write (output_file, (& symtab_entries_bytes), (sizeof (long))); /* Leave slot for entries, which we fill in later. */ symtab_start_position = (iou_lseek (output_file, 0, 1)); initialize_symtab_entries (); iou_lseek (output_file, symtab_entries_bytes, 1); iou_write (output_file, (& symtab_names_length), (sizeof (long))); iou_write (output_file, (symtab_member_data + (sizeof (struct hp_ar_symtab_hdr))), symtab_names_length); return; } void initialize_symtab_entries () { register struct hp_ar_symtab_entry *scan_hp; register struct hp_ar_symtab_entry *end; register struct gnu_symdef *scan_gnu; hp_symtab_entries = ((struct hp_ar_symtab_entry *) (symtab_member_data + (sizeof (struct hp_ar_symtab_hdr)) + symtab_names_length)); gnu_symtab_entries = ((struct gnu_symdef *) (iou_malloc (symtab_entries_length * (sizeof (struct gnu_symdef))))); scan_hp = hp_symtab_entries; end = (scan_hp + symtab_entries_length); scan_gnu = gnu_symtab_entries; while (scan_hp < end) { (scan_gnu -> symbol_name_string_index) = (scan_hp -> string_index); (scan_gnu -> library_member_offset) = (-1); scan_hp += 1; scan_gnu += 1; } return; } void update_symtab_entries (old_offset, new_offset) register long old_offset; long new_offset; { register struct hp_ar_symtab_entry *scan_hp; register struct hp_ar_symtab_entry *end; register struct gnu_symdef *scan_gnu; #ifdef DEBUG_SYMTAB fprintf (stdout, "Update: old = %d, new = %d\n", old_offset, new_offset); #endif scan_hp = hp_symtab_entries; end = (scan_hp + symtab_entries_length); scan_gnu = gnu_symtab_entries; while (scan_hp < end) { if ((scan_hp -> file_index) == old_offset) { #ifdef DEBUG_SYMTAB fprintf (stdout, "\t%s\n", (symtab_member_data + (sizeof (struct hp_ar_symtab_hdr)) + (scan -> string_index))); #endif (scan_gnu -> library_member_offset) = new_offset; } scan_hp += 1; scan_gnu += 1; } return; } void check_symtab_entries () { register struct gnu_symdef *scan; register struct gnu_symdef *end; scan = gnu_symtab_entries; end = (scan + symtab_entries_length); while (scan < end) if (((scan++) -> library_member_offset) == (-1)) iou_error ("Uninitialized __.SYMTAB entry"); return; } void output_symtab_entries (output_file, input_header) int output_file; struct hp_ar_hdr *input_header; { check_symtab_entries (); iou_lseek (output_file, symtab_start_position, 0); iou_write (output_file, gnu_symtab_entries, (symtab_entries_length * (sizeof (struct gnu_symdef)))); iou_free (symtab_member_data); iou_free (gnu_symtab_entries); return; } \f void process_archive_entry (input_file, output_file, input_header, member_length) int input_file; int output_file; struct hp_ar_hdr *input_header; int member_length; { long header_position; long output_start; long output_end; long input_end; /* Strategy: leave a hole for the header, then process the file. Afterwards, back up and write the header in place. */ header_position = (iou_lseek (output_file, 0, 1)); output_start = (iou_lseek (output_file, (sizeof (* input_header)), 1)); input_end = ((iou_lseek (input_file, 0, 1)) + member_length); process_executable_file (input_file, output_file); if ((iou_lseek (input_file, 0, 1)) != input_end) iou_error ("process_executable_file used wrong amount of input"); output_end = (iou_lseek (output_file, 0, 1)); iou_lseek (output_file, header_position, 0); (* (index ((input_header -> ar_name), '/'))) = ' '; { char string_buffer [((sizeof (input_header -> ar_size)) + 1)]; sprintf (string_buffer, "%-*d", (sizeof (input_header -> ar_size)), (output_end - output_start)); strncpy ((input_header -> ar_size), string_buffer, (sizeof (input_header -> ar_size))); } iou_write (output_file, input_header, (sizeof (* input_header))); iou_lseek (output_file, output_end, 0); /* Pad to even byte boundary if needed */ if ((input_end & 1) != 0) iou_lseek (input_file, 1, 1); if ((output_end & 1) != 0) iou_write (output_file, "\0", 1); return; } \f void main (argc, argv) int argc; char *argv[]; { int input_file; int output_file; register int length; struct hp_magic input_magic; iou_set_program_name (argv); if (argc != 3) { fprintf (stderr, "usage: %s input-file output-file\n", iou_program_name); iou_error (); } input_file = (iou_open ((argv [1]), O_RDONLY)); output_file = (iou_open ((argv [2]), (O_WRONLY | O_CREAT | O_TRUNC), 0666)); xread (input_file, (& input_magic), (sizeof (input_magic))); if (HP_MAGIC_OK (input_magic)) { iou_lseek (input_file, 0, 0); process_executable_file (input_file, output_file); } else { char armag [HP_SARMAG]; iou_lseek (input_file, 0, 0); xread (input_file, armag, HP_SARMAG); if ((strncmp (armag, HP_ARMAG, HP_SARMAG)) != 0) iou_error ("input file not executable or archive"); iou_write (output_file, GNU_ARMAG, GNU_SARMAG); process_archive_file (input_file, output_file); } exit (0); /*NOTREACHED*/ }