modula-2, driver, Front end: Revise handling of I and L paths [PR108182].

Message ID 20230117170431.52986-1-iain@sandoe.co.uk
State New
Headers
Series modula-2, driver, Front end: Revise handling of I and L paths [PR108182]. |

Commit Message

Iain Sandoe Jan. 17, 2023, 5:04 p.m. UTC
  Tested on x86_64-linux-gnu (with a 32b multilib), powerpc, i686 and
x86_64-darwin.  OK for trunk?
thanks,
Iain

--- 8< ---

The adds the includes in the FE as done in other GCC languages.
It also revises the library handling to avoid additional -L options
from hiding LIBDIR.

For the include/import paths as presented to the front end initialisation,
we capture them and then arrange to emit the 'standard library' paths in
the same order as specified for C.

The specs are tidied up.

Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>

	PR modula2/108182

gcc/m2/ChangeLog:

	* Make-lang.in: Pass libsubdir to the language init
	build.
	* gm2-lang.cc (INCLUDE_VECTOR): Define.
	(add_one_import_path): New.
	(add_m2_import_paths): New.
	(gm2_langhook_post_options): Arrange to add the include
	paths (and add the system ones) in the same order as C
	uses.
	* gm2spec.cc (build_archive_path): Remove.
	(add_default_combination): Remove.
	(add_default_archives): Remove.
	(add_default_libs): We no longer need a '-L' option, just
	emit the -l and each library in use.
	(build_include_path): Remove.
	(add_include): Remove.
	(add_default_includes): Remove.
	(library_installed): Remove.
	(check_valid_library): Remove.
	(check_valid_list): Remove.
	(convert_abbreviation): Diagnose unhandled cases.
	(lang_specific_driver): Skip options where we will add back
	a validated version.
	* lang-specs.h (M2CPP): Reformat, append %I when -fcpp is not
	in use.  Revise the cc1gm2 spec to omit mentioning options that
	are handled in the c pre-processor line.
	* lang.opt: Allow preprocessing and path options as input to the
	cc1gm2 invocation, so that they can be passed to the preprocessor
	invocation.
---
 gcc/m2/Make-lang.in |   1 +
 gcc/m2/gm2-lang.cc  | 168 ++++++++++++++++++++--
 gcc/m2/gm2spec.cc   | 344 ++++++++++++--------------------------------
 gcc/m2/lang-specs.h |  13 +-
 gcc/m2/lang.opt     |  48 +++++++
 5 files changed, 304 insertions(+), 270 deletions(-)
  

Comments

Richard Biener Jan. 23, 2023, 7:12 a.m. UTC | #1
On Tue, Jan 17, 2023 at 6:05 PM Iain Sandoe via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Tested on x86_64-linux-gnu (with a 32b multilib), powerpc, i686 and
> x86_64-darwin.  OK for trunk?

Reading through the patch I fear there's more issues lurking
(-sysroot?) but this seems to be
a step in the right direction, so OK for trunk unless Gaius has more
comments or objections.

Can you mention PR108480 in the commit log?

Thanks,
Richard.

> thanks,
> Iain
>
> --- 8< ---
>
> The adds the includes in the FE as done in other GCC languages.
> It also revises the library handling to avoid additional -L options
> from hiding LIBDIR.
>
> For the include/import paths as presented to the front end initialisation,
> we capture them and then arrange to emit the 'standard library' paths in
> the same order as specified for C.
>
> The specs are tidied up.
>
> Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
>
>         PR modula2/108182
>
> gcc/m2/ChangeLog:
>
>         * Make-lang.in: Pass libsubdir to the language init
>         build.
>         * gm2-lang.cc (INCLUDE_VECTOR): Define.
>         (add_one_import_path): New.
>         (add_m2_import_paths): New.
>         (gm2_langhook_post_options): Arrange to add the include
>         paths (and add the system ones) in the same order as C
>         uses.
>         * gm2spec.cc (build_archive_path): Remove.
>         (add_default_combination): Remove.
>         (add_default_archives): Remove.
>         (add_default_libs): We no longer need a '-L' option, just
>         emit the -l and each library in use.
>         (build_include_path): Remove.
>         (add_include): Remove.
>         (add_default_includes): Remove.
>         (library_installed): Remove.
>         (check_valid_library): Remove.
>         (check_valid_list): Remove.
>         (convert_abbreviation): Diagnose unhandled cases.
>         (lang_specific_driver): Skip options where we will add back
>         a validated version.
>         * lang-specs.h (M2CPP): Reformat, append %I when -fcpp is not
>         in use.  Revise the cc1gm2 spec to omit mentioning options that
>         are handled in the c pre-processor line.
>         * lang.opt: Allow preprocessing and path options as input to the
>         cc1gm2 invocation, so that they can be passed to the preprocessor
>         invocation.
> ---
>  gcc/m2/Make-lang.in |   1 +
>  gcc/m2/gm2-lang.cc  | 168 ++++++++++++++++++++--
>  gcc/m2/gm2spec.cc   | 344 ++++++++++++--------------------------------
>  gcc/m2/lang-specs.h |  13 +-
>  gcc/m2/lang.opt     |  48 +++++++
>  5 files changed, 304 insertions(+), 270 deletions(-)
>
> diff --git a/gcc/m2/Make-lang.in b/gcc/m2/Make-lang.in
> index 367be8e8af7..00cca7de617 100644
> --- a/gcc/m2/Make-lang.in
> +++ b/gcc/m2/Make-lang.in
> @@ -543,6 +543,7 @@ m2/gm2-gcc/m2configure.o: $(srcdir)/m2/gm2-gcc/m2configure.cc \
>
>  m2/gm2-lang.o: $(srcdir)/m2/gm2-lang.cc gt-m2-gm2-lang.h $(GCC_HEADER_DEPENDENCIES_FOR_M2)
>         $(COMPILER) -c -g $(GM2GCC) $(ALL_COMPILERFLAGS) \
> +           -DLIBSUBDIR=\"$(libsubdir)\" \
>              $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
>
>  m2/stor-layout.o: $(srcdir)/stor-layout.cc $(GCC_HEADER_DEPENDENCIES_FOR_M2)
> diff --git a/gcc/m2/gm2-lang.cc b/gcc/m2/gm2-lang.cc
> index b8123273368..98707430ef5 100644
> --- a/gcc/m2/gm2-lang.cc
> +++ b/gcc/m2/gm2-lang.cc
> @@ -20,6 +20,7 @@ along with GNU Modula-2; see the file COPYING.  If not, write to the
>  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
>  02110-1301, USA.  */
>
> +#define INCLUDE_VECTOR
>  #include "gm2-gcc/gcc-consolidation.h"
>
>  #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name.  */
> @@ -45,6 +46,18 @@ static void write_globals (void);
>
>  static int insideCppArgs = FALSE;
>
> +/* We default to pim in the absence of fiso.  */
> +static bool iso = false;
> +
> +/* The language include paths are based on the libraries in use.  */
> +static bool allow_libraries = true;
> +static const char *flibs = nullptr;
> +static const char *iprefix = nullptr;
> +static const char *imultilib = nullptr;
> +static std::vector<const char*>Ipaths;
> +static std::vector<const char*>isystem;
> +static std::vector<const char*>iquote;
> +
>  #define EXPR_STMT_EXPR(NODE) TREE_OPERAND (EXPR_STMT_CHECK (NODE), 0)
>
>  /* start of new stuff.  */
> @@ -198,34 +211,41 @@ gm2_langhook_handle_option (
>        return 1;
>      case OPT_I:
>        if (insideCppArgs)
> -        {
> -          const struct cl_option *option = &cl_options[scode];
> -          const char *opt = (const char *)option->opt_text;
> -          M2Options_CppArg (opt, arg, TRUE);
> -        }
> +       {
> +         const struct cl_option *option = &cl_options[scode];
> +         const char *opt = (const char *)option->opt_text;
> +         M2Options_CppArg (opt, arg, (option->flags & CL_JOINED)
> +                                      && !(option->flags & CL_SEPARATE));
> +       }
>        else
> -        M2Options_SetSearchPath (arg);
> +       Ipaths.push_back (arg);
>        return 1;
>      case OPT_fiso:
>        M2Options_SetISO (value);
> +      iso = value;
>        return 1;
>      case OPT_fpim:
>        M2Options_SetPIM (value);
> +      iso = value ? false : iso;
>        return 1;
>      case OPT_fpim2:
>        M2Options_SetPIM2 (value);
> +      iso = value ? false : iso;
>        return 1;
>      case OPT_fpim3:
>        M2Options_SetPIM3 (value);
> +      iso = value ? false : iso;
>        return 1;
>      case OPT_fpim4:
>        M2Options_SetPIM4 (value);
> +      iso = value ? false : iso;
>        return 1;
>      case OPT_fpositive_mod_floor_div:
>        M2Options_SetPositiveModFloor (value);
>        return 1;
>      case OPT_flibs_:
> -      /* handled in the gm2 driver.  */
> +      allow_libraries = value;
> +      flibs = arg;
>        return 1;
>      case OPT_fgen_module_list_:
>        M2Options_SetGenModuleList (value, arg);
> @@ -374,6 +394,30 @@ gm2_langhook_handle_option (
>      case OPT_fm2_g:
>        M2Options_SetM2g (value);
>        return 1;
> +      break;
> +    case OPT_iprefix:
> +    case OPT_imultilib:
> +    case OPT_isystem:
> +    case OPT_iquote:
> +    case OPT_isysroot:
> +      if (insideCppArgs)
> +       {
> +         const struct cl_option *option = &cl_options[scode];
> +         const char *opt = (const char *)option->opt_text;
> +         M2Options_CppArg (opt, arg, (option->flags & CL_JOINED)
> +                                      && !(option->flags & CL_SEPARATE));
> +       }
> +      if (code == OPT_iprefix)
> +       iprefix = arg;
> +      else if (code == OPT_imultilib)
> +       imultilib = arg;
> +      else if (code == OPT_iquote)
> +       iquote.push_back (arg);
> +      else if (code == OPT_isystem)
> +       isystem.push_back (arg);
> +      /* Otherwise, ignored, at least for now. */
> +      return 1;
> +      break;
>      case OPT_O:
>        M2Options_SetOptimizing (value);
>        return 1;
> @@ -412,18 +456,77 @@ gm2_langhook_handle_option (
>        return 1;
>      default:
>        if (insideCppArgs)
> -        {
> -          const struct cl_option *option = &cl_options[scode];
> -          const char *opt = (const char *)option->opt_text;
> -
> -          M2Options_CppArg (opt, arg, TRUE);
> -          return 1;
> -        }
> +       {
> +         const struct cl_option *option = &cl_options[scode];
> +         const char *opt = (const char *)option->opt_text;
> +         M2Options_CppArg (opt, arg, (option->flags & CL_JOINED)
> +                                      && !(option->flags & CL_SEPARATE));
> +         return 1;
> +       }
>        return 0;
>      }
>    return 0;
>  }
>
> +/* This prefixes LIBNAME with the current compiler prefix (if it has been
> +   relocated) or the LIBSUBDIR, if not.  */
> +static void
> +add_one_import_path (const char *libname)
> +{
> +  const char *libpath = iprefix ? iprefix : LIBSUBDIR;
> +  const char dir_sep[] = {DIR_SEPARATOR, (char)0};
> +  size_t dir_sep_size = strlen (dir_sep);
> +  unsigned int mlib_len = 0;
> +
> +  if (imultilib)
> +    {
> +      mlib_len = strlen (imultilib);
> +      mlib_len += strlen (dir_sep);
> +    }
> +
> +  char *lib = (char *)alloca (strlen (libpath) + dir_sep_size
> +                             + strlen ("m2") + dir_sep_size
> +                             + strlen (libname) + 1
> +                             + mlib_len + 1);
> +  strcpy (lib, libpath);
> +  /* iprefix has a trailing dir separator, LIBSUBDIR does not.  */
> +  if (!iprefix)
> +    strcat (lib, dir_sep);
> +
> +  if (imultilib)
> +    {
> +      strcat (lib, imultilib);
> +      strcat (lib, dir_sep);
> +    }
> +  strcat (lib, "m2");
> +  strcat (lib, dir_sep);
> +  strcat (lib, libname);
> +  M2Options_SetSearchPath (lib);
> +}
> +
> +/* For each comma-separated standard library name in LIBLIST, add the
> +   corresponding include path.  */
> +static void
> +add_m2_import_paths (const char *liblist)
> +{
> +  while (*liblist != 0 && *liblist != '-')
> +    {
> +      const char *comma = strstr (liblist, ",");
> +      size_t len;
> +      if (comma)
> +       len = comma - liblist;
> +      else
> +       len = strlen (liblist);
> +      char *libname = (char *) alloca (len+1);
> +      strncpy (libname, liblist, len);
> +      libname[len] = 0;
> +      add_one_import_path (libname);
> +      liblist += len;
> +      if (*liblist == ',')
> +       liblist++;
> +    }
> +}
> +
>  /* Run after parsing options.  */
>
>  static bool
> @@ -435,7 +538,42 @@ gm2_langhook_post_options (const char **pfilename)
>    M2Options_FinaliseOptions ();
>    main_input_filename = filename;
>
> -  /* Returning false means that the backend should be used.  */
> +  /* Add the include paths as per the libraries specified.
> +     NOTE: This assumes that the driver has validated the input and makes
> +     no attempt to be defensive of nonsense input in flibs=.  */
> +  if (allow_libraries)
> +    {
> +      if (!flibs)
> +       {
> +         if (iso)
> +           flibs = "m2iso,m2cor,m2pim,m2log";
> +         else
> +           flibs = "m2pim,m2iso,m2cor,m2log";
> +       }
> +    }
> +
> +  /* Add search paths.
> +     We are not handling all of the cases yet (e.g idirafter).
> +     This (barring the missing cases) is intended to follow the directory
> +     search rules used for c-family.  It would be less confusing if the
> +     presence of absence of these search paths was not dependent on the
> +     flibs= option. */
> +
> +  for (auto *s : iquote)
> +    M2Options_SetSearchPath (s);
> +  iquote.clear();
> +  for (auto *s : Ipaths)
> +    M2Options_SetSearchPath (s);
> +  Ipaths.clear();
> +  for (auto *s : isystem)
> +    M2Options_SetSearchPath (s);
> +  isystem.clear();
> +  /* FIXME: this is not a good way to suppress the addition of the import
> +     paths.  */
> +  if (allow_libraries)
> +    add_m2_import_paths (flibs);
> +
> + /* Returning false means that the backend should be used.  */
>    return false;
>  }
>
> diff --git a/gcc/m2/gm2spec.cc b/gcc/m2/gm2spec.cc
> index f964eccbf7a..c248d1bfcb2 100644
> --- a/gcc/m2/gm2spec.cc
> +++ b/gcc/m2/gm2spec.cc
> @@ -103,6 +103,7 @@ enum stdcxxlib_kind
>  };
>
>  #define DEFAULT_DIALECT "pim"
> +
>  #undef DEBUG_ARG
>
>  typedef enum { iso, pim, min, logitech, pimcoroutine, maxlib } libs;
> @@ -132,14 +133,13 @@ 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_dynamic = true; // Default uses -fscaffold-dynamic.
>  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;
> @@ -148,6 +148,8 @@ 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;
> +static const char *full_libraries = NULL;
> +static const char *libraries = NULL;  /* Abbreviated libraries.  */
>
>
>  /* Return whether strings S1 and S2 are both NULL or both the same
> @@ -227,50 +229,6 @@ append_option (size_t opt_index, const char *arg, int value)
>    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 *
> @@ -281,205 +239,65 @@ safe_strdup (const char *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)
> +static char *
> +concat_option (char *dest, const char *pre, const char *path, const char *post)
>  {
> -  if (library != NULL)
> +  if (dest == NULL)
>      {
> -      append_option (OPT_L, build_archive_path (libpath, library), 1);
> -      append_option (OPT_l, safe_strdup (library), 1);
> -      return true;
> +      dest = (char *) xmalloc (strlen (pre) + strlen (path) + strlen (post) + 1);
> +      strcpy (dest, pre);
> +      strcat (dest, path);
> +      strcat (dest, post);
> +      return dest;
> +    }
> +  else
> +    {
> +      char *result = (char *) xmalloc (strlen (dest) + strlen (pre)
> +                                      + strlen (path) + strlen (post) + 1 + 1);
> +      strcpy (result, dest);
> +      strcat (result, " ");
> +      strcat (result, pre);
> +      strcat (result, path);
> +      strcat (result, post);
> +      free (dest);
> +      return result;
>      }
> -  return false;
>  }
>
> -/* add_default_archives adds the default archives to the end of the
> -   current command line.  */
> +/* add_default_libs adds the -l option which is derived from the
> +   libraries.  */
>
>  static int
> -add_default_archives (const char *libpath, const char *libraries)
> +add_default_libs (const char *libraries)
>  {
>    const char *l = libraries;
>    const char *e;
>    char *libname;
>    unsigned int libcount = 0;
>
> -  do
> +  while ((l != NULL) && (l[0] != (char)0))
>      {
>        e = index (l, ',');
>        if (e == NULL)
>          {
>            libname = xstrdup (l);
>            l = NULL;
> -         if (add_default_combination (libpath, libname))
> -           libcount++;
> +         append_option (OPT_l, safe_strdup (libname), 1);
> +         libcount++;
>           free (libname);
>          }
>        else
>          {
>            libname = xstrndup (l, e - l);
>            l = e + 1;
> -         if (add_default_combination (libpath, libname))
> -           libcount++;
> +         append_option (OPT_l, safe_strdup (libname), 1);
> +         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
> @@ -509,8 +327,14 @@ 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);
> +  /* Perhaps the user typed in the whole lib name rather than an abbrev.  */
> +  for (int i = 0; i < maxlib; i++)
> +    if (strcmp (abbreviation, library_name[i]) == 0)
> +      return add_word (full_libraries, abbreviation);
> +  /* Not found, probably a user typo.  */
> +  error ("%qs is not a valid Modula-2 system library name or abbreviation",
> +        abbreviation);
> +  return full_libraries;
>  }
>
>  /* convert_abbreviations checks each element in the library list to
> @@ -535,7 +359,8 @@ convert_abbreviations (const char *libraries)
>          }
>        else
>          {
> -          full_libraries = convert_abbreviation (full_libraries, xstrndup (start, end - start));
> +         full_libraries = convert_abbreviation (full_libraries,
> +                                                xstrndup (start, end - start));
>            start = end + 1;
>          }
>      }
> @@ -572,9 +397,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>    /* 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.  */
> @@ -673,12 +496,15 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>         case OPT_flibs_:
>           libraries = xstrdup (arg);
>           allow_libraries = decoded_options[i].value;
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>           break;
>         case OPT_fmod_:
>           seen_module_extension = true;
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>           break;
>          case OPT_fpthread:
>            need_pthread = decoded_options[i].value;
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>            break;
>          case OPT_fm2_plugin:
>            need_plugin = decoded_options[i].value;
> @@ -687,24 +513,29 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>             error ("plugin support is disabled; configure with "
>                    "%<--enable-plugin%>");
>  #endif
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>            break;
>         case OPT_fscaffold_dynamic:
>           seen_scaffold_dynamic = true;
>           scaffold_dynamic = decoded_options[i].value;
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>           break;
>         case OPT_fscaffold_static:
>           seen_scaffold_static = true;
>           scaffold_static = decoded_options[i].value;
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>           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;
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>           break;
>         case OPT_fuse_list_:
>           seen_uselist = true;
>           uselist = decoded_options[i].value;
> +         args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
>           break;
>
>         case OPT_nostdlib:
> @@ -794,24 +625,23 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>           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);
> +         break;
>         }
>      }
>    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");
> -    }
> +  /* Override the default when the user specifies it.  */
> +  if (seen_scaffold_static && scaffold_static && !seen_scaffold_dynamic)
> +    scaffold_dynamic = false;
> +
> +  /* If both options have been seen and both are true, that means the user
> +     tried to set both.  */
> +  if (seen_scaffold_dynamic && scaffold_dynamic
> +     && seen_scaffold_static && scaffold_static)
> +    error ("%qs and %qs cannot both be enabled",
> +          "-fscaffold-dynamic", "-fscaffold-static");
> +
>    if (uselist && gen_module_list)
>      {
>        if (! seen_gen_module_list)
> @@ -855,32 +685,44 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>  #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.  */
> +  /* We now add in extra arguments to facilitate a successful link.
> +     Note that the libraries are added to the end of the link here
> +     and also placed earlier into the link by lang-specs.h.  Possibly
> +     this is needed because the m2pim,m2iso libraries are cross linked
> +     (--fixme-- combine all the m2 libraries into a single archive).
> +
> +     We also add 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);
>
> +  /* We checked that they were not both enabled above, if there was a set
> +     value (even iff that is 'off'), pass that to the FE.  */
> +  if (seen_scaffold_dynamic || scaffold_dynamic)
> +    append_option (OPT_fscaffold_dynamic, NULL, scaffold_dynamic);
> +  if (seen_scaffold_static)
> +    append_option (OPT_fscaffold_static, NULL, scaffold_static);
> +
>    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 the libraries have not been specified by the user, select the
> +        appropriate libraries for the active dialect.  */
>        if (libraries == NULL)
>         {
>           if (strcmp (dialect, "iso") == 0)
> -           libraries = xstrdup ("m2iso,m2pim");
> +           libraries = xstrdup ("m2iso,m2cor,m2pim,m2log");
>           else
> -           /* Default to pim libraries if none specified.  */
> -           libraries = xstrdup ("m2pim,m2log,m2iso");
> +           /* Default to pim libraries otherwise.  */
> +           libraries = xstrdup ("m2pim,m2iso,m2cor,m2log");
>         }
>        libraries = convert_abbreviations (libraries);
> -      if (! check_valid_list (libpath, libraries))
> -       return;
> -      add_default_includes (libpath, libraries);
> +      append_option (OPT_flibs_, xstrdup (libraries), 1);
>      }
> +  else
> +    append_option (OPT_flibs_, xstrdup ("-"), 0); /* no system libs.  */
> +
>    if ((! seen_x_flag) && seen_module_extension)
>      append_option (OPT_x, "modula-2", 1);
>
> @@ -889,16 +731,19 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options,
>
>    if (linking)
>      {
> +      if (allow_libraries)
> +       {
>  #ifdef HAVE_LD_STATIC_DYNAMIC
> -      if (allow_libraries && !shared_libgm2)
> -       append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
> +         if (!shared_libgm2)
> +           append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
>  #endif
> -      if (allow_libraries)
> -       add_default_archives (libpath, libraries);
> +         added_libraries += add_default_libs (libraries);
>  #ifdef HAVE_LD_STATIC_DYNAMIC
> -      if (allow_libraries && !shared_libgm2)
> -       append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
> +         if (!shared_libgm2)
> +           append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
>  #endif
> +       }
> +
>        /* Add `-lstdc++' if we haven't already done so.  */
>  #ifdef HAVE_LD_STATIC_DYNAMIC
>        if (library > 1 && !static_link)
> @@ -962,6 +807,7 @@ lang_specific_driver (struct cl_decoded_option **in_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.  */
> diff --git a/gcc/m2/lang-specs.h b/gcc/m2/lang-specs.h
> index 92dc20fba5e..bf882649b21 100644
> --- a/gcc/m2/lang-specs.h
> +++ b/gcc/m2/lang-specs.h
> @@ -24,15 +24,16 @@ along with GCC; see the file COPYING3.  If not see
>  /* 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}"
> +#define M2CPP \
> +  "%{fcpp:-fcpp-begin " \
> +  "      -E -lang-asm -traditional-cpp " \
> +  "      %(cpp_unique_options) -fcpp-end; \
> +     : %I } "
>
>    {".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*} %{v} "
> +      "      %(cc1_options) %{B*} %{c*} %{+e*} %{I*} "
> +      "      %{i*} %{save-temps*} %{v} "
>        "      %i %{!fsyntax-only:%(invoke_as)}",
>        0, 0, 0},
> diff --git a/gcc/m2/lang.opt b/gcc/m2/lang.opt
> index 6586fd6fa2c..7a19adc0790 100644
> --- a/gcc/m2/lang.opt
> +++ b/gcc/m2/lang.opt
> @@ -50,6 +50,50 @@ M
>  Modula-2
>  ; Documented in c.opt
>
> +MD
> +Modula-2
> +; Documented in c.opt
> +
> +MF
> +Modula-2
> +; Documented in c.opt
> +
> +MG
> +Modula-2
> +; Documented in c.opt
> +
> +MM
> +Modula-2
> +; Documented in c.opt
> +
> +MMD
> +Modula-2
> +; Documented in c.opt
> +
> +Mmodules
> +Modula-2
> +; Documented in c.opt
> +
> +Mno-modules
> +Modula-2
> +; Documented in c.opt
> +
> +MP
> +Modula-2
> +; Documented in c.opt
> +
> +MQ
> +Modula-2
> +; Documented in c.opt
> +
> +MT
> +Modula-2
> +; Documented in c.opt
> +
> +P
> +Modula-2
> +; Documented in c.opt
> +
>  O
>  Modula-2
>  ; Documented in c.opt
> @@ -310,6 +354,10 @@ iprefix
>  Modula-2
>  ; Documented in c.opt
>
> +iquote
> +Modula-2
> +; Documented in c.opt
> +
>  isystem
>  Modula-2
>  ; Documented in c.opt
> --
> 2.37.1 (Apple Git-137.1)
>
  
Gaius Mulley Jan. 23, 2023, 3:20 p.m. UTC | #2
Iain Sandoe <iains.gcc@gmail.com> writes:

> Tested on x86_64-linux-gnu (with a 32b multilib), powerpc, i686 and
> x86_64-darwin.  OK for trunk?
> thanks,
> Iain
>
> --- 8< ---
>
> The adds the includes in the FE as done in other GCC languages.
> It also revises the library handling to avoid additional -L options
> from hiding LIBDIR.
>
> For the include/import paths as presented to the front end initialisation,
> we capture them and then arrange to emit the 'standard library' paths in
> the same order as specified for C.
>
> The specs are tidied up.

yes LGTM - apologies for the delay

thank you!
Gaius
  

Patch

diff --git a/gcc/m2/Make-lang.in b/gcc/m2/Make-lang.in
index 367be8e8af7..00cca7de617 100644
--- a/gcc/m2/Make-lang.in
+++ b/gcc/m2/Make-lang.in
@@ -543,6 +543,7 @@  m2/gm2-gcc/m2configure.o: $(srcdir)/m2/gm2-gcc/m2configure.cc \
 
 m2/gm2-lang.o: $(srcdir)/m2/gm2-lang.cc gt-m2-gm2-lang.h $(GCC_HEADER_DEPENDENCIES_FOR_M2)
 	$(COMPILER) -c -g $(GM2GCC) $(ALL_COMPILERFLAGS) \
+	    -DLIBSUBDIR=\"$(libsubdir)\" \
             $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
 
 m2/stor-layout.o: $(srcdir)/stor-layout.cc $(GCC_HEADER_DEPENDENCIES_FOR_M2)
diff --git a/gcc/m2/gm2-lang.cc b/gcc/m2/gm2-lang.cc
index b8123273368..98707430ef5 100644
--- a/gcc/m2/gm2-lang.cc
+++ b/gcc/m2/gm2-lang.cc
@@ -20,6 +20,7 @@  along with GNU Modula-2; see the file COPYING.  If not, write to the
 Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA.  */
 
+#define INCLUDE_VECTOR
 #include "gm2-gcc/gcc-consolidation.h"
 
 #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name.  */
@@ -45,6 +46,18 @@  static void write_globals (void);
 
 static int insideCppArgs = FALSE;
 
+/* We default to pim in the absence of fiso.  */
+static bool iso = false;
+
+/* The language include paths are based on the libraries in use.  */
+static bool allow_libraries = true;
+static const char *flibs = nullptr;
+static const char *iprefix = nullptr;
+static const char *imultilib = nullptr;
+static std::vector<const char*>Ipaths;
+static std::vector<const char*>isystem;
+static std::vector<const char*>iquote;
+
 #define EXPR_STMT_EXPR(NODE) TREE_OPERAND (EXPR_STMT_CHECK (NODE), 0)
 
 /* start of new stuff.  */
@@ -198,34 +211,41 @@  gm2_langhook_handle_option (
       return 1;
     case OPT_I:
       if (insideCppArgs)
-        {
-          const struct cl_option *option = &cl_options[scode];
-          const char *opt = (const char *)option->opt_text;
-          M2Options_CppArg (opt, arg, TRUE);
-        }
+	{
+	  const struct cl_option *option = &cl_options[scode];
+	  const char *opt = (const char *)option->opt_text;
+	  M2Options_CppArg (opt, arg, (option->flags & CL_JOINED)
+				       && !(option->flags & CL_SEPARATE));
+	}
       else
-        M2Options_SetSearchPath (arg);
+	Ipaths.push_back (arg);
       return 1;
     case OPT_fiso:
       M2Options_SetISO (value);
+      iso = value;
       return 1;
     case OPT_fpim:
       M2Options_SetPIM (value);
+      iso = value ? false : iso;
       return 1;
     case OPT_fpim2:
       M2Options_SetPIM2 (value);
+      iso = value ? false : iso;
       return 1;
     case OPT_fpim3:
       M2Options_SetPIM3 (value);
+      iso = value ? false : iso;
       return 1;
     case OPT_fpim4:
       M2Options_SetPIM4 (value);
+      iso = value ? false : iso;
       return 1;
     case OPT_fpositive_mod_floor_div:
       M2Options_SetPositiveModFloor (value);
       return 1;
     case OPT_flibs_:
-      /* handled in the gm2 driver.  */
+      allow_libraries = value;
+      flibs = arg;
       return 1;
     case OPT_fgen_module_list_:
       M2Options_SetGenModuleList (value, arg);
@@ -374,6 +394,30 @@  gm2_langhook_handle_option (
     case OPT_fm2_g:
       M2Options_SetM2g (value);
       return 1;
+      break;
+    case OPT_iprefix:
+    case OPT_imultilib:
+    case OPT_isystem:
+    case OPT_iquote:
+    case OPT_isysroot:
+      if (insideCppArgs)
+	{
+	  const struct cl_option *option = &cl_options[scode];
+	  const char *opt = (const char *)option->opt_text;
+	  M2Options_CppArg (opt, arg, (option->flags & CL_JOINED)
+				       && !(option->flags & CL_SEPARATE));
+	}
+      if (code == OPT_iprefix)
+	iprefix = arg;
+      else if (code == OPT_imultilib)
+	imultilib = arg;
+      else if (code == OPT_iquote)
+	iquote.push_back (arg);
+      else if (code == OPT_isystem)
+	isystem.push_back (arg);
+      /* Otherwise, ignored, at least for now. */
+      return 1;
+      break;
     case OPT_O:
       M2Options_SetOptimizing (value);
       return 1;
@@ -412,18 +456,77 @@  gm2_langhook_handle_option (
       return 1;
     default:
       if (insideCppArgs)
-        {
-          const struct cl_option *option = &cl_options[scode];
-          const char *opt = (const char *)option->opt_text;
-
-          M2Options_CppArg (opt, arg, TRUE);
-          return 1;
-        }
+	{
+	  const struct cl_option *option = &cl_options[scode];
+	  const char *opt = (const char *)option->opt_text;
+	  M2Options_CppArg (opt, arg, (option->flags & CL_JOINED)
+				       && !(option->flags & CL_SEPARATE));
+	  return 1;
+	}
       return 0;
     }
   return 0;
 }
 
+/* This prefixes LIBNAME with the current compiler prefix (if it has been
+   relocated) or the LIBSUBDIR, if not.  */
+static void
+add_one_import_path (const char *libname)
+{
+  const char *libpath = iprefix ? iprefix : LIBSUBDIR;
+  const char dir_sep[] = {DIR_SEPARATOR, (char)0};
+  size_t dir_sep_size = strlen (dir_sep);
+  unsigned int mlib_len = 0;
+
+  if (imultilib)
+    {
+      mlib_len = strlen (imultilib);
+      mlib_len += strlen (dir_sep);
+    }
+
+  char *lib = (char *)alloca (strlen (libpath) + dir_sep_size
+			      + strlen ("m2") + dir_sep_size
+			      + strlen (libname) + 1
+			      + mlib_len + 1);
+  strcpy (lib, libpath);
+  /* iprefix has a trailing dir separator, LIBSUBDIR does not.  */
+  if (!iprefix)
+    strcat (lib, dir_sep);
+
+  if (imultilib)
+    {
+      strcat (lib, imultilib);
+      strcat (lib, dir_sep);
+    }
+  strcat (lib, "m2");
+  strcat (lib, dir_sep);
+  strcat (lib, libname);
+  M2Options_SetSearchPath (lib);
+}
+
+/* For each comma-separated standard library name in LIBLIST, add the
+   corresponding include path.  */
+static void
+add_m2_import_paths (const char *liblist)
+{
+  while (*liblist != 0 && *liblist != '-')
+    {
+      const char *comma = strstr (liblist, ",");
+      size_t len;
+      if (comma)
+	len = comma - liblist;
+      else
+	len = strlen (liblist);
+      char *libname = (char *) alloca (len+1);
+      strncpy (libname, liblist, len);
+      libname[len] = 0;
+      add_one_import_path (libname);
+      liblist += len;
+      if (*liblist == ',')
+	liblist++;
+    }
+}
+
 /* Run after parsing options.  */
 
 static bool
@@ -435,7 +538,42 @@  gm2_langhook_post_options (const char **pfilename)
   M2Options_FinaliseOptions ();
   main_input_filename = filename;
 
-  /* Returning false means that the backend should be used.  */
+  /* Add the include paths as per the libraries specified.
+     NOTE: This assumes that the driver has validated the input and makes
+     no attempt to be defensive of nonsense input in flibs=.  */
+  if (allow_libraries)
+    {
+      if (!flibs)
+	{
+	  if (iso)
+	    flibs = "m2iso,m2cor,m2pim,m2log";
+	  else
+	    flibs = "m2pim,m2iso,m2cor,m2log";
+	}
+    }
+
+  /* Add search paths.
+     We are not handling all of the cases yet (e.g idirafter).
+     This (barring the missing cases) is intended to follow the directory
+     search rules used for c-family.  It would be less confusing if the
+     presence of absence of these search paths was not dependent on the
+     flibs= option. */
+
+  for (auto *s : iquote)
+    M2Options_SetSearchPath (s);
+  iquote.clear();
+  for (auto *s : Ipaths)
+    M2Options_SetSearchPath (s);
+  Ipaths.clear();
+  for (auto *s : isystem)
+    M2Options_SetSearchPath (s);
+  isystem.clear();
+  /* FIXME: this is not a good way to suppress the addition of the import
+     paths.  */
+  if (allow_libraries)
+    add_m2_import_paths (flibs);
+
+ /* Returning false means that the backend should be used.  */
   return false;
 }
 
diff --git a/gcc/m2/gm2spec.cc b/gcc/m2/gm2spec.cc
index f964eccbf7a..c248d1bfcb2 100644
--- a/gcc/m2/gm2spec.cc
+++ b/gcc/m2/gm2spec.cc
@@ -103,6 +103,7 @@  enum stdcxxlib_kind
 };
 
 #define DEFAULT_DIALECT "pim"
+
 #undef DEBUG_ARG
 
 typedef enum { iso, pim, min, logitech, pimcoroutine, maxlib } libs;
@@ -132,14 +133,13 @@  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_dynamic = true; // Default uses -fscaffold-dynamic.
 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;
@@ -148,6 +148,8 @@  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;
+static const char *full_libraries = NULL;
+static const char *libraries = NULL;  /* Abbreviated libraries.  */
 
 
 /* Return whether strings S1 and S2 are both NULL or both the same
@@ -227,50 +229,6 @@  append_option (size_t opt_index, const char *arg, int value)
   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 *
@@ -281,205 +239,65 @@  safe_strdup (const char *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)
+static char *
+concat_option (char *dest, const char *pre, const char *path, const char *post)
 {
-  if (library != NULL)
+  if (dest == NULL)
     {
-      append_option (OPT_L, build_archive_path (libpath, library), 1);
-      append_option (OPT_l, safe_strdup (library), 1);
-      return true;
+      dest = (char *) xmalloc (strlen (pre) + strlen (path) + strlen (post) + 1);
+      strcpy (dest, pre);
+      strcat (dest, path);
+      strcat (dest, post);
+      return dest;
+    }
+  else
+    {
+      char *result = (char *) xmalloc (strlen (dest) + strlen (pre)
+				       + strlen (path) + strlen (post) + 1 + 1);
+      strcpy (result, dest);
+      strcat (result, " ");
+      strcat (result, pre);
+      strcat (result, path);
+      strcat (result, post);
+      free (dest);
+      return result;
     }
-  return false;
 }
 
-/* add_default_archives adds the default archives to the end of the
-   current command line.  */
+/* add_default_libs adds the -l option which is derived from the
+   libraries.  */
 
 static int
-add_default_archives (const char *libpath, const char *libraries)
+add_default_libs (const char *libraries)
 {
   const char *l = libraries;
   const char *e;
   char *libname;
   unsigned int libcount = 0;
 
-  do
+  while ((l != NULL) && (l[0] != (char)0))
     {
       e = index (l, ',');
       if (e == NULL)
         {
           libname = xstrdup (l);
           l = NULL;
-	  if (add_default_combination (libpath, libname))
-	    libcount++;
+	  append_option (OPT_l, safe_strdup (libname), 1);
+	  libcount++;
 	  free (libname);
         }
       else
         {
           libname = xstrndup (l, e - l);
           l = e + 1;
-	  if (add_default_combination (libpath, libname))
-	    libcount++;
+	  append_option (OPT_l, safe_strdup (libname), 1);
+	  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
@@ -509,8 +327,14 @@  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);
+  /* Perhaps the user typed in the whole lib name rather than an abbrev.  */
+  for (int i = 0; i < maxlib; i++)
+    if (strcmp (abbreviation, library_name[i]) == 0)
+      return add_word (full_libraries, abbreviation);
+  /* Not found, probably a user typo.  */
+  error ("%qs is not a valid Modula-2 system library name or abbreviation",
+	 abbreviation);
+  return full_libraries;
 }
 
 /* convert_abbreviations checks each element in the library list to
@@ -535,7 +359,8 @@  convert_abbreviations (const char *libraries)
         }
       else
         {
-          full_libraries = convert_abbreviation (full_libraries, xstrndup (start, end - start));
+	  full_libraries = convert_abbreviation (full_libraries,
+						 xstrndup (start, end - start));
           start = end + 1;
         }
     }
@@ -572,9 +397,7 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
   /* 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.  */
@@ -673,12 +496,15 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 	case OPT_flibs_:
 	  libraries = xstrdup (arg);
 	  allow_libraries = decoded_options[i].value;
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
 	  break;
 	case OPT_fmod_:
 	  seen_module_extension = true;
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
 	  break;
         case OPT_fpthread:
           need_pthread = decoded_options[i].value;
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
           break;
         case OPT_fm2_plugin:
           need_plugin = decoded_options[i].value;
@@ -687,24 +513,29 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 	    error ("plugin support is disabled; configure with "
 		   "%<--enable-plugin%>");
 #endif
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
           break;
 	case OPT_fscaffold_dynamic:
 	  seen_scaffold_dynamic = true;
 	  scaffold_dynamic = decoded_options[i].value;
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
 	  break;
 	case OPT_fscaffold_static:
 	  seen_scaffold_static = true;
 	  scaffold_static = decoded_options[i].value;
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
 	  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;
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
 	  break;
 	case OPT_fuse_list_:
 	  seen_uselist = true;
 	  uselist = decoded_options[i].value;
+	  args[i] |= SKIPOPT; /* We will add the option if it is needed.  */
 	  break;
 
 	case OPT_nostdlib:
@@ -794,24 +625,23 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 	  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);
+	  break;
 	}
     }
   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");
-    }
+  /* Override the default when the user specifies it.  */
+  if (seen_scaffold_static && scaffold_static && !seen_scaffold_dynamic)
+    scaffold_dynamic = false;
+
+  /* If both options have been seen and both are true, that means the user
+     tried to set both.  */
+  if (seen_scaffold_dynamic && scaffold_dynamic
+     && seen_scaffold_static && scaffold_static)
+    error ("%qs and %qs cannot both be enabled",
+	   "-fscaffold-dynamic", "-fscaffold-static");
+
   if (uselist && gen_module_list)
     {
       if (! seen_gen_module_list)
@@ -855,32 +685,44 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 #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.  */
+  /* We now add in extra arguments to facilitate a successful link.
+     Note that the libraries are added to the end of the link here
+     and also placed earlier into the link by lang-specs.h.  Possibly
+     this is needed because the m2pim,m2iso libraries are cross linked
+     (--fixme-- combine all the m2 libraries into a single archive).
+
+     We also add 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);
 
+  /* We checked that they were not both enabled above, if there was a set
+     value (even iff that is 'off'), pass that to the FE.  */
+  if (seen_scaffold_dynamic || scaffold_dynamic)
+    append_option (OPT_fscaffold_dynamic, NULL, scaffold_dynamic);
+  if (seen_scaffold_static)
+    append_option (OPT_fscaffold_static, NULL, scaffold_static);
+
   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 the libraries have not been specified by the user, select the
+	 appropriate libraries for the active dialect.  */
       if (libraries == NULL)
 	{
 	  if (strcmp (dialect, "iso") == 0)
-	    libraries = xstrdup ("m2iso,m2pim");
+	    libraries = xstrdup ("m2iso,m2cor,m2pim,m2log");
 	  else
-	    /* Default to pim libraries if none specified.  */
-	    libraries = xstrdup ("m2pim,m2log,m2iso");
+	    /* Default to pim libraries otherwise.  */
+	    libraries = xstrdup ("m2pim,m2iso,m2cor,m2log");
 	}
       libraries = convert_abbreviations (libraries);
-      if (! check_valid_list (libpath, libraries))
-	return;
-      add_default_includes (libpath, libraries);
+      append_option (OPT_flibs_, xstrdup (libraries), 1);
     }
+  else
+    append_option (OPT_flibs_, xstrdup ("-"), 0); /* no system libs.  */
+
   if ((! seen_x_flag) && seen_module_extension)
     append_option (OPT_x, "modula-2", 1);
 
@@ -889,16 +731,19 @@  lang_specific_driver (struct cl_decoded_option **in_decoded_options,
 
   if (linking)
     {
+      if (allow_libraries)
+	{
 #ifdef HAVE_LD_STATIC_DYNAMIC
-      if (allow_libraries && !shared_libgm2)
-	append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
+	  if (!shared_libgm2)
+	    append_option (OPT_Wl_, LD_STATIC_OPTION, 1);
 #endif
-      if (allow_libraries)
-	add_default_archives (libpath, libraries);
+	  added_libraries += add_default_libs (libraries);
 #ifdef HAVE_LD_STATIC_DYNAMIC
-      if (allow_libraries && !shared_libgm2)
-	append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
+	  if (!shared_libgm2)
+	    append_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1);
 #endif
+	}
+
       /* Add `-lstdc++' if we haven't already done so.  */
 #ifdef HAVE_LD_STATIC_DYNAMIC
       if (library > 1 && !static_link)
@@ -962,6 +807,7 @@  lang_specific_driver (struct cl_decoded_option **in_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.  */
diff --git a/gcc/m2/lang-specs.h b/gcc/m2/lang-specs.h
index 92dc20fba5e..bf882649b21 100644
--- a/gcc/m2/lang-specs.h
+++ b/gcc/m2/lang-specs.h
@@ -24,15 +24,16 @@  along with GCC; see the file COPYING3.  If not see
 /* 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}"
+#define M2CPP \
+  "%{fcpp:-fcpp-begin " \
+  "      -E -lang-asm -traditional-cpp " \
+  "      %(cpp_unique_options) -fcpp-end; \
+     : %I } "
 
   {".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*} %{v} "
+      "      %(cc1_options) %{B*} %{c*} %{+e*} %{I*} "
+      "      %{i*} %{save-temps*} %{v} "
       "      %i %{!fsyntax-only:%(invoke_as)}",
       0, 0, 0},
diff --git a/gcc/m2/lang.opt b/gcc/m2/lang.opt
index 6586fd6fa2c..7a19adc0790 100644
--- a/gcc/m2/lang.opt
+++ b/gcc/m2/lang.opt
@@ -50,6 +50,50 @@  M
 Modula-2
 ; Documented in c.opt
 
+MD
+Modula-2
+; Documented in c.opt
+
+MF
+Modula-2
+; Documented in c.opt
+
+MG
+Modula-2
+; Documented in c.opt
+
+MM
+Modula-2
+; Documented in c.opt
+
+MMD
+Modula-2
+; Documented in c.opt
+
+Mmodules
+Modula-2
+; Documented in c.opt
+
+Mno-modules
+Modula-2
+; Documented in c.opt
+
+MP
+Modula-2
+; Documented in c.opt
+
+MQ
+Modula-2
+; Documented in c.opt
+
+MT
+Modula-2
+; Documented in c.opt
+
+P
+Modula-2
+; Documented in c.opt
+
 O
 Modula-2
 ; Documented in c.opt
@@ -310,6 +354,10 @@  iprefix
 Modula-2
 ; Documented in c.opt
 
+iquote
+Modula-2
+; Documented in c.opt
+
 isystem
 Modula-2
 ; Documented in c.opt