+/* Information about one member of an archive. */
+struct member_layout {
+ /* The archive member that this structure describes. */
+ bfd *member;
+
+ /* The number of bytes of padding that must be inserted before the
+ start of the member in order to ensure that the section contents
+ are correctly aligned. */
+ unsigned int leading_padding;
+
+ /* The offset of MEMBER from the start of the archive (i.e. the end
+ of the leading padding). */
+ file_ptr offset;
+
+ /* The normalized name of MEMBER. */
+ const char *name;
+
+ /* The length of NAME, without padding. */
+ bfd_size_type namlen;
+
+ /* The length of NAME, with padding. */
+ bfd_size_type padded_namlen;
+
+ /* The size of MEMBER's header, including the name and magic sequence. */
+ bfd_size_type header_size;
+
+ /* The size of the MEMBER's contents. */
+ bfd_size_type contents_size;
+
+ /* The number of bytes of padding that must be inserted after MEMBER
+ in order to preserve even alignment. */
+ bfd_size_type trailing_padding;
+};
+
+/* A structure used for iterating over the members of an archive. */
+struct archive_iterator {
+ /* The archive itself. */
+ bfd *archive;
+
+ /* Information about the current archive member. */
+ struct member_layout current;
+
+ /* Information about the next archive member. MEMBER is null if there
+ are no more archive members, in which case OFFSET is the offset of
+ the first unused byte. */
+ struct member_layout next;
+};
+
+/* Initialize INFO so that it describes member MEMBER of archive ARCHIVE.
+ OFFSET is the even-padded offset of MEMBER, not including any leading
+ padding needed for section alignment. */
+
+static void
+member_layout_init (struct member_layout *info, bfd *archive,
+ bfd *member, file_ptr offset)
+{
+ info->member = member;
+ info->leading_padding = 0;
+ if (member)
+ {
+ info->name = normalize_filename (member);
+ info->namlen = strlen (info->name);
+ info->padded_namlen = info->namlen + (info->namlen & 1);
+ if (xcoff_big_format_p (archive))
+ info->header_size = SIZEOF_AR_HDR_BIG;
+ else
+ info->header_size = SIZEOF_AR_HDR;
+ info->header_size += info->padded_namlen + SXCOFFARFMAG;
+ info->contents_size = arelt_size (member);
+ info->trailing_padding = info->contents_size & 1;
+
+ if (bfd_check_format (member, bfd_object)
+ && bfd_get_flavour (member) == bfd_target_xcoff_flavour
+ && (member->flags & DYNAMIC) != 0)
+ info->leading_padding
+ = (-(offset + info->header_size)
+ & ((1 << bfd_xcoff_text_align_power (member)) - 1));
+ }
+ info->offset = offset + info->leading_padding;
+}
+
+/* Set up ITERATOR to iterate through archive ARCHIVE. */
+
+static void
+archive_iterator_begin (struct archive_iterator *iterator,
+ bfd *archive)
+{
+ iterator->archive = archive;
+ member_layout_init (&iterator->next, archive, archive->archive_head,
+ xcoff_big_format_p (archive)
+ ? SIZEOF_AR_FILE_HDR_BIG
+ : SIZEOF_AR_FILE_HDR);
+}
+
+/* Make ITERATOR visit the first unvisited archive member. Return true
+ on success; return false if all members have been visited. */
+
+static bfd_boolean
+archive_iterator_next (struct archive_iterator *iterator)
+{
+ if (!iterator->next.member)
+ return FALSE;
+
+ iterator->current = iterator->next;
+ member_layout_init (&iterator->next, iterator->archive,
+ iterator->current.member->archive_next,
+ iterator->current.offset
+ + iterator->current.header_size
+ + iterator->current.contents_size
+ + iterator->current.trailing_padding);
+ return TRUE;
+}
+