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