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