arsup.c revision 33965
1/* arsup.c - Archive support for MRI compatibility 2 Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. 3 4This file is part of GNU Binutils. 5 6This program is free software; you can redistribute it and/or modify 7it under the terms of the GNU General Public License as published by 8the Free Software Foundation; either version 2 of the License, or 9(at your option) any later version. 10 11This program is distributed in the hope that it will be useful, 12but WITHOUT ANY WARRANTY; without even the implied warranty of 13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14GNU General Public License for more details. 15 16You should have received a copy of the GNU General Public License 17along with this program; if not, write to the Free Software 18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19 20 21/* Contributed by Steve Chamberlain 22 sac@cygnus.com 23 24This file looks after requests from arparse.y, to provide the MRI 25style librarian command syntax + 1 word LIST 26 27*/ 28 29#include "bfd.h" 30#include "arsup.h" 31#include "libiberty.h" 32#include "bucomm.h" 33 34static void map_over_list 35 PARAMS ((bfd *, void (*function) (bfd *, bfd *), struct list *)); 36static void ar_directory_doer PARAMS ((bfd *, bfd *)); 37static void ar_addlib_doer PARAMS ((bfd *, bfd *)); 38 39extern int verbose; 40 41static void 42map_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 { 72 boolean found = false; 73 bfd *prev = arch; 74 75 for (head = arch->next; head; head = head->next) 76 { 77 if (head->filename != NULL 78 && strcmp (ptr->name, head->filename) == 0) 79 { 80 found = true; 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 92FILE *outfile; 93 94/*ARGSUSED*/ 95static void 96ar_directory_doer (abfd, ignore) 97 bfd *abfd; 98 bfd *ignore; 99{ 100 print_arelt_descr(outfile, abfd, verbose); 101} 102 103void 104ar_directory (ar_name, list, output) 105 char *ar_name; 106 struct list *list; 107 char *output; 108{ 109 bfd *arch; 110 111 arch = open_inarch (ar_name, (char *) NULL); 112 if (output) 113 { 114 outfile = fopen(output,"w"); 115 if (outfile == 0) 116 { 117 outfile = stdout; 118 fprintf (stderr,"Can't open file %s\n", output); 119 output = 0; 120 } 121 } 122 else 123 outfile = stdout; 124 125 map_over_list (arch, ar_directory_doer, list); 126 127 bfd_close (arch); 128 129 if (output) 130 fclose (outfile); 131} 132 133void 134DEFUN_VOID(prompt) 135{ 136 extern int interactive; 137 if (interactive) 138 { 139 printf("AR >"); 140 fflush(stdout); 141 } 142} 143 144void 145maybequit () 146{ 147 if (! interactive) 148 xexit (9); 149} 150 151 152bfd *obfd; 153char *real_name ; 154void 155DEFUN(ar_open,(name, t), 156 char *name AND 157 int t) 158 159{ 160 char *tname = (char *) xmalloc (strlen (name) + 10); 161 real_name = name; 162 sprintf(tname, "%s-tmp", name); 163 obfd = bfd_openw(tname, NULL); 164 165 if (!obfd) { 166 fprintf(stderr,"%s: Can't open output archive %s\n", program_name, 167 tname); 168 169 maybequit(); 170 } 171 else { 172 if (!t) { 173 bfd **ptr; 174 bfd *element; 175 bfd *ibfd; 176 ibfd = bfd_openr(name, NULL); 177 if (!ibfd) { 178 fprintf(stderr,"%s: Can't open input archive %s\n", 179 program_name, name); 180 maybequit(); 181 return; 182 } 183 if (bfd_check_format(ibfd, bfd_archive) != true) { 184 fprintf(stderr,"%s: file %s is not an archive\n", program_name, 185 name); 186 maybequit(); 187 return; 188 } 189 ptr = &(obfd->archive_head); 190 element = bfd_openr_next_archived_file(ibfd, NULL); 191 192 while (element) { 193 *ptr = element; 194 ptr = &element->next; 195 element = bfd_openr_next_archived_file(ibfd, element); 196 } 197 } 198 199 bfd_set_format(obfd, bfd_archive); 200 201 obfd->has_armap = 1; 202 } 203} 204 205 206static void 207ar_addlib_doer (abfd, prev) 208 bfd *abfd; 209 bfd *prev; 210{ 211 /* Add this module to the output bfd */ 212 if (prev != NULL) 213 prev->next = abfd->next; 214 abfd->next = obfd->archive_head; 215 obfd->archive_head = abfd; 216} 217 218void 219ar_addlib (name, list) 220 char *name; 221 struct list *list; 222{ 223 if (obfd == NULL) 224 { 225 fprintf (stderr, "%s: no output archive specified yet\n", program_name); 226 maybequit (); 227 } 228 else 229 { 230 bfd *arch; 231 232 arch = open_inarch (name, (char *) NULL); 233 if (arch != NULL) 234 map_over_list (arch, ar_addlib_doer, list); 235 236 /* Don't close the bfd, since it will make the elements disasppear */ 237 } 238} 239 240void 241DEFUN(ar_addmod, (list), 242 struct list *list) 243{ 244 if (!obfd) { 245 fprintf(stderr, "%s: no open output archive\n", program_name); 246 maybequit(); 247 } 248 else 249 { 250 while (list) { 251 bfd *abfd = bfd_openr(list->name, NULL); 252 if (!abfd) { 253 fprintf(stderr,"%s: can't open file %s\n", program_name, 254 list->name); 255 maybequit(); 256 } 257 else { 258 abfd->next = obfd->archive_head; 259 obfd->archive_head = abfd; 260 } 261 list = list->next; 262 } 263 } 264} 265 266 267 268void 269DEFUN_VOID(ar_clear) 270{ 271if (obfd) 272 obfd->archive_head = 0; 273} 274 275void 276DEFUN(ar_delete, (list), 277 struct list *list) 278{ 279 if (!obfd) { 280 fprintf(stderr, "%s: no open output archive\n", program_name); 281 maybequit(); 282 } 283 else 284 { 285 while (list) { 286 /* Find this name in the archive */ 287 bfd *member = obfd->archive_head; 288 bfd **prev = &(obfd->archive_head); 289 int found = 0; 290 while (member) { 291 if (strcmp(member->filename, list->name) == 0) { 292 *prev = member->next; 293 found = 1; 294 } 295 else { 296 prev = &(member->next); 297 } 298 member = member->next; 299 } 300 if (!found) { 301 fprintf(stderr,"%s: can't find module file %s\n", program_name, 302 list->name); 303 maybequit(); 304 } 305 list = list->next; 306 } 307 } 308} 309 310 311void 312DEFUN_VOID(ar_save) 313{ 314 315 if (!obfd) { 316 fprintf(stderr, "%s: no open output archive\n", program_name); 317 maybequit(); 318 } 319 else { 320 char *ofilename = xstrdup (bfd_get_filename (obfd)); 321 bfd_close(obfd); 322 323 rename (ofilename, real_name); 324 obfd = 0; 325 free(ofilename); 326 } 327} 328 329 330 331void 332DEFUN(ar_replace, (list), 333 struct list *list) 334{ 335 if (!obfd) { 336 fprintf(stderr, "%s: no open output archive\n", program_name); 337 maybequit(); 338 } 339 else 340 { 341 while (list) { 342 /* Find this name in the archive */ 343 bfd *member = obfd->archive_head; 344 bfd **prev = &(obfd->archive_head); 345 int found = 0; 346 while (member) 347 { 348 if (strcmp(member->filename, list->name) == 0) 349 { 350 /* Found the one to replace */ 351 bfd *abfd = bfd_openr(list->name, 0); 352 if (!abfd) 353 { 354 fprintf(stderr, "%s: can't open file %s\n", program_name, list->name); 355 maybequit(); 356 } 357 else { 358 *prev = abfd; 359 abfd->next = member->next; 360 found = 1; 361 } 362 } 363 else { 364 prev = &(member->next); 365 } 366 member = member->next; 367 } 368 if (!found) { 369 bfd *abfd = bfd_openr(list->name, 0); 370 fprintf(stderr,"%s: can't find module file %s\n", program_name, 371 list->name); 372 if (!abfd) 373 { 374 fprintf(stderr, "%s: can't open file %s\n", program_name, list->name); 375 maybequit(); 376 } 377 else 378 { 379 *prev = abfd; 380 } 381 } 382 383 list = list->next; 384 } 385 } 386} 387 388/* And I added this one */ 389void 390DEFUN_VOID(ar_list) 391{ 392 if (!obfd) 393 { 394 fprintf(stderr, "%s: no open output archive\n", program_name); 395 maybequit(); 396 } 397 else { 398 bfd *abfd; 399 outfile = stdout; 400 verbose =1 ; 401 printf("Current open archive is %s\n", bfd_get_filename (obfd)); 402 for (abfd = obfd->archive_head; 403 abfd != (bfd *)NULL; 404 abfd = abfd->next) 405 { 406 ar_directory_doer (abfd, (bfd *) NULL); 407 } 408 } 409} 410 411 412void 413DEFUN_VOID(ar_end) 414{ 415 if (obfd) 416 { 417 fclose((FILE *)(obfd->iostream)); 418 unlink(bfd_get_filename (obfd)); 419 } 420} 421void 422DEFUN(ar_extract,(list), 423 struct list *list) 424{ 425 if (!obfd) 426 { 427 428 fprintf(stderr, "%s: no open archive\n", program_name); 429 maybequit(); 430 } 431 else 432 { 433 while (list) { 434 /* Find this name in the archive */ 435 bfd *member = obfd->archive_head; 436 int found = 0; 437 while (member && !found) 438 { 439 if (strcmp(member->filename, list->name) == 0) 440 { 441 extract_file(member); 442 found = 1; 443 } 444 445 member = member->next; 446 } 447 if (!found) { 448 bfd_openr(list->name, 0); 449 fprintf(stderr,"%s: can't find module file %s\n", program_name, 450 list->name); 451 452 } 453 list = list->next; 454 } 455 } 456} 457