| /* do not edit automatically generated by mc from M2Dependent. */ |
| /* M2Dependent.mod implements the run time module dependencies. |
| |
| Copyright (C) 2022-2025 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" |
| #include <stdbool.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_C |
| |
| #include "GM2Dependent.h" |
| # include "Glibc.h" |
| # include "GASCII.h" |
| # include "GSYSTEM.h" |
| # include "GStorage.h" |
| # include "GStrLib.h" |
| |
| typedef struct M2Dependent_ArgCVEnvP_p M2Dependent_ArgCVEnvP; |
| |
| typedef struct M2Dependent_DependencyList_r M2Dependent_DependencyList; |
| |
| typedef char *M2Dependent_PtrToChar; |
| |
| typedef struct M2Dependent_ProcedureList_r M2Dependent_ProcedureList; |
| |
| typedef struct M2Dependent__T2_r M2Dependent__T2; |
| |
| typedef M2Dependent__T2 *M2Dependent_ModuleChain; |
| |
| typedef struct M2Dependent__T3_r M2Dependent__T3; |
| |
| typedef M2Dependent__T3 *M2Dependent_ProcedureChain; |
| |
| typedef struct M2Dependent__T4_a M2Dependent__T4; |
| |
| typedef enum {M2Dependent_unregistered, M2Dependent_unordered, M2Dependent_started, M2Dependent_ordered, M2Dependent_user} M2Dependent_DependencyState; |
| |
| struct M2Dependent_DependencyList_r { |
| PROC proc; |
| bool forced; |
| bool forc; |
| bool appl; |
| M2Dependent_DependencyState state; |
| }; |
| |
| struct M2Dependent_ProcedureList_r { |
| M2Dependent_ProcedureChain head; |
| M2Dependent_ProcedureChain tail; |
| }; |
| |
| struct M2Dependent__T3_r { |
| PROC p; |
| M2Dependent_ProcedureChain prev; |
| M2Dependent_ProcedureChain next; |
| }; |
| |
| struct M2Dependent__T4_a { M2Dependent_ModuleChain array[M2Dependent_user-M2Dependent_unregistered+1]; }; |
| struct M2Dependent__T2_r { |
| void * name; |
| void * libname; |
| M2Dependent_ArgCVEnvP init; |
| M2Dependent_ArgCVEnvP fini; |
| M2Dependent_DependencyList dependency; |
| M2Dependent_ModuleChain prev; |
| M2Dependent_ModuleChain next; |
| }; |
| |
| static M2Dependent__T4 Modules; |
| static bool DynamicInitialization; |
| static bool Initialized; |
| static bool WarningTrace; |
| static bool ModuleTrace; |
| static bool HexTrace; |
| static bool DependencyTrace; |
| static bool PreTrace; |
| static bool PostTrace; |
| static bool ForceTrace; |
| static M2Dependent_ProcedureList InitialProc; |
| static M2Dependent_ProcedureList TerminateProc; |
| |
| /* |
| ConstructModules - resolve dependencies and then call each |
| module constructor in turn. |
| */ |
| |
| extern "C" void M2Dependent_ConstructModules (void * applicationmodule, void * libname, void * overrideliborder, int argc, void * argv, void * envp); |
| |
| /* |
| DeconstructModules - resolve dependencies and then call each |
| module constructor in turn. |
| */ |
| |
| extern "C" void M2Dependent_DeconstructModules (void * applicationmodule, void * libname, 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 * modulename, void * libname, 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 using DynamicInitialization. |
| */ |
| |
| extern "C" void M2Dependent_RequestDependant (void * modulename, void * libname, void * dependantmodule, void * dependantlibname); |
| |
| /* |
| InstallTerminationProcedure - installs a procedure, p, which will |
| be called when the procedure |
| ExecuteTerminationProcedures |
| is invoked. It returns TRUE if the |
| procedure is installed. |
| */ |
| |
| extern "C" bool M2Dependent_InstallTerminationProcedure (PROC p); |
| |
| /* |
| ExecuteInitialProcedures - executes the initial procedures installed by |
| InstallInitialProcedure. |
| */ |
| |
| extern "C" void M2Dependent_ExecuteInitialProcedures (void); |
| |
| /* |
| InstallInitialProcedure - installs a procedure to be executed just |
| before the BEGIN code section of the |
| main program module. |
| */ |
| |
| extern "C" bool M2Dependent_InstallInitialProcedure (PROC p); |
| |
| /* |
| ExecuteTerminationProcedures - calls each installed termination procedure |
| in reverse order. |
| */ |
| |
| extern "C" void M2Dependent_ExecuteTerminationProcedures (void); |
| |
| /* |
| InitDependencyList - initialize all fields of DependencyList. |
| */ |
| |
| static void InitDependencyList (M2Dependent_DependencyList *depList, PROC proc, M2Dependent_DependencyState state); |
| |
| /* |
| CreateModule - creates a new module entry and returns the |
| ModuleChain. |
| */ |
| |
| static M2Dependent_ModuleChain CreateModule (void * name, void * libname, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies); |
| |
| /* |
| AppendModule - append chain to end of the list. |
| */ |
| |
| static void AppendModule (M2Dependent_ModuleChain *head, M2Dependent_ModuleChain chain); |
| |
| /* |
| RemoveModule - remove chain from double linked list head. |
| */ |
| |
| static void RemoveModule (M2Dependent_ModuleChain *head, M2Dependent_ModuleChain chain); |
| |
| /* |
| onChain - returns TRUE if mptr is on the Modules[state] list. |
| */ |
| |
| static bool onChain (M2Dependent_DependencyState state, M2Dependent_ModuleChain mptr); |
| |
| /* |
| max - |
| */ |
| |
| static unsigned int max (unsigned int a, unsigned int b); |
| |
| /* |
| min - |
| */ |
| |
| static unsigned int min (unsigned int a, unsigned int b); |
| |
| /* |
| LookupModuleN - lookup module from the state list. |
| The strings lengths are known. |
| */ |
| |
| static M2Dependent_ModuleChain LookupModuleN (M2Dependent_DependencyState state, void * name, unsigned int namelen, void * libname, unsigned int libnamelen); |
| |
| /* |
| LookupModule - lookup and return the ModuleChain pointer containing |
| module name from a particular list. |
| */ |
| |
| static M2Dependent_ModuleChain LookupModule (M2Dependent_DependencyState state, void * name, void * libname); |
| |
| /* |
| 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 (M2Dependent_PtrToChar a, M2Dependent_PtrToChar b); |
| |
| /* |
| strncmp - return 0 if both strings are equal. |
| We cannot use Builtins.def during bootstrap. |
| */ |
| |
| static int strncmp (M2Dependent_PtrToChar a, M2Dependent_PtrToChar b, unsigned int n); |
| |
| /* |
| strlen - returns the length of string. |
| */ |
| |
| static int strlen_ (M2Dependent_PtrToChar string); |
| |
| /* |
| traceprintf - wrap printf with a boolean flag. |
| */ |
| |
| static void traceprintf (bool flag, const char *str_, unsigned int _str_high); |
| |
| /* |
| traceprintf2 - wrap printf with a boolean flag. |
| */ |
| |
| static void traceprintf2 (bool flag, const char *str_, unsigned int _str_high, void * arg); |
| |
| /* |
| traceprintf3 - wrap printf with a boolean flag. |
| */ |
| |
| static void traceprintf3 (bool flag, const char *str_, unsigned int _str_high, void * arg1, void * arg2); |
| |
| /* |
| moveTo - moves mptr to the new list determined by newstate. |
| It updates the mptr state appropriately. |
| */ |
| |
| static void moveTo (M2Dependent_DependencyState newstate, M2Dependent_ModuleChain mptr); |
| |
| /* |
| ResolveDependant - |
| */ |
| |
| static void ResolveDependant (M2Dependent_ModuleChain mptr, void * currentmodule, void * libname); |
| |
| /* |
| 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 * libname, void * dependantmodule, void * dependantlibname); |
| |
| /* |
| ResolveDependencies - resolve dependencies for currentmodule, libname. |
| */ |
| |
| static void ResolveDependencies (void * currentmodule, void * libname); |
| |
| /* |
| DisplayModuleInfo - displays all module in the state. |
| */ |
| |
| static void DisplayModuleInfo (M2Dependent_DependencyState state, const char *desc_, unsigned int _desc_high); |
| |
| /* |
| DumpModuleData - |
| */ |
| |
| static void DumpModuleData (bool 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 (M2Dependent_DependencyState src, M2Dependent_DependencyState dest); |
| |
| /* |
| tracemodule - |
| */ |
| |
| static void tracemodule (bool flag, void * modname, unsigned int modlen, void * libname, unsigned int liblen); |
| |
| /* |
| ForceModule - |
| */ |
| |
| static void ForceModule (void * modname, unsigned int modlen, void * libname, unsigned int liblen); |
| |
| /* |
| ForceDependencies - if the user has specified a forced order then we override |
| the dynamic ordering with the preference. |
| */ |
| |
| static void ForceDependencies (void * overrideliborder); |
| |
| /* |
| CheckApplication - check to see that the application is the last entry in the list. |
| This might happen if the application only imports FOR C modules. |
| */ |
| |
| static void CheckApplication (void); |
| |
| /* |
| warning3 - write format arg1 arg2 to stderr. |
| */ |
| |
| static void warning3 (const char *format_, unsigned int _format_high, void * arg1, void * arg2); |
| |
| /* |
| equal - return TRUE if C string cstr is equal to str. |
| */ |
| |
| static bool 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,hex,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. |
| hex dump the modules ctor functions address in hex. |
| 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); |
| |
| /* |
| ExecuteReverse - execute the procedure associated with procptr |
| and then proceed to try and execute all previous |
| procedures in the chain. |
| */ |
| |
| static void ExecuteReverse (M2Dependent_ProcedureChain procptr); |
| |
| /* |
| AppendProc - append proc to the end of the procedure list |
| defined by proclist. |
| */ |
| |
| static bool AppendProc (M2Dependent_ProcedureList *proclist, PROC proc); |
| |
| /* |
| InitProcList - initialize the head and tail pointers to NIL. |
| */ |
| |
| static void InitProcList (M2Dependent_ProcedureList *p); |
| |
| |
| /* |
| InitDependencyList - initialize all fields of DependencyList. |
| */ |
| |
| static void InitDependencyList (M2Dependent_DependencyList *depList, PROC proc, M2Dependent_DependencyState state) |
| { |
| (*depList).proc = proc; |
| (*depList).forced = false; |
| (*depList).forc = false; |
| (*depList).appl = false; |
| (*depList).state = state; |
| } |
| |
| |
| /* |
| CreateModule - creates a new module entry and returns the |
| ModuleChain. |
| */ |
| |
| static M2Dependent_ModuleChain CreateModule (void * name, void * libname, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies) |
| { |
| M2Dependent_ModuleChain mptr; |
| |
| Storage_ALLOCATE ((void **) &mptr, sizeof (M2Dependent__T2)); |
| mptr->name = name; |
| mptr->libname = libname; |
| mptr->init = init; |
| mptr->fini = fini; |
| InitDependencyList (&mptr->dependency, dependencies, M2Dependent_unregistered); |
| mptr->prev = NULL; |
| mptr->next = NULL; |
| if (HexTrace) |
| { |
| libc_printf ((const char *) " (init: %p fini: %p", 22, init, fini); |
| libc_printf ((const char *) " dep: %p)", 10, dependencies); |
| } |
| 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 (M2Dependent_ModuleChain *head, M2Dependent_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 (M2Dependent_ModuleChain *head, M2Dependent_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 bool onChain (M2Dependent_DependencyState state, M2Dependent_ModuleChain mptr) |
| { |
| M2Dependent_ModuleChain ptr; |
| |
| if (Modules.array[state-M2Dependent_unregistered] != NULL) |
| { |
| ptr = Modules.array[state-M2Dependent_unregistered]; |
| do { |
| if (ptr == mptr) |
| { |
| return true; |
| } |
| ptr = ptr->next; |
| } while (! (ptr == Modules.array[state-M2Dependent_unregistered])); |
| } |
| return false; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| max - |
| */ |
| |
| static unsigned int max (unsigned int a, unsigned int b) |
| { |
| if (a > b) |
| { |
| return a; |
| } |
| else |
| { |
| return b; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| min - |
| */ |
| |
| static unsigned int min (unsigned int a, unsigned int b) |
| { |
| if (a < b) |
| { |
| return a; |
| } |
| else |
| { |
| return b; |
| } |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| LookupModuleN - lookup module from the state list. |
| The strings lengths are known. |
| */ |
| |
| static M2Dependent_ModuleChain LookupModuleN (M2Dependent_DependencyState state, void * name, unsigned int namelen, void * libname, unsigned int libnamelen) |
| { |
| M2Dependent_ModuleChain ptr; |
| |
| if (Modules.array[state-M2Dependent_unregistered] != NULL) |
| { |
| ptr = Modules.array[state-M2Dependent_unregistered]; |
| do { |
| if (((strncmp (reinterpret_cast <M2Dependent_PtrToChar> (ptr->name), reinterpret_cast <M2Dependent_PtrToChar> (name), max (namelen, static_cast<unsigned int> (strlen_ (reinterpret_cast <M2Dependent_PtrToChar> (ptr->name)))))) == 0) && ((strncmp (reinterpret_cast <M2Dependent_PtrToChar> (ptr->libname), reinterpret_cast <M2Dependent_PtrToChar> (libname), max (libnamelen, static_cast<unsigned int> (strlen_ (reinterpret_cast <M2Dependent_PtrToChar> (ptr->libname)))))) == 0)) |
| { |
| return ptr; |
| } |
| ptr = ptr->next; |
| } while (! (ptr == Modules.array[state-M2Dependent_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 M2Dependent_ModuleChain LookupModule (M2Dependent_DependencyState state, void * name, void * libname) |
| { |
| return LookupModuleN (state, name, static_cast<unsigned int> (strlen_ (reinterpret_cast <M2Dependent_PtrToChar> (name))), libname, static_cast<unsigned int> (strlen_ (reinterpret_cast <M2Dependent_PtrToChar> (libname)))); |
| /* 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 ((i < high) && (str[i] == '\\')) |
| { |
| if (str[i+1] == 'n') |
| { |
| const_cast<char *>(str)[i] = ASCII_nl; |
| j = i+1; |
| while (j < high) |
| { |
| const_cast<char *>(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 (M2Dependent_PtrToChar a, M2Dependent_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 (M2Dependent_PtrToChar a, M2Dependent_PtrToChar b, unsigned int n) |
| { |
| if (n == 0) |
| { |
| return 0; |
| } |
| else if ((a != NULL) && (b != NULL)) |
| { |
| /* avoid dangling else. */ |
| 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_ (M2Dependent_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 (bool 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 (bool flag, const char *str_, unsigned int _str_high, void * arg) |
| { |
| char ch; |
| 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); |
| if (arg == NULL) |
| { |
| ch = (char) 0; |
| arg = &ch; |
| } |
| libc_printf ((const char *) str, _str_high, arg); |
| } |
| } |
| |
| |
| /* |
| traceprintf3 - wrap printf with a boolean flag. |
| */ |
| |
| static void traceprintf3 (bool flag, const char *str_, unsigned int _str_high, void * arg1, void * arg2) |
| { |
| char ch; |
| 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); |
| if (arg1 == NULL) |
| { |
| ch = (char) 0; |
| arg1 = &ch; |
| } |
| if (arg2 == NULL) |
| { |
| ch = (char) 0; |
| arg2 = &ch; |
| } |
| libc_printf ((const char *) str, _str_high, arg1, arg2); |
| } |
| } |
| |
| |
| /* |
| moveTo - moves mptr to the new list determined by newstate. |
| It updates the mptr state appropriately. |
| */ |
| |
| static void moveTo (M2Dependent_DependencyState newstate, M2Dependent_ModuleChain mptr) |
| { |
| if (onChain (mptr->dependency.state, mptr)) |
| { |
| RemoveModule (&Modules.array[mptr->dependency.state-M2Dependent_unregistered], mptr); |
| } |
| mptr->dependency.state = newstate; |
| AppendModule (&Modules.array[mptr->dependency.state-M2Dependent_unregistered], mptr); |
| } |
| |
| |
| /* |
| ResolveDependant - |
| */ |
| |
| static void ResolveDependant (M2Dependent_ModuleChain mptr, void * currentmodule, void * libname) |
| { |
| if (mptr == NULL) |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] has not been registered via a global constructor\\n", 68, currentmodule, libname); |
| } |
| else |
| { |
| if (onChain (M2Dependent_started, mptr)) |
| { |
| traceprintf (DependencyTrace, (const char *) " processing...\\n", 18); |
| } |
| else |
| { |
| moveTo (M2Dependent_started, mptr); |
| traceprintf3 (DependencyTrace, (const char *) " starting: %s [%s]\\n", 22, currentmodule, libname); |
| (*mptr->dependency.proc.proc) (); /* Invoke and process the dependency graph. */ |
| traceprintf3 (DependencyTrace, (const char *) " finished: %s [%s]\\n", 22, currentmodule, libname); /* Invoke and process the dependency graph. */ |
| moveTo (M2Dependent_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 * libname, void * dependantmodule, void * dependantlibname) |
| { |
| M2Dependent_ModuleChain mptr; |
| |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s]", 16, modulename, libname); |
| if (dependantmodule == NULL) |
| { |
| /* avoid dangling else. */ |
| traceprintf (DependencyTrace, (const char *) " has finished its import graph\\n", 32); |
| mptr = LookupModule (M2Dependent_unordered, modulename, libname); |
| if (mptr != NULL) |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] is now ordered\\n", 33, modulename, libname); |
| moveTo (M2Dependent_ordered, mptr); |
| } |
| } |
| else |
| { |
| traceprintf3 (DependencyTrace, (const char *) " imports from %s [%s]\\n", 23, dependantmodule, dependantlibname); |
| mptr = LookupModule (M2Dependent_ordered, dependantmodule, dependantlibname); |
| if (mptr == NULL) |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] is not ordered\\n", 33, dependantmodule, dependantlibname); |
| mptr = LookupModule (M2Dependent_unordered, dependantmodule, dependantlibname); |
| if (mptr == NULL) |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] is not unordered\\n", 35, dependantmodule, dependantlibname); |
| mptr = LookupModule (M2Dependent_started, dependantmodule, dependantlibname); |
| if (mptr == NULL) |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] has not started\\n", 34, dependantmodule, dependantlibname); |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] attempting to import from", 42, modulename, libname); |
| traceprintf3 (DependencyTrace, (const char *) " %s [%s] which has not registered itself via a constructor\\n", 60, dependantmodule, dependantlibname); |
| } |
| else |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] has registered itself and has started\\n", 56, dependantmodule, dependantlibname); |
| } |
| } |
| else |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s] resolving\\n", 28, dependantmodule, dependantlibname); |
| ResolveDependant (mptr, dependantmodule, dependantlibname); |
| } |
| } |
| else |
| { |
| traceprintf3 (DependencyTrace, (const char *) " module %s [%s]", 16, modulename, libname); |
| traceprintf3 (DependencyTrace, (const char *) " dependant %s [%s] is ordered\\n", 31, dependantmodule, dependantlibname); |
| } |
| } |
| } |
| |
| |
| /* |
| ResolveDependencies - resolve dependencies for currentmodule, libname. |
| */ |
| |
| static void ResolveDependencies (void * currentmodule, void * libname) |
| { |
| M2Dependent_ModuleChain mptr; |
| |
| mptr = LookupModule (M2Dependent_unordered, currentmodule, libname); |
| while (mptr != NULL) |
| { |
| traceprintf3 (DependencyTrace, (const char *) " attempting to resolve the dependants for %s [%s]\\n", 53, currentmodule, libname); |
| ResolveDependant (mptr, currentmodule, libname); |
| mptr = Modules.array[M2Dependent_unordered-M2Dependent_unregistered]; |
| } |
| } |
| |
| |
| /* |
| DisplayModuleInfo - displays all module in the state. |
| */ |
| |
| static void DisplayModuleInfo (M2Dependent_DependencyState state, const char *desc_, unsigned int _desc_high) |
| { |
| M2Dependent_ModuleChain mptr; |
| unsigned int count; |
| char desc[_desc_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (desc, desc_, _desc_high+1); |
| |
| if (Modules.array[state-M2Dependent_unregistered] != NULL) |
| { |
| libc_printf ((const char *) "%s modules\\n", 12, const_cast<void*> (static_cast<const void*>(desc))); |
| mptr = Modules.array[state-M2Dependent_unregistered]; |
| count = 0; |
| do { |
| if (mptr->name == NULL) |
| { |
| libc_printf ((const char *) " %d %s []", 11, count, mptr->name); |
| } |
| else |
| { |
| libc_printf ((const char *) " %d %s [%s]", 13, count, mptr->name, mptr->libname); |
| } |
| count += 1; |
| 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-M2Dependent_unregistered])); |
| } |
| } |
| |
| |
| /* |
| DumpModuleData - |
| */ |
| |
| static void DumpModuleData (bool flag) |
| { |
| if (flag) |
| { |
| DisplayModuleInfo (M2Dependent_unregistered, (const char *) "unregistered", 12); |
| DisplayModuleInfo (M2Dependent_unordered, (const char *) "unordered", 9); |
| DisplayModuleInfo (M2Dependent_started, (const char *) "started", 7); |
| DisplayModuleInfo (M2Dependent_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 (M2Dependent_DependencyState src, M2Dependent_DependencyState dest) |
| { |
| M2Dependent_ModuleChain last; |
| |
| while (Modules.array[src-M2Dependent_unregistered] != NULL) |
| { |
| last = Modules.array[src-M2Dependent_unregistered]->prev; |
| moveTo (M2Dependent_ordered, last); |
| Modules.array[dest-M2Dependent_unregistered] = last; /* New item is at the head. */ |
| } |
| } |
| |
| |
| /* |
| tracemodule - |
| */ |
| |
| static void tracemodule (bool flag, void * modname, unsigned int modlen, void * libname, unsigned int liblen) |
| { |
| typedef struct tracemodule__T5_a tracemodule__T5; |
| |
| struct tracemodule__T5_a { char array[100+1]; }; |
| tracemodule__T5 buffer; |
| unsigned int len; |
| |
| if (flag) |
| { |
| len = min (modlen, sizeof (buffer)-1); |
| libc_strncpy (&buffer, modname, len); |
| buffer.array[len] = (char) 0; |
| libc_printf ((const char *) "%s ", 3, &buffer); |
| len = min (liblen, sizeof (buffer)-1); |
| libc_strncpy (&buffer, libname, len); |
| buffer.array[len] = (char) 0; |
| libc_printf ((const char *) " [%s]", 5, &buffer); |
| } |
| } |
| |
| |
| /* |
| ForceModule - |
| */ |
| |
| static void ForceModule (void * modname, unsigned int modlen, void * libname, unsigned int liblen) |
| { |
| M2Dependent_ModuleChain mptr; |
| |
| traceprintf (ForceTrace, (const char *) "forcing module: ", 16); |
| tracemodule (ForceTrace, modname, modlen, libname, liblen); |
| traceprintf (ForceTrace, (const char *) "\\n", 2); |
| mptr = LookupModuleN (M2Dependent_ordered, modname, modlen, libname, liblen); |
| if (mptr != NULL) |
| { |
| mptr->dependency.forced = true; |
| moveTo (M2Dependent_user, mptr); |
| } |
| } |
| |
| |
| /* |
| ForceDependencies - if the user has specified a forced order then we override |
| the dynamic ordering with the preference. |
| */ |
| |
| static void ForceDependencies (void * overrideliborder) |
| { |
| unsigned int len; |
| unsigned int modlen; |
| unsigned int liblen; |
| M2Dependent_PtrToChar modname; |
| M2Dependent_PtrToChar libname; |
| M2Dependent_PtrToChar pc; |
| M2Dependent_PtrToChar start; |
| |
| if (overrideliborder != NULL) |
| { |
| traceprintf2 (ForceTrace, (const char *) "user forcing order: %s\\n", 24, overrideliborder); |
| pc = static_cast<M2Dependent_PtrToChar> (overrideliborder); |
| start = pc; |
| len = 0; |
| modname = NULL; |
| modlen = 0; |
| libname = NULL; |
| liblen = 0; |
| while ((*pc) != ASCII_nul) |
| { |
| switch ((*pc)) |
| { |
| case ':': |
| libname = start; |
| liblen = len; |
| len = 0; |
| pc += 1; |
| start = pc; |
| break; |
| |
| case ',': |
| modname = start; |
| modlen = len; |
| ForceModule (reinterpret_cast <void *> (modname), modlen, reinterpret_cast <void *> (libname), liblen); |
| libname = NULL; |
| liblen = 0; |
| modlen = 0; |
| len = 0; |
| pc += 1; |
| start = pc; |
| break; |
| |
| |
| default: |
| pc += 1; |
| len += 1; |
| break; |
| } |
| } |
| if (start != pc) |
| { |
| ForceModule (reinterpret_cast <void *> (start), len, reinterpret_cast <void *> (libname), liblen); |
| } |
| combine (M2Dependent_user, M2Dependent_ordered); |
| } |
| } |
| |
| |
| /* |
| CheckApplication - check to see that the application is the last entry in the list. |
| This might happen if the application only imports FOR C modules. |
| */ |
| |
| static void CheckApplication (void) |
| { |
| M2Dependent_ModuleChain mptr; |
| M2Dependent_ModuleChain appl; |
| |
| mptr = Modules.array[M2Dependent_ordered-M2Dependent_unregistered]; |
| if (mptr != NULL) |
| { |
| appl = NULL; |
| do { |
| if (mptr->dependency.appl) |
| { |
| appl = mptr; |
| } |
| else |
| { |
| mptr = mptr->next; |
| } |
| } while (! ((appl != NULL) || (mptr == Modules.array[M2Dependent_ordered-M2Dependent_unregistered]))); |
| if (appl != NULL) |
| { |
| RemoveModule (&Modules.array[M2Dependent_ordered-M2Dependent_unregistered], appl); |
| AppendModule (&Modules.array[M2Dependent_ordered-M2Dependent_unregistered], appl); |
| } |
| } |
| } |
| |
| |
| /* |
| warning3 - write format arg1 arg2 to stderr. |
| */ |
| |
| static void warning3 (const char *format_, unsigned int _format_high, void * arg1, void * arg2) |
| { |
| typedef struct warning3__T6_a warning3__T6; |
| |
| struct warning3__T6_a { char array[4096+1]; }; |
| warning3__T6 buffer; |
| int len; |
| char format[_format_high+1]; |
| |
| /* make a local copy of each unbounded array. */ |
| memcpy (format, format_, _format_high+1); |
| |
| if (WarningTrace) |
| { |
| len = libc_snprintf (&buffer, static_cast<size_t> (sizeof (buffer)), (const char *) "warning: ", 9); |
| libc_write (2, &buffer, static_cast<size_t> (len)); |
| len = libc_snprintf (&buffer, static_cast<size_t> (sizeof (buffer)), (const char *) format, _format_high, arg1, arg2); |
| libc_write (2, &buffer, static_cast<size_t> (len)); |
| } |
| } |
| |
| |
| /* |
| equal - return TRUE if C string cstr is equal to str. |
| */ |
| |
| static bool 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 <M2Dependent_PtrToChar> (cstr), reinterpret_cast <M2Dependent_PtrToChar> (const_cast<void*> (static_cast<const void*>(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,hex,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. |
| hex dump the modules ctor functions address in hex. |
| 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 *SetupDebugFlags__T1; |
| |
| SetupDebugFlags__T1 pc; |
| |
| ModuleTrace = false; |
| DependencyTrace = false; |
| PostTrace = false; |
| PreTrace = false; |
| ForceTrace = false; |
| HexTrace = false; |
| WarningTrace = false; |
| pc = static_cast<SetupDebugFlags__T1> (libc_getenv (const_cast<void*> (static_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; |
| HexTrace = true; |
| WarningTrace = 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 *) "warning", 7)) |
| { |
| /* avoid dangling else. */ |
| WarningTrace = true; |
| pc += 7; |
| } |
| else if (equal (reinterpret_cast <void *> (pc), (const char *) "hex", 3)) |
| { |
| /* avoid dangling else. */ |
| HexTrace = true; |
| pc += 3; |
| } |
| 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) |
| { |
| M2Dependent_DependencyState state; |
| |
| InitProcList (&InitialProc); |
| InitProcList (&TerminateProc); |
| SetupDebugFlags (); |
| for (state=M2Dependent_unregistered; state<=M2Dependent_user; state= static_cast<M2Dependent_DependencyState>(static_cast<int>(state+1))) |
| { |
| Modules.array[state-M2Dependent_unregistered] = NULL; |
| } |
| DynamicInitialization = false; |
| } |
| |
| |
| /* |
| 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 (); |
| } |
| } |
| |
| |
| /* |
| ExecuteReverse - execute the procedure associated with procptr |
| and then proceed to try and execute all previous |
| procedures in the chain. |
| */ |
| |
| static void ExecuteReverse (M2Dependent_ProcedureChain procptr) |
| { |
| while (procptr != NULL) |
| { |
| (*procptr->p.proc) (); /* Invoke the procedure. */ |
| procptr = procptr->prev; /* Invoke the procedure. */ |
| } |
| } |
| |
| |
| /* |
| AppendProc - append proc to the end of the procedure list |
| defined by proclist. |
| */ |
| |
| static bool AppendProc (M2Dependent_ProcedureList *proclist, PROC proc) |
| { |
| M2Dependent_ProcedureChain pdes; |
| |
| Storage_ALLOCATE ((void **) &pdes, sizeof (M2Dependent__T3)); |
| pdes->p = proc; |
| pdes->prev = (*proclist).tail; |
| pdes->next = NULL; |
| if ((*proclist).head == NULL) |
| { |
| (*proclist).head = pdes; |
| } |
| (*proclist).tail = pdes; |
| return true; |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| InitProcList - initialize the head and tail pointers to NIL. |
| */ |
| |
| static void InitProcList (M2Dependent_ProcedureList *p) |
| { |
| (*p).head = NULL; |
| (*p).tail = NULL; |
| } |
| |
| |
| /* |
| ConstructModules - resolve dependencies and then call each |
| module constructor in turn. |
| */ |
| |
| extern "C" void M2Dependent_ConstructModules (void * applicationmodule, void * libname, void * overrideliborder, int argc, void * argv, void * envp) |
| { |
| M2Dependent_ModuleChain mptr; |
| |
| CheckInitialized (); |
| DynamicInitialization = true; /* This procedure is only called if we desire dynamic initialization. */ |
| traceprintf3 (ModuleTrace, (const char *) "application module: %s [%s]\\n", 29, applicationmodule, libname); /* This procedure is only called if we desire dynamic initialization. */ |
| mptr = LookupModule (M2Dependent_unordered, applicationmodule, libname); |
| if (mptr != NULL) |
| { |
| mptr->dependency.appl = true; |
| } |
| traceprintf (PreTrace, (const char *) "Pre resolving dependents\\n", 26); |
| DumpModuleData (PreTrace); |
| ResolveDependencies (applicationmodule, libname); |
| traceprintf (PreTrace, (const char *) "Post resolving dependents\\n", 27); |
| DumpModuleData (PostTrace); |
| ForceDependencies (overrideliborder); |
| traceprintf (ForceTrace, (const char *) "After user forcing ordering\\n", 29); |
| DumpModuleData (ForceTrace); |
| CheckApplication (); |
| traceprintf (ForceTrace, (const char *) "After runtime forces application to the end\\n", 45); |
| DumpModuleData (ForceTrace); |
| if (Modules.array[M2Dependent_ordered-M2Dependent_unregistered] == NULL) |
| { |
| traceprintf3 (ModuleTrace, (const char *) " module: %s [%s] has not registered itself using a global constructor\\n", 72, applicationmodule, libname); |
| 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[M2Dependent_ordered-M2Dependent_unregistered]; |
| do { |
| if (mptr->dependency.forc) |
| { |
| traceprintf3 (ModuleTrace, (const char *) "initializing module: %s [%s] for C\\n", 36, mptr->name, mptr->libname); |
| } |
| else |
| { |
| traceprintf3 (ModuleTrace, (const char *) "initializing module: %s [%s]\\n", 30, mptr->name, mptr->libname); |
| } |
| if (mptr->dependency.appl) |
| { |
| traceprintf3 (ModuleTrace, (const char *) "application module: %s [%s]\\n", 29, mptr->name, mptr->libname); |
| traceprintf (ModuleTrace, (const char *) " calling ExecuteInitialProcedures\\n", 36); |
| M2Dependent_ExecuteInitialProcedures (); |
| traceprintf (ModuleTrace, (const char *) " calling application module\\n", 30); |
| } |
| (*mptr->init.proc) (argc, argv, envp); |
| mptr = mptr->next; |
| } while (! (mptr == Modules.array[M2Dependent_ordered-M2Dependent_unregistered])); |
| } |
| } |
| |
| |
| /* |
| DeconstructModules - resolve dependencies and then call each |
| module constructor in turn. |
| */ |
| |
| extern "C" void M2Dependent_DeconstructModules (void * applicationmodule, void * libname, int argc, void * argv, void * envp) |
| { |
| M2Dependent_ModuleChain mptr; |
| |
| traceprintf3 (ModuleTrace, (const char *) "application module finishing: %s [%s]\\n", 39, applicationmodule, libname); |
| if (Modules.array[M2Dependent_ordered-M2Dependent_unregistered] == NULL) |
| { |
| traceprintf (ModuleTrace, (const char *) " no ordered modules found during finishing\\n", 45); |
| } |
| else |
| { |
| traceprintf (ModuleTrace, (const char *) "ExecuteTerminationProcedures\\n", 30); |
| M2Dependent_ExecuteTerminationProcedures (); |
| traceprintf (ModuleTrace, (const char *) "terminating modules in sequence\\n", 33); |
| mptr = Modules.array[M2Dependent_ordered-M2Dependent_unregistered]->prev; |
| do { |
| if (mptr->dependency.forc) |
| { |
| traceprintf3 (ModuleTrace, (const char *) "finalizing module: %s [%s] for C\\n", 34, mptr->name, mptr->libname); |
| } |
| else |
| { |
| traceprintf3 (ModuleTrace, (const char *) "finalizing module: %s [%s]\\n", 28, mptr->name, mptr->libname); |
| } |
| (*mptr->fini.proc) (argc, argv, envp); |
| mptr = mptr->prev; |
| } while (! (mptr == Modules.array[M2Dependent_ordered-M2Dependent_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 * modulename, void * libname, M2Dependent_ArgCVEnvP init, M2Dependent_ArgCVEnvP fini, PROC dependencies) |
| { |
| M2Dependent_ModuleChain mptr; |
| |
| CheckInitialized (); |
| mptr = LookupModule (M2Dependent_unordered, modulename, libname); |
| if (mptr == NULL) |
| { |
| traceprintf3 (ModuleTrace, (const char *) "module: %s [%s] registering", 27, modulename, libname); |
| moveTo (M2Dependent_unordered, CreateModule (modulename, libname, init, fini, dependencies)); |
| traceprintf (ModuleTrace, (const char *) "\\n", 2); |
| } |
| else |
| { |
| warning3 ((const char *) "module: %s [%s] (ignoring duplicate registration)\\n", 51, modulename, libname); |
| } |
| } |
| |
| |
| /* |
| RequestDependant - used to specify that modulename is dependant upon |
| module dependantmodule. It only takes effect |
| if we are using DynamicInitialization. |
| */ |
| |
| extern "C" void M2Dependent_RequestDependant (void * modulename, void * libname, void * dependantmodule, void * dependantlibname) |
| { |
| CheckInitialized (); |
| PerformRequestDependant (modulename, libname, dependantmodule, dependantlibname); |
| } |
| |
| |
| /* |
| InstallTerminationProcedure - installs a procedure, p, which will |
| be called when the procedure |
| ExecuteTerminationProcedures |
| is invoked. It returns TRUE if the |
| procedure is installed. |
| */ |
| |
| extern "C" bool M2Dependent_InstallTerminationProcedure (PROC p) |
| { |
| return AppendProc (&TerminateProc, p); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ExecuteInitialProcedures - executes the initial procedures installed by |
| InstallInitialProcedure. |
| */ |
| |
| extern "C" void M2Dependent_ExecuteInitialProcedures (void) |
| { |
| ExecuteReverse (InitialProc.tail); |
| } |
| |
| |
| /* |
| InstallInitialProcedure - installs a procedure to be executed just |
| before the BEGIN code section of the |
| main program module. |
| */ |
| |
| extern "C" bool M2Dependent_InstallInitialProcedure (PROC p) |
| { |
| return AppendProc (&InitialProc, p); |
| /* static analysis guarentees a RETURN statement will be used before here. */ |
| __builtin_unreachable (); |
| } |
| |
| |
| /* |
| ExecuteTerminationProcedures - calls each installed termination procedure |
| in reverse order. |
| */ |
| |
| extern "C" void M2Dependent_ExecuteTerminationProcedures (void) |
| { |
| ExecuteReverse (TerminateProc.tail); |
| } |
| |
| extern "C" void _M2_M2Dependent_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| CheckInitialized (); |
| } |
| |
| extern "C" void _M2_M2Dependent_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[]) |
| { |
| } |