DIRECTORY
AmpersandContext USING[MakeNodeFromNode],
CCTypes USING[CCError, CCErrorCase, CreateFrameNodeForSelf],
CedarCode USING[ExtractFieldFromNode, GetTypeOfNode, LoadThroughIndirectNode, SelectFieldFromNode, StoreThroughIndirectNode],
CirioNubAccess USING[FileEntry, GetConcreteTypecode, GetFileEntry, GetTypestring, Handle, LookupFileEntryByStemName, LookupMatchingSymEntryByName, LookupMatchingSymEntryByValue, LookupSymEntryByName, ReadBytes, Read32BitsAsCard, SymEntry, WriteCardAs32Bits],
CirioTypes USING[CirioAddress, CirioAddressBody, CompilerContext, Node, Type],
Convert USING[RopeFromCard],
IO USING[card, Error, PutChar, PutF, PutFR, PutRope, rope, STREAM],
NewAmpersandProcs USING[Handle],
PBasics USING[BITAND, BITLSHIFT, BITNOT, BITOR, BITRSHIFT],
PFS USING [RopeFromPath],
Rope,
SystemInterface USING[ShowReport];

NewAmpersandProcsImpl: CEDAR PROGRAM IMPORTS AmpersandContext, CCTypes, CedarCode, CirioNubAccess, Convert, IO, PBasics, PFS, Rope, SystemInterface EXPORTS NewAmpersandProcs =

BEGIN
CC: TYPE = CirioTypes.CompilerContext;
CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError;

Handle: TYPE = NewAmpersandProcs.Handle;

FriendlyFileEntry: TYPE ~ RECORD[
seqNum: CARD,
commitPoint: BOOL,
fileName: Rope.ROPE,
fOffset: CARD,
fmagic: CARD,
size: CARD,
mtime: CARD,
smagic: CARD,
stamp: Rope.ROPE,
readerData: CARD,
readerDataSize: CARD,
patchReloc: CARD,
patchSize: CARD,
textReloc: CARD,
textSize: CARD,
dataReloc: CARD,
dataSize: CARD,
bssReloc: CARD,
bssSize: CARD,
commonReloc: CARD,
commonSize: CARD];

InstallItems: PUBLIC PROC[ampersandContext: CirioTypes.Node, handle: Handle, cc: CC] =
BEGIN
indirectFrameForSelf: CirioTypes.Node _ CCTypes.CreateFrameNodeForSelf[cc];
indirectTypeForSelf: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirectFrameForSelf];
indirectArgs: CirioTypes.Node _ CedarCode.SelectFieldFromNode["&args", indirectTypeForSelf, indirectFrameForSelf, cc];
indirectTypeForArgs:  CirioTypes.Type _ CedarCode.GetTypeOfNode[indirectArgs];
indirectGlobalFrame: CirioTypes.Node _ CedarCode.ExtractFieldFromNode["&enclosingContext", indirectTypeForSelf, indirectFrameForSelf, cc];
indirectTypeForGlobalFrame: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirectGlobalFrame];
indirectGlobalVars: CirioTypes.Node _ CedarCode.SelectFieldFromNode["&globalVars", indirectTypeForGlobalFrame, indirectGlobalFrame, cc];
indirectTypeForGlobalVars: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirectGlobalVars];
globalVars: CirioTypes.Node _ CedarCode.LoadThroughIndirectNode[indirectTypeForGlobalVars, indirectGlobalVars, cc];
typeForGlobalvars: CirioTypes.Type _ CedarCode.GetTypeOfNode[globalVars];
ampersandContextType: CirioTypes.Type _ CedarCode.GetTypeOfNode[ampersandContext];

InstallAnArg: PROC[name: Rope.ROPE, argItemName: Rope.ROPE] =
BEGIN
indirect: CirioTypes.Node _ CedarCode.SelectFieldFromNode[argItemName, indirectTypeForArgs, indirectArgs, cc];
indirectType: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirect];
item: CirioTypes.Node _ CedarCode.LoadThroughIndirectNode[indirectType, indirect, cc];

FinishInstall[name, item];
END;

InstallAGlobal: PROC[name: Rope.ROPE, globalItemName: Rope.ROPE] =
BEGIN
<<indirect: CirioTypes.Node _ CedarCode.SelectFieldFromNode[globalItemName, indirectTypeForGlobalVars, indirectGlobalVars, cc];
indirectType: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirect];>>
item: CirioTypes.Node _ CedarCode.ExtractFieldFromNode[globalItemName, typeForGlobalvars, globalVars, cc];

FinishInstall[name, item];
END;


FinishInstall: PROC[name: Rope.ROPE, item: CirioTypes.Node] =
BEGIN
indirectAmpersandNode: CirioTypes.Node _ CedarCode.SelectFieldFromNode[name, ampersandContextType, ampersandContext, cc];
indirectAmpersandType: CirioTypes.Type _ CedarCode.GetTypeOfNode[indirectAmpersandNode];
encapsulatedItem: CirioTypes.Node _ AmpersandContext.MakeNodeFromNode[item, cc];
encapsulatedType: CirioTypes.Type _ CedarCode.GetTypeOfNode[encapsulatedItem];
CedarCode.StoreThroughIndirectNode[encapsulatedType, encapsulatedItem, indirectAmpersandType, indirectAmpersandNode, cc];
END;

InstallAnArg["&&H", "handle"];
InstallAGlobal["&TestProc", "TestProc"];
InstallAGlobal["&MemDump", "MemDump"];
InstallAGlobal["&IndirectMemDump", "IndirectMemDump"];
InstallAGlobal["&RdMem", "RdMem"];
InstallAGlobal["&IndirectRdMem", "IndirectRdMem"];
InstallAGlobal["&PokeCard", "PokeCard"];
InstallAGlobal["&dr", "DecimalRead"];
InstallAGlobal["&LookupFileEntryByStemName", "LookupFileEntryByStemName"];
InstallAGlobal["&LookupSymEntryByName", "LookupSymEntryByName"];
InstallAGlobal["&LookupMatchingSymEntryByName", "NubLookupMatchingSymEntryByName"];
InstallAGlobal["&LookupMatchingSymEntryByValue", "NubLookupMatchingSymEntryByValue"];
InstallAGlobal["&GetFileEntry", "GetFileEntry"];
InstallAGlobal["&RdPath", "RdPath"];
InstallAGlobal["&RdRope", "RdRope"];
InstallAGlobal["&RdXString", "RdXString"];
InstallAGlobal["&RdXStringBody", "RdXStringBody"];
InstallAGlobal["&RdRopeDB", "RdRopeDB"];
InstallAGlobal["&MakeLocalRope5", "MakeLocalRope5"];
InstallAGlobal["&MakeLocalRope10", "MakeLocalRope10"];
InstallAGlobal["&LocalRopeConcat", "LocalRopeConcat"];
InstallAGlobal["&LocalRopeCat", "LocalRopeCat"];
InstallAGlobal["&LocalRopeSubstr", "LocalRopeSubstr"];
InstallAGlobal["&GetTypestring", "GetTypestring"];
InstallAGlobal["&GetConcreteTypecode", "GetConcreteTypecode"];
END;

TestProc: PROC =
BEGIN
handle: Handle _ GetHandle[];
IO.PutF[handle.out, "hi, ampersand procs here\N"];
END;

Double: PROC [a: Rope.ROPE] RETURNS [Rope.ROPE]
~ {RETURN a.Concat[a]};

AnaRope: PROC [a: Rope.ROPE] RETURNS [len: INT, c0: CHAR] ~ {
len _ a.Length[];
c0 _ IF len>0 THEN a.Fetch[0] ELSE '?;
RETURN};

rgv1: Rope.ROPE _ "rgv1";
rgv2: Rope.ROPE _ "rgv2!";

BytesPerWord: CARD = 4;
DecimalRead: PROC[addr: CARD, count: CARD _ 4] =
BEGIN
handle: Handle _ GetHandle[];
byteAddr: CARD _ (addr/BytesPerWord)*BytesPerWord;
IO.PutF[handle.out, "%g:", IO.card[addr]];
FOR I: CARD IN [0..count) DO
word: CARD _ CirioNubAccess.Read32BitsAsCard[[handle.nub, byteAddr, 0, FALSE, TRUE]];
IO.PutF[handle.out, " %g", IO.card[word]];
byteAddr _ byteAddr + BytesPerWord;
ENDLOOP;
END;

hexChars: ARRAY [0 .. 15] OF CHAR = ['0, '1, '2, '3, '4, '5, '6, '7, '8, '9, 'A, 'B, 'C, 'D, 'E, 'F];

RdMem: PROC [addr: CARD, bytes: INTEGER _ 16, base: CARD _ 16]
~ {FullMemDump[addr, bytes, FALSE, base]};

IndirectRdMem: PROC [addr: CARD, bytes: INTEGER _ 16, base: CARD _ 16]
~ {FullMemDump[addr, bytes, TRUE, base]};

MemDump: PROC [addr: CARD, bytes: INTEGER _ 16]
~ {FullMemDump[addr, bytes, FALSE, 16]};

IndirectMemDump: PROC [addr: CARD, bytes: INTEGER _ 16]
~ {FullMemDump[addr, bytes, TRUE, 16]};

FullMemDump: PROC [addr: CARD, bytes: INTEGER, indirect: BOOL, base: CARD] ~ {
addr _ (addr/BytesPerWord)*BytesPerWord;
{len: CARD ~ CARD[bytes];
afterLast: CARD ~ addr + len;
handle: Handle _ GetHandle[];
IF (addr <= CARD[INT.LAST]) # (afterLast <= CARD[INT.LAST]) THEN {
IO.PutF[handle.out, "Can't dump across address sign change (%08x + %08x).\n", [cardinal[addr]], [cardinal[len]] ];
RETURN};
IF indirect THEN {ur: CARD ~ addr;
addr _ CirioNubAccess.Read32BitsAsCard[[handle.nub, addr, 0, FALSE, TRUE]];
IF (addr MOD BytesPerWord) # 0 THEN {
IO.PutF[handle.out, "%08x contains a non-word-aligned pointer (%08x).\n", [cardinal[ur]], [cardinal[addr]] ];
RETURN};
};
IO.PutF[handle.out, "%l", [rope["f"]]];
{ENABLE UNWIND => IO.PutF[handle.out, "%l(dump aborted)\n", [rope["F"]] !IO.Error => CONTINUE];
WHILE bytes>0 DO
bytes _ bytes + 3;
bytes _ bytes - (bytes MOD 4);
SELECT base FROM
8 => IO.PutF[handle.out, "%08x:", [cardinal[addr]]];
10 =>IO.PutF[handle.out, "%08x:", [cardinal[addr]]];
16 =>IO.PutF[handle.out, "%08x:", [cardinal[addr]]];
ENDCASE => {
IO.PutF[handle.out, "%g is not a valid base.  Try 8, 10, or 16.\n", [cardinal[base]]];
RETURN};
{nAsk: NAT ~ MIN[16, bytes];
lb: REF TEXT ~ CirioNubAccess.ReadBytes[[handle.nub, LOOPHOLE[addr], 0, FALSE, TRUE], nAsk];
IF lb.length # nAsk THEN {
IO.PutF[handle.out, "%lReadBytes[%08x, %g] returned %g bytes.\n", [rope["F"]], [cardinal[addr]], [integer[nAsk]], [integer[lb.length]] ];
RETURN};
{
didVal: BOOLEAN _ FALSE;
tmpVal: CARD _ 0;
FOR i: NAT IN [0 .. 16] DO
IF (i MOD 4)=0 THEN {
IF didVal THEN
SELECT base FROM
8 => handle.out.PutF["%011bB", [cardinal[tmpVal]]];
10 => handle.out.PutF["%010dD", [cardinal[tmpVal]]];
16 => handle.out.PutF["%08xH", [cardinal[tmpVal]]];
ENDCASE => ERROR
ELSE IF i # 0 THEN
SELECT base FROM
8 => handle.out.PutF["            "];
10 => handle.out.PutF["           "];
16 => handle.out.PutF["         "];
ENDCASE => ERROR;
tmpVal _ 0;
didVal _ FALSE;
handle.out.PutChar[' ];
};
IF i<bytes AND i # 16 THEN {
b: BYTE ~ lb[i].ORD;
tmpVal _ tmpVal * 16 * 16 + VAL[b];
didVal _ TRUE;
}
ELSE IF i # 16  AND didVal THEN
tmpVal _ tmpVal * 16 * 16;
ENDLOOP;
};
handle.out.PutRope[" - "];
FOR i: NAT IN [0 .. 15] DO
IF (i MOD 8)=0 THEN handle.out.PutChar[' ];
IF i>=bytes THEN handle.out.PutRope[" "]
ELSE SELECT lb[i] FROM
<' , >'~ => handle.out.PutChar['.];
ENDCASE => handle.out.PutChar[lb[i]];
ENDLOOP;
handle.out.PutRope["\n"];
addr _ addr + 16;
bytes _ bytes - 16;
}ENDLOOP;
};
IO.PutF[handle.out, "%l", [rope["F"]]]}};

PokeCard: PROC [addr, val: CARD, mask: CARD _ 0FFFFFFFFH] ~ {
handle: Handle _ GetHandle[];
addr _ (addr/BytesPerWord)*BytesPerWord;
{old: CARD ~ CirioNubAccess.Read32BitsAsCard[[handle.nub, addr, 0, FALSE, TRUE]];
maskBar: CARD ~ PBasics.BITNOT[mask];
rem: CARD ~ PBasics.BITAND[old, maskBar];
delt: CARD ~ PBasics.BITAND[val, mask];
new: CARD ~ PBasics.BITOR[rem, delt];
CirioNubAccess.WriteCardAs32Bits[[handle.nub, addr, 0, FALSE, TRUE], new];
RETURN}};

GetTypestring: PROC [code: CARD] RETURNS [string, whyNot: Rope.ROPE] ~ {
handle: Handle _ GetHandle[];
[string, whyNot] _ CirioNubAccess.GetTypestring[handle.nub, [code]];
RETURN};

GetConcreteTypecode: PROC [opaque: CARD] RETURNS [concrete: CARD, whyNot: Rope.ROPE] ~ {
handle: Handle _ GetHandle[];
[[concrete], whyNot] _ CirioNubAccess.GetConcreteTypecode[handle.nub, [opaque]];
RETURN};

LookupFileEntryByStemName: PROC [stemName: Rope.ROPE, numToSkip: INT] RETURNS [name: Rope.ROPE, type, value, size, fileSeqNum: CARD] ~ {
handle: Handle _ GetHandle[];
se: CirioNubAccess.SymEntry _ CirioNubAccess.LookupFileEntryByStemName[handle.nub, stemName, numToSkip];
IF se=NIL THEN RETURN [NIL, 0, 0, 0, 0];
RETURN [se.name, se.type, se.value, se.size, se.fileSeqNum]};

LookupSymEntryByName: PROC [sym: Rope.ROPE, caseSensitive: BOOLEAN, externOnly: BOOLEAN, numToSkip: INT] RETURNS [name: Rope.ROPE, type, value, size, fileSeqNum: CARD] ~ {
handle: Handle _ GetHandle[];
se: CirioNubAccess.SymEntry _ CirioNubAccess.LookupSymEntryByName[handle.nub, sym, caseSensitive, externOnly, numToSkip];
IF se=NIL THEN RETURN [NIL, 0, 0, 0, 0];
RETURN [se.name, se.type, se.value, se.size, se.fileSeqNum]};

NubLookupMatchingSymEntryByName: PROC[symID: CARD, pattern: Rope.ROPE, caseSensitive: BOOLEAN, wantedTypes: CARD, ignoreClasses: CARD, numToSkip: INT] RETURNS[CirioNubAccess.SymEntry] =
BEGIN
handle: Handle _ GetHandle[];
RETURN[CirioNubAccess.LookupMatchingSymEntryByName[handle.nub, symID, pattern, caseSensitive, wantedTypes, ignoreClasses, numToSkip]];
END;

NubLookupMatchingSymEntryByValue: PROC[symID: CARD, val: CARD, wantedTypes: CARD, ignoreClasses: CARD, numToSkip: INT] RETURNS[CirioNubAccess.SymEntry] =
BEGIN
handle: Handle _ GetHandle[];
RETURN[CirioNubAccess.LookupMatchingSymEntryByValue[handle.nub, symID, val, wantedTypes, ignoreClasses, numToSkip]];
END;

GetFileEntry: PROC [seqNum: CARD] RETURNS [ffe: REF FriendlyFileEntry _ NIL] ~ {
handle: Handle _ GetHandle[];
fe: CirioNubAccess.FileEntry ~ CirioNubAccess.GetFileEntry[handle.nub, seqNum];
IF fe#NIL THEN ffe _ NEW [FriendlyFileEntry _ [
seqNum: fe.seqNum,
commitPoint: fe.commitPoint,
fileName: PFS.RopeFromPath[fe.fileName],
fOffset: fe.fOffset,
fmagic: fe.fmagic,
size: fe.size,
mtime: fe.mtime,
smagic: fe.smagic,
stamp: fe.stamp,
readerData: fe.readerData,
readerDataSize: fe.readerDataSize,
patchReloc: fe.patchReloc,
patchSize: fe.patchSize,
textReloc: fe.textReloc,
textSize: fe.textSize,
dataReloc: fe.dataReloc,
dataSize: fe.dataSize,
bssReloc: fe.bssReloc,
bssSize: fe.bssSize,
commonReloc: fe.commonReloc,
commonSize: fe.commonSize]];
RETURN};


RdXString: PROC[a: CARD, nChars: CARD _ 100] =
BEGIN
handle: Handle _ GetHandle[];
xStringVarAddr: CirioTypes.CirioAddress _ CreateLCAFromCard[a, handle.nub];
xStringBodyVarAddr: CirioTypes.CirioAddress _ xStringVarAddr.followPointer[0, xStringVarAddr];
IF xStringBodyVarAddr.asCard[xStringBodyVarAddr] = 0 THEN
SystemInterface.ShowReport["XString is NIL, maybe this is an XStringBody.", $urgent];
RdXStringBody[xStringBodyVarAddr.asCard[xStringBodyVarAddr], nChars];
END;

RdXStringBody: PROC[a: CARD, nChars: CARD _ 100] =
BEGIN
handle: Handle _ GetHandle[];
xStringBodyVarAddr: CirioTypes.CirioAddress _ CreateLCAFromCard[a, handle.nub];
rope: Rope.ROPE _ "  ";
SeeOneChar: PROC[c: CHAR] =
{rope _ Rope.Cat[rope, Rope.FromChar[c]]};
GenCharsForXString[xStringBodyVarAddr, 0, nChars, FALSE, SeeOneChar];
SystemInterface.ShowReport[rope, $urgent];
END;

GenCharsForXString: PROC[a: CirioTypes.CirioAddress, first: CARD, nChars: CARD, debug: BOOLEAN, for: PROC[CHAR]] =
BEGIN
suffixSizeF: Field = [0, 16];
homogeneousF: Field = [16, 8];
prefixF: Field = [24, 8];
limitF: Field = [32, 32];
offsetF: Field = [64, 32];
charsF: Field = [96, 32];
siffixSize: CARD _ a.readBits[0, suffixSizeF.offset, suffixSizeF.size, a];
homogeneous: CARD _ a.readBits[0, homogeneousF.offset, homogeneousF.size, a];
prefix: CARD _ a.readBits[0, prefixF.offset, prefixF.size, a];
limit: CARD _ a.readBits[0, limitF.offset, limitF.size, a];
offset: CARD _ a.readBits[0, offsetF.offset, offsetF.size, a];
chars: CARD _ a.readBits[0, charsF.offset, charsF.size, a];
length: CARD _ limit - offset;

handle: Handle _ GetHandle[];
b: CirioTypes.CirioAddress _ CreateLCAFromCard[chars + offset, handle.nub];
n: CARD _ IF first >= length THEN 0 ELSE MIN[length-first, nChars];
ShowClient: PROC[c: CHAR] RETURNS[quit: BOOL] =
{for[c]; RETURN[FALSE]};

FOR I: CARD IN [0..n) DO
byte: CARD _ b.readBits[first + I, 0, 8, b];
for[VAL[BYTE[byte]]];
ENDLOOP;
END;

RdPath: PROC[a: CARD] =
BEGIN
handle: Handle _ GetHandle[];
pathVarAddr: CirioTypes.CirioAddress _ CreateLCAFromCard[a, handle.nub];
pathObjAddr: CirioTypes.CirioAddress _ pathVarAddr.followPointer[0, pathVarAddr];
privPathObjAddr: CirioTypes.CirioAddress _ pathObjAddr.followPointer[0, pathObjAddr];
RdRopeMain[privPathObjAddr.asCard[privPathObjAddr] + 4, 500, FALSE];
END;

RdRopeMain: PROC[a: CARD, nChars: CARD _ 100, debug: BOOLEAN _ FALSE] =
BEGIN
handle: Handle _ GetHandle[];
ropeVarAddr: CirioTypes.CirioAddress _ CreateLCAFromCard[a, handle.nub];
rope: Rope.ROPE _ "  ";
SeeOneChar: PROC[c: CHAR] =
{rope _ Rope.Cat[rope, Rope.FromChar[c]]};
GenCharsForRope[ropeVarAddr.followPointer[0, ropeVarAddr], 0, nChars, debug, SeeOneChar];
SystemInterface.ShowReport[rope, $urgent];
END;

RdRope: PROC[a: CARD, nChars: CARD _ 100] = { RdRopeMain[a, nChars]; };

RdRopeDB: PROC[a: CARD, nChars: CARD _ 100] = { RdRopeMain[a, nChars, TRUE]; };

MakeLocalRope5: PROC [c1, c2, c3, c4, c5: CHAR _ ' ] RETURNS [Rope.ROPE] ~ {
a: ARRAY [1..5] OF CHAR ~ [c1, c2, c3, c4, c5];
i: INT _ 0;
GetChar: PROC RETURNS [CHAR] ~ {RETURN [a[i _ i.SUCC]]};
r: Rope.ROPE _ Rope.FromProc[5, GetChar];
RETURN r.Substr[len: r.Index[s2: " "]]};

MakeLocalRope10: PROC [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10: CHAR _ ' ] RETURNS [Rope.ROPE] ~ {
a: ARRAY [1..10] OF CHAR ~ [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10];
i: INT _ 0;
GetChar: PROC RETURNS [CHAR] ~ {RETURN [a[i _ i.SUCC]]};
r: Rope.ROPE _ Rope.FromProc[10, GetChar];
RETURN r.Substr[len: r.Index[s2: " "]]};

LocalRopeConcat: PROC [base, rest: Rope.ROPE] RETURNS [Rope.ROPE]
~ {RETURN Rope.Concat[base, rest]};

LocalRopeCat: PROC [r1, r2, r3, r4, r5: Rope.ROPE _ NIL] RETURNS [Rope.ROPE]
~ {RETURN Rope.Cat[r1, r2, r3, r4, r5]};

LocalRopeSubstr: PROC [base: Rope.ROPE, start: INT _ 0, len: INT _ INT.LAST] RETURNS [Rope.ROPE]
~ {RETURN Rope.Substr[base, start, len]};


GetHandle: PUBLIC SIGNAL RETURNS[Handle] = CODE;


Field: TYPE = RECORD[offset: INT, size: CARD];


GenCharsForRope: PROC[a: CirioTypes.CirioAddress, first: CARD, nChars: CARD, debug: BOOLEAN, for: PROC[CHAR]] =
BEGIN
tagF: Field = [0, 1];
tag: CARD _ a.readBits[tagF.offset, 0, tagF.size, a];
ShowClient: PROC[c: CHAR] RETURNS[quit: BOOL] =
{for[c]; RETURN[FALSE]};

IF debug THEN SystemInterface.ShowReport[IO.PutFR["tag = %g",  IO.rope[Convert.RopeFromCard[tag, 16]]], $debug];
SELECT tag FROM
0 => -- we are looking at a text
BEGIN
lengthF: Field = [1, 15];
maxF: Field = [16, 16];
length: CARD _ a.readBits[0, lengthF.offset, lengthF.size, a];
max: CARD _ a.readBits[0, maxF.offset, maxF.size, a];
n: CARD _ IF first >= length THEN 0 ELSE MIN[length-first, nChars];

FOR I: CARD IN [0..n) DO
byte: CARD _ a.readBits[4+first+I, 0, 8, a];
for[VAL[BYTE[byte]]];
ENDLOOP;
END;
1 => -- we are looking at a node
BEGIN
sizeF: Field = [1, 31];
depthF: Field = [32, 30];
casesF: Field = [62, 2];
size: CARD _ a.readBits[0, sizeF.offset, sizeF.size, a];
depth: CARD _ a.readBits[0, depthF.offset, depthF.size, a];
cases: CARD _ a.readBits[0, casesF.offset, casesF.size, a];
n: CARD _ IF first >= size THEN 0 ELSE MIN[size-first, nChars];
IF n > 0 THEN
SELECT cases FROM
0 =>  -- substr
BEGIN
baseF: Field = [64, 32];
startF: Field = [96, 32];
base: CirioTypes.CirioAddress _ a.followPointer[baseF.offset/8, a];
start: CARD _ a.readBits[0, startF.offset, startF.size, a];
IF debug THEN [] _ Rope.Map[base: "??substr??", action: ShowClient];
GenCharsForRope[base, start, n, debug, for];
END;
1 =>  -- concat
BEGIN
baseF: Field = [64, 32];
restF: Field = [96, 32];
posF: Field = [128, 32];
base: CirioTypes.CirioAddress _ a.followPointer[baseF.offset/8, a];
rest: CirioTypes.CirioAddress _ a.followPointer[restF.offset/8, a];
pos: CARD _ a.readBits[0, posF.offset, posF.size, a];
IF debug THEN [] _ Rope.Map[base: "??concat??", action: ShowClient];
IF first < pos THEN
BEGIN
GenCharsForRope[base, first, MIN[pos-first, n], debug, for];
IF n > pos-first THEN GenCharsForRope[rest, 0, n-pos+first, debug, for];
END
 ELSE
GenCharsForRope[rest, first-pos, n, debug, for];
END;
2 => 
BEGIN
baseF: Field = [64, 32];
replaceF: Field = [96, 32];
startF: Field = [128, 32];
oldPosF: Field = [160, 32];
newPosF: Field = [192, 32];
base: CirioTypes.CirioAddress _ a.followPointer[baseF.offset/8, a];
replace: CirioTypes.CirioAddress _ a.followPointer[replaceF.offset/8, a];
start: CARD _  a.readBits[0, startF.offset, startF.size, a];
oldPos: CARD _  a.readBits[0, oldPosF.offset, oldPosF.size, a];
newPos: CARD _  a.readBits[0, newPosF.offset, newPosF.size, a];
IF debug THEN [] _ Rope.Map[base: "??replace??", action: ShowClient];

IF n > 0 AND first < start THEN
BEGIN
GenCharsForRope[base, first, MIN[n, start-first], debug, for];
first _ start;
n _ n-MIN[n, start-first];
END;

IF n > 0 AND first < newPos THEN
BEGIN
GenCharsForRope[replace, first-start, MIN[n, newPos-first], debug, for];
first _ newPos;
n _ n - MIN[n, newPos-first];
END;

IF n > 0 AND first < size THEN
GenCharsForRope[base, first-newPos+oldPos, n, debug, for];

END;
3 => [] _ Rope.Map[base: "??ObjectRope??", action: ShowClient];
ENDCASE => CCE[cirioError];
END;
ENDCASE => CCE[cirioError];
END;




CreateLCAFromCard: PROC[addr: CARD, nub: CirioNubAccess.Handle] RETURNS[CirioTypes.CirioAddress] =
BEGIN
RETURN[NEW[CirioTypes.CirioAddressBody_[
readBits: LCAReadBits,
writeBits: LCAWriteBits,
followPointer: LCAFollowPointer,
asCard: LCAAsCard,
data: NEW[LCADataBody _ [nub, addr]]]]];
END;


LCAData: TYPE = REF LCADataBody;
LCADataBody: TYPE = RECORD[
nub: CirioNubAccess.Handle,
byteAddr: CARD];

LCAReadBits: PROC[byteOffset: INT _ 0, bitOffset: INT _ 0, bitSize: CARD, data: CirioTypes.CirioAddress] RETURNS[CARD] =
BEGIN
lcaData: LCAData _ NARROW[data.data];
fullByteOffset: INT _ byteOffset + bitOffset/8;
fullByteAddr: INT _ lcaData.byteAddr+fullByteOffset;
cardByteAddr: CARD _ (fullByteAddr/4)*4;
remainingBitOffset: INT _ (fullByteAddr MOD 4)*8 + (bitOffset MOD 8);
cardVal: CARD _ CirioNubAccess.Read32BitsAsCard[[lcaData.nub, cardByteAddr, 0, FALSE, TRUE]];
RETURN[PBasics.BITRSHIFT[PBasics.BITLSHIFT[cardVal, remainingBitOffset],
32-bitSize]];
END;

LCAWriteBits: PROC[byteOffset: INT _ 0, bitOffset: INT _ 0, bitSize: CARD, data: CirioTypes.CirioAddress, bits: CARD] =
BEGIN
ERROR
END;

LCAFollowPointer: PROC[byteOffset: INT _ 0, data: CirioTypes.CirioAddress] RETURNS[CirioTypes.CirioAddress] =
BEGIN
lcaData: LCAData _ NARROW[data.data];
pointer: CARD _ data.readBits[byteOffset, 0, 32, data];
RETURN[CreateLCAFromCard[pointer, lcaData.nub]];
END;

LCAAsCard: PROC[data: CirioTypes.CirioAddress] RETURNS[CARD] =
BEGIN
lcaData: LCAData _ NARROW[data.data];
RETURN[lcaData.byteAddr];
END;

END..
���”��
NewAmpersandProcsImpl.mesa
Copyright Ó 1990, 1991, 1992 by Xerox Corporation.  All rights reserved.
Sturgis, April 3, 1990 11:17 am PDT
Spreitze, May 31, 1990 8:55 am PDT
Last tweaked by Mike Spreitzer on December 23, 1991 10:19 am PST
Laurie Horton, January 28, 1992 2:51 pm PST
Philip James, March 6, 1992 11:21 am PST
FOR i: NAT IN [0 .. 15] DO
IF (i MOD 4)=0 THEN handle.out.PutChar[' ];
IF i>=bytes THEN handle.out.PutRope["  "] ELSE {
b: BYTE ~ lb[i].ORD;
h: CARDINAL ~ b/16;
l: CARDINAL ~ b MOD 16;
handle.out.PutChar[hexChars[h]];
handle.out.PutChar[hexChars[l]]};
ENDLOOP;
The original version of this procedure took "a: CirioTypes.CirioAddress", which works in the Dorado world, but fails with an internal Cirio error in the Sun world.  I should investigate.
"a" is intended to be the numerical byte address of a variable of type Rope.ROPE.
ropeBodyAddr: CirioTypes.CirioAddress _ a.followPointer[0, a];
ropeBodyContents: CARD _ ropeBodyAddr.readBits[0, 0, 32, ropeBodyAddr];
support
The field declarations in the following procedures must agree with Rope.RopeRep in the PCedar world (see [PCedar2.0]<Rope>Rope.mesa)
This procedure assumes that a is the address of a rope body.
Local CirioAddress impl (for RdRope, since we can't at the moment define RdRope to take a CirioAddress as an argument, for unknown reasons)
only works for fields that do not cross word boundaries
adapted from RMTWFrames.UBFReadBits
�Êu��•NewlineDelimiter
™�codešœ™K™HKšœ#™#K™"K™@K™+K™(—K˜�šÏk	˜	Kšœœ˜)Kšœœ/˜<Kšœ
œn˜}Kšœœî˜‚Kšœœ>˜NKšœœ˜Kšœœ3œ˜CKšœœ	˜ Kš
œœœ	œœœ	œ˜;Kšœœ˜Kšœ˜Kšœœ
˜"K˜�—KšÏnœœœœ@œœœ˜¯˜�Kš˜Kšœœ˜&Kšœœ&œœ˜NK˜�Kšœœ˜(K˜�šœœœ˜!Kšœœ˜
Kšœ
œ˜Kšœœ˜Kšœ	œ˜Kšœœ˜
Kšœœ˜Kšœœ˜Kšœœ˜
Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ
œ˜Kšœœ˜Kšœ
œ˜Kšœ
œ˜Kšœ	œ˜Kšœ
œ˜Kšœœ˜—K˜�šžœœœ8œ˜VKš˜KšœK˜KKšœU˜UKšœv˜vKšœN˜NKšœŠ˜ŠKšœ[˜[Kšœˆ˜ˆKšœY˜YKšœs˜sKšœI˜IKšœR˜RK˜�šžœœœœ˜=Kš˜Kšœn˜nKšœB˜BKšœV˜VK˜�Kšœ˜Kšœ˜—K˜�šžœœœœ˜BKš˜Kšœ˜KšœD˜DKšœj˜jK˜�Kšœ˜Kšœ˜—K˜�K˜�šž
œœœ˜=Kš˜Kšœy˜yKšœX˜XK˜PK˜NKšœy˜yKšœ˜—K˜�K˜Kšœ(˜(Kšœ&˜&Kšœ6˜6Kšœ"˜"Kšœ2˜2Kšœ(˜(Kšœ%˜%KšœJ˜JKšœ@˜@KšœS˜SKšœU˜UKšœ0˜0Kšœ$˜$Kšœ$˜$Kšœ*˜*Kšœ2˜2Kšœ(˜(Kšœ4˜4Kšœ6˜6Kšœ6˜6Kšœ0˜0Kšœ6˜6Kšœ2˜2Kšœ>˜>Kšœ˜—K˜�šžœœ˜Kš˜Kšœ˜Kšœ0˜2Kšœ˜—K˜�š
žœœ
œœœ˜/Kšœœ˜—K˜�šžœœ
œœœœ˜=K˜Kšœœœœ˜&Kšœ˜—K˜�Kšœœ
˜Kšœœ˜K˜�Kšžœœ˜šžœœœ	œ˜0Kš˜Kšœ˜Kšœ
œ$˜2Kšœœ
˜*š	œžœœœ˜Kšœœ=œœ˜UKšœœ
˜*Kšœ#˜#Kšœ˜—Kšœ˜—K˜�Kšœ
œœœD˜eK˜�š
žœœœ	œ
œ˜>Kšœœ	˜*K˜�—š
ž
œœœ	œ
œ˜FKšœœ	˜)K˜�—šžœœœ	œ˜/Kšœœ˜(—K˜�šžœœœ	œ˜7Kšœœ˜'—K˜�šžœœœ	œœœ˜NKšœ(˜(Kšœœœ˜Kšœœ˜Kšœ˜šœ
œœœœœœœ˜BKšœp˜rKšœ˜—šœ
œœ˜"Kšœ=œœ˜Kšœœœ˜%Kšœk˜mKšœ˜—K˜—Kšœ%˜'Kšœœœœ5œ
œ˜_šœ	˜K˜K˜šœ˜Kšœœ-˜4Kšœœ-˜4Kšœœ-˜4šœ˜KšœT˜VKšœ˜——Kšœœœ˜Kšœœœ)œœœ	˜\šœœ˜Kšœ‡˜‰Kšœ˜—Kšœ˜Kšœœœ˜Kšœœ˜šœœœ˜šœœœ˜šœ˜šœ˜K˜3K˜4K˜3Kšœ˜——šœœ˜šœ˜K˜%K˜%K˜#Kšœœ˜——K˜Kšœ	œ˜Kšœ˜K˜—šœ	œœ˜Kšœœ	œ˜Kšœœ˜#Kšœ	œ˜K˜—šœœ	œ˜Kšœ˜—Kšœ˜K˜—šœœœ™Kšœœœ™+šœ
œœ™0Kšœœ	œ™Kšœœ™Kšœœœ™K™ K™!—Kšœ™—K˜šœœœ˜Kšœœœ˜+Kšœ
œ˜(šœœ˜K˜#Kšœ˜%—Kšœ˜—K˜K˜K˜Kšœœ˜	—Kšœ˜Kšœ'˜)—K˜�šžœœ
œœ˜=Kšœ˜Kšœ(˜(Kšœœ9œœ˜QKšœ	œœ˜%Kšœœœ˜)Kšœœœ˜'Kšœœœ˜%Kšœ7œœ˜JKšœ˜	—K˜�š
ž
œœœœœ˜HKšœ˜KšœD˜DKšœ˜K˜�—šžœœ
œœœœ˜XKšœ˜KšœP˜PKšœ˜K˜�—šžœœœ
œœ
œ!œ˜ˆKšœ˜Kšœh˜hKš
œœœœœ˜(Kšœ7˜=—K˜�šžœœœœœ
œœ
œ!œ˜«Kšœ˜Kšœy˜yKš
œœœœœ˜(Kšœ7˜=—K˜�šžœœœœœœœ
œœ˜¹Kš˜Kšœ˜Kšœ€˜†Kšœ˜—K˜�šž œœœœœœ
œœ˜™Kš˜Kšœ˜Kšœn˜tKšœ˜—K˜�šžœœ
œœœœ˜PKšœ˜KšœO˜Ošœœœœ˜/Kšœ˜Kšœ˜Kšœ
œ˜(Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ"˜"Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜K˜�Kšœº™ºK™Q—K˜�šž	œœœ
œ	˜.Kš˜Kšœ˜KšœK˜KKšœ^˜^šœ3˜9K˜U—KšœE˜EKšœ˜K˜�—šž
œœœ
œ	˜2Kš˜Kšœ˜KšœO˜OKšœœœ˜šž
œœœ˜K˜*—Kšœ2œ˜EK˜*Kšœ˜K˜�—šžœœ$œ
œ	œœœ˜rKš˜K˜K˜K˜K˜K˜K˜Kšœœ:˜JKšœ
œ<˜MKšœœ2˜>Kšœœ0˜;Kšœœ2˜>Kšœœ0˜;Kšœœ˜K˜�K˜K˜KKšœœœœœœ˜Cš
ž
œœœœœ˜/Kšœ	œœ˜—K˜�š	œžœœœ˜Kšœœ"˜,Kšœœœ	˜Kšœ˜—Kšœ˜K˜�—šžœœœ˜Kš˜Kšœ˜KšœH˜HKšœQ˜QKšœU˜UKšœ=œ˜DKšœ˜K˜�—šž
œœœ
œœœ˜GKš˜Kšœ>™>Kšœœ1™GKšœ˜KšœH˜HKšœœœ˜šž
œœœ˜K˜*—KšœY˜YK˜*Kšœ˜K˜�—šžœœœ
œ%˜GK˜�—š
žœœœ
œ"œ˜OK˜�—š
žœœœœœ˜LKšœœœœ˜/Kšœœ˜Kšžœœœœœ
œ˜8Kšœœ˜)Kšœ"˜(—K˜�š
žœœ+œœœ˜bKšœœ	œœ-˜EKšœœ˜Kšžœœœœœ
œ˜8Kšœœ˜*Kšœ"˜(—K˜�š
žœœœœœ˜AKšœœ˜#—K˜�šžœœœœœœ˜LKšœœ˜(—K˜�šžœœ
œ	œœœœœœ˜`Kšœœ ˜)—K˜�Kšœ™K˜�Kš
ž	œœœœœ˜0K˜�K˜�Kš	œœœ	œœ˜.˜�Kšœ„™„—˜�Kšœ<™<—šžœœ$œ
œ	œœœ˜oKš˜K˜Kšœœ,˜5š
ž
œœœœœ˜/Kšœ	œœ˜K˜�—Kšœœœœ/˜pšœ˜šœÏc˜ Kš˜K˜K˜Kšœœ2˜>Kšœœ,˜5Kšœœœœœœ˜CK˜�š	œžœœœ˜Kšœœ"˜,Kšœœœ	˜Kšœ˜—Kšœ˜—šœŸ˜ Kš˜K˜K˜K˜Kšœœ.˜8Kšœœ0˜;Kšœœ0˜;Kšœœœœœœ˜?šœ˜
šœ˜šœŸ	˜Kš˜Kšœ˜Kšœ˜KšœC˜CKšœœ0˜;Kšœœ7˜DK˜,Kšœ˜—šœŸ	˜Kš˜Kšœ˜Kšœ˜Kšœ˜KšœC˜CKšœC˜CKšœœ,˜5Kšœœ7˜Dšœ
˜Kš˜Kšœœ˜<Kšœœ3˜HKš˜—šœ˜K˜0—Kšœ˜—šœ˜Kš˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜KšœC˜CKšœI˜IKšœœ1˜<Kšœœ3˜?Kšœœ3˜?Kšœœ8˜EK˜�šœœ˜Kš˜Kšœœ˜>K˜Kšœœ˜šœ˜K˜�——šœœ˜ Kš˜Kšœ&œ˜HK˜Kšœœ˜Kšœ˜—K˜�šœœ˜Kšœ:˜:K˜�—Kšœ˜—Kšœ?˜?Kšœœ
˜——Kšœ˜—Kšœœ
˜—Kšœ˜—K˜�K˜�K˜�™‹K˜�šžœœœœ˜bKš˜šœœ˜(Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœœ˜(—Kšœ˜—K˜�K˜�Kšœ	œœ
˜ šœ
œœ˜K˜Kšœ
œ˜—˜�K™7Kšœ#™#—šžœœ
œœœ!œœ˜xKš˜Kšœœ˜%Kšœœ˜/Kšœœ#˜4Kšœœ˜(Kšœœœœ˜EKšœ	œBœœ˜]šœ		œ		œ˜HKšœ
˜
—Kšœ˜—K˜�šžœœ
œœœ'œ˜wKš˜Kš˜Kšœ˜—K˜�šžœœ
œ%œ˜mKš˜Kšœœ˜%Kšœ	œ*˜7Kšœ*˜0Kšœ˜—K˜�šž	œœ œœ˜>Kš˜Kšœœ˜%Kšœ˜Kšœ˜—K˜�—Kšœ˜——�…—����Q’��n›��