-- file ModuleMaker.mesa
-- last edited by Satterthwaite, July 2, 1982 3:57 pm
DIRECTORY
Environment: TYPE USING [bytesPerWord],
File: TYPE USING [Capability],
FileStream: TYPE USING [FileByteIndex, Create, GetLength, SetIndex],
OSMiscOps: TYPE USING [FindFile],
PGSConDefs: TYPE USING [
objectVersion, sourceVersion, FixupBcdHeader, WriteBcdHeader],
Spaces: TYPE USING [FreeWords, Words],
Stream: TYPE USING [Handle, Delete, GetBlock, GetWord, PutBlock],
Strings: TYPE USING [
String, SubStringDescriptor, AppendChar, AppendString, EquivalentSubStrings],
TableCommand: TYPE USING [CreateTime, GenerateVersion];
ModuleMaker: PROGRAM
IMPORTS
FileStream, OSMiscOps, PGSConDefs, Spaces, Stream, Strings, TableCommand
EXPORTS TableCommand = {
StreamIndex: TYPE = FileStream.FileByteIndex;
bytesPerWord: CARDINAL = Environment.bytesPerWord;
-- interface to PGSBcd
CreateBCDStream: PUBLIC PROC [
in: Stream.Handle,
modId, interfaceId: Strings.String,
altoCode: BOOL ← FALSE]
RETURNS [output: Stream.Handle] = {
modRoot: STRING ← [40];
interfaceRoot: STRING ← [40];
self: Strings.SubStringDescriptor ← ["SELF"L, 0, ("SELF"L).length];
interface: Strings.SubStringDescriptor;
t: STRING = [40];
SetSourceVersion[in];
PGSConDefs.objectVersion ← TableCommand.GenerateVersion[];
FOR i: CARDINAL IN [0..modId.length) DO
IF modId[i] = '. THEN EXIT;
Strings.AppendChar[modRoot, modId[i]];
ENDLOOP;
Strings.AppendString[t, modId];
output ← FileStream.Create[OSMiscOps.FindFile[t, write]];
-- fill in interface info
FOR i: CARDINAL IN [0..interfaceId.length) DO
IF interfaceId[i] = '. THEN EXIT;
Strings.AppendChar[interfaceRoot, interfaceId[i]];
ENDLOOP;
interface ← [interfaceRoot, 0, interfaceRoot.length];
PGSConDefs.WriteBcdHeader[
outStream: output,
tableId: modRoot, binaryId: modId,
interfaceId:
IF Strings.EquivalentSubStrings[@interface, @self] THEN NIL ELSE interfaceRoot,
fileId: NIL, -- for now
altoCode: altoCode];
RETURN};
FinishBcdStream: PUBLIC PROC = {
PGSConDefs.FixupBcdHeader[]};
-- input management
CheckForBr: PROC [name: Strings.String] RETURNS [BOOL] = {
FOR i: CARDINAL IN [0..name.length) DO
IF name[i] = '. THEN GOTO extension;
REPEAT
extension =>
IF name.length = i+3 AND
(name[i+1] = 'b OR name[i+1] = 'B) AND
(name[i+2] = 'r OR name[i+2] = 'R) THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE]};
FindSegmentSize: PROC [br: BOOL, file: File.Capability]
RETURNS [count: CARDINAL, in: Stream.Handle] = {
in ← FileStream.Create[file];
IF br THEN {
FileStream.SetIndex[in, 7*Environment.bytesPerWord];
count ← in.GetWord[];
FileStream.SetIndex[in, count*Environment.bytesPerWord];
count ← in.GetWord[]}
ELSE {
eof: StreamIndex = FileStream.GetLength[in];
count ← eof/Environment.bytesPerWord;
FileStream.SetIndex[in, 0]};
RETURN};
CreateSegmentStream: PROC [segmentId: Strings.String]
RETURNS [in: Stream.Handle, count: CARDINAL] = {
brFile: BOOL = CheckForBr[segmentId];
t: STRING = [40];
file: File.Capability;
Strings.AppendString[t, segmentId];
file ← OSMiscOps.FindFile[t, read];
[count, in] ← FindSegmentSize[brFile, file];
RETURN};
SetSourceVersion: PROC [sh: Stream.Handle] = {
PGSConDefs.sourceVersion ← [0, 0, TableCommand.CreateTime[sh]]};
-- overall control
WriteSegment: PROC [in, out: Stream.Handle, count: CARDINAL] = {
p: LONG POINTER ← Spaces.Words[count];
[] ← in.GetBlock[[p, 0, count*Environment.bytesPerWord]];
out.PutBlock[[p, 0, count*Environment.bytesPerWord]];
Spaces.FreeWords[p]};
MakeModule: PUBLIC PROC [
inputFile, moduleId, interfaceId: Strings.String, altocode: BOOL] = {
in, output: Stream.Handle;
count: CARDINAL;
[in, count] ← CreateSegmentStream[inputFile];
output ← CreateBCDStream[in, moduleId, interfaceId, altocode];
WriteSegment[in, output, count];
FinishBcdStream[];
Stream.Delete[in];
Stream.Delete[output]};
}.