xfail scan-tree-dump-not throw in g++.dg/pr99966.C on hppa*64*-*-*
[official-gcc.git] / gcc / m2 / gm2-libs / M2Dependent.mod
blobe7b502e29d77331be6effadefc90f9e33d8bc620
1 (* M2Dependent.mod implements the run time module dependencies.
3 Copyright (C) 2022-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. *)
27 IMPLEMENTATION MODULE M2Dependent ;
30 FROM libc IMPORT abort, exit, write, getenv, printf, snprintf, strncpy ;
31 FROM ASCII IMPORT nul, nl ;
32 FROM SYSTEM IMPORT ADR ;
33 FROM Storage IMPORT ALLOCATE ;
34 FROM StrLib IMPORT StrCopy, StrLen, StrEqual ;
36 IMPORT M2RTS ;
39 TYPE
40 PtrToChar = POINTER TO CHAR ;
42 DependencyState = (unregistered, unordered, started, ordered, user) ;
44 DependencyList = RECORD
45 proc : PROC ;
46 (* Has this module order been forced by the user? *)
47 forced,
48 (* Is the module a definition module for C? *)
49 forc : BOOLEAN ;
50 appl : BOOLEAN ; (* The application module? *)
51 state : DependencyState ;
52 END ;
54 ModuleChain = POINTER TO RECORD
55 name,
56 libname : ADDRESS ;
57 init,
58 fini : ArgCVEnvP ;
59 dependency: DependencyList ;
60 prev,
61 next : ModuleChain ;
62 END ;
64 VAR
65 Modules : ARRAY DependencyState OF ModuleChain ;
66 DynamicInitialization,
67 Initialized,
68 WarningTrace,
69 ModuleTrace,
70 HexTrace,
71 DependencyTrace,
72 PreTrace,
73 PostTrace,
74 ForceTrace : BOOLEAN ;
78 InitDependencyList - initialize all fields of DependencyList.
81 PROCEDURE InitDependencyList (VAR depList: DependencyList;
82 proc: PROC; state: DependencyState) ;
83 BEGIN
84 depList.proc := proc ;
85 depList.forced := FALSE ;
86 depList.forc := FALSE ;
87 depList.appl := FALSE ;
88 depList.state := state
89 END InitDependencyList ;
93 CreateModule - creates a new module entry and returns the
94 ModuleChain.
97 PROCEDURE CreateModule (name, libname: ADDRESS;
98 init, fini: ArgCVEnvP;
99 dependencies: PROC) : ModuleChain ;
101 mptr: ModuleChain ;
102 BEGIN
103 NEW (mptr) ;
104 mptr^.name := name ;
105 mptr^.libname := libname ;
106 mptr^.init := init ;
107 mptr^.fini := fini ;
108 InitDependencyList (mptr^.dependency, dependencies, unregistered) ;
109 mptr^.prev := NIL ;
110 mptr^.next := NIL ;
111 IF HexTrace
112 THEN
113 printf (" (init: %p fini: %p", init, fini) ;
114 printf (" dep: %p)", dependencies)
115 END ;
116 RETURN mptr
117 END CreateModule ;
121 AppendModule - append chain to end of the list.
124 PROCEDURE AppendModule (VAR head: ModuleChain; chain: ModuleChain) ;
125 BEGIN
126 IF head = NIL
127 THEN
128 head := chain ;
129 chain^.prev := chain ;
130 chain^.next := chain
131 ELSE
132 chain^.next := head ; (* Add Item to the end of list. *)
133 chain^.prev := head^.prev ;
134 head^.prev^.next := chain ;
135 head^.prev := chain
137 END AppendModule ;
141 RemoveModule - remove chain from double linked list head.
144 PROCEDURE RemoveModule (VAR head: ModuleChain; chain: ModuleChain) ;
145 BEGIN
146 IF (chain^.next=head) AND (chain=head)
147 THEN
148 head := NIL
149 ELSE
150 IF head=chain
151 THEN
152 head := head^.next
153 END ;
154 chain^.prev^.next := chain^.next ;
155 chain^.next^.prev := chain^.prev
157 END RemoveModule ;
161 onChain - returns TRUE if mptr is on the Modules[state] list.
164 PROCEDURE onChain (state: DependencyState; mptr: ModuleChain) : BOOLEAN ;
166 ptr: ModuleChain ;
167 BEGIN
168 IF Modules[state] # NIL
169 THEN
170 ptr := Modules[state] ;
171 REPEAT
172 IF ptr = mptr
173 THEN
174 RETURN TRUE
175 END ;
176 ptr := ptr^.next
177 UNTIL ptr=Modules[state]
178 END ;
179 RETURN FALSE
180 END onChain ;
184 max -
187 PROCEDURE max (a, b: CARDINAL) : CARDINAL ;
188 BEGIN
189 IF a > b
190 THEN
191 RETURN a
192 ELSE
193 RETURN b
195 END max ;
199 min -
202 PROCEDURE min (a, b: CARDINAL) : CARDINAL ;
203 BEGIN
204 IF a < b
205 THEN
206 RETURN a
207 ELSE
208 RETURN b
210 END min ;
214 LookupModuleN - lookup module from the state list.
215 The strings lengths are known.
218 PROCEDURE LookupModuleN (state: DependencyState;
219 name: ADDRESS; namelen: CARDINAL;
220 libname: ADDRESS; libnamelen: CARDINAL) : ModuleChain ;
222 ptr: ModuleChain ;
223 BEGIN
224 IF Modules[state] # NIL
225 THEN
226 ptr := Modules[state] ;
227 REPEAT
228 IF (strncmp (ptr^.name, name,
229 max (namelen, strlen (ptr^.name))) = 0) AND
230 (strncmp (ptr^.libname, libname,
231 max (libnamelen, strlen (ptr^.libname))) = 0)
232 THEN
233 RETURN ptr
234 END ;
235 ptr := ptr^.next
236 UNTIL ptr = Modules[state]
237 END ;
238 RETURN NIL
239 END LookupModuleN ;
243 LookupModule - lookup and return the ModuleChain pointer containing
244 module name from a particular list.
247 PROCEDURE LookupModule (state: DependencyState; name, libname: ADDRESS) : ModuleChain ;
248 BEGIN
249 RETURN LookupModuleN (state,
250 name, strlen (name),
251 libname, strlen (libname))
252 END LookupModule ;
256 toCString - replace any character sequence \n into a newline.
259 PROCEDURE toCString (VAR str: ARRAY OF CHAR) ;
261 high, i, j: CARDINAL ;
262 BEGIN
263 i := 0 ;
264 high := HIGH (str) ;
265 WHILE i < high DO
266 IF (i < high) AND (str[i] = "\")
267 THEN
268 IF str[i+1] = "n"
269 THEN
270 str[i] := nl ;
271 j := i+1 ;
272 WHILE j < high DO
273 str[j] := str[j+1] ;
274 INC (j)
277 END ;
278 INC (i)
280 END toCString ;
284 strcmp - return 0 if both strings are equal.
285 We cannot use Builtins.def during bootstrap.
288 PROCEDURE strcmp (a, b: PtrToChar) : INTEGER ;
289 BEGIN
290 IF (a # NIL) AND (b # NIL)
291 THEN
292 IF a = b
293 THEN
294 RETURN 0
295 ELSE
296 WHILE a^ = b^ DO
297 IF a^ = nul
298 THEN
299 RETURN 0
300 END ;
301 INC (a) ;
302 INC (b)
305 END ;
306 RETURN 1
307 END strcmp ;
311 strncmp - return 0 if both strings are equal.
312 We cannot use Builtins.def during bootstrap.
315 PROCEDURE strncmp (a, b: PtrToChar; n: CARDINAL) : INTEGER ;
316 BEGIN
317 IF n = 0
318 THEN
319 RETURN 0
320 ELSIF (a # NIL) AND (b # NIL)
321 THEN
322 IF a = b
323 THEN
324 RETURN 0
325 ELSE
326 WHILE (a^ = b^) AND (n > 0) DO
327 IF (a^ = nul) OR (n = 1)
328 THEN
329 RETURN 0
330 END ;
331 INC (a) ;
332 INC (b) ;
333 DEC (n)
336 END ;
337 RETURN 1
338 END strncmp ;
342 strlen - returns the length of string.
345 PROCEDURE strlen (string: PtrToChar) : INTEGER ;
347 count: INTEGER ;
348 BEGIN
349 IF string = NIL
350 THEN
351 RETURN 0
352 ELSE
353 count := 0 ;
354 WHILE string^ # nul DO
355 INC (string) ;
356 INC (count)
357 END ;
358 RETURN count
360 END strlen ;
364 traceprintf - wrap printf with a boolean flag.
367 PROCEDURE traceprintf (flag: BOOLEAN; str: ARRAY OF CHAR) ;
368 BEGIN
369 IF flag
370 THEN
371 toCString (str) ;
372 printf (str)
374 END traceprintf ;
378 traceprintf2 - wrap printf with a boolean flag.
381 PROCEDURE traceprintf2 (flag: BOOLEAN; str: ARRAY OF CHAR; arg: ADDRESS) ;
383 ch: CHAR ;
384 BEGIN
385 IF flag
386 THEN
387 toCString (str) ;
388 IF arg = NIL
389 THEN
390 ch := 0C ;
391 arg := ADR (ch)
392 END ;
393 printf (str, arg)
395 END traceprintf2 ;
399 traceprintf3 - wrap printf with a boolean flag.
402 PROCEDURE traceprintf3 (flag: BOOLEAN; str: ARRAY OF CHAR;
403 arg1, arg2: ADDRESS) ;
405 ch: CHAR ;
406 BEGIN
407 IF flag
408 THEN
409 toCString (str) ;
410 IF arg1 = NIL
411 THEN
412 ch := 0C ;
413 arg1 := ADR (ch)
414 END ;
415 IF arg2 = NIL
416 THEN
417 ch := 0C ;
418 arg2 := ADR (ch)
419 END ;
420 printf (str, arg1, arg2)
422 END traceprintf3 ;
426 moveTo - moves mptr to the new list determined by newstate.
427 It updates the mptr state appropriately.
430 PROCEDURE moveTo (newstate: DependencyState; mptr: ModuleChain) ;
431 BEGIN
432 IF onChain (mptr^.dependency.state, mptr)
433 THEN
434 RemoveModule (Modules[mptr^.dependency.state], mptr)
435 END ;
436 mptr^.dependency.state := newstate ;
437 AppendModule (Modules[mptr^.dependency.state], mptr)
438 END moveTo ;
442 ResolveDependant -
445 PROCEDURE ResolveDependant (mptr: ModuleChain; currentmodule, libname: ADDRESS) ;
446 BEGIN
447 IF mptr = NIL
448 THEN
449 traceprintf3 (DependencyTrace,
450 " module %s [%s] has not been registered via a global constructor\n",
451 currentmodule, libname);
452 ELSE
453 IF onChain (started, mptr)
454 THEN
455 traceprintf (DependencyTrace, " processing...\n");
456 ELSE
457 moveTo (started, mptr) ;
458 traceprintf3 (DependencyTrace, " starting: %s [%s]\n",
459 currentmodule, libname);
460 mptr^.dependency.proc ; (* Invoke and process the dependency graph. *)
461 traceprintf3 (DependencyTrace, " finished: %s [%s]\n",
462 currentmodule, libname);
463 moveTo (ordered, mptr)
466 END ResolveDependant ;
470 RequestDependant - used to specify that modulename is dependant upon
471 module dependantmodule. It only takes effect
472 if we are using DynamicInitialization.
475 PROCEDURE RequestDependant (modulename, libname,
476 dependantmodule, dependantlibname: ADDRESS) ;
477 BEGIN
478 CheckInitialized ;
479 PerformRequestDependant (modulename, libname,
480 dependantmodule, dependantlibname)
481 END RequestDependant ;
485 PerformRequestDependant - the current modulename has a dependancy upon
486 dependantmodule. If dependantmodule is NIL then
487 modulename has no further dependants and it can be
488 resolved.
491 PROCEDURE PerformRequestDependant (modulename, libname,
492 dependantmodule, dependantlibname: ADDRESS) ;
494 mptr: ModuleChain ;
495 BEGIN
496 traceprintf3 (DependencyTrace, " module %s [%s]", modulename, libname) ;
497 IF dependantmodule = NIL
498 THEN
499 traceprintf (DependencyTrace, " has finished its import graph\n") ;
500 mptr := LookupModule (unordered, modulename, libname) ;
501 IF mptr # NIL
502 THEN
503 traceprintf3 (DependencyTrace, " module %s [%s] is now ordered\n",
504 modulename, libname) ;
505 moveTo (ordered, mptr)
507 ELSE
508 traceprintf3 (DependencyTrace, " imports from %s [%s]\n",
509 dependantmodule, dependantlibname) ;
510 mptr := LookupModule (ordered, dependantmodule, dependantlibname) ;
511 IF mptr = NIL
512 THEN
513 traceprintf3 (DependencyTrace, " module %s [%s] is not ordered\n",
514 dependantmodule, dependantlibname) ;
515 mptr := LookupModule (unordered, dependantmodule, dependantlibname) ;
516 IF mptr = NIL
517 THEN
518 traceprintf3 (DependencyTrace, " module %s [%s] is not unordered\n",
519 dependantmodule, dependantlibname) ;
520 mptr := LookupModule (started, dependantmodule, dependantlibname) ;
521 IF mptr = NIL
522 THEN
523 traceprintf3 (DependencyTrace, " module %s [%s] has not started\n",
524 dependantmodule, dependantlibname) ;
525 traceprintf3 (DependencyTrace, " module %s [%s] attempting to import from",
526 modulename, libname) ;
527 traceprintf3 (DependencyTrace, " %s [%s] which has not registered itself via a constructor\n",
528 dependantmodule, dependantlibname)
529 ELSE
530 traceprintf3 (DependencyTrace, " module %s [%s] has registered itself and has started\n",
531 dependantmodule, dependantlibname)
533 ELSE
534 traceprintf3 (DependencyTrace, " module %s [%s] resolving\n", dependantmodule, dependantlibname) ;
535 ResolveDependant (mptr, dependantmodule, dependantlibname)
537 ELSE
538 traceprintf3 (DependencyTrace, " module %s [%s]", modulename, libname) ;
539 traceprintf3 (DependencyTrace, " dependant %s [%s] is ordered\n", dependantmodule, dependantlibname)
542 END PerformRequestDependant ;
546 ResolveDependencies - resolve dependencies for currentmodule, libname.
549 PROCEDURE ResolveDependencies (currentmodule, libname: ADDRESS) ;
551 mptr: ModuleChain ;
552 BEGIN
553 mptr := LookupModule (unordered, currentmodule, libname) ;
554 WHILE mptr # NIL DO
555 traceprintf3 (DependencyTrace, " attempting to resolve the dependants for %s [%s]\n",
556 currentmodule, libname);
557 ResolveDependant (mptr, currentmodule, libname) ;
558 mptr := Modules[unordered]
560 END ResolveDependencies ;
564 DisplayModuleInfo - displays all module in the state.
567 PROCEDURE DisplayModuleInfo (state: DependencyState; desc: ARRAY OF CHAR) ;
569 mptr : ModuleChain ;
570 count: CARDINAL ;
571 BEGIN
572 IF Modules[state] # NIL
573 THEN
574 printf ("%s modules\n", ADR (desc)) ;
575 mptr := Modules[state] ;
576 count := 0 ;
577 REPEAT
578 IF mptr^.name = NIL
579 THEN
580 printf (" %d %s []", count, mptr^.name)
581 ELSE
582 printf (" %d %s [%s]", count, mptr^.name, mptr^.libname)
583 END ;
584 INC (count) ;
585 IF mptr^.dependency.appl
586 THEN
587 printf (" application")
588 END ;
589 IF mptr^.dependency.forc
590 THEN
591 printf (" for C")
592 END ;
593 IF mptr^.dependency.forced
594 THEN
595 printf (" forced ordering")
596 END ;
597 printf ("\n") ;
598 mptr := mptr^.next ;
599 UNTIL mptr = Modules[state]
601 END DisplayModuleInfo ;
605 DumpModuleData -
608 PROCEDURE DumpModuleData (flag: BOOLEAN) ;
609 BEGIN
610 IF flag
611 THEN
612 DisplayModuleInfo (unregistered, "unregistered") ;
613 DisplayModuleInfo (unordered, "unordered") ;
614 DisplayModuleInfo (started, "started") ;
615 DisplayModuleInfo (ordered, "ordered") ;
617 END DumpModuleData ;
621 combine - dest := src + dest. Places src at the front of list dest.
622 Pre condition: src, dest are lists.
623 Post condition : dest := src + dest
624 src := NIL.
627 PROCEDURE combine (src, dest: DependencyState) ;
629 last: ModuleChain ;
630 BEGIN
631 WHILE Modules[src] # NIL DO
632 last := Modules[src]^.prev ;
633 moveTo (ordered, last) ;
634 Modules[dest] := last (* New item is at the head. *)
636 END combine ;
640 tracemodule -
643 PROCEDURE tracemodule (flag: BOOLEAN; modname: ADDRESS; modlen: CARDINAL; libname: ADDRESS; liblen: CARDINAL) ;
645 buffer: ARRAY [0..100] OF CHAR ;
646 len : CARDINAL ;
647 BEGIN
648 IF flag
649 THEN
650 len := min (modlen, SIZE (buffer)-1) ;
651 strncpy (ADR(buffer), modname, len) ;
652 buffer[len] := 0C ;
653 printf ("%s ", ADR (buffer)) ;
654 len := min (liblen, SIZE (buffer)-1) ;
655 strncpy (ADR(buffer), libname, len) ;
656 buffer[len] := 0C ;
657 printf (" [%s]", ADR (buffer))
659 END tracemodule ;
663 ForceModule -
666 PROCEDURE ForceModule (modname: ADDRESS; modlen: CARDINAL;
667 libname: ADDRESS; liblen: CARDINAL) ;
669 mptr: ModuleChain ;
670 BEGIN
671 traceprintf (ForceTrace, "forcing module: ") ;
672 tracemodule (ForceTrace, modname, modlen, libname, liblen) ;
673 traceprintf (ForceTrace, "\n") ;
674 mptr := LookupModuleN (ordered, modname, modlen, libname, liblen) ;
675 IF mptr # NIL
676 THEN
677 mptr^.dependency.forced := TRUE ;
678 moveTo (user, mptr)
680 END ForceModule ;
684 ForceDependencies - if the user has specified a forced order then we override
685 the dynamic ordering with the preference.
688 PROCEDURE ForceDependencies (overrideliborder: ADDRESS) ;
690 len,
691 modlen,
692 liblen : CARDINAL ;
693 modname,
694 libname,
695 pc, start: PtrToChar ;
696 BEGIN
697 IF overrideliborder # NIL
698 THEN
699 traceprintf2 (ForceTrace, "user forcing order: %s\n", overrideliborder) ;
700 pc := overrideliborder ;
701 start := pc ;
702 len := 0 ;
703 modname := NIL ;
704 modlen := 0 ;
705 libname := NIL ;
706 liblen := 0 ;
707 WHILE pc^ # nul DO
708 CASE pc^ OF
710 ':': libname := start ;
711 liblen := len ;
712 len := 0 ;
713 INC (pc) ;
714 start := pc |
715 ',': modname := start ;
716 modlen := len ;
717 ForceModule (modname, modlen, libname, liblen) ;
718 libname := NIL ;
719 liblen := 0 ;
720 modlen := 0 ;
721 len := 0 ;
722 INC (pc) ;
723 start := pc
724 ELSE
725 INC (pc) ;
726 INC (len)
728 END ;
729 IF start # pc
730 THEN
731 ForceModule (start, len, libname, liblen)
732 END ;
733 combine (user, ordered)
735 END ForceDependencies ;
739 CheckApplication - check to see that the application is the last entry in the list.
740 This might happen if the application only imports FOR C modules.
743 PROCEDURE CheckApplication ;
745 mptr,
746 appl: ModuleChain ;
747 BEGIN
748 mptr := Modules[ordered] ;
749 IF mptr # NIL
750 THEN
751 appl := NIL ;
752 REPEAT
753 IF mptr^.dependency.appl
754 THEN
755 appl := mptr
756 ELSE
757 mptr := mptr^.next
759 UNTIL (appl # NIL) OR (mptr=Modules[ordered]) ;
760 IF appl # NIL
761 THEN
762 RemoveModule (Modules[ordered], appl) ;
763 AppendModule (Modules[ordered], appl)
766 END CheckApplication ;
770 ConstructModules - resolve dependencies and then call each
771 module constructor in turn.
774 PROCEDURE ConstructModules (applicationmodule, libname,
775 overrideliborder: ADDRESS;
776 argc: INTEGER; argv, envp: ADDRESS) ;
778 mptr: ModuleChain ;
779 BEGIN
780 CheckInitialized ;
781 DynamicInitialization := TRUE ; (* This procedure is only called if we desire dynamic initialization. *)
782 traceprintf3 (ModuleTrace, "application module: %s [%s]\n",
783 applicationmodule, libname);
784 mptr := LookupModule (unordered, applicationmodule, libname) ;
785 IF mptr # NIL
786 THEN
787 mptr^.dependency.appl := TRUE
788 END ;
789 traceprintf (PreTrace, "Pre resolving dependents\n");
790 DumpModuleData (PreTrace) ;
791 ResolveDependencies (applicationmodule, libname) ;
792 traceprintf (PreTrace, "Post resolving dependents\n");
793 DumpModuleData (PostTrace) ;
794 ForceDependencies (overrideliborder) ;
795 traceprintf (ForceTrace, "After user forcing ordering\n");
796 DumpModuleData (ForceTrace) ;
797 CheckApplication ;
798 traceprintf (ForceTrace, "After runtime forces application to the end\n");
799 DumpModuleData (ForceTrace) ;
800 IF Modules[ordered] = NIL
801 THEN
802 traceprintf3 (ModuleTrace, " module: %s [%s] has not registered itself using a global constructor\n",
803 applicationmodule, libname);
804 traceprintf2 (ModuleTrace, " hint try compile and linking using: gm2 %s.mod\n", applicationmodule);
805 traceprintf2 (ModuleTrace, " or try using: gm2 -fscaffold-static %s.mod\n",
806 applicationmodule);
807 ELSE
808 mptr := Modules[ordered] ;
809 REPEAT
810 IF mptr^.dependency.forc
811 THEN
812 traceprintf3 (ModuleTrace, "initializing module: %s [%s] for C\n", mptr^.name, mptr^.libname)
813 ELSE
814 traceprintf3 (ModuleTrace, "initializing module: %s [%s]\n", mptr^.name, mptr^.libname);
815 END ;
816 IF mptr^.dependency.appl
817 THEN
818 traceprintf3 (ModuleTrace, "application module: %s [%s]\n", mptr^.name, mptr^.libname);
819 traceprintf (ModuleTrace, " calling M2RTS_ExecuteInitialProcedures\n");
820 M2RTS.ExecuteInitialProcedures ;
821 traceprintf (ModuleTrace, " calling application module\n");
822 END ;
823 mptr^.init (argc, argv, envp) ;
824 mptr := mptr^.next
825 UNTIL mptr = Modules[ordered]
827 END ConstructModules ;
831 DeconstructModules - resolve dependencies and then call each
832 module constructor in turn.
835 PROCEDURE DeconstructModules (applicationmodule, libname: ADDRESS;
836 argc: INTEGER; argv, envp: ADDRESS) ;
838 mptr: ModuleChain ;
839 BEGIN
840 traceprintf3 (ModuleTrace, "application module finishing: %s [%s]\n",
841 applicationmodule, libname);
842 IF Modules[ordered] = NIL
843 THEN
844 traceprintf (ModuleTrace, " no ordered modules found during finishing\n")
845 ELSE
846 traceprintf (ModuleTrace, "ExecuteTerminationProcedures\n") ;
847 M2RTS.ExecuteTerminationProcedures ;
848 traceprintf (ModuleTrace, "terminating modules in sequence\n") ;
849 mptr := Modules[ordered]^.prev ;
850 REPEAT
851 IF mptr^.dependency.forc
852 THEN
853 traceprintf3 (ModuleTrace, "finalizing module: %s [%s] for C\n",
854 mptr^.name, mptr^.libname)
855 ELSE
856 traceprintf3 (ModuleTrace, "finalizing module: %s [%s]\n",
857 mptr^.name, mptr^.libname)
858 END ;
859 mptr^.fini (argc, argv, envp) ;
860 mptr := mptr^.prev
861 UNTIL mptr = Modules[ordered]^.prev
863 END DeconstructModules ;
867 warning3 - write format arg1 arg2 to stderr.
870 PROCEDURE warning3 (format: ARRAY OF CHAR; arg1, arg2: ADDRESS) ;
872 buffer: ARRAY [0..4096] OF CHAR ;
873 len : INTEGER ;
874 BEGIN
875 IF WarningTrace
876 THEN
877 len := snprintf (ADR (buffer), SIZE (buffer), "warning: ") ;
878 write (2, ADR (buffer), len) ;
879 len := snprintf (ADR (buffer), SIZE (buffer), format, arg1, arg2) ;
880 write (2, ADR (buffer), len)
882 END warning3 ;
886 RegisterModule - adds module name to the list of outstanding
887 modules which need to have their dependencies
888 explored to determine initialization order.
891 PROCEDURE RegisterModule (modulename, libname: ADDRESS;
892 init, fini: ArgCVEnvP;
893 dependencies: PROC) ;
895 mptr: ModuleChain ;
896 BEGIN
897 CheckInitialized ;
898 mptr := LookupModule (unordered, modulename, libname) ;
899 IF mptr = NIL
900 THEN
901 traceprintf3 (ModuleTrace, "module: %s [%s] registering",
902 modulename, libname);
903 moveTo (unordered,
904 CreateModule (modulename, libname, init, fini, dependencies)) ;
905 traceprintf (ModuleTrace, "\n") ;
906 ELSE
907 warning3 ("module: %s [%s] (ignoring duplicate registration)\n",
908 modulename, libname)
910 END RegisterModule ;
914 equal - return TRUE if C string cstr is equal to str.
917 PROCEDURE equal (cstr: ADDRESS; str: ARRAY OF CHAR) : BOOLEAN ;
918 BEGIN
919 RETURN strncmp (cstr, ADR (str), StrLen (str)) = 0
920 END equal ;
924 SetupDebugFlags - By default assigns ModuleTrace, DependencyTrace,
925 DumpPostInit to FALSE. It checks the environment
926 GCC_M2LINK_RTFLAG which can contain
927 "all,module,hex,pre,post,dep,force". all turns them all on.
928 The flag meanings are as follows and flags the are in
929 execution order.
931 module generate trace info as the modules are registered.
932 hex dump the modules ctor functions address in hex.
933 pre generate a list of all modules seen prior to having
934 their dependancies resolved.
935 dep display a trace as the modules are resolved.
936 post generate a list of all modules seen after having
937 their dependancies resolved dynamically.
938 force generate a list of all modules seen after having
939 their dependancies resolved and forced.
942 PROCEDURE SetupDebugFlags ;
944 pc: POINTER TO CHAR ;
945 BEGIN
946 ModuleTrace := FALSE ;
947 DependencyTrace := FALSE ;
948 PostTrace := FALSE ;
949 PreTrace := FALSE ;
950 ForceTrace := FALSE ;
951 HexTrace := FALSE ;
952 WarningTrace := FALSE ;
953 pc := getenv (ADR ("GCC_M2LINK_RTFLAG")) ;
954 WHILE (pc # NIL) AND (pc^ # nul) DO
955 IF equal (pc, "all")
956 THEN
957 ModuleTrace := TRUE ;
958 DependencyTrace := TRUE ;
959 PreTrace := TRUE ;
960 PostTrace := TRUE ;
961 ForceTrace := TRUE ;
962 HexTrace := TRUE ;
963 WarningTrace := TRUE ;
964 INC (pc, 3)
965 ELSIF equal (pc, "module")
966 THEN
967 ModuleTrace := TRUE ;
968 INC (pc, 6)
969 ELSIF equal (pc, "warning")
970 THEN
971 WarningTrace := TRUE ;
972 INC (pc, 7)
973 ELSIF equal (pc, "hex")
974 THEN
975 HexTrace := TRUE ;
976 INC (pc, 3)
977 ELSIF equal (pc, "dep")
978 THEN
979 DependencyTrace := TRUE ;
980 INC (pc, 3)
981 ELSIF equal (pc, "pre")
982 THEN
983 PreTrace := TRUE ;
984 INC (pc, 3)
985 ELSIF equal (pc, "post")
986 THEN
987 PostTrace := TRUE ;
988 INC (pc, 4)
989 ELSIF equal (pc, "force")
990 THEN
991 ForceTrace := TRUE ;
992 INC (pc, 5)
993 ELSE
994 INC (pc)
997 END SetupDebugFlags ;
1001 Init - initialize the debug flags and set all lists to NIL.
1004 PROCEDURE Init ;
1006 state: DependencyState ;
1007 BEGIN
1008 SetupDebugFlags ;
1009 FOR state := MIN (DependencyState) TO MAX (DependencyState) DO
1010 Modules[state] := NIL
1011 END ;
1012 DynamicInitialization := FALSE
1013 END Init ;
1017 CheckInitialized - checks to see if this module has been initialized
1018 and if it has not it calls Init. We need this
1019 approach as this module is called by module ctors
1020 before we reach main.
1023 PROCEDURE CheckInitialized ;
1024 BEGIN
1025 IF NOT Initialized
1026 THEN
1027 Initialized := TRUE ;
1028 Init
1030 END CheckInitialized ;
1033 BEGIN
1034 CheckInitialized
1035 END M2Dependent.