Subversion Repositories Kolibri OS

Rev

Rev 5219 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* arsup.c - Archive support for MRI compatibility
  2.    Copyright (C) 1992-2015 Free Software Foundation, Inc.
  3.  
  4.    This file is part of GNU Binutils.
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 3 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  19.    MA 02110-1301, USA.  */
  20.  
  21.  
  22. /* Contributed by Steve Chamberlain
  23.    sac@cygnus.com
  24.  
  25.    This file looks after requests from arparse.y, to provide the MRI
  26.    style librarian command syntax + 1 word LIST.  */
  27.  
  28. #include "sysdep.h"
  29. #include "bfd.h"
  30. #include "libiberty.h"
  31. #include "filenames.h"
  32. #include "bucomm.h"
  33. #include "arsup.h"
  34.  
  35. static void map_over_list
  36.   (bfd *, void (*function) (bfd *, bfd *), struct list *);
  37. static void ar_directory_doer (bfd *, bfd *);
  38. static void ar_addlib_doer (bfd *, bfd *);
  39.  
  40. extern int verbose;
  41. extern int deterministic;
  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.       if (deterministic > 0)
  338.         obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
  339.  
  340.       bfd_close (obfd);
  341.  
  342.       smart_rename (ofilename, real_name, 0);
  343.       obfd = 0;
  344.       free (ofilename);
  345.     }
  346. }
  347.  
  348. void
  349. ar_replace (struct list *list)
  350. {
  351.   if (!obfd)
  352.     {
  353.       fprintf (stderr, _("%s: no open output archive\n"), program_name);
  354.       maybequit ();
  355.     }
  356.   else
  357.     {
  358.       while (list)
  359.         {
  360.           /* Find this name in the archive.  */
  361.           bfd *member = obfd->archive_head;
  362.           bfd **prev = &(obfd->archive_head);
  363.           int found = 0;
  364.  
  365.           while (member)
  366.             {
  367.               if (FILENAME_CMP (member->filename, list->name) == 0)
  368.                 {
  369.                   /* Found the one to replace.  */
  370.                   bfd *abfd = bfd_openr (list->name, 0);
  371.  
  372.                   if (!abfd)
  373.                     {
  374.                       fprintf (stderr, _("%s: can't open file %s\n"),
  375.                                program_name, list->name);
  376.                       maybequit ();
  377.                     }
  378.                   else
  379.                     {
  380.                       *prev = abfd;
  381.                       abfd->archive_next = member->archive_next;
  382.                       found = 1;
  383.                     }
  384.                 }
  385.               else
  386.                 {
  387.                   prev = &(member->archive_next);
  388.                 }
  389.               member = member->archive_next;
  390.             }
  391.  
  392.           if (!found)
  393.             {
  394.               bfd *abfd = bfd_openr (list->name, 0);
  395.  
  396.               fprintf (stderr,_("%s: can't find module file %s\n"),
  397.                        program_name, list->name);
  398.               if (!abfd)
  399.                 {
  400.                   fprintf (stderr, _("%s: can't open file %s\n"),
  401.                            program_name, list->name);
  402.                   maybequit ();
  403.                 }
  404.               else
  405.                 *prev = abfd;
  406.             }
  407.  
  408.           list = list->next;
  409.         }
  410.     }
  411. }
  412.  
  413. /* And I added this one.  */
  414. void
  415. ar_list (void)
  416. {
  417.   if (!obfd)
  418.     {
  419.       fprintf (stderr, _("%s: no open output archive\n"), program_name);
  420.       maybequit ();
  421.     }
  422.   else
  423.     {
  424.       bfd *abfd;
  425.  
  426.       outfile = stdout;
  427.       verbose =1 ;
  428.       printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
  429.  
  430.       for (abfd = obfd->archive_head;
  431.            abfd != (bfd *)NULL;
  432.            abfd = abfd->archive_next)
  433.         ar_directory_doer (abfd, (bfd *) NULL);
  434.     }
  435. }
  436.  
  437. void
  438. ar_end (void)
  439. {
  440.   if (obfd)
  441.     {
  442.       bfd_cache_close (obfd);
  443.       unlink (bfd_get_filename (obfd));
  444.     }
  445. }
  446.  
  447. void
  448. ar_extract (struct list *list)
  449. {
  450.   if (!obfd)
  451.     {
  452.       fprintf (stderr, _("%s: no open archive\n"), program_name);
  453.       maybequit ();
  454.     }
  455.   else
  456.     {
  457.       while (list)
  458.         {
  459.           /* Find this name in the archive.  */
  460.           bfd *member = obfd->archive_head;
  461.           int found = 0;
  462.  
  463.           while (member && !found)
  464.             {
  465.               if (FILENAME_CMP (member->filename, list->name) == 0)
  466.                 {
  467.                   extract_file (member);
  468.                   found = 1;
  469.                 }
  470.  
  471.               member = member->archive_next;
  472.             }
  473.  
  474.           if (!found)
  475.             {
  476.               bfd_openr (list->name, 0);
  477.               fprintf (stderr, _("%s: can't find module file %s\n"),
  478.                        program_name, list->name);
  479.             }
  480.  
  481.           list = list->next;
  482.         }
  483.     }
  484. }
  485.