-- 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]}; }.