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