-- file PGSBcd.Mesa
-- last modified by Satterthwaite, August 26, 1980 1:21 PM
DIRECTORY
AltoDefs: TYPE USING [BytesPerPage, BytesPerWord],
BcdDefs: TYPE ,
MiscDefs: TYPE USING [GetNetworkNumber, Zero],
OsStaticDefs: TYPE USING [OsStatics],
PGScondefs: TYPE USING [
objectVersion, outeol, outstring, pgsVersion,
resetoutstream, seterrstream, sourceVersion, warningslogged,
WriteSymbols],
SegmentDefs: TYPE USING [FileSegmentHandle],
StreamDefs: TYPE USING [StreamHandle, StreamIndex, GetIndex, SetIndex, WriteBlock],
StringDefs: TYPE USING [AppendChar, AppendString, WordsForString],
SystemDefs: TYPE USING [AllocateHeapNode, FreeHeapNode, PagesForWords],
TableCommand: TYPE USING [FindInterface, FindItem, BadInterface],
TimeDefs: TYPE USING [CurrentDayTime];
PGSBcd: PROGRAM
IMPORTS
MiscDefs, PGScondefs, StreamDefs, StringDefs, SystemDefs,
TableCommand, TimeDefs
EXPORTS PGScondefs =
BEGIN
-- 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];
dName: BcdDefs.NameRecord;
out: StreamDefs.StreamHandle;
moduleIndex, segIndex: StreamDefs.StreamIndex; -- for fixup
InitializePackedString: PROC = {ssb.string.length ← 1; ssb.size[1] ← 0};
AddName: PROC [n: STRING] RETURNS [name: BcdDefs.NameRecord] = {
IF n = NIL
THEN name ← BcdDefs.NullName
ELSE {
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], acMap: SGNull, framesize: 4,
tableCompiled: TRUE, altoCode: altoCode, long: FALSE,
residentFrame: FALSE, crossJumped: FALSE, packageable: TRUE,
gfi: 1, variables: EVNull, ngfi: 1, frame: [length: 0, frag: ],
boundsChecks: FALSE, nilChecks: FALSE];
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]; -- clear all fields
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;
MiscDefs.Zero[@bcdHeader, SIZE[BcdDefs.BCD]]; -- clear all fields
versionIdent ← BcdDefs.VersionID;
version ← PGScondefs.objectVersion;
sourceVersion ← PGScondefs.sourceVersion;
creator ← PGScondefs.pgsVersion;
nPages ← 1;
nConfigs ← 0; nModules ← 1;
nImports ← 0; nExports ← IF export = NIL THEN 0 ELSE 1;
definitions ← repackaged ← typeExported ← FALSE; tableCompiled ← TRUE;
versions ← extended ← FALSE;
firstdummy ← 2; nDummies ← 0;
ctOffset ← impOffset ← ntOffset ← SIZE[BcdDefs.BCD];
ssOffset ← 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]}};
-- overall control
moduleId: STRING ← [40];
WriteBcdHeader: PUBLIC PROC [
outStream: StreamDefs.StreamHandle,
binaryId, interfaceId: STRING,
altoCode: BOOLEAN ← TRUE] = {
symbolSeg: SegmentDefs.FileSegmentHandle;
out ← outStream; moduleId.length ← 0;
FOR i: CARDINAL IN [0 .. binaryId.length)
DO
IF binaryId[i] = '. THEN EXIT;
StringDefs.AppendChar[moduleId, binaryId[i]];
ENDLOOP;
PGScondefs.objectVersion ← BcdDefs.VersionStamp[
time: LOOPHOLE[TimeDefs.CurrentDayTime[]],
net: MiscDefs.GetNetworkNumber[],
host: OsStaticDefs.OsStatics.SerialNumber];
InitializePackedString[];
dName ← AddName[interfaceId];
FillInModule[AddName[moduleId], 0, altoCode];
-- fill in interface info
IF interfaceId = NIL
THEN export ← NIL
ELSE {
size, entry: CARDINAL;
[defsFile.version, symbolSeg] ←
TableCommand.FindInterface[interfaceId
! TableCommand.BadInterface => {
OPEN PGScondefs;
seterrstream[]; outeol[1];
outstring[id]; outstring[" cannot be opened -- SELF used"L];
outeol[2]; resetoutstream[]; warningslogged ← TRUE;
GO TO fail}];
defsFile.name ← dName;
[size, entry] ← TableCommand.FindItem[symbolSeg, moduleId];
FillInExport[dName, size, entry];
EXITS
fail => export ← NIL};
FillInHeader[]; -- Do this after all strings entered
WriteBcd[out];
StreamDefs.SetIndex[out, [1, 0]]};
FixupBcdHeader: PUBLIC PROC = {
OPEN AltoDefs;
endIndex: StreamDefs.StreamIndex ← StreamDefs.GetIndex[out];
nBytes: CARDINAL = (endIndex.page-1)*BytesPerPage + endIndex.byte;
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]};
END.