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