Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* arsup.c - Archive support for MRI compatibility
  2.    Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
  3.    2004, 2005, 2007, 2008 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Binutils.
  6.  
  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 3 of the License, or
  10.    (at your option) any later version.
  11.  
  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.
  16.  
  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,
  20.    MA 02110-1301, USA.  */
  21.  
  22.  
  23. /* Contributed by Steve Chamberlain
  24.    sac@cygnus.com
  25.  
  26.    This file looks after requests from arparse.y, to provide the MRI
  27.    style librarian command syntax + 1 word LIST.  */
  28.  
  29. #include "sysdep.h"
  30. #include "bfd.h"
  31. #include "libiberty.h"
  32. #include "filenames.h"
  33. #include "bucomm.h"
  34. #include "arsup.h"
  35.  
  36. static void map_over_list
  37.   (bfd *, void (*function) (bfd *, bfd *), struct list *);
  38. static void ar_directory_doer (bfd *, bfd *);
  39. static void ar_addlib_doer (bfd *, bfd *);
  40.  
  41. extern int verbose;
  42.  
  43. static bfd *obfd;
  44. static char *real_name;
  45. static FILE *outfile;
  46.  
  47. static void
  48. map_over_list (bfd *arch, void (*function) (bfd *, bfd *), struct list *list)
  49. {
  50.   bfd *head;
  51.  
  52.   if (list == NULL)
  53.     {
  54.       bfd *next;
  55.  
  56.       head = arch->archive_next;
  57.       while (head != NULL)
  58.         {
  59.           next = head->archive_next;
  60.           function (head, (bfd *) NULL);
  61.           head = next;
  62.         }
  63.     }
  64.   else
  65.     {
  66.       struct list *ptr;
  67.  
  68.       /* This may appear to be a baroque way of accomplishing what we
  69.          want.  however we have to iterate over the filenames in order
  70.          to notice where a filename is requested but does not exist in
  71.          the archive.  Ditto mapping over each file each time -- we
  72.          want to hack multiple references.  */
  73.       for (ptr = list; ptr; ptr = ptr->next)
  74.         {
  75.           bfd_boolean found = FALSE;
  76.           bfd *prev = arch;
  77.  
  78.           for (head = arch->archive_next; head; head = head->archive_next)
  79.             {
  80.               if (head->filename != NULL
  81.                   && FILENAME_CMP (ptr->name, head->filename) == 0)
  82.                 {
  83.                   found = TRUE;
  84.                   function (head, prev);
  85.                 }
  86.               prev = head;
  87.             }
  88.           if (! found)
  89.             fprintf (stderr, _("No entry %s in archive.\n"), ptr->name);
  90.         }
  91.     }
  92. }
  93.  
  94.  
  95.  
  96. static void
  97. ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
  98. {
  99.   print_arelt_descr(outfile, abfd, verbose);
  100. }
  101.  
  102. void
  103. ar_directory (char *ar_name, struct list *list, char *output)
  104. {
  105.   bfd *arch;
  106.  
  107.   arch = open_inarch (ar_name, (char *) NULL);
  108.   if (output)
  109.     {
  110.       outfile = fopen(output,"w");
  111.       if (outfile == 0)
  112.         {
  113.           outfile = stdout;
  114.           fprintf (stderr,_("Can't open file %s\n"), output);
  115.           output = 0;
  116.         }
  117.     }
  118.   else
  119.     outfile = stdout;
  120.  
  121.   map_over_list (arch, ar_directory_doer, list);
  122.  
  123.   bfd_close (arch);
  124.  
  125.   if (output)
  126.    fclose (outfile);
  127. }
  128.  
  129. void
  130. prompt (void)
  131. {
  132.   extern int interactive;
  133.  
  134.   if (interactive)
  135.     {
  136.       printf ("AR >");
  137.       fflush (stdout);
  138.     }
  139. }
  140.  
  141. void
  142. maybequit (void)
  143. {
  144.   if (! interactive)
  145.     xexit (9);
  146. }
  147.  
  148.  
  149. void
  150. ar_open (char *name, int t)
  151. {
  152.   char *tname = (char *) xmalloc (strlen (name) + 10);
  153.   const char *bname = lbasename (name);
  154.   real_name = name;
  155.  
  156.   /* Prepend tmp- to the beginning, to avoid file-name clashes after
  157.      truncation on filesystems with limited namespaces (DOS).  */
  158.   sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname);
  159.   obfd = bfd_openw (tname, NULL);
  160.  
  161.   if (!obfd)
  162.     {
  163.       fprintf (stderr,
  164.                _("%s: Can't open output archive %s\n"),
  165.                program_name,  tname);
  166.  
  167.       maybequit ();
  168.     }
  169.   else
  170.     {
  171.       if (!t)
  172.         {
  173.           bfd **ptr;
  174.           bfd *element;
  175.           bfd *ibfd;
  176.  
  177.           ibfd = bfd_openr (name, NULL);
  178.  
  179.           if (!ibfd)
  180.             {
  181.               fprintf (stderr,_("%s: Can't open input archive %s\n"),
  182.                        program_name, name);
  183.               maybequit ();
  184.               return;
  185.             }
  186.  
  187.           if (!bfd_check_format(ibfd, bfd_archive))
  188.             {
  189.               fprintf (stderr,
  190.                        _("%s: file %s is not an archive\n"),
  191.                        program_name, name);
  192.               maybequit ();
  193.               return;
  194.             }
  195.  
  196.           ptr = &(obfd->archive_head);
  197.           element = bfd_openr_next_archived_file (ibfd, NULL);
  198.  
  199.           while (element)
  200.             {
  201.               *ptr = element;
  202.               ptr = &element->archive_next;
  203.               element = bfd_openr_next_archived_file (ibfd, element);
  204.             }
  205.         }
  206.  
  207.       bfd_set_format (obfd, bfd_archive);
  208.  
  209.       obfd->has_armap = 1;
  210.       obfd->is_thin_archive = 0;
  211.     }
  212. }
  213.  
  214. static void
  215. ar_addlib_doer (bfd *abfd, bfd *prev)
  216. {
  217.   /* Add this module to the output bfd.  */
  218.   if (prev != NULL)
  219.     prev->archive_next = abfd->archive_next;
  220.  
  221.   abfd->archive_next = obfd->archive_head;
  222.   obfd->archive_head = abfd;
  223. }
  224.  
  225. void
  226. ar_addlib (char *name, struct list *list)
  227. {
  228.   if (obfd == NULL)
  229.     {
  230.       fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
  231.       maybequit ();
  232.     }
  233.   else
  234.     {
  235.       bfd *arch;
  236.  
  237.       arch = open_inarch (name, (char *) NULL);
  238.       if (arch != NULL)
  239.         map_over_list (arch, ar_addlib_doer, list);
  240.  
  241.       /* Don't close the bfd, since it will make the elements disappear.  */
  242.     }
  243. }
  244.  
  245. void
  246. ar_addmod (struct list *list)
  247. {
  248.   if (!obfd)
  249.     {
  250.       fprintf (stderr, _("%s: no open output archive\n"), program_name);
  251.       maybequit ();
  252.     }
  253.   else
  254.     {
  255.       while (list)
  256.         {
  257.           bfd *abfd = bfd_openr (list->name, NULL);
  258.  
  259.           if (!abfd)
  260.             {
  261.               fprintf (stderr, _("%s: can't open file %s\n"),
  262.                        program_name, list->name);
  263.               maybequit ();
  264.             }
  265.           else
  266.             {
  267.               abfd->archive_next = obfd->archive_head;
  268.               obfd->archive_head = abfd;
  269.             }
  270.           list = list->next;
  271.         }
  272.     }
  273. }
  274.  
  275.  
  276. void
  277. ar_clear (void)
  278. {
  279.   if (obfd)
  280.     obfd->archive_head = 0;
  281. }
  282.  
  283. void
  284. ar_delete (struct list *list)
  285. {
  286.   if (!obfd)
  287.     {
  288.       fprintf (stderr, _("%s: no open output archive\n"), program_name);
  289.       maybequit ();
  290.     }
  291.   else
  292.     {
  293.       while (list)
  294.         {
  295.           /* Find this name in the archive.  */
  296.           bfd *member = obfd->archive_head;
  297.           bfd **prev = &(obfd->archive_head);
  298.           int found = 0;
  299.  
  300.           while (member)
  301.             {
  302.               if (FILENAME_CMP(member->filename, list->name) == 0)
  303.                 {
  304.                   *prev = member->archive_next;
  305.                   found = 1;
  306.                 }
  307.               else
  308.                 prev = &(member->archive_next);
  309.  
  310.               member = member->archive_next;
  311.             }
  312.  
  313.           if (!found)
  314.             {
  315.               fprintf (stderr, _("%s: can't find module file %s\n"),
  316.                        program_name, list->name);
  317.               maybequit ();
  318.             }
  319.  
  320.           list = list->next;
  321.         }
  322.     }
  323. }
  324.  
  325. void
  326. ar_save (void)
  327. {
  328.   if (!obfd)
  329.     {
  330.       fprintf (stderr, _("%s: no open output archive\n"), program_name);
  331.       maybequit ();
  332.     }
  333.   else
  334.     {
  335.       char *ofilename = xstrdup (bfd_get_filename (obfd));
  336.  
  337.       bfd_close (obfd);
  338.  
  339.       smart_rename (ofilename, real_name, 0);
  340.       obfd = 0;
  341.       free (ofilename);
  342.     }
  343. }
  344.  
  345. void
  346. ar_replace (struct list *list)
  347. {
  348.   if (!obfd)
  349.     {
  350.       fprintf (stderr, _("%s: no open output archive\n"), program_name);
  351.       maybequit ();
  352.     }
  353.   else
  354.     {
  355.       while (list)
  356.         {
  357.           /* Find this name in the archive.  */
  358.           bfd *member = obfd->archive_head;
  359.           bfd **prev = &(obfd->archive_head);
  360.           int found = 0;
  361.  
  362.           while (member)
  363.             {
  364.               if (FILENAME_CMP (member->filename, list->name) == 0)
  365.                 {
  366.                   /* Found the one to replace.  */
  367.                   bfd *abfd = bfd_openr (list->name, 0);
  368.  
  369.                   if (!abfd)
  370.                     {
  371.                       fprintf (stderr, _("%s: can't open file %s\n"),
  372.                                program_name, list->name);
  373.                       maybequit ();
  374.                     }
  375.                   else
  376.                     {
  377.                       *prev = abfd;
  378.                       abfd->archive_next = member->archive_next;
  379.                       found = 1;
  380.                     }
  381.                 }
  382.               else
  383.                 {
  384.                   prev = &(member->archive_next);
  385.                 }
  386.               member = member->archive_next;
  387.             }
  388.  
  389.           if (!found)
  390.             {
  391.               bfd *abfd = bfd_openr (list->name, 0);
  392.  
  393.               fprintf (stderr,_("%s: can't find module file %s\n"),
  394.                        program_name, list->name);
  395.               if (!abfd)
  396.                 {
  397.                   fprintf (stderr, _("%s: can't open file %s\n"),
  398.                            program_name, list->name);
  399.                   maybequit ();
  400.                 }
  401.               else
  402.                 *prev = abfd;
  403.             }
  404.  
  405.           list = list->next;
  406.         }
  407.     }
  408. }
  409.  
  410. /* And I added this one.  */
  411. void
  412. ar_list (void)
  413. {
  414.   if (!obfd)
  415.     {
  416.       fprintf (stderr, _("%s: no open output archive\n"), program_name);
  417.       maybequit ();
  418.     }
  419.   else
  420.     {
  421.       bfd *abfd;
  422.  
  423.       outfile = stdout;
  424.       verbose =1 ;
  425.       printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
  426.  
  427.       for (abfd = obfd->archive_head;
  428.            abfd != (bfd *)NULL;
  429.            abfd = abfd->archive_next)
  430.         ar_directory_doer (abfd, (bfd *) NULL);
  431.     }
  432. }
  433.  
  434. void
  435. ar_end (void)
  436. {
  437.   if (obfd)
  438.     {
  439.       bfd_cache_close (obfd);
  440.       unlink (bfd_get_filename (obfd));
  441.     }
  442. }
  443.  
  444. void
  445. ar_extract (struct list *list)
  446. {
  447.   if (!obfd)
  448.     {
  449.       fprintf (stderr, _("%s: no open archive\n"), program_name);
  450.       maybequit ();
  451.     }
  452.   else
  453.     {
  454.       while (list)
  455.         {
  456.           /* Find this name in the archive.  */
  457.           bfd *member = obfd->archive_head;
  458.           int found = 0;
  459.  
  460.           while (member && !found)
  461.             {
  462.               if (FILENAME_CMP (member->filename, list->name) == 0)
  463.                 {
  464.                   extract_file (member);
  465.                   found = 1;
  466.                 }
  467.  
  468.               member = member->archive_next;
  469.             }
  470.  
  471.           if (!found)
  472.             {
  473.               bfd_openr (list->name, 0);
  474.               fprintf (stderr, _("%s: can't find module file %s\n"),
  475.                        program_name, list->name);
  476.             }
  477.  
  478.           list = list->next;
  479.         }
  480.     }
  481. }
  482.