arsup.c revision 89857
1/* arsup.c - Archive support for MRI compatibility 2 Copyright 1992, 1994, 1995, 1996, 1997, 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 const char *bname = lbasename (name); 164 real_name = name; 165 /* Prepend tmp- to the beginning, to avoid file-name clashes after 166 truncation on filesystems with limited namespaces (DOS). */ 167 sprintf(tname, "%.*stmp-%s", (int) (bname - name), name, bname); 168 obfd = bfd_openw(tname, NULL); 169 170 if (!obfd) { 171 fprintf(stderr,_("%s: Can't open output archive %s\n"), program_name, 172 tname); 173 174 maybequit(); 175 } 176 else { 177 if (!t) { 178 bfd **ptr; 179 bfd *element; 180 bfd *ibfd; 181 ibfd = bfd_openr(name, NULL); 182 if (!ibfd) { 183 fprintf(stderr,_("%s: Can't open input archive %s\n"), 184 program_name, name); 185 maybequit(); 186 return; 187 } 188 if (bfd_check_format(ibfd, bfd_archive) != true) { 189 fprintf(stderr,_("%s: file %s is not an archive\n"), program_name, 190 name); 191 maybequit(); 192 return; 193 } 194 ptr = &(obfd->archive_head); 195 element = bfd_openr_next_archived_file(ibfd, NULL); 196 197 while (element) { 198 *ptr = element; 199 ptr = &element->next; 200 element = bfd_openr_next_archived_file(ibfd, element); 201 } 202 } 203 204 bfd_set_format(obfd, bfd_archive); 205 206 obfd->has_armap = 1; 207 } 208} 209 210 211static void 212ar_addlib_doer (abfd, prev) 213 bfd *abfd; 214 bfd *prev; 215{ 216 /* Add this module to the output bfd */ 217 if (prev != NULL) 218 prev->next = abfd->next; 219 abfd->next = obfd->archive_head; 220 obfd->archive_head = abfd; 221} 222 223void 224ar_addlib (name, list) 225 char *name; 226 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 disasppear */ 242 } 243} 244 245void 246DEFUN(ar_addmod, (list), 247 struct list *list) 248{ 249 if (!obfd) { 250 fprintf(stderr, _("%s: no open output archive\n"), program_name); 251 maybequit(); 252 } 253 else 254 { 255 while (list) { 256 bfd *abfd = bfd_openr(list->name, NULL); 257 if (!abfd) { 258 fprintf(stderr,_("%s: can't open file %s\n"), program_name, 259 list->name); 260 maybequit(); 261 } 262 else { 263 abfd->next = obfd->archive_head; 264 obfd->archive_head = abfd; 265 } 266 list = list->next; 267 } 268 } 269} 270 271 272 273void 274DEFUN_VOID(ar_clear) 275{ 276if (obfd) 277 obfd->archive_head = 0; 278} 279 280void 281DEFUN(ar_delete, (list), 282 struct list *list) 283{ 284 if (!obfd) { 285 fprintf(stderr, _("%s: no open output archive\n"), program_name); 286 maybequit(); 287 } 288 else 289 { 290 while (list) { 291 /* Find this name in the archive */ 292 bfd *member = obfd->archive_head; 293 bfd **prev = &(obfd->archive_head); 294 int found = 0; 295 while (member) { 296 if (FILENAME_CMP(member->filename, list->name) == 0) { 297 *prev = member->next; 298 found = 1; 299 } 300 else { 301 prev = &(member->next); 302 } 303 member = member->next; 304 } 305 if (!found) { 306 fprintf(stderr,_("%s: can't find module file %s\n"), program_name, 307 list->name); 308 maybequit(); 309 } 310 list = list->next; 311 } 312 } 313} 314 315 316void 317DEFUN_VOID(ar_save) 318{ 319 320 if (!obfd) { 321 fprintf(stderr, _("%s: no open output archive\n"), program_name); 322 maybequit(); 323 } 324 else { 325 char *ofilename = xstrdup (bfd_get_filename (obfd)); 326 bfd_close(obfd); 327 328 rename (ofilename, real_name); 329 obfd = 0; 330 free(ofilename); 331 } 332} 333 334 335 336void 337DEFUN(ar_replace, (list), 338 struct list *list) 339{ 340 if (!obfd) { 341 fprintf(stderr, _("%s: no open output archive\n"), program_name); 342 maybequit(); 343 } 344 else 345 { 346 while (list) { 347 /* Find this name in the archive */ 348 bfd *member = obfd->archive_head; 349 bfd **prev = &(obfd->archive_head); 350 int found = 0; 351 while (member) 352 { 353 if (FILENAME_CMP(member->filename, list->name) == 0) 354 { 355 /* Found the one to replace */ 356 bfd *abfd = bfd_openr(list->name, 0); 357 if (!abfd) 358 { 359 fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name); 360 maybequit(); 361 } 362 else { 363 *prev = abfd; 364 abfd->next = member->next; 365 found = 1; 366 } 367 } 368 else { 369 prev = &(member->next); 370 } 371 member = member->next; 372 } 373 if (!found) { 374 bfd *abfd = bfd_openr(list->name, 0); 375 fprintf(stderr,_("%s: can't find module file %s\n"), program_name, 376 list->name); 377 if (!abfd) 378 { 379 fprintf(stderr, _("%s: can't open file %s\n"), program_name, list->name); 380 maybequit(); 381 } 382 else 383 { 384 *prev = abfd; 385 } 386 } 387 388 list = list->next; 389 } 390 } 391} 392 393/* And I added this one */ 394void 395DEFUN_VOID(ar_list) 396{ 397 if (!obfd) 398 { 399 fprintf(stderr, _("%s: no open output archive\n"), program_name); 400 maybequit(); 401 } 402 else { 403 bfd *abfd; 404 outfile = stdout; 405 verbose =1 ; 406 printf(_("Current open archive is %s\n"), bfd_get_filename (obfd)); 407 for (abfd = obfd->archive_head; 408 abfd != (bfd *)NULL; 409 abfd = abfd->next) 410 { 411 ar_directory_doer (abfd, (bfd *) NULL); 412 } 413 } 414} 415 416 417void 418DEFUN_VOID(ar_end) 419{ 420 if (obfd) 421 { 422 fclose((FILE *)(obfd->iostream)); 423 unlink(bfd_get_filename (obfd)); 424 } 425} 426void 427DEFUN(ar_extract,(list), 428 struct list *list) 429{ 430 if (!obfd) 431 { 432 433 fprintf(stderr, _("%s: no open archive\n"), program_name); 434 maybequit(); 435 } 436 else 437 { 438 while (list) { 439 /* Find this name in the archive */ 440 bfd *member = obfd->archive_head; 441 int found = 0; 442 while (member && !found) 443 { 444 if (FILENAME_CMP(member->filename, list->name) == 0) 445 { 446 extract_file(member); 447 found = 1; 448 } 449 450 member = member->next; 451 } 452 if (!found) { 453 bfd_openr(list->name, 0); 454 fprintf(stderr,_("%s: can't find module file %s\n"), program_name, 455 list->name); 456 457 } 458 list = list->next; 459 } 460 } 461} 462