bfd/
[deliverable/binutils-gdb.git] / binutils / arsup.c
1 /* arsup.c - Archive support for MRI compatibility
2 Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
3 2004, 2007 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 #include "sysdep.h"
29 #include "bfd.h"
30 #include "libiberty.h"
31 #include "filenames.h"
32 #include "bucomm.h"
33 #include "arsup.h"
34
35 static void map_over_list
36 (bfd *, void (*function) (bfd *, bfd *), struct list *);
37 static void ar_directory_doer (bfd *, bfd *);
38 static void ar_addlib_doer (bfd *, bfd *);
39
40 extern int verbose;
41
42 static bfd *obfd;
43 static char *real_name;
44 static FILE *outfile;
45
46 static void
47 map_over_list (bfd *arch, void (*function) (bfd *, bfd *), 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 bfd_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
95 static void
96 ar_directory_doer (bfd *abfd, bfd *ignore ATTRIBUTE_UNUSED)
97 {
98 print_arelt_descr(outfile, abfd, verbose);
99 }
100
101 void
102 ar_directory (char *ar_name, struct list *list, char *output)
103 {
104 bfd *arch;
105
106 arch = open_inarch (ar_name, (char *) NULL);
107 if (output)
108 {
109 outfile = fopen(output,"w");
110 if (outfile == 0)
111 {
112 outfile = stdout;
113 fprintf (stderr,_("Can't open file %s\n"), output);
114 output = 0;
115 }
116 }
117 else
118 outfile = stdout;
119
120 map_over_list (arch, ar_directory_doer, list);
121
122 bfd_close (arch);
123
124 if (output)
125 fclose (outfile);
126 }
127
128 void
129 prompt (void)
130 {
131 extern int interactive;
132
133 if (interactive)
134 {
135 printf ("AR >");
136 fflush (stdout);
137 }
138 }
139
140 void
141 maybequit (void)
142 {
143 if (! interactive)
144 xexit (9);
145 }
146
147
148 void
149 ar_open (char *name, int t)
150 {
151 char *tname = (char *) xmalloc (strlen (name) + 10);
152 const char *bname = lbasename (name);
153 real_name = name;
154
155 /* Prepend tmp- to the beginning, to avoid file-name clashes after
156 truncation on filesystems with limited namespaces (DOS). */
157 sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname);
158 obfd = bfd_openw (tname, NULL);
159
160 if (!obfd)
161 {
162 fprintf (stderr,
163 _("%s: Can't open output archive %s\n"),
164 program_name, tname);
165
166 maybequit ();
167 }
168 else
169 {
170 if (!t)
171 {
172 bfd **ptr;
173 bfd *element;
174 bfd *ibfd;
175
176 ibfd = bfd_openr (name, NULL);
177
178 if (!ibfd)
179 {
180 fprintf (stderr,_("%s: Can't open input archive %s\n"),
181 program_name, name);
182 maybequit ();
183 return;
184 }
185
186 if (!bfd_check_format(ibfd, bfd_archive))
187 {
188 fprintf (stderr,
189 _("%s: file %s is not an archive\n"),
190 program_name, name);
191 maybequit ();
192 return;
193 }
194
195 ptr = &(obfd->archive_head);
196 element = bfd_openr_next_archived_file (ibfd, NULL);
197
198 while (element)
199 {
200 *ptr = element;
201 ptr = &element->next;
202 element = bfd_openr_next_archived_file (ibfd, element);
203 }
204 }
205
206 bfd_set_format (obfd, bfd_archive);
207
208 obfd->has_armap = 1;
209 }
210 }
211
212 static void
213 ar_addlib_doer (bfd *abfd, bfd *prev)
214 {
215 /* Add this module to the output bfd. */
216 if (prev != NULL)
217 prev->next = abfd->next;
218
219 abfd->next = obfd->archive_head;
220 obfd->archive_head = abfd;
221 }
222
223 void
224 ar_addlib (char *name, struct list *list)
225 {
226 if (obfd == NULL)
227 {
228 fprintf (stderr, _("%s: no output archive specified yet\n"), program_name);
229 maybequit ();
230 }
231 else
232 {
233 bfd *arch;
234
235 arch = open_inarch (name, (char *) NULL);
236 if (arch != NULL)
237 map_over_list (arch, ar_addlib_doer, list);
238
239 /* Don't close the bfd, since it will make the elements disappear. */
240 }
241 }
242
243 void
244 ar_addmod (struct list *list)
245 {
246 if (!obfd)
247 {
248 fprintf (stderr, _("%s: no open output archive\n"), program_name);
249 maybequit ();
250 }
251 else
252 {
253 while (list)
254 {
255 bfd *abfd = bfd_openr (list->name, NULL);
256
257 if (!abfd)
258 {
259 fprintf (stderr, _("%s: can't open file %s\n"),
260 program_name, list->name);
261 maybequit ();
262 }
263 else
264 {
265 abfd->next = obfd->archive_head;
266 obfd->archive_head = abfd;
267 }
268 list = list->next;
269 }
270 }
271 }
272
273
274 void
275 ar_clear (void)
276 {
277 if (obfd)
278 obfd->archive_head = 0;
279 }
280
281 void
282 ar_delete (struct list *list)
283 {
284 if (!obfd)
285 {
286 fprintf (stderr, _("%s: no open output archive\n"), program_name);
287 maybequit ();
288 }
289 else
290 {
291 while (list)
292 {
293 /* Find this name in the archive. */
294 bfd *member = obfd->archive_head;
295 bfd **prev = &(obfd->archive_head);
296 int found = 0;
297
298 while (member)
299 {
300 if (FILENAME_CMP(member->filename, list->name) == 0)
301 {
302 *prev = member->next;
303 found = 1;
304 }
305 else
306 prev = &(member->next);
307
308 member = member->next;
309 }
310
311 if (!found)
312 {
313 fprintf (stderr, _("%s: can't find module file %s\n"),
314 program_name, list->name);
315 maybequit ();
316 }
317
318 list = list->next;
319 }
320 }
321 }
322
323 void
324 ar_save (void)
325 {
326 if (!obfd)
327 {
328 fprintf (stderr, _("%s: no open output archive\n"), program_name);
329 maybequit ();
330 }
331 else
332 {
333 char *ofilename = xstrdup (bfd_get_filename (obfd));
334
335 bfd_close (obfd);
336
337 smart_rename (ofilename, real_name, 0);
338 obfd = 0;
339 free (ofilename);
340 }
341 }
342
343 void
344 ar_replace (struct list *list)
345 {
346 if (!obfd)
347 {
348 fprintf (stderr, _("%s: no open output archive\n"), program_name);
349 maybequit ();
350 }
351 else
352 {
353 while (list)
354 {
355 /* Find this name in the archive. */
356 bfd *member = obfd->archive_head;
357 bfd **prev = &(obfd->archive_head);
358 int found = 0;
359
360 while (member)
361 {
362 if (FILENAME_CMP (member->filename, list->name) == 0)
363 {
364 /* Found the one to replace. */
365 bfd *abfd = bfd_openr (list->name, 0);
366
367 if (!abfd)
368 {
369 fprintf (stderr, _("%s: can't open file %s\n"),
370 program_name, list->name);
371 maybequit ();
372 }
373 else
374 {
375 *prev = abfd;
376 abfd->next = member->next;
377 found = 1;
378 }
379 }
380 else
381 {
382 prev = &(member->next);
383 }
384 member = member->next;
385 }
386
387 if (!found)
388 {
389 bfd *abfd = bfd_openr (list->name, 0);
390
391 fprintf (stderr,_("%s: can't find module file %s\n"),
392 program_name, list->name);
393 if (!abfd)
394 {
395 fprintf (stderr, _("%s: can't open file %s\n"),
396 program_name, list->name);
397 maybequit ();
398 }
399 else
400 *prev = abfd;
401 }
402
403 list = list->next;
404 }
405 }
406 }
407
408 /* And I added this one. */
409 void
410 ar_list (void)
411 {
412 if (!obfd)
413 {
414 fprintf (stderr, _("%s: no open output archive\n"), program_name);
415 maybequit ();
416 }
417 else
418 {
419 bfd *abfd;
420
421 outfile = stdout;
422 verbose =1 ;
423 printf (_("Current open archive is %s\n"), bfd_get_filename (obfd));
424
425 for (abfd = obfd->archive_head;
426 abfd != (bfd *)NULL;
427 abfd = abfd->next)
428 ar_directory_doer (abfd, (bfd *) NULL);
429 }
430 }
431
432 void
433 ar_end (void)
434 {
435 if (obfd)
436 {
437 bfd_cache_close (obfd);
438 unlink (bfd_get_filename (obfd));
439 }
440 }
441
442 void
443 ar_extract (struct list *list)
444 {
445 if (!obfd)
446 {
447 fprintf (stderr, _("%s: no open archive\n"), program_name);
448 maybequit ();
449 }
450 else
451 {
452 while (list)
453 {
454 /* Find this name in the archive. */
455 bfd *member = obfd->archive_head;
456 int found = 0;
457
458 while (member && !found)
459 {
460 if (FILENAME_CMP (member->filename, list->name) == 0)
461 {
462 extract_file (member);
463 found = 1;
464 }
465
466 member = member->next;
467 }
468
469 if (!found)
470 {
471 bfd_openr (list->name, 0);
472 fprintf (stderr, _("%s: can't find module file %s\n"),
473 program_name, list->name);
474 }
475
476 list = list->next;
477 }
478 }
479 }
This page took 0.039228 seconds and 4 git commands to generate.