arsup.c revision 33965
1/* arsup.c - Archive support for MRI compatibility
2   Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
3
4This file is part of GNU Binutils.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20
21/* Contributed by Steve Chamberlain
22   		  sac@cygnus.com
23
24This file looks after requests from arparse.y, to provide the MRI
25style 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
34static void map_over_list
35  PARAMS ((bfd *, void (*function) (bfd *, bfd *), struct list *));
36static void ar_directory_doer PARAMS ((bfd *, bfd *));
37static void ar_addlib_doer PARAMS ((bfd *, bfd *));
38
39extern int verbose;
40
41static void
42map_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
92FILE *outfile;
93
94/*ARGSUSED*/
95static void
96ar_directory_doer (abfd, ignore)
97     bfd *abfd;
98     bfd *ignore;
99{
100    print_arelt_descr(outfile, abfd, verbose);
101}
102
103void
104ar_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
133void
134DEFUN_VOID(prompt)
135{
136  extern int interactive;
137  if (interactive)
138  {
139    printf("AR >");
140    fflush(stdout);
141  }
142}
143
144void
145maybequit ()
146{
147  if (! interactive)
148    xexit (9);
149}
150
151
152bfd *obfd;
153char *real_name ;
154void
155DEFUN(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
206static void
207ar_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
218void
219ar_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
240void
241DEFUN(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
268void
269DEFUN_VOID(ar_clear)
270{
271if (obfd)
272 obfd->archive_head = 0;
273}
274
275void
276DEFUN(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
311void
312DEFUN_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
331void
332DEFUN(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 */
389void
390DEFUN_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
412void
413DEFUN_VOID(ar_end)
414{
415  if (obfd)
416  {
417    fclose((FILE *)(obfd->iostream));
418    unlink(bfd_get_filename (obfd));
419  }
420}
421void
422DEFUN(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}
457