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