Back to index

cell-binutils  2.17cvs20070401
arsup.c
Go to the documentation of this file.
00001 /* arsup.c - Archive support for MRI compatibility
00002    Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
00003    2004 Free Software Foundation, Inc.
00004 
00005    This file is part of GNU Binutils.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 
00022 /* Contributed by Steve Chamberlain
00023    sac@cygnus.com
00024 
00025    This file looks after requests from arparse.y, to provide the MRI
00026    style librarian command syntax + 1 word LIST.  */
00027 
00028 #include "bfd.h"
00029 #include "arsup.h"
00030 #include "libiberty.h"
00031 #include "bucomm.h"
00032 #include "filenames.h"
00033 
00034 static void map_over_list
00035   (bfd *, void (*function) (bfd *, bfd *), struct list *);
00036 static void ar_directory_doer (bfd *, bfd *);
00037 static void ar_addlib_doer (bfd *, bfd *);
00038 
00039 extern int verbose;
00040 
00041 static bfd *obfd;
00042 static char *real_name;
00043 static FILE *outfile;
00044 
00045 static void
00046 map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list)
00047 {
00048   bfd *head;
00049 
00050   if (list == NULL)
00051     {
00052       bfd *next;
00053 
00054       head = arch->next;
00055       while (head != NULL)
00056        {
00057          next = head->next;
00058          function (head, (bfd *) NULL);
00059          head = next;
00060        }
00061     }
00062   else
00063     {
00064       struct list *ptr;
00065 
00066       /* This may appear to be a baroque way of accomplishing what we
00067         want.  however we have to iterate over the filenames in order
00068         to notice where a filename is requested but does not exist in
00069         the archive.  Ditto mapping over each file each time -- we
00070         want to hack multiple references.  */
00071       for (ptr = list; ptr; ptr = ptr->next)
00072        {
00073          bfd_boolean found = FALSE;
00074          bfd *prev = arch;
00075 
00076          for (head = arch->next; head; head = head->next)
00077            {
00078              if (head->filename != NULL
00079                 && FILENAME_CMP (ptr->name, head->filename) == 0)
00080               {
00081                 found = TRUE;
00082                 function (head, prev);
00083               }
00084              prev = head;
00085            }
00086          if (! found)
00087            fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
00088        }
00089     }
00090 }
00091 
00092 
00093 
00094 static void
00095 ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
00096 {
00097   print_arelt_descr(outfile, abfd, verbose);
00098 }
00099 
00100 void
00101 ar_directory (char *ar_name, struct list *list, char *output)
00102 {
00103   bfd *arch;
00104 
00105   arch = open_inarch (ar_name, (char *) NULL);
00106   if (output)
00107     {
00108       outfile = fopen(output,"w");
00109       if (outfile == 0)
00110        {
00111          outfile = stdout;
00112          fprintf (stderr,_("Can't open file %s\n"), output);
00113          output = 0;
00114        }
00115     }
00116   else
00117     outfile = stdout;
00118 
00119   map_over_list (arch, ar_directory_doer, list);
00120 
00121   bfd_close (arch);
00122 
00123   if (output)
00124    fclose (outfile);
00125 }
00126 
00127 void
00128 prompt (void)
00129 {
00130   extern int interactive;
00131 
00132   if (interactive)
00133     {
00134       printf ("AR >");
00135       fflush (stdout);
00136     }
00137 }
00138 
00139 void
00140 maybequit (void)
00141 {
00142   if (! interactive)
00143     xexit (9);
00144 }
00145 
00146 
00147 void
00148 ar_open (char *name, int t)
00149 {
00150   char *tname = (char *) xmalloc (strlen (name) + 10);
00151   const char *bname = lbasename (name);
00152   real_name = name;
00153 
00154   /* Prepend tmp- to the beginning, to avoid file-name clashes after
00155      truncation on filesystems with limited namespaces (DOS).  */
00156   sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname);
00157   obfd = bfd_openw (tname, NULL);
00158 
00159   if (!obfd)
00160     {
00161       fprintf (stderr,
00162               _("%s: Can't open output archive %s\n"),
00163               program_name,  tname);
00164 
00165       maybequit ();
00166     }
00167   else
00168     {
00169       if (!t)
00170        {
00171          bfd **ptr;
00172          bfd *element;
00173          bfd *ibfd;
00174 
00175          ibfd = bfd_openr (name, NULL);
00176 
00177          if (!ibfd)
00178            {
00179              fprintf (stderr,_("%s: Can't open input archive %s\n"),
00180                      program_name, name);
00181              maybequit ();
00182              return;
00183            }
00184 
00185          if (!bfd_check_format(ibfd, bfd_archive))
00186            {
00187              fprintf (stderr,
00188                      _("%s: file %s is not an archive\n"),
00189                      program_name, name);
00190              maybequit ();
00191              return;
00192            }
00193 
00194          ptr = &(obfd->archive_head);
00195          element = bfd_openr_next_archived_file (ibfd, NULL);
00196 
00197          while (element)
00198            {
00199              *ptr = element;
00200              ptr = &element->next;
00201              element = bfd_openr_next_archived_file (ibfd, element);
00202            }
00203        }
00204 
00205       bfd_set_format (obfd, bfd_archive);
00206 
00207       obfd->has_armap = 1;
00208     }
00209 }
00210 
00211 static void
00212 ar_addlib_doer (bfd *abfd, bfd *prev)
00213 {
00214   /* Add this module to the output bfd.  */
00215   if (prev != NULL)
00216     prev->next = abfd->next;
00217 
00218   abfd->next = obfd->archive_head;
00219   obfd->archive_head = abfd;
00220 }
00221 
00222 void
00223 ar_addlib (char *name, struct list *list)
00224 {
00225   if (obfd == NULL)
00226     {
00227       fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
00228       maybequit ();
00229     }
00230   else
00231     {
00232       bfd *arch;
00233 
00234       arch = open_inarch (name, (char *) NULL);
00235       if (arch != NULL)
00236        map_over_list (arch, ar_addlib_doer, list);
00237 
00238       /* Don't close the bfd, since it will make the elements disappear.  */
00239     }
00240 }
00241 
00242 void
00243 ar_addmod (struct list *list)
00244 {
00245   if (!obfd)
00246     {
00247       fprintf (stderr, _("%s: no open output archive\n"), program_name);
00248       maybequit ();
00249     }
00250   else
00251     {
00252       while (list)
00253        {
00254          bfd *abfd = bfd_openr (list->name, NULL);
00255 
00256          if (!abfd)
00257            {
00258              fprintf (stderr, _("%s: can't open file %s\n"),
00259                      program_name, list->name);
00260              maybequit ();
00261            }
00262          else
00263            {
00264              abfd->next = obfd->archive_head;
00265              obfd->archive_head = abfd;
00266            }
00267          list = list->next;
00268        }
00269     }
00270 }
00271 
00272 
00273 void
00274 ar_clear (void)
00275 {
00276   if (obfd)
00277     obfd->archive_head = 0;
00278 }
00279 
00280 void
00281 ar_delete (struct list *list)
00282 {
00283   if (!obfd)
00284     {
00285       fprintf (stderr, _("%s: no open output archive\n"), program_name);
00286       maybequit ();
00287     }
00288   else
00289     {
00290       while (list)
00291        {
00292          /* Find this name in the archive.  */
00293          bfd *member = obfd->archive_head;
00294          bfd **prev = &(obfd->archive_head);
00295          int found = 0;
00296 
00297          while (member)
00298            {
00299              if (FILENAME_CMP(member->filename, list->name) == 0)
00300               {
00301                 *prev = member->next;
00302                 found = 1;
00303               }
00304              else
00305               prev = &(member->next);
00306 
00307              member = member->next;
00308            }
00309 
00310          if (!found)
00311            {
00312              fprintf (stderr, _("%s: can't find module file %s\n"),
00313                      program_name, list->name);
00314              maybequit ();
00315            }
00316 
00317          list = list->next;
00318        }
00319     }
00320 }
00321 
00322 void
00323 ar_save (void)
00324 {
00325   if (!obfd)
00326     {
00327       fprintf (stderr, _("%s: no open output archive\n"), program_name);
00328       maybequit ();
00329     }
00330   else
00331     {
00332       char *ofilename = xstrdup (bfd_get_filename (obfd));
00333 
00334       bfd_close (obfd);
00335 
00336       smart_rename (ofilename, real_name, 0);
00337       obfd = 0;
00338       free (ofilename);
00339     }
00340 }
00341 
00342 void
00343 ar_replace (struct list *list)
00344 {
00345   if (!obfd)
00346     {
00347       fprintf (stderr, _("%s: no open output archive\n"), program_name);
00348       maybequit ();
00349     }
00350   else
00351     {
00352       while (list)
00353        {
00354          /* Find this name in the archive.  */
00355          bfd *member = obfd->archive_head;
00356          bfd **prev = &(obfd->archive_head);
00357          int found = 0;
00358 
00359          while (member)
00360            {
00361              if (FILENAME_CMP (member->filename, list->name) == 0)
00362               {
00363                 /* Found the one to replace.  */
00364                 bfd *abfd = bfd_openr (list->name, 0);
00365 
00366                 if (!abfd)
00367                   {
00368                     fprintf (stderr, _("%s: can't open file %s\n"),
00369                             program_name, list->name);
00370                     maybequit ();
00371                   }
00372                 else
00373                   {
00374                     *prev = abfd;
00375                     abfd->next = member->next;
00376                     found = 1;
00377                   }
00378               }
00379              else
00380               {
00381                 prev = &(member->next);
00382               }
00383              member = member->next;
00384            }
00385 
00386          if (!found)
00387            {
00388              bfd *abfd = bfd_openr (list->name, 0);
00389 
00390              fprintf (stderr,_("%s: can't find module file %s\n"),
00391                      program_name, list->name);
00392              if (!abfd)
00393               {
00394                 fprintf (stderr, _("%s: can't open file %s\n"),
00395                         program_name, list->name);
00396                 maybequit ();
00397               }
00398              else
00399               *prev = abfd;
00400            }
00401 
00402          list = list->next;
00403        }
00404     }
00405 }
00406 
00407 /* And I added this one.  */
00408 void
00409 ar_list (void)
00410 {
00411   if (!obfd)
00412     {
00413       fprintf (stderr, _("%s: no open output archive\n"), program_name);
00414       maybequit ();
00415     }
00416   else
00417     {
00418       bfd *abfd;
00419 
00420       outfile = stdout;
00421       verbose =1 ;
00422       printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
00423 
00424       for (abfd = obfd->archive_head;
00425           abfd != (bfd *)NULL;
00426           abfd = abfd->next)
00427        ar_directory_doer (abfd, (bfd *) NULL);
00428     }
00429 }
00430 
00431 void
00432 ar_end (void)
00433 {
00434   if (obfd)
00435     {
00436       bfd_cache_close (obfd);
00437       unlink (bfd_get_filename (obfd));
00438     }
00439 }
00440 
00441 void
00442 ar_extract (struct list *list)
00443 {
00444   if (!obfd)
00445     {
00446       fprintf (stderr, _("%s: no open archive\n"), program_name);
00447       maybequit ();
00448     }
00449   else
00450     {
00451       while (list)
00452        {
00453          /* Find this name in the archive.  */
00454          bfd *member = obfd->archive_head;
00455          int found = 0;
00456 
00457          while (member && !found)
00458            {
00459              if (FILENAME_CMP (member->filename, list->name) == 0)
00460               {
00461                 extract_file (member);
00462                 found = 1;
00463               }
00464 
00465              member = member->next;
00466            }
00467 
00468          if (!found)
00469            {
00470              bfd_openr (list->name, 0);
00471              fprintf (stderr, _("%s: can't find module file %s\n"),
00472                      program_name, list->name);
00473            }
00474 
00475          list = list->next;
00476        }
00477     }
00478 }