This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / binutils / arsup.c
1 /* arsup.c - Archive support for MRI compatibility
2    Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999
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 */
29
30 #include "bfd.h"
31 #include "arsup.h"
32 #include "libiberty.h"
33 #include "bucomm.h"
34
35 static void map_over_list
36   PARAMS ((bfd *, void (*function) (bfd *, bfd *), struct list *));
37 static void ar_directory_doer PARAMS ((bfd *, bfd *));
38 static void ar_addlib_doer PARAMS ((bfd *, bfd *));
39
40 extern int verbose;
41
42 static void
43 map_over_list (arch, function, list)
44      bfd *arch;
45      void (*function) PARAMS ((bfd *, bfd *));
46      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           boolean found = false;
74           bfd *prev = arch;
75
76           for (head = arch->next; head; head = head->next) 
77             {
78               if (head->filename != NULL
79                   && strcmp (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 FILE *outfile;
94
95 /*ARGSUSED*/
96 static void
97 ar_directory_doer (abfd, ignore)
98      bfd *abfd;
99      bfd *ignore ATTRIBUTE_UNUSED;
100 {
101     print_arelt_descr(outfile, abfd, verbose);
102 }
103
104 void
105 ar_directory (ar_name, list, output)
106      char *ar_name;
107      struct list *list;
108      char *output;
109 {
110   bfd *arch;
111
112   arch = open_inarch (ar_name, (char *) NULL);
113   if (output)
114     {
115       outfile = fopen(output,"w");
116       if (outfile == 0)
117         {
118           outfile = stdout;
119           fprintf (stderr,_("Can't open file %s\n"), output);
120           output = 0;
121         }
122     }
123   else 
124     outfile = stdout;
125
126   map_over_list (arch, ar_directory_doer, list);
127
128   bfd_close (arch);
129
130   if (output)
131    fclose (outfile);
132 }
133
134 void
135 DEFUN_VOID(prompt)
136 {
137   extern int interactive;
138   if (interactive) 
139   {
140     printf("AR >");
141     fflush(stdout); 
142   }
143 }
144
145 void
146 maybequit ()
147 {
148   if (! interactive) 
149     xexit (9);
150 }
151
152
153 bfd *obfd;
154 char *real_name ; 
155 void
156 DEFUN(ar_open,(name, t),
157       char *name AND
158       int t)
159
160 {
161   char *tname = (char *) xmalloc (strlen (name) + 10);
162   real_name = name;
163   sprintf(tname, "%s-tmp", name);
164   obfd = bfd_openw(tname, NULL);
165
166   if (!obfd) {
167     fprintf(stderr,_("%s: Can't open output archive %s\n"), program_name,
168             tname);
169
170     maybequit();
171   }
172   else {
173     if (!t) {
174       bfd **ptr;
175       bfd *element;
176       bfd *ibfd;
177       ibfd = bfd_openr(name, NULL);
178       if (!ibfd) {
179         fprintf(stderr,_("%s: Can't open input archive %s\n"),
180                 program_name, name);
181         maybequit();
182         return;
183       }
184       if (bfd_check_format(ibfd, bfd_archive) != true) {
185         fprintf(stderr,_("%s: file %s is not an archive\n"), program_name,
186                 name);
187         maybequit();
188         return;
189       }
190       ptr = &(obfd->archive_head);
191       element = bfd_openr_next_archived_file(ibfd, NULL);
192
193       while (element) {
194         *ptr = element;
195         ptr = &element->next;
196         element = bfd_openr_next_archived_file(ibfd, element);
197       }
198     }
199
200     bfd_set_format(obfd, bfd_archive);
201
202     obfd->has_armap = 1;
203   }
204 }
205
206
207 static void
208 ar_addlib_doer (abfd, prev)
209      bfd *abfd;
210      bfd *prev;
211 {
212   /* Add this module to the output bfd */
213   if (prev != NULL)
214     prev->next = abfd->next;
215   abfd->next = obfd->archive_head;
216   obfd->archive_head = abfd;
217 }
218
219 void
220 ar_addlib (name, list)
221      char *name;
222      struct list *list;
223 {
224   if (obfd == NULL)
225     {
226       fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
227       maybequit ();
228     }
229   else
230     {
231       bfd *arch;
232
233       arch = open_inarch (name, (char *) NULL);
234       if (arch != NULL)
235         map_over_list (arch, ar_addlib_doer, list);
236
237       /* Don't close the bfd, since it will make the elements disasppear */
238     }
239 }
240
241 void
242 DEFUN(ar_addmod, (list),
243       struct list *list)
244 {
245   if (!obfd) {
246     fprintf(stderr, _("%s: no open output archive\n"), program_name);
247     maybequit();
248   }
249   else 
250   {
251     while (list) {
252       bfd *abfd = bfd_openr(list->name, NULL);
253       if (!abfd)  {
254         fprintf(stderr,_("%s: can't open file %s\n"), program_name,
255                 list->name);
256         maybequit();
257       }
258       else {
259         abfd->next = obfd->archive_head;
260         obfd->archive_head = abfd;
261       }
262       list = list->next;
263     }
264   }
265 }
266
267
268
269 void
270 DEFUN_VOID(ar_clear)
271 {
272 if (obfd) 
273  obfd->archive_head = 0;
274 }
275
276 void
277 DEFUN(ar_delete, (list),
278       struct list *list)
279 {
280   if (!obfd) {
281     fprintf(stderr, _("%s: no open output archive\n"), program_name);
282     maybequit();
283   }
284   else 
285   {
286     while (list) {
287       /* Find this name in the archive */
288       bfd *member = obfd->archive_head;
289       bfd **prev = &(obfd->archive_head);
290       int found = 0;
291       while (member) {
292         if (strcmp(member->filename, list->name) == 0) {
293           *prev = member->next;
294           found = 1;
295         }
296         else {
297           prev = &(member->next);
298         }
299           member = member->next;
300       }
301       if (!found)  {
302         fprintf(stderr,_("%s: can't find module file %s\n"), program_name,
303                 list->name);
304         maybequit();
305       }
306       list = list->next;
307     }
308   }
309 }
310
311
312 void
313 DEFUN_VOID(ar_save)
314 {
315
316   if (!obfd) {
317     fprintf(stderr, _("%s: no open output archive\n"), program_name);
318     maybequit();
319   }
320   else {
321     char *ofilename = xstrdup (bfd_get_filename (obfd));
322     bfd_close(obfd);
323     
324     rename (ofilename, real_name);
325     obfd = 0;
326     free(ofilename);
327   }
328 }
329
330
331
332 void
333 DEFUN(ar_replace, (list),
334       struct list *list)
335 {
336   if (!obfd) {
337     fprintf(stderr, _("%s: no open output archive\n"), program_name);
338     maybequit();
339   }
340   else 
341   {
342     while (list) {
343       /* Find this name in the archive */
344       bfd *member = obfd->archive_head;
345       bfd **prev = &(obfd->archive_head);
346       int found = 0;
347       while (member) 
348       {
349         if (strcmp(member->filename, list->name) == 0) 
350         {
351           /* Found the one to replace */
352           bfd *abfd = bfd_openr(list->name, 0);
353           if (!abfd) 
354           {
355             fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name);
356             maybequit();
357           }
358           else {
359             *prev = abfd;
360             abfd->next = member->next;
361             found = 1;
362           }
363         }
364         else {
365           prev = &(member->next);
366         }
367         member = member->next;
368       }
369       if (!found)  {
370         bfd *abfd = bfd_openr(list->name, 0);
371         fprintf(stderr,_("%s: can't find module file %s\n"), program_name,
372                 list->name);
373         if (!abfd) 
374         {
375           fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name);
376           maybequit();
377         }
378         else 
379         {
380           *prev = abfd;
381         }
382       }
383
384     list = list->next;
385     }
386   }
387 }
388
389 /* And I added this one */
390 void
391 DEFUN_VOID(ar_list)
392 {
393   if (!obfd) 
394   {
395     fprintf(stderr, _("%s: no open output archive\n"), program_name);
396     maybequit();
397   }
398   else {
399     bfd *abfd;
400     outfile = stdout;
401     verbose =1 ;
402     printf(_("Current open archive is %s\n"), bfd_get_filename (obfd));
403     for (abfd = obfd->archive_head;
404          abfd != (bfd *)NULL;
405          abfd = abfd->next) 
406     {
407       ar_directory_doer (abfd, (bfd *) NULL);
408     }
409   }
410 }
411
412
413 void 
414 DEFUN_VOID(ar_end)
415 {
416   if (obfd)
417   {
418     fclose((FILE *)(obfd->iostream));
419     unlink(bfd_get_filename (obfd));
420   }
421 }
422 void
423 DEFUN(ar_extract,(list),
424       struct list *list)
425 {
426   if (!obfd) 
427   {
428
429     fprintf(stderr, _("%s: no open  archive\n"), program_name);
430     maybequit();
431   }
432   else 
433   {
434     while (list) {
435       /* Find this name in the archive */
436       bfd *member = obfd->archive_head;
437       int found = 0;
438       while (member && !found) 
439       {
440         if (strcmp(member->filename, list->name) == 0) 
441         {
442           extract_file(member);
443           found = 1;
444           }
445
446         member = member->next;
447       }
448       if (!found)  {
449         bfd_openr(list->name, 0);
450         fprintf(stderr,_("%s: can't find module file %s\n"), program_name,
451                 list->name);
452
453       }
454       list = list->next;
455     }
456   }
457 }