<> <> DIRECTORY FS, IO, Rope; UserProfileOps: CEDAR DEFINITIONS = BEGIN MaxKeys: NAT = 3; KeyChar: CHAR = 'k; <<-- This interface is designed to allow clients to generate a list of filenames from a template.>> <<-- Its main purpose is to overcome the difficulty of generating filenames to meet local >> <<-- naming conventions. >> <<-- For example, a problem occurs with AIS separation files. Normally AIS filenames conform to>> <<-- the template -.. Even so at least two different>> <<-- SeparationFlag naming conventions exist and at least two AISExtension naming conventions.>> <<-- Typically one client will use the flag "grn" to name the green separation, another "g" and >> <<-- a third "green". When these options are permuted with the AISExtension naming>> <<-- conventions ".pic", ".ais", ".image", 9 possible need to be tested.>> <<-->> <<-- Expand provides a simple way of specifying a template containing keys that are>> <<-- to be replaced by ropes extracted from the user.profile. >> <<-->> <<-- Template format: >> <<-- The format rope conforms to the protocol used by the formatting routine PutF in IO.>> <<-- (See IODoc.tioga). In its simplest form expand can be used like PutFR to generate>> <<-- a single rope which is the result of calling PutFR with the format rope and the>> <<-- IO.Values: v1..v5. Expand actually returns a list of length 1. >> <<-- e.g. Expand["File%g.ext", IO.real[99]] => "File99.ext">> <<-->> <<-- To use the user.profile substitution feature a special format sequence introduced by %k is>> <<-- used. The general form is: %k where:>> <<-- is any character used to delimit the following sequences of characters >> <<-- is a user.profile key as specified by UserProfileDoc.Tioga>> <<-- is a default sequence to be used if no corresponding key is found>> <<-->> <<-- So the example above would be handled as follows:>> <<-->> <<-- l _ Expand["%g%k|AISseparationKeys.green|red|.%k|AISExtensions|ais|", IO.rope[fileStem]];>> <<-->> <<-- The user profile would be searched for the keys: "AISseparationKeys.green" and >> <<-- "AISExtensions" and every possible permutation of ropes returned.>> <<-->> <<-- If the user profile contained the entries:>> <<-- AISseparationKeys.green: "-grn" "-green" "-g">> <<-- AISExtensions: "ais" "pic" "image">> <<-->> <<-- and fileStem = "Foo", then>> <<-- l = ("Foo-grn.ais", "Foo-grn.pic", "Foo-grn.image", "Foo-green.ais",>> <<-- "Foo-green.pic", "Foo-green.image", "Foo-g.ais", "Foo-g.pic", "Foo-g.image")>> <<-- Note that the first name in the list is built from the first options of each user.prfile key>> <<-->> <<-- If neither key had been present in the user.profile then >> <<-- l = ("Foo-grn.ais")>> EnumerateProc: TYPE = PROC [rope: Rope.ROPE] RETURNS [tryNext: BOOLEAN _ TRUE]; Expand: PROC [ format: Rope.ROPE _ NIL, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] RETURNS [names: LIST OF Rope.ROPE _ NIL] ; <<>> Enumerate: PROC [ proc: EnumerateProc, format: Rope.ROPE _ NIL, v1, v2, v3, v4, v5: IO.Value _ [null[]] ] ; <<-- Expands the format string using the values v1 .. v5 to produce a list of ropes. The client>> <<-- procedure is then called for each rope in the sequence. If the client procedure returns >> <<-- FALSE then Enumerate returns. >> StreamOpen: PROC [ format: Rope.ROPE _ NIL, v1, v2, v3, v4, v5: IO.Value _ [null[]], accessOptions: FS.AccessOptions _ $read, streamOptions: FS.StreamOptions _ FS.defaultStreamOptions, keep: CARDINAL _ 1, createByteCount: FS.ByteCount _ 2560, streamBufferParms: FS.StreamBufferParms _ FS.defaultStreamBufferParms, extendFileProc: FS.ExtendFileProc _ NIL ] RETURNS [stream: IO.STREAM _ NIL] ; <<-- Expands the format string using the values v1 .. v5. The result is expected to be a list of >> <<-- filenames. An attempt is made to open or create each filename (depending on accessOptions) >> <<-- until one succeeds and produces a stream. If no stream can be produced NIL is returned. >> END.