-- file ModuleMaker.Mesa -- last edited by Satterthwaite, August 26, 1980 1:43 PM DIRECTORY AltoDefs: TYPE USING [BytesPerPage, BytesPerWord], BcdDefs: TYPE , MiscDefs: TYPE USING [GetNetworkNumber, Zero], OsStaticDefs: TYPE USING [OsStatics], PGScondefs: TYPE USING [WriteSymbols], SegmentDefs: TYPE USING [ FileSegmentHandle, FileHandle, OldFileOnly, Append, Read, Write, NewFile], StreamDefs: TYPE USING [ StreamHandle, StreamIndex, GetIndex, CreateWordStream, FileLength, NewWordStream, ReadBlock, SetIndex, WriteBlock], StringDefs: TYPE USING [AppendChar, AppendString, EquivalentString, WordsForString], SystemDefs: TYPE USING [ AllocateHeapNode, AllocateSegment, FreeHeapNode, FreeSegment, PagesForWords], TableCommand: TYPE USING [CreateTime, FindInterface, FindItem, MyBcdVersion], TimeDefs: TYPE USING [CurrentDayTime]; ModuleMaker: PROGRAM IMPORTS MiscDefs, PGScondefs, SegmentDefs, StreamDefs, StringDefs, SystemDefs, TableCommand, TimeDefs EXPORTS PGScondefs, TableCommand = BEGIN OPEN SegmentDefs; -- BCD construction bcdHeader: BcdDefs.BCD; module: BcdDefs.MTRecord; export: POINTER TO BcdDefs.EXPRecord; defsFile: BcdDefs.FTRecord; codeSeg, symbolSeg: BcdDefs.SGRecord; ssbString: STRING ← [60]; ssb: POINTER TO BcdDefs.PackedString ← LOOPHOLE[ssbString]; pgsVersion: PUBLIC BcdDefs.VersionStamp ← TableCommand.MyBcdVersion[]; sourceVersion: PUBLIC BcdDefs.VersionStamp ← [0, 0, 0]; objectVersion: PUBLIC BcdDefs.VersionStamp ← [ time: LOOPHOLE[TimeDefs.CurrentDayTime[]], net: MiscDefs.GetNetworkNumber[], host: OsStaticDefs.OsStatics.SerialNumber]; moduleIndex, segIndex: StreamDefs.StreamIndex; -- for fixup moduleId: STRING ← [40]; out: StreamDefs.StreamHandle; InitializePackedString: PROC = { ssb.string.length ← 1; ssb.size[1] ← 0; moduleId.length ← 0}; AddName: PROC [n: STRING] RETURNS [name: BcdDefs.NameRecord] = { StringDefs.AppendChar[@ssb.string, LOOPHOLE[n.length]]; name ← BcdDefs.NameRecord[ssb.string.length]; StringDefs.AppendString[@ssb.string, n]; RETURN}; FillInModule: PROC [ name: BcdDefs.NameRecord, segmentSize: CARDINAL, altoCode: BOOLEAN] = { OPEN BcdDefs; module ← MTRecord[ name: name, namedInstance: FALSE, initial: FALSE, file: FTSelf, links: frame, config: CTNull, code: [sgi: FIRST[SGIndex], linkspace: FALSE, packed: FALSE, offset: 0, length: 2*segmentSize], sseg: FIRST[SGIndex]+SIZE[SGRecord], framesize: 4, altoCode: altoCode, long: FALSE, tableCompiled: TRUE, packageable: TRUE, residentFrame: FALSE, crossJumped: FALSE, boundsChecks: FALSE, nilChecks: FALSE, acMap: SGNull, gfi: 1, variables: EVNull, ngfi: 1, frame: [length: 0, frag: ]]; codeSeg ← SGRecord[class: code, file: FTSelf, base: 2, pages: SystemDefs.PagesForWords[segmentSize], extraPages: 0]; symbolSeg ← SGRecord[class: symbols, file: FTNull, base: 0, pages: 0, extraPages: 0]}; FillInExport: PROC [name: BcdDefs.NameRecord, size, entry: CARDINAL] = { export ← SystemDefs.AllocateHeapNode[SIZE[BcdDefs.EXPRecord]+size]; MiscDefs.Zero[export, SIZE[BcdDefs.EXPRecord]+size]; export↑ ← BcdDefs.EXPRecord[name: name, size: size, port: interface, namedInstance: FALSE, typeExported: FALSE, file: FIRST[BcdDefs.FTIndex], links:]; export.links[entry] ← BcdDefs.Link[variable[vgfi:1, var:0, vtag:var]]}; FillInHeader: PROC = { OPEN bcdHeader; net: CARDINAL = MiscDefs.GetNetworkNumber[]; MiscDefs.Zero[@bcdHeader, SIZE[BcdDefs.BCD]]; -- clear all fields versionIdent ← BcdDefs.VersionID; version ← objectVersion; sourceVersion ← sourceVersion; creator ← pgsVersion; nPages ← 1; nConfigs ← 0; nModules ← 1; nImports ← 0; nExports ← IF export = NIL THEN 0 ELSE 1; definitions ← repackaged ← typeExported ← FALSE; tableCompiled ← TRUE; firstdummy ← 2; nDummies ← 0; ssOffset ← ctOffset ← impOffset ← ntOffset ← SIZE[BcdDefs.BCD]; ssLimit ← StringDefs.WordsForString[ssb.string.length]; mtOffset ← ssOffset + LOOPHOLE[ssLimit, CARDINAL]; mtLimit ← LOOPHOLE[SIZE[BcdDefs.MTRecord]]; sgOffset ← mtOffset + LOOPHOLE[mtLimit, CARDINAL]; sgLimit ← LOOPHOLE[2*SIZE[BcdDefs.SGRecord]]; IF export # NIL THEN { ftOffset ← sgOffset + LOOPHOLE[sgLimit, CARDINAL]; ftLimit ← LOOPHOLE[SIZE[BcdDefs.FTRecord]]; expOffset ← ftOffset + LOOPHOLE[ftLimit, CARDINAL]; expLimit ← LOOPHOLE[SIZE[BcdDefs.EXPRecord]+export.size]}; source ← BcdDefs.NullName}; WriteBcd: PROC [out: StreamDefs.StreamHandle] = { OPEN StreamDefs; [] ← WriteBlock[out, @bcdHeader, SIZE[BcdDefs.BCD]]; [] ← WriteBlock[out, ssb, StringDefs.WordsForString[ssb.string.length]]; moduleIndex ← StreamDefs.GetIndex[out]; [] ← WriteBlock[out, @module, SIZE[BcdDefs.MTRecord]]; segIndex ← StreamDefs.GetIndex[out]; [] ← WriteBlock[out, @codeSeg, SIZE[BcdDefs.SGRecord]]; [] ← WriteBlock[out, @symbolSeg, SIZE[BcdDefs.SGRecord]]; IF export # NIL THEN { [] ← WriteBlock[out, @defsFile, SIZE[BcdDefs.FTRecord]]; [] ← WriteBlock[out, export, SIZE[BcdDefs.EXPRecord]+export.size]; SystemDefs.FreeHeapNode[export]}}; CreateBCDStream: PUBLIC PROC [ in: StreamDefs.StreamHandle, modId, interfaceId: STRING, count: CARDINAL, altoCode: BOOLEAN ← TRUE] RETURNS [output: StreamDefs.StreamHandle] = { modRoot: STRING ← [40]; interfaceRoot: STRING ← [40]; symbolSeg: SegmentDefs.FileSegmentHandle; SetSourceVersion[in]; FOR i: CARDINAL IN [0..modId.length) DO IF modId[i] = '. THEN EXIT; StringDefs.AppendChar[modRoot, modId[i]]; ENDLOOP; out ← output ← StreamDefs.NewWordStream[modId, SegmentDefs.Write+SegmentDefs.Append]; InitializePackedString[]; StringDefs.AppendString[moduleId, modRoot]; FillInModule[AddName[modRoot], count, altoCode]; FOR i: CARDINAL IN [0..interfaceId.length) DO IF interfaceId[i] = '. THEN EXIT; StringDefs.AppendChar[interfaceRoot, interfaceId[i]]; ENDLOOP; -- fill in interface info IF StringDefs.EquivalentString[interfaceRoot, "SELF"L] THEN export ← NIL ELSE { dName: BcdDefs.NameRecord ← AddName[interfaceRoot]; size, entry: CARDINAL; [defsFile.version, symbolSeg] ← TableCommand.FindInterface[interfaceRoot]; defsFile.name ← dName; [size, entry] ← TableCommand.FindItem[symbolSeg, modRoot]; FillInExport[dName, size, entry]}; FillInHeader[]; -- Do this after all strings entered WriteBcd[out]; StreamDefs.SetIndex[out, [1, 0]]; RETURN}; -- input management CheckForBr: PROC [name: STRING] RETURNS [BOOLEAN] = { 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: BOOLEAN, file: SegmentDefs.FileHandle] RETURNS [count: CARDINAL, in: StreamDefs.StreamHandle] = { OPEN StreamDefs; in ← CreateWordStream[file, Read]; IF br THEN { SetIndex[in, [0, 7*AltoDefs.BytesPerWord]]; count ← in.get[in]; SetIndex[in, [0, count*AltoDefs.BytesPerWord]]; count ← in.get[in]} ELSE { eof: StreamIndex = StreamDefs.FileLength[in]; count ← (eof.page*AltoDefs.BytesPerPage + eof.byte)/AltoDefs.BytesPerWord; in.reset[in]}; RETURN}; CreateSegmentStream: PROC [segmentId: STRING] RETURNS [in: StreamDefs.StreamHandle, count: CARDINAL] = { OPEN SegmentDefs; brFile: BOOLEAN = CheckForBr[segmentId]; file: FileHandle = NewFile[segmentId, Read, OldFileOnly]; [count, in] ← FindSegmentSize[brFile, file]; RETURN}; FixupBcdHeader: PUBLIC PROC = { OPEN AltoDefs; endIndex: StreamDefs.StreamIndex ← StreamDefs.GetIndex[out]; nBytes: CARDINAL = (endIndex.page-1)*BytesPerPage + endIndex.byte; IF export # NIL THEN RETURN; module.code.length ← nBytes; codeSeg.pages ← SystemDefs.PagesForWords[(nBytes + (BytesPerWord-1))/BytesPerWord]; IF bcdHeader.nExports = 0 THEN { startIndex: StreamDefs.StreamIndex; symbolBytes: CARDINAL; UNTIL (startIndex ← StreamDefs.GetIndex[out]).byte = 0 DO out.put[out, 0] ENDLOOP; symbolSeg ← [ class: symbols, file: BcdDefs.FTSelf, base: codeSeg.base+codeSeg.pages, pages: , extraPages: 0]; PGScondefs.WriteSymbols[out, moduleId]; endIndex ← StreamDefs.GetIndex[out]; symbolBytes ← (endIndex.page-startIndex.page)*BytesPerPage + endIndex.byte; symbolSeg.pages ← SystemDefs.PagesForWords[(symbolBytes + (BytesPerWord-1))/BytesPerWord]}; StreamDefs.SetIndex[out, moduleIndex]; [] ← StreamDefs.WriteBlock[out, @module, SIZE[BcdDefs.MTRecord]]; StreamDefs.SetIndex[out, segIndex]; [] ← StreamDefs.WriteBlock[out, @codeSeg, SIZE[BcdDefs.SGRecord]]; [] ← StreamDefs.WriteBlock[out, @symbolSeg, SIZE[BcdDefs.SGRecord]]; StreamDefs.SetIndex[out, endIndex]}; SetSourceVersion: PROC [sh: StreamDefs.StreamHandle] = { sourceVersion ← [0, 0, TableCommand.CreateTime[sh]]}; -- overall control WriteSegment: PROC [in, out: StreamDefs.StreamHandle, count: CARDINAL] = { p: POINTER ← SystemDefs.AllocateSegment[count]; [] ← StreamDefs.ReadBlock[in, p, count]; IF StreamDefs.WriteBlock[out, p, count] # count THEN ERROR; SystemDefs.FreeSegment[p]}; MakeModule: PUBLIC PROC [ inputFile, moduleId, interfaceId: STRING, altocode: BOOLEAN] = { in, output: StreamDefs.StreamHandle; count: CARDINAL; [in, count] ← CreateSegmentStream[inputFile]; output ← CreateBCDStream[in, moduleId, interfaceId, count, altocode]; WriteSegment[in, output, count]; FixupBcdHeader[]; in.destroy[in]; output.destroy[output]}; END.