DIRECTORY Basics USING [ Card16FromH, Card32FromF, FFromCard32, FFromInt32, FWORD, HFromCard16, HFromInt16, HWORD, Int16FromH, Int32FromF, LongNumber, LowHalf, RawBytes ], IO USING [ STREAM, UnsafeGetBlock, UnsafePutBlock ], KipperSupport USING [ Kipperer, KippererBody, KipperCard16, KipperCard32, KipperRef, KipperRope, Reason, UnKipperCard16, UnKipperCard32, UnKipperRef, UnKipperRope, UnKipperer, UnKippererBody ], RefTab USING [ Create, EqualProc, Fetch, HashProc, Insert, Ref ], RefText USING [ ObtainScratch, ReleaseScratch ], Rope USING [ AppendChars, Concat, FromRefText, Length, ROPE, ToRefText ]; KipperSupportImpl: CEDAR PROGRAM IMPORTS Basics, IO, KipperSupport, RefTab, RefText, Rope EXPORTS KipperSupport ~ { OPEN KipperSupport; Error: PUBLIC ERROR [ reason: Reason ] ~ CODE; KipperKey: CARD32 ~ 4207557320B; -- 221EDED0h, 572448464 KipperKeyFSwapped: CARD32 ~ 33664021036B; -- 0DED0221Eh, -556785122 KipperVersion: TYPE ~ MACHINE DEPENDENT { unknown(0), dMachine(1), fword(2), adaptive(3) }; CreateKipperer: PUBLIC PROC [ s: IO.STREAM ] RETURNS [ k: Kipperer ] ~ { context: Context ~ NEW[ContextObject ฌ [version: fword] ]; k ฌ NEW [KippererBody ฌ [s, 1, NIL, context]]; k.KipperCard32[KipperKey]; k.KipperCard16[KipperVersion.fword.ORD]; }; Context: TYPE ~ REF ContextObject; ContextObject: TYPE ~ RECORD [ version: KipperVersion ]; CreateUnKipperer: PUBLIC PROC [ s: IO.STREAM ] RETURNS [ u: UnKipperer ] ~ { key: CARD32; version: CARD16; context: Context ~ NEW[ContextObject ฌ [version: unknown] ]; u ฌ NEW [UnKippererBody ฌ [s, 1, NIL, context]]; key ฌ u.UnKipperCard32[]; SELECT TRUE FROM ( key = KipperKey ) => { NULL }; ( key = KipperKeyFSwapped ) => { NULL }; ENDCASE => { Error[notAKipperStream] }; version ฌ u.UnKipperCard16[]; SELECT version FROM ( KipperVersion.dMachine.ORD ) => { NULL }; ( KipperVersion.fword.ORD ) => { NULL }; ( KipperVersion.adaptive.ORD ) => { Error[unsupportedVersion] }; ENDCASE => { Error[wrongKipperVersion] }; context.version ฌ VAL[version]; }; fzero: Basics.FWORD ~ [[0, 0], [0, 0]]; RawBytes: PROC [ local: POINTER ] RETURNS [ raw: LONG POINTER TO Basics.RawBytes ] ~ TRUSTED INLINE { raw ฌ LOOPHOLE[LONG[local], LONG POINTER TO Basics.RawBytes] }; InternalPut16: PROC [ k: Kipperer, ptr: POINTER ] ~ TRUSTED INLINE { k.stream.UnsafePutBlock[[RawBytes[ptr], 2, 2]]; -- magic here: dorado: 0, sparc: 2! }; InternalGet16: PROC [ u: UnKipperer, ptr: POINTER ] ~ TRUSTED INLINE { IF ( u.stream.UnsafeGetBlock[[RawBytes[ptr], 2, 2]] # 2 ) THEN ERROR; }; InternalPut32: PROC [ k: Kipperer, ptr: POINTER ] ~ TRUSTED INLINE { k.stream.UnsafePutBlock[[RawBytes[ptr], 0, 4]]; }; InternalGet32: PROC [ u: UnKipperer, ptr: POINTER ] ~ TRUSTED INLINE { context: Context ~ NARROW[u.private]; IF ( context.version = dMachine ) THEN { dword32: Basics.LongNumber; SwapHalves: PROC[ln: Basics.LongNumber] RETURNS[swp: Basics.LongNumber] ~ TRUSTED INLINE { swp.hi ฌ ln.lo; swp.lo ฌ ln.hi; }; IF ( u.stream.UnsafeGetBlock[[RawBytes[@dword32], 0, 4]] # 4 ) THEN ERROR; LOOPHOLE[ptr, POINTER TO Basics.LongNumber]ญ ฌ SwapHalves[dword32]; } ELSE { IF ( u.stream.UnsafeGetBlock[[RawBytes[ptr], 0, 4]] # 4 ) THEN ERROR; }; }; InternalPutBytes: PROC [ k: Kipperer, ptr: POINTER, bytes: CARD16 ] ~ TRUSTED INLINE { k.stream.UnsafePutBlock[[RawBytes[ptr], 0, bytes]]; }; InternalGetBytes: PROC [ u: UnKipperer, ptr: POINTER, bytes: CARD16 ] ~ TRUSTED INLINE { IF ( u.stream.UnsafeGetBlock[[RawBytes[ptr], 0, bytes]] # bytes ) THEN ERROR; }; KipperBool: PUBLIC PROC [ k: Kipperer, bool: BOOL ] ~ { k.KipperCard16[IF ( bool ) THEN 1 ELSE 0]; }; UnKipperBool: PUBLIC PROC [ u: UnKipperer ] RETURNS [ BOOL ] ~ { RETURN [( u.UnKipperCard16[] = 1 )]; }; KipperCard16: PUBLIC PROC [ k: Kipperer, card16: CARD16 ] ~ TRUSTED { hword: Basics.HWORD ฌ Basics.HFromCard16[card16]; InternalPut16[k, @hword]; }; UnKipperCard16: PUBLIC PROC [ u: UnKipperer ] RETURNS [ card16: CARD16 ] ~ TRUSTED { fword: Basics.FWORD ฌ fzero; -- so we don't get trash InternalGet16[u, @fword]; card16 ฌ Basics.Card16FromH[fword.lo]; }; KipperCard32: PUBLIC PROC [ k: Kipperer, card32: CARD32 ] ~ TRUSTED { fword: Basics.FWORD ฌ Basics.FFromCard32[card32]; InternalPut32[k, @fword]; }; UnKipperCard32: PUBLIC PROC [u: UnKipperer] RETURNS [ card32: CARD32 ] ~ TRUSTED { fword: Basics.FWORD; InternalGet32[u, @fword]; card32 ฌ Basics.Card32FromF[fword]; }; KipperChar: PUBLIC PROC [ k: Kipperer, char: CHAR ] ~ { k.KipperCard16[char.ORD]; }; UnKipperChar: PUBLIC PROC [ u: UnKipperer ] RETURNS [ char: CHAR ] ~ { RETURN [VAL[u.UnKipperCard16[]]]; }; KipperInt16: PUBLIC PROC [ k: Kipperer, int16: INT16 ] ~ TRUSTED { hword: Basics.HWORD ฌ Basics.HFromInt16[int16]; InternalPut16[k, @hword]; }; UnKipperInt16: PUBLIC PROC [ u: UnKipperer ] RETURNS [ int16: INT16 ] ~ TRUSTED { fword: Basics.FWORD ฌ fzero; -- so we don't get trash InternalGet16[u, @fword]; int16 ฌ Basics.Int16FromH[fword.lo]; }; KipperInt32: PUBLIC PROC [ k: Kipperer, int32: INT32 ] ~ TRUSTED { fword: Basics.FWORD ฌ Basics.FFromInt32[int32]; InternalPut32[k, @fword]; }; UnKipperInt32: PUBLIC PROC [ u: UnKipperer ] RETURNS [ int32: INT32 ] ~ TRUSTED { fword: Basics.FWORD; InternalGet32[u, @fword]; int32 ฌ Basics.Int32FromF[fword]; }; KipperNat31: PUBLIC PROC [ k: Kipperer, nat: NAT ] ~ TRUSTED { fword: Basics.FWORD ฌ Basics.FFromCard32[nat]; InternalPut32[k, @fword]; }; UnKipperNat31: PUBLIC PROC [ u: UnKipperer ] RETURNS [ nat: NAT ] ~ TRUSTED { fword: Basics.FWORD; InternalGet32[u, @fword]; nat ฌ Basics.Card32FromF[fword]; }; FFromReal: PROC [n: REAL] RETURNS [Basics.FWORD] = INLINE { RETURN[LOOPHOLE[n]] }; RealFromF: PROC [f: Basics.FWORD] RETURNS [REAL] = INLINE { RETURN[LOOPHOLE[f]] }; KipperReal: PUBLIC PROC [ k: Kipperer, real: REAL ] ~ TRUSTED { fword: Basics.FWORD ฌ --Basics.--FFromReal[real]; InternalPut32[k, @fword]; }; UnKipperReal: PUBLIC PROC [ u: UnKipperer ] RETURNS [ real: REAL ] ~ TRUSTED { fword: Basics.FWORD; InternalGet32[u, @fword]; real ฌ --Basics.--RealFromF[fword]; }; KipperRefText: PUBLIC PROC [ k: Kipperer, refText: REF TEXT ] ~ { k.KipperRope[Rope.FromRefText[refText]]; }; UnKipperRefText: PUBLIC PROC [ u: UnKipperer ] RETURNS [ refText: REF TEXT ] ~ { refText ฌ Rope.ToRefText[u.UnKipperRope[]]; }; RopeBundleSize: CARD16 ฌ 100; KipperRope: PUBLIC PROC [ k: Kipperer, rope: Rope.ROPE ] ~ TRUSTED { IF ( k.KipperRef[rope] ) THEN { textBuffer: REF TEXT ฌ RefText.ObtainScratch[RopeBundleSize]; { ENABLE { UNWIND => RefText.ReleaseScratch[textBuffer] }; position: INT ฌ 0; remaining: INT ฌ rope.Length[]; thisBundleSize: CARD16; thisByteCount: CARD16; WHILE ( remaining > 0 ) DO thisBundleSize ฌ Rope.AppendChars[textBuffer, rope, position, RopeBundleSize]; thisByteCount ฌ ( ( thisBundleSize + 1 ) / 2 ) * 2; InternalPut16[k, @thisBundleSize]; InternalPutBytes[k, BASE[DESCRIPTOR[textBufferญ]], thisByteCount]; textBuffer.length ฌ 0; position ฌ position + thisBundleSize; remaining ฌ remaining - thisBundleSize; ENDLOOP; thisBundleSize ฌ 0; InternalPut16[k, @thisBundleSize]; }; RefText.ReleaseScratch[textBuffer]; }; }; UnKipperRope: PUBLIC PROC [ u: UnKipperer ] RETURNS [ rope: Rope.ROPE ฌ NIL ] ~ TRUSTED { flag: BOOL; ref: REF ANY; [flag, ref] ฌ u.UnKipperRef[]; IF ( NOT flag ) THEN { rope ฌ NARROW[ref]; RETURN; } ELSE { textBuffer: REF TEXT ฌ RefText.ObtainScratch[RopeBundleSize]; { ENABLE { UNWIND => RefText.ReleaseScratch[textBuffer] }; thisBundleSize: CARD16 ฌ u.UnKipperCard16[]; WHILE ( thisBundleSize > 0 ) DO thisByteCount: CARD16 ~ ( ( thisBundleSize + 1 ) / 2 ) * 2; InternalGetBytes[u, BASE[DESCRIPTOR[textBufferญ]], thisByteCount]; textBuffer.length ฌ thisBundleSize; rope ฌ rope.Concat[Rope.FromRefText[textBuffer]]; thisBundleSize ฌ u.UnKipperCard16[]; ENDLOOP; }; RefText.ReleaseScratch[textBuffer]; RecordUnKipperedRef[u, rope]; RETURN; }; }; KipperWord: PUBLIC PROC [ k: Kipperer, word: WORD ] ~ TRUSTED { hword: Basics.HWORD ฌ Basics.HFromCard16[word]; InternalPut16[k, @hword]; }; UnKipperWord: PUBLIC PROC [ u: UnKipperer ] RETURNS [ word: WORD ] ~ TRUSTED { fword: Basics.FWORD ฌ fzero; -- so we don't get trash InternalGet16[u, @fword]; word ฌ Basics.Card16FromH[fword.lo]; }; KipperRef: PUBLIC PROC [ k: Kipperer, r: REF ANY ] RETURNS [ kipperTheBody: BOOL ] ~ TRUSTED { IF ( r = NIL ) THEN { one: CARD16 ฌ 1; InternalPut16[k, @one]; kipperTheBody ฌ FALSE; RETURN; } ELSE { refEncoding: CARD32 ฌ LookUpPossiblyKipperedRef[k, r, k.refCounter]; IF ( refEncoding # 0 ) THEN { two: CARD16 ฌ 2; InternalPut16[k, @two]; InternalPut32[k, @refEncoding]; kipperTheBody ฌ FALSE; RETURN; } ELSE { zero: CARD16 ฌ 0; InternalPut16[k, @zero]; k.refCounter ฌ k.refCounter.SUCC; kipperTheBody ฌ TRUE; RETURN; }; }; }; UnKipperRef: PUBLIC PROC [ u: UnKipperer ] RETURNS [ kipperTheBody: BOOL, ref: REF ANY ] ~ TRUSTED { flag: CARD16 ฌ u.UnKipperCard16[]; SELECT flag FROM 0 => { RETURN [TRUE, NIL] }; 1 => { RETURN [FALSE, NIL] }; 2 => { code: CARD32; InternalGet32[u, @code]; RETURN [FALSE, LookUpPreviouslyUnKipperedRef[u.refTable, code]]; }; ENDCASE => { ERROR }; }; RecordUnKipperedRef: PUBLIC PROC [ u: UnKipperer, r: REF ANY ] ~ { IF ( u.refTable = NIL ) THEN { u.refTable ฌ RefTab.Create[equal: EqualCode, hash: HashCode]; }; IF ( NOT u.refTable.Insert[NEW [CARD32 ฌ u.refCounter], r] ) THEN ERROR; u.refCounter ฌ u.refCounter.SUCC; }; LookUpPreviouslyUnKipperedRef: PROC [ t: RefTab.Ref, code: CARD32 ] RETURNS [ ref: REF ANY ] ~ { found: BOOL; [found, ref] ฌ t.Fetch[NEW [CARD32 ฌ code]]; IF ( NOT found ) THEN ERROR; RETURN; }; LookUpPossiblyKipperedRef: PROC [ k: Kipperer, r: REF ANY, c: CARD32 ] RETURNS [ card32: CARD32 ฌ 0 ] ~ { IF ( k.refTable = NIL ) THEN { k.refTable ฌ RefTab.Create[equal: EqualRef, hash: HashRef]; }; { found: BOOL; indexRef: REF ANY; [found, indexRef] ฌ k.refTable.Fetch[r]; IF ( found ) THEN { card32 ฌ NARROW[indexRef, REF CARD32]ญ; RETURN}; }; { codedRef: REF CARD32; codedRef ฌ NEW [CARD32 ฌ c]; IF ( NOT k.refTable.Insert[r, codedRef] ) THEN ERROR; }; RETURN; }; EqualRef: RefTab.EqualProc ~ CHECKED { RETURN [( key1 = key2 )]; }; HashRef: RefTab.HashProc ~ CHECKED { RETURN [Basics.LowHalf[LOOPHOLE[key]]]; }; EqualCode: RefTab.EqualProc ~ CHECKED { RETURN [NARROW[key1, REF CARD32]ญ = NARROW[key2, REF CARD32]ญ]; }; HashCode: RefTab.HashProc ~ CHECKED { RETURN [Basics.LowHalf[NARROW[key, REF CARD32]ญ]]; }; }. F KipperSupportImpl.mesa December 6, 1985 9:35:33 am PST Copyright ำ 1985, 1986, 1987, 1992 by Xerox Corporation. All rights reserved. Sturgis, January 6, 1986 1:26:43 pm PST Bill Jackson (bj) October 19, 1988 3:32:45 pm PDT Willie-s, April 9, 1992 10:03 am PDT Creation procedures RETURN [k]; RETURN [u]; Internal procedures Client callable procedures InternalGet16[u, @thisBundleSize]; - could be more efficient InternalGet16[u, @thisBundleSize]; - could be more efficient Private Procedures called by generated stubs first a one word flag, perhaps followed by more data 0 for body follows -- this agrees with Lupine "ref=NIL", when ref is non NIL. 1 for NIL -- this agrees with Lupine "ref=NIL", when ref is NIL. 2 for encoding as INT follows, assumes same ref was seen earlier InternalGet16[u, @flag]; - could be more efficient สฬ–(cedarcode) style•NewlineDelimiter ™codešœ3ฯk™6Kšœ ฯeœC™NKšœ$™'Kšœ1™1K™$—K˜š ˜ Kšœœ6œœ:˜กKšœœœ#˜4Kšœœฎ˜มKšœœ5˜AKšœœ#˜0Kšœœ-œ˜IK˜—šฯnœœ˜ Kšœ œ&˜8Kšœ˜Kšœ˜headšฯz™Kšะbnœœœœ˜.KšŸ œœฯc˜8KšŸœœข˜CKšœœœ œ4˜[K˜š กœœœœœœ˜HKšœœ$˜:Kšœœœ ˜.Kšœ˜Kšœ#œ˜(Kšœ™ Kšœ˜—K˜Kšœ œœ˜"šœœœ˜Kšœ˜Kšœ˜K˜—š กœœœœœœ˜LKšœœ˜ Kšœ œ˜Kšœœ&˜Kšœœ˜.Kšœ˜Kšœ˜K˜—š ก œœœœœœ˜NKšœœ˜Kšœ˜K˜ Kšœ˜—K˜š Ÿ œœœœ œ˜0Kšœœœœ˜!—š Ÿ œœ œœœ˜0Kšœœœœ˜!K˜—š ก œœœœœ˜?Kšœœข œ˜1Kšœ˜Kšœ˜K˜—š ก œœœœ œœ˜NKšœœ˜Kšœ˜Kšœข œ˜#Kšœ˜K˜—š ก œœœœœ˜AKšœ(˜(Kšœ˜—K˜š กœœœœ œœ˜PK˜,Kšœ˜——˜KšŸœœ˜K˜š ก œœœœœ˜Dšœœ˜Kšœ œœ)˜=šœ˜Kšœœ)˜8Kšœ œ˜Kšœ œ˜Kšœœ˜Kšœœ˜šœ˜K˜NK˜3Kšœ"˜"Kšœœ œ˜BK˜K˜%K˜'Kšœ˜—K˜Kšœ"˜"Kšœ˜—K˜#Kšœ˜—Kšœ˜—K˜šก œœœœœœœ˜YKšœœœœ˜K˜šœœ˜šœ˜Kšœœ˜Kšœ˜K˜—šœ˜Kšœ œœ)˜=šœ˜Kšœœ)˜8šœœ˜,Kšœ<™<—šœ˜Kšœœ&˜;Kšœœ œ˜BK˜#K˜1˜$Kšœ<™<—Kšœ˜—Kšœ˜—K˜#Kšœ˜Kšœ˜Kšœ˜——Kšœ˜—K˜š ก œœœœœ˜?Kšœœ˜/Kšœ˜Kšœ˜—K˜š ก œœœœ œœ˜NKšœœ ข˜5Kšœ˜K˜$Kšœ˜——š ,™,šก œœœœœœœœ˜^™4Kšœข:™MKšœœข6™@Kšœœ+™@—K˜šœœ˜šœ˜Kšœœ˜Kšœ˜Kšœœ˜Kšœ˜Kšœ˜—šœ˜Kšœ œ1˜Dšœ˜šœ˜Kšœœ˜Kšœ˜Kšœ˜Kšœœ˜Kšœ˜Kšœ˜—šœ˜Kšœœ˜Kšœ˜Kšœœ˜!Kšœœ˜Kšœ˜Kšœ˜——Kšœ˜——Kšœ˜—K˜šก œœœœœœœœ˜dšœœ˜"Kšœ2™2—šœ˜Kšœœœœ˜Kšœœœœ˜šœ˜Kšœœ˜ Kšœ˜Kšœœ3˜@Kšœ˜—Kšœœ˜—Kšœ˜—K˜š กœœœœœ˜Bšœœœ˜K˜=Kšœ˜—Kš œœœœœœ˜HKšœœ˜!Kšœ˜—K˜š Ÿœœœœœœ˜`Kšœœ˜ Kšœœœ ˜,Kšœœ œœ˜Kšœ˜Kšœ˜—K˜šŸœœœœœœ œ ˜išœœœ˜K˜;K˜—šœ˜Kšœœ œœ˜K˜(Kš œ œ œ œœœ˜DKšœ˜—šœ˜Kšœ œœ˜Kšœ œœ˜Kšœœ"œœ˜5Kšœ˜—Kšœ˜Kšœ˜—K˜šŸœœ˜&Kšœ˜Kšœ˜—K˜šŸœœ˜$Kšœœ˜'Kšœ˜—K˜šŸ œœ˜'Kšœœœœœœœ˜?Kšœ˜—K˜šŸœœ˜%Kšœœœœ˜2Kšœ˜K˜——Kšœ˜K˜——…—(^;p