1*3d8817e4Smiod /* arsup.c - Archive support for MRI compatibility
2*3d8817e4Smiod Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
3*3d8817e4Smiod 2004 Free Software Foundation, Inc.
4*3d8817e4Smiod
5*3d8817e4Smiod This file is part of GNU Binutils.
6*3d8817e4Smiod
7*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
8*3d8817e4Smiod it under the terms of the GNU General Public License as published by
9*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
10*3d8817e4Smiod (at your option) any later version.
11*3d8817e4Smiod
12*3d8817e4Smiod This program is distributed in the hope that it will be useful,
13*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
14*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*3d8817e4Smiod GNU General Public License for more details.
16*3d8817e4Smiod
17*3d8817e4Smiod You should have received a copy of the GNU General Public License
18*3d8817e4Smiod along with this program; if not, write to the Free Software
19*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20*3d8817e4Smiod
21*3d8817e4Smiod
22*3d8817e4Smiod /* Contributed by Steve Chamberlain
23*3d8817e4Smiod sac@cygnus.com
24*3d8817e4Smiod
25*3d8817e4Smiod This file looks after requests from arparse.y, to provide the MRI
26*3d8817e4Smiod style librarian command syntax + 1 word LIST. */
27*3d8817e4Smiod
28*3d8817e4Smiod #include "bfd.h"
29*3d8817e4Smiod #include "arsup.h"
30*3d8817e4Smiod #include "libiberty.h"
31*3d8817e4Smiod #include "bucomm.h"
32*3d8817e4Smiod #include "filenames.h"
33*3d8817e4Smiod
34*3d8817e4Smiod static void map_over_list
35*3d8817e4Smiod (bfd *, void (*function) (bfd *, bfd *), struct list *);
36*3d8817e4Smiod static void ar_directory_doer (bfd *, bfd *);
37*3d8817e4Smiod static void ar_addlib_doer (bfd *, bfd *);
38*3d8817e4Smiod
39*3d8817e4Smiod extern int verbose;
40*3d8817e4Smiod
41*3d8817e4Smiod static bfd *obfd;
42*3d8817e4Smiod static char *real_name;
43*3d8817e4Smiod static FILE *outfile;
44*3d8817e4Smiod
45*3d8817e4Smiod static void
map_over_list(bfd * arch,void (* function)(bfd *,bfd *),struct list * list)46*3d8817e4Smiod map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list)
47*3d8817e4Smiod {
48*3d8817e4Smiod bfd *head;
49*3d8817e4Smiod
50*3d8817e4Smiod if (list == NULL)
51*3d8817e4Smiod {
52*3d8817e4Smiod bfd *next;
53*3d8817e4Smiod
54*3d8817e4Smiod head = arch->next;
55*3d8817e4Smiod while (head != NULL)
56*3d8817e4Smiod {
57*3d8817e4Smiod next = head->next;
58*3d8817e4Smiod function (head, (bfd *) NULL);
59*3d8817e4Smiod head = next;
60*3d8817e4Smiod }
61*3d8817e4Smiod }
62*3d8817e4Smiod else
63*3d8817e4Smiod {
64*3d8817e4Smiod struct list *ptr;
65*3d8817e4Smiod
66*3d8817e4Smiod /* This may appear to be a baroque way of accomplishing what we
67*3d8817e4Smiod want. however we have to iterate over the filenames in order
68*3d8817e4Smiod to notice where a filename is requested but does not exist in
69*3d8817e4Smiod the archive. Ditto mapping over each file each time -- we
70*3d8817e4Smiod want to hack multiple references. */
71*3d8817e4Smiod for (ptr = list; ptr; ptr = ptr->next)
72*3d8817e4Smiod {
73*3d8817e4Smiod bfd_boolean found = FALSE;
74*3d8817e4Smiod bfd *prev = arch;
75*3d8817e4Smiod
76*3d8817e4Smiod for (head = arch->next; head; head = head->next)
77*3d8817e4Smiod {
78*3d8817e4Smiod if (head->filename != NULL
79*3d8817e4Smiod && FILENAME_CMP (ptr->name, head->filename) == 0)
80*3d8817e4Smiod {
81*3d8817e4Smiod found = TRUE;
82*3d8817e4Smiod function (head, prev);
83*3d8817e4Smiod }
84*3d8817e4Smiod prev = head;
85*3d8817e4Smiod }
86*3d8817e4Smiod if (! found)
87*3d8817e4Smiod fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
88*3d8817e4Smiod }
89*3d8817e4Smiod }
90*3d8817e4Smiod }
91*3d8817e4Smiod
92*3d8817e4Smiod
93*3d8817e4Smiod
94*3d8817e4Smiod static void
ar_directory_doer(bfd * abfd,bfd * ignore ATTRIBUTE_UNUSED)95*3d8817e4Smiod ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
96*3d8817e4Smiod {
97*3d8817e4Smiod print_arelt_descr(outfile, abfd, verbose);
98*3d8817e4Smiod }
99*3d8817e4Smiod
100*3d8817e4Smiod void
ar_directory(char * ar_name,struct list * list,char * output)101*3d8817e4Smiod ar_directory (char *ar_name, struct list *list, char *output)
102*3d8817e4Smiod {
103*3d8817e4Smiod bfd *arch;
104*3d8817e4Smiod
105*3d8817e4Smiod arch = open_inarch (ar_name, (char *) NULL);
106*3d8817e4Smiod if (output)
107*3d8817e4Smiod {
108*3d8817e4Smiod outfile = fopen(output,"w");
109*3d8817e4Smiod if (outfile == 0)
110*3d8817e4Smiod {
111*3d8817e4Smiod outfile = stdout;
112*3d8817e4Smiod fprintf (stderr,_("Can't open file %s\n"), output);
113*3d8817e4Smiod output = 0;
114*3d8817e4Smiod }
115*3d8817e4Smiod }
116*3d8817e4Smiod else
117*3d8817e4Smiod outfile = stdout;
118*3d8817e4Smiod
119*3d8817e4Smiod map_over_list (arch, ar_directory_doer, list);
120*3d8817e4Smiod
121*3d8817e4Smiod bfd_close (arch);
122*3d8817e4Smiod
123*3d8817e4Smiod if (output)
124*3d8817e4Smiod fclose (outfile);
125*3d8817e4Smiod }
126*3d8817e4Smiod
127*3d8817e4Smiod void
prompt(void)128*3d8817e4Smiod prompt (void)
129*3d8817e4Smiod {
130*3d8817e4Smiod extern int interactive;
131*3d8817e4Smiod
132*3d8817e4Smiod if (interactive)
133*3d8817e4Smiod {
134*3d8817e4Smiod printf ("AR >");
135*3d8817e4Smiod fflush (stdout);
136*3d8817e4Smiod }
137*3d8817e4Smiod }
138*3d8817e4Smiod
139*3d8817e4Smiod void
maybequit(void)140*3d8817e4Smiod maybequit (void)
141*3d8817e4Smiod {
142*3d8817e4Smiod if (! interactive)
143*3d8817e4Smiod xexit (9);
144*3d8817e4Smiod }
145*3d8817e4Smiod
146*3d8817e4Smiod
147*3d8817e4Smiod void
ar_open(char * name,int t)148*3d8817e4Smiod ar_open (char *name, int t)
149*3d8817e4Smiod {
150*3d8817e4Smiod char *tname = (char *) xmalloc (strlen (name) + 10);
151*3d8817e4Smiod const char *bname = lbasename (name);
152*3d8817e4Smiod real_name = name;
153*3d8817e4Smiod
154*3d8817e4Smiod /* Prepend tmp- to the beginning, to avoid file-name clashes after
155*3d8817e4Smiod truncation on filesystems with limited namespaces (DOS). */
156*3d8817e4Smiod sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname);
157*3d8817e4Smiod obfd = bfd_openw (tname, NULL);
158*3d8817e4Smiod
159*3d8817e4Smiod if (!obfd)
160*3d8817e4Smiod {
161*3d8817e4Smiod fprintf (stderr,
162*3d8817e4Smiod _("%s: Can't open output archive %s\n"),
163*3d8817e4Smiod program_name, tname);
164*3d8817e4Smiod
165*3d8817e4Smiod maybequit ();
166*3d8817e4Smiod }
167*3d8817e4Smiod else
168*3d8817e4Smiod {
169*3d8817e4Smiod if (!t)
170*3d8817e4Smiod {
171*3d8817e4Smiod bfd **ptr;
172*3d8817e4Smiod bfd *element;
173*3d8817e4Smiod bfd *ibfd;
174*3d8817e4Smiod
175*3d8817e4Smiod ibfd = bfd_openr (name, NULL);
176*3d8817e4Smiod
177*3d8817e4Smiod if (!ibfd)
178*3d8817e4Smiod {
179*3d8817e4Smiod fprintf (stderr,_("%s: Can't open input archive %s\n"),
180*3d8817e4Smiod program_name, name);
181*3d8817e4Smiod maybequit ();
182*3d8817e4Smiod return;
183*3d8817e4Smiod }
184*3d8817e4Smiod
185*3d8817e4Smiod if (!bfd_check_format(ibfd, bfd_archive))
186*3d8817e4Smiod {
187*3d8817e4Smiod fprintf (stderr,
188*3d8817e4Smiod _("%s: file %s is not an archive\n"),
189*3d8817e4Smiod program_name, name);
190*3d8817e4Smiod maybequit ();
191*3d8817e4Smiod return;
192*3d8817e4Smiod }
193*3d8817e4Smiod
194*3d8817e4Smiod ptr = &(obfd->archive_head);
195*3d8817e4Smiod element = bfd_openr_next_archived_file (ibfd, NULL);
196*3d8817e4Smiod
197*3d8817e4Smiod while (element)
198*3d8817e4Smiod {
199*3d8817e4Smiod *ptr = element;
200*3d8817e4Smiod ptr = &element->next;
201*3d8817e4Smiod element = bfd_openr_next_archived_file (ibfd, element);
202*3d8817e4Smiod }
203*3d8817e4Smiod }
204*3d8817e4Smiod
205*3d8817e4Smiod bfd_set_format (obfd, bfd_archive);
206*3d8817e4Smiod
207*3d8817e4Smiod obfd->has_armap = 1;
208*3d8817e4Smiod }
209*3d8817e4Smiod }
210*3d8817e4Smiod
211*3d8817e4Smiod static void
ar_addlib_doer(bfd * abfd,bfd * prev)212*3d8817e4Smiod ar_addlib_doer (bfd *abfd, bfd *prev)
213*3d8817e4Smiod {
214*3d8817e4Smiod /* Add this module to the output bfd. */
215*3d8817e4Smiod if (prev != NULL)
216*3d8817e4Smiod prev->next = abfd->next;
217*3d8817e4Smiod
218*3d8817e4Smiod abfd->next = obfd->archive_head;
219*3d8817e4Smiod obfd->archive_head = abfd;
220*3d8817e4Smiod }
221*3d8817e4Smiod
222*3d8817e4Smiod void
ar_addlib(char * name,struct list * list)223*3d8817e4Smiod ar_addlib (char *name, struct list *list)
224*3d8817e4Smiod {
225*3d8817e4Smiod if (obfd == NULL)
226*3d8817e4Smiod {
227*3d8817e4Smiod fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
228*3d8817e4Smiod maybequit ();
229*3d8817e4Smiod }
230*3d8817e4Smiod else
231*3d8817e4Smiod {
232*3d8817e4Smiod bfd *arch;
233*3d8817e4Smiod
234*3d8817e4Smiod arch = open_inarch (name, (char *) NULL);
235*3d8817e4Smiod if (arch != NULL)
236*3d8817e4Smiod map_over_list (arch, ar_addlib_doer, list);
237*3d8817e4Smiod
238*3d8817e4Smiod /* Don't close the bfd, since it will make the elements disappear. */
239*3d8817e4Smiod }
240*3d8817e4Smiod }
241*3d8817e4Smiod
242*3d8817e4Smiod void
ar_addmod(struct list * list)243*3d8817e4Smiod ar_addmod (struct list *list)
244*3d8817e4Smiod {
245*3d8817e4Smiod if (!obfd)
246*3d8817e4Smiod {
247*3d8817e4Smiod fprintf (stderr, _("%s: no open output archive\n"), program_name);
248*3d8817e4Smiod maybequit ();
249*3d8817e4Smiod }
250*3d8817e4Smiod else
251*3d8817e4Smiod {
252*3d8817e4Smiod while (list)
253*3d8817e4Smiod {
254*3d8817e4Smiod bfd *abfd = bfd_openr (list->name, NULL);
255*3d8817e4Smiod
256*3d8817e4Smiod if (!abfd)
257*3d8817e4Smiod {
258*3d8817e4Smiod fprintf (stderr, _("%s: can't open file %s\n"),
259*3d8817e4Smiod program_name, list->name);
260*3d8817e4Smiod maybequit ();
261*3d8817e4Smiod }
262*3d8817e4Smiod else
263*3d8817e4Smiod {
264*3d8817e4Smiod abfd->next = obfd->archive_head;
265*3d8817e4Smiod obfd->archive_head = abfd;
266*3d8817e4Smiod }
267*3d8817e4Smiod list = list->next;
268*3d8817e4Smiod }
269*3d8817e4Smiod }
270*3d8817e4Smiod }
271*3d8817e4Smiod
272*3d8817e4Smiod
273*3d8817e4Smiod void
ar_clear(void)274*3d8817e4Smiod ar_clear (void)
275*3d8817e4Smiod {
276*3d8817e4Smiod if (obfd)
277*3d8817e4Smiod obfd->archive_head = 0;
278*3d8817e4Smiod }
279*3d8817e4Smiod
280*3d8817e4Smiod void
ar_delete(struct list * list)281*3d8817e4Smiod ar_delete (struct list *list)
282*3d8817e4Smiod {
283*3d8817e4Smiod if (!obfd)
284*3d8817e4Smiod {
285*3d8817e4Smiod fprintf (stderr, _("%s: no open output archive\n"), program_name);
286*3d8817e4Smiod maybequit ();
287*3d8817e4Smiod }
288*3d8817e4Smiod else
289*3d8817e4Smiod {
290*3d8817e4Smiod while (list)
291*3d8817e4Smiod {
292*3d8817e4Smiod /* Find this name in the archive. */
293*3d8817e4Smiod bfd *member = obfd->archive_head;
294*3d8817e4Smiod bfd **prev = &(obfd->archive_head);
295*3d8817e4Smiod int found = 0;
296*3d8817e4Smiod
297*3d8817e4Smiod while (member)
298*3d8817e4Smiod {
299*3d8817e4Smiod if (FILENAME_CMP(member->filename, list->name) == 0)
300*3d8817e4Smiod {
301*3d8817e4Smiod *prev = member->next;
302*3d8817e4Smiod found = 1;
303*3d8817e4Smiod }
304*3d8817e4Smiod else
305*3d8817e4Smiod prev = &(member->next);
306*3d8817e4Smiod
307*3d8817e4Smiod member = member->next;
308*3d8817e4Smiod }
309*3d8817e4Smiod
310*3d8817e4Smiod if (!found)
311*3d8817e4Smiod {
312*3d8817e4Smiod fprintf (stderr, _("%s: can't find module file %s\n"),
313*3d8817e4Smiod program_name, list->name);
314*3d8817e4Smiod maybequit ();
315*3d8817e4Smiod }
316*3d8817e4Smiod
317*3d8817e4Smiod list = list->next;
318*3d8817e4Smiod }
319*3d8817e4Smiod }
320*3d8817e4Smiod }
321*3d8817e4Smiod
322*3d8817e4Smiod void
ar_save(void)323*3d8817e4Smiod ar_save (void)
324*3d8817e4Smiod {
325*3d8817e4Smiod if (!obfd)
326*3d8817e4Smiod {
327*3d8817e4Smiod fprintf (stderr, _("%s: no open output archive\n"), program_name);
328*3d8817e4Smiod maybequit ();
329*3d8817e4Smiod }
330*3d8817e4Smiod else
331*3d8817e4Smiod {
332*3d8817e4Smiod char *ofilename = xstrdup (bfd_get_filename (obfd));
333*3d8817e4Smiod
334*3d8817e4Smiod bfd_close (obfd);
335*3d8817e4Smiod
336*3d8817e4Smiod smart_rename (ofilename, real_name, 0);
337*3d8817e4Smiod obfd = 0;
338*3d8817e4Smiod free (ofilename);
339*3d8817e4Smiod }
340*3d8817e4Smiod }
341*3d8817e4Smiod
342*3d8817e4Smiod void
ar_replace(struct list * list)343*3d8817e4Smiod ar_replace (struct list *list)
344*3d8817e4Smiod {
345*3d8817e4Smiod if (!obfd)
346*3d8817e4Smiod {
347*3d8817e4Smiod fprintf (stderr, _("%s: no open output archive\n"), program_name);
348*3d8817e4Smiod maybequit ();
349*3d8817e4Smiod }
350*3d8817e4Smiod else
351*3d8817e4Smiod {
352*3d8817e4Smiod while (list)
353*3d8817e4Smiod {
354*3d8817e4Smiod /* Find this name in the archive. */
355*3d8817e4Smiod bfd *member = obfd->archive_head;
356*3d8817e4Smiod bfd **prev = &(obfd->archive_head);
357*3d8817e4Smiod int found = 0;
358*3d8817e4Smiod
359*3d8817e4Smiod while (member)
360*3d8817e4Smiod {
361*3d8817e4Smiod if (FILENAME_CMP (member->filename, list->name) == 0)
362*3d8817e4Smiod {
363*3d8817e4Smiod /* Found the one to replace. */
364*3d8817e4Smiod bfd *abfd = bfd_openr (list->name, 0);
365*3d8817e4Smiod
366*3d8817e4Smiod if (!abfd)
367*3d8817e4Smiod {
368*3d8817e4Smiod fprintf (stderr, _("%s: can't open file %s\n"),
369*3d8817e4Smiod program_name, list->name);
370*3d8817e4Smiod maybequit ();
371*3d8817e4Smiod }
372*3d8817e4Smiod else
373*3d8817e4Smiod {
374*3d8817e4Smiod *prev = abfd;
375*3d8817e4Smiod abfd->next = member->next;
376*3d8817e4Smiod found = 1;
377*3d8817e4Smiod }
378*3d8817e4Smiod }
379*3d8817e4Smiod else
380*3d8817e4Smiod {
381*3d8817e4Smiod prev = &(member->next);
382*3d8817e4Smiod }
383*3d8817e4Smiod member = member->next;
384*3d8817e4Smiod }
385*3d8817e4Smiod
386*3d8817e4Smiod if (!found)
387*3d8817e4Smiod {
388*3d8817e4Smiod bfd *abfd = bfd_openr (list->name, 0);
389*3d8817e4Smiod
390*3d8817e4Smiod fprintf (stderr,_("%s: can't find module file %s\n"),
391*3d8817e4Smiod program_name, list->name);
392*3d8817e4Smiod if (!abfd)
393*3d8817e4Smiod {
394*3d8817e4Smiod fprintf (stderr, _("%s: can't open file %s\n"),
395*3d8817e4Smiod program_name, list->name);
396*3d8817e4Smiod maybequit ();
397*3d8817e4Smiod }
398*3d8817e4Smiod else
399*3d8817e4Smiod *prev = abfd;
400*3d8817e4Smiod }
401*3d8817e4Smiod
402*3d8817e4Smiod list = list->next;
403*3d8817e4Smiod }
404*3d8817e4Smiod }
405*3d8817e4Smiod }
406*3d8817e4Smiod
407*3d8817e4Smiod /* And I added this one. */
408*3d8817e4Smiod void
ar_list(void)409*3d8817e4Smiod ar_list (void)
410*3d8817e4Smiod {
411*3d8817e4Smiod if (!obfd)
412*3d8817e4Smiod {
413*3d8817e4Smiod fprintf (stderr, _("%s: no open output archive\n"), program_name);
414*3d8817e4Smiod maybequit ();
415*3d8817e4Smiod }
416*3d8817e4Smiod else
417*3d8817e4Smiod {
418*3d8817e4Smiod bfd *abfd;
419*3d8817e4Smiod
420*3d8817e4Smiod outfile = stdout;
421*3d8817e4Smiod verbose =1 ;
422*3d8817e4Smiod printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
423*3d8817e4Smiod
424*3d8817e4Smiod for (abfd = obfd->archive_head;
425*3d8817e4Smiod abfd != (bfd *)NULL;
426*3d8817e4Smiod abfd = abfd->next)
427*3d8817e4Smiod ar_directory_doer (abfd, (bfd *) NULL);
428*3d8817e4Smiod }
429*3d8817e4Smiod }
430*3d8817e4Smiod
431*3d8817e4Smiod void
ar_end(void)432*3d8817e4Smiod ar_end (void)
433*3d8817e4Smiod {
434*3d8817e4Smiod if (obfd)
435*3d8817e4Smiod {
436*3d8817e4Smiod bfd_cache_close (obfd);
437*3d8817e4Smiod unlink (bfd_get_filename (obfd));
438*3d8817e4Smiod }
439*3d8817e4Smiod }
440*3d8817e4Smiod
441*3d8817e4Smiod void
ar_extract(struct list * list)442*3d8817e4Smiod ar_extract (struct list *list)
443*3d8817e4Smiod {
444*3d8817e4Smiod if (!obfd)
445*3d8817e4Smiod {
446*3d8817e4Smiod fprintf (stderr, _("%s: no open archive\n"), program_name);
447*3d8817e4Smiod maybequit ();
448*3d8817e4Smiod }
449*3d8817e4Smiod else
450*3d8817e4Smiod {
451*3d8817e4Smiod while (list)
452*3d8817e4Smiod {
453*3d8817e4Smiod /* Find this name in the archive. */
454*3d8817e4Smiod bfd *member = obfd->archive_head;
455*3d8817e4Smiod int found = 0;
456*3d8817e4Smiod
457*3d8817e4Smiod while (member && !found)
458*3d8817e4Smiod {
459*3d8817e4Smiod if (FILENAME_CMP (member->filename, list->name) == 0)
460*3d8817e4Smiod {
461*3d8817e4Smiod extract_file (member);
462*3d8817e4Smiod found = 1;
463*3d8817e4Smiod }
464*3d8817e4Smiod
465*3d8817e4Smiod member = member->next;
466*3d8817e4Smiod }
467*3d8817e4Smiod
468*3d8817e4Smiod if (!found)
469*3d8817e4Smiod {
470*3d8817e4Smiod bfd_openr (list->name, 0);
471*3d8817e4Smiod fprintf (stderr, _("%s: can't find module file %s\n"),
472*3d8817e4Smiod program_name, list->name);
473*3d8817e4Smiod }
474*3d8817e4Smiod
475*3d8817e4Smiod list = list->next;
476*3d8817e4Smiod }
477*3d8817e4Smiod }
478*3d8817e4Smiod }
479