blob: 70b6eae6557b912ba5bc27571d261c1457f77bfa [file] [log] [blame]
(* gm2lorder.mod ensure that underlying runtime modules are initialized.
Copyright (C) 2008-2026 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.
You should have received a copy of the GNU General Public License
along with GNU Modula-2; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. *)
MODULE gm2lorder ;
(*
Author : Gaius Mulley
Title : gm2lorder
Date : Thu Sep 4 21:18:33 BST 2008
Description: Ensures that underlying runtime modules are initialized
before all other modules.
*)
FROM libc IMPORT exit ;
FROM ASCII IMPORT eof ;
FROM SArgs IMPORT GetArg ;
FROM StrLib IMPORT StrLen ;
FROM DynamicStrings IMPORT String, InitString, KillString, Length, Equal, EqualArray, Slice, Mark ;
FROM Indexing IMPORT Index, PutIndice, GetIndice, RemoveIndiceFromIndex, InitIndex, KillIndex, HighIndice ;
FROM FIO IMPORT File, StdIn, StdOut, StdErr, WriteChar, WriteLine,
Close, EOF, IsNoError, WriteString, FlushBuffer ;
FROM SFIO IMPORT OpenToRead, OpenToWrite, ReadS, WriteS ;
IMPORT DynamicStrings ;
CONST
Comment = '#' ; (* Comment identifier. *)
DefaultRuntimeModules = 'Storage,SYSTEM,M2RTS,RTExceptions,IOLink' ;
VAR
fi, fo : File ;
runTime : Index ;
moduleList: Index ;
(*
InitRuntimeModules - initializes the list of critical runtime modules
which must be initialized first and in a particular
order.
*)
PROCEDURE InitRuntimeModules (s: String) ;
VAR
a : CARDINAL ;
i, j: INTEGER ;
BEGIN
IF runTime # NIL
THEN
runTime := KillIndex (runTime)
END ;
runTime := InitIndex (0) ;
i := 0 ;
a := 0 ;
REPEAT
j := DynamicStrings.Index (s, ',', i) ;
IF j = -1
THEN
PutIndice (runTime, a, Slice (s, i, 0))
ELSE
PutIndice (runTime, a, Slice (s, i, j)) ;
i := j+1
END ;
INC(a)
UNTIL j=-1 ;
s := KillString (s)
END InitRuntimeModules ;
(*
Reorder - reorders the list of modules to ensure critical runtime
modules are initialized first. It writes out the new
ordered list.
*)
PROCEDURE Reorder ;
VAR
rh, mh,
ri, mi: CARDINAL ;
rs, ms: String ;
BEGIN
rh := HighIndice (runTime) ;
mh := HighIndice (moduleList) ;
ri := 0 ;
WHILE ri <= rh DO
mi := 0 ;
rs := GetIndice (runTime, ri) ;
WHILE mi <= mh DO
ms := GetIndice (moduleList, mi) ;
IF Equal (rs, ms)
THEN
rs := WriteS (fo, rs) ; WriteLine (fo) ;
RemoveIndiceFromIndex (moduleList, ms) ;
mh := HighIndice (moduleList)
ELSE
INC (mi)
END
END ;
INC (ri)
END ;
mi := 0 ;
WHILE mi <= mh DO
ms := GetIndice (moduleList, mi) ;
ms := WriteS (fo, ms) ; WriteLine (fo) ;
INC (mi)
END ;
Close (fo)
END Reorder ;
(*
ReadList - populates the moduleList with a list of module names.
*)
PROCEDURE ReadList ;
VAR
s: String ;
i: CARDINAL ;
BEGIN
moduleList := InitIndex (0) ;
i := 0 ;
s := ReadS (fi) ;
WHILE NOT EOF (fi) DO
IF NOT EqualArray (s, '')
THEN
PutIndice (moduleList, i, s) ;
INC (i)
END ;
s := ReadS (fi)
END ;
IF NOT EqualArray (s, '')
THEN
PutIndice (moduleList, i, s)
END
END ReadList ;
(*
OpenOutputFile - attempts to open an output file.
*)
PROCEDURE OpenOutputFile (s: String) ;
BEGIN
IF EqualArray(s, '-')
THEN
fo := StdOut
ELSE
fo := OpenToWrite(s) ;
IF NOT IsNoError(fo)
THEN
WriteString(StdErr, 'cannot write to: ') ; s := WriteS(StdErr, s) ; WriteLine(StdErr) ;
exit(1)
END
END
END OpenOutputFile ;
(*
Usage - prints out a usage and exits with 0.
*)
PROCEDURE Usage ;
BEGIN
WriteString(StdOut, 'gm2lorder [-h] [-o outputfile] [-fruntime-modules=] inputfile') ; WriteLine(StdOut) ;
WriteString(StdOut, ' inputfile is a file containing a list of modules, each module on a separate line') ; WriteLine(StdOut) ;
WriteString(StdOut, ' the list of runtime modules can be specified as follows -fruntime-modules=module1,module2,module3') ; WriteLine(StdOut) ;
WriteString(StdOut, ' the default for this flag is -fruntime-modules=') ;
WriteString(StdOut, DefaultRuntimeModules) ; WriteLine(StdOut) ;
WriteString(StdOut, ' Note that the list of runtime modules does not mean they will appear in the executable') ; WriteLine(StdOut) ;
WriteString(StdOut, ' a runtime module is only included into the final executable if it is required,') ; WriteLine(StdOut) ;
WriteString(StdOut, ' however gm2lorder will ensure the order of these modules.') ; WriteLine(StdOut) ;
FlushBuffer(StdOut) ;
exit(0)
END Usage ;
(*
ScanArgs - scans arguments.
*)
PROCEDURE ScanArgs ;
VAR
i : CARDINAL ;
s : String ;
FoundFile: BOOLEAN ;
BEGIN
FoundFile := FALSE ;
fi := StdIn ;
fo := StdOut ;
i := 1 ;
WHILE GetArg(s, i) DO
IF EqualArray(s, '-o')
THEN
s := KillString(s) ;
INC(i) ;
IF GetArg(s, i)
THEN
OpenOutputFile(s)
ELSE
WriteString(StdErr, 'missing filename option after -o') ; WriteLine(StdErr) ;
exit(1)
END
ELSIF EqualArray(s, '-h')
THEN
Usage
ELSIF EqualArray(Mark(Slice(s, 0, StrLen('-fruntime-modules='))), '-fruntime-modules=')
THEN
InitRuntimeModules(Slice(s, StrLen('-fruntime-modules='), 0))
ELSE
IF FoundFile
THEN
WriteString(StdErr, 'already opened one file for reading') ; WriteLine(StdErr)
ELSE
FoundFile := TRUE ;
fi := OpenToRead(s) ;
IF NOT IsNoError(fi)
THEN
WriteString(StdErr, 'failed to open: ') ; s := WriteS(StdErr, s) ; WriteLine(StdErr) ;
exit(1)
END
END
END ;
INC(i)
END ;
IF NOT FoundFile
THEN
WriteString(StdErr, 'a module file list must be specified on the command line') ; WriteLine(StdErr) ;
exit(1)
END
END ScanArgs ;
(*
Init -
*)
PROCEDURE Init ;
BEGIN
runTime := NIL ;
moduleList := NIL ;
InitRuntimeModules(InitString(DefaultRuntimeModules)) ;
ScanArgs ;
ReadList ;
Reorder
END Init ;
BEGIN
Init
END gm2lorder.