DIRECTORY Rope USING [ROPE]; Profiles: CEDAR DEFINITIONS = BEGIN OPEN Rope; Profile: TYPE ~ REF ProfileRep; ProfileRep: TYPE; --Private Create: PROC [files: LIST OF ROPE, keepFresh: BOOL ฌ TRUE] RETURNS [profile: Profile]; CreateFromRope: PROC [slices: LIST OF ROPE] RETURNS [profile: Profile]; Slice: TYPE ~ RECORD [ SELECT type: * FROM rope => [text: Rope.ROPE], file => [fileName: Rope.ROPE], ENDCASE ]; CreateFromSlices: PROC [slices: LIST OF Slice, keepFresh: BOOL ฌ TRUE] RETURNS [profile: Profile]; LetProfileGetStale: PROC [profile: Profile]; Boolean: PROC [profile: Profile, key: ROPE, default: BOOL ฌ FALSE] RETURNS [value: BOOL]; Number: PROC [profile: Profile, key: ROPE, default: INT ฌ 0] RETURNS [value: INT]; Token: PROC [profile: Profile, key: ROPE, default: ROPE ฌ NIL] RETURNS [value: ROPE]; ListOfTokens: PROC [profile: Profile, key: ROPE, default: LIST OF ROPE ฌ NIL] RETURNS [value: LIST OF ROPE]; Line: PROC [profile: Profile, key: ROPE, default: ROPE ฌ NIL] RETURNS [value: ROPE]; EnumerateKeys: PROC [profile: Profile, pattern: ROPE, proc: EnumProc]; EnumProc: TYPE ~ PROC [key: ROPE] RETURNS [quit: BOOL ฌ FALSE]; HasEntry: PROC [profile: Profile, key: ROPE] RETURNS [BOOL]; GetProfileNames: PROC [profile: Profile] RETURNS [LIST OF ROPE]; GetProfileSlices: PROC [profile: Profile] RETURNS [LIST OF Slice]; Error: ERROR [reason: ROPE]; CallWhenProfileChanges: PROC [profile: Profile, proc: ProfileChangedProc, clientData: REF]; ProfileChangedProc: TYPE = PROC [profile: Profile, reason: ProfileChangeReason, clientData: REF ฌ NIL]; ProfileChangeReason: TYPE = {firstTime, rollBack, edit}; ProfileChanged: ProfileChangedProc; END. ` Profiles.mesa Copyright ำ 1985, 1986, 1987, 1988, 1991 by Xerox Corporation. All rights reserved. Teitelman on December 16, 1982 11:59 am Russ Atkinson (RRA) November 28, 1988 10:22:25 pm PST Doug Wyatt, January 18, 1987 11:09:25 pm PST Eric Nickell, May 17, 1988 4:41:37 pm PDT Overview Profile is a package for reading information from a disk file .profile, or if none exists, User.profile. The purpose of a profile is to allow personalized tailoring of the system. Entries in the user's profile are of the form: : RETURN, where value is either (1) a BOOL, (2) an INT, (3) a TOKEN, (4) a ListOfTokens, or (5) an expression which can be assigned to some Cedar type (for more details, see ProfileDoc.tioga). Comments (indicated using the standard "--" convention) can appear anywhere in the profile and will be ignored. The parsing will also ignore extra spaces or blank lines. Any errors or anomalies discovered when parsing or accessing the profile will cause diagnostics to be printed to the file Profile.log. The user will be informed that problems have been encountered via the Message Window. In no case however will the system break. Access to individual profile entries via the procedures below is relatively efficient, since this access does not require any file reads or parsing. Therefore, many simple applications can simply read information from the profile as needed. However, some applications derive complex data structures from the profile (consider the effect of the "UserCategory" profile entry on the state of Tioga), and hence cannot afford to interrogate the profile whenever some information derived from it is used. Such an application must register a ProfileChangedProc and perform all of its profile interrogations from within this procedure. This guarantees that the corresponding values will be updated whenever the profile changes. The ProfileChangedProc will be called when it is first registered, whenever the system is booted or rolled-back, or whenever the profile file is saved. Note: Since the ProfileChangedProc for an application is not called from that application's process(es), the application must explicitly synchronize its reads to variables derived from the profile with the ProfileChangedProc's writes to these variables. This may involve adding a monitor to an application that previously did not require one. Creating the Profile Parses a set of profile files and returns the data structure which can be used to access the values. keepFresh implies that the implementation will track changes in the profile, either by editing or upon checkpoint or rollback, etc. Parses a set of profile files and returns the data structure which can be used to access the values. keepFresh implies that the implementation will track changes in the profile, either by editing or upon checkpoint or rollback, etc. Parses a set of profile files and returns the data structure which can be used to access the values. keepFresh implies that the implementation will track changes in the profile, either by editing or upon checkpoint or rollback, etc. If profile was created with Create[keepFresh~TRUE], then the implementation must be holding on the profile in order to know when to update it upon appropriate changes. Calling LetProfileGetStale will remove any references the implementation has to profile. If the profile is not currently being kept fresh, then this operation is a noop. Accessing the Profile The procedures described below all read simple results from the value field given a key. The default value is passed in as an argument so that the client can specify what the procedure returns should the value be absent or malformed, or the profile be missing. returns next token following :, i.e. effectively does an IO.GetTokenRope[... IDBreak]. If the first character encountered is ", then reads everything to the next matching ", and returns this as a single rope. For example, if your profile contains: PreRun: Clock.bcd Foo.bcd Bar.bcd then Token["PreRun"] will return "Clock.bcd". if your profile contains: PreRun: "nay doo run run run" Foo.bcd Bar.bcd then Token["PreRun"] will return "nay doo run run run". For example, if your profile contains: PreRun: Clock.bcd, VersionMapOpsImpl.bcd, HideousKludge.bcd, -- just until 3.4 -- WalnutSend.bcd then ListOfTOkens["PreRun"] will return ("Clock.bcd", "VersionMapOpsImpl.bcd", "HideousKludge.bcd", "WalnutSend.bcd). Note that if the user profile contains Key:{cr}, then ListOfTokens["key", default] will return NIL, not default, i.e. the entry for "key" is neither malformed or absent. Like ListOfTokens except returns the result as a single rope, e.g. for above example, the value of Line["PreRun"] would be "Clock.bcd VersionMapOpsImpl.bcd HideousKludge.bcd WalnutSend.bcd". Pattern is any acceptable to Rope.Match Returns TRUE iff key is defined in profile. returns name of file used to build the profile. returns pieces used to build the profile. Errors Registering procedures for accessing the profile As mentioned above, if the result of accessing the user profile is going to be cached by the client, then the profile should not be accessed directly, but via a ProfileChangedProc which has been registered with CallWhenProfileChanges. This guarantees that the corresponding values will be updated whenever the profile changes. In other words, rather than writing: ClientCheckpointFlag: BOOL _ Profile.Boolean[profile, "ClientCheckpoint", TRUE]; the implementor should write: ClientCheckpointFlag: BOOL; Init: ProfileChangedProc = { ClientCheckpointFlag _ Profile.Boolean[profile, "ClientCheckpoint", TRUE]; }; Profile.CallWhenProfileChanges[profile, Init]; proc is called when it is first registered with reason = firstTime. Calls all of the ProfileChangedProcs. This procedure is automatically called after a rollback, whenever any of its associated files are saved by tioga, or whenever the logged-in user changes. ส๏•NewlineDelimiter –(cedarcode) style™codešœ ™ Kšœ ฯeœI™TKšฯy'™'K™5K™,K™)—˜šฯk ˜ KšœŸœŸœ˜K˜——Kš ะbnœŸœŸ œŸœŸœ˜.K˜headšœ™šœพ™พK™—Kš œ=ะosœŸœ ŸœŸœฎ™ฌK™Kšœ˜ฯnœซขœ™่™šฯsื™ืK™———™Kšœ ŸœŸœ ˜Kšœ Ÿœฯc ˜K˜šขœŸœ ŸœŸœŸœ ŸœŸœŸœ˜VK™dK™ƒK™—š ขœŸœ ŸœŸœŸœŸœ˜GK™dK™ƒK™—šœŸœŸœ˜šŸœ Ÿ˜KšœŸœ˜KšœŸœ˜KšŸ˜—Kšœ˜—šขœŸœ ŸœŸœŸœŸœŸœ˜bK™dK™ƒK™—šขœŸœ˜,K™งK™XK™PK™——™K™Kšœ„™„K˜šขœŸœŸœ ŸœŸœŸœ Ÿœ˜YK˜—š ขœŸœŸœ ŸœŸœ Ÿœ˜RK˜—šขœŸœŸœ ŸœŸœŸœ Ÿœ˜UKšœ>Ÿœ•™ีšœ'™'Kšะpr"™"—Kšœ-™-šœ™Kšฅ.™.—Kšœ7™7K˜—šข œŸœŸœ ŸœŸœŸœŸœŸœ ŸœŸœŸœ˜lšœ'™'Kšฅa™a—Kšœฅœ ฅLœ™uK™Kšœฉ™ฉK˜—šขœŸœŸœ ŸœŸœŸœ Ÿœ˜TKšœcฅœ ฅC™พK™—šข œŸœŸœ˜FKš œ ŸœŸœŸœŸœŸœŸœ˜?K™'K™—š ขœŸœŸœŸœŸœ˜