]> Git Repo - binutils.git/blobdiff - binutils/ar.c
* mips-dis.c, z8k-dis.c: Converted to use interface defined in
[binutils.git] / binutils / ar.c
index f37713e25fdc60b6be4abd5aee57376835b814ae..d034ab2d6cc6d9b33e83969579151cdf3c918894 100644 (file)
@@ -1,5 +1,5 @@
 /* ar.c - Archive modify and extract.
-   Copyright (C) 1991 Free Software Foundation, Inc.
+   Copyright 1991, 1992 Free Software Foundation, Inc.
 
 This file is part of GNU Binutils.
 
@@ -26,40 +26,63 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 */
 #include "bfd.h"
 #include "sysdep.h"
-#include "ar.h"
+#include "bucomm.h"
+#include "aout/ar.h"
+#include "../bfd/libbfd.h"
+#include "arsup.h"
 #include <stdio.h>
+#ifdef POSIX_UTIME
+#include <utime.h>
+#else /* ! POSIX_UTIME */
+#ifdef USE_UTIME
+#include <time.h>
+#else /* ! USE_UTIME */
 #include <sys/time.h>
+#endif /* ! USE_UTIME */
+#endif /* ! POSIX_UTIME */
 #include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
 #define BUFSIZE 8192
-/* FIXME: Not great to have these here.  Should they be exported or not? */
-PROTO(size_t, bfd_read, (void *ptr, size_t size, size_t nitems, bfd * abfd));
-PROTO(size_t, bfd_write, (void *ptr, size_t size, size_t nitems, bfd * abfd));
-/* PROTO (void, open_inarch, (char *archive_filename)); */
-#ifdef __STDC__
-static void     open_inarch(char *archive_filename);
-#else
-static void     open_inarch();
-#endif                         /* __STDC__ */
-
-PROTO(void, map_over_members, (void (*function) (), char **files, int count));
-PROTO(void, print_contents, (bfd * member));
-PROTO(void, extract_file, (bfd * abfd));
-PROTO(void, delete_members, (char **files_to_delete));
-PROTO(void, do_quick_append, (char *archive_filename, char **files_to_append));
-PROTO(void, move_members, (char **files_to_move));
-PROTO(void, replace_members, (char **files_to_replace));
-PROTO(void, print_descr, (bfd * abfd));
-PROTO(void, ranlib_only, (char *archname));
+
+/* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
+
+struct ar_hdr *
+bfd_special_undocumented_glue PARAMS ((bfd *abfd, char *filename));
+
+/* Forward declarations */
+
+static void
+print_contents PARAMS ((bfd * member));
+
+static void
+delete_members PARAMS ((char **files_to_delete));
+
+static void
+do_quick_append PARAMS ((char *archive_filename, char **files_to_append));
+
+static void
+move_members PARAMS ((char **files_to_move));
+
+static void
+replace_members PARAMS ((char **files_to_replace));
+
+static void
+print_descr PARAMS ((bfd * abfd));
+
+static void
+ranlib_only PARAMS ((char *archname));
 
 /** Globals and flags */
 
 char           *program_name = NULL;
-bfd             bogus_archive;
 bfd            *inarch;                /* The input arch we're manipulating */
 
+int mri_mode;
 /* This flag distinguishes between ar and ranlib:
-   1 means this is 'ranlib'; -1 means this is 'ar'.
-   0 means if we should use argv[0] to decide. */
+   1 means this is 'ranlib'; 0 means this is 'ar'.
+   -1 means if we should use argv[0] to decide. */
 extern int is_ranlib;
 /* Nonzero means don't warn about creating the archive file if necessary.  */
 int             silent_create = 0;
@@ -114,10 +137,72 @@ enum pos {
        }
 #endif
 
+int interactive = 0;
+void
+DEFUN_VOID(mri_emul)
+{
+  interactive = isatty(fileno(stdin)) ;
+  yyparse();
+}
+
+/*
+   If count is 0, then function is called once on each entry. if nonzero,
+   count is the length of the files chain; function is called on each entry
+   whose name matches one in files
+*/
+void
+DEFUN(map_over_members,(function, files, count),
+      void            (*function) () AND
+      char          **files AND
+      int             count)
+{
+  bfd            *head;
+
+  if (count == 0) {
+    for (head = inarch->next; head; head = head->next)
+     function(head);
+    return;
+  }
+  /*
+    This may appear to be a baroque way of accomplishing what we want.
+    however we have to iterate over the filenames in order to notice where
+    a filename is requested but does not exist in the archive.  Ditto
+    mapping over each file each time -- we want to hack multiple
+    references.
+    */
+
+  for (; count > 0; files++, count--) {
+    boolean         found = false;
+    for (head = inarch->next; head; head = head->next)
+    {
+      if (head->filename == NULL)
+      {
+       /* Some archive formats don't get the filenames filled in
+          'till the elements are opened */
+       struct stat buf;
+       bfd_stat_arch_elt(head, &buf);
+      }
+      if ((head->filename != NULL) &&
+         (!strcmp(*files, head->filename))) {
+       found = true;
+       function(head);
+      }
+    }
+    if (!found)
+     fprintf(stderr, "No entry %s in archive.\n", *files);
+  }
+}
 
 
 boolean operation_alters_arch = false;
 
+void
+do_show_version ()
+{
+  extern char *program_version;
+  printf ("%s version %s\n", program_name, program_version);
+}
+
 /*
    The option parsing should be in its own function.  It will be when I have
    getopt working.
@@ -127,195 +212,219 @@ main(argc, argv)
     int             argc;
     char          **argv;
 {
-    char           *arg_ptr;
-    char            c;
-    enum {
-       none = 0, delete, replace, print_table,
-       print_files, extract, move, quick_append
-    }               operation = none;
-    int             arg_index;
-    char          **files;
-    char           *inarch_filename;
-    char           *temp;
-
-    bfd_init();
-
+  char           *arg_ptr;
+  char            c;
+  enum {
+    none = 0, delete, replace, print_table,
+    print_files, extract, move, quick_append
+  }               operation = none;
+  int             arg_index;
+  char          **files;
+  char           *inarch_filename;
+  char           *temp;
+  int           show_version;
+
+  bfd_init();
+  show_version = 0;
 #ifdef GNU960
-    check_v960( argc, argv );
-    default_target = bfd_make_targ_name(BFD_COFF_FORMAT,HOST_BYTE_ORDER_BIG_P);
+  check_v960( argc, argv );
+  default_target = bfd_make_targ_name(BFD_COFF_FORMAT,HOST_BYTE_ORDER_BIG_P);
 #endif
 
-    program_name = argv[0];
+  program_name = argv[0];
 
-    temp = strrchr(program_name, '/');
-    if (temp == (char *) NULL)
-       temp = program_name;    /* shouldn't happen, but... */
-    else
-       ++temp;
-    if (is_ranlib > 0 || (is_ranlib == 0 && strcmp(temp, "ranlib") == 0)) {
-       if (argc < 2)
-           fatal("Too few command arguments.");
-       ranlib_only(argv[1]);
+  temp = strrchr(program_name, '/');
+  if (temp == (char *) NULL)
+   temp = program_name;                /* shouldn't happen, but... */
+  else
+   ++temp;
+  if (is_ranlib > 0 || (is_ranlib < 0 && strcmp(temp, "ranlib") == 0)) {
+    if (argc < 2)
+     fatal("Too few command arguments.");
+    arg_ptr = argv[1];
+    if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "-v") == 0) {
+      do_show_version();
+      if (argc == 2)
+       exit(0);
+      arg_ptr = argv[2];
     }
+    ranlib_only(arg_ptr);
+  }
 
+  if (argc == 2 && strcmp(argv[1],"-M") == 0) {
+    mri_emul();
+    exit(0);
+  }
+
+  if (argc < 2)
+   fatal("Too few command arguments.");
+
+  arg_ptr = argv[1];
+
+  if (*arg_ptr == '-')
+   ++arg_ptr;                  /* compatibility */
+
+  while (c = *arg_ptr++) {
+    switch (c) {
+     case 'd':
+     case 'm':
+     case 'p':
+     case 'q':
+     case 'r':
+     case 't':
+     case 'x':
+      if (operation != none)
+       fatal("two different operation switches specified");
+      switch (c) {
+       case 'd':
+       operation = delete;
+       operation_alters_arch = true;
+       break;
+       case 'm':
+       operation = move;
+       operation_alters_arch = true;
+       break;
+       case 'p':
+       operation = print_files;
+       break;
+       case 'q':
+       operation = quick_append;
+       operation_alters_arch = true;
+       break;
+       case 'r':
+       operation = replace;
+       operation_alters_arch = true;
+       break;
+       case 't':
+       operation = print_table;
+       break;
+       case 'x':
+       operation = extract;
+       break;
+      }
+     case 'l':
+      break;
+     case 'c':
+      silent_create = 1;
+      break;
+     case 'o':
+      preserve_dates = 1;
+      break;
+     case 'V':
+      show_version = true;
+      break;
+     case 's':
+      write_armap = true;
+      break;
+     case 'u':
+      newer_only = 1;
+      break;
+     case 'v':
+      verbose = 1;
+      break;
+     case 'a':
+      postype = pos_after;
+      break;
+     case 'b':
+      postype = pos_before;
+      break;
+     case 'i':
+      postype = pos_before;
+      break;
+     case 'M':
+
+      mri_mode = 1;
+      break;
+     default:
+      fatal("invalid option %c", c);
+    }
+  }
 
-    if (argc < 3)
-       fatal("Too few command arguments.");
-
-    arg_ptr = argv[1];
+  if (show_version)
+     do_show_version();
 
-    if (*arg_ptr == '-')
-       ++arg_ptr;              /* compatibility */
-
-    while (c = *arg_ptr++) {
-       switch (c) {
-       case 'd':
-       case 'm':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 't':
-       case 'x':
-           if (operation != none)
-               fatal("two different operation switches specified");
-           switch (c) {
-           case 'd':
-               operation = delete;
-               operation_alters_arch = true;
-               break;
-           case 'm':
-               operation = move;
-               operation_alters_arch = true;
-               break;
-           case 'p':
-               operation = print_files;
-               break;
-           case 'q':
-               operation = quick_append;
-               operation_alters_arch = true;
-               break;
-           case 'r':
-               operation = replace;
-               operation_alters_arch = true;
-               break;
-           case 't':
-               operation = print_table;
-               break;
-           case 'x':
-               operation = extract;
-               break;
-           }
-       case 'l':
-           break;
-       case 'c':
-           silent_create = 1;
-           break;
-       case 'o':
-           preserve_dates = 1;
-           break;
-       case 's':
-           write_armap = true;
-           break;
-       case 'u':
-           newer_only = 1;
-           break;
-       case 'v':
-           verbose = 1;
-           break;
-       case 'a':
-           postype = pos_after;
-           break;
-       case 'b':
-           postype = pos_before;
-           break;
-       case 'i':
-           postype = pos_before;
-           break;
-       default:
-           fatal("invalid option %c", c);
-       }
-    }
+  if (argc < 3)
+    if (show_version)
+       exit(0);
+    else
+      fatal("Too few command arguments.");
 
-    if (operation == none && write_armap)
-       ranlib_only(argv[2]);
+  if (mri_mode) {
+    mri_emul();
+  }
+  else {
+    if ((operation == none || operation == print_table) 
+       && write_armap == true)
+     ranlib_only(argv[2]);
 
     if (operation == none)
-       fatal("no operation specified");
+     fatal("no operation specified");
 
     if (newer_only && operation != replace)
-       fatal("'u' only meaningful with 'r' option.");
+     fatal("'u' only meaningful with 'r' option.");
 
     arg_index = 2;
 
     if (postype != pos_default)
-       posname = argv[arg_index++];
+     posname = argv[arg_index++];
 
     inarch_filename = argv[arg_index++];
 
     if (arg_index < argc) {
-       files = argv + arg_index;
-       while (arg_index < argc)
-           if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
-               ignore_symdef = 1;
-               break;
-           }
+      files = argv + arg_index;
+      while (arg_index < argc)
+       if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
+        ignore_symdef = 1;
+        break;
+       }
     }
     else
-       files = NULL;
+     files = NULL;
 
     if (operation == quick_append) {
-       if (files != NULL)
-           do_quick_append(inarch_filename, files);
-       exit(0);
+      if (files != NULL)
+       do_quick_append(inarch_filename, files);
+      exit(0);
     }
 
 
     open_inarch(inarch_filename);
-    /*
-       If we have no archive, and we've been asked to replace then create one
-    */
-#if 0
-    if (operation == replace && inarch == &bogus_archive) {
-       silent_create = 1;
-       do_quick_append(inarch_filename, 0);
-       open_inarch(inarch_filename);
-    }
-#endif
+
     switch (operation) {
 
-    case print_table:
-       map_over_members(print_descr, files, argc - 3);
-       break;
+     case print_table:
+      map_over_members(print_descr, files, argc - 3);
+      break;
 
-    case print_files:
-       map_over_members(print_contents, files, argc - 3);
-       break;
+     case print_files:
+      map_over_members(print_contents, files, argc - 3);
+      break;
 
-    case extract:
-       map_over_members(extract_file, files, argc - 3);
-       break;
+     case extract:
+      map_over_members(extract_file, files, argc - 3);
+      break;
 
-    case delete:
-       if (files != NULL)
-           delete_members(files);
-       break;
+     case delete:
+      if (files != NULL)
+       delete_members(files);
+      break;
 
-    case move:
-       if (files != NULL)
-           move_members(files);
-       break;
+     case move:
+      if (files != NULL)
+       move_members(files);
+      break;
 
-    case replace:
-       if (files != NULL || write_armap)
-           replace_members(files);
-       break;
+     case replace:
+      if (files != NULL || write_armap)
+       replace_members(files);
+      break;
 
-       /* Shouldn't happen! */
-    default:
-       fprintf(stderr, "Sorry; this option not implemented.\n");
+      /* Shouldn't happen! */
+     default:
+      fprintf(stderr, "Sorry; this option not implemented.\n");
     }
-
-    return (0);
+  }
+  return (0);
 }                              /* main() */
 
 static
@@ -332,7 +441,7 @@ char *file;
     return filename;
 }
 
-static void
+int 
 open_inarch(archive_filename)
     char           *archive_filename;
 {
@@ -346,103 +455,49 @@ open_inarch(archive_filename)
        if (!operation_alters_arch) {
          fprintf (stderr, "%s: %s not found.\n", program_name,
                   archive_filename);
-         exit (1);
+         maybequit();
+         return 0;
        }       
-       if (!silent_create)
-           fprintf(stderr,
-                   "%s: creating %s\n", program_name, archive_filename);
-
-       inarch = &bogus_archive;
-       inarch->filename = archive_filename;
-       inarch->has_armap = true;
 
+       /* This routine is one way to forcibly create the archive. */
+       do_quick_append(archive_filename, 0);
     }
-    else {
+
 #ifdef GNU960
-       inarch = bfd_openr(archive_filename, default_target);
+    inarch = bfd_openr(archive_filename, default_target);
 #else
-       inarch = bfd_openr(archive_filename, NULL);
+    inarch = bfd_openr(archive_filename, NULL);
 #endif
-       if (inarch == NULL) {
-    bloser:
-           bfd_perror(archive_filename);
-           exit(1);
-       }
+    if (inarch == NULL) {
+      bloser:
+       bfd_perror(archive_filename);
+       exit(1);
+    }
 
-       if (bfd_check_format(inarch, bfd_archive) != true)
-           fatal("File %s is not an archive.", archive_filename);
+    if (bfd_check_format(inarch, bfd_archive) != true)
+       fatal("File %s is not an archive.", archive_filename);
 #ifdef GNU960
-       gnu960_verify_target(inarch);   /* Exits on failure */
+    gnu960_verify_target(inarch);      /* Exits on failure */
 #endif
-       last_one = &(inarch->next);
-       /* Read all the contents right away, regardless. */
-       for (next_one = bfd_openr_next_archived_file(inarch, NULL);
-            next_one;
-            next_one = bfd_openr_next_archived_file(inarch, next_one)) {
-           *last_one = next_one;
-           last_one = &next_one->next;
-       }
-       *last_one = (bfd *) NULL;
-       if (bfd_error != no_more_archived_files)
-           goto bloser;
+    last_one = &(inarch->next);
+    /* Read all the contents right away, regardless. */
+    for (next_one = bfd_openr_next_archived_file(inarch, NULL);
+        next_one;
+        next_one = bfd_openr_next_archived_file(inarch, next_one)) {
+       *last_one = next_one;
+       last_one = &next_one->next;
     }
+    *last_one = (bfd *) NULL;
+    if (bfd_error != no_more_archived_files)
+       goto bloser;
+    return 1;
 }
 
 
 
-/*
-   If count is 0, then function is called once on each entry. if nonzero,
-   count is the length of the files chain; function is called on each entry
-   whose name matches one in files
-*/
-void
-map_over_members(function, files, count)
-    void            (*function) ();
-    char          **files;
-    int             count;
-{
-    bfd            *head;
-
-
-
 
-    if (count == 0) {
-       for (head = inarch->next; head; head = head->next)
-           function(head);
-       return;
-    }
-    /*
-       This may appear to be a baroque way of accomplishing what we want.
-       however we have to iterate over the filenames in order to notice where
-       a filename is requested but does not exist in the archive.  Ditto
-       mapping over each file each time -- we want to hack multiple
-       references.
-    */
-
-    for (; count > 0; files++, count--) {
-       boolean         found = false;
-       for (head = inarch->next; head; head = head->next)
-           if ((head->filename != NULL) &&
-               (!strcmp(*files, head->filename))) {
-               found = true;
-               function(head);
-           }
-       if (!found)
-           fprintf(stderr, "No entry %s in archive.\n", *files);
-    }
-}
-
-
-/* Things which are interesting to map over all or some of the files: */
 
-void
-print_descr(abfd)
-    bfd            *abfd;
-{
-    print_arelt_descr(abfd, verbose);
-}
-
-void
+static void
 print_contents(abfd)
     bfd            *abfd;
 {
@@ -511,7 +566,7 @@ extract_file(abfd)
     ostream = 0;
     if (size == 0) {
       /* Seems like an abstraction violation, eh?  Well it's OK! */
-      ostream = fopen(abfd->filename, "w");
+      ostream = fopen(abfd->filename, FOPEN_WB);
       if (!ostream) {
        perror(abfd->filename);
        exit(1);
@@ -529,7 +584,7 @@ extract_file(abfd)
        /* See comment above; this saves disk arm motion */
        if (!ostream) {
            /* Seems like an abstraction violation, eh?  Well it's OK! */
-           ostream = fopen(abfd->filename, "w");
+           ostream = fopen(abfd->filename, FOPEN_WB);
            if (!ostream) {
                perror(abfd->filename);
                exit(1);
@@ -543,30 +598,33 @@ extract_file(abfd)
     chmod(abfd->filename, buf.st_mode);
 
     if (preserve_dates) {
-#ifdef USG
+#ifdef POSIX_UTIME
+        struct utimbuf tb;
+       tb.actime = buf.st_mtime;
+       tb.modtime = buf.st_mtime;
+       utime(abfd->filename, tb);      /* FIXME check result */
+#else /* ! POSIX_UTIME */
+#ifdef USE_UTIME
        long            tb[2];
        tb[0] = buf.st_mtime;
        tb[1] = buf.st_mtime;
        utime(abfd->filename, tb);      /* FIXME check result */
-#else
+#else /* ! USE_UTIME */
        struct timeval  tv[2];
        tv[0].tv_sec = buf.st_mtime;
        tv[0].tv_usec = 0;
        tv[1].tv_sec = buf.st_mtime;
        tv[1].tv_usec = 0;
        utimes(abfd->filename, tv);     /* FIXME check result */
-#endif
+#endif /* ! USE_UTIME */
+#endif /* ! POSIX_UTIME */
     }
 }
 
 
 /* Just do it quickly; don't worry about dups, armap, or anything like that */
 
-/* This is ugly! XXX */
-
-PROTO(struct ar_hdr *, bfd_special_undocumented_glue, (bfd *abfd, char *filename));
-
-void
+static void
 do_quick_append(archive_filename, files_to_append)
     char           *archive_filename;
     char          **files_to_append;
@@ -589,7 +647,7 @@ do_quick_append(archive_filename, files_to_append)
     }
 
 
-    ofile = fopen(archive_filename, "a+");
+    ofile = fopen(archive_filename, FOPEN_AUB);
     if (ofile == NULL) {
        perror(program_name);
        exit(1);
@@ -630,7 +688,7 @@ do_quick_append(archive_filename, files_to_append)
 
        BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
 
-       ifile = fopen(*files_to_append, "r");
+       ifile = fopen(*files_to_append, FOPEN_RB);
        if (ifile == NULL)
            bfd_perror(program_name);
 
@@ -664,19 +722,12 @@ void
 write_archive()
 {
     bfd            *obfd;
-    char           *xmalloc();
     int             namelen = strlen(inarch->filename);
     char           *new_name = xmalloc(namelen + 6);
     bfd            *contents_head = inarch->next;
-#if 0
-    if (inarch == &bogus_archive) {
-       /* How can this be ? */
-       return;
-    }
-    else {
-#endif
+
        strcpy(new_name, inarch->filename);
-       strcpy(new_name + namelen, ".art");
+       strcpy(new_name + namelen, "-art");
        obfd = bfd_openw(new_name,
                 /* FIXME: violates abstraction; need a better protocol */
                         (inarch->xvec ? bfd_get_target(inarch) : NULL));
@@ -692,13 +743,13 @@ write_archive()
 
        if (!bfd_close(obfd))
            bfd_fatal(inarch->filename);
-       if (unlink(inarch->filename) != 0)
-           bfd_fatal(inarch->filename);
+
+       /* We don't care if this fails, we might be creating the
+          archive */
+       (void) unlink(inarch->filename);
+
        if (rename(new_name, inarch->filename) != 0)
            bfd_fatal(inarch->filename);
-#if 0
-    }
-#endif
 }
 
 
@@ -714,36 +765,26 @@ get_pos_bfd(contents, default_pos)
     bfd           **contents;
     enum pos        default_pos;
 {
-    bfd           **after_bfd;
-
+    bfd           **after_bfd = contents;
     enum pos        realpos = (postype == pos_default ? default_pos : postype);
-    switch (realpos) {
 
-    case pos_end:
-       after_bfd = contents;
-       while (*after_bfd) {
+    if (realpos == pos_end) {
+       while (*after_bfd)
            after_bfd = &((*after_bfd)->next);
-       }
-
-       break;
-#if 0
-    case pos_after:
-       for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
-           if (!strcpy(after_bfd->filename, posname))
-               break;
-       break;
-    case pos_before:
-       for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
-           if (after_bfd->next && (!strcpy(after_bfd->next->filename, posname)))
+    }
+    else {
+       for ( ; *after_bfd; after_bfd = &(*after_bfd)->next)
+           if (!strcmp((*after_bfd)->filename, posname)) {
+               if (realpos == pos_after)
+                   after_bfd = &(*after_bfd)->next;
                break;
-#endif
+       }
     }
-
     return after_bfd;
 }
 
 
-void
+static void
 delete_members(files_to_delete)
     char          **files_to_delete;
 {
@@ -796,7 +837,7 @@ next_file:;
 
 /* Reposition existing members within an archive */
 
-void
+static void
 move_members(files_to_move)
     char          **files_to_move;
 {
@@ -841,7 +882,7 @@ next_file:;
 
 /* Ought to default to replacing in place, but this is existing practice! */
 
-void
+static void
 replace_members(files_to_move)
     char          **files_to_move;
 {
@@ -939,7 +980,7 @@ next_file:;
     write_archive();
 }
 
-void
+static void
 ranlib_only(archname)
     char           *archname;
 {
@@ -950,3 +991,12 @@ ranlib_only(archname)
 }
 
 
+
+/* Things which are interesting to map over all or some of the files: */
+
+static void
+print_descr(abfd)
+    bfd            *abfd;
+{
+    print_arelt_descr(stdout,abfd, verbose);
+}
This page took 0.048485 seconds and 4 git commands to generate.