arsup.c revision 61843
1/* arsup.c - Archive support for MRI compatibility
2   Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 99, 2000
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#include "filenames.h"
35
36static void map_over_list
37  PARAMS ((bfd *, void (*function) (bfd *, bfd *), struct list *));
38static void ar_directory_doer PARAMS ((bfd *, bfd *));
39static void ar_addlib_doer PARAMS ((bfd *, bfd *));
40
41extern int verbose;
42
43static void
44map_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
94FILE *outfile;
95
96/*ARGSUSED*/
97static void
98ar_directory_doer (abfd, ignore)
99     bfd *abfd;
100     bfd *ignore ATTRIBUTE_UNUSED;
101{
102    print_arelt_descr(outfile, abfd, verbose);
103}
104
105void
106ar_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
135void
136DEFUN_VOID(prompt)
137{
138  extern int interactive;
139  if (interactive)
140  {
141    printf("AR >");
142    fflush(stdout);
143  }
144}
145
146void
147maybequit ()
148{
149  if (! interactive)
150    xexit (9);
151}
152
153
154bfd *obfd;
155char *real_name ;
156void
157DEFUN(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
210static void
211ar_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
222void
223ar_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
244void
245DEFUN(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
272void
273DEFUN_VOID(ar_clear)
274{
275if (obfd)
276 obfd->archive_head = 0;
277}
278
279void
280DEFUN(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
315void
316DEFUN_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
335void
336DEFUN(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 */
393void
394DEFUN_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
416void
417DEFUN_VOID(ar_end)
418{
419  if (obfd)
420  {
421    fclose((FILE *)(obfd->iostream));
422    unlink(bfd_get_filename (obfd));
423  }
424}
425void
426DEFUN(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}
461