2007-06-04 Olivier Hainque <hainque@adacore.com>
[binutils.git] / binutils / arsup.c
blob0d2b2a5fc3aa57f998566ae3938076a1d6446216
1 /* arsup.c - Archive support for MRI compatibility
2 Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
3 2004, 2007 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
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.
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.
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. */
22 /* Contributed by Steve Chamberlain
23 sac@cygnus.com
25 This file looks after requests from arparse.y, to provide the MRI
26 style librarian command syntax + 1 word LIST. */
28 #include "sysdep.h"
29 #include "bfd.h"
30 #include "libiberty.h"
31 #include "filenames.h"
32 #include "bucomm.h"
33 #include "arsup.h"
35 static void map_over_list
36 (bfd *, void (*function) (bfd *, bfd *), struct list *);
37 static void ar_directory_doer (bfd *, bfd *);
38 static void ar_addlib_doer (bfd *, bfd *);
40 extern int verbose;
42 static bfd *obfd;
43 static char *real_name;
44 static FILE *outfile;
46 static void
47 map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list)
49 bfd *head;
51 if (list == NULL)
53 bfd *next;
55 head = arch->next;
56 while (head != NULL)
58 next = head->next;
59 function (head, (bfd *) NULL);
60 head = next;
63 else
65 struct list *ptr;
67 /* This may appear to be a baroque way of accomplishing what we
68 want. however we have to iterate over the filenames in order
69 to notice where a filename is requested but does not exist in
70 the archive. Ditto mapping over each file each time -- we
71 want to hack multiple references. */
72 for (ptr = list; ptr; ptr = ptr->next)
74 bfd_boolean found = FALSE;
75 bfd *prev = arch;
77 for (head = arch->next; head; head = head->next)
79 if (head->filename != NULL
80 && FILENAME_CMP (ptr->name, head->filename) == 0)
82 found = TRUE;
83 function (head, prev);
85 prev = head;
87 if (! found)
88 fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
95 static void
96 ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
98 print_arelt_descr(outfile, abfd, verbose);
101 void
102 ar_directory (char *ar_name, struct list *list, char *output)
104 bfd *arch;
106 arch = open_inarch (ar_name, (char *) NULL);
107 if (output)
109 outfile = fopen(output,"w");
110 if (outfile == 0)
112 outfile = stdout;
113 fprintf (stderr,_("Can't open file %s\n"), output);
114 output = 0;
117 else
118 outfile = stdout;
120 map_over_list (arch, ar_directory_doer, list);
122 bfd_close (arch);
124 if (output)
125 fclose (outfile);
128 void
129 prompt (void)
131 extern int interactive;
133 if (interactive)
135 printf ("AR >");
136 fflush (stdout);
140 void
141 maybequit (void)
143 if (! interactive)
144 xexit (9);
148 void
149 ar_open (char *name, int t)
151 char *tname = (char *) xmalloc (strlen (name) + 10);
152 const char *bname = lbasename (name);
153 real_name = name;
155 /* Prepend tmp- to the beginning, to avoid file-name clashes after
156 truncation on filesystems with limited namespaces (DOS). */
157 sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname);
158 obfd = bfd_openw (tname, NULL);
160 if (!obfd)
162 fprintf (stderr,
163 _("%s: Can't open output archive %s\n"),
164 program_name, tname);
166 maybequit ();
168 else
170 if (!t)
172 bfd **ptr;
173 bfd *element;
174 bfd *ibfd;
176 ibfd = bfd_openr (name, NULL);
178 if (!ibfd)
180 fprintf (stderr,_("%s: Can't open input archive %s\n"),
181 program_name, name);
182 maybequit ();
183 return;
186 if (!bfd_check_format(ibfd, bfd_archive))
188 fprintf (stderr,
189 _("%s: file %s is not an archive\n"),
190 program_name, name);
191 maybequit ();
192 return;
195 ptr = &(obfd->archive_head);
196 element = bfd_openr_next_archived_file (ibfd, NULL);
198 while (element)
200 *ptr = element;
201 ptr = &element->next;
202 element = bfd_openr_next_archived_file (ibfd, element);
206 bfd_set_format (obfd, bfd_archive);
208 obfd->has_armap = 1;
212 static void
213 ar_addlib_doer (bfd *abfd, bfd *prev)
215 /* Add this module to the output bfd. */
216 if (prev != NULL)
217 prev->next = abfd->next;
219 abfd->next = obfd->archive_head;
220 obfd->archive_head = abfd;
223 void
224 ar_addlib (char *name, struct list *list)
226 if (obfd == NULL)
228 fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
229 maybequit ();
231 else
233 bfd *arch;
235 arch = open_inarch (name, (char *) NULL);
236 if (arch != NULL)
237 map_over_list (arch, ar_addlib_doer, list);
239 /* Don't close the bfd, since it will make the elements disappear. */
243 void
244 ar_addmod (struct list *list)
246 if (!obfd)
248 fprintf (stderr, _("%s: no open output archive\n"), program_name);
249 maybequit ();
251 else
253 while (list)
255 bfd *abfd = bfd_openr (list->name, NULL);
257 if (!abfd)
259 fprintf (stderr, _("%s: can't open file %s\n"),
260 program_name, list->name);
261 maybequit ();
263 else
265 abfd->next = obfd->archive_head;
266 obfd->archive_head = abfd;
268 list = list->next;
274 void
275 ar_clear (void)
277 if (obfd)
278 obfd->archive_head = 0;
281 void
282 ar_delete (struct list *list)
284 if (!obfd)
286 fprintf (stderr, _("%s: no open output archive\n"), program_name);
287 maybequit ();
289 else
291 while (list)
293 /* Find this name in the archive. */
294 bfd *member = obfd->archive_head;
295 bfd **prev = &(obfd->archive_head);
296 int found = 0;
298 while (member)
300 if (FILENAME_CMP(member->filename, list->name) == 0)
302 *prev = member->next;
303 found = 1;
305 else
306 prev = &(member->next);
308 member = member->next;
311 if (!found)
313 fprintf (stderr, _("%s: can't find module file %s\n"),
314 program_name, list->name);
315 maybequit ();
318 list = list->next;
323 void
324 ar_save (void)
326 if (!obfd)
328 fprintf (stderr, _("%s: no open output archive\n"), program_name);
329 maybequit ();
331 else
333 char *ofilename = xstrdup (bfd_get_filename (obfd));
335 bfd_close (obfd);
337 smart_rename (ofilename, real_name, 0);
338 obfd = 0;
339 free (ofilename);
343 void
344 ar_replace (struct list *list)
346 if (!obfd)
348 fprintf (stderr, _("%s: no open output archive\n"), program_name);
349 maybequit ();
351 else
353 while (list)
355 /* Find this name in the archive. */
356 bfd *member = obfd->archive_head;
357 bfd **prev = &(obfd->archive_head);
358 int found = 0;
360 while (member)
362 if (FILENAME_CMP (member->filename, list->name) == 0)
364 /* Found the one to replace. */
365 bfd *abfd = bfd_openr (list->name, 0);
367 if (!abfd)
369 fprintf (stderr, _("%s: can't open file %s\n"),
370 program_name, list->name);
371 maybequit ();
373 else
375 *prev = abfd;
376 abfd->next = member->next;
377 found = 1;
380 else
382 prev = &(member->next);
384 member = member->next;
387 if (!found)
389 bfd *abfd = bfd_openr (list->name, 0);
391 fprintf (stderr,_("%s: can't find module file %s\n"),
392 program_name, list->name);
393 if (!abfd)
395 fprintf (stderr, _("%s: can't open file %s\n"),
396 program_name, list->name);
397 maybequit ();
399 else
400 *prev = abfd;
403 list = list->next;
408 /* And I added this one. */
409 void
410 ar_list (void)
412 if (!obfd)
414 fprintf (stderr, _("%s: no open output archive\n"), program_name);
415 maybequit ();
417 else
419 bfd *abfd;
421 outfile = stdout;
422 verbose =1 ;
423 printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
425 for (abfd = obfd->archive_head;
426 abfd != (bfd *)NULL;
427 abfd = abfd->next)
428 ar_directory_doer (abfd, (bfd *) NULL);
432 void
433 ar_end (void)
435 if (obfd)
437 bfd_cache_close (obfd);
438 unlink (bfd_get_filename (obfd));
442 void
443 ar_extract (struct list *list)
445 if (!obfd)
447 fprintf (stderr, _("%s: no open archive\n"), program_name);
448 maybequit ();
450 else
452 while (list)
454 /* Find this name in the archive. */
455 bfd *member = obfd->archive_head;
456 int found = 0;
458 while (member && !found)
460 if (FILENAME_CMP (member->filename, list->name) == 0)
462 extract_file (member);
463 found = 1;
466 member = member->next;
469 if (!found)
471 bfd_openr (list->name, 0);
472 fprintf (stderr, _("%s: can't find module file %s\n"),
473 program_name, list->name);
476 list = list->next;