133965Sjdp/* arsup.c - Archive support for MRI compatibility 2218822Sdim Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 3218822Sdim 2004, 2007 Free Software Foundation, Inc. 433965Sjdp 5104834Sobrien This file is part of GNU Binutils. 633965Sjdp 7104834Sobrien This program is free software; you can redistribute it and/or modify 8104834Sobrien it under the terms of the GNU General Public License as published by 9104834Sobrien the Free Software Foundation; either version 2 of the License, or 10104834Sobrien (at your option) any later version. 1133965Sjdp 12104834Sobrien This program is distributed in the hope that it will be useful, 13104834Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 14104834Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15104834Sobrien GNU General Public License for more details. 1633965Sjdp 17104834Sobrien You should have received a copy of the GNU General Public License 18104834Sobrien along with this program; if not, write to the Free Software 19218822Sdim Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2033965Sjdp 2133965Sjdp 2233965Sjdp/* Contributed by Steve Chamberlain 23104834Sobrien sac@cygnus.com 2433965Sjdp 25104834Sobrien This file looks after requests from arparse.y, to provide the MRI 26104834Sobrien style librarian command syntax + 1 word LIST. */ 2733965Sjdp 28218822Sdim#include "sysdep.h" 2933965Sjdp#include "bfd.h" 3033965Sjdp#include "libiberty.h" 31218822Sdim#include "filenames.h" 3233965Sjdp#include "bucomm.h" 33218822Sdim#include "arsup.h" 3433965Sjdp 3533965Sjdpstatic void map_over_list 36130561Sobrien (bfd *, void (*function) (bfd *, bfd *), struct list *); 37130561Sobrienstatic void ar_directory_doer (bfd *, bfd *); 38130561Sobrienstatic void ar_addlib_doer (bfd *, bfd *); 3933965Sjdp 4033965Sjdpextern int verbose; 4133965Sjdp 42218822Sdimstatic bfd *obfd; 43218822Sdimstatic char *real_name; 44218822Sdimstatic FILE *outfile; 45218822Sdim 4633965Sjdpstatic void 47130561Sobrienmap_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list) 4833965Sjdp{ 4933965Sjdp bfd *head; 5033965Sjdp 5133965Sjdp if (list == NULL) 5233965Sjdp { 5333965Sjdp bfd *next; 5433965Sjdp 55218822Sdim head = arch->archive_next; 5633965Sjdp while (head != NULL) 5733965Sjdp { 58218822Sdim next = head->archive_next; 5933965Sjdp function (head, (bfd *) NULL); 6033965Sjdp head = next; 6133965Sjdp } 6233965Sjdp } 6333965Sjdp else 6433965Sjdp { 6533965Sjdp struct list *ptr; 6633965Sjdp 6733965Sjdp /* This may appear to be a baroque way of accomplishing what we 6833965Sjdp want. however we have to iterate over the filenames in order 6933965Sjdp to notice where a filename is requested but does not exist in 7033965Sjdp the archive. Ditto mapping over each file each time -- we 7133965Sjdp want to hack multiple references. */ 7233965Sjdp for (ptr = list; ptr; ptr = ptr->next) 7333965Sjdp { 74130561Sobrien bfd_boolean found = FALSE; 7533965Sjdp bfd *prev = arch; 7633965Sjdp 77218822Sdim for (head = arch->archive_next; head; head = head->archive_next) 7833965Sjdp { 7933965Sjdp if (head->filename != NULL 8061843Sobrien && FILENAME_CMP (ptr->name, head->filename) == 0) 8133965Sjdp { 82130561Sobrien found = TRUE; 8333965Sjdp function (head, prev); 8433965Sjdp } 8533965Sjdp prev = head; 8633965Sjdp } 8733965Sjdp if (! found) 8860484Sobrien fprintf (stderr, _("No entry %s in archive.\n"), ptr->name); 8933965Sjdp } 9033965Sjdp } 9133965Sjdp} 9233965Sjdp 9333965Sjdp 9433965Sjdp 9533965Sjdpstatic void 96130561Sobrienar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED) 9733965Sjdp{ 98104834Sobrien print_arelt_descr(outfile, abfd, verbose); 9933965Sjdp} 10033965Sjdp 10133965Sjdpvoid 102130561Sobrienar_directory (char *ar_name, struct list *list, char *output) 10333965Sjdp{ 10433965Sjdp bfd *arch; 10533965Sjdp 10633965Sjdp arch = open_inarch (ar_name, (char *) NULL); 10733965Sjdp if (output) 10833965Sjdp { 10933965Sjdp outfile = fopen(output,"w"); 11033965Sjdp if (outfile == 0) 11133965Sjdp { 11233965Sjdp outfile = stdout; 11360484Sobrien fprintf (stderr,_("Can't open file %s\n"), output); 11433965Sjdp output = 0; 11533965Sjdp } 11633965Sjdp } 117104834Sobrien else 11833965Sjdp outfile = stdout; 11933965Sjdp 12033965Sjdp map_over_list (arch, ar_directory_doer, list); 12133965Sjdp 12233965Sjdp bfd_close (arch); 12333965Sjdp 12433965Sjdp if (output) 12533965Sjdp fclose (outfile); 12633965Sjdp} 12733965Sjdp 12833965Sjdpvoid 129130561Sobrienprompt (void) 13033965Sjdp{ 13133965Sjdp extern int interactive; 132104834Sobrien 133104834Sobrien if (interactive) 134104834Sobrien { 135104834Sobrien printf ("AR >"); 136104834Sobrien fflush (stdout); 137104834Sobrien } 13833965Sjdp} 13933965Sjdp 14033965Sjdpvoid 141130561Sobrienmaybequit (void) 14233965Sjdp{ 143104834Sobrien if (! interactive) 14433965Sjdp xexit (9); 14533965Sjdp} 14633965Sjdp 14733965Sjdp 14833965Sjdpvoid 149130561Sobrienar_open (char *name, int t) 15033965Sjdp{ 15133965Sjdp char *tname = (char *) xmalloc (strlen (name) + 10); 15289857Sobrien const char *bname = lbasename (name); 15333965Sjdp real_name = name; 154104834Sobrien 15561843Sobrien /* Prepend tmp- to the beginning, to avoid file-name clashes after 15661843Sobrien truncation on filesystems with limited namespaces (DOS). */ 157104834Sobrien sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname); 158104834Sobrien obfd = bfd_openw (tname, NULL); 15933965Sjdp 160104834Sobrien if (!obfd) 161104834Sobrien { 162104834Sobrien fprintf (stderr, 163104834Sobrien _("%s: Can't open output archive %s\n"), 164104834Sobrien program_name, tname); 16533965Sjdp 166104834Sobrien maybequit (); 16733965Sjdp } 168104834Sobrien else 169104834Sobrien { 170104834Sobrien if (!t) 171104834Sobrien { 172104834Sobrien bfd **ptr; 173104834Sobrien bfd *element; 174104834Sobrien bfd *ibfd; 17533965Sjdp 176104834Sobrien ibfd = bfd_openr (name, NULL); 17733965Sjdp 178104834Sobrien if (!ibfd) 179104834Sobrien { 180104834Sobrien fprintf (stderr,_("%s: Can't open input archive %s\n"), 181104834Sobrien program_name, name); 182104834Sobrien maybequit (); 183104834Sobrien return; 184104834Sobrien } 185104834Sobrien 186130561Sobrien if (!bfd_check_format(ibfd, bfd_archive)) 187104834Sobrien { 188104834Sobrien fprintf (stderr, 189104834Sobrien _("%s: file %s is not an archive\n"), 190104834Sobrien program_name, name); 191104834Sobrien maybequit (); 192104834Sobrien return; 193104834Sobrien } 194104834Sobrien 195104834Sobrien ptr = &(obfd->archive_head); 196104834Sobrien element = bfd_openr_next_archived_file (ibfd, NULL); 197104834Sobrien 198104834Sobrien while (element) 199104834Sobrien { 200104834Sobrien *ptr = element; 201218822Sdim ptr = &element->archive_next; 202104834Sobrien element = bfd_openr_next_archived_file (ibfd, element); 203104834Sobrien } 204104834Sobrien } 205104834Sobrien 206104834Sobrien bfd_set_format (obfd, bfd_archive); 207104834Sobrien 208104834Sobrien obfd->has_armap = 1; 209104834Sobrien } 21033965Sjdp} 21133965Sjdp 21233965Sjdpstatic void 213130561Sobrienar_addlib_doer (bfd *abfd, bfd *prev) 21433965Sjdp{ 215104834Sobrien /* Add this module to the output bfd. */ 21633965Sjdp if (prev != NULL) 217218822Sdim prev->archive_next = abfd->archive_next; 218104834Sobrien 219218822Sdim abfd->archive_next = obfd->archive_head; 22033965Sjdp obfd->archive_head = abfd; 22133965Sjdp} 22233965Sjdp 22333965Sjdpvoid 224130561Sobrienar_addlib (char *name, struct list *list) 22533965Sjdp{ 22633965Sjdp if (obfd == NULL) 22733965Sjdp { 22860484Sobrien fprintf (stderr, _("%s: no output archive specified yet\n"), program_name); 22933965Sjdp maybequit (); 23033965Sjdp } 23133965Sjdp else 23233965Sjdp { 23333965Sjdp bfd *arch; 23433965Sjdp 23533965Sjdp arch = open_inarch (name, (char *) NULL); 23633965Sjdp if (arch != NULL) 23733965Sjdp map_over_list (arch, ar_addlib_doer, list); 23833965Sjdp 239130561Sobrien /* Don't close the bfd, since it will make the elements disappear. */ 24033965Sjdp } 24133965Sjdp} 24233965Sjdp 24333965Sjdpvoid 244130561Sobrienar_addmod (struct list *list) 24533965Sjdp{ 246104834Sobrien if (!obfd) 247104834Sobrien { 248104834Sobrien fprintf (stderr, _("%s: no open output archive\n"), program_name); 249104834Sobrien maybequit (); 25033965Sjdp } 251104834Sobrien else 252104834Sobrien { 253104834Sobrien while (list) 254104834Sobrien { 255104834Sobrien bfd *abfd = bfd_openr (list->name, NULL); 256104834Sobrien 257104834Sobrien if (!abfd) 258104834Sobrien { 259104834Sobrien fprintf (stderr, _("%s: can't open file %s\n"), 260104834Sobrien program_name, list->name); 261104834Sobrien maybequit (); 262104834Sobrien } 263104834Sobrien else 264104834Sobrien { 265218822Sdim abfd->archive_next = obfd->archive_head; 266104834Sobrien obfd->archive_head = abfd; 267104834Sobrien } 268104834Sobrien list = list->next; 269104834Sobrien } 270104834Sobrien } 27133965Sjdp} 27233965Sjdp 27333965Sjdp 27433965Sjdpvoid 275130561Sobrienar_clear (void) 27633965Sjdp{ 277104834Sobrien if (obfd) 278104834Sobrien obfd->archive_head = 0; 27933965Sjdp} 28033965Sjdp 28133965Sjdpvoid 282130561Sobrienar_delete (struct list *list) 28333965Sjdp{ 284104834Sobrien if (!obfd) 285104834Sobrien { 286104834Sobrien fprintf (stderr, _("%s: no open output archive\n"), program_name); 287104834Sobrien maybequit (); 288104834Sobrien } 289104834Sobrien else 290104834Sobrien { 291104834Sobrien while (list) 292104834Sobrien { 293104834Sobrien /* Find this name in the archive. */ 294104834Sobrien bfd *member = obfd->archive_head; 295104834Sobrien bfd **prev = &(obfd->archive_head); 296104834Sobrien int found = 0; 297104834Sobrien 298104834Sobrien while (member) 299104834Sobrien { 300104834Sobrien if (FILENAME_CMP(member->filename, list->name) == 0) 301104834Sobrien { 302218822Sdim *prev = member->archive_next; 303104834Sobrien found = 1; 304104834Sobrien } 305104834Sobrien else 306218822Sdim prev = &(member->archive_next); 307104834Sobrien 308218822Sdim member = member->archive_next; 309104834Sobrien } 310104834Sobrien 311104834Sobrien if (!found) 312104834Sobrien { 313104834Sobrien fprintf (stderr, _("%s: can't find module file %s\n"), 314104834Sobrien program_name, list->name); 315104834Sobrien maybequit (); 316104834Sobrien } 317104834Sobrien 318104834Sobrien list = list->next; 31933965Sjdp } 32033965Sjdp } 32133965Sjdp} 32233965Sjdp 32333965Sjdpvoid 324130561Sobrienar_save (void) 32533965Sjdp{ 326104834Sobrien if (!obfd) 327104834Sobrien { 328104834Sobrien fprintf (stderr, _("%s: no open output archive\n"), program_name); 329104834Sobrien maybequit (); 330104834Sobrien } 331104834Sobrien else 332104834Sobrien { 333104834Sobrien char *ofilename = xstrdup (bfd_get_filename (obfd)); 33433965Sjdp 335104834Sobrien bfd_close (obfd); 336104834Sobrien 337130561Sobrien smart_rename (ofilename, real_name, 0); 338104834Sobrien obfd = 0; 339104834Sobrien free (ofilename); 340104834Sobrien } 34133965Sjdp} 34233965Sjdp 34333965Sjdpvoid 344130561Sobrienar_replace (struct list *list) 34533965Sjdp{ 346104834Sobrien if (!obfd) 347104834Sobrien { 348104834Sobrien fprintf (stderr, _("%s: no open output archive\n"), program_name); 349104834Sobrien maybequit (); 350104834Sobrien } 351104834Sobrien else 352104834Sobrien { 353104834Sobrien while (list) 35433965Sjdp { 355104834Sobrien /* Find this name in the archive. */ 356104834Sobrien bfd *member = obfd->archive_head; 357104834Sobrien bfd **prev = &(obfd->archive_head); 358104834Sobrien int found = 0; 359104834Sobrien 360104834Sobrien while (member) 361104834Sobrien { 362104834Sobrien if (FILENAME_CMP (member->filename, list->name) == 0) 363104834Sobrien { 364104834Sobrien /* Found the one to replace. */ 365104834Sobrien bfd *abfd = bfd_openr (list->name, 0); 366104834Sobrien 367104834Sobrien if (!abfd) 368104834Sobrien { 369104834Sobrien fprintf (stderr, _("%s: can't open file %s\n"), 370104834Sobrien program_name, list->name); 371104834Sobrien maybequit (); 372104834Sobrien } 373104834Sobrien else 374104834Sobrien { 375104834Sobrien *prev = abfd; 376218822Sdim abfd->archive_next = member->archive_next; 377104834Sobrien found = 1; 378104834Sobrien } 379104834Sobrien } 380104834Sobrien else 381104834Sobrien { 382218822Sdim prev = &(member->archive_next); 383104834Sobrien } 384218822Sdim member = member->archive_next; 385104834Sobrien } 386104834Sobrien 387104834Sobrien if (!found) 388104834Sobrien { 389104834Sobrien bfd *abfd = bfd_openr (list->name, 0); 390104834Sobrien 391104834Sobrien fprintf (stderr,_("%s: can't find module file %s\n"), 392104834Sobrien program_name, list->name); 393104834Sobrien if (!abfd) 394104834Sobrien { 395104834Sobrien fprintf (stderr, _("%s: can't open file %s\n"), 396104834Sobrien program_name, list->name); 397104834Sobrien maybequit (); 398104834Sobrien } 399104834Sobrien else 400104834Sobrien *prev = abfd; 401104834Sobrien } 402104834Sobrien 403104834Sobrien list = list->next; 40433965Sjdp } 40533965Sjdp } 40633965Sjdp} 40733965Sjdp 408104834Sobrien/* And I added this one. */ 40933965Sjdpvoid 410130561Sobrienar_list (void) 41133965Sjdp{ 412104834Sobrien if (!obfd) 41333965Sjdp { 414104834Sobrien fprintf (stderr, _("%s: no open output archive\n"), program_name); 415104834Sobrien maybequit (); 41633965Sjdp } 417104834Sobrien else 418104834Sobrien { 419104834Sobrien bfd *abfd; 420104834Sobrien 421104834Sobrien outfile = stdout; 422104834Sobrien verbose =1 ; 423104834Sobrien printf (_("Current open archive is %s\n"), bfd_get_filename (obfd)); 424104834Sobrien 425104834Sobrien for (abfd = obfd->archive_head; 426104834Sobrien abfd != (bfd *)NULL; 427218822Sdim abfd = abfd->archive_next) 428104834Sobrien ar_directory_doer (abfd, (bfd *) NULL); 429104834Sobrien } 43033965Sjdp} 43133965Sjdp 432104834Sobrienvoid 433130561Sobrienar_end (void) 43433965Sjdp{ 43533965Sjdp if (obfd) 436104834Sobrien { 437130561Sobrien bfd_cache_close (obfd); 438104834Sobrien unlink (bfd_get_filename (obfd)); 439104834Sobrien } 44033965Sjdp} 441104834Sobrien 44233965Sjdpvoid 443130561Sobrienar_extract (struct list *list) 44433965Sjdp{ 445104834Sobrien if (!obfd) 446104834Sobrien { 447104834Sobrien fprintf (stderr, _("%s: no open archive\n"), program_name); 448104834Sobrien maybequit (); 449104834Sobrien } 450104834Sobrien else 451104834Sobrien { 452104834Sobrien while (list) 45333965Sjdp { 454104834Sobrien /* Find this name in the archive. */ 455104834Sobrien bfd *member = obfd->archive_head; 456104834Sobrien int found = 0; 45733965Sjdp 458104834Sobrien while (member && !found) 459104834Sobrien { 460104834Sobrien if (FILENAME_CMP (member->filename, list->name) == 0) 461104834Sobrien { 462104834Sobrien extract_file (member); 463104834Sobrien found = 1; 464104834Sobrien } 46533965Sjdp 466218822Sdim member = member->archive_next; 467104834Sobrien } 468104834Sobrien 469104834Sobrien if (!found) 470104834Sobrien { 471104834Sobrien bfd_openr (list->name, 0); 472104834Sobrien fprintf (stderr, _("%s: can't find module file %s\n"), 473104834Sobrien program_name, list->name); 474104834Sobrien } 475104834Sobrien 476104834Sobrien list = list->next; 477104834Sobrien } 47833965Sjdp } 47933965Sjdp} 480