DIRECTORY BasicTime USING [GMT], LoganBerry USING [AttributeType, AttributeValue, Entry], Rope USING [ROPE]; LoganBerryEntry: CEDAR DEFINITIONS ~ BEGIN ROPE: TYPE ~ Rope.ROPE; GetAttr: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType] RETURNS [LoganBerry.AttributeValue]; GetAllAttrs: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType] RETURNS [LIST OF LoganBerry.AttributeValue]; SetAttr: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType, value: LoganBerry.AttributeValue] RETURNS []; ChangeAttr: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType, value: LoganBerry.AttributeValue] RETURNS [found: BOOLEAN]; AddAttr: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType, value: LoganBerry.AttributeValue] RETURNS [new: LoganBerry.Entry]; RemoveAttr: PROC [entry: LoganBerry.Entry, type: LoganBerry.AttributeType, value: LoganBerry.AttributeValue] RETURNS [new: LoganBerry.Entry]; CopyEntry: PROC [entry: LoganBerry.Entry] RETURNS [new: LoganBerry.Entry]; ReverseEntry: PROC [entry: LoganBerry.Entry] RETURNS [new: LoganBerry.Entry]; AppendEntries: PROC [e1, e2: LoganBerry.Entry] RETURNS [new: LoganBerry.Entry]; EntriesEqual: PROC [e1, e2: LoganBerry.Entry] RETURNS [BOOL]; Timestamp: TYPE ~ LoganBerry.AttributeValue; NewTimestamp: PROC [] RETURNS [ts: Timestamp]; I2V: PROC [i: INT] RETURNS [v: LoganBerry.AttributeValue]; B2V: PROC [b: BOOL] RETURNS [v: LoganBerry.AttributeValue]; S2V: PROC [s: ROPE] RETURNS [v: LoganBerry.AttributeValue]; A2V: PROC [a: ATOM] RETURNS [v: LoganBerry.AttributeValue]; T2V: PROC [t: BasicTime.GMT] RETURNS [v: LoganBerry.AttributeValue]; T2Ts: PROC [t: BasicTime.GMT] RETURNS [ts: Timestamp]; V2I: PROC [v: LoganBerry.AttributeValue] RETURNS [i: INT]; V2B: PROC [v: LoganBerry.AttributeValue] RETURNS [b: BOOL]; V2S: PROC [v: LoganBerry.AttributeValue] RETURNS [s: ROPE]; V2A: PROC [v: LoganBerry.AttributeValue] RETURNS [a: ATOM]; V2T: PROC [v: LoganBerry.AttributeValue] RETURNS [t: BasicTime.GMT]; Ts2T: PROC [ts: Timestamp] RETURNS [t: BasicTime.GMT]; ParseError: ERROR [explanation: Rope.ROPE ¬ NIL]; EntryToRope: TYPE = PROC [entry: LoganBerry.Entry] RETURNS [rope: Rope.ROPE]; RopeToEntry: TYPE = PROC [rope: Rope.ROPE] RETURNS [entry: LoganBerry.Entry, error: BOOL]; Formatter: TYPE = REF FormatterRec; FormatterRec: TYPE = RECORD [ -- The per formatter data structure name: ATOM, -- The name of the formatter format: ATOM, -- The format of the node entryToRope: EntryToRope, -- Convert an entry to it's corresp. rope ropeToEntry: RopeToEntry -- Convert a rope to it's corresp. entry ]; RegisterFormatter: PROC [name: ATOM, formatter: Formatter] RETURNS []; GetFormatterByName: PROC [name: ATOM] RETURNS [formatter: Formatter]; EachFormatterAction: TYPE = PROC [formatter: Formatter] RETURNS [quit: BOOL ¬ FALSE]; EnumerateFormatters: PROC [action: EachFormatterAction] RETURNS [BOOL]; END.   LoganBerryEntry.mesa Copyright Σ 1987, 1992 by Xerox Corporation. All rights reserved. Doug Terry, November 14, 1989 9:40:29 am PST Routines for manipulating LoganBerry entries. Entry operations Operations on attributes within entries: Extracts value of particular attribute from entry. Returns NIL if entry does not contain an attribute of the specified type. Extracts all values of the particular attribute type and returns them as a list. Returns NIL if entry does not contain an attribute of the specified type. Changes the value of a particular attribute in entry. Does nothing if entry does not contain an attribute of the specified type. Like SetAttr but returns found=FALSE if entry does not contain an attribute of the specified type. Appends an attrribute to the entry. Returns the new entry. Removes the specified attribute from the entry. Returns the new entry, which may be NIL. Operations on whole entries: Makes a copy of the given entry. Destructively reverses the order of the entry's attributes. Concatenates two entries together. Returns true if two entries are equal up to reordering. Timestamps For some databases, there may be no natural attribute to serve as a key. In this case, a unique timestamp can be used as a key. Generates a timestamp that is close to the current time and such that subsequent calls to NewTimestamp yield different results provided (1) the calls are performed on the same machine, and (2) the machine has not crashed and been restarted in between calls. Even if NewTimestamp is called on different machines, the results will be unique with a high probability. Timestamps generated by calls to NewTimestamp may be used directly as keys as in the following piece of code: LoganBerry.WriteEntry[db: db, entry: AddAttr[entry, $Key, NewTimestamp[]]]; However, this may occasionally fail since NewTimestamp is not guaranteed to provide a unique result. Hence, the following is a safer way to use NewTimestamp: WriteWithTimestamp: PROC [db: LoganBerry.OpenDB, entry: LoganBerry.Entry] = { timestampedEntry: LoganBerry.Entry _ AddAttr[entry, $Key, NewTimestamp[]]; LoganBerry.WriteEntry[db: db, entry: timestampedEntry ! LoganBerry.Error => IF ec=$ValueNotUnique THEN {SetAttr[entry, $Key, NewTimestamp[]]; RETRY} ]; }; Conversions From various data types to attribute values: From an integer to an attribute value, e.g. "101". From a boolean to an attribute value, e.g. "TRUE". From a rope to an attribute value (most likely a no-op). From an atom to an attribute value. From a time to an attribute value, e.g. "19 Jan 87 14:27:05 PST". From a time to a timestamp. A timestamp is not human-readable, e.g. "2804473302", but does have the property that BasicTime.Period[from: t1, to: t2] > 0 => T2Ts[t1] < T2Ts[t2] lexicographically. From attribute values to various data types: From an attribute value to an integer. From an attribute value, i.e. "TRUE" or "FALSE", to a boolean. From an attribute value to a rope (most likely a no-op). From an attribute value to an atom. From an attribute value, e.g. "19 Jan 87 14:27:05 PST", to a time. From a timestamp to a time. Formatters Formatters are parsers and unparsers for LoganBerry entries. Creates the rope corresponding to an entry. Creates an entry corresponding to a rope; raises ParseError if the entry is in error. Register a set of formatting procedures for a named class; if formatter is NIL then the name is unregistered. Get the registered formatter of the specified name or NIL if there is no such formatter. Enumerates pairs currently in the formatter registry in unspecified order; applies action to each pair until action returns TRUE or no more pairs; returns TRUE if some action returns TRUE. ΚΑ•NewlineDelimiter –(cedarcode) style™code•Mark outsideHeaderšœ™Kšœ Οeœ7™BK™,K™K™-K™—šΟk ˜ Kšœ žœ˜Kšœ žœ(˜8Kšœžœžœ˜—K˜KšΠblœžœž ˜"šœž˜K˜Kšžœžœžœ˜K˜—head™K™(K˜šΟnœžœ;žœ˜lK™}K™—š   œžœ;žœžœžœ˜xK™›K™—š œžœ]žœ˜uK™K™—š  œžœ]žœ žœ˜†K™bK™—š œžœ]žœ˜ŠK™;K™—š  œžœ]žœ˜K™YK™—K™K™š  œžœžœžœ˜JK™ K™—š  œžœžœžœ˜MKšœ;™;K™—š  œžœžœžœ˜OK™"K™—š  œžœžœžœ˜=K™7K™——™ J™€J™Kšœ žœ˜,J™š  œžœžœ˜.Jšœμ™μJ™—šœm™mJ™J•StartOfExpansionŒ[conv: LoganBerry.Conv _ NIL, db: LoganBerry.OpenDB, entry: LoganBerry.Entry, log: LoganBerry.LogID _ 0, replace: BOOLEAN _ FALSE]šœK™KJ™—šœž™žJ™šœžœ5™MJ–Œ[conv: LoganBerry.Conv _ NIL, db: LoganBerry.OpenDB, entry: LoganBerry.Entry, log: LoganBerry.LogID _ 0, replace: BOOLEAN _ FALSE]šœJ™Jšœ6™6Jšœžœžœ(žœ™a—J™——J™—™ Kšœ,™,K™š œžœžœžœ ˜:Kšœ2™2K˜—š œžœžœžœ ˜;Kšœ2™2K˜—š œžœžœžœ ˜;Kšœ8™8K˜—š œžœžœžœ ˜;Kšœ#™#K˜—š œžœžœžœ ˜DKšœA™AK™—š œžœžœžœ˜6KšœΓ™Γ—K™Kšœ,™,K˜š œžœ žœžœ˜:Kšœ&™&K˜—š œžœ žœžœ˜;Kšœ>™>K˜—š œžœ žœžœ˜;Kšœ8™8K˜—š œžœ žœžœ˜;Kšœ#™#K˜—š œžœ žœžœ˜DKšœB™BK˜—š œžœžœžœ˜6Kšœ™K˜——™ J™