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