1 /* do not edit automatically generated by mc from M2Dependent. */
2 /* M2Dependent.mod implements the run time module dependencies.
4 Copyright (C) 2022-2024 Free Software Foundation, Inc.
5 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
7 This file is part of GNU Modula-2.
9 GNU Modula-2 is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 GNU Modula-2 is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 Under Section 7 of GPL version 3, you are granted additional
20 permissions described in the GCC Runtime Library Exception, version
21 3.1, as published by the Free Software Foundation.
23 You should have received a copy of the GNU General Public License and
24 a copy of the GCC Runtime Library Exception along with this program;
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
26 <http://www.gnu.org/licenses/>. */
31 # if !defined (PROC_D)
33 typedef void (*PROC_t
) (void);
34 typedef struct { PROC_t proc
; } PROC
;
45 # include "GStorage.h"
46 #if defined(__cplusplus)
50 #define _M2Dependent_C
52 #include "GM2Dependent.h"
56 # include "GStorage.h"
59 typedef struct M2Dependent_ArgCVEnvP_p M2Dependent_ArgCVEnvP
;
61 typedef struct M2Dependent_DependencyList_r M2Dependent_DependencyList
;
63 typedef char *M2Dependent_PtrToChar
;
65 typedef struct M2Dependent_ProcedureList_r M2Dependent_ProcedureList
;
67 typedef struct M2Dependent__T2_r M2Dependent__T2
;
69 typedef M2Dependent__T2
*M2Dependent_ModuleChain
;
71 typedef struct M2Dependent__T3_r M2Dependent__T3
;
73 typedef M2Dependent__T3
*M2Dependent_ProcedureChain
;
75 typedef struct M2Dependent__T4_a M2Dependent__T4
;
77 typedef enum {M2Dependent_unregistered
, M2Dependent_unordered
, M2Dependent_started
, M2Dependent_ordered
, M2Dependent_user
} M2Dependent_DependencyState
;
79 struct M2Dependent_DependencyList_r
{
84 M2Dependent_DependencyState state
;
87 struct M2Dependent_ProcedureList_r
{
88 M2Dependent_ProcedureChain head
;
89 M2Dependent_ProcedureChain tail
;
92 struct M2Dependent__T3_r
{
94 M2Dependent_ProcedureChain prev
;
95 M2Dependent_ProcedureChain next
;
98 struct M2Dependent__T4_a
{ M2Dependent_ModuleChain array
[M2Dependent_user
-M2Dependent_unregistered
+1]; };
99 struct M2Dependent__T2_r
{
102 M2Dependent_ArgCVEnvP init
;
103 M2Dependent_ArgCVEnvP fini
;
104 M2Dependent_DependencyList dependency
;
105 M2Dependent_ModuleChain prev
;
106 M2Dependent_ModuleChain next
;
109 static M2Dependent__T4 Modules
;
110 static bool DynamicInitialization
;
111 static bool Initialized
;
112 static bool WarningTrace
;
113 static bool ModuleTrace
;
114 static bool HexTrace
;
115 static bool DependencyTrace
;
116 static bool PreTrace
;
117 static bool PostTrace
;
118 static bool ForceTrace
;
119 static M2Dependent_ProcedureList InitialProc
;
120 static M2Dependent_ProcedureList TerminateProc
;
123 ConstructModules - resolve dependencies and then call each
124 module constructor in turn.
127 extern "C" void M2Dependent_ConstructModules (void * applicationmodule
, void * libname
, void * overrideliborder
, int argc
, void * argv
, void * envp
);
130 DeconstructModules - resolve dependencies and then call each
131 module constructor in turn.
134 extern "C" void M2Dependent_DeconstructModules (void * applicationmodule
, void * libname
, int argc
, void * argv
, void * envp
);
137 RegisterModule - adds module name to the list of outstanding
138 modules which need to have their dependencies
139 explored to determine initialization order.
142 extern "C" void M2Dependent_RegisterModule (void * modulename
, void * libname
, M2Dependent_ArgCVEnvP init
, M2Dependent_ArgCVEnvP fini
, PROC dependencies
);
145 RequestDependant - used to specify that modulename is dependant upon
146 module dependantmodule. It only takes effect
147 if we are using DynamicInitialization.
150 extern "C" void M2Dependent_RequestDependant (void * modulename
, void * libname
, void * dependantmodule
, void * dependantlibname
);
153 InstallTerminationProcedure - installs a procedure, p, which will
154 be called when the procedure
155 ExecuteTerminationProcedures
156 is invoked. It returns TRUE if the
157 procedure is installed.
160 extern "C" bool M2Dependent_InstallTerminationProcedure (PROC p
);
163 ExecuteInitialProcedures - executes the initial procedures installed by
164 InstallInitialProcedure.
167 extern "C" void M2Dependent_ExecuteInitialProcedures (void);
170 InstallInitialProcedure - installs a procedure to be executed just
171 before the BEGIN code section of the
175 extern "C" bool M2Dependent_InstallInitialProcedure (PROC p
);
178 ExecuteTerminationProcedures - calls each installed termination procedure
182 extern "C" void M2Dependent_ExecuteTerminationProcedures (void);
185 InitDependencyList - initialize all fields of DependencyList.
188 static void InitDependencyList (M2Dependent_DependencyList
*depList
, PROC proc
, M2Dependent_DependencyState state
);
191 CreateModule - creates a new module entry and returns the
195 static M2Dependent_ModuleChain
CreateModule (void * name
, void * libname
, M2Dependent_ArgCVEnvP init
, M2Dependent_ArgCVEnvP fini
, PROC dependencies
);
198 AppendModule - append chain to end of the list.
201 static void AppendModule (M2Dependent_ModuleChain
*head
, M2Dependent_ModuleChain chain
);
204 RemoveModule - remove chain from double linked list head.
207 static void RemoveModule (M2Dependent_ModuleChain
*head
, M2Dependent_ModuleChain chain
);
210 onChain - returns TRUE if mptr is on the Modules[state] list.
213 static bool onChain (M2Dependent_DependencyState state
, M2Dependent_ModuleChain mptr
);
219 static unsigned int max (unsigned int a
, unsigned int b
);
225 static unsigned int min (unsigned int a
, unsigned int b
);
228 LookupModuleN - lookup module from the state list.
229 The strings lengths are known.
232 static M2Dependent_ModuleChain
LookupModuleN (M2Dependent_DependencyState state
, void * name
, unsigned int namelen
, void * libname
, unsigned int libnamelen
);
235 LookupModule - lookup and return the ModuleChain pointer containing
236 module name from a particular list.
239 static M2Dependent_ModuleChain
LookupModule (M2Dependent_DependencyState state
, void * name
, void * libname
);
242 toCString - replace any character sequence
246 static void toCString (char *str
, unsigned int _str_high
);
249 strcmp - return 0 if both strings are equal.
250 We cannot use Builtins.def during bootstrap.
253 static int strcmp (M2Dependent_PtrToChar a
, M2Dependent_PtrToChar b
);
256 strncmp - return 0 if both strings are equal.
257 We cannot use Builtins.def during bootstrap.
260 static int strncmp (M2Dependent_PtrToChar a
, M2Dependent_PtrToChar b
, unsigned int n
);
263 strlen - returns the length of string.
266 static int strlen_ (M2Dependent_PtrToChar string
);
269 traceprintf - wrap printf with a boolean flag.
272 static void traceprintf (bool flag
, const char *str_
, unsigned int _str_high
);
275 traceprintf2 - wrap printf with a boolean flag.
278 static void traceprintf2 (bool flag
, const char *str_
, unsigned int _str_high
, void * arg
);
281 traceprintf3 - wrap printf with a boolean flag.
284 static void traceprintf3 (bool flag
, const char *str_
, unsigned int _str_high
, void * arg1
, void * arg2
);
287 moveTo - moves mptr to the new list determined by newstate.
288 It updates the mptr state appropriately.
291 static void moveTo (M2Dependent_DependencyState newstate
, M2Dependent_ModuleChain mptr
);
297 static void ResolveDependant (M2Dependent_ModuleChain mptr
, void * currentmodule
, void * libname
);
300 PerformRequestDependant - the current modulename has a dependancy upon
301 dependantmodule. If dependantmodule is NIL then
302 modulename has no further dependants and it can be
306 static void PerformRequestDependant (void * modulename
, void * libname
, void * dependantmodule
, void * dependantlibname
);
309 ResolveDependencies - resolve dependencies for currentmodule, libname.
312 static void ResolveDependencies (void * currentmodule
, void * libname
);
315 DisplayModuleInfo - displays all module in the state.
318 static void DisplayModuleInfo (M2Dependent_DependencyState state
, const char *desc_
, unsigned int _desc_high
);
324 static void DumpModuleData (bool flag
);
327 combine - dest := src + dest. Places src at the front of list dest.
328 Pre condition: src, dest are lists.
329 Post condition : dest := src + dest
333 static void combine (M2Dependent_DependencyState src
, M2Dependent_DependencyState dest
);
339 static void tracemodule (bool flag
, void * modname
, unsigned int modlen
, void * libname
, unsigned int liblen
);
345 static void ForceModule (void * modname
, unsigned int modlen
, void * libname
, unsigned int liblen
);
348 ForceDependencies - if the user has specified a forced order then we override
349 the dynamic ordering with the preference.
352 static void ForceDependencies (void * overrideliborder
);
355 CheckApplication - check to see that the application is the last entry in the list.
356 This might happen if the application only imports FOR C modules.
359 static void CheckApplication (void);
362 warning3 - write format arg1 arg2 to stderr.
365 static void warning3 (const char *format_
, unsigned int _format_high
, void * arg1
, void * arg2
);
368 equal - return TRUE if C string cstr is equal to str.
371 static bool equal (void * cstr
, const char *str_
, unsigned int _str_high
);
374 SetupDebugFlags - By default assigns ModuleTrace, DependencyTrace,
375 DumpPostInit to FALSE. It checks the environment
376 GCC_M2LINK_RTFLAG which can contain
377 "all,module,hex,pre,post,dep,force". all turns them all on.
378 The flag meanings are as follows and flags the are in
381 module generate trace info as the modules are registered.
382 hex dump the modules ctor functions address in hex.
383 pre generate a list of all modules seen prior to having
384 their dependancies resolved.
385 dep display a trace as the modules are resolved.
386 post generate a list of all modules seen after having
387 their dependancies resolved dynamically.
388 force generate a list of all modules seen after having
389 their dependancies resolved and forced.
392 static void SetupDebugFlags (void);
395 Init - initialize the debug flags and set all lists to NIL.
398 static void Init (void);
401 CheckInitialized - checks to see if this module has been initialized
402 and if it has not it calls Init. We need this
403 approach as this module is called by module ctors
404 before we reach main.
407 static void CheckInitialized (void);
410 ExecuteReverse - execute the procedure associated with procptr
411 and then proceed to try and execute all previous
412 procedures in the chain.
415 static void ExecuteReverse (M2Dependent_ProcedureChain procptr
);
418 AppendProc - append proc to the end of the procedure list
422 static bool AppendProc (M2Dependent_ProcedureList
*proclist
, PROC proc
);
425 InitProcList - initialize the head and tail pointers to NIL.
428 static void InitProcList (M2Dependent_ProcedureList
*p
);
432 InitDependencyList - initialize all fields of DependencyList.
435 static void InitDependencyList (M2Dependent_DependencyList
*depList
, PROC proc
, M2Dependent_DependencyState state
)
437 (*depList
).proc
= proc
;
438 (*depList
).forced
= false;
439 (*depList
).forc
= false;
440 (*depList
).appl
= false;
441 (*depList
).state
= state
;
446 CreateModule - creates a new module entry and returns the
450 static M2Dependent_ModuleChain
CreateModule (void * name
, void * libname
, M2Dependent_ArgCVEnvP init
, M2Dependent_ArgCVEnvP fini
, PROC dependencies
)
452 M2Dependent_ModuleChain mptr
;
454 Storage_ALLOCATE ((void **) &mptr
, sizeof (M2Dependent__T2
));
456 mptr
->libname
= libname
;
459 InitDependencyList (&mptr
->dependency
, dependencies
, M2Dependent_unregistered
);
464 libc_printf ((const char *) " (init: %p fini: %p", 22, init
, fini
);
465 libc_printf ((const char *) " dep: %p)", 10, dependencies
);
468 /* static analysis guarentees a RETURN statement will be used before here. */
469 __builtin_unreachable ();
474 AppendModule - append chain to end of the list.
477 static void AppendModule (M2Dependent_ModuleChain
*head
, M2Dependent_ModuleChain chain
)
487 chain
->next
= (*head
); /* Add Item to the end of list. */
488 chain
->prev
= (*head
)->prev
; /* Add Item to the end of list. */
489 (*head
)->prev
->next
= chain
;
490 (*head
)->prev
= chain
;
496 RemoveModule - remove chain from double linked list head.
499 static void RemoveModule (M2Dependent_ModuleChain
*head
, M2Dependent_ModuleChain chain
)
501 if ((chain
->next
== (*head
)) && (chain
== (*head
)))
507 if ((*head
) == chain
)
509 (*head
) = (*head
)->next
;
511 chain
->prev
->next
= chain
->next
;
512 chain
->next
->prev
= chain
->prev
;
518 onChain - returns TRUE if mptr is on the Modules[state] list.
521 static bool onChain (M2Dependent_DependencyState state
, M2Dependent_ModuleChain mptr
)
523 M2Dependent_ModuleChain ptr
;
525 if (Modules
.array
[state
-M2Dependent_unregistered
] != NULL
)
527 ptr
= Modules
.array
[state
-M2Dependent_unregistered
];
534 } while (! (ptr
== Modules
.array
[state
-M2Dependent_unregistered
]));
537 /* static analysis guarentees a RETURN statement will be used before here. */
538 __builtin_unreachable ();
546 static unsigned int max (unsigned int a
, unsigned int b
)
556 /* static analysis guarentees a RETURN statement will be used before here. */
557 __builtin_unreachable ();
565 static unsigned int min (unsigned int a
, unsigned int b
)
575 /* static analysis guarentees a RETURN statement will be used before here. */
576 __builtin_unreachable ();
581 LookupModuleN - lookup module from the state list.
582 The strings lengths are known.
585 static M2Dependent_ModuleChain
LookupModuleN (M2Dependent_DependencyState state
, void * name
, unsigned int namelen
, void * libname
, unsigned int libnamelen
)
587 M2Dependent_ModuleChain ptr
;
589 if (Modules
.array
[state
-M2Dependent_unregistered
] != NULL
)
591 ptr
= Modules
.array
[state
-M2Dependent_unregistered
];
593 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))
598 } while (! (ptr
== Modules
.array
[state
-M2Dependent_unregistered
]));
601 /* static analysis guarentees a RETURN statement will be used before here. */
602 __builtin_unreachable ();
607 LookupModule - lookup and return the ModuleChain pointer containing
608 module name from a particular list.
611 static M2Dependent_ModuleChain
LookupModule (M2Dependent_DependencyState state
, void * name
, void * libname
)
613 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
))));
614 /* static analysis guarentees a RETURN statement will be used before here. */
615 __builtin_unreachable ();
620 toCString - replace any character sequence
624 static void toCString (char *str
, unsigned int _str_high
)
634 if ((i
< high
) && (str
[i
] == '\\'))
638 const_cast<char *>(str
)[i
] = ASCII_nl
;
642 const_cast<char *>(str
)[j
] = str
[j
+1];
653 strcmp - return 0 if both strings are equal.
654 We cannot use Builtins.def during bootstrap.
657 static int strcmp (M2Dependent_PtrToChar a
, M2Dependent_PtrToChar b
)
659 if ((a
!= NULL
) && (b
!= NULL
))
661 /* avoid gcc warning by using compound statement even if not strictly necessary. */
670 if ((*a
) == ASCII_nul
)
680 /* static analysis guarentees a RETURN statement will be used before here. */
681 __builtin_unreachable ();
686 strncmp - return 0 if both strings are equal.
687 We cannot use Builtins.def during bootstrap.
690 static int strncmp (M2Dependent_PtrToChar a
, M2Dependent_PtrToChar b
, unsigned int n
)
696 else if ((a
!= NULL
) && (b
!= NULL
))
698 /* avoid dangling else. */
705 while (((*a
) == (*b
)) && (n
> 0))
707 if (((*a
) == ASCII_nul
) || (n
== 1))
718 /* static analysis guarentees a RETURN statement will be used before here. */
719 __builtin_unreachable ();
724 strlen - returns the length of string.
727 static int strlen_ (M2Dependent_PtrToChar string
)
738 while ((*string
) != ASCII_nul
)
745 /* static analysis guarentees a RETURN statement will be used before here. */
746 __builtin_unreachable ();
751 traceprintf - wrap printf with a boolean flag.
754 static void traceprintf (bool flag
, const char *str_
, unsigned int _str_high
)
756 char str
[_str_high
+1];
758 /* make a local copy of each unbounded array. */
759 memcpy (str
, str_
, _str_high
+1);
763 toCString ((char *) str
, _str_high
);
764 libc_printf ((const char *) str
, _str_high
);
770 traceprintf2 - wrap printf with a boolean flag.
773 static void traceprintf2 (bool flag
, const char *str_
, unsigned int _str_high
, void * arg
)
776 char str
[_str_high
+1];
778 /* make a local copy of each unbounded array. */
779 memcpy (str
, str_
, _str_high
+1);
783 toCString ((char *) str
, _str_high
);
789 libc_printf ((const char *) str
, _str_high
, arg
);
795 traceprintf3 - wrap printf with a boolean flag.
798 static void traceprintf3 (bool flag
, const char *str_
, unsigned int _str_high
, void * arg1
, void * arg2
)
801 char str
[_str_high
+1];
803 /* make a local copy of each unbounded array. */
804 memcpy (str
, str_
, _str_high
+1);
808 toCString ((char *) str
, _str_high
);
819 libc_printf ((const char *) str
, _str_high
, arg1
, arg2
);
825 moveTo - moves mptr to the new list determined by newstate.
826 It updates the mptr state appropriately.
829 static void moveTo (M2Dependent_DependencyState newstate
, M2Dependent_ModuleChain mptr
)
831 if (onChain (mptr
->dependency
.state
, mptr
))
833 RemoveModule (&Modules
.array
[mptr
->dependency
.state
-M2Dependent_unregistered
], mptr
);
835 mptr
->dependency
.state
= newstate
;
836 AppendModule (&Modules
.array
[mptr
->dependency
.state
-M2Dependent_unregistered
], mptr
);
844 static void ResolveDependant (M2Dependent_ModuleChain mptr
, void * currentmodule
, void * libname
)
848 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] has not been registered via a global constructor\\n", 68, currentmodule
, libname
);
852 if (onChain (M2Dependent_started
, mptr
))
854 traceprintf (DependencyTrace
, (const char *) " processing...\\n", 18);
858 moveTo (M2Dependent_started
, mptr
);
859 traceprintf3 (DependencyTrace
, (const char *) " starting: %s [%s]\\n", 22, currentmodule
, libname
);
860 (*mptr
->dependency
.proc
.proc
) (); /* Invoke and process the dependency graph. */
861 traceprintf3 (DependencyTrace
, (const char *) " finished: %s [%s]\\n", 22, currentmodule
, libname
); /* Invoke and process the dependency graph. */
862 moveTo (M2Dependent_ordered
, mptr
);
869 PerformRequestDependant - the current modulename has a dependancy upon
870 dependantmodule. If dependantmodule is NIL then
871 modulename has no further dependants and it can be
875 static void PerformRequestDependant (void * modulename
, void * libname
, void * dependantmodule
, void * dependantlibname
)
877 M2Dependent_ModuleChain mptr
;
879 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s]", 16, modulename
, libname
);
880 if (dependantmodule
== NULL
)
882 /* avoid dangling else. */
883 traceprintf (DependencyTrace
, (const char *) " has finished its import graph\\n", 32);
884 mptr
= LookupModule (M2Dependent_unordered
, modulename
, libname
);
887 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] is now ordered\\n", 33, modulename
, libname
);
888 moveTo (M2Dependent_ordered
, mptr
);
893 traceprintf3 (DependencyTrace
, (const char *) " imports from %s [%s]\\n", 23, dependantmodule
, dependantlibname
);
894 mptr
= LookupModule (M2Dependent_ordered
, dependantmodule
, dependantlibname
);
897 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] is not ordered\\n", 33, dependantmodule
, dependantlibname
);
898 mptr
= LookupModule (M2Dependent_unordered
, dependantmodule
, dependantlibname
);
901 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] is not unordered\\n", 35, dependantmodule
, dependantlibname
);
902 mptr
= LookupModule (M2Dependent_started
, dependantmodule
, dependantlibname
);
905 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] has not started\\n", 34, dependantmodule
, dependantlibname
);
906 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] attempting to import from", 42, modulename
, libname
);
907 traceprintf3 (DependencyTrace
, (const char *) " %s [%s] which has not registered itself via a constructor\\n", 60, dependantmodule
, dependantlibname
);
911 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] has registered itself and has started\\n", 56, dependantmodule
, dependantlibname
);
916 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s] resolving\\n", 28, dependantmodule
, dependantlibname
);
917 ResolveDependant (mptr
, dependantmodule
, dependantlibname
);
922 traceprintf3 (DependencyTrace
, (const char *) " module %s [%s]", 16, modulename
, libname
);
923 traceprintf3 (DependencyTrace
, (const char *) " dependant %s [%s] is ordered\\n", 31, dependantmodule
, dependantlibname
);
930 ResolveDependencies - resolve dependencies for currentmodule, libname.
933 static void ResolveDependencies (void * currentmodule
, void * libname
)
935 M2Dependent_ModuleChain mptr
;
937 mptr
= LookupModule (M2Dependent_unordered
, currentmodule
, libname
);
940 traceprintf3 (DependencyTrace
, (const char *) " attempting to resolve the dependants for %s [%s]\\n", 53, currentmodule
, libname
);
941 ResolveDependant (mptr
, currentmodule
, libname
);
942 mptr
= Modules
.array
[M2Dependent_unordered
-M2Dependent_unregistered
];
948 DisplayModuleInfo - displays all module in the state.
951 static void DisplayModuleInfo (M2Dependent_DependencyState state
, const char *desc_
, unsigned int _desc_high
)
953 M2Dependent_ModuleChain mptr
;
955 char desc
[_desc_high
+1];
957 /* make a local copy of each unbounded array. */
958 memcpy (desc
, desc_
, _desc_high
+1);
960 if (Modules
.array
[state
-M2Dependent_unregistered
] != NULL
)
962 libc_printf ((const char *) "%s modules\\n", 12, const_cast<void*> (static_cast<const void*>(desc
)));
963 mptr
= Modules
.array
[state
-M2Dependent_unregistered
];
966 if (mptr
->name
== NULL
)
968 libc_printf ((const char *) " %d %s []", 11, count
, mptr
->name
);
972 libc_printf ((const char *) " %d %s [%s]", 13, count
, mptr
->name
, mptr
->libname
);
975 if (mptr
->dependency
.appl
)
977 libc_printf ((const char *) " application", 12);
979 if (mptr
->dependency
.forc
)
981 libc_printf ((const char *) " for C", 6);
983 if (mptr
->dependency
.forced
)
985 libc_printf ((const char *) " forced ordering", 16);
987 libc_printf ((const char *) "\\n", 2);
989 } while (! (mptr
== Modules
.array
[state
-M2Dependent_unregistered
]));
998 static void DumpModuleData (bool flag
)
1002 DisplayModuleInfo (M2Dependent_unregistered
, (const char *) "unregistered", 12);
1003 DisplayModuleInfo (M2Dependent_unordered
, (const char *) "unordered", 9);
1004 DisplayModuleInfo (M2Dependent_started
, (const char *) "started", 7);
1005 DisplayModuleInfo (M2Dependent_ordered
, (const char *) "ordered", 7);
1011 combine - dest := src + dest. Places src at the front of list dest.
1012 Pre condition: src, dest are lists.
1013 Post condition : dest := src + dest
1017 static void combine (M2Dependent_DependencyState src
, M2Dependent_DependencyState dest
)
1019 M2Dependent_ModuleChain last
;
1021 while (Modules
.array
[src
-M2Dependent_unregistered
] != NULL
)
1023 last
= Modules
.array
[src
-M2Dependent_unregistered
]->prev
;
1024 moveTo (M2Dependent_ordered
, last
);
1025 Modules
.array
[dest
-M2Dependent_unregistered
] = last
; /* New item is at the head. */
1034 static void tracemodule (bool flag
, void * modname
, unsigned int modlen
, void * libname
, unsigned int liblen
)
1036 typedef struct tracemodule__T5_a tracemodule__T5
;
1038 struct tracemodule__T5_a
{ char array
[100+1]; };
1039 tracemodule__T5 buffer
;
1044 len
= min (modlen
, sizeof (buffer
)-1);
1045 libc_strncpy (&buffer
, modname
, len
);
1046 buffer
.array
[len
] = (char) 0;
1047 libc_printf ((const char *) "%s ", 3, &buffer
);
1048 len
= min (liblen
, sizeof (buffer
)-1);
1049 libc_strncpy (&buffer
, libname
, len
);
1050 buffer
.array
[len
] = (char) 0;
1051 libc_printf ((const char *) " [%s]", 5, &buffer
);
1060 static void ForceModule (void * modname
, unsigned int modlen
, void * libname
, unsigned int liblen
)
1062 M2Dependent_ModuleChain mptr
;
1064 traceprintf (ForceTrace
, (const char *) "forcing module: ", 16);
1065 tracemodule (ForceTrace
, modname
, modlen
, libname
, liblen
);
1066 traceprintf (ForceTrace
, (const char *) "\\n", 2);
1067 mptr
= LookupModuleN (M2Dependent_ordered
, modname
, modlen
, libname
, liblen
);
1070 mptr
->dependency
.forced
= true;
1071 moveTo (M2Dependent_user
, mptr
);
1077 ForceDependencies - if the user has specified a forced order then we override
1078 the dynamic ordering with the preference.
1081 static void ForceDependencies (void * overrideliborder
)
1084 unsigned int modlen
;
1085 unsigned int liblen
;
1086 M2Dependent_PtrToChar modname
;
1087 M2Dependent_PtrToChar libname
;
1088 M2Dependent_PtrToChar pc
;
1089 M2Dependent_PtrToChar start
;
1091 if (overrideliborder
!= NULL
)
1093 traceprintf2 (ForceTrace
, (const char *) "user forcing order: %s\\n", 24, overrideliborder
);
1094 pc
= static_cast<M2Dependent_PtrToChar
> (overrideliborder
);
1101 while ((*pc
) != ASCII_nul
)
1116 ForceModule (reinterpret_cast <void *> (modname
), modlen
, reinterpret_cast <void *> (libname
), liblen
);
1134 ForceModule (reinterpret_cast <void *> (start
), len
, reinterpret_cast <void *> (libname
), liblen
);
1136 combine (M2Dependent_user
, M2Dependent_ordered
);
1142 CheckApplication - check to see that the application is the last entry in the list.
1143 This might happen if the application only imports FOR C modules.
1146 static void CheckApplication (void)
1148 M2Dependent_ModuleChain mptr
;
1149 M2Dependent_ModuleChain appl
;
1151 mptr
= Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
];
1156 if (mptr
->dependency
.appl
)
1164 } while (! ((appl
!= NULL
) || (mptr
== Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
])));
1167 RemoveModule (&Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
], appl
);
1168 AppendModule (&Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
], appl
);
1175 warning3 - write format arg1 arg2 to stderr.
1178 static void warning3 (const char *format_
, unsigned int _format_high
, void * arg1
, void * arg2
)
1180 typedef struct warning3__T6_a warning3__T6
;
1182 struct warning3__T6_a
{ char array
[4096+1]; };
1183 warning3__T6 buffer
;
1185 char format
[_format_high
+1];
1187 /* make a local copy of each unbounded array. */
1188 memcpy (format
, format_
, _format_high
+1);
1192 len
= libc_snprintf (&buffer
, static_cast<size_t> (sizeof (buffer
)), (const char *) "warning: ", 9);
1193 libc_write (2, &buffer
, static_cast<size_t> (len
));
1194 len
= libc_snprintf (&buffer
, static_cast<size_t> (sizeof (buffer
)), (const char *) format
, _format_high
, arg1
, arg2
);
1195 libc_write (2, &buffer
, static_cast<size_t> (len
));
1201 equal - return TRUE if C string cstr is equal to str.
1204 static bool equal (void * cstr
, const char *str_
, unsigned int _str_high
)
1206 char str
[_str_high
+1];
1208 /* make a local copy of each unbounded array. */
1209 memcpy (str
, str_
, _str_high
+1);
1211 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;
1212 /* static analysis guarentees a RETURN statement will be used before here. */
1213 __builtin_unreachable ();
1218 SetupDebugFlags - By default assigns ModuleTrace, DependencyTrace,
1219 DumpPostInit to FALSE. It checks the environment
1220 GCC_M2LINK_RTFLAG which can contain
1221 "all,module,hex,pre,post,dep,force". all turns them all on.
1222 The flag meanings are as follows and flags the are in
1225 module generate trace info as the modules are registered.
1226 hex dump the modules ctor functions address in hex.
1227 pre generate a list of all modules seen prior to having
1228 their dependancies resolved.
1229 dep display a trace as the modules are resolved.
1230 post generate a list of all modules seen after having
1231 their dependancies resolved dynamically.
1232 force generate a list of all modules seen after having
1233 their dependancies resolved and forced.
1236 static void SetupDebugFlags (void)
1238 typedef char *SetupDebugFlags__T1
;
1240 SetupDebugFlags__T1 pc
;
1242 ModuleTrace
= false;
1243 DependencyTrace
= false;
1248 WarningTrace
= false;
1249 pc
= static_cast<SetupDebugFlags__T1
> (libc_getenv (const_cast<void*> (static_cast<const void*>("GCC_M2LINK_RTFLAG"))));
1250 while ((pc
!= NULL
) && ((*pc
) != ASCII_nul
))
1252 if (equal (reinterpret_cast <void *> (pc
), (const char *) "all", 3))
1255 DependencyTrace
= true;
1260 WarningTrace
= true;
1263 else if (equal (reinterpret_cast <void *> (pc
), (const char *) "module", 6))
1265 /* avoid dangling else. */
1269 else if (equal (reinterpret_cast <void *> (pc
), (const char *) "warning", 7))
1271 /* avoid dangling else. */
1272 WarningTrace
= true;
1275 else if (equal (reinterpret_cast <void *> (pc
), (const char *) "hex", 3))
1277 /* avoid dangling else. */
1281 else if (equal (reinterpret_cast <void *> (pc
), (const char *) "dep", 3))
1283 /* avoid dangling else. */
1284 DependencyTrace
= true;
1287 else if (equal (reinterpret_cast <void *> (pc
), (const char *) "pre", 3))
1289 /* avoid dangling else. */
1293 else if (equal (reinterpret_cast <void *> (pc
), (const char *) "post", 4))
1295 /* avoid dangling else. */
1299 else if (equal (reinterpret_cast <void *> (pc
), (const char *) "force", 5))
1301 /* avoid dangling else. */
1307 /* avoid dangling else. */
1315 Init - initialize the debug flags and set all lists to NIL.
1318 static void Init (void)
1320 M2Dependent_DependencyState state
;
1322 InitProcList (&InitialProc
);
1323 InitProcList (&TerminateProc
);
1325 for (state
=M2Dependent_unregistered
; state
<=M2Dependent_user
; state
= static_cast<M2Dependent_DependencyState
>(static_cast<int>(state
+1)))
1327 Modules
.array
[state
-M2Dependent_unregistered
] = NULL
;
1329 DynamicInitialization
= false;
1334 CheckInitialized - checks to see if this module has been initialized
1335 and if it has not it calls Init. We need this
1336 approach as this module is called by module ctors
1337 before we reach main.
1340 static void CheckInitialized (void)
1351 ExecuteReverse - execute the procedure associated with procptr
1352 and then proceed to try and execute all previous
1353 procedures in the chain.
1356 static void ExecuteReverse (M2Dependent_ProcedureChain procptr
)
1358 while (procptr
!= NULL
)
1360 (*procptr
->p
.proc
) (); /* Invoke the procedure. */
1361 procptr
= procptr
->prev
; /* Invoke the procedure. */
1367 AppendProc - append proc to the end of the procedure list
1368 defined by proclist.
1371 static bool AppendProc (M2Dependent_ProcedureList
*proclist
, PROC proc
)
1373 M2Dependent_ProcedureChain pdes
;
1375 Storage_ALLOCATE ((void **) &pdes
, sizeof (M2Dependent__T3
));
1377 pdes
->prev
= (*proclist
).tail
;
1379 if ((*proclist
).head
== NULL
)
1381 (*proclist
).head
= pdes
;
1383 (*proclist
).tail
= pdes
;
1385 /* static analysis guarentees a RETURN statement will be used before here. */
1386 __builtin_unreachable ();
1391 InitProcList - initialize the head and tail pointers to NIL.
1394 static void InitProcList (M2Dependent_ProcedureList
*p
)
1402 ConstructModules - resolve dependencies and then call each
1403 module constructor in turn.
1406 extern "C" void M2Dependent_ConstructModules (void * applicationmodule
, void * libname
, void * overrideliborder
, int argc
, void * argv
, void * envp
)
1408 M2Dependent_ModuleChain mptr
;
1410 CheckInitialized ();
1411 DynamicInitialization
= true; /* This procedure is only called if we desire dynamic initialization. */
1412 traceprintf3 (ModuleTrace
, (const char *) "application module: %s [%s]\\n", 29, applicationmodule
, libname
); /* This procedure is only called if we desire dynamic initialization. */
1413 mptr
= LookupModule (M2Dependent_unordered
, applicationmodule
, libname
);
1416 mptr
->dependency
.appl
= true;
1418 traceprintf (PreTrace
, (const char *) "Pre resolving dependents\\n", 26);
1419 DumpModuleData (PreTrace
);
1420 ResolveDependencies (applicationmodule
, libname
);
1421 traceprintf (PreTrace
, (const char *) "Post resolving dependents\\n", 27);
1422 DumpModuleData (PostTrace
);
1423 ForceDependencies (overrideliborder
);
1424 traceprintf (ForceTrace
, (const char *) "After user forcing ordering\\n", 29);
1425 DumpModuleData (ForceTrace
);
1426 CheckApplication ();
1427 traceprintf (ForceTrace
, (const char *) "After runtime forces application to the end\\n", 45);
1428 DumpModuleData (ForceTrace
);
1429 if (Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
] == NULL
)
1431 traceprintf3 (ModuleTrace
, (const char *) " module: %s [%s] has not registered itself using a global constructor\\n", 72, applicationmodule
, libname
);
1432 traceprintf2 (ModuleTrace
, (const char *) " hint try compile and linking using: gm2 %s.mod\\n", 50, applicationmodule
);
1433 traceprintf2 (ModuleTrace
, (const char *) " or try using: gm2 -fscaffold-static %s.mod\\n", 46, applicationmodule
);
1437 mptr
= Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
];
1439 if (mptr
->dependency
.forc
)
1441 traceprintf3 (ModuleTrace
, (const char *) "initializing module: %s [%s] for C\\n", 36, mptr
->name
, mptr
->libname
);
1445 traceprintf3 (ModuleTrace
, (const char *) "initializing module: %s [%s]\\n", 30, mptr
->name
, mptr
->libname
);
1447 if (mptr
->dependency
.appl
)
1449 traceprintf3 (ModuleTrace
, (const char *) "application module: %s [%s]\\n", 29, mptr
->name
, mptr
->libname
);
1450 traceprintf (ModuleTrace
, (const char *) " calling ExecuteInitialProcedures\\n", 36);
1451 M2Dependent_ExecuteInitialProcedures ();
1452 traceprintf (ModuleTrace
, (const char *) " calling application module\\n", 30);
1454 (*mptr
->init
.proc
) (argc
, argv
, envp
);
1456 } while (! (mptr
== Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
]));
1462 DeconstructModules - resolve dependencies and then call each
1463 module constructor in turn.
1466 extern "C" void M2Dependent_DeconstructModules (void * applicationmodule
, void * libname
, int argc
, void * argv
, void * envp
)
1468 M2Dependent_ModuleChain mptr
;
1470 traceprintf3 (ModuleTrace
, (const char *) "application module finishing: %s [%s]\\n", 39, applicationmodule
, libname
);
1471 if (Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
] == NULL
)
1473 traceprintf (ModuleTrace
, (const char *) " no ordered modules found during finishing\\n", 45);
1477 traceprintf (ModuleTrace
, (const char *) "ExecuteTerminationProcedures\\n", 30);
1478 M2Dependent_ExecuteTerminationProcedures ();
1479 traceprintf (ModuleTrace
, (const char *) "terminating modules in sequence\\n", 33);
1480 mptr
= Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
]->prev
;
1482 if (mptr
->dependency
.forc
)
1484 traceprintf3 (ModuleTrace
, (const char *) "finalizing module: %s [%s] for C\\n", 34, mptr
->name
, mptr
->libname
);
1488 traceprintf3 (ModuleTrace
, (const char *) "finalizing module: %s [%s]\\n", 28, mptr
->name
, mptr
->libname
);
1490 (*mptr
->fini
.proc
) (argc
, argv
, envp
);
1492 } while (! (mptr
== Modules
.array
[M2Dependent_ordered
-M2Dependent_unregistered
]->prev
));
1498 RegisterModule - adds module name to the list of outstanding
1499 modules which need to have their dependencies
1500 explored to determine initialization order.
1503 extern "C" void M2Dependent_RegisterModule (void * modulename
, void * libname
, M2Dependent_ArgCVEnvP init
, M2Dependent_ArgCVEnvP fini
, PROC dependencies
)
1505 M2Dependent_ModuleChain mptr
;
1507 CheckInitialized ();
1508 mptr
= LookupModule (M2Dependent_unordered
, modulename
, libname
);
1511 traceprintf3 (ModuleTrace
, (const char *) "module: %s [%s] registering", 27, modulename
, libname
);
1512 moveTo (M2Dependent_unordered
, CreateModule (modulename
, libname
, init
, fini
, dependencies
));
1513 traceprintf (ModuleTrace
, (const char *) "\\n", 2);
1517 warning3 ((const char *) "module: %s [%s] (ignoring duplicate registration)\\n", 51, modulename
, libname
);
1523 RequestDependant - used to specify that modulename is dependant upon
1524 module dependantmodule. It only takes effect
1525 if we are using DynamicInitialization.
1528 extern "C" void M2Dependent_RequestDependant (void * modulename
, void * libname
, void * dependantmodule
, void * dependantlibname
)
1530 CheckInitialized ();
1531 PerformRequestDependant (modulename
, libname
, dependantmodule
, dependantlibname
);
1536 InstallTerminationProcedure - installs a procedure, p, which will
1537 be called when the procedure
1538 ExecuteTerminationProcedures
1539 is invoked. It returns TRUE if the
1540 procedure is installed.
1543 extern "C" bool M2Dependent_InstallTerminationProcedure (PROC p
)
1545 return AppendProc (&TerminateProc
, p
);
1546 /* static analysis guarentees a RETURN statement will be used before here. */
1547 __builtin_unreachable ();
1552 ExecuteInitialProcedures - executes the initial procedures installed by
1553 InstallInitialProcedure.
1556 extern "C" void M2Dependent_ExecuteInitialProcedures (void)
1558 ExecuteReverse (InitialProc
.tail
);
1563 InstallInitialProcedure - installs a procedure to be executed just
1564 before the BEGIN code section of the
1565 main program module.
1568 extern "C" bool M2Dependent_InstallInitialProcedure (PROC p
)
1570 return AppendProc (&InitialProc
, p
);
1571 /* static analysis guarentees a RETURN statement will be used before here. */
1572 __builtin_unreachable ();
1577 ExecuteTerminationProcedures - calls each installed termination procedure
1581 extern "C" void M2Dependent_ExecuteTerminationProcedures (void)
1583 ExecuteReverse (TerminateProc
.tail
);
1586 extern "C" void _M2_M2Dependent_init (__attribute__((unused
)) int argc
, __attribute__((unused
)) char *argv
[], __attribute__((unused
)) char *envp
[])
1588 CheckInitialized ();
1591 extern "C" void _M2_M2Dependent_fini (__attribute__((unused
)) int argc
, __attribute__((unused
)) char *argv
[], __attribute__((unused
)) char *envp
[])