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