xref: /openbsd/gnu/usr.bin/binutils/binutils/arsup.c (revision 007c2a45)
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