Wed Apr 15 14:33:07 1992 Steve Chamberlain (sac@thepub.cygnus.com)
authorSteve Chamberlain <sac@cygnus>
Wed, 15 Apr 1992 21:36:37 +0000 (21:36 +0000)
committerSteve Chamberlain <sac@cygnus>
Wed, 15 Apr 1992 21:36:37 +0000 (21:36 +0000)
* arsup.c, arsup.h, arparse.y, arlex.l: support for archive
scripting language.

binutils/.Sanitize
binutils/ar.c
binutils/arlex.l [new file with mode: 0644]
binutils/arparse.y [new file with mode: 0644]
binutils/arsup.c [new file with mode: 0644]
binutils/arsup.h [new file with mode: 0644]

index 074f50c5e6c4969b232cb99043daf05d719e2855..4cc1130f36caa89867fe8b08a756c04dee83f082 100644 (file)
@@ -36,6 +36,10 @@ alloca.c
 am29k-pinsn.c
 ar.1
 ar.c
+arlex.l
+arsup.c
+arsup.h
+arparse.y
 binutils.texi
 bucomm.c
 bucomm.h
index cdee7589c7f2011dfa826024455e9c484872bf07..244a15a1bd300778117b4754f3b85b9ffdb910eb 100644 (file)
@@ -29,18 +29,19 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "bucomm.h"
 #include "aout/ar.h"
 #include "../bfd/libbfd.h"
+#include "arsup.h"
 #include <stdio.h>
+#ifdef USG
+#include <time.h>
+#else
 #include <sys/time.h>
+#endif
 #include <errno.h>
 #define BUFSIZE 8192
-/* 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));
+void EXFUN(open_inarch,(char *archive_filename));
+
+
 PROTO(void, print_contents, (bfd * member));
 PROTO(void, extract_file, (bfd * abfd));
 PROTO(void, delete_members, (char **files_to_delete));
@@ -56,6 +57,7 @@ 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'; 0 means this is 'ar'.
    -1 means if we should use argv[0] to decide. */
@@ -113,6 +115,52 @@ 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) &&
+        (!strcmp(*files, head->filename))) {
+       found = true;
+       function(head);
+     }
+    if (!found)
+     fprintf(stderr, "No entry %s in archive.\n", *files);
+  }
+}
 
 
 boolean operation_alters_arch = false;
@@ -126,196 +174,207 @@ 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;
+
+  bfd_init();
+verbose = 1;
 #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];
-
-    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)
-           bfd_fatal("Too few command arguments.");
-       ranlib_only(argv[1]);
-    }
-
-
-    if (argc < 3)
-       bfd_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 '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);
-       }
+  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)
+     bfd_fatal("Too few command arguments.");
+    ranlib_only(argv[1]);
+  }
+
+  if (argc == 2 && strcmp(argv[1],"-M") == 0) {
+    mri_emul();
+    exit(0);
+  }
+  if (argc < 3)
+   bfd_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 '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 (mri_mode) {
+    mri_emul();
+  }
+  else {
     if ((operation == none || operation == print_table) 
        && write_armap == true)
-       ranlib_only(argv[2]);
+     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 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);
+      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 +391,7 @@ char *file;
     return filename;
 }
 
-static void
+ void
 open_inarch(archive_filename)
     char           *archive_filename;
 {
@@ -346,7 +405,8 @@ open_inarch(archive_filename)
        if (!operation_alters_arch) {
          fprintf (stderr, "%s: %s not found.\n", program_name,
                   archive_filename);
-         exit (1);
+         maybequit();
+         return ;
        }       
        if (!silent_create)
            fprintf(stderr,
@@ -390,47 +450,6 @@ open_inarch(archive_filename)
 
 
 
-/*
-   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);
-    }
-}
 
 
 void
@@ -502,7 +521,7 @@ extract_file(abfd)
     ostream = 0;
     if (size == 0) {
       /* Seems like an abstraction violation, eh?  Well it's OK! */
-      ostream = fopen(abfd->filename, "wb");
+      ostream = fopen(abfd->filename, FOPEN_WB);
       if (!ostream) {
        perror(abfd->filename);
        exit(1);
@@ -520,7 +539,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, "wb");
+           ostream = fopen(abfd->filename, FOPEN_WB);
            if (!ostream) {
                perror(abfd->filename);
                exit(1);
@@ -580,7 +599,7 @@ do_quick_append(archive_filename, files_to_append)
     }
 
 
-    ofile = fopen(archive_filename, "a+b");
+    ofile = fopen(archive_filename, FOPEN_AUB);
     if (ofile == NULL) {
        perror(program_name);
        exit(1);
@@ -621,7 +640,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, "rb");
+       ifile = fopen(*files_to_append, FOPEN_RB);
        if (ifile == NULL)
            bfd_perror(program_name);
 
@@ -940,5 +959,8 @@ void
 print_descr(abfd)
     bfd            *abfd;
 {
-    print_arelt_descr(abfd, verbose);
+    print_arelt_descr(stdout,abfd, verbose);
 }
+
+
+
diff --git a/binutils/arlex.l b/binutils/arlex.l
new file mode 100644 (file)
index 0000000..47f8361
--- /dev/null
@@ -0,0 +1,77 @@
+%{
+/* arlex.l - Strange script language lexer */
+
+/*   Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Contributed by Steve Chamberlain
+                 sac@cygnus.com
+
+*/
+#define DONTDECLARE_MALLOC
+#include <ansidecl.h>
+#include <sysdep.h>
+#include "arparse.h"
+int linenumber;
+%}
+%%
+
+"ADDLIB"       { return ADDLIB; }
+"ADDMOD"       { return ADDMOD; }
+"CLEAR"        { return CLEAR; }
+"CREATE"       { return CREATE; }
+"DELETE"       { return DELETE; }
+"DIRECTORY"    { return DIRECTORY; }
+"END"          { return END; }
+"EXTRACT"      { return EXTRACT; }
+"FULLDIR"      { return FULLDIR; }
+"HELP"         { return HELP; }
+"LIST"         { return LIST; }
+"OPEN"         { return OPEN; }
+"REPLACE"      { return REPLACE; }
+"VERBOSE"      { return VERBOSE; }
+"SAVE"         { return SAVE; }
+"addlib"       { return ADDLIB; }
+"addmod"       { return ADDMOD; }
+"clear"        { return CLEAR; }
+"create"       { return CREATE; }
+"delete"       { return DELETE; }
+"directory"    { return DIRECTORY; }
+"end"          { return END; }
+"extract"      { return EXTRACT; }
+"fulldir"      { return FULLDIR; }
+"help"         { return HELP; }
+"list"         { return LIST; }
+"open"         { return OPEN; }
+"replace"      { return REPLACE; }
+"verbose"      { return VERBOSE; }
+"save"         { return SAVE; }
+"+\n"           { linenumber ++; }
+"("             { return '('; }
+")"             { return ')'; }
+","             { return ','; }
+[A-Za-z0-9/$:.\-]+  {  
+               yylval.name =  strdup(yytext);
+               return FILENAME;
+               }
+"*".*          { }
+";".*          { }
+" "            { }
+"\n"            { linenumber ++; return NEWLINE; }     
+
diff --git a/binutils/arparse.y b/binutils/arparse.y
new file mode 100644 (file)
index 0000000..dccdf8e
--- /dev/null
@@ -0,0 +1,197 @@
+%{
+/* arparse.y - Stange script language parser */
+
+/*   Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Contributed by Steve Chamberlain
+                 sac@cygnus.com
+
+*/
+#define DONTDECLARE_MALLOC
+#include "bfd.h"
+#include <sysdep.h>
+#include "arsup.h"
+extern int interactive;
+extern bfd *inarch;
+extern int verbose;
+void (*command)();
+FILE *listing;
+%}
+
+%union {
+  char *name;
+struct list *list ;
+
+};
+
+%token NEWLINE
+%token VERBOSE
+%token <name> FILENAME
+%token ADDLIB
+%token LIST
+%token ADDMOD
+%token CLEAR
+%token CREATE
+%token DELETE
+%token DIRECTORY
+%token END
+%token EXTRACT
+%token FULLDIR
+%token HELP
+%token QUIT
+%token REPLACE
+%token SAVE
+%token OPEN
+
+%type <list> modulelist 
+%type <list> modulename
+%type <name> optional_filename
+%%
+
+start:
+       { prompt(); } session
+       ;
+
+session:
+           session command_line
+       |
+       ;
+
+command_line:
+               command NEWLINE { prompt(); }
+
+command:
+               open_command    
+       |       create_command  
+       |       verbose_command
+       |       directory_command
+       |       addlib_command
+       |       clear_command
+       |       addmod_command
+       |       save_command
+       |       replace_command
+       |       delete_command
+       |       list_command
+       |       END      { return 0; }
+       |       error
+       |
+       ;
+
+
+replace_command:       
+               REPLACE modulename
+               { ar_replace($2); }
+       ;
+       
+clear_command:
+               CLEAR
+               { ar_clear(); }
+       ;
+
+delete_command:
+               DELETE modulename
+               { ar_delete($2); }
+       ;
+addmod_command:
+       ADDMOD modulename
+               { ar_addmod($2); }
+       ;
+
+list_command:  
+               LIST
+               { ar_list(); }
+       ;
+
+save_command:  
+               SAVE
+               { ar_save(); }
+       ;
+
+
+
+open_command:
+               OPEN FILENAME 
+               { ar_open($2,0); }
+       ;
+
+create_command:
+               CREATE FILENAME 
+               { ar_open($2,1); }
+       ;
+
+
+addlib_command:
+               ADDLIB FILENAME modulelist
+               { ar_addlib($2,$3); }
+       ;
+directory_command:
+               DIRECTORY FILENAME modulelist optional_filename
+               { ar_directory($2, $3, $4); }
+       ;
+
+
+
+optional_filename:
+               FILENAME
+               { $$ = $1; }
+       |       { $$ = 0; }
+       ;
+
+modulelist:
+       '(' modulename ')' 
+               { $$ = $2; }
+       |
+               { $$ = 0; }
+       ;
+
+modulename:
+               modulename optcomma FILENAME
+               {       struct list *n  = (struct list *) malloc(sizeof(struct list));
+                       n->next = $1; 
+                       n->name = $3;
+                       $$ = n;
+                }
+       |       { $$ = 0; }
+       ;
+       
+
+optcomma:
+               ','
+       |
+       ;
+       
+               
+verbose_command:
+       VERBOSE 
+               { verbose = !verbose; }
+       ;
+
+
+%%
+
+
+int
+yyerror(x)
+char *x;
+{
+  extern int linenumber;
+  printf("Synax error in archive script, line %d\n", linenumber + 1);
+  return 0;
+}
diff --git a/binutils/arsup.c b/binutils/arsup.c
new file mode 100644 (file)
index 0000000..ee7e4e9
--- /dev/null
@@ -0,0 +1,382 @@
+/* arsup.c - Archive support for MRI compatibility */
+
+/*   Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Contributed by Steve Chamberlain
+                 sac@cygnus.com
+
+This file looks after requests from arparse.y, to provide the MRI
+style librarian command syntax + 1 word LIST
+
+*/
+
+#include "bfd.h"
+#include "arsup.h"
+#include <sysdep.h>
+#include "bucomm.h"
+extern bfd *inarch;
+extern int verbose;
+
+
+
+void
+DEFUN(map_over_list,(function, list),
+      void            (*function) () AND
+      struct list           *list)
+
+{
+  bfd            *head;
+
+  if (list == 0) {
+    for (head = inarch->next; head; head = head->next){
+      function(head);
+    }
+  }
+  else {
+    /*
+      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.
+      */
+    struct list *ptr = list;
+
+    for (ptr = list; ptr; ptr=ptr->next)
+    {
+      boolean         found = false;
+      bfd *prev = inarch;
+      for (head = inarch->next; head; head = head->next) 
+      {
+       if ((head->filename != NULL) &&
+           (!strcmp(ptr->name, head->filename))) 
+       {
+         found = true;
+         function(head, prev);
+
+       }
+       prev = head;
+      }
+      if (!found)
+       fprintf(stderr, "No entry %s in archive.\n", ptr->name);
+    }
+  }
+}
+
+
+FILE *outfile;
+void
+DEFUN(ar_directory_doer,(abfd),
+      bfd *abfd)
+{
+    print_arelt_descr(outfile, abfd, verbose);
+}
+
+void
+DEFUN(ar_directory,(ar_name, list, output),
+      char *ar_name AND
+      struct list *list AND
+      char *output)
+{
+  open_inarch(ar_name);
+  if (output)  {
+    outfile = fopen(output,"w");
+    if (outfile == 0) {
+      outfile =stdout;
+      fprintf(stderr,"Can't open file %s\n", output);
+      output = 0;
+    }
+  }
+  else 
+   outfile = stdout;
+
+  map_over_list(ar_directory_doer, list);
+  bfd_close(inarch);
+  if (output)
+   fclose(outfile);
+}
+
+void
+DEFUN_VOID(prompt)
+{
+  extern int interactive;
+  if (interactive) 
+  {
+    printf("AR >");
+    fflush(stdout); 
+  }
+}
+
+void
+DEFUN_VOID(maybequit)
+{
+if (!interactive) 
+ exit(9);
+}
+
+
+bfd *obfd;
+char *real_name ; 
+void
+DEFUN(ar_open,(name, t),
+      char *name AND
+      int t)
+
+{
+  char *tname = malloc(strlen(name)+10);
+  real_name = name;
+  sprintf(tname, "%s-tmp", name);
+  obfd = bfd_openw(tname, NULL);
+
+  if (!obfd) {
+    fprintf(stderr,"%s: Can't open output archive %s\n", program_name,
+           tname);
+
+    maybequit();
+  }
+  else {
+    if (!t) {
+      bfd **ptr;
+      bfd *element;
+      bfd *ibfd;
+      ibfd = bfd_openr(name, NULL);
+      if (bfd_check_format(ibfd, bfd_archive) != true) {
+       fprintf(stderr,"%s: file %s is not an archive\n", program_name,
+               name);
+       maybequit();
+       return;
+      }
+      ptr = &(obfd->archive_head);
+      element = bfd_openr_next_archived_file(ibfd, NULL);
+
+      while (element) {
+       *ptr = element;
+       ptr = &element->next;
+       element = bfd_openr_next_archived_file(ibfd, element);
+      }
+    }
+
+    bfd_set_format(obfd, bfd_archive);
+
+    obfd->has_armap = 1;
+  }
+}
+
+
+void
+DEFUN(ar_addlib_doer, (abfd, prev),
+      bfd *abfd AND
+      bfd *prev)
+{
+  /* Add this module to the output bfd */
+  
+  prev->next = abfd->next;
+  abfd->next = obfd->archive_head;
+  obfd->archive_head = abfd;
+}
+
+void
+DEFUN(ar_addlib, (name, list),
+      char *name AND
+      struct list *list)
+{
+  if (!obfd) {
+    fprintf(stderr, "%s: no output archive specified yet\n", program_name);
+    maybequit();
+  }
+  else {
+    if (open_inarch(name) ) {
+      map_over_list(ar_addlib_doer, list);
+    }
+    /* Don't close the bfd, since it will make the elements disasppear */
+  }
+}
+
+
+
+void
+DEFUN(ar_addmod, (list),
+      struct list *list)
+{
+  if (!obfd) {
+    fprintf(stderr, "%s: no open output archive\n", program_name);
+    maybequit();
+  }
+  else 
+  {
+    while (list) {
+      bfd *abfd = bfd_openr(list->name, NULL);
+      if (!abfd)  {
+       fprintf(stderr,"%s: can't open file %s\n", program_name,
+               list->name);
+       maybequit();
+      }
+      else {
+       abfd->next = obfd->archive_head;
+       obfd->archive_head = abfd;
+      }
+      list = list->next;
+    }
+  }
+}
+
+
+
+void
+DEFUN_VOID(ar_clear)
+{
+if (obfd) 
+ obfd->archive_head = 0;
+}
+
+void
+DEFUN(ar_delete, (list),
+      struct list *list)
+{
+  if (!obfd) {
+    fprintf(stderr, "%s: no open output archive\n", program_name);
+    maybequit();
+  }
+  else 
+  {
+    while (list) {
+      /* Find this name in the archive */
+      bfd *member = obfd->archive_head;
+      bfd **prev = &(obfd->archive_head);
+      int found = 0;
+      while (member) {
+       if (strcmp(member->filename, list->name) == 0) {
+         *prev = member->next;
+         found = 1;
+       }
+       else {
+         prev = &(member->next);
+       }
+         member = member->next;
+      }
+      if (!found)  {
+       fprintf(stderr,"%s: can't find module file %s\n", program_name,
+               list->name);
+       maybequit();
+      }
+      list = list->next;
+    }
+  }
+}
+
+
+void
+DEFUN_VOID(ar_save)
+{
+
+  if (!obfd) {
+    fprintf(stderr, "%s: no open output archive\n", program_name);
+    maybequit();
+  }
+  else {
+    bfd_close(obfd);
+    unlink(real_name);
+    link(obfd->filename, real_name);
+    unlink(obfd->filename);
+    obfd = 0;
+  }
+}
+
+
+
+void
+DEFUN(ar_replace, (list),
+      struct list *list)
+{
+  if (!obfd) {
+    fprintf(stderr, "%s: no open output archive\n", program_name);
+    maybequit();
+  }
+  else 
+  {
+    while (list) {
+      /* Find this name in the archive */
+      bfd *member = obfd->archive_head;
+      bfd **prev = &(obfd->archive_head);
+      int found = 0;
+      while (member) 
+      {
+       if (strcmp(member->filename, list->name) == 0) 
+       {
+         /* Found the one to replace */
+         bfd *abfd = bfd_openr(list->name, 0);
+         if (!abfd) 
+         {
+           fprintf(stderr, "%s: can't open file %s\n", program_name, list->name);
+           maybequit();
+         }
+         else {
+           *prev = abfd;
+           abfd->next = member->next;
+           found = 1;
+         }
+       }
+       else {
+         prev = &(member->next);
+       }
+       member = member->next;
+      }
+      if (!found)  {
+       bfd *abfd = bfd_openr(list->name, 0);
+       fprintf(stderr,"%s: can't find module file %s\n", program_name,
+               list->name);
+       if (!abfd) 
+       {
+         fprintf(stderr, "%s: can't open file %s\n", program_name, list->name);
+         maybequit();
+       }
+       else 
+       {
+         *prev = abfd;
+       }
+      }
+
+    list = list->next;
+    }
+  }
+}
+
+/* And I added this one */
+void
+DEFUN_VOID(ar_list)
+{
+  if (!obfd) 
+  {
+    fprintf(stderr, "%s: no open output archive\n", program_name);
+    maybequit();
+  }
+  else {
+    bfd *abfd;
+    outfile = stdout;
+    verbose =1 ;
+    printf("Current open archive is %s\n", obfd->filename);
+    for (abfd = obfd->archive_head;
+        abfd != (bfd *)NULL;
+        abfd = abfd->next) 
+    {
+      ar_directory_doer(abfd);
+    }
+  }
+}
diff --git a/binutils/arsup.h b/binutils/arsup.h
new file mode 100644 (file)
index 0000000..a750c08
--- /dev/null
@@ -0,0 +1,29 @@
+
+
+
+
+void EXFUN( map_over_members, (void (*function) (), char **files, int count));
+
+
+
+
+
+       struct list {
+               char *name;     
+               struct list *next;
+       } ;
+
+void EXFUN(maybequit,(void));
+void EXFUN(prompt,(void));
+void EXFUN(ar_clear,(void));
+void EXFUN(ar_replace,(struct list *));
+void EXFUN(ar_delete,(struct list *));
+void EXFUN(ar_save, (void));
+void EXFUN(ar_list, (void));
+void EXFUN(ar_open, (char *, int));
+void EXFUN(ar_directory,(char *, struct list *, char *));
+void EXFUN(ar_addmod, (struct list *));
+void EXFUN(ar_addlib, (char *, struct list *));
+int interactive;
+
+int yyparse();