1/* Binutils emulation layer.
2   Copyright 2002, 2003, 2006 Free Software Foundation, Inc.
3   Written by Tom Rix, Red Hat Inc.
4
5   This file is part of GNU Binutils.
6
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.
11
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.
16
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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
20
21#include "binemul.h"
22#include "bfdlink.h"
23#include "coff/internal.h"
24#include "coff/xcoff.h"
25#include "libcoff.h"
26#include "libxcoff.h"
27
28/* Default to <bigaf>.  */
29static bfd_boolean big_archive = TRUE;
30
31/* Whether to include 32 bit objects.  */
32static bfd_boolean X32 = TRUE;
33
34/* Whether to include 64 bit objects.  */
35static bfd_boolean X64 = FALSE;
36
37static void ar_emul_aix_usage (FILE *);
38static bfd_boolean ar_emul_aix_append (bfd **, char *, bfd_boolean);
39static bfd_boolean ar_emul_aix5_append (bfd **, char *, bfd_boolean);
40static bfd_boolean ar_emul_aix_replace (bfd **, char *, bfd_boolean);
41static bfd_boolean ar_emul_aix5_replace (bfd **, char *, bfd_boolean);
42static bfd_boolean ar_emul_aix_parse_arg (char *);
43static bfd_boolean ar_emul_aix_internal
44  (bfd **, char *, bfd_boolean, const char *, bfd_boolean);
45
46static void
47ar_emul_aix_usage (FILE *fp)
48{
49  AR_EMUL_USAGE_PRINT_OPTION_HEADER (fp);
50  /* xgettext:c-format */
51  fprintf (fp, _("  [-g]         - 32 bit small archive\n"));
52  fprintf (fp, _("  [-X32]       - ignores 64 bit objects\n"));
53  fprintf (fp, _("  [-X64]       - ignores 32 bit objects\n"));
54  fprintf (fp, _("  [-X32_64]    - accepts 32 and 64 bit objects\n"));
55}
56
57static bfd_boolean
58ar_emul_aix_internal (bfd **after_bfd, char *file_name, bfd_boolean verbose,
59		      const char * target_name, bfd_boolean is_append)
60{
61  bfd *temp;
62  bfd *try_bfd;
63
64  temp = *after_bfd;
65
66  /* Try 64 bit.  */
67  try_bfd = bfd_openr (file_name, target_name);
68
69  /* Failed or the object is possibly 32 bit.  */
70  if (NULL == try_bfd || ! bfd_check_format (try_bfd, bfd_object))
71    try_bfd = bfd_openr (file_name, "aixcoff-rs6000");
72
73  AR_EMUL_ELEMENT_CHECK (try_bfd, file_name);
74
75  if (bfd_xcoff_is_xcoff64 (try_bfd) && (! X64))
76    return FALSE;
77
78  if (bfd_xcoff_is_xcoff32 (try_bfd)
79      && bfd_check_format (try_bfd, bfd_object) && (! X32))
80    return FALSE;
81
82  if (is_append)
83    {
84      AR_EMUL_APPEND_PRINT_VERBOSE (verbose, file_name);
85    }
86  else
87    {
88      AR_EMUL_REPLACE_PRINT_VERBOSE (verbose, file_name);
89    }
90
91  *after_bfd = try_bfd;
92  (*after_bfd)->next = temp;
93
94  return TRUE;
95}
96
97
98static bfd_boolean
99ar_emul_aix_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
100{
101  return ar_emul_aix_internal (after_bfd, file_name, verbose,
102			       "aixcoff64-rs6000", TRUE);
103}
104
105static bfd_boolean
106ar_emul_aix5_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
107{
108  return ar_emul_aix_internal (after_bfd, file_name, verbose,
109			       "aix5coff64-rs6000", TRUE);
110}
111
112static bfd_boolean
113ar_emul_aix_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
114{
115  return ar_emul_aix_internal (after_bfd, file_name, verbose,
116			       "aixcoff64-rs6000", FALSE);
117}
118
119static bfd_boolean
120ar_emul_aix5_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
121{
122  return ar_emul_aix_internal (after_bfd, file_name, verbose,
123			       "aix5coff64-rs6000", FALSE);
124}
125
126static bfd_boolean
127ar_emul_aix_parse_arg (char *arg)
128{
129  if (CONST_STRNEQ (arg, "-X32_64"))
130    {
131      big_archive = TRUE;
132      X32 = TRUE;
133      X64 = TRUE;
134    }
135  else if (CONST_STRNEQ (arg, "-X32"))
136    {
137      big_archive = TRUE;
138      X32 = TRUE;
139      X64 = FALSE;
140    }
141  else if (CONST_STRNEQ (arg, "-X64"))
142    {
143      big_archive = TRUE;
144      X32 = FALSE;
145      X64 = TRUE;
146    }
147  else if (CONST_STRNEQ (arg, "-g"))
148    {
149      big_archive = FALSE;
150      X32 = TRUE;
151      X64 = FALSE;
152    }
153  else
154    return FALSE;
155
156  return TRUE;
157}
158
159struct bin_emulation_xfer_struct bin_aix_emulation =
160{
161  ar_emul_aix_usage,
162  ar_emul_aix_append,
163  ar_emul_aix_replace,
164  ar_emul_aix_parse_arg,
165};
166
167struct bin_emulation_xfer_struct bin_aix5_emulation =
168{
169  ar_emul_aix_usage,
170  ar_emul_aix5_append,
171  ar_emul_aix5_replace,
172  ar_emul_aix_parse_arg,
173};
174