DIRECTORY
CommandUtil: TYPE USING [GetRootName],
FileIO: TYPE USING [Open, StreamFromOpenFile],
FS: TYPE USING [Open, OpenFile],
IO: TYPE USING [Close, GetLength, SetIndex, STREAM, UnsafeGetBlock, UnsafePutBlock],
PGSConDefs:
TYPE
USING [
objectVersion, sourceVersion, FixupBcdHeader, WriteBcdHeader],
PrincOps: TYPE USING [bytesPerWord],
Rope: TYPE USING [Equal, Find, Length, ROPE],
TableCommand: TYPE USING [CreateTime, GenerateVersion],
VM: TYPE USING [Allocate, Free, Interval, PageNumberToAddress, WordsToPages];
ModuleMaker:
PROGRAM
IMPORTS
CommandUtil, FileIO, FS, IO, PGSConDefs, Rope, TableCommand, VM
EXPORTS TableCommand = {
StreamIndex: TYPE = INT; -- FileStream.FileByteIndex
bytesPerWord: NAT = PrincOps.bytesPerWord;
interface to PGSBcd
CreateBCDStream:
PUBLIC
PROC [
in: IO.STREAM,
modId, interfaceId: Rope.ROPE,
altoCode: BOOL ← FALSE]
RETURNS [output: IO.STREAM] = {
modRoot: Rope.ROPE;
interfaceRoot: Rope.ROPE;
SetSourceVersion[in];
PGSConDefs.objectVersion ← TableCommand.GenerateVersion[];
modRoot ← CommandUtil.GetRootName[modId];
output ← FileIO.Open[modId, write];
fill in interface info
interfaceRoot ← CommandUtil.GetRootName[interfaceId];
PGSConDefs.WriteBcdHeader[
outStream: output,
tableId: modRoot, binaryId: modId,
interfaceId: IF Rope.Equal[interfaceRoot, "SELF", FALSE] THEN NIL ELSE interfaceRoot,
fileId: NIL, -- for now
altoCode: altoCode];
RETURN};
FinishBcdStream:
PUBLIC
PROC = {
PGSConDefs.FixupBcdHeader[]};
input management
CheckForBr:
PROC [name: Rope.
ROPE]
RETURNS [
BOOL] = {
index: INT ← Rope.Find[s1: name, s2: ".BR", case: FALSE];
IF index < 0 THEN RETURN[FALSE];
RETURN[name.Length[] = index + 3]};
FindSegmentSize:
PROC [br:
BOOL, file:
FS.OpenFile]
RETURNS [count: CARDINAL, in: IO.STREAM] = {
GetWord:
PROC[stream:
IO.
STREAM]
RETURNS[word:
WORD ← 0] =
INLINE {
[] ← stream.UnsafeGetBlock[[@word, 0, 1]]};
in ← FileIO.StreamFromOpenFile[file];
IF br
THEN {
IO.SetIndex[in, 7*PrincOps.bytesPerWord];
count ← GetWord[in];
IO.SetIndex[in, count*PrincOps.bytesPerWord];
count ← GetWord[in]}
ELSE {
eof: StreamIndex = IO.GetLength[in];
count ← eof/PrincOps.bytesPerWord;
IO.SetIndex[in, 0]};
RETURN};
CreateSegmentStream:
PROC [segmentId: Rope.
ROPE]
RETURNS [in: IO.STREAM, count: CARDINAL] = {
brFile: BOOL = CheckForBr[segmentId];
file: FS.OpenFile;
file ← FS.Open[segmentId, read];
[count, in] ← FindSegmentSize[brFile, file];
RETURN};
SetSourceVersion:
PROC [sh:
IO.
STREAM] = {
PGSConDefs.sourceVersion ← [0, 0, TableCommand.CreateTime[sh]]};
overall control
WriteSegment:
PROC [in, out:
IO.
STREAM, count:
CARDINAL] = {
interval: VM.Interval ← VM.Allocate[VM.WordsToPages[count]];
p: LONG POINTER ← VM.PageNumberToAddress[interval.page];
[] ← in.UnsafeGetBlock[[p, 0, count*PrincOps.bytesPerWord]];
out.UnsafePutBlock[[p, 0, count*PrincOps.bytesPerWord]];
VM.Free[interval]};
MakeModule:
PUBLIC
PROC [
inputFile, moduleId, interfaceId: Rope.ROPE, altocode: BOOL] = {
in, output: IO.STREAM;
count: CARDINAL;
[in, count] ← CreateSegmentStream[inputFile];
output ← CreateBCDStream[in, moduleId, interfaceId, altocode];
WriteSegment[in, output, count];
FinishBcdStream[];
IO.Close[in];
IO.Close[output]};
}.