12159047fSniklas /* arsup.c - Archive support for MRI compatibility
2*007c2a45Smiod Copyright 1992, 1994, 1995, 1996, 1997, 2000, 2002, 2003, 2004
3b305b0f1Sespie Free Software Foundation, Inc.
42159047fSniklas
52159047fSniklas This file is part of GNU Binutils.
62159047fSniklas
72159047fSniklas This program is free software; you can redistribute it and/or modify
82159047fSniklas it under the terms of the GNU General Public License as published by
92159047fSniklas the Free Software Foundation; either version 2 of the License, or
102159047fSniklas (at your option) any later version.
112159047fSniklas
122159047fSniklas This program is distributed in the hope that it will be useful,
132159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
142159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152159047fSniklas GNU General Public License for more details.
162159047fSniklas
172159047fSniklas You should have received a copy of the GNU General Public License
182159047fSniklas along with this program; if not, write to the Free Software
192159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
202159047fSniklas
212159047fSniklas
222159047fSniklas /* Contributed by Steve Chamberlain
232159047fSniklas sac@cygnus.com
242159047fSniklas
252159047fSniklas This file looks after requests from arparse.y, to provide the MRI
26c074d1c9Sdrahn style librarian command syntax + 1 word LIST. */
272159047fSniklas
282159047fSniklas #include "bfd.h"
292159047fSniklas #include "arsup.h"
302159047fSniklas #include "libiberty.h"
312159047fSniklas #include "bucomm.h"
32b305b0f1Sespie #include "filenames.h"
332159047fSniklas
342159047fSniklas static void map_over_list
35*007c2a45Smiod (bfd *, void (*function) (bfd *, bfd *), struct list *);
36*007c2a45Smiod static void ar_directory_doer (bfd *, bfd *);
37*007c2a45Smiod static void ar_addlib_doer (bfd *, bfd *);
382159047fSniklas
392159047fSniklas extern int verbose;
402159047fSniklas
412159047fSniklas static void
map_over_list(bfd * arch,void (* function)(bfd *,bfd *),struct list * list)42*007c2a45Smiod map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list)
432159047fSniklas {
442159047fSniklas bfd *head;
452159047fSniklas
46c88b1d6cSniklas if (list == NULL)
47c88b1d6cSniklas {
48c88b1d6cSniklas bfd *next;
492159047fSniklas
50c88b1d6cSniklas head = arch->next;
51c88b1d6cSniklas while (head != NULL)
52c88b1d6cSniklas {
53c88b1d6cSniklas next = head->next;
54c88b1d6cSniklas function (head, (bfd *) NULL);
55c88b1d6cSniklas head = next;
56c88b1d6cSniklas }
57c88b1d6cSniklas }
58c88b1d6cSniklas else
59c88b1d6cSniklas {
60c88b1d6cSniklas struct list *ptr;
61c88b1d6cSniklas
62c88b1d6cSniklas /* This may appear to be a baroque way of accomplishing what we
63c88b1d6cSniklas want. however we have to iterate over the filenames in order
64c88b1d6cSniklas to notice where a filename is requested but does not exist in
65c88b1d6cSniklas the archive. Ditto mapping over each file each time -- we
66c88b1d6cSniklas want to hack multiple references. */
672159047fSniklas for (ptr = list; ptr; ptr = ptr->next)
682159047fSniklas {
69c074d1c9Sdrahn bfd_boolean found = FALSE;
702159047fSniklas bfd *prev = arch;
71c88b1d6cSniklas
722159047fSniklas for (head = arch->next; head; head = head->next)
732159047fSniklas {
74c88b1d6cSniklas if (head->filename != NULL
75b305b0f1Sespie && FILENAME_CMP (ptr->name, head->filename) == 0)
762159047fSniklas {
77c074d1c9Sdrahn found = TRUE;
782159047fSniklas function (head, prev);
792159047fSniklas }
802159047fSniklas prev = head;
812159047fSniklas }
822159047fSniklas if (! found)
83b305b0f1Sespie fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
842159047fSniklas }
852159047fSniklas }
862159047fSniklas }
872159047fSniklas
882159047fSniklas
892159047fSniklas FILE *outfile;
902159047fSniklas
912159047fSniklas static void
ar_directory_doer(bfd * abfd,bfd * ignore ATTRIBUTE_UNUSED)92*007c2a45Smiod ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
932159047fSniklas {
942159047fSniklas print_arelt_descr(outfile, abfd, verbose);
952159047fSniklas }
962159047fSniklas
972159047fSniklas void
ar_directory(char * ar_name,struct list * list,char * output)98*007c2a45Smiod ar_directory (char *ar_name, struct list *list, char *output)
992159047fSniklas {
1002159047fSniklas bfd *arch;
1012159047fSniklas
1020c6d0228Sniklas arch = open_inarch (ar_name, (char *) NULL);
1032159047fSniklas if (output)
1042159047fSniklas {
1052159047fSniklas outfile = fopen(output,"w");
1062159047fSniklas if (outfile == 0)
1072159047fSniklas {
1082159047fSniklas outfile = stdout;
109b305b0f1Sespie fprintf (stderr,_("Can't open file %s\n"), output);
1102159047fSniklas output = 0;
1112159047fSniklas }
1122159047fSniklas }
1132159047fSniklas else
1142159047fSniklas outfile = stdout;
1152159047fSniklas
1162159047fSniklas map_over_list (arch, ar_directory_doer, list);
1172159047fSniklas
1182159047fSniklas bfd_close (arch);
1192159047fSniklas
1202159047fSniklas if (output)
1212159047fSniklas fclose (outfile);
1222159047fSniklas }
1232159047fSniklas
1242159047fSniklas void
prompt(void)125*007c2a45Smiod prompt (void)
1262159047fSniklas {
1272159047fSniklas extern int interactive;
128c074d1c9Sdrahn
1292159047fSniklas if (interactive)
1302159047fSniklas {
1312159047fSniklas printf ("AR >");
1322159047fSniklas fflush (stdout);
1332159047fSniklas }
1342159047fSniklas }
1352159047fSniklas
1362159047fSniklas void
maybequit(void)137*007c2a45Smiod maybequit (void)
1382159047fSniklas {
1392159047fSniklas if (! interactive)
1402159047fSniklas xexit (9);
1412159047fSniklas }
1422159047fSniklas
1432159047fSniklas
1442159047fSniklas bfd *obfd;
1452159047fSniklas char *real_name;
1462159047fSniklas
147c074d1c9Sdrahn void
ar_open(char * name,int t)148*007c2a45Smiod ar_open (char *name, int t)
1492159047fSniklas {
150b305b0f1Sespie char *tname = (char *) xmalloc (strlen (name) + 10);
151c074d1c9Sdrahn const char *bname = lbasename (name);
1522159047fSniklas real_name = name;
153c074d1c9Sdrahn
154b305b0f1Sespie /* Prepend tmp- to the beginning, to avoid file-name clashes after
155b305b0f1Sespie truncation on filesystems with limited namespaces (DOS). */
156c074d1c9Sdrahn sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname);
1572159047fSniklas obfd = bfd_openw (tname, NULL);
1582159047fSniklas
159c074d1c9Sdrahn if (!obfd)
160c074d1c9Sdrahn {
161c074d1c9Sdrahn fprintf (stderr,
162c074d1c9Sdrahn _("%s: Can't open output archive %s\n"),
163c074d1c9Sdrahn program_name, tname);
1642159047fSniklas
1652159047fSniklas maybequit ();
1662159047fSniklas }
167c074d1c9Sdrahn else
168c074d1c9Sdrahn {
169c074d1c9Sdrahn if (!t)
170c074d1c9Sdrahn {
1712159047fSniklas bfd **ptr;
1722159047fSniklas bfd *element;
1732159047fSniklas bfd *ibfd;
174c074d1c9Sdrahn
1752159047fSniklas ibfd = bfd_openr (name, NULL);
176c074d1c9Sdrahn
177c074d1c9Sdrahn if (!ibfd)
178c074d1c9Sdrahn {
179b305b0f1Sespie fprintf (stderr,_("%s: Can't open input archive %s\n"),
1802159047fSniklas program_name, name);
1812159047fSniklas maybequit ();
1822159047fSniklas return;
1832159047fSniklas }
184c074d1c9Sdrahn
185c074d1c9Sdrahn if (!bfd_check_format(ibfd, bfd_archive))
186c074d1c9Sdrahn {
187c074d1c9Sdrahn fprintf (stderr,
188c074d1c9Sdrahn _("%s: file %s is not an archive\n"),
189c074d1c9Sdrahn program_name, name);
1902159047fSniklas maybequit ();
1912159047fSniklas return;
1922159047fSniklas }
193c074d1c9Sdrahn
1942159047fSniklas ptr = &(obfd->archive_head);
1952159047fSniklas element = bfd_openr_next_archived_file (ibfd, NULL);
1962159047fSniklas
197c074d1c9Sdrahn while (element)
198c074d1c9Sdrahn {
1992159047fSniklas *ptr = element;
2002159047fSniklas ptr = &element->next;
2012159047fSniklas element = bfd_openr_next_archived_file (ibfd, element);
2022159047fSniklas }
2032159047fSniklas }
2042159047fSniklas
2052159047fSniklas bfd_set_format (obfd, bfd_archive);
2062159047fSniklas
2072159047fSniklas obfd->has_armap = 1;
2082159047fSniklas }
2092159047fSniklas }
2102159047fSniklas
2112159047fSniklas static void
ar_addlib_doer(bfd * abfd,bfd * prev)212*007c2a45Smiod ar_addlib_doer (bfd *abfd, bfd *prev)
2132159047fSniklas {
214c074d1c9Sdrahn /* Add this module to the output bfd. */
215c88b1d6cSniklas if (prev != NULL)
2162159047fSniklas prev->next = abfd->next;
217c074d1c9Sdrahn
2182159047fSniklas abfd->next = obfd->archive_head;
2192159047fSniklas obfd->archive_head = abfd;
2202159047fSniklas }
2212159047fSniklas
2222159047fSniklas void
ar_addlib(char * name,struct list * list)223*007c2a45Smiod ar_addlib (char *name, struct list *list)
2242159047fSniklas {
2252159047fSniklas if (obfd == NULL)
2262159047fSniklas {
227b305b0f1Sespie fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
2282159047fSniklas maybequit ();
2292159047fSniklas }
2302159047fSniklas else
2312159047fSniklas {
2322159047fSniklas bfd *arch;
2332159047fSniklas
2340c6d0228Sniklas arch = open_inarch (name, (char *) NULL);
2352159047fSniklas if (arch != NULL)
2362159047fSniklas map_over_list (arch, ar_addlib_doer, list);
2372159047fSniklas
238*007c2a45Smiod /* Don't close the bfd, since it will make the elements disappear. */
2392159047fSniklas }
2402159047fSniklas }
2412159047fSniklas
2422159047fSniklas void
ar_addmod(struct list * list)243*007c2a45Smiod ar_addmod (struct list *list)
2442159047fSniklas {
245c074d1c9Sdrahn if (!obfd)
246c074d1c9Sdrahn {
247b305b0f1Sespie fprintf (stderr, _("%s: no open output archive\n"), program_name);
2482159047fSniklas maybequit ();
2492159047fSniklas }
2502159047fSniklas else
2512159047fSniklas {
252c074d1c9Sdrahn while (list)
253c074d1c9Sdrahn {
2542159047fSniklas bfd *abfd = bfd_openr (list->name, NULL);
255c074d1c9Sdrahn
256c074d1c9Sdrahn if (!abfd)
257c074d1c9Sdrahn {
258c074d1c9Sdrahn fprintf (stderr, _("%s: can't open file %s\n"),
259c074d1c9Sdrahn program_name, list->name);
2602159047fSniklas maybequit ();
2612159047fSniklas }
262c074d1c9Sdrahn else
263c074d1c9Sdrahn {
2642159047fSniklas abfd->next = obfd->archive_head;
2652159047fSniklas obfd->archive_head = abfd;
2662159047fSniklas }
2672159047fSniklas list = list->next;
2682159047fSniklas }
2692159047fSniklas }
2702159047fSniklas }
2712159047fSniklas
2722159047fSniklas
2732159047fSniklas void
ar_clear(void)274*007c2a45Smiod ar_clear (void)
2752159047fSniklas {
2762159047fSniklas if (obfd)
2772159047fSniklas obfd->archive_head = 0;
2782159047fSniklas }
2792159047fSniklas
2802159047fSniklas void
ar_delete(struct list * list)281*007c2a45Smiod ar_delete (struct list *list)
2822159047fSniklas {
283c074d1c9Sdrahn if (!obfd)
284c074d1c9Sdrahn {
285b305b0f1Sespie fprintf (stderr, _("%s: no open output archive\n"), program_name);
2862159047fSniklas maybequit ();
2872159047fSniklas }
2882159047fSniklas else
2892159047fSniklas {
290c074d1c9Sdrahn while (list)
291c074d1c9Sdrahn {
292c074d1c9Sdrahn /* Find this name in the archive. */
2932159047fSniklas bfd *member = obfd->archive_head;
2942159047fSniklas bfd **prev = &(obfd->archive_head);
2952159047fSniklas int found = 0;
296c074d1c9Sdrahn
297c074d1c9Sdrahn while (member)
298c074d1c9Sdrahn {
299c074d1c9Sdrahn if (FILENAME_CMP(member->filename, list->name) == 0)
300c074d1c9Sdrahn {
3012159047fSniklas *prev = member->next;
3022159047fSniklas found = 1;
3032159047fSniklas }
304c074d1c9Sdrahn else
3052159047fSniklas prev = &(member->next);
306c074d1c9Sdrahn
3072159047fSniklas member = member->next;
3082159047fSniklas }
309c074d1c9Sdrahn
310c074d1c9Sdrahn if (!found)
311c074d1c9Sdrahn {
312c074d1c9Sdrahn fprintf (stderr, _("%s: can't find module file %s\n"),
313c074d1c9Sdrahn program_name, list->name);
3142159047fSniklas maybequit ();
3152159047fSniklas }
316c074d1c9Sdrahn
3172159047fSniklas list = list->next;
3182159047fSniklas }
3192159047fSniklas }
3202159047fSniklas }
3212159047fSniklas
3222159047fSniklas void
ar_save(void)323*007c2a45Smiod ar_save (void)
3242159047fSniklas {
325c074d1c9Sdrahn if (!obfd)
326c074d1c9Sdrahn {
327b305b0f1Sespie fprintf (stderr, _("%s: no open output archive\n"), program_name);
3282159047fSniklas maybequit ();
3292159047fSniklas }
330c074d1c9Sdrahn else
331c074d1c9Sdrahn {
332b305b0f1Sespie char *ofilename = xstrdup (bfd_get_filename (obfd));
333c074d1c9Sdrahn
3342159047fSniklas bfd_close (obfd);
3352159047fSniklas
336*007c2a45Smiod smart_rename (ofilename, real_name, 0);
3372159047fSniklas obfd = 0;
3382159047fSniklas free (ofilename);
3392159047fSniklas }
3402159047fSniklas }
3412159047fSniklas
3422159047fSniklas void
ar_replace(struct list * list)343*007c2a45Smiod ar_replace (struct list *list)
3442159047fSniklas {
345c074d1c9Sdrahn if (!obfd)
346c074d1c9Sdrahn {
347b305b0f1Sespie fprintf (stderr, _("%s: no open output archive\n"), program_name);
3482159047fSniklas maybequit ();
3492159047fSniklas }
3502159047fSniklas else
3512159047fSniklas {
352c074d1c9Sdrahn while (list)
353c074d1c9Sdrahn {
354c074d1c9Sdrahn /* Find this name in the archive. */
3552159047fSniklas bfd *member = obfd->archive_head;
3562159047fSniklas bfd **prev = &(obfd->archive_head);
3572159047fSniklas int found = 0;
358c074d1c9Sdrahn
3592159047fSniklas while (member)
3602159047fSniklas {
361b305b0f1Sespie if (FILENAME_CMP (member->filename, list->name) == 0)
3622159047fSniklas {
363c074d1c9Sdrahn /* Found the one to replace. */
3642159047fSniklas bfd *abfd = bfd_openr (list->name, 0);
365c074d1c9Sdrahn
3662159047fSniklas if (!abfd)
3672159047fSniklas {
368c074d1c9Sdrahn fprintf (stderr, _("%s: can't open file %s\n"),
369c074d1c9Sdrahn program_name, list->name);
3702159047fSniklas maybequit ();
3712159047fSniklas }
3722159047fSniklas else
3732159047fSniklas {
3742159047fSniklas *prev = abfd;
375c074d1c9Sdrahn abfd->next = member->next;
376c074d1c9Sdrahn found = 1;
3772159047fSniklas }
3782159047fSniklas }
379c074d1c9Sdrahn else
380c074d1c9Sdrahn {
381c074d1c9Sdrahn prev = &(member->next);
382c074d1c9Sdrahn }
383c074d1c9Sdrahn member = member->next;
384c074d1c9Sdrahn }
385c074d1c9Sdrahn
386c074d1c9Sdrahn if (!found)
387c074d1c9Sdrahn {
388c074d1c9Sdrahn bfd *abfd = bfd_openr (list->name, 0);
389c074d1c9Sdrahn
390c074d1c9Sdrahn fprintf (stderr,_("%s: can't find module file %s\n"),
391c074d1c9Sdrahn program_name, list->name);
392c074d1c9Sdrahn if (!abfd)
393c074d1c9Sdrahn {
394c074d1c9Sdrahn fprintf (stderr, _("%s: can't open file %s\n"),
395c074d1c9Sdrahn program_name, list->name);
396c074d1c9Sdrahn maybequit ();
397c074d1c9Sdrahn }
398c074d1c9Sdrahn else
399c074d1c9Sdrahn *prev = abfd;
400c074d1c9Sdrahn }
4012159047fSniklas
4022159047fSniklas list = list->next;
4032159047fSniklas }
4042159047fSniklas }
4052159047fSniklas }
4062159047fSniklas
407c074d1c9Sdrahn /* And I added this one. */
4082159047fSniklas void
ar_list(void)409*007c2a45Smiod ar_list (void)
4102159047fSniklas {
4112159047fSniklas if (!obfd)
4122159047fSniklas {
413b305b0f1Sespie fprintf (stderr, _("%s: no open output archive\n"), program_name);
4142159047fSniklas maybequit ();
4152159047fSniklas }
416c074d1c9Sdrahn else
417c074d1c9Sdrahn {
4182159047fSniklas bfd *abfd;
419c074d1c9Sdrahn
4202159047fSniklas outfile = stdout;
4212159047fSniklas verbose =1 ;
422b305b0f1Sespie printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
423c074d1c9Sdrahn
4242159047fSniklas for (abfd = obfd->archive_head;
4252159047fSniklas abfd != (bfd *)NULL;
4262159047fSniklas abfd = abfd->next)
4272159047fSniklas ar_directory_doer (abfd, (bfd *) NULL);
4282159047fSniklas }
4292159047fSniklas }
4302159047fSniklas
4312159047fSniklas void
ar_end(void)432*007c2a45Smiod ar_end (void)
4332159047fSniklas {
4342159047fSniklas if (obfd)
4352159047fSniklas {
436*007c2a45Smiod bfd_cache_close (obfd);
4372159047fSniklas unlink (bfd_get_filename (obfd));
4382159047fSniklas }
4392159047fSniklas }
440c074d1c9Sdrahn
4412159047fSniklas void
ar_extract(struct list * list)442*007c2a45Smiod ar_extract (struct list *list)
4432159047fSniklas {
4442159047fSniklas if (!obfd)
4452159047fSniklas {
446b305b0f1Sespie fprintf (stderr, _("%s: no open archive\n"), program_name);
4472159047fSniklas maybequit ();
4482159047fSniklas }
4492159047fSniklas else
4502159047fSniklas {
451c074d1c9Sdrahn while (list)
452c074d1c9Sdrahn {
453c074d1c9Sdrahn /* Find this name in the archive. */
4542159047fSniklas bfd *member = obfd->archive_head;
4552159047fSniklas int found = 0;
456c074d1c9Sdrahn
4572159047fSniklas while (member && !found)
4582159047fSniklas {
459b305b0f1Sespie if (FILENAME_CMP (member->filename, list->name) == 0)
4602159047fSniklas {
4612159047fSniklas extract_file (member);
4622159047fSniklas found = 1;
4632159047fSniklas }
4642159047fSniklas
4652159047fSniklas member = member->next;
4662159047fSniklas }
4672159047fSniklas
468c074d1c9Sdrahn if (!found)
469c074d1c9Sdrahn {
470c074d1c9Sdrahn bfd_openr (list->name, 0);
471c074d1c9Sdrahn fprintf (stderr, _("%s: can't find module file %s\n"),
472c074d1c9Sdrahn program_name, list->name);
4732159047fSniklas }
474c074d1c9Sdrahn
4752159047fSniklas list = list->next;
4762159047fSniklas }
4772159047fSniklas }
4782159047fSniklas }
479