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