DIRECTORY Basics USING [LongNumber, ShortNumber], BasicTime USING [FromNSTime, GMT, nullGMT, OutOfRange, ToNSTime], CHNameP2V0 USING [], FilingAttributesP10V5 USING [AccessEntrySequence, AccessList, Attribute, AttributeSequence, AttributeSequenceObject, AttributeValue, AttributeValueObject, FileID, Interpretation, InterpretedAttributeType, nullFileID, Ordering, Position, PositionObject, User], FilingP10V5 USING [allDescendants, Control, ControlSequence, ControlSequenceObject, Direction, Filter, FilterObject, FilterType, PatternFilter, RelationFilter, Scope, ScopeObject, ScopeSequence, ScopeSequenceObject, ScopeType, unlimitedCount], RefText USING [InlineAppendChar, ObtainScratch], Rope USING [FromProc, InlineFetch, Length, ROPE], XNSFilingAttributes USING [Interpreted, InterpretedRange]; XNSFilingAttributeImpl: CEDAR MONITOR IMPORTS BasicTime, RefText, Rope EXPORTS XNSFilingAttributes ~ { OPEN FilingP10V5, FilingAttributesP10V5, XNSFilingAttributes; ROPE: TYPE ~ Rope.ROPE; InfoFromAttributeSequence: PUBLIC PROC [attributes: AttributeSequence] RETURNS [vers: CARD ฌ 0, bytes: INT ฌ -1, created: BasicTime.GMT ฌ BasicTime.nullGMT, fileType: CARD ฌ 0, pathName: REF TEXT ฌ NIL, fID: FileID ฌ nullFileID, isDir: BOOL ฌ FALSE, numKids: CARD ฌ 0] ~ { FOR i: INT IN [0..attributes.length) DO attribute: Attribute ~ attributes[i]; color: Interpreted; IF ( attribute.type NOT IN InterpretedRange ) THEN LOOP; color ฌ VAL[attribute.type]; SELECT color FROM createdOn => { temp: CARD32 ~ DecapsulateCard32[attribute.value]; created ฌ BasicTime.FromNSTime[temp ! BasicTime.OutOfRange => CONTINUE]; }; numberOfChildren => { numKids ฌ 0; IF ( attribute.value = NIL ) THEN LOOP; IF ( attribute.value.length = 0 ) THEN LOOP; numKids ฌ DecapsulateCard16[attribute.value]; }; dataSize => { bytes ฌ DecapsulateCard32[attribute.value] }; fileID => { fID ฌ DecapsulateFileID[attribute.value] }; isDirectory => { isDir ฌ DecapsulateBoolean[attribute.value] }; pathname => { pathName ฌ DecapsulateRefText[attribute.value] }; type => { fileType ฌ DecapsulateCard32[attribute.value] }; version => { vers ฌ DecapsulateCard16[attribute.value] }; ENDCASE => NULL; ENDLOOP; }; nullAttributes: PUBLIC AttributeSequence ฌ NEW[AttributeSequenceObject[0]]; nullControls: PUBLIC ControlSequence ฌ NEW[ControlSequenceObject[0]]; BuildScope: PUBLIC PROC [filterType: FilterType, rope: ROPE, type: CARD32] RETURNS [scope: ScopeSequence] = { value: AttributeValue ฌ EncapsulateRope[rope]; filter: Filter; scope ฌ NEW[ScopeSequenceObject[4]]; scope[0] ฌ NEW[ScopeObject.count ฌ [count[unlimitedCount]]]; scope[1] ฌ NEW[ScopeObject.depth ฌ [depth[allDescendants]]]; scope[2] ฌ NEW[ScopeObject.direction ฌ [direction[forward]]]; filter ฌ SELECT filterType FROM matches => NEW [FilterObject.matches ฌ [matches[matches: [attribute: [type: type, value: value]]] ]], equal => NEW [FilterObject.equal ฌ [equal[equal: [attribute: [type: type, value: value], interpretation: string]] ]], ENDCASE => NEW [FilterObject.none ฌ [none[none: [null: 0]] ]]; scope[3] ฌ NEW [ScopeObject.filter ฌ [filter[filter: filter]]]; }; BuildAttribute: PUBLIC PROC [name: ROPE, type: CARD32, time: BasicTime.GMT ฌ BasicTime.nullGMT, timeType: CARD32 ฌ 0] RETURNS [attributes: AttributeSequence] = { IF time = BasicTime.nullGMT THEN { attributes ฌ NEW [AttributeSequenceObject[1]]; attributes[0] ฌ [type: type, value: EncapsulateRope[name]]; RETURN[attributes]; }; attributes ฌ NEW [AttributeSequenceObject[2]]; attributes[0] ฌ [type: timeType, value: EncapsulateCard32[BasicTime.ToNSTime[time]]]; attributes[1] ฌ [type: type, value: EncapsulateRope[name]]; RETURN[attributes]; }; BuildDirectoryAttribute: PUBLIC PROC [nameR: ROPE] RETURNS [attributes: AttributeSequence] = { attributes ฌ NEW [AttributeSequenceObject[3]]; attributes[0] ฌ [type: Interpreted.isDirectory.ORD, value: EncapsulateBoolean[TRUE]]; attributes[1] ฌ [type: Interpreted.name.ORD, value: EncapsulateRope[nameR]]; attributes[2] ฌ [type: Interpreted.type.ORD, value: EncapsulateCard32[1 -- tDirectory --]]; RETURN[attributes]; }; BuildStoreAttributes: PUBLIC PROC [file: ROPE, vers: CARDINAL, created: BasicTime.GMT] RETURNS [attributes: AttributeSequence] ~ { num: CARDINAL ฌ IF ( created = BasicTime.nullGMT ) THEN 2 ELSE 3; attributes ฌ NEW [AttributeSequenceObject[num]]; attributes[0] ฌ [type: Interpreted.name.ORD, value: EncapsulateRope[file]]; attributes[1] ฌ [type: Interpreted.version.ORD, value: EncapsulateCard16[vers]]; IF ( created # BasicTime.nullGMT ) THEN { time: CARD32 ฌ BasicTime.ToNSTime[created]; attributes[2] ฌ [type: Interpreted.createdOn.ORD, value: EncapsulateCard32[time]]; }; }; EncapsulateAccessList: PUBLIC PROC [accessList: AccessList] RETURNS [value: AttributeValue] ~ { value ฌ NIL; }; DecapsulateAccessList: PUBLIC PROC [value: AttributeValue] RETURNS [accessList: AccessList] ~ { }; EncapsulateFileID: PUBLIC PROC [fileID: FileID] RETURNS [value: AttributeValue] ~ { len: CARDINAL ~ 5; value ฌ NEW[AttributeValueObject[len]]; FOR i: CARDINAL IN [0..len) DO value[i] ฌ fileID[i]; ENDLOOP; }; DecapsulateFileID: PUBLIC PROC [value: AttributeValue] RETURNS [fileID: FileID] ~ { IF value = NIL THEN ERROR; IF value.length # 5 THEN ERROR; FOR i: CARDINAL IN [0..5) DO fileID[i] ฌ value[i]; ENDLOOP; }; EncapsulateOrdering: PUBLIC PROC [ordering: Ordering] RETURNS [value: AttributeValue] ~ { value ฌ NIL; }; DecapsulateOrdering: PUBLIC PROC [value: AttributeValue] RETURNS [ordering: Ordering] ~ { temp: Basics.LongNumber; IF value = NIL THEN ERROR; IF value.length # 4 THEN ERROR; temp.hi ฌ value[0]; temp.lo ฌ value[1]; ordering.key ฌ temp.lc; ordering.ascending ฌ IF value[2] = 1 THEN TRUE ELSE FALSE; ordering.interpretation ฌ VAL[value[3]]; }; EncapsulatePosition: PUBLIC PROC [position: Position] RETURNS [value: AttributeValue] ~ { value ฌ NIL; }; DecapsulatePosition: PUBLIC PROC [value: AttributeValue] RETURNS [position: Position] ~ { length: CARDINAL; IF value = NIL THEN ERROR; IF value.length <= 0 THEN ERROR; length ฌ value[0]; position ฌ NEW[PositionObject[length]]; FOR i: CARDINAL IN [0..length) DO position.body[i] ฌ value[i+1]; ENDLOOP; }; EncapsulateUser: PUBLIC PROC [name: ROPE] RETURNS [value: AttributeValue] ~ { value ฌ NIL; }; DecapsulateUser: PUBLIC PROC [value: AttributeValue] RETURNS [user: User] ~ { place: NAT ฌ 0; GetRope: PROC [] RETURNS [r: ROPE] = { temp: Basics.ShortNumber; len, i: NAT ฌ 0; P: PROC RETURNS[c: CHAR] = { IF i MOD 2 = 0 THEN {temp.sc ฌ value[place]; place ฌ place + 1; c ฌ VAL[temp.hi]} ELSE {c ฌ VAL[temp.lo]}; i ฌ i + 1; }; len ฌ value[place]; place ฌ place + 1; r ฌ Rope.FromProc[len: len, p: P]; }; IF value = NIL THEN ERROR; user.organization ฌ GetRope[]; user.domain ฌ GetRope[]; user.object ฌ GetRope[]; }; EncapsulateBoolean: PUBLIC PROC [b: BOOL] RETURNS [value: AttributeValue] ~ { len: NAT ~ 1; -- wrapped len value ฌ NEW [AttributeValueObject[len]]; value[0] ฌ IF b THEN 1 ELSE 0; }; DecapsulateBoolean: PUBLIC PROC [value: AttributeValue] RETURNS [b: BOOL] ~ { IF value = NIL THEN ERROR; IF value.length # 1 THEN ERROR; b ฌ IF value[0] = 1 THEN TRUE ELSE FALSE; }; EncapsulateCard16: PUBLIC PROC [i: CARD16] RETURNS [value: AttributeValue] ~ { len: NAT ~ 1; -- wrapped len value ฌ NEW [AttributeValueObject[len]]; value[0] ฌ i; }; DecapsulateCard16: PUBLIC PROC [value: AttributeValue] RETURNS [i: CARD16] ~ { IF value = NIL THEN ERROR; IF value.length # 1 THEN ERROR; i ฌ value[0]; }; EncapsulateCard32: PUBLIC PROC [i: CARD32] RETURNS [value: AttributeValue] ~ { temp: Basics.LongNumber; len: NAT ~ 2; -- wrapped len value ฌ NEW [AttributeValueObject[len]]; temp.lc ฌ i; value[0] ฌ temp.hi; value[1] ฌ temp.lo; }; DecapsulateCard32: PUBLIC PROC [value: AttributeValue] RETURNS [i: CARD32] ~ { temp: Basics.LongNumber; IF value = NIL THEN ERROR; IF value.length # 2 THEN ERROR; temp.hi ฌ value[0]; temp.lo ฌ value[1]; i ฌ temp.lc; }; EncapsulateRope: PUBLIC PROC [name: ROPE] RETURNS [value: AttributeValue] ~ { len: NAT ~ (name.Length[]+3) / 2; -- wrapped len value ฌ NEW[AttributeValueObject[len]]; TRUSTED { EncapsulateBytes[@(value.body), name] }; }; DecapsulateRope: PUBLIC PROC [value: AttributeValue] RETURNS [rope: ROPE] ~ { place: NAT ฌ 0; GetRope: PROC [] RETURNS [r: ROPE] = { temp: Basics.ShortNumber; len, i: NAT ฌ 0; P: PROC RETURNS[c: CHAR] = { IF i MOD 2 = 0 THEN {temp.sc ฌ value[place]; place ฌ place + 1; c ฌ VAL[temp.hi]} ELSE {c ฌ VAL[temp.lo]}; i ฌ i + 1; }; len ฌ value[place]; place ฌ place + 1; r ฌ Rope.FromProc[len: len, p: P]; }; IF value = NIL THEN ERROR; rope ฌ GetRope[]; }; DecapsulateRefText: PUBLIC PROC [value: AttributeValue] RETURNS [rope: REF TEXT] ~ { place: NAT ฌ 0; GetRope: PROC [] RETURNS [r: REF TEXT] = { temp: Basics.ShortNumber; len: NAT ฌ 0; P: PROC [i: NAT] RETURNS[c: CHAR] = { IF i MOD 2 = 0 THEN {temp.sc ฌ value[place]; place ฌ place + 1; c ฌ VAL[temp.hi]} ELSE {c ฌ VAL[temp.lo]}; }; len ฌ value[place]; place ฌ place + 1; r ฌ RefText.ObtainScratch[len]; FOR i: NAT IN [0 .. len) DO c: CHAR ~ P[i]; r ฌ RefText.InlineAppendChar[r, c]; ENDLOOP; }; IF value = NIL THEN ERROR; rope ฌ GetRope[]; }; OpaqueByteObject: TYPE ~ MACHINE DEPENDENT RECORD [ length: CARDINAL, body: PACKED ARRAY [0..1000) OF CHAR ]; EncapsulateBytes: PUBLIC PROC [bytes: LONG POINTER, rope: ROPE] ~ TRUSTED { len: NAT ~ rope.Length[]; b: LONG POINTER TO OpaqueByteObject ~ bytes; avo: LONG POINTER TO AttributeValueObject ~ bytes; avo.body[0] ฌ len; FOR i: NAT IN [0..len) DO b.body[i+2] ฌ rope.InlineFetch[i]; ENDLOOP; IF ( (len MOD 2) = 1 ) THEN b.body[len+2] ฌ 0C; }; EncapsulateNull: PUBLIC PROC RETURNS [value: AttributeValue] ~ { len: NAT ~ 0; -- wrapped len value ฌ NEW [AttributeValueObject[len]]; }; << AllInterpretedValues: TYPE ~ REF AllInterpretedValuesRep; AllInterpretedValuesRep: TYPE ~ RECORD [ set: PACKED ARRAY Interpreted OF BOOL, checksum: CARDINAL ]; GetInterpretation: PUBLIC PROC [attribute: Attribute, old: AllInterpretedValues ฌ NIL] RETURNS [new: AllInterpretedValues] ~ { IF old # NIL THEN new ฌ old ELSE { new ฌ NEW[AllInterpretedValuesRep]; new.set ฌ ALL[FALSE] }; IF ( attribute.type IN InterpretedRange ) THEN { color: Interpreted ~ VAL[attribute.type]; new.set[color] ฌ TRUE; SELECT color FROM checksum => { new.checksum ฌ DecapsulateCard16[attribute.value]; }; childrenUniquelyNamed => { new.childrenUniquelyNamed ฌ DecapsulateBoolean[attribute.value] }; createdBy => { new.createdBy ฌ DecapsulateUser[attribute.value] }; createdOn => { new.createdOn ฌ DecapsulateCard32[attribute.value] }; fileID => { new.fileID ฌ DecapsulateFileID[attribute.value] }; isDirectory => { new.isDirectory ฌ DecapsulateBoolean[attribute.value] }; isTemporary => { new.isTemporary ฌ DecapsulateBoolean[attribute.value] }; modifiedBy => { new.modifiedBy ฌ DecapsulateUser[attribute.value] }; modifiedOn => { new.modifiedOn ฌ DecapsulateCard32[attribute.value] }; name => { new.name ฌ DecapsulateRope[attribute.value] }; numberOfChildren => { new.numberOfChildren ฌ DecapsulateCard16[attribute.value] }; ordering => { new.ordering ฌ DecapsulateOrdering[attribute.value] }; parentID => { new.parentID ฌ DecapsulateFileID[attribute.value] }; position => { new.position ฌ DecapsulatePosition[attribute.value] }; readBy => { new.readBy ฌ DecapsulateUser[attribute.value] }; readOn => { new.readOn ฌ DecapsulateCard32[attribute.value] }; dataSize => { new.dataSize ฌ DecapsulateCard32[attribute.value] }; type => { new.type ฌ DecapsulateCard32[attribute.value] }; version => { new.version ฌ DecapsulateCard16[attribute.value] }; accessList => { new.accessList ฌ DecapsulateAccessList[attribute.value] }; defaultAccessList => { new.defaultAccessList ฌ DecapsulateAccessList[attribute.value] }; pathname => { new.pathname ฌ DecapsulateRope[attribute.value] }; storedSize => { new.storedSize ฌ DecapsulateCard32[attribute.value] }; subtreeSize => { new.subtreeSize ฌ DecapsulateCard32[attribute.value] }; subtreeSizeLimit => { new.subtreeSizeLimit ฌ DecapsulateCard32[attribute.value] }; ENDCASE => ERROR; }; }; >> }. ึ XNSFilingAttributeImpl.mesa Copyright ำ 1990, 1992 by Xerox Corporation. All rights reserved. Bill Jackson (bj), May 25, 1990 6:51 pm PDT xx Well-known constants Support things Attribute Encapsulation GetAccessEntrySequence: PROC [h: CrRPC.Handle, s: CrRPC.STREAM] RETURNS [res: AccessEntrySequence] ~ { GetAccess: PROC [h: CrRPC.Handle, s: CrRPC.STREAM] RETURNS [res: AccessSequence] ~ { length14: CARDINAL ~ DecapsulateCard16[attribute.value]; interpreted _ NEW[AccessSequenceObject[length14]]; FOR i13: CARDINAL IN [0..length14) DO res.body[i13] _ VAL[DecapsulateCard16[attribute.value]]; ENDLOOP; }; length11: CARDINAL ~ DecapsulateCard16[attribute.value]; interpreted _ NEW[AccessEntrySequenceObject[length11]]; FOR i10: CARDINAL IN [0..length11) DO res.body[i10].key.organization _ DecapsulateRope[attribute.value]; res.body[i10].key.domain _ DecapsulateRope[attribute.value]; res.body[i10].key.object _ DecapsulateRope[attribute.value]; res.body[i10].access _ GetAccess[h, s]; ENDLOOP; }; accessList.entries _ GetAccessEntrySequence[h, s]; accessList.defaulted _ DecapsulateBoolean[attribute.value]; Generic (immuatable?) textLength: CARD16, -- first two bytes of body! b.sequenceLength _ len; -- skip sequence length xx สe–(cedarcode) style•NewlineDelimiter ™šœ™Jšœ ฯeœ7™BJ™+Icode™—šฯk ˜ Kšœžœ˜'Kšœ žœžœ!˜AKšœ žœ˜Kšœžœ่˜ƒKšœ žœโ˜๓Kšœžœ#˜0Kšœžœ!žœ˜1Kšœžœ!˜:K˜—šฯnœžœž˜%Kšžœ˜ Kšžœ˜Kšžœ9˜=Kšžœžœžœ˜head2šฯz™šŸœžœžœ!žœžœ žœžœ žœžœžœžœ#žœžœ žœ ˜šžœžœžœž˜'Kšœ%˜%Kšœ˜Kš žœžœžœžœžœ˜8Kšœžœ˜šžœž˜šœ˜Kšœžœ&˜2Kšœ>žœ˜HKšœ˜—šœ˜K˜ Kšžœžœžœžœ˜'Kšžœ žœžœ˜,K˜-Kšœ˜—K˜;K˜7K˜?K˜?K˜:K˜9Kšžœžœ˜—Kšžœ˜—Kšœ˜——headš ™Kšœžœžœ˜KKšœžœžœ˜E—š ™š Ÿ œžœžœ žœžœžœ˜mK˜.Kšœ˜Kšœžœ˜$Kšœ žœ.˜—Kšœ žœ1˜?Kšœ˜—K˜šŸœžœžœžœžœžœ žœžœ$˜กšžœžœ˜"Kšœ žœ˜.K˜;Kšžœ ˜Kšœ˜—Kšœ žœ˜.K˜UK˜;Kšžœ ˜Kšœ˜—K˜š Ÿœžœžœ žœžœ$˜^Kšœ žœ˜.Kšœ/žœžœ˜UKšœ(žœ!˜LKšœ(žœฯcœ˜[Kšžœ ˜Kšœ˜K˜—šŸœžœžœžœžœžœžœ$˜‚Kš œžœžœ!žœžœ˜AKšœ žœ ˜0Kšœ(žœ ˜KKšœ+žœ"˜Pšžœ!žœ˜)K•StartOfExpansion[GMT]šœžœ˜+Kšœ-žœ"˜RKšœ˜—K˜——š ™šŸœžœžœžœ˜_Kšœžœ˜ K˜—šŸœžœžœžœ˜_šœ?™?Kšœ&™&šœ2™2Kšœ!™!Kšœ8™8Kšœ2™2Kšœ%™%Kšœ8™8Kšœ™Kšœ™—Kšœ8™8Kšœ7™7Kšœ%™%KšœB™BKšœ<™K˜IK˜IK˜DK˜FK˜8K˜RK˜DK˜BK˜DK˜K˜BK˜:K˜@K˜JK˜XK˜@K˜FK˜HK˜RKšžœžœ˜—K˜—K˜K˜K˜——K˜——…—.าB