diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/gm2spec.cc
--- /dev/null	2022-08-24 16:22:16.888000070 +0100
+++ gcc-git-devel-modula2/gcc/m2/gm2spec.cc	2022-12-06 02:56:51.360774949 +0000
@@ -0,0 +1,946 @@
+/* gm2spec.cc specific flags and argument handling within GNU Modula-2.
+
+Copyright (C) 2007-2022 Free Software Foundation, Inc.
+Contributed by Gaius Mulley <gaius@glam.ac.uk>.
+
+This file is part of GNU Modula-2.
+
+GNU Modula-2 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 3, or (at your option)
+any later version.
+
+GNU Modula-2 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 GNU Modula-2; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "xregex.h"
+#include "obstack.h"
+#include "intl.h"
+#include "prefix.h"
+#include "opt-suggestions.h"
+#include "gcc.h"
+#include "opts.h"
+#include "vec.h"
+
+#include "m2/gm2config.h"
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#else
+#ifdef HAVE_SYS_NDIR_H
+#include <sys/ndir.h>
+#endif
+#ifdef HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif
+#ifdef HAVE_NDIR_H
+#include <ndir.h>
+#endif
+#endif
+
+/* This bit is set if we saw a `-xfoo' language specification.  */
+#define LANGSPEC	(1<<1)
+/* This bit is set if they did `-lm' or `-lmath'.  */
+#define MATHLIB		(1<<2)
+/* This bit is set if they did `-lc'.  */
+#define WITHLIBC	(1<<3)
+/* Skip this option.  */
+#define SKIPOPT		(1<<4)
+
+#ifndef MATH_LIBRARY
+#define MATH_LIBRARY "m"
+#endif
+#ifndef MATH_LIBRARY_PROFILE
+#define MATH_LIBRARY_PROFILE MATH_LIBRARY
+#endif
+
+#ifndef LIBSTDCXX
+#define LIBSTDCXX "stdc++"
+#endif
+#ifndef LIBSTDCXX_PROFILE
+#define LIBSTDCXX_PROFILE LIBSTDCXX
+#endif
+#ifndef LIBSTDCXX_STATIC
+#define LIBSTDCXX_STATIC NULL
+#endif
+
+#ifndef LIBCXX
+#define LIBCXX "c++"
+#endif
+#ifndef LIBCXX_PROFILE
+#define LIBCXX_PROFILE LIBCXX
+#endif
+#ifndef LIBCXX_STATIC
+#define LIBCXX_STATIC NULL
+#endif
+
+#ifndef LIBCXXABI
+#define LIBCXXABI "c++abi"
+#endif
+#ifndef LIBCXXABI_PROFILE
+#define LIBCXXABI_PROFILE LIBCXXABI
+#endif
+#ifndef LIBCXXABI_STATIC
+#define LIBCXXABI_STATIC NULL
+#endif
+
+/* The values used here must match those of the stdlib_kind enumeration
+   in c.opt.  */
+enum stdcxxlib_kind
+{
+  USE_LIBSTDCXX = 1,
+  USE_LIBCXX = 2
+};
+
+#define DEFAULT_DIALECT "pim"
+#undef DEBUG_ARG
+
+typedef enum { iso, pim, min, logitech, pimcoroutine, maxlib } libs;
+
+/* These are the library names which are installed as part of gm2 and reflect
+   -flibs=name.  The -flibs= option provides the user with a short cut to add
+   libraries without having to know the include and link path.  */
+
+static const char *library_name[maxlib]
+    = { "m2iso", "m2pim", "m2min", "m2log", "m2cor" };
+
+/* They match the installed archive name for example libm2iso.a,
+   libm2pim.a, libm2min.a, libm2log.a and libm2cor.a.  They also match a
+   subdirectory name where the definition modules are kept.  The driver
+   checks the argument to -flibs= for an entry in library_name or
+   alternatively the existance of the subdirectory (to allow for third
+   party libraries to coexist).  */
+
+static const char *library_abbrev[maxlib]
+    = { "iso", "pim", "min", "log", "cor" };
+
+/* Users may specifiy -flibs=pim,iso etc which are mapped onto
+   -flibs=m2pim,m2iso respectively.  This provides a match between
+   the dialect of Modula-2 and the library set.  */
+
+static const char *add_include (const char *libpath, const char *library);
+
+static bool seen_scaffold_static = false;
+static bool seen_scaffold_dynamic = false;
+static bool scaffold_static = false;
+static bool scaffold_dynamic = true;  // Default uses -fscaffold-dynamic.
+static bool seen_gen_module_list = false;
+static bool seen_uselist = false;
+static bool uselist = false;
+static bool gen_module_list = true;  // Default uses -fgen-module-list=-.
+static const char *gen_module_filename = "-";
+static const char *multilib_dir = NULL;
+/* The original argument list and related info is copied here.  */
+static unsigned int gm2_xargc;
+static const struct cl_decoded_option *gm2_x_decoded_options;
+static void append_arg (const struct cl_decoded_option *);
+
+/* The new argument list will be built here.  */
+static unsigned int gm2_newargc;
+static struct cl_decoded_option *gm2_new_decoded_options;
+
+
+/* Return whether strings S1 and S2 are both NULL or both the same
+   string.  */
+
+static bool
+strings_same (const char *s1, const char *s2)
+{
+  return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0);
+}
+
+bool
+options_same (const struct cl_decoded_option *opt1,
+	      const struct cl_decoded_option *opt2)
+{
+  return (opt1->opt_index == opt2->opt_index
+	  && strings_same (opt1->arg, opt2->arg)
+	  && strings_same (opt1->orig_option_with_args_text,
+			   opt2->orig_option_with_args_text)
+	  && strings_same (opt1->canonical_option[0],
+			   opt2->canonical_option[0])
+	  && strings_same (opt1->canonical_option[1],
+			   opt2->canonical_option[1])
+	  && strings_same (opt1->canonical_option[2],
+			   opt2->canonical_option[2])
+	  && strings_same (opt1->canonical_option[3],
+			   opt2->canonical_option[3])
+	  && (opt1->canonical_option_num_elements
+	      == opt2->canonical_option_num_elements)
+	  && opt1->value == opt2->value
+	  && opt1->errors == opt2->errors);
+}
+
+/* Append another argument to the list being built.  */
+
+static void
+append_arg (const struct cl_decoded_option *arg)
+{
+  static unsigned int newargsize;
+
+  if (gm2_new_decoded_options == gm2_x_decoded_options
+      && gm2_newargc < gm2_xargc
+      && options_same (arg, &gm2_x_decoded_options[gm2_newargc]))
+    {
+      ++gm2_newargc;
+      return;			/* Nothing new here.  */
+    }
+
+  if (gm2_new_decoded_options == gm2_x_decoded_options)
+    {				/* Make new arglist.  */
+      unsigned int i;
+
+      newargsize = (gm2_xargc << 2) + 20;	/* This should handle all.  */
+      gm2_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
+
+      /* Copy what has been done so far.  */
+      for (i = 0; i < gm2_newargc; ++i)
+	gm2_new_decoded_options[i] = gm2_x_decoded_options[i];
+    }
+
+  if (gm2_newargc == newargsize)
+    fatal_error (input_location, "overflowed output argument list for %qs",
+		 arg->orig_option_with_args_text);
+
+  gm2_new_decoded_options[gm2_newargc++] = *arg;
+}
+
+/* Append an option described by OPT_INDEX, ARG and VALUE to the list
+   being built.  */
+
+static void
+append_option (size_t opt_index, const char *arg, int value)
+{
+  struct cl_decoded_option decoded;
+
+  generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
+  append_arg (&decoded);
+}
+
+/* build_archive_path returns a string containing the path to the
+   archive defined by libpath and dialectLib.  */
+
+static const char *
+build_archive_path (const char *libpath, const char *library)
+{
+  if (library != NULL)
+    {
+      const char *libdir = (const char *)library;
+
+      if (libdir != NULL)
+        {
+	  int machine_length = 0;
+          char dir_sep[2];
+
+          dir_sep[0] = DIR_SEPARATOR;
+          dir_sep[1] = (char)0;
+
+	  if (multilib_dir != NULL)
+	    {
+	      machine_length = strlen (multilib_dir);
+	      machine_length += strlen (dir_sep);
+	    }
+
+	  int l = strlen (libpath) + 1 + strlen ("m2") + 1
+	    + strlen (libdir) + 1 + machine_length + 1;
+          char *s = (char *)xmalloc (l);
+
+          strcpy (s, libpath);
+          strcat (s, dir_sep);
+	  if (machine_length > 0)
+	    {
+	      strcat (s, multilib_dir);
+	      strcat (s, dir_sep);
+	    }
+          strcat (s, "m2");
+          strcat (s, dir_sep);
+          strcat (s, libdir);
+          return s;
+        }
+    }
+  return NULL;
+}
+
+/* safe_strdup safely duplicates a string.  */
+
+static char *
+safe_strdup (const char *s)
+{
+  if (s != NULL)
+    return xstrdup (s);
+  return NULL;
+}
+
+/* add_default_combination adds the correct link path and then the
+   library name.  */
+
+static bool
+add_default_combination (const char *libpath, const char *library)
+{
+  if (library != NULL)
+    {
+      append_option (OPT_L, build_archive_path (libpath, library), 1);
+      append_option (OPT_l, safe_strdup (library), 1);
+      return true;
+    }
+  return false;
+}
+
+/* add_default_archives adds the default archives to the end of the
+   current command line.  */
+
+static int
+add_default_archives (const char *libpath, const char *libraries)
+{
+  const char *l = libraries;
+  const char *e;
+  char *libname;
+  unsigned int libcount = 0;
+
+  do
+    {
+      e = index (l, ',');
+      if (e == NULL)
+        {
+          libname = xstrdup (l);
+          l = NULL;
+	  if (add_default_combination (libpath, libname))
+	    libcount++;
+	  free (libname);
+        }
+      else
+        {
+          libname = xstrndup (l, e - l);
+          l = e + 1;
+	  if (add_default_combination (libpath, libname))
+	    libcount++;
+	  free (libname);
+        }
+    }
+  while ((l != NULL) && (l[0] != (char)0));
+  return libcount;
+}
+
+/* build_include_path builds the component of the include path
+   referenced by the library.  */
+
+static const char *
+build_include_path (const char *libpath, const char *library)
+{
+  char dir_sep[2];
+  char *gm2libs;
+  unsigned int machine_length = 0;
+
+  dir_sep[0] = DIR_SEPARATOR;
+  dir_sep[1] = (char)0;
+
+  if (multilib_dir != NULL)
+    {
+      machine_length = strlen (multilib_dir);
+      machine_length += strlen (dir_sep);
+    }
+
+  gm2libs = (char *)alloca (strlen (libpath) + strlen (dir_sep) + strlen ("m2")
+                            + strlen (dir_sep) + strlen (library) + 1
+			    + machine_length + 1);
+  strcpy (gm2libs, libpath);
+  strcat (gm2libs, dir_sep);
+  if (machine_length > 0)
+    {
+      strcat (gm2libs, multilib_dir);
+      strcat (gm2libs, dir_sep);
+    }
+  strcat (gm2libs, "m2");
+  strcat (gm2libs, dir_sep);
+  strcat (gm2libs, library);
+
+  return xstrdup (gm2libs);
+}
+
+/* add_include add the correct include path given the libpath and
+   library.  The new path is returned.  */
+
+static const char *
+add_include (const char *libpath, const char *library)
+{
+  if (library == NULL)
+    return NULL;
+  else
+    return build_include_path (libpath, library);
+}
+
+/* add_default_includes add the appropriate default include paths
+   depending upon the style of libraries chosen.  */
+
+static void
+add_default_includes (const char *libpath, const char *libraries)
+{
+  const char *l = libraries;
+  const char *e;
+  const char *c;
+  const char *path;
+
+  do
+    {
+      e = index (l, ',');
+      if (e == NULL)
+        {
+          c = xstrdup (l);
+          l = NULL;
+        }
+      else
+        {
+          c = xstrndup (l, e - l);
+          l = e + 1;
+        }
+      path = add_include (libpath, c);
+      append_option (OPT_I, path, 1);
+    }
+  while ((l != NULL) && (l[0] != (char)0));
+}
+
+/* library_installed returns true if directory library is found under
+   libpath.  */
+
+static bool
+library_installed (const char *libpath, const char *library)
+{
+#if defined(HAVE_OPENDIR) && defined(HAVE_DIRENT_H)
+  const char *complete = build_archive_path (libpath, library);
+  DIR *directory = opendir (complete);
+
+  if (directory == NULL || (errno == ENOENT))
+    return false;
+  /* Directory exists and therefore the library also exists.  */
+  closedir (directory);
+  return true;
+#else
+  return false;
+#endif
+}
+
+/* check_valid check to see that the library is valid.
+   It check the library against the default library set in gm2 and
+   also against any additional libraries installed in the prefix tree.  */
+
+static bool
+check_valid_library (const char *libpath, const char *library)
+{
+  /* Firstly check against the default libraries (which might not be
+     installed yet).  */
+  for (int i = 0; i < maxlib; i++)
+    if (strcmp (library, library_name[i]) == 0)
+      return true;
+  /* Secondly check whether it is installed (a third party library).  */
+  return library_installed (libpath, library);
+}
+
+/* check_valid_list check to see that the libraries specified are valid.
+   It checks against the default library set in gm2 and also against
+   any additional libraries installed in the libpath tree.  */
+
+static bool
+check_valid_list (const char *libpath, const char *libraries)
+{
+  const char *start = libraries;
+  const char *end;
+  const char *copy;
+
+  do
+    {
+      end = index (start, ',');
+      if (end == NULL)
+        {
+          copy = xstrdup (start);
+          start = NULL;
+        }
+      else
+        {
+          copy = xstrndup (start, end - start);
+          start = end + 1;
+        }
+      if (! check_valid_library (libpath, copy))
+	{
+	  error ("library specified %sq is either not installed or does not exist",
+		 copy);
+	  return false;
+	}
+    }
+  while ((start != NULL) && (start[0] != (char)0));
+  return true;
+}
+
+/* add_word returns a new string which has the contents of lib
+   appended to list.  If list is NULL then lib is duplicated and
+   returned otherwise the list is appended by "," and the contents of
+   lib.  */
+
+static const char *
+add_word (const char *list, const char *lib)
+{
+  char *copy;
+  if (list == NULL)
+    return xstrdup (lib);
+  copy = (char *) xmalloc (strlen (list) + strlen (lib) + 1 + 1);
+  strcpy (copy, list);
+  strcat (copy, ",");
+  strcat (copy, lib);
+  return copy;
+}
+
+/* convert_abbreviation checks abbreviation against known library
+   abbreviations.  If an abbreviation is found it converts the element
+   to the full library name, otherwise the user supplied name is added
+   to the full_libraries list.  A new string is returned.  */
+
+static const char *
+convert_abbreviation (const char *full_libraries, const char *abbreviation)
+{
+  for (int i = 0; i < maxlib; i++)
+    if (strcmp (abbreviation, library_abbrev[i]) == 0)
+      return add_word (full_libraries, library_name[i]);
+  /* No abbreviation found therefore assume user specified full library name.  */
+  return add_word (full_libraries, abbreviation);
+}
+
+/* convert_abbreviations checks each element in the library list to
+   see if an a known library abbreviation was used.  If found it
+   converts the element to the full library name, otherwise the
+   element is copied into the list.  A new string is returned.  */
+
+static const char *
+convert_abbreviations (const char *libraries)
+{
+  const char *start = libraries;
+  const char *end;
+  const char *full_libraries = NULL;
+
+  do
+    {
+      end = index (start, ',');
+      if (end == NULL)
+        {
+          full_libraries = convert_abbreviation (full_libraries, start);
+          start = NULL;
+        }
+      else
+        {
+          full_libraries = convert_abbreviation (full_libraries, xstrndup (start, end - start));
+          start = end + 1;
+        }
+    }
+  while ((start != NULL) && (start[0] != (char)0));
+  return full_libraries;
+}
+
+
+void
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+		      unsigned int *in_decoded_options_count,
+		      int *in_added_libraries)
+{
+  unsigned int argc = *in_decoded_options_count;
+  struct cl_decoded_option *decoded_options = *in_decoded_options;
+  unsigned int i;
+
+  /* True if we saw a `-xfoo' language specification on the command
+     line.  This function will add a -xmodula-2 if the user has not
+     already placed one onto the command line.  */
+  bool seen_x_flag = false;
+  const char *language = NULL;
+
+  /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
+  int saw_profile_flag = 0;
+
+  /* What action to take for the c++ runtime library:
+    -1  means we should not link it in.
+     0  means we should link it if it is needed.
+     1  means it is needed and should be linked in.
+     2  means it is needed but should be linked statically.  */
+  int library = 0;
+
+  /* Which c++ runtime library to link.  */
+  stdcxxlib_kind which_library = USE_LIBSTDCXX;
+
+  const char *libraries = NULL;
+  const char *dialect = DEFAULT_DIALECT;
+  const char *libpath = LIBSUBDIR;
+
+  /* An array used to flag each argument that needs a bit set for
+     LANGSPEC, MATHLIB, or WITHLIBC.  */
+  int *args;
+
+  /* Have we seen -fmod=?  */
+  bool seen_module_extension = false;
+
+  /* Should the driver perform a link?  */
+  bool linking = true;
+
+  /* "-lm" or "-lmath" if it appears on the command line.  */
+  const struct cl_decoded_option *saw_math = NULL;
+
+  /* "-lc" if it appears on the command line.  */
+  const struct cl_decoded_option *saw_libc = NULL;
+
+  /* By default, we throw on the math library if we have one.  */
+  int need_math = (MATH_LIBRARY[0] != '\0');
+
+  /* 1 if we should add -lpthread to the command-line.  */
+  int need_pthread = 1;
+
+  /* True if we saw -static.  */
+  int static_link = 0;
+
+  /* True if we should add -shared-libgcc to the command-line.  */
+  int shared_libgcc = 1;
+
+  /* Have we seen the -v flag?  */
+  bool verbose = false;
+
+  /* The number of libraries added in.  */
+  int added_libraries;
+
+#ifdef ENABLE_PLUGIN
+  /* True if we should add -fplugin=m2rte to the command-line.  */
+  bool need_plugin = true;
+#else
+  bool need_plugin = false;
+#endif
+
+  /* True if we should set up include paths and library paths.  */
+  bool allow_libraries = true;
+
+#if defined(DEBUG_ARG)
+  printf ("argc = %d\n", argc);
+  fprintf (stderr, "Incoming:");
+  for (i = 0; i < argc; i++)
+    fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text);
+  fprintf (stderr, "\n");
+#endif
+
+  gm2_xargc = argc;
+  gm2_x_decoded_options = decoded_options;
+  gm2_newargc = 0;
+  gm2_new_decoded_options = decoded_options;
+  added_libraries = *in_added_libraries;
+  args = XCNEWVEC (int, argc);
+
+  /* First pass through arglist.
+
+     If -nostdlib or a "turn-off-linking" option is anywhere in the
+     command line, don't do any library-option processing (except
+     relating to -x).  */
+
+  for (i = 1; i < argc; i++)
+    {
+      const char *arg = decoded_options[i].arg;
+      args[i] = 0;
+#if defined(DEBUG_ARG)
+      printf ("1st pass: %s\n",
+	      decoded_options[i].orig_option_with_args_text);
+#endif
+      switch (decoded_options[i].opt_index)
+	{
+	case OPT_fiso:
+	  dialect = "iso";
+	  break;
+	case OPT_fpim2:
+	  dialect = "pim2";
+	  break;
+	case OPT_fpim3:
+	  dialect = "pim3";
+	  break;
+	case OPT_fpim4:
+	  dialect = "pim4";
+	  break;
+	case OPT_fpim:
+	  dialect = "pim";
+	  break;
+	case OPT_flibs_:
+	  libraries = xstrdup (arg);
+	  allow_libraries = decoded_options[i].value;
+	  break;
+	case OPT_fmod_:
+	  seen_module_extension = true;
+	  break;
+        case OPT_fpthread:
+          need_pthread = decoded_options[i].value;
+          break;
+        case OPT_fm2_plugin:
+          need_plugin = decoded_options[i].value;
+#ifndef ENABLE_PLUGIN
+	  if (need_plugin)
+	    error ("plugin support is disabled; configure with "
+		   "%<--enable-plugin%>");
+#endif
+          break;
+	case OPT_fscaffold_dynamic:
+	  seen_scaffold_dynamic = true;
+	  scaffold_dynamic = decoded_options[i].value;
+	  break;
+	case OPT_fscaffold_static:
+	  seen_scaffold_static = true;
+	  scaffold_static = decoded_options[i].value;
+	  break;
+	case OPT_fgen_module_list_:
+	  seen_gen_module_list = true;
+	  gen_module_list = decoded_options[i].value;
+	  if (gen_module_list)
+	    gen_module_filename = decoded_options[i].arg;
+	  break;
+	case OPT_fuse_list_:
+	  seen_uselist = true;
+	  uselist = decoded_options[i].value;
+	  break;
+
+	case OPT_nostdlib:
+	case OPT_nostdlib__:
+	case OPT_nodefaultlibs:
+	  library = -1;
+	  break;
+
+	case OPT_l:
+	  if (strcmp (arg, MATH_LIBRARY) == 0)
+	    {
+	      args[i] |= MATHLIB;
+	      need_math = 0;
+	    }
+	  else if (strcmp (arg, "c") == 0)
+	    args[i] |= WITHLIBC;
+	  else
+	    /* Unrecognized libraries (e.g. -lfoo) may require libstdc++.  */
+	    library = (library == 0) ? 1 : library;
+	  break;
+
+	case OPT_pg:
+	case OPT_p:
+	  saw_profile_flag++;
+	  break;
+
+	case OPT_x:
+          seen_x_flag = true;
+          language = arg;
+	  break;
+
+	case OPT_v:
+	  verbose = true;
+	  break;
+
+	case OPT_Xlinker:
+	case OPT_Wl_:
+	  /* Arguments that go directly to the linker might be .o files,
+	     or something, and so might cause libstdc++ to be needed.  */
+	  if (library == 0)
+	    library = 1;
+	  break;
+
+	case OPT_c:
+	case OPT_r:
+	case OPT_S:
+	case OPT_E:
+	case OPT_M:
+	case OPT_MM:
+	case OPT_fsyntax_only:
+	  /* Don't specify libraries if we won't link, since that would
+	     cause a warning.  */
+	  linking = false;
+	  library = -1;
+	  break;
+
+	case OPT_static:
+	  static_link = 1;
+	  break;
+
+	case OPT_static_libgcc:
+	  shared_libgcc = 0;
+	  break;
+
+	case OPT_static_libstdc__:
+	  library = library >= 0 ? 2 : library;
+	  args[i] |= SKIPOPT;
+	  break;
+
+	case OPT_stdlib_:
+	  which_library = (stdcxxlib_kind) decoded_options[i].value;
+	  break;
+
+	default:
+	  if ((decoded_options[i].orig_option_with_args_text != NULL)
+	      && (strncmp (decoded_options[i].orig_option_with_args_text,
+			   "-m", 2) == 0))
+	    multilib_dir = xstrdup (decoded_options[i].orig_option_with_args_text
+				    + 2);
+	}
+    }
+  if (language != NULL && (strcmp (language, "modula-2") != 0))
+    return;
+
+  if (scaffold_static && scaffold_dynamic)
+    {
+      if (! seen_scaffold_dynamic)
+	scaffold_dynamic = false;
+      if (scaffold_dynamic && scaffold_static)
+	error ("%qs and %qs cannot both be enabled",
+	       "-fscaffold-dynamic", "-fscaffold-static");
+    }
+  if (uselist && gen_module_list)
+    {
+      if (! seen_gen_module_list)
+	gen_module_list = false;
+      if (uselist && gen_module_list)
+	error ("%qs and %qs cannot both be enabled",
+	       "-fgen-module-list=", "-fuse-list=");
+    }
+
+
+  /* There's no point adding -shared-libgcc if we don't have a shared
+     libgcc.  */
+#ifndef ENABLE_SHARED_LIBGCC
+  shared_libgcc = 0;
+#endif
+
+  /* Second pass through arglist, transforming arguments as appropriate.  */
+
+  append_arg (&decoded_options[0]); /* Start with command name, of course.  */
+  for (i = 1; i < argc; ++i)
+    {
+#if defined(DEBUG_ARG)
+      printf ("2nd pass: %s\n",
+	      decoded_options[i].orig_option_with_args_text);
+#endif
+      if ((args[i] & SKIPOPT) == 0)
+	{
+	  append_arg (&decoded_options[i]);
+	  /* Make sure -lstdc++ is before the math library, since libstdc++
+	     itself uses those math routines.  */
+	  if (!saw_math && (args[i] & MATHLIB) && library > 0)
+	    saw_math = &decoded_options[i];
+
+	  if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
+	    saw_libc = &decoded_options[i];
+	}
+#if defined(DEBUG_ARG)
+      else
+	printf ("skipping: %s\n",
+		decoded_options[i].orig_option_with_args_text);
+#endif
+    }
+
+  /* We now add in extra arguments to facilitate a successful
+     compile or link.  For example include paths for dialect of Modula-2,
+     library paths and default scaffold linking options.  */
+
+  /* If we have not seen either uselist or gen_module_list and we need
+     to link then we turn on -fgen_module_list=- as the default.  */
+  if ((! (seen_uselist || seen_gen_module_list)) && linking)
+    append_option (OPT_fgen_module_list_, "-", 1);
+
+  if (allow_libraries)
+    {
+      /* If the libraries have not been specified by the user but the
+	 dialect has been specified then select the appropriate libraries.  */
+      if (libraries == NULL)
+	{
+	  if (strcmp (dialect, "iso") == 0)
+	    libraries = xstrdup ("m2iso,m2pim");
+	  else
+	    /* Default to pim libraries if none specified.  */
+	    libraries = xstrdup ("m2pim,m2log,m2iso");
+	}
+      libraries = convert_abbreviations (libraries);
+      if (! check_valid_list (libpath, libraries))
+	return;
+      add_default_includes (libpath, libraries);
+    }
+  if ((! seen_x_flag) && seen_module_extension)
+    append_option (OPT_x, "modula-2", 1);
+
+  if (need_plugin)
+    append_option (OPT_fplugin_, "m2rte", 1);
+
+  if (linking)
+    {
+      if (allow_libraries)
+	add_default_archives (libpath, libraries);
+      /* Add `-lstdc++' if we haven't already done so.  */
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (library > 1 && !static_link)
+	append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
+#endif
+      if (which_library == USE_LIBCXX)
+	{
+	  append_option (OPT_l, saw_profile_flag ? LIBCXX_PROFILE : LIBCXX, 1);
+	  added_libraries++;
+	  if (LIBCXXABI != NULL)
+	    {
+	      append_option (OPT_l, saw_profile_flag ? LIBCXXABI_PROFILE
+			     : LIBCXXABI, 1);
+	      added_libraries++;
+	    }
+	}
+      else
+	{
+	  append_option (OPT_l, saw_profile_flag ? LIBSTDCXX_PROFILE
+			 : LIBSTDCXX, 1);
+	  added_libraries++;
+	}
+      /* Add target-dependent static library, if necessary.  */
+      if ((static_link || library > 1) && LIBSTDCXX_STATIC != NULL)
+	{
+	  append_option (OPT_l, LIBSTDCXX_STATIC, 1);
+	  added_libraries++;
+	}
+#ifdef HAVE_LD_STATIC_DYNAMIC
+      if (library > 1 && !static_link)
+	append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
+#endif
+    }
+  if (need_math)
+    {
+      append_option (OPT_l, saw_profile_flag ? MATH_LIBRARY_PROFILE :
+		     MATH_LIBRARY, 1);
+      added_libraries++;
+    }
+  if (need_pthread)
+    {
+      append_option (OPT_l, "pthread", 1);
+      added_libraries++;
+    }
+  if (shared_libgcc && !static_link)
+    append_option (OPT_shared_libgcc, NULL, 1);
+
+  if (verbose && gm2_new_decoded_options != gm2_x_decoded_options)
+    {
+      fprintf (stderr, _("Driving:"));
+      for (i = 0; i < gm2_newargc; i++)
+	fprintf (stderr, " %s",
+		 gm2_new_decoded_options[i].orig_option_with_args_text);
+      fprintf (stderr, "\n");
+      fprintf (stderr, "new argc = %d, added_libraries = %d\n",
+	       gm2_newargc, added_libraries);
+    }
+
+  *in_decoded_options_count = gm2_newargc;
+  *in_decoded_options = gm2_new_decoded_options;
+  *in_added_libraries = added_libraries;
+}
+
+/* Called before linking.  Returns 0 on success and -1 on failure.  */
+int
+lang_specific_pre_link (void)  /* Not used for M2.  */
+{
+  return 0;
+}
+
+/* Number of extra output files that lang_specific_pre_link may generate.  */
+int lang_specific_extra_outfiles = 0;
diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/lang.opt
--- /dev/null	2022-08-24 16:22:16.888000070 +0100
+++ gcc-git-devel-modula2/gcc/m2/lang.opt	2022-12-06 02:56:51.360774949 +0000
@@ -0,0 +1,356 @@
+; Options for the Modula-2 front end.
+;
+; Copyright (C) 2016-2022 Free Software Foundation, Inc.
+; Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
+;
+; This file is part of GNU Modula-2.
+;
+; GNU Modula-2 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 3, or (at your option)
+; any later version.
+;
+; GNU Modula-2 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 GNU Modula-2; see the file COPYING.  If not,
+; see <https://www.gnu.org/licenses/>.  *)
+
+; See the GCC internals manual for a description of this file's format.
+
+; Please try to keep this file in ASCII collating order.
+
+Language
+Modula-2
+
+B
+Modula-2
+; Documented in c.opt
+
+D
+Modula-2
+; Documented in c.opt
+
+E
+Modula-2
+; Documented in c.opt (passed to the preprocessor if -fcpp is used)
+
+I
+Modula-2 Joined Separate
+; Documented in c.opt
+
+L
+Modula-2 Joined Separate
+; Not documented
+
+M
+Modula-2
+; Documented in c.opt
+
+O
+Modula-2
+; Documented in c.opt
+
+Wall
+Modula-2
+; Documented in c.opt
+
+Wpedantic
+Modula-2
+; Documented in common.opt
+
+Wpedantic-param-names
+Modula-2
+compiler checks to force definition module procedure parameter names with their implementation module counterpart
+
+Wpedantic-cast
+Modula-2
+compiler warns if a cast is being used on types of differing sizes
+
+Wverbose-unbounded
+Modula-2
+inform user which parameters will be passed by reference
+
+Wstyle
+Modula-2
+extra compile time semantic checking, typically tries to catch poor programming style
+
+Wunused-variable
+Modula-2
+; Documented in c.opt
+
+Wunused-parameter
+Modula-2
+; Documented in c.opt
+
+c
+Modula-2
+; Documented in c.opt
+
+fauto-init
+Modula-2
+automatically initializes all pointers to NIL
+
+fbounds
+Modula-2
+turns on runtime subrange, array index and indirection via NIL pointer checking
+
+fcase
+Modula-2
+turns on runtime checking to check whether a CASE statement requires an ELSE clause when on was not specified
+
+fobjc-std=objc1
+Modula-2
+; Documented in c.opt
+
+fcpp
+Modula-2
+use cpp to preprocess the module
+
+fcpp-end
+Modula-2
+passed to the preprocessor if -fcpp is used (internal switch)
+
+fcpp-begin
+Modula-2
+passed to the preprocessor if -fcpp is used (internal switch)
+
+fdebug-builtins
+Modula-2
+call a real function, rather than the builtin equivalent
+
+fdump-system-exports
+Modula-2
+display all inbuilt system items
+
+fd
+Modula-2
+turn on internal debugging of the compiler
+
+fdebug-trace-quad
+Modula-2
+turn on quadruple tracing (internal switch)
+
+fdebug-trace-api
+Modula-2
+turn on the Modula-2 api tracing (internal switch)
+
+fdebug-function-line-numbers
+Modula-2
+turn on the Modula-2 function line number generation (internal switch)
+
+fdef=
+Modula-2 Joined
+recognise the specified suffix as a definition module filename
+
+fexceptions
+Modula-2
+; Documented in common.opt
+
+fextended-opaque
+Modula-2
+allows opaque types to be implemented as any type (a GNU Modula-2 extension)
+
+ffloatvalue
+Modula-2
+turns on runtime checking to check whether a floating point number is about to exceed range
+
+fgen-module-list=
+Modula-2 Joined
+create a topologically sorted module list from all dependent modules used in the application
+
+findex
+Modula-2
+turns on all range checking for numerical values
+
+fiso
+Modula-2
+use ISO dialect of Modula-2
+
+flibs=
+Modula-2 Joined
+specify the library order, currently legal entries include: log, min, pim, iso or their directory name equivalent m2log, m2min, m2pim, m2iso.
+
+flocation=
+Modula-2 Joined
+set all location values to a specific value (internal switch)
+
+fm2-g
+Modula-2
+generate extra nops to improve debugging, producing an instruction for every code related keyword
+
+fm2-lower-case
+Modula-2
+generate error messages which render keywords in lower case
+
+fm2-plugin
+Modula-2
+insert plugin to identify runtime errors at compiletime (default on)
+
+fm2-statistics
+Modula-2
+display statistics about the amount of source lines compiled and symbols used
+
+fm2-strict-type
+Modula-2
+experimental flag to turn on the new strict type checker
+
+fm2-whole-program
+Modula-2
+compile all implementation modules and program module at once
+
+fmod=
+Modula-2 Joined
+recognise the specified suffix as implementation and module filenames
+
+fnil
+Modula-2
+turns on runtime checking to detect accessing data through a NIL value pointer
+
+fpim
+Modula-2
+use PIM [234] dialect of Modula-2
+
+fpim2
+Modula-2
+use PIM 2 dialect of Modula-2
+
+fpim3
+Modula-2
+use PIM 3 dialect of Modula-2
+
+fpim4
+Modula-2
+use PIM 4 dialect of Modula-2
+
+fpositive-mod-floor-div
+Modula-2
+force positive result from MOD and DIV result floor
+
+fpthread
+Modula-2
+link against the pthread library (default on)
+
+fq
+Modula-2
+internal compiler debugging information, dump the list of quadruples
+
+frange
+Modula-2
+turns on all range checking for numerical values
+
+freturn
+Modula-2
+turns on runtime checking for functions which finish without executing a RETURN statement
+
+fruntime-modules=
+Modula-2 Joined
+specify the list of runtime modules and their initialization order
+
+fscaffold-static
+Modula-2
+generate static scaffold initialization and finalization for every module inside main
+
+fscaffold-dynamic
+Modula-2
+the modules initialization order is dynamically determined by M2RTS and application dependancies
+
+fscaffold-c
+Modula-2
+generate a C source scaffold for the current module being compiled
+
+fscaffold-c++
+Modula-2
+generate a C++ source scaffold for the current module being compiled
+
+fscaffold-main
+Modula-2
+generate the main function
+
+fshared
+Modula-2
+generate a shared library from the module
+
+fsoft-check-all
+Modula-2
+turns on all software runtime checking (an abbreviation for -fnil -frange -findex -fwholediv -fcase -freturn -fwholediv -ffloatvalue)
+
+fsources
+Modula-2
+display the location of module source files as they are compiled
+
+fswig
+Modula-2
+create a swig interface file for the module
+
+funbounded-by-reference
+Modula-2
+optimize non var unbounded parameters by passing it by reference, providing it is not written to within the callee procedure.
+
+fuse-list=
+Modula-2 Joined
+orders the initialization/finalializations for scaffold-static or force linking of modules if scaffold-dynamic
+
+fversion
+Modula-2
+; Documented in common.opt
+
+fwholediv
+Modula-2
+turns on all division and modulus by zero checking for ordinal values
+
+fwholevalue
+Modula-2
+turns on runtime checking to check whether a whole number is about to exceed range
+
+fxcode
+Modula-2
+issue all errors and warnings in the Xcode format
+
+iprefix
+Modula-2
+; Documented in c.opt
+
+isystem
+Modula-2
+; Documented in c.opt
+
+idirafter
+Modula-2
+; Documented in c.opt
+
+imultilib
+Modula-2
+; Documented in c.opt
+
+lang-asm
+Modula-2
+; Documented in c.opt
+
+-save-temps
+Modula-2 Alias(save-temps)
+
+save-temps
+Modula-2
+save temporary preprocessed files
+
+save-temps=
+Modula-2 Joined
+save temporary preprocessed files
+
+traditional-cpp
+Modula-2
+; Documented in c.opt
+
+v
+Modula-2
+; Documented in c.opt
+
+x
+Modula-2 Joined
+specify the language from the compiler driver
+
+; This comment is to ensure we retain the blank line above.
diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/lang-specs.h
--- /dev/null	2022-08-24 16:22:16.888000070 +0100
+++ gcc-git-devel-modula2/gcc/m2/lang-specs.h	2022-12-06 02:56:51.360774949 +0000
@@ -0,0 +1,38 @@
+/* Definitions for specs for GNU Modula-2.
+   Copyright (C) 2001-2022 Free Software Foundation, Inc.
+   Contributed by Gaius Mulley.
+
+This file is part of GCC.
+
+GCC 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 3, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+/* This is the contribution to the `default_compilers' array in gcc.c for
+   GNU Modula-2.  */
+
+/* Pass the preprocessor options on the command line together with
+   the exec prefix.  */
+
+#define M2CPP "%{fcpp:-fcpp-begin " \
+              "      -E -lang-asm -traditional-cpp " \
+              "      %(cpp_unique_options) -fcpp-end}"
+
+  {".mod", "@modula-2", 0, 0, 0},
+  {"@modula-2",
+      "cc1gm2 " M2CPP
+      "      %(cc1_options) %{B*} %{c*} %{f*} %{+e*} %{I*} "
+      "      %{MD} %{MMD} %{M} %{MM} %{MA} %{MT*} %{MF*} %V"
+      "      %{save-temps*}"
+      "      %i %{!fsyntax-only:%(invoke_as)}",
+      0, 0, 0},
diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/config-lang.in
--- /dev/null	2022-08-24 16:22:16.888000070 +0100
+++ gcc-git-devel-modula2/gcc/m2/config-lang.in	2022-12-06 02:56:51.328774517 +0000
@@ -0,0 +1,83 @@
+# Top level configure fragment for GNU Modula-2.
+# Copyright (C) 2000-2022 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC 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 3, or (at your option)
+# any later version.
+
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Configure looks for the existence of this file to auto-config each language.
+# We define several parameters used by configure:
+#
+# language	- name of language as it would appear in $(LANGUAGES)
+# compilers	- value to add to $(COMPILERS)
+# stagestuff	- files to add to $(STAGESTUFF)
+
+language="m2"
+
+compilers="cc1gm2\$(exeext)"
+
+stagestuff="gm2\$(exeext) cc1gm2\$(exeext) cc1gm2-cross\$(exeext)"
+
+target_libs="target-libstdc++-v3 target-libgm2"
+
+# The Modula-2 frontend needs C++ compiler during stage 1.
+lang_requires_boot_languages=c++
+
+# Do not build by default.
+build_by_default="no"
+
+gtfiles="\$(srcdir)/m2/gm2-lang.cc \
+         \$(srcdir)/m2/gm2-lang.h \
+         \$(srcdir)/m2/gm2-gcc/rtegraph.cc \
+         \$(srcdir)/m2/gm2-gcc/m2block.cc \
+         \$(srcdir)/m2/gm2-gcc/m2builtins.cc \
+         \$(srcdir)/m2/gm2-gcc/m2decl.cc \
+         \$(srcdir)/m2/gm2-gcc/m2except.cc \
+         \$(srcdir)/m2/gm2-gcc/m2expr.cc \
+         \$(srcdir)/m2/gm2-gcc/m2statement.cc \
+         \$(srcdir)/m2/gm2-gcc/m2type.cc"
+
+outputs="m2/config-make \
+         m2/Make-maintainer \
+        "
+
+mkdir -p m2/gm2-compiler-boot
+mkdir -p m2/gm2-libs-boot
+mkdir -p m2/gm2-ici-boot
+mkdir -p m2/gm2-libiberty
+mkdir -p m2/gm2-gcc
+mkdir -p m2/gm2-compiler
+mkdir -p m2/gm2-libs
+mkdir -p m2/gm2-libs-iso
+mkdir -p m2/gm2-compiler-paranoid
+mkdir -p m2/gm2-libs-paranoid
+mkdir -p m2/gm2-compiler-verify
+mkdir -p m2/boot-bin
+mkdir -p m2/gm2-libs-pim
+mkdir -p m2/gm2-libs-coroutines
+mkdir -p m2/gm2-libs-min
+mkdir -p m2/pge-boot
+mkdir -p plugin
+mkdir -p stage1/m2 stage2/m2 stage3/m2 stage4/m2
+
+# directories used by Make-maintainer
+
+mkdir -p m2/gm2-auto
+mkdir -p m2/gm2-pg-boot
+mkdir -p m2/gm2-pge-boot
+mkdir -p m2/gm2-ppg-boot
+mkdir -p m2/mc-boot
+mkdir -p m2/mc-boot-ch
+mkdir -p m2/mc-boot-gen
diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/config-make.in
--- /dev/null	2022-08-24 16:22:16.888000070 +0100
+++ gcc-git-devel-modula2/gcc/m2/config-make.in	2022-12-06 02:56:51.328774517 +0000
@@ -0,0 +1,6 @@
+# Target libraries are put under this directory:
+TARGET_SUBDIR = @target_subdir@
+# Python3 executable name if it exists
+PYTHON = @PYTHON@
+# Does Python3 exist?  (yes/no).
+HAVE_PYTHON = @HAVE_PYTHON@
\ No newline at end of file
diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/configure.ac
--- /dev/null	2022-08-24 16:22:16.888000070 +0100
+++ gcc-git-devel-modula2/gcc/m2/configure.ac	2022-12-06 02:56:51.328774517 +0000
@@ -0,0 +1,38 @@
+# configure.ac provides gm2spec.c with access to config values.
+
+# Copyright (C) 2001-2022 Free Software Foundation, Inc.
+# Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
+
+# GCC 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 3, or (at your option)
+# any later version.
+
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+AC_INIT(m2, [ ])
+
+# Determine the host, build, and target systems
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+AC_CHECK_PROGS(regex_realpath, realpath)
+if test x$regex_realpath = "x" ; then
+    AC_MSG_ERROR([realpath is required to build GNU Modula-2 (hint install coreutils).])
+fi
+
+AC_CHECK_FUNCS([stpcpy])
+
+AC_CHECK_HEADERS(sys/types.h)
+AC_HEADER_DIRENT
+AC_CHECK_LIB([c],[opendir],[AC_DEFINE([HAVE_OPENDIR],[1],[found opendir])])
+AC_CONFIG_HEADERS(gm2config.h, [echo timestamp > stamp-h])
+AC_OUTPUT
diff -ruw /dev/null gcc-git-devel-modula2/gcc/m2/gm2config.h.in
--- /dev/null	2022-08-24 16:22:16.888000070 +0100
+++ gcc-git-devel-modula2/gcc/m2/gm2config.h.in	2022-12-06 02:56:51.360774949 +0000
@@ -0,0 +1,56 @@
+/* gm2config.h.in template file for values required by gm2spec.c.
+
+Copyright (C) 2006-2022 Free Software Foundation, Inc.
+Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
+
+This file is part of GNU Modula-2.
+
+GNU Modula-2 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 3, or (at your option)
+any later version.
+
+GNU Modula-2 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 GNU Modula-2; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef PACKAGE_BUGREPORT
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+#endif
+
+#ifndef PACKAGE_NAME
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+#endif
+
+#ifndef PACKAGE_STRING
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+#endif
+
+/* Define to 1 if you have the `stpcmp' function. */
+#undef HAVE_STPCMP
+
+/* Define to 1 if you have the dirent.h header. */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the sys/ndir.h header. */
+#undef HAVE_SYS_NDIR_H
+
+/* Define to 1 if you have the sys/dir.h header. */
+#undef HAVE_SYS_DIR_H
+
+/* Define to 1 if you have the ndir.h header. */
+#undef HAVE_NDIR_H
+
+/* Define to 1 if you have the sys/types.h header. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the opendir function.  */
+#undef HAVE_OPENDIR
