arsup.c revision 78828
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 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