-- 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.