* ar.c (counted_name_mode): New static variable.
(counted_name_counter): New static variable.
(map_over_members): Handle counted mode.
(usage): Mention N modifier.
(main): Handle N modifier.
(delete_members): Handle counted mode.
* binutils.texi, ar.1: Document N modifier.
1999-09-12 Donn Terry <donn@interix.com>
1999-09-12 Donn Terry <donn@interix.com>
+ * ar.c (counted_name_mode): New static variable.
+ (counted_name_counter): New static variable.
+ (map_over_members): Handle counted mode.
+ (usage): Mention N modifier.
+ (main): Handle N modifier.
+ (delete_members): Handle counted mode.
+ * binutils.texi, ar.1: Document N modifier.
+
* ar.c (print_contents): Change printing of member name for
POSIX.2 conformance.
* ar.c (print_contents): Change printing of member name for
POSIX.2 conformance.
(usage): Mention P modifier.
(normalize): If full_pathname is true, don't do anything.
(main): Accept P modifier.
(usage): Mention P modifier.
(normalize): If full_pathname is true, don't do anything.
(main): Accept P modifier.
+ (delete_members): Call normalize on command line parameter.
* binutils.texi, ar.1: Document P modifier.
1999-09-09 Andreas Schwab <schwab@suse.de>
* binutils.texi, ar.1: Document P modifier.
1999-09-09 Andreas Schwab <schwab@suse.de>
.hy 0
.na
.BR ar " [\|" "-" "\|]"\c
.hy 0
.na
.BR ar " [\|" "-" "\|]"\c
-.I {dmpqrtx}[abcilosSuvV] \c
+.I {dmpqrtx}[abcfilNoPsSuvV] \c
[\|\c
.I membername\c
\&\|] \c
[\|\c
.I membername\c
\&\|] \c
+[\|\c
+.I count\c
+\&\|] \c
.I archive\c
\& \c
.I files\c
.I archive\c
\& \c
.I files\c
modifier may be used to truncate file names when putting them in the
archive.
modifier may be used to truncate file names when putting them in the
archive.
-.TP
-.B P
-Use the full path name when matching names in the archive.
-.B ar
-can not create an archive with a full path name (such archives are not
-POSIX complaint), but other archive creators can. This option will
-cause
-.B ar
-to match file names using a complete path name, which can be
-convenient when extracting a single file from an archive created by
-another tool.
-
.TP
.B i
Insert new files \c
.TP
.B i
Insert new files \c
.B l
This modifier is accepted but not used.
.B l
This modifier is accepted but not used.
+.TP
+.B N
+Uses the
+.I count
+parameter. This is used if there are multiple entries in the archive
+with the same name. Extract or delete instance
+.I count
+of the given name from the archive.
+
you do not specify this modifier, files extracted from the archive
will be stamped with the time of extraction.
you do not specify this modifier, files extracted from the archive
will be stamped with the time of extraction.
+.TP
+.B P
+Use the full path name when matching names in the archive.
+.B ar
+can not create an archive with a full path name (such archives are not
+POSIX complaint), but other archive creators can. This option will
+cause
+.B ar
+to match file names using a complete path name, which can be
+convenient when extracting a single file from an archive created by
+another tool.
+
.TP
.B s
Write an object-file index into the archive, or update an existing one,
.TP
.B s
Write an object-file index into the archive, or update an existing one,
static bfd **
get_pos_bfd PARAMS ((bfd **, enum pos, const char *));
static bfd **
get_pos_bfd PARAMS ((bfd **, enum pos, const char *));
+/* For extract/delete only. If COUNTED_NAME_MODE is true, we only
+ extract the COUNTED_NAME_COUNTER instance of that name. */
+static boolean counted_name_mode = 0;
+static int counted_name_counter = 0;
+
/* Whether to truncate names of files stored in the archive. */
static boolean ar_truncate = false;
/* Whether to truncate names of files stored in the archive. */
static boolean ar_truncate = false;
/* 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
/* 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
for (head = arch->next; head; head = head->next)
{
PROGRESS (1);
for (head = arch->next; head; head = head->next)
{
PROGRESS (1);
if ((head->filename != NULL) &&
(!strcmp (normalize (*files, arch), head->filename)))
{
if ((head->filename != NULL) &&
(!strcmp (normalize (*files, arch), head->filename)))
{
+ ++match_count;
+ if (counted_name_mode
+ && match_count != counted_name_counter)
+ {
+ /* Counting, and didn't match on count; go on to the
+ next one. */
+ continue;
+ }
+
found = true;
function (head);
}
found = true;
function (head);
}
if (! is_ranlib)
{
/* xgettext:c-format */
if (! is_ranlib)
{
/* xgettext:c-format */
- fprintf (s, _("Usage: %s [-]{dmpqrstx}[abcilosSuvV] [member-name] archive-file file...\n"), program_name);
+ fprintf (s, _("Usage: %s [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
+ program_name);
/* xgettext:c-format */
fprintf (s, _(" %s -M [<mri-script]\n"), program_name);
fprintf (s, _(" commands:\n"));
/* xgettext:c-format */
fprintf (s, _(" %s -M [<mri-script]\n"), program_name);
fprintf (s, _(" commands:\n"));
fprintf (s, _(" command specific modifiers:\n"));
fprintf (s, _(" [a] - put file(s) after [member-name]\n"));
fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n"));
fprintf (s, _(" command specific modifiers:\n"));
fprintf (s, _(" [a] - put file(s) after [member-name]\n"));
fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n"));
+ fprintf (s, _(" [N] - use instance [count] of name\n"));
fprintf (s, _(" [f] - truncate inserted file names\n"));
fprintf (s, _(" [P] - use full path names when matching\n"));
fprintf (s, _(" [o] - preserve original dates\n"));
fprintf (s, _(" [f] - truncate inserted file names\n"));
fprintf (s, _(" [P] - use full path names when matching\n"));
fprintf (s, _(" [o] - preserve original dates\n"));
} operation = none;
int arg_index;
char **files;
} operation = none;
int arg_index;
char **files;
char *inarch_filename;
int show_version;
char *inarch_filename;
int show_version;
case 'M':
mri_mode = 1;
break;
case 'M':
mri_mode = 1;
break;
+ case 'N':
+ counted_name_mode = true;
+ break;
case 'f':
ar_truncate = true;
break;
case 'f':
ar_truncate = true;
break;
if (postype != pos_default)
posname = argv[arg_index++];
if (postype != pos_default)
posname = argv[arg_index++];
+ if (counted_name_mode)
+ {
+ if (operation != extract && operation != delete)
+ fatal (_("`N' is only meaningful with the `x' and 'd' options."));
+ counted_name_counter = atoi (argv[arg_index++]);
+ if (counted_name_counter <= 0)
+ fatal (_("Value for `N' must be positive."));
+ }
+
inarch_filename = argv[arg_index++];
files = arg_index < argc ? argv + arg_index : NULL;
inarch_filename = argv[arg_index++];
files = arg_index < argc ? argv + arg_index : NULL;
+ file_count = argc - arg_index;
#if 0
/* We don't use do_quick_append any more. Too many systems
#if 0
/* We don't use do_quick_append any more. Too many systems
switch (operation)
{
case print_table:
switch (operation)
{
case print_table:
- map_over_members (arch, print_descr, files, argc - 3);
+ map_over_members (arch, print_descr, files, file_count);
- map_over_members (arch, print_contents, files, argc - 3);
+ map_over_members (arch, print_contents, files, file_count);
- map_over_members (arch, extract_file, files, argc - 3);
+ map_over_members (arch, extract_file, files, file_count);
bfd **current_ptr_ptr;
boolean found;
boolean something_changed = false;
bfd **current_ptr_ptr;
boolean found;
boolean something_changed = false;
for (; *files_to_delete != NULL; ++files_to_delete)
{
/* In a.out systems, the armap is optional. It's also called
for (; *files_to_delete != NULL; ++files_to_delete)
{
/* In a.out systems, the armap is optional. It's also called
current_ptr_ptr = &(arch->next);
while (*current_ptr_ptr)
{
current_ptr_ptr = &(arch->next);
while (*current_ptr_ptr)
{
- if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
- {
- found = true;
- something_changed = true;
- if (verbose)
- printf ("d - %s\n",
- *files_to_delete);
- *current_ptr_ptr = ((*current_ptr_ptr)->next);
- goto next_file;
- }
- else
+ if (strcmp (normalize (*files_to_delete, arch),
+ (*current_ptr_ptr)->filename) == 0)
- current_ptr_ptr = &((*current_ptr_ptr)->next);
+ ++match_count;
+ if (counted_name_mode
+ && match_count != counted_name_counter)
+ {
+ /* Counting, and didn't match on count; go on to the
+ next one. */
+ }
+ else
+ {
+ found = true;
+ something_changed = true;
+ if (verbose)
+ printf ("d - %s\n",
+ *files_to_delete);
+ *current_ptr_ptr = ((*current_ptr_ptr)->next);
+ goto next_file;
+ }
+
+ current_ptr_ptr = &((*current_ptr_ptr)->next);
}
if (verbose && found == false)
}
if (verbose && found == false)
@cindex archives
@cindex collections of files
@smallexample
@cindex archives
@cindex collections of files
@smallexample
-ar [-]@var{p}[@var{mod} [@var{relpos}]] @var{archive} [@var{member}@dots{}]
+ar [-]@var{p}[@var{mod} [@var{relpos}] [@var{count}]] @var{archive} [@var{member}@dots{}]
ar -M [ <mri-script ]
@end smallexample
ar -M [ <mri-script ]
@end smallexample
@section Controlling @code{ar} on the command line
@smallexample
@section Controlling @code{ar} on the command line
@smallexample
-ar [-]@var{p}[@var{mod} [@var{relpos}]] @var{archive} [@var{member}@dots{}]
+ar [-]@var{p}[@var{mod} [@var{relpos}] [@var{count}]] @var{archive} [@var{member}@dots{}]
@end smallexample
@cindex Unix compatibility, @code{ar}
@end smallexample
@cindex Unix compatibility, @code{ar}
this is a concern, the @samp{f} modifier may be used to truncate file
names when putting them in the archive.
this is a concern, the @samp{f} modifier may be used to truncate file
names when putting them in the archive.
-@item P
-Use the full path name when matching names in the archive. @sc{gnu}
-@code{ar} can not create an archive with a full path name (such archives
-are not POSIX complaint), but other archive creators can. This option
-will cause @sc{gnu} @code{ar} to match file names using a complete path
-name, which can be convenient when extracting a single file from an
-archive created by another tool.
-
@item i
Insert new files @emph{before} an existing member of the
archive. If you use the modifier @samp{i}, the name of an existing archive
@item i
Insert new files @emph{before} an existing member of the
archive. If you use the modifier @samp{i}, the name of an existing archive
@c whaffor ar l modifier??? presumably compat; with
@c what???---doc@@cygnus.com, 25jan91
@c whaffor ar l modifier??? presumably compat; with
@c what???---doc@@cygnus.com, 25jan91
+@item N
+Uses the @var{count} parameter. This is used if there are multiple
+entries in the archive with the same name. Extract or delete instance
+@var{count} of the given name from the archive.
+
@item o
@cindex dates in archive
Preserve the @emph{original} dates of members when extracting them. If
you do not specify this modifier, files extracted from the archive
are stamped with the time of extraction.
@item o
@cindex dates in archive
Preserve the @emph{original} dates of members when extracting them. If
you do not specify this modifier, files extracted from the archive
are stamped with the time of extraction.
+@item P
+Use the full path name when matching names in the archive. @sc{gnu}
+@code{ar} can not create an archive with a full path name (such archives
+are not POSIX complaint), but other archive creators can. This option
+will cause @sc{gnu} @code{ar} to match file names using a complete path
+name, which can be convenient when extracting a single file from an
+archive created by another tool.
+
@item s
@cindex writing archive index
Write an object-file index into the archive, or update an existing one,
@item s
@cindex writing archive index
Write an object-file index into the archive, or update an existing one,