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