]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Renamed files from .c to .cc and added new support header files.
authorGaius Mulley <gaius.mulley@southwales.ac.uk>
Wed, 29 Jun 2022 00:37:38 +0000 (01:37 +0100)
committerGaius Mulley <gaius.mulley@southwales.ac.uk>
Wed, 29 Jun 2022 00:37:38 +0000 (01:37 +0100)
This patch also includes a mc-boot translated copy of the
module M2Dependent.

gcc/m2/ChangeLog:

* gm2-libs-ch/UnixArgs.cc: Renamed from gm2-libs-ch/UnixArgs.c.
* gm2-libs-ch/dtoa.cc: Renamed from gm2-libs-ch/dtoa.c.
* gm2-libs-ch/ldtoa.cc: Renamed from gm2-libs-ch/ldtoa.c.
* gm2-libs-ch/m2rts.h: New file.
* mc-boot-ch/GUnixArgs.cc: New file.
* mc-boot-ch/m2rts.h: New file.
* mc-boot/GM2Dependent.c: New file.
* mc-boot/GM2Dependent.h: New file.

Signed-off-by: Gaius Mulley <gaius.mulley@southwales.ac.uk>
gcc/m2/gm2-libs-ch/UnixArgs.cc [moved from gcc/m2/gm2-libs-ch/UnixArgs.c with 100% similarity]
gcc/m2/gm2-libs-ch/dtoa.cc [moved from gcc/m2/gm2-libs-ch/dtoa.c with 100% similarity]
gcc/m2/gm2-libs-ch/ldtoa.cc [moved from gcc/m2/gm2-libs-ch/ldtoa.c with 100% similarity]
gcc/m2/gm2-libs-ch/m2rts.h [new file with mode: 0644]
gcc/m2/mc-boot-ch/GUnixArgs.cc [new file with mode: 0644]
gcc/m2/mc-boot-ch/m2rts.h [new file with mode: 0644]
gcc/m2/mc-boot/GM2Dependent.c [new file with mode: 0644]
gcc/m2/mc-boot/GM2Dependent.h [new file with mode: 0644]

diff --git a/gcc/m2/gm2-libs-ch/m2rts.h b/gcc/m2/gm2-libs-ch/m2rts.h
new file mode 100644 (file)
index 0000000..57e6e90
--- /dev/null
@@ -0,0 +1,41 @@
+/* m2rts.h provides a C interface to M2RTS.mod.
+
+Copyright (C) 2019-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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+
+typedef void (*proc_con) (int, char **, char **);
+typedef void (*proc_dep) (void);
+
+extern "C" void M2RTS_RequestDependant (const char *modulename, const char *dependancy);
+extern "C" void M2RTS_RegisterModule (const char *modulename,
+                                     proc_con init, proc_con fini, proc_dep dependencies);
+extern "C" void _M2_M2RTS_init (void);
+
+extern "C" void M2RTS_ConstructModules (const char *,
+                                       int argc, char *argv[], char *envp[]);
+extern "C" void M2RTS_Terminate (void);
+extern "C" void M2RTS_DeconstructModules (void);
+
+extern "C" void M2RTS_Halt (const char *, int, const char *, const char *) __attribute__ ((noreturn));
diff --git a/gcc/m2/mc-boot-ch/GUnixArgs.cc b/gcc/m2/mc-boot-ch/GUnixArgs.cc
new file mode 100644 (file)
index 0000000..1180f35
--- /dev/null
@@ -0,0 +1,91 @@
+/* UnixArgs.cc record argc, argv as global variables.
+
+Copyright (C) 2009-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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include "m2rts.h"
+
+
+extern "C" int UnixArgs_GetArgC (void);
+extern "C" char **UnixArgs_GetArgV (void);
+extern "C" char **UnixArgs_GetEnvV (void);
+
+static int UnixArgs_ArgC;
+static char **UnixArgs_ArgV;
+static char **UnixArgs_EnvV;
+
+
+/* GetArgC returns argc.  */
+
+extern "C" int
+UnixArgs_GetArgC (void)
+{
+  return UnixArgs_ArgC;
+}
+
+
+/* GetArgV returns argv.  */
+
+extern "C" char **
+UnixArgs_GetArgV (void)
+{
+  return UnixArgs_ArgV;
+}
+
+
+/* GetEnvV returns envv.  */
+
+extern "C" char **
+UnixArgs_GetEnvV (void)
+{
+  return UnixArgs_EnvV;
+}
+
+
+extern "C" void
+_M2_UnixArgs_init (int argc, char *argv[], char *envp[])
+{
+  UnixArgs_ArgC = argc;
+  UnixArgs_ArgV = argv;
+  UnixArgs_EnvV = envp;
+}
+
+extern "C" void
+_M2_UnixArgs_finish (int argc, char *argv[], char *envp[])
+{
+}
+
+extern "C" void
+_M2_UnixArgs_dep (void)
+{
+}
+
+struct _M2_UnixArgs_ctor { _M2_UnixArgs_ctor (); } _M2_UnixArgs_ctor;
+
+_M2_UnixArgs_ctor::_M2_UnixArgs_ctor (void)
+{
+  M2RTS_RegisterModule ("UnixArgs", _M2_UnixArgs_init, _M2_UnixArgs_finish,
+                       _M2_UnixArgs_dep);
+}
diff --git a/gcc/m2/mc-boot-ch/m2rts.h b/gcc/m2/mc-boot-ch/m2rts.h
new file mode 100644 (file)
index 0000000..57e6e90
--- /dev/null
@@ -0,0 +1,41 @@
+/* m2rts.h provides a C interface to M2RTS.mod.
+
+Copyright (C) 2019-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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+
+typedef void (*proc_con) (int, char **, char **);
+typedef void (*proc_dep) (void);
+
+extern "C" void M2RTS_RequestDependant (const char *modulename, const char *dependancy);
+extern "C" void M2RTS_RegisterModule (const char *modulename,
+                                     proc_con init, proc_con fini, proc_dep dependencies);
+extern "C" void _M2_M2RTS_init (void);
+
+extern "C" void M2RTS_ConstructModules (const char *,
+                                       int argc, char *argv[], char *envp[]);
+extern "C" void M2RTS_Terminate (void);
+extern "C" void M2RTS_DeconstructModules (void);
+
+extern "C" void M2RTS_Halt (const char *, int, const char *, const char *) __attribute__ ((noreturn));
diff --git a/gcc/m2/mc-boot/GM2Dependent.c b/gcc/m2/mc-boot/GM2Dependent.c
new file mode 100644 (file)
index 0000000..d677798
--- /dev/null
@@ -0,0 +1,1113 @@
+/* do not edit automatically generated by mc from M2Dependent.  */
+/* M2Dependent.mod implements the run time module dependencies.
+
+Copyright (C) 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#   if !defined (PROC_D)
+#      define PROC_D
+       typedef void (*PROC_t) (void);
+       typedef struct { PROC_t proc; } PROC;
+#   endif
+
+#   if !defined (TRUE)
+#      define TRUE (1==1)
+#   endif
+
+#   if !defined (FALSE)
+#      define FALSE (1==0)
+#   endif
+
+#   include "GStorage.h"
+#if defined(__cplusplus)
+#   undef NULL
+#   define NULL 0
+#endif
+#define _M2Dependent_H
+#define _M2Dependent_C
+
+#   include "Glibc.h"
+#   include "GM2LINK.h"
+#   include "GASCII.h"
+#   include "GSYSTEM.h"
+#   include "GStorage.h"
+#   include "GStrLib.h"
+#   include "GM2RTS.h"
+
+typedef struct M2Dependent_ArgCVEnvP_p M2Dependent_ArgCVEnvP;
+
+typedef struct DependencyList_r DependencyList;
+
+typedef struct _T2_r _T2;
+
+typedef _T2 *ModuleChain;
+
+typedef struct _T3_a _T3;
+
+typedef enum {unregistered, unordered, started, ordered, user} DependencyState;
+
+typedef void (*M2Dependent_ArgCVEnvP_t) (int, void *, void *);
+struct M2Dependent_ArgCVEnvP_p { M2Dependent_ArgCVEnvP_t proc; };
+
+struct DependencyList_r {
+                          PROC proc;
+                          unsigned int forced;
+                          unsigned int forc;
+                          unsigned int appl;
+                          DependencyState state;
+                        };
+
+struct _T3_a { ModuleChain array[user-unregistered+1]; };
+struct _T2_r {
+               void *name;
+               M2Dependent_ArgCVEnvP init;
+               M2Dependent_ArgCVEnvP fini;
+               DependencyList dependency;
+               ModuleChain prev;
+               ModuleChain next;
+             };
+
+static _T3 Modules;
+static unsigned int Initialized;
+static unsigned int ModuleTrace;
+static unsigned int DependencyTrace;
+static unsigned int PreTrace;
+static unsigned int PostTrace;
+static unsigned int ForceTrace;
+
+/*
+   ConstructModules - resolve dependencies and then call each
+                      module constructor in turn.
+*/
+
+extern "C" void M2Dependent_ConstructModules (void * applicationmodule, int argc, void * argv, void * envp);
+
+/*
+   DeconstructModules - resolve dependencies and then call each
+                        module constructor in turn.
+*/
+
+extern "C" void M2Dependent_DeconstructModules (void * applicationmodule, int argc, void * argv, void * envp);
+
+/*
+   RegisterModule - adds module name to the list of outstanding
+                    modules which need to have their dependencies
+                    explored to determine initialization order.
+*/
+
+extern "C" void M2Dependent_RegisterModule (void * name, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies);
+
+/*
+   RequestDependant - used to specify that modulename is dependant upon
+                      module dependantmodule.  It only takes effect
+                      if we are not using StaticInitialization.
+*/
+
+extern "C" void M2Dependent_RequestDependant (void * modulename, void * dependantmodule);
+
+/*
+   CreateModule - creates a new module entry and returns the
+                  ModuleChain.
+*/
+
+static ModuleChain CreateModule (void * name, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies);
+
+/*
+   AppendModule - append chain to end of the list.
+*/
+
+static void AppendModule (ModuleChain *head, ModuleChain chain);
+
+/*
+   RemoveModule - remove chain from double linked list head.
+*/
+
+static void RemoveModule (ModuleChain *head, ModuleChain chain);
+
+/*
+   onChain - returns TRUE if mptr is on the Modules[state] list.
+*/
+
+static unsigned int onChain (DependencyState state, ModuleChain mptr);
+
+/*
+   LookupModuleN - lookup module from the state list.  The string is limited
+                   to nchar.
+*/
+
+static ModuleChain LookupModuleN (DependencyState state, void * name, unsigned int nchar);
+
+/*
+   LookupModule - lookup and return the ModuleChain pointer containing
+                  module name from a particular list.
+*/
+
+static ModuleChain LookupModule (DependencyState state, void * name);
+
+/*
+   toCString - replace any character sequence 
+ into a newline.
+*/
+
+static void toCString (char *str, unsigned int _str_high);
+
+/*
+   strcmp - return 0 if both strings are equal.
+            We cannot use Builtins.def during bootstrap.
+*/
+
+static int strcmp (M2LINK_PtrToChar a, M2LINK_PtrToChar b);
+
+/*
+   strncmp - return 0 if both strings are equal.
+             We cannot use Builtins.def during bootstrap.
+*/
+
+static int strncmp (M2LINK_PtrToChar a, M2LINK_PtrToChar b, unsigned int n);
+
+/*
+   strlen - returns the length of string.
+*/
+
+static int strlen_ (M2LINK_PtrToChar string);
+
+/*
+   traceprintf - wrap printf with a boolean flag.
+*/
+
+static void traceprintf (unsigned int flag, const char *str_, unsigned int _str_high);
+
+/*
+   traceprintf2 - wrap printf with a boolean flag.
+*/
+
+static void traceprintf2 (unsigned int flag, const char *str_, unsigned int _str_high, void * arg);
+
+/*
+   moveTo - moves mptr to the new list determined by newstate.
+            It updates the mptr state appropriately.
+*/
+
+static void moveTo (DependencyState newstate, ModuleChain mptr);
+
+/*
+   ResolveDependant -
+*/
+
+static void ResolveDependant (ModuleChain mptr, void * currentmodule);
+
+/*
+   PerformRequestDependant - the current modulename has a dependancy upon
+                             dependantmodule.  If dependantmodule is NIL then
+                             modulename has no further dependants and it can be
+                             resolved.
+*/
+
+static void PerformRequestDependant (void * modulename, void * dependantmodule);
+
+/*
+   ResolveDependencies - resolve dependencies for currentmodule.
+*/
+
+static void ResolveDependencies (void * currentmodule);
+
+/*
+   DisplayModuleInfo - displays all module in the state.
+*/
+
+static void DisplayModuleInfo (DependencyState state, const char *name_, unsigned int _name_high);
+
+/*
+   DumpModuleData -
+*/
+
+static void DumpModuleData (unsigned int flag);
+
+/*
+   combine - dest := src + dest.  Places src at the front of list dest.
+             Pre condition:  src, dest are lists.
+             Post condition : dest := src + dest
+                              src := NIL.
+*/
+
+static void combine (DependencyState src, DependencyState dest);
+
+/*
+   ForceDependencies - if the user has specified a forced order then we override
+                       the dynamic ordering with the preference.
+*/
+
+static void ForceDependencies (void);
+
+/*
+   equal - return TRUE if C string cstr is equal to str.
+*/
+
+static unsigned int equal (void * cstr, const char *str_, unsigned int _str_high);
+
+/*
+   SetupDebugFlags - By default assigns ModuleTrace, DependencyTrace,
+                     DumpPostInit to FALSE.  It checks the environment
+                     GCC_M2LINK_RTFLAG which can contain
+                     "all,module,pre,post,dep,force".  all turns them all on.
+                     The flag meanings are as follows and flags the are in
+                     execution order.
+
+                     module   generate trace info as the modules are registered.
+                     pre      generate a list of all modules seen prior to having
+                              their dependancies resolved.
+                     dep      display a trace as the modules are resolved.
+                     post     generate a list of all modules seen after having
+                              their dependancies resolved dynamically.
+                     force    generate a list of all modules seen after having
+                              their dependancies resolved and forced.
+*/
+
+static void SetupDebugFlags (void);
+
+/*
+   Init - initialize the debug flags and set all lists to NIL.
+*/
+
+static void Init (void);
+
+/*
+   CheckInitialized - checks to see if this module has been initialized
+                      and if it has not it calls Init.  We need this
+                      approach as this module is called by module ctors
+                      before we reach main.
+*/
+
+static void CheckInitialized (void);
+
+
+/*
+   CreateModule - creates a new module entry and returns the
+                  ModuleChain.
+*/
+
+static ModuleChain CreateModule (void * name, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies)
+{
+  ModuleChain mptr;
+
+  Storage_ALLOCATE ((void **) &mptr, sizeof (_T2));
+  mptr->name = name;
+  mptr->init = init;
+  mptr->fini = fini;
+  mptr->dependency.proc = dependencies;
+  mptr->dependency.state = unregistered;
+  mptr->prev = NULL;
+  mptr->next = NULL;
+  return mptr;
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   AppendModule - append chain to end of the list.
+*/
+
+static void AppendModule (ModuleChain *head, ModuleChain chain)
+{
+  if ((*head) == NULL)
+    {
+      (*head) = chain;
+      chain->prev = chain;
+      chain->next = chain;
+    }
+  else
+    {
+      chain->next = (*head);  /* Add Item to the end of list.  */
+      chain->prev = (*head)->prev;  /* Add Item to the end of list.  */
+      (*head)->prev->next = chain;
+      (*head)->prev = chain;
+    }
+}
+
+
+/*
+   RemoveModule - remove chain from double linked list head.
+*/
+
+static void RemoveModule (ModuleChain *head, ModuleChain chain)
+{
+  if ((chain->next == (*head)) && (chain == (*head)))
+    {
+      (*head) = NULL;
+    }
+  else
+    {
+      if ((*head) == chain)
+        {
+          (*head) = (*head)->next;
+        }
+      chain->prev->next = chain->next;
+      chain->next->prev = chain->prev;
+    }
+}
+
+
+/*
+   onChain - returns TRUE if mptr is on the Modules[state] list.
+*/
+
+static unsigned int onChain (DependencyState state, ModuleChain mptr)
+{
+  ModuleChain ptr;
+
+  if (Modules.array[state-unregistered] != NULL)
+    {
+      ptr = Modules.array[state-unregistered];
+      do {
+        if (ptr == mptr)
+          {
+            return TRUE;
+          }
+        ptr = ptr->next;
+      } while (! (ptr == Modules.array[state-unregistered]));
+    }
+  return FALSE;
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   LookupModuleN - lookup module from the state list.  The string is limited
+                   to nchar.
+*/
+
+static ModuleChain LookupModuleN (DependencyState state, void * name, unsigned int nchar)
+{
+  ModuleChain ptr;
+
+  if (Modules.array[state-unregistered] != NULL)
+    {
+      ptr = Modules.array[state-unregistered];
+      do {
+        if ((strncmp (reinterpret_cast<M2LINK_PtrToChar> (ptr->name), reinterpret_cast<M2LINK_PtrToChar> (name), nchar)) == 0)
+          {
+            return ptr;
+          }
+        ptr = ptr->next;
+      } while (! (ptr == Modules.array[state-unregistered]));
+    }
+  return NULL;
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   LookupModule - lookup and return the ModuleChain pointer containing
+                  module name from a particular list.
+*/
+
+static ModuleChain LookupModule (DependencyState state, void * name)
+{
+  return LookupModuleN (state, name, static_cast<unsigned int> (strlen_ (reinterpret_cast<M2LINK_PtrToChar> (name))));
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   toCString - replace any character sequence 
+ into a newline.
+*/
+
+static void toCString (char *str, unsigned int _str_high)
+{
+  unsigned int high;
+  unsigned int i;
+  unsigned int j;
+
+  i = 0;
+  high = _str_high;
+  while (i < high)
+    {
+      if ((str[i] == '\\') && (i < high))
+        {
+          if (str[i+1] == 'n')
+            {
+              str[i] = ASCII_nl;
+              j = i+1;
+              while (j < high)
+                {
+                  str[j] = str[j+1];
+                  j += 1;
+                }
+            }
+        }
+      i += 1;
+    }
+}
+
+
+/*
+   strcmp - return 0 if both strings are equal.
+            We cannot use Builtins.def during bootstrap.
+*/
+
+static int strcmp (M2LINK_PtrToChar a, M2LINK_PtrToChar b)
+{
+  if ((a != NULL) && (b != NULL))
+    {
+      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
+      if (a == b)
+        {
+          return 0;
+        }
+      else
+        {
+          while ((*a) == (*b))
+            {
+              if ((*a) == ASCII_nul)
+                {
+                  return 0;
+                }
+              a += 1;
+              b += 1;
+            }
+        }
+    }
+  return 1;
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   strncmp - return 0 if both strings are equal.
+             We cannot use Builtins.def during bootstrap.
+*/
+
+static int strncmp (M2LINK_PtrToChar a, M2LINK_PtrToChar b, unsigned int n)
+{
+  if (((a != NULL) && (b != NULL)) && (n > 0))
+    {
+      /* avoid gcc warning by using compound statement even if not strictly necessary.  */
+      if (a == b)
+        {
+          return 0;
+        }
+      else
+        {
+          while (((*a) == (*b)) && (n > 0))
+            {
+              if (((*a) == ASCII_nul) || (n == 1))
+                {
+                  return 0;
+                }
+              a += 1;
+              b += 1;
+              n -= 1;
+            }
+        }
+    }
+  return 1;
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   strlen - returns the length of string.
+*/
+
+static int strlen_ (M2LINK_PtrToChar string)
+{
+  int count;
+
+  if (string == NULL)
+    {
+      return 0;
+    }
+  else
+    {
+      count = 0;
+      while ((*string) != ASCII_nul)
+        {
+          string += 1;
+          count += 1;
+        }
+      return count;
+    }
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   traceprintf - wrap printf with a boolean flag.
+*/
+
+static void traceprintf (unsigned int flag, const char *str_, unsigned int _str_high)
+{
+  char str[_str_high+1];
+
+  /* make a local copy of each unbounded array.  */
+  memcpy (str, str_, _str_high+1);
+
+  if (flag)
+    {
+      toCString ((char *) str, _str_high);
+      libc_printf ((const char *) str, _str_high);
+    }
+}
+
+
+/*
+   traceprintf2 - wrap printf with a boolean flag.
+*/
+
+static void traceprintf2 (unsigned int flag, const char *str_, unsigned int _str_high, void * arg)
+{
+  char str[_str_high+1];
+
+  /* make a local copy of each unbounded array.  */
+  memcpy (str, str_, _str_high+1);
+
+  if (flag)
+    {
+      toCString ((char *) str, _str_high);
+      libc_printf ((const char *) str, _str_high, arg);
+    }
+}
+
+
+/*
+   moveTo - moves mptr to the new list determined by newstate.
+            It updates the mptr state appropriately.
+*/
+
+static void moveTo (DependencyState newstate, ModuleChain mptr)
+{
+  if (onChain (mptr->dependency.state, mptr))
+    {
+      RemoveModule (&Modules.array[mptr->dependency.state-unregistered], mptr);
+    }
+  mptr->dependency.state = newstate;
+  AppendModule (&Modules.array[mptr->dependency.state-unregistered], mptr);
+}
+
+
+/*
+   ResolveDependant -
+*/
+
+static void ResolveDependant (ModuleChain mptr, void * currentmodule)
+{
+  if (mptr == NULL)
+    {
+      traceprintf (DependencyTrace, (const char *) "   module has not been registered via a global constructor\\n", 60);
+    }
+  else
+    {
+      if (onChain (started, mptr))
+        {
+          traceprintf (DependencyTrace, (const char *) "   processing...\\n", 18);
+        }
+      else
+        {
+          moveTo (started, mptr);
+          traceprintf2 (DependencyTrace, (const char *) "   starting: %s\\n", 17, currentmodule);
+          (*mptr->dependency.proc.proc) ();  /* Invoke and process the dependency graph.  */
+          traceprintf2 (DependencyTrace, (const char *) "   finished: %s\\n", 17, currentmodule);  /* Invoke and process the dependency graph.  */
+          moveTo (ordered, mptr);
+        }
+    }
+}
+
+
+/*
+   PerformRequestDependant - the current modulename has a dependancy upon
+                             dependantmodule.  If dependantmodule is NIL then
+                             modulename has no further dependants and it can be
+                             resolved.
+*/
+
+static void PerformRequestDependant (void * modulename, void * dependantmodule)
+{
+  ModuleChain mptr;
+
+  traceprintf2 (DependencyTrace, (const char *) "  module %s", 11, modulename);
+  if (dependantmodule == NULL)
+    {
+      /* avoid dangling else.  */
+      traceprintf2 (DependencyTrace, (const char *) " has finished its import graph\\n", 32, modulename);
+      mptr = LookupModule (unordered, modulename);
+      if (mptr != NULL)
+        {
+          traceprintf2 (DependencyTrace, (const char *) "  module %s is now ordered\\n", 28, modulename);
+          moveTo (ordered, mptr);
+        }
+    }
+  else
+    {
+      traceprintf2 (DependencyTrace, (const char *) " imports from %s\\n", 18, dependantmodule);
+      mptr = LookupModule (ordered, dependantmodule);
+      if (mptr == NULL)
+        {
+          traceprintf2 (DependencyTrace, (const char *) "  module %s is not ordered\\n", 28, dependantmodule);
+          mptr = LookupModule (unordered, dependantmodule);
+          if (mptr == NULL)
+            {
+              traceprintf2 (DependencyTrace, (const char *) "  module %s is not unordered\\n", 30, dependantmodule);
+              mptr = LookupModule (started, dependantmodule);
+              if (mptr == NULL)
+                {
+                  traceprintf2 (DependencyTrace, (const char *) "  module %s has not started\\n", 29, dependantmodule);
+                  traceprintf2 (DependencyTrace, (const char *) "  module %s attempting to import from", 37, modulename);
+                  traceprintf2 (DependencyTrace, (const char *) " %s which has not registered itself via a constructor\\n", 55, dependantmodule);
+                }
+              else
+                {
+                  traceprintf2 (DependencyTrace, (const char *) "  module %s has registered itself and has started\\n", 51, dependantmodule);
+                }
+            }
+          else
+            {
+              traceprintf2 (DependencyTrace, (const char *) "  module %s resolving\\n", 23, dependantmodule);
+              ResolveDependant (mptr, dependantmodule);
+            }
+        }
+      else
+        {
+          traceprintf2 (DependencyTrace, (const char *) "  module %s ", 12, modulename);
+          traceprintf2 (DependencyTrace, (const char *) " dependant %s is ordered\\n", 26, dependantmodule);
+        }
+    }
+}
+
+
+/*
+   ResolveDependencies - resolve dependencies for currentmodule.
+*/
+
+static void ResolveDependencies (void * currentmodule)
+{
+  ModuleChain mptr;
+
+  mptr = LookupModule (unordered, currentmodule);
+  while (mptr != NULL)
+    {
+      traceprintf2 (DependencyTrace, (const char *) "   attempting to resolve the dependants for %s\\n", 48, currentmodule);
+      ResolveDependant (mptr, currentmodule);
+      mptr = Modules.array[unordered-unregistered];
+    }
+}
+
+
+/*
+   DisplayModuleInfo - displays all module in the state.
+*/
+
+static void DisplayModuleInfo (DependencyState state, const char *name_, unsigned int _name_high)
+{
+  ModuleChain mptr;
+  char name[_name_high+1];
+
+  /* make a local copy of each unbounded array.  */
+  memcpy (name, name_, _name_high+1);
+
+  if (Modules.array[state-unregistered] != NULL)
+    {
+      libc_printf ((const char *) "%s modules\\n", 12, &name);
+      mptr = Modules.array[state-unregistered];
+      do {
+        libc_printf ((const char *) "  %s", 4, mptr->name);
+        if (mptr->dependency.appl)
+          {
+            libc_printf ((const char *) " application", 12);
+          }
+        if (mptr->dependency.forc)
+          {
+            libc_printf ((const char *) " for C", 6);
+          }
+        if (mptr->dependency.forced)
+          {
+            libc_printf ((const char *) " forced ordering", 16);
+          }
+        libc_printf ((const char *) "\\n", 2);
+        mptr = mptr->next;
+      } while (! (mptr == Modules.array[state-unregistered]));
+    }
+}
+
+
+/*
+   DumpModuleData -
+*/
+
+static void DumpModuleData (unsigned int flag)
+{
+  ModuleChain mptr;
+
+  if (flag)
+    {
+      DisplayModuleInfo (unregistered, (const char *) "unregistered", 12);
+      DisplayModuleInfo (unordered, (const char *) "unordered", 9);
+      DisplayModuleInfo (started, (const char *) "started", 7);
+      DisplayModuleInfo (ordered, (const char *) "ordered", 7);
+    }
+}
+
+
+/*
+   combine - dest := src + dest.  Places src at the front of list dest.
+             Pre condition:  src, dest are lists.
+             Post condition : dest := src + dest
+                              src := NIL.
+*/
+
+static void combine (DependencyState src, DependencyState dest)
+{
+  ModuleChain last;
+
+  while (Modules.array[src-unregistered] != NULL)
+    {
+      last = Modules.array[src-unregistered]->prev;
+      moveTo (ordered, last);
+      Modules.array[dest-unregistered] = last;  /* New item is at the head.  */
+    }
+}
+
+
+/*
+   ForceDependencies - if the user has specified a forced order then we override
+                       the dynamic ordering with the preference.
+*/
+
+static void ForceDependencies (void)
+{
+  ModuleChain mptr;
+  ModuleChain userChain;
+  unsigned int count;
+  M2LINK_PtrToChar pc;
+  M2LINK_PtrToChar start;
+
+  if (M2LINK_ForcedModuleInitOrder != NULL)
+    {
+      userChain = NULL;
+      pc = M2LINK_ForcedModuleInitOrder;
+      start = pc;
+      count = 0;
+      while ((*pc) != ASCII_nul)
+        {
+          if ((*pc) == ',')
+            {
+              mptr = LookupModuleN (ordered, reinterpret_cast<void *> (start), count);
+              if (mptr != NULL)
+                {
+                  moveTo (user, mptr);
+                }
+              pc += 1;
+              start = pc;
+              count = 0;
+            }
+          else
+            {
+              pc += 1;
+              count += 1;
+            }
+        }
+      if (start != pc)
+        {
+          mptr = LookupModuleN (ordered, reinterpret_cast<void *> (start), count);
+          if (mptr != NULL)
+            {
+              moveTo (user, mptr);
+            }
+        }
+      combine (user, ordered);
+    }
+}
+
+
+/*
+   equal - return TRUE if C string cstr is equal to str.
+*/
+
+static unsigned int equal (void * cstr, const char *str_, unsigned int _str_high)
+{
+  char str[_str_high+1];
+
+  /* make a local copy of each unbounded array.  */
+  memcpy (str, str_, _str_high+1);
+
+  return (strncmp (reinterpret_cast<M2LINK_PtrToChar> (cstr), reinterpret_cast<M2LINK_PtrToChar> (&str), StrLib_StrLen ((const char *) str, _str_high))) == 0;
+  /* static analysis guarentees a RETURN statement will be used before here.  */
+  __builtin_unreachable ();
+}
+
+
+/*
+   SetupDebugFlags - By default assigns ModuleTrace, DependencyTrace,
+                     DumpPostInit to FALSE.  It checks the environment
+                     GCC_M2LINK_RTFLAG which can contain
+                     "all,module,pre,post,dep,force".  all turns them all on.
+                     The flag meanings are as follows and flags the are in
+                     execution order.
+
+                     module   generate trace info as the modules are registered.
+                     pre      generate a list of all modules seen prior to having
+                              their dependancies resolved.
+                     dep      display a trace as the modules are resolved.
+                     post     generate a list of all modules seen after having
+                              their dependancies resolved dynamically.
+                     force    generate a list of all modules seen after having
+                              their dependancies resolved and forced.
+*/
+
+static void SetupDebugFlags (void)
+{
+  typedef char *_T1;
+
+  _T1 pc;
+
+  ModuleTrace = FALSE;
+  DependencyTrace = FALSE;
+  PostTrace = FALSE;
+  PreTrace = FALSE;
+  pc = static_cast<_T1> (libc_getenv (const_cast<void*> (reinterpret_cast<const void*>("GCC_M2LINK_RTFLAG"))));
+  while ((pc != NULL) && ((*pc) != ASCII_nul))
+    {
+      if (equal (reinterpret_cast<void *> (pc), (const char *) "all", 3))
+        {
+          ModuleTrace = TRUE;
+          DependencyTrace = TRUE;
+          PreTrace = TRUE;
+          PostTrace = TRUE;
+          ForceTrace = TRUE;
+          pc += 3;
+        }
+      else if (equal (reinterpret_cast<void *> (pc), (const char *) "module", 6))
+        {
+          /* avoid dangling else.  */
+          ModuleTrace = TRUE;
+          pc += 6;
+        }
+      else if (equal (reinterpret_cast<void *> (pc), (const char *) "dep", 3))
+        {
+          /* avoid dangling else.  */
+          DependencyTrace = TRUE;
+          pc += 3;
+        }
+      else if (equal (reinterpret_cast<void *> (pc), (const char *) "pre", 3))
+        {
+          /* avoid dangling else.  */
+          PreTrace = TRUE;
+          pc += 3;
+        }
+      else if (equal (reinterpret_cast<void *> (pc), (const char *) "post", 4))
+        {
+          /* avoid dangling else.  */
+          PostTrace = TRUE;
+          pc += 4;
+        }
+      else if (equal (reinterpret_cast<void *> (pc), (const char *) "force", 5))
+        {
+          /* avoid dangling else.  */
+          ForceTrace = TRUE;
+          pc += 5;
+        }
+      else
+        {
+          /* avoid dangling else.  */
+          pc += 1;
+        }
+    }
+}
+
+
+/*
+   Init - initialize the debug flags and set all lists to NIL.
+*/
+
+static void Init (void)
+{
+  DependencyState state;
+
+  SetupDebugFlags ();
+  for (state=unregistered; state<=user; state= static_cast<DependencyState>(static_cast<int>(state+1)))
+    {
+      Modules.array[state-unregistered] = NULL;
+    }
+}
+
+
+/*
+   CheckInitialized - checks to see if this module has been initialized
+                      and if it has not it calls Init.  We need this
+                      approach as this module is called by module ctors
+                      before we reach main.
+*/
+
+static void CheckInitialized (void)
+{
+  if (! Initialized)
+    {
+      Initialized = TRUE;
+      Init ();
+    }
+}
+
+
+/*
+   ConstructModules - resolve dependencies and then call each
+                      module constructor in turn.
+*/
+
+extern "C" void M2Dependent_ConstructModules (void * applicationmodule, int argc, void * argv, void * envp)
+{
+  ModuleChain mptr;
+  M2Dependent_ArgCVEnvP nulp;
+
+  CheckInitialized ();
+  traceprintf2 (ModuleTrace, (const char *) "application module: %s\\n", 24, applicationmodule);
+  mptr = LookupModule (unordered, applicationmodule);
+  if (mptr != NULL)
+    {
+      mptr->dependency.appl = TRUE;
+    }
+  traceprintf (PreTrace, (const char *) "Pre resolving dependents\\n", 26);
+  DumpModuleData (PreTrace);
+  ResolveDependencies (applicationmodule);
+  traceprintf (PreTrace, (const char *) "Post resolving dependents\\n", 27);
+  DumpModuleData (PostTrace);
+  ForceDependencies ();
+  traceprintf (ForceTrace, (const char *) "After user forcing ordering\\n", 29);
+  DumpModuleData (ForceTrace);
+  if (Modules.array[ordered-unregistered] == NULL)
+    {
+      traceprintf2 (ModuleTrace, (const char *) "  module: %s has not registered itself using a global constructor\\n", 67, applicationmodule);
+      traceprintf2 (ModuleTrace, (const char *) "  hint try compile and linking using: gm2 %s.mod\\n", 50, applicationmodule);
+      traceprintf2 (ModuleTrace, (const char *) "  or try using: gm2 -fscaffold-static %s.mod\\n", 46, applicationmodule);
+    }
+  else
+    {
+      mptr = Modules.array[ordered-unregistered];
+      do {
+        if (mptr->dependency.forc)
+          {
+            traceprintf2 (ModuleTrace, (const char *) "initializing module: %s for C\\n", 31, mptr->name);
+          }
+        else
+          {
+            traceprintf2 (ModuleTrace, (const char *) "initializing module: %s\\n", 25, mptr->name);
+          }
+        if (mptr->dependency.appl)
+          {
+            traceprintf2 (ModuleTrace, (const char *) "application module: %s\\n", 24, mptr->name);
+            traceprintf (ModuleTrace, (const char *) "  calling M2RTS_ExecuteInitialProcedures\\n", 42);
+            M2RTS_ExecuteInitialProcedures ();
+            traceprintf (ModuleTrace, (const char *) "  calling application module\\n", 30);
+          }
+        (*mptr->init.proc) (argc, argv, envp);
+        mptr = mptr->next;
+      } while (! (mptr == Modules.array[ordered-unregistered]));
+    }
+}
+
+
+/*
+   DeconstructModules - resolve dependencies and then call each
+                        module constructor in turn.
+*/
+
+extern "C" void M2Dependent_DeconstructModules (void * applicationmodule, int argc, void * argv, void * envp)
+{
+  ModuleChain mptr;
+
+  traceprintf2 (ModuleTrace, (const char *) "application module finishing: %s\\n", 34, applicationmodule);
+  if (Modules.array[ordered-unregistered] == NULL)
+    {
+      traceprintf (ModuleTrace, (const char *) "  no ordered modules found during finishing\\n", 45);
+    }
+  else
+    {
+      traceprintf (ModuleTrace, (const char *) "ExecuteTerminationProcedures\\n", 30);
+      M2RTS_ExecuteTerminationProcedures ();
+      traceprintf (ModuleTrace, (const char *) "terminating modules in sequence\\n", 33);
+      mptr = Modules.array[ordered-unregistered]->prev;
+      do {
+        if (mptr->dependency.forc)
+          {
+            traceprintf2 (ModuleTrace, (const char *) "finalizing module: %s for C\\n", 29, mptr->name);
+          }
+        else
+          {
+            traceprintf2 (ModuleTrace, (const char *) "finalizing module: %s\\n", 23, mptr->name);
+          }
+        (*mptr->fini.proc) (argc, argv, envp);
+        mptr = mptr->prev;
+      } while (! (mptr == Modules.array[ordered-unregistered]->prev));
+    }
+}
+
+
+/*
+   RegisterModule - adds module name to the list of outstanding
+                    modules which need to have their dependencies
+                    explored to determine initialization order.
+*/
+
+extern "C" void M2Dependent_RegisterModule (void * name, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies)
+{
+  CheckInitialized ();
+  if (! M2LINK_StaticInitialization)
+    {
+      traceprintf2 (ModuleTrace, (const char *) "module: %s registering\\n", 24, name);
+      moveTo (unordered, CreateModule (name, init, fini, dependencies));
+    }
+}
+
+
+/*
+   RequestDependant - used to specify that modulename is dependant upon
+                      module dependantmodule.  It only takes effect
+                      if we are not using StaticInitialization.
+*/
+
+extern "C" void M2Dependent_RequestDependant (void * modulename, void * dependantmodule)
+{
+  CheckInitialized ();
+  if (! M2LINK_StaticInitialization)
+    {
+      PerformRequestDependant (modulename, dependantmodule);
+    }
+}
+
+extern "C" void _M2_M2Dependent_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[])
+{
+  CheckInitialized ();
+}
+
+extern "C" void _M2_M2Dependent_finish (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[])
+{
+}
diff --git a/gcc/m2/mc-boot/GM2Dependent.h b/gcc/m2/mc-boot/GM2Dependent.h
new file mode 100644 (file)
index 0000000..7cdbee6
--- /dev/null
@@ -0,0 +1,78 @@
+/* do not edit automatically generated by mc from M2Dependent.  */
+/* M2Dependent.def defines the run time module dependencies interface.
+
+Copyright (C) 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+
+#if !defined (_M2Dependent_H)
+#   define _M2Dependent_H
+
+#include "config.h"
+#include "system.h"
+#   ifdef __cplusplus
+extern "C" {
+#   endif
+#   if !defined (PROC_D)
+#      define PROC_D
+       typedef void (*PROC_t) (void);
+       typedef struct { PROC_t proc; } PROC;
+#   endif
+
+#   include "GSYSTEM.h"
+
+#   if defined (_M2Dependent_C)
+#      define EXTERN
+#   else
+#      define EXTERN extern
+#   endif
+
+typedef struct M2Dependent_ArgCVEnvP_p M2Dependent_ArgCVEnvP;
+
+typedef void (*M2Dependent_ArgCVEnvP_t) (int, void *, void *);
+struct M2Dependent_ArgCVEnvP_p { M2Dependent_ArgCVEnvP_t proc; };
+
+EXTERN void M2Dependent_ConstructModules (void * applicationmodule, int argc, void * argv, void * envp);
+EXTERN void M2Dependent_DeconstructModules (void * applicationmodule, int argc, void * argv, void * envp);
+
+/*
+   RegisterModule - adds module name to the list of outstanding
+                    modules which need to have their dependencies
+                    explored to determine initialization order.
+*/
+
+EXTERN void M2Dependent_RegisterModule (void * name, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies);
+
+/*
+   RequestDependant - used to specify that modulename is dependant upon
+                      module dependantmodule.
+*/
+
+EXTERN void M2Dependent_RequestDependant (void * modulename, void * dependantmodule);
+#   ifdef __cplusplus
+}
+#   endif
+
+#   undef EXTERN
+#endif