New L modifier for ar q operation to flatten archives.

binutils/
	* doc/binutils.texi (ar cmdline): Document L modifier for q operation.
	* NEWS: Mention that.
	* ar.c (flatten_archives): New variable.
	(usage): Describe L.
	(decode_options): Parse L.
	(replace_members): Use L.
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index b775f0a..ee027af 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,12 @@
+2021-07-14  Roland McGrath  <mcgrathr@google.com>
+
+	* doc/binutils.texi (ar cmdline): Document L modifier for q operation.
+	* NEWS: Mention that.
+	* ar.c (flatten_archives): New variable.
+	(usage): Describe L.
+	(decode_options): Parse L.
+	(replace_members): Use L.
+
 2021-07-14  Clément Chigot  <clement.chigot@atos.net>
 
 	* dwarf.h (struct dwarf_section): Add XCOFF name.
diff --git a/binutils/NEWS b/binutils/NEWS
index 8a73387..b8da1ff 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -54,6 +54,9 @@
 * Nm has a new command line option: --quiet.  This suppresses "no symbols"
   diagnostic.
 
+* The ar tool has a new L modifier for the q operation.  This says to flatten
+  archive files added on the command line by adding their individual members.
+
 Changes in 2.36:
 
 * Update elfedit and readelf with LAM_U48 and LAM_U57 support.
diff --git a/binutils/ar.c b/binutils/ar.c
index 5d6976c..d727384 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -138,6 +138,9 @@
 /* Whether to create a "thin" archive (symbol index only -- no files).  */
 static bool make_thin_archive = false;
 
+/* Whether to flatten other archives as inputs so their members are added.  */
+static bool flatten_archives = false;
+
 #define LIBDEPS	"__.LIBDEP"
 /* Text to store in the __.LIBDEP archive element for the linker to use.  */
 static char * libdeps = NULL;
@@ -285,13 +288,13 @@
 #if BFD_SUPPORTS_PLUGINS
   /* xgettext:c-format */
   const char *command_line
-    = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilMNoOPsSTuvV]"
+    = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilLMNoOPsSTuvV]"
 	" [--plugin <name>] [member-name] [count] archive-file file...\n");
 
 #else
   /* xgettext:c-format */
   const char *command_line
-    = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilMNoOPsSTuvV]"
+    = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilLMNoOPsSTuvV]"
 	" [member-name] [count] archive-file file...\n");
 #endif
   s = help ? stdout : stderr;
@@ -304,7 +307,7 @@
   fprintf (s, _("  d            - delete file(s) from the archive\n"));
   fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
   fprintf (s, _("  p            - print file(s) found in the archive\n"));
-  fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
+  fprintf (s, _("  q[f][L]      - quick append file(s) to the archive\n"));
   fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
   fprintf (s, _("  s            - act as ranlib\n"));
   fprintf (s, _("  t[O][v]      - display contents of the archive\n"));
@@ -332,6 +335,7 @@
   fprintf (s, _("  [o]          - preserve original dates\n"));
   fprintf (s, _("  [O]          - display offsets of files in the archive\n"));
   fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
+  fprintf (s, _("  [L]          - flatten archive files: add their members\n"));
   fprintf (s, _(" generic modifiers:\n"));
   fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
   fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
@@ -495,7 +499,7 @@
       argv = new_argv;
     }
 
-  while ((c = getopt_long (argc, argv, "hdmpqrtxl:coOVsSuvabiMNfPTDU",
+  while ((c = getopt_long (argc, argv, "hdmpqrtxl:coOVsSuvabiMNfPTDUL",
 			   long_options, NULL)) != EOF)
     {
       switch (c)
@@ -601,6 +605,9 @@
         case 'U':
           deterministic = false;
           break;
+        case 'L':
+          flatten_archives = true;
+          break;
 	case OPTION_PLUGIN:
 #if BFD_SUPPORTS_PLUGINS
 	  bfd_plugin_set_plugin (optarg);
@@ -622,6 +629,12 @@
         }
     }
 
+  if (flatten_archives && operation != quick_append) {
+    fprintf(stderr, _("%s: L modifier is only valid with q operation\n"),
+            program_name);
+    usage (1);
+  }
+
   /* PR 13256: Allow for the possibility that the first command line option
      started with a dash (eg --plugin) but then the following option(s) are
      old style, non-dash-prefixed versions.  */
@@ -1476,6 +1489,8 @@
   bfd *current;
   bfd **current_ptr;
 
+  const bool flatten = make_thin_archive || flatten_archives;
+
   while (files_to_move && *files_to_move)
     {
       if (! quick)
@@ -1545,12 +1560,12 @@
 	  && FILENAME_CMP (normalize (*files_to_move, arch), LIBDEPS) == 0)
         {
 	  changed |= ar_emul_append_bfd (after_bfd, libdeps_bfd,
-					 verbose, make_thin_archive);
+					 verbose, flatten);
 	}
       else
         {
 	  changed |= ar_emul_append (after_bfd, *files_to_move, target,
-				     verbose, make_thin_archive);
+				     verbose, flatten);
 	}
 
     next_file:;
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 504c3ea..b7f44a1 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -323,6 +323,12 @@
 
 The modifier @samp{v} makes @command{ar} list each file as it is appended.
 
+The modifier @samp{L} makes @command{ar} check whether each file being
+added is itself an archive file.  If it's an archive file, then each
+of the archive's members is added as a separate member with its own
+name rather than the archive file itself being added as a single
+member with the name of the archive file.
+
 Since the point of this operation is speed, implementations of
 @command{ar} have the option of not updating the archive's symbol
 table if one exists.  Too many different systems however assume that
@@ -595,7 +601,7 @@
 directory into which archive members should be extracted.  If this
 option is not specified then the current directory will be used.
 
-Note - although the presence of this option does imply a @option{x} 
+Note - although the presence of this option does imply a @option{x}
 extraction operation that option must still be included on the command
 line.
 
@@ -1078,7 +1084,7 @@
 @item --inlines
 @cindex objdump inlines
 When option @option{-l} is active, if the address belongs to a
-function that was inlined, then this option causes the source 
+function that was inlined, then this option causes the source
 information for all enclosing scopes back to the first non-inlined
 function to be printed as well.  For example, if @code{main} inlines
 @code{callee1} which inlines @code{callee2}, and address is from
@@ -1720,7 +1726,7 @@
 @item --set-section-alignment @var{sectionpattern}=@var{align}
 Set the alignment for any sections matching @var{sectionpattern}.
 @var{align} specifies the alignment in bytes and must be a power of
-two, i.e. 1, 2, 4, 8@dots{}. 
+two, i.e. 1, 2, 4, 8@dots{}.
 
 @item --add-section @var{sectionname}=@var{filename}
 Add a new section named @var{sectionname} while copying the file.  The
@@ -2354,7 +2360,7 @@
 @cindex disassembling object code
 @cindex machine instructions
 Display the assembler mnemonics for the machine instructions from the
-input file.  This option only disassembles those sections which are 
+input file.  This option only disassembles those sections which are
 expected to contain instructions.  If the optional @var{symbol}
 argument is given, then display the assembler mnemonics starting at
 @var{symbol}.  If @var{symbol} is a function name then disassembly