UPOps.mesa
Mik Lamming - October 29, 1984 4:11:12 pm PST
DIRECTORY FS, IO, Rope;
UPOps: 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 <FileStem>-<SeparationFlag>.<AISExtension>. 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<c><UPKey><c><Default><c> where:
--  <c>    is any character used to delimit the following sequences of characters
--  <UPKey> is a user.profile key as specified by UserProfileDoc.Tioga
--  <Default> 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: BOOLEANTRUE];
Expand: PROC [
format: Rope.ROPENIL,
v1, v2, v3, v4, v5: IO.Value ← [null[]]
]
RETURNS [names: LIST OF Rope.ROPENIL] ;
Enumerate: PROC [
proc: EnumerateProc,
format: Rope.ROPENIL,
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.ROPENIL,
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.STREAMNIL] ;
-- 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.