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