DIRECTORY Basics USING [bytesPerHWord, Card16FromH, HFromCard16, HWORD, ShortNumber], CHEntriesP0V0 USING [addressList], CHOpsP2V3 USING [AddGroupProperty, AddItemProperty, AddMember, AddSelf, Authenticator, ChangeItem, CreateAlias, CreateObject, DeleteAlias, DeleteMember, DeleteSelf, DeleteObject, DeleteProperty, IsMember, ItemObject, ListAliases, ListAliasesOf, ListDomains, ListDomainsServed, ListObjects, ListOrganizations, ListProperties, LookupObject, NetworkAddressList, RetrieveAddresses, RetrieveItem, RetrieveMembers], CrRPC USING [BulkDataCheckAbortProc, BulkDataValueProc, BulkDataXferProc, GetRope, Handle, MarshalledRopeHWords, PutRope, ReadBulkDataStream, WriteBulkDataSegment], IO USING [STREAM], RefText USING [AppendChar, ObtainScratch, ReleaseScratch], Rope USING [Cat, FromRefText, Index, InlineFetch, IsEmpty, Length, ROPE, Substr], XNS USING [Address, Host, unknownAddress], XNSAuth USING [Identity], XNSCH USING [Conversation, Element, ElementStreamProc, EnumeratorProc, ErrorCode, InitiateConversation, Item, Name, NameStreamProc, notUsable, Pattern, Properties, PropertyID, TerminateConversation, unspecified, Which], XNSCHPrivate USING [CallRemote, GetAuthenticator, IsGeneric, RemoteProc], XNSRouter USING [GetHops] ; XNSCHImpl: CEDAR PROGRAM IMPORTS Basics, CHOpsP2V3, CrRPC, RefText, Rope, XNSCH, XNSCHPrivate, XNSRouter EXPORTS XNSCH, XNSCHPrivate ~ { OPEN CHEntries: CHEntriesP0V0, CHOps: CHOpsP2V3; ROPE: TYPE ~ Rope.ROPE; Name: TYPE ~ XNSCH.Name; Pattern: TYPE ~ XNSCH.Pattern; Element: TYPE ~ XNSCH.Element; PropertyID: TYPE ~ XNSCH.PropertyID; Properties: TYPE ~ XNSCH.Properties; Item: TYPE ~ XNSCH.Item; Conversation: TYPE ~ XNSCH.Conversation; HWORD: TYPE ~ Basics.HWORD; RemoteProc: TYPE ~ XNSCHPrivate.RemoteProc; BulkDataXferProc: TYPE ~ CrRPC.BulkDataXferProc; BulkDataValueProc: TYPE ~ CrRPC.BulkDataValueProc; shiftInName: ROPE ~ "CHServers"; chServiceName: Name ~ [organization~shiftInName, domain~shiftInName, object~"Clearinghouse Service"]; Error: PUBLIC ERROR [code: XNSCH.ErrorCode, which: XNSCH.Which] ~ CODE; Add: PUBLIC PROC [c: Conversation, name: Name] ~ { DoAdd: RemoteProc -- [handle, host] -- ~ { CHOps.CreateObject[handle, name, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAdd, DomainFromElement[name]]; }; Delete: PUBLIC PROC [c: Conversation, name: Name] ~ { DoDelete: RemoteProc -- [handle, host] -- ~ { CHOps.DeleteObject[handle, name, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDelete, DomainFromElement[name]]; }; Lookup: PUBLIC PROC [c: Conversation, pattern: Pattern] RETURNS [distingName: Name] ~ { DoLookup: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.LookupObject[handle, pattern, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoLookup, DomainFromElement[pattern]]; }; AddAlias: PUBLIC PROC [c: Conversation, name, alias: Name] RETURNS [distingName: Name] ~ { DoAddAlias: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.CreateAlias[handle, alias, name, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddAlias, DomainFromElement[alias--????--]]; }; DeleteAlias: PUBLIC PROC [c: Conversation, alias: Name] RETURNS [distingName: Name] ~ { DoDeleteAlias: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteAlias[handle, alias, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteAlias, DomainFromElement[alias]]; }; ListAliases: PUBLIC PROC [c: Conversation, pattern: Pattern, eachAlias: XNSCH.NameStreamProc] RETURNS [distingName: Name] ~ { ReadStreamOfNames: BulkDataXferProc ~ { EachNameInStream: BulkDataValueProc ~ { eachAlias[GetElement[s]] }; RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachNameInStream]]; }; DoListAliases: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.ListAliasesOf[handle, pattern, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoListAliases, DomainFromElement[pattern], FALSE]; }; GetProperties: PUBLIC PROC [c: Conversation, pattern: Pattern] RETURNS [distingName: Name, properties: Properties] ~ { DoGetProperties: RemoteProc -- [handle, host] -- ~ { [distinguishedObject~distingName, properties~properties] _ CHOps.ListProperties[handle, pattern, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoGetProperties, DomainFromElement[pattern]]; }; DeleteProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID] RETURNS [distingName: Name] ~ { DoDeleteProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteProperty[handle, name, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteProperty, DomainFromElement[name]]; }; AddItemProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, item: Item] RETURNS [distingName: Name] ~ { DoAddItemProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddItemProperty[handle, name, pID, item, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddItemProperty, DomainFromElement[name]]; }; ChangeItemProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, item: Item] RETURNS [distingName: Name] ~ { DoChangeItemProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.ChangeItem[handle, name, pID, item, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoChangeItemProperty, DomainFromElement[name]]; }; LookupItemProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID] RETURNS [distingName: Name, item: Item] ~ { DoLookupItemProperty: RemoteProc -- [handle, host] -- ~ { [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoLookupItemProperty, DomainFromElement[pattern]]; }; LookupAddress: PUBLIC PROC [c: Conversation, pattern: Pattern] RETURNS [distingName: Name, address: XNS.Address] ~ { DoLookupAddress: RemoteProc -- [handle, host] -- ~ { item: Item; addresses: LIST OF XNS.Address; [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, CHEntries.addressList, XNSCHPrivate.GetAuthenticator[c, host]]; addresses _ AddressesFromItem[item]; IF addresses # NIL THEN address _ BestAddressInList[addresses] ELSE address _ XNS.unknownAddress; }; XNSCHPrivate.CallRemote[c, DoLookupAddress, DomainFromElement[pattern]]; }; LookupRopeProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID] RETURNS [distingName: Name, ropeProperty: ROPE] ~ { DoLookupRopeProperty: RemoteProc -- [handle, host] -- ~ { item: Item; [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, pID, XNSCHPrivate.GetAuthenticator[c, host]]; ropeProperty _ RopeFromItem[item]; }; XNSCHPrivate.CallRemote[c, DoLookupRopeProperty, DomainFromElement[pattern]]; }; LookupNameProperty: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID] RETURNS [distingName: Name, nameProperty: Name] ~ { DoLookupNameProperty: RemoteProc -- [handle, host] -- ~ { item: Item; [distinguishedObject~distingName, value~item] _ CHOps.RetrieveItem[handle, pattern, pID, XNSCHPrivate.GetAuthenticator[c, host]]; nameProperty _ ElementFromItem[item]; }; XNSCHPrivate.CallRemote[c, DoLookupNameProperty, DomainFromElement[pattern]]; }; HeAborted: ERROR ~ CODE; AddGroupProperty: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, enumerator: XNSCH.EnumeratorProc] RETURNS [distingName: Name] ~ { WriteStreamOfElements: BulkDataXferProc ~ { heAborted: BOOL _ FALSE; EachElement: PROC [element: Element] ~ { WriteTheElement: BulkDataValueProc ~ { PutElement[s, element]; RETURN [FALSE] }; [heAborted~heAborted] _ CrRPC.WriteBulkDataSegment[h, s, checkAbort, WriteTheElement, 1]; IF heAborted THEN ERROR HeAborted[]; }; enumerator[EachElement ! HeAborted => CONTINUE ]; IF NOT heAborted THEN [] _ CrRPC.WriteBulkDataSegment[h, s, NIL, NIL, 0]; RETURN [FALSE] }; DoAddGroupProperty: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddGroupProperty[handle, name, pID, WriteStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddGroupProperty, DomainFromElement[name]]; }; AddMember: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, member: Element] RETURNS [distingName: Name] ~ { DoAddMember: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddMember[handle, name, pID, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddMember, DomainFromElement[name]]; }; AddSelf: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID] RETURNS [distingName: Name] ~ { DoAddSelf: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.AddSelf[handle, name, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoAddSelf, DomainFromElement[name]]; }; DeleteMember: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID, member: Element] RETURNS [distingName: Name] ~ { DoDeleteMember: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteMember[handle, name, pID, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteMember, DomainFromElement[name]]; }; DeleteSelf: PUBLIC PROC [c: Conversation, name: Name, pID: PropertyID] RETURNS [distingName: Name] ~ { DoDeleteSelf: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.DeleteSelf[handle, name, pID, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoDeleteSelf, DomainFromElement[name]]; }; ListMembers: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, eachMember: XNSCH.ElementStreamProc] RETURNS [distingName: Name] ~ { ReadStreamOfElements: BulkDataXferProc ~ { EachElementInStream: BulkDataValueProc ~ { eachMember[GetElement[s]] }; RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachElementInStream]]; }; DoListMembers: RemoteProc -- [handle, host] -- ~ { distingName _ CHOps.RetrieveMembers[handle, pattern, pID, ReadStreamOfElements, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoListMembers, DomainFromElement[pattern], FALSE]; }; IsMember: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, member: Element] RETURNS [distingName: Name, isMember: BOOL] ~ { DoIsMember: RemoteProc -- [handle, host] -- ~ { [isMember~isMember, distinguishedObject~distingName] _ CHOps.IsMember[handle, pattern, pID, XNSCH.notUsable, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoIsMember, DomainFromElement[pattern]]; }; IsMemberClosure: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, member: Element, pID2: PropertyID] RETURNS [distingName: Name, isMember: BOOL] ~ { DoIsMemberClosure: RemoteProc -- [handle, host] -- ~ { [isMember~isMember, distinguishedObject~distingName] _ CHOps.IsMember[handle, pattern, pID, pID2, member, XNSCHPrivate.GetAuthenticator[c, host]]; }; IF pID2 = XNSCH.unspecified THEN pID2 _ pID; XNSCHPrivate.CallRemote[c, DoIsMemberClosure, DomainFromElement[pattern]]; }; Enumerate: PUBLIC PROC [c: Conversation, pattern: Pattern, pID: PropertyID, eachObject: XNSCH.NameStreamProc] ~ { ReadStreamOfNames: BulkDataXferProc ~ { EachNameInStream: BulkDataValueProc ~ { eachObject[GetElement[s]] }; RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachNameInStream]]; }; DoEnumerate: RemoteProc -- [handle, host] -- ~ { CHOps.ListObjects[handle, pattern, pID, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerate, DomainFromElement[pattern], FALSE]; }; EnumerateAliases: PUBLIC PROC [c: Conversation, pattern: Pattern, eachName: XNSCH.NameStreamProc] ~ { ReadStreamOfNames: BulkDataXferProc ~ { EachNameInStream: BulkDataValueProc ~ { eachName[GetElement[s]] }; RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachNameInStream]]; }; DoEnumerateAliases: RemoteProc -- [handle, host] -- ~ { CHOps.ListAliases[handle, pattern, ReadStreamOfNames, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerateAliases, DomainFromElement[pattern], FALSE]; }; EnumerateOrganizations: PUBLIC PROC [c: Conversation, pattern: Pattern, eachOrganization: XNSCH.ElementStreamProc] ~ { ReadStreamOfOrganizations: BulkDataXferProc ~ { EachOrganizationInStream: BulkDataValueProc ~ { eachOrganization[GetOrganization[s]] }; RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachOrganizationInStream]]; }; DoEnumerateOrganizations: RemoteProc -- [handle, host] -- ~ { CHOps.ListOrganizations[handle, pattern.organization, ReadStreamOfOrganizations, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerateOrganizations, NIL, FALSE]; }; EnumerateDomains: PUBLIC PROC [c: Conversation, pattern: Pattern, eachDomain: XNSCH.ElementStreamProc] ~ { ReadStreamOfDomains: BulkDataXferProc ~ { EachDomainInStream: BulkDataValueProc ~ { eachDomain[GetDomain[s]] }; RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachDomainInStream]]; }; DoEnumerateDomains: RemoteProc -- [handle, host] -- ~ { CHOps.ListDomains[handle, [organization~pattern.organization, domain~pattern.domain], ReadStreamOfDomains, XNSCHPrivate.GetAuthenticator[c, host]]; }; XNSCHPrivate.CallRemote[c, DoEnumerateDomains, NIL, FALSE]; }; LookupAddressFromRope: PUBLIC PROC [rope: ROPE] RETURNS [distingName: Name, address: XNS.Address] ~ { c: Conversation ~ XNSCH.InitiateConversation[]; [distingName, address] _ LookupAddress[c, ElementFromRope[rope] ! Error => { distingName _ [NIL,NIL,NIL]; address _ XNS.unknownAddress; CONTINUE }]; XNSCH.TerminateConversation[c] }; GetServerAddresses: PUBLIC PROC [c: Conversation] RETURNS [addresses: LIST OF XNS.Address] ~ { list: CHOps.NetworkAddressList; DoGetServerAddresses: RemoteProc -- [handle, host] -- ~ { i: CARDINAL; list _ CHOps.RetrieveAddresses[handle]; i _ list.length; addresses _ NIL; WHILE i > 0 DO i _ i - 1; addresses _ CONS [LOOPHOLE[list.body[i]], addresses]; ENDLOOP; }; IF XNSCHPrivate.IsGeneric[c] THEN ERROR Error[inappropriateConversation, first]; XNSCHPrivate.CallRemote[c, DoGetServerAddresses, NIL]; }; EnumerateDomainsServed: PUBLIC PROC [c: Conversation, eachDomain: XNSCH.ElementStreamProc] ~ { ReadStreamOfDomains: BulkDataXferProc ~ { EachDomainInStream: BulkDataValueProc ~ { eachDomain[GetDomain[s]] }; RETURN [CrRPC.ReadBulkDataStream[h, s, checkAbort, EachDomainInStream]]; }; DoEnumerateDomainsServed: RemoteProc -- [handle, host] -- ~ { CHOps.ListDomainsServed[handle, ReadStreamOfDomains, XNSCHPrivate.GetAuthenticator[c, host]]; }; IF XNSCHPrivate.IsGeneric[c] THEN ERROR Error[inappropriateConversation, first]; XNSCHPrivate.CallRemote[c, DoEnumerateDomainsServed, NIL]; }; adrHWords: CARDINAL ~ BITS[XNS.Address]/BITS[HWORD]; AddressesFromItem: PUBLIC PROC [item: Item] RETURNS [addresses: LIST OF XNS.Address] ~ { buf: ARRAY [0..adrHWords) OF HWORD; cnt: CARD16 _ item.body[0]; index: CARDINAL _ 1; IF item.length < 1+cnt*adrHWords THEN RETURN[NIL]; THROUGH [1..cnt] DO FOR i: CARDINAL IN [0..adrHWords) DO buf[i] _ Basics.HFromCard16[item.body[index]]; index _ index + 1; ENDLOOP; addresses _ CONS[LOOPHOLE[buf], addresses]; ENDLOOP; }; ItemFromAddresses: PUBLIC PROC [addresses: LIST OF XNS.Address] RETURNS [item: Item] ~ { buf: ARRAY [0..adrHWords) OF HWORD; index: CARDINAL; cnt: CARD16 _ 0; FOR temp: LIST OF XNS.Address _ addresses, temp.rest WHILE temp # NIL DO cnt _ cnt + 1; ENDLOOP; item _ NEW[CHOps.ItemObject[1+cnt*adrHWords]]; item.body[0] _ cnt; index _ 1; FOR temp: LIST OF XNS.Address _ addresses, temp.rest WHILE temp # NIL DO buf _ LOOPHOLE[temp.first]; FOR i: CARDINAL IN [0..adrHWords) DO item.body[index] _ Basics.Card16FromH[buf[i]]; index _ index + 1; ENDLOOP; ENDLOOP; }; RopeFromItem: PUBLIC PROC [item: Item] RETURNS [rope: ROPE] ~ { [rope~rope] _ RopeFromItemInner[item,0] }; ElementFromItem: PUBLIC PROC [item: Item] RETURNS [element: Element] ~ { pos: INT; [rope~element.organization, newPos~pos] _ RopeFromItemInner[item, 0]; [rope~element.domain, newPos~pos] _ RopeFromItemInner[item, pos]; [rope~element.object] _ RopeFromItemInner[item, pos]; }; RopeFromItemInner: PROC [item: Item, pos: INT] RETURNS [rope: ROPE, newPos: INT] ~ { buf: Basics.ShortNumber; text: REF TEXT; cnt: CARDINAL; IF item.length <= pos THEN RETURN [NIL, pos]; cnt _ item.body[pos]; IF ((item.length-pos-1)*Basics.bytesPerHWord) < cnt THEN RETURN [NIL, pos]; -- ERROR text _ RefText.ObtainScratch[cnt]; newPos _ pos+1; DO IF cnt = 0 THEN EXIT; buf.sc _ item.body[newPos]; newPos _ newPos+1; text _ RefText.AppendChar[to~text, from~LOOPHOLE[buf.hi]]; cnt _ cnt-1; IF cnt = 0 THEN EXIT; text _ RefText.AppendChar[to~text, from~LOOPHOLE[buf.lo]]; cnt _ cnt-1; ENDLOOP; rope _ Rope.FromRefText[text]; RefText.ReleaseScratch[text]; }; ItemFromRope: PUBLIC PROC [rope: ROPE] RETURNS [item: Item] ~ { itemLen: INT ~ 1 + CrRPC.MarshalledRopeHWords[rope]; item _ NEW[CHOps.ItemObject[itemLen]]; ItemFromRopeInner[rope, item, 0]; }; ItemFromElement: PUBLIC PROC [element: Element] RETURNS [item: Item] ~ { orgLen: INT ~ CrRPC.MarshalledRopeHWords[element.organization]; domLen: INT ~ CrRPC.MarshalledRopeHWords[element.domain]; objLen: INT ~ CrRPC.MarshalledRopeHWords[element.object]; itemLen: INT ~ orgLen + domLen + objLen; item _ NEW[CHOps.ItemObject[itemLen]]; ItemFromRopeInner[element.organization, item, 0]; ItemFromRopeInner[element.domain, item, orgLen]; ItemFromRopeInner[element.object, item, orgLen + domLen] }; ItemFromRopeInner: PROC [rope: ROPE, item: Item, pos: INT] ~ { buf: Basics.ShortNumber; ropeLen: INT ~ Rope.Length[rope]; itemLen: INT ~ 1 + ((ropeLen+Basics.bytesPerHWord-1) / Basics.bytesPerHWord); iFrom: INT _ 0; item.body[pos] _ ropeLen; pos _ pos + 1; DO IF iFrom >= ropeLen THEN EXIT; buf.hi _ ORD[Rope.InlineFetch[rope, iFrom]]; iFrom _ iFrom+1; buf.lo _ IF iFrom < ropeLen THEN ORD[Rope.InlineFetch[rope, iFrom]] ELSE 0; iFrom _ iFrom+1; item.body[pos] _ buf.sc; pos _ pos + 1; ENDLOOP; }; ElementFromRope: PUBLIC PROC [rope: ROPE, defaultDomain: ROPE _ NIL, defaultOrganization: ROPE _ NIL] RETURNS [element: Element] ~ { GetDefaultDomain: PROC RETURNS [ROPE] ~ INLINE { IF Rope.IsEmpty[defaultDomain] THEN defaultDomain _ "PARC"; -- BOGUS RETURN [defaultDomain] }; GetDefaultOrganization: PROC RETURNS [ROPE] ~ INLINE { IF Rope.IsEmpty[defaultOrganization] THEN defaultOrganization _ "Xerox"; -- BOGUS RETURN [defaultOrganization] }; pos1, pos2, len: INT; len _ Rope.Length[rope]; pos1 _ Rope.Index[s1~rope, pos1~0, s2~":"]; pos2 _ Rope.Index[s1~rope, pos1~pos1+1, s2~":"]; element.object _ Rope.Substr[base~rope, start~0, len~pos1]; element.domain _ IF pos1 < len THEN Rope.Substr[base~rope, start~pos1+1, len~pos2-pos1-1] ELSE NIL; IF Rope.IsEmpty[element.domain] THEN element.domain _ GetDefaultDomain[]; element.organization _ IF pos2 < len THEN Rope.Substr[base~rope, start~pos2+1, len~len-pos2-1] ELSE NIL; IF Rope.IsEmpty[element.organization] THEN element.organization _ GetDefaultOrganization[]; }; RopeFromElement: PUBLIC PROC [element: Element] RETURNS [rope: ROPE] ~ { rope _ Rope.Cat[element.object, ":", "element.domain", ":", element.organization]; }; DomainFromElement: PROC [element: Element] RETURNS [rope: ROPE] ~ INLINE { rope _ Rope.Cat[element.organization, ":", element.domain] }; BestAddressInList: PUBLIC PROC [list: LIST OF XNS.Address] RETURNS [bestAddress: XNS.Address] ~ { bestHops: CARDINAL _ LAST[CARDINAL]; WHILE list # NIL DO tempHops: CARDINAL ~ XNSRouter.GetHops[list.first.net]; IF tempHops < bestHops THEN { bestAddress _ list.first; bestHops _ tempHops }; list _ list.rest; ENDLOOP; }; GetElement: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ { element.organization _ CrRPC.GetRope[stream]; element.domain _ CrRPC.GetRope[stream]; element.object _ CrRPC.GetRope[stream] }; GetOrganization: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ { element.organization _ CrRPC.GetRope[stream]; element.domain _ NIL; element.object _ NIL }; GetDomain: PUBLIC PROC [stream: IO.STREAM] RETURNS [element: Element] ~ { element.organization _ CrRPC.GetRope[stream]; element.domain _ CrRPC.GetRope[stream]; element.object _ NIL }; PutElement: PUBLIC PROC [stream: IO.STREAM, element: Element] ~ { CrRPC.PutRope[stream, element.organization]; CrRPC.PutRope[stream, element.domain]; CrRPC.PutRope[stream, element.object] }; }. όXNSCHImpl.mesa Demers, January 1, 1987 9:12:06 pm PST Operations on Objects [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Operations on Properties [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL] [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Enumeration operations [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL _ FALSE] [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL _ FALSE] [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL _ FALSE] [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Common Lookups Server-Specific Queries [h: Handle, s: IO.STREAM, checkAbort: BulkDataCheckAbortProc] RETURNS [abort: BOOL]; [s: IO.STREAM] RETURNS [abort: BOOL _ FALSE] Utilities (Un)marshalling These are strange because the Items have already been byte-swapped to internal representation, which can mess up objects like XNS.Addresses that are stored inside them. Element <-> Rope conversion e.g. ["Xerox", "PARC", "*"] -> "Xerox:PARC" Address List Manipulation Bulk Data Stream / Marshalling Procs ΚE˜code™K™&K™—šΟk ˜ Kšœœ+œ˜KKšœœ˜"Kšœ œŠ˜™Kšœœ™˜€Kšœœœ˜Kšœœ-˜:Kšœœ9œ ˜QKšœœ!˜*Kšœœ ˜KšœœΠ˜ΫKšœ œ7˜IKšœ œ ˜Kšœ˜K˜—šΟn œœ˜Kšœ*œ˜OKšœœ˜K˜Kšœž œžœ ˜0K˜Kšœœœ˜K˜Kšœœœ˜Kšœ œœ ˜Kšœ œœ ˜Kšœ œœ ˜$Kšœ œœ ˜$Kšœœœ˜Kšœœœ˜(K˜Kšœœ œ˜K˜Kšœ œ˜+Kšœœ˜0Kšœœ˜2K˜Kšœ œ˜ Kšœe˜eK˜Kš žœœœœœ œ˜Ghead™šžœœœ"˜2šžœ Οcœ˜*KšœI˜IK˜—Kšœ;˜;K˜K˜—šžœœœ"˜5šžœ Ÿœ˜-KšœI˜IK˜—Kšœ>˜>K˜K˜—šžœœœ%œ˜Wšžœ Ÿœ˜-KšœZ˜ZK˜—KšœA˜AK˜K˜—šžœœœ&œ˜Zšž œ Ÿœ˜/Kšœ]˜]K˜—Kšœ>Ÿœ˜IK˜K˜—šž œœœ œ˜Wšž œ Ÿœ˜2KšœW˜WK˜—KšœD˜DK˜K˜—šž œ œ0œœ˜}šžœ˜#Kš œœœ&œ œ™TK˜šžœ˜#Kš œœœœ œœ™,Kšœ˜—Kšœ@˜FKšœ˜—šž œ Ÿœ˜2Kšœn˜nK˜—KšœFœ˜MK˜K˜——™šž œœœ%œ0˜všžœ Ÿœ˜4šœ:˜:KšœN˜N—K˜—KšœH˜HK˜K˜—šžœœœ0œ˜jšžœ Ÿœ˜5Kšœ^˜^K˜—KšœF˜FK˜K˜—šžœœœ<œ˜wšžœ Ÿœ˜6Kšœe˜eK˜—KšœG˜GK˜K˜—šžœœœ<œ˜zšžœ Ÿœ˜9Kšœ`˜`K˜—KšœJ˜JK˜K˜—šžœœœ6œ$˜€šžœ Ÿœ˜9šœ/˜/KšœQ˜Q—K˜—KšœM˜MK˜K˜—šž œœœ%œ.˜tšžœ Ÿœ˜4K˜ Kšœ œœœ ˜šœ/˜/Kšœc˜c—Kšœ$˜$šœ ˜Kšœ'˜+Kšœ œ˜"—K˜—KšœH˜HK˜K˜—š žœœœ6œ#œ˜ˆšžœ Ÿœ˜9K˜ šœ/˜/KšœQ˜Q—Kšœ"˜"K˜—KšœM˜MK˜K˜—šžœœœ6œ,˜ˆšžœ Ÿœ˜9K˜ šœ/˜/KšœQ˜Q—Kšœ%˜%K˜—KšœM˜MK˜K˜—Kšž œœœ˜K˜š žœœœ<œœ˜Žšžœ˜'Kš œœœ&œ œ™TK˜Kšœ œœ˜šž œœ˜(šžœ˜"Kš œœœœ œ™$Kšœœœ˜-—KšœY˜YKšœ œœ ˜$K˜—Kšœ&œ˜1Kš œœ œ'œœ˜IKšœœ˜—šžœ Ÿœ˜7Kšœw˜wK˜—KšœH˜HK˜K˜—šž œ œAœ˜všž œ Ÿœ˜0Kšœa˜aK˜—KšœA˜AK˜K˜—šžœ œ0œ˜cšž œ Ÿœ˜.KšœW˜WK˜—Kšœ?˜?K˜K˜—šž œ œAœ˜yšžœ Ÿœ˜3Kšœd˜dK˜—KšœD˜DK˜—K˜šž œ œ0œ˜fšž œ Ÿœ˜1KšœZ˜ZK˜—KšœB˜BK˜K˜—šž œ œBœœ˜’šžœ˜&Kš œœœ&œ œ™TK˜šžœ˜&Kš œœœœ œœ™,Kšœ ˜ —KšœC˜IKšœ˜—šž œ Ÿœ˜2Kšœx˜xK˜—KšœFœ˜MK˜K˜—šžœ œGœœ˜‹šž œ Ÿœ˜/Kšœ\œ<˜K˜—KšœC˜CK˜K˜—šžœ œYœœ˜€šžœ Ÿœ˜6Kšœ’˜’K˜—Kšœœ ˜,KšœJ˜JK˜——™šž œ œBœ˜qšžœ˜#Kš œœœ&œ œ™TK˜šžœ˜#Kš œœœœ œœ™,Kšœ ˜ —Kšœ@˜FKšœ˜—šž œ Ÿœ˜0Kšœc˜cK˜—KšœDœ˜KK˜K˜—šžœ œ/œ˜ešžœ˜#Kš œœœ&œ œ™TK˜šžœ˜#Kš œœœœ œœ™,Kšœ˜—Kšœ@˜FKšœ˜—šžœ Ÿœ˜7Kšœ^˜^K˜—KšœKœ˜RK˜K˜—šžœ œ7œ˜všžœ˜+Kš œœœ&œ œ™TK˜šžœ˜+Kš œœœœ œœ™,Kšœ+˜+—KšœH˜NKšœ˜—šžœ Ÿœ˜=Kšœy˜yK˜—Kšœ5œœ˜AK˜K˜—šžœ œ1œ˜jšžœ˜%Kš œœœ&œ œ™TK˜šžœ˜%Kš œœœœ œœ™,Kšœ˜—KšœB˜HKšœ˜—šžœ Ÿœ˜7Kšœ“˜“K˜—Kšœ/œœ˜;K˜——™š žœœœœœœ ˜eKšœ/˜/šœ?˜?šœ ˜ Kš œœœœœœ˜H——Kšœ!˜!——™šžœœœœ œœœ ˜^Kšœ˜šžœ Ÿœ˜9Kšœœ˜ Kšœ'˜'Kšœ˜Kšœ œ˜šœ˜K˜ Kšœ œœ˜5Kšœ˜—K˜—Kšœœœ)˜PKšœ1œ˜6Kšœ˜K˜—šžœœœœ˜^šžœ˜%Kš œœœ&œ œ™TK˜šžœ˜%Kš œœœœ œœ™,Kšœ˜—KšœB˜HKšœ˜—šžœ Ÿœ˜=Kšœ]˜]K˜—Kšœœœ)˜PKšœ5œ˜:Kšœ˜——™ ™K™¨K˜Kš œ œœœ œœ˜4K˜š žœ œœ œœœ ˜XKšœœœœ˜#Kšœ œ ˜Kšœœ˜Kšœœœœ˜2šœ ˜šœœœ˜$K˜.K˜Kšœ˜—Kšœ œœ˜+Kšœ˜—K˜K˜—š žœ œ œœœ œ˜XKšœœœœ˜#Kšœœ˜Kšœœ˜š œœœœ œœ˜HKšœ˜Kšœ˜—Kšœœ$˜.K˜K˜ š œœœœ œœ˜HKšœœ ˜šœœœ˜$K˜.K˜Kšœ˜—Kšœ˜—K˜K˜—šž œ œœœ˜?K˜*K˜—šžœ œœ˜HKšœœ˜ KšœE˜EKšœA˜AKšœ8˜8K˜—š žœœœœœ œ˜TK˜Kšœœœ˜Kšœœ˜Kšœœœœ˜-Kšœ˜Kš œ2œœœŸ˜TKšœ"˜"Kšœ˜š˜Kšœ œœ˜Kšœ.˜.Kšœ(œ ˜:Kšœ ˜ Kšœ œœ˜Kšœ(œ ˜:Kšœ ˜ Kšœ˜—K˜K˜Kšœ˜K˜—šž œ œœœ˜?Kšœ œ(˜4Kšœœ˜&K˜!K˜K˜—šžœ œœ˜HKšœœ4˜?Kšœœ.˜9Kšœœ.˜9Kšœ œ˜(Kšœœ˜&Kšœ1˜1Kšœ0˜0Kšœ;˜;K˜—šžœœœœ˜>K˜Kšœ œ˜!Kšœ œA˜MKšœœ˜Kšœ)˜)š˜Kšœœœ˜Kšœ œ ˜,Kšœ˜Kš œ œœœ œ˜KKšœ˜Kšœ(˜(Kšœ˜—K˜——™šžœœœœœœœœœ˜„š žœœœœœ˜0KšœœŸ˜DKšœ˜—š žœœœœœ˜6Kšœ#œ Ÿ˜QKšœ˜—Kšœœ˜Kšœ˜K˜+K˜0K˜;šœ˜Kšœ œ7œœ˜R—šœ˜Kšœ%˜)—šœ˜Kšœ œ6œœ˜Q—šœ#˜%Kšœ1˜5—Kšœ˜K˜—š žœœœœœ˜HKšœR˜RK˜K˜—š žœœœœœ˜JK™+K˜=——™šžœ œœœœ œœ ˜aKšœ œœœ˜$šœœ˜Kšœ œ%˜7šœœ˜K˜K˜—K˜Kšœ˜—K˜———™$K˜š ž œ œ œœœ˜JKšœ-˜-Kšœ'˜'Kšœ)˜)K˜—š žœ œ œœœ˜OKšœ-˜-Kšœœ˜Kšœœ˜K˜—š ž œ œ œœœ˜IKšœ-˜-Kšœ'˜'Kšœœ˜K˜—šž œ œ œœ˜AK˜,K˜&K˜(K˜——K˜—J˜—…—OˆiΙ