DIRECTORY BasicTime USING [GMT, nullGMT, Period], BcdDefs USING [NullVersion, VersionStamp], Commander USING [CommandProc, Handle, Register], FS USING [Close, Error, FileInfo, GetName, Open, OpenFile], IO USING [EndOfStream, GetTokenRope, IDProc, PutF, RIS, STREAM], Process USING [CheckForAbort], Rope USING [Cat, Compare, Concat, Equal, Fetch, Flatten, Index, Length, Match, ROPE, Run, Substr], TiogaMenuOps USING [Open], TiogaOps USING [FindDef], UserProfile USING [Line], VersionMap USING [Length, Map, MapList, Range, RangeList, RangeToEntry, ShortNameToRanges], VersionMapDefaults USING [GetMapList], ViewerClasses USING [Viewer]; OpenRCommandsImpl: CEDAR MONITOR IMPORTS BasicTime, Commander, FS, IO, Process, Rope, TiogaMenuOps, TiogaOps, UserProfile, VersionMap, VersionMapDefaults SHARES VersionMap = BEGIN SourceFileList: TYPE = LIST OF SourceFileEntry; SourceFileEntry: TYPE = RECORD[ map: VersionMap.Map, name: ROPE, created: BasicTime.GMT, stamp: VersionStamp]; GMT: TYPE = BasicTime.GMT; Map: TYPE = VersionMap.Map; MapList: TYPE = VersionMap.MapList; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; VersionStamp: TYPE = BcdDefs.VersionStamp; NullVersion: VersionStamp = BcdDefs.NullVersion; OpenCommand: Commander.CommandProc = { st: IO.STREAM _ cmd.out; inStream: IO.STREAM _ IO.RIS[cmd.commandLine]; eachFile: PROC = { MyOpen: PROC [def: ROPE _ NIL] = { file: FS.OpenFile _ FS.Open[name: name, wantedCreatedTime: date ! FS.Error => { IF error.code = $unknownFile THEN { IO.PutF[st, "Not found: %g\n", [rope[name]] ]; } ELSE { IO.PutF[st, "%g\n", [rope[error.explanation]] ]; }; result _ $Failure; GO TO exit; }; ]; viewer: ViewerClasses.Viewer _ NIL; name _ FS.GetName[file].fullFName; FS.Close[file]; viewer _ TiogaMenuOps.Open[name]; IF viewer = NIL THEN { IO.PutF[st, "Not found: %g\n", [rope[r]] ]; result _ $Failure; } ELSE { IO.PutF[st, "Opened: %g\n", [rope[r]] ]; result _ NIL; IF Rope.Length[def] # 0 THEN [] _ TiogaOps.FindDef[viewer, def, forwards, feedback]; }; EXITS exit => {}; }; sfl: SourceFileList _ NIL; name: ROPE _ NIL; date: GMT; r: ROPE _ IO.GetTokenRope[inStream, IO.IDProc].token; IF Rope.Length[r] = 0 THEN RETURN; sfl _ FindSource[r]; SELECT TRUE FROM sfl = NIL => { rBase, rExt: ROPE; [rBase, rExt] _ SplitName[r]; IF rExt = NIL THEN { sfl _ FindSource[Rope.Concat[rBase, ".*"]]; [name, date] _ TryExtensions[sfl]; MyOpen[]; } ELSE { sfl _ FindSource[Rope.Concat[rBase, ".mesa"]]; [name, date] _ FindMostRecent[sfl]; MyOpen[rExt]; }; IF name = NIL THEN { IO.PutF[st, "Sorry, '%g' is not in the current Cedar release.\n", [rope[r]]]; result _ $Failure; RETURN; }; }; ENDCASE => { [name, date] _ FindMostRecent[sfl]; MyOpen[]; }; }; DO eachFile[ ! FS.Error => {msg _ error.explanation; result _ $Failed; EXIT}; IO.EndOfStream => EXIT; ]; ENDLOOP; }; FindCommand: Commander.CommandProc = { st: IO.STREAM _ cmd.out; inStream: IO.STREAM _ IO.RIS[cmd.commandLine]; useBin: BOOL _ cmd.procData.clientData = $Bin; eachFile: PROC = { sfl: SourceFileList _ NIL; r: ROPE _ IO.GetTokenRope[inStream, IO.IDProc].token; IF Rope.Length[r] = 0 THEN RETURN; IF NOT Rope.Match["*.*", r] THEN r _ Rope.Concat[r, ".*"]; sfl _ FindSource[r, FALSE, IF useBin THEN $Symbols ELSE $Source]; IF sfl = NIL THEN { IO.PutF[st, "Sorry, '%g' is not in the current Cedar release.\n", [rope[r]] ]; RETURN; }; IO.PutF[st, "%g =>\n", [rope[r]] ]; WHILE sfl # NIL DO IO.PutF[st, " %g\n %g\n", [rope[sfl.first.name]], [time[sfl.first.created]] ]; sfl _ sfl.rest; ENDLOOP; }; DO eachFile[ ! FS.Error => {msg _ error.explanation; result _ $Failed; EXIT}; IO.EndOfStream => EXIT; ]; ENDLOOP; }; FindSource: PROC [short: ROPE, removeDuplDates: BOOL _ TRUE, which: ATOM _ NIL] RETURNS [SourceFileList _ NIL] = TRUSTED { size: INT _ Rope.Length[short]; starPos: INT _ short.Index[0, "*"]; match: BOOL _ starPos # size; hasDot: BOOL _ short.Index[0, "."] # size; rangeList: VersionMap.RangeList _ NIL; head: SourceFileList _ NIL; tail: SourceFileList _ NIL; shortShort: ROPE _ Rope.Flatten[short, 0, starPos]; shortShortLen: INT _ Rope.Length[shortShort]; mapList: MapList _ NIL; IF size = 0 THEN RETURN; IF which = NIL THEN which _ $Source; IF mapList = NIL THEN mapList _ VersionMapDefaults.GetMapList[which]; rangeList _ VersionMap.ShortNameToRanges[mapList, short]; WHILE rangeList # NIL DO range: VersionMap.Range _ rangeList.first; map: Map = range.map; rangeList _ rangeList.rest; Process.CheckForAbort[]; IF match THEN { entries: CARDINAL = VersionMap.Length[map]; IF range.first >= entries THEN LOOP; range.len _ entries - range.first; WHILE range.len # 0 DO fullName: ROPE; stamp: VersionStamp; thisShort: ROPE; created: BasicTime.GMT; [fullName, stamp, created, range] _ VersionMap.RangeToEntry[range]; thisShort _ ShortName[fullName]; IF Rope.Run[shortShort, 0, thisShort, 0, FALSE] # shortShortLen THEN EXIT; IF Rope.Match[short, thisShort, FALSE] THEN { new: SourceFileList _ LIST[[map: range.map, name: fullName, created: created, stamp: stamp]]; IF tail = NIL THEN head _ new ELSE tail.rest _ new; tail _ new; }; ENDLOOP; } ELSE { WHILE range.len # 0 DO new: SourceFileList; fullName: ROPE; stamp: VersionStamp; created: BasicTime.GMT; [fullName, stamp, created, range] _ VersionMap.RangeToEntry[range]; new _ LIST[[map: range.map, name: fullName, created: created, stamp: stamp]]; IF tail = NIL THEN head _ new ELSE tail.rest _ new; tail _ new; ENDLOOP; }; ENDLOOP; RemoveDuplicates[head, removeDuplDates]; RETURN [head]; }; ShortName: PROC [r: ROPE] RETURNS [ROPE] = { first: INT _ 0; last: INT _ Rope.Length[r]; FOR i: INT DECREASING IN [0..last) DO c: CHAR _ r.Fetch[i]; SELECT c FROM '>, '/ => {first _ i+1; EXIT}; '! => last _ i ENDCASE; ENDLOOP; RETURN [r.Substr[first, last - first]] }; SplitName: PROC [name: ROPE] RETURNS [prefix: ROPE _ NIL, ext: ROPE _ NIL] = { dot: INT _ 0; len: INT _ Rope.Length[name]; pos: INT _ len; WHILE (pos _ pos - 1) > 0 DO SELECT Rope.Fetch[name, pos] FROM '! => {name _ Rope.Flatten[name, 0, pos]; len _ pos}; '. => {prefix _ Rope.Flatten[name, 0, pos]; ext _ Rope.Flatten[name, pos+1]; RETURN}; '], '/, '> => EXIT; ENDCASE; ENDLOOP; RETURN [name, NIL]; }; FindMostRecent: PROC [sfl: SourceFileList] RETURNS [name: ROPE _ NIL, date: GMT] = { IF sfl # NIL THEN { date _ sfl.first.created; name _ sfl.first.name; FOR each: SourceFileList _ sfl.rest, each.rest WHILE each # NIL DO eachDate: GMT _ each.first.created; period: INT _ BasicTime.Period[from: date, to: eachDate]; IF period >= 0 THEN { eachName: ROPE _ each.first.name; IF period < 0 OR Rope.Compare[eachName, name, FALSE] = greater THEN { date _ eachDate; name _ eachName; }; }; ENDLOOP; }; }; RemoveDuplicates: PROC [sfl: SourceFileList, removeDuplDates: BOOL] = { WHILE sfl # NIL DO entry: SourceFileEntry _ sfl.first; thisStamp: VersionStamp _ entry.stamp; each: SourceFileList _ sfl.rest; lag: SourceFileList _ sfl; WHILE each # NIL DO next: SourceFileList _ each.rest; SELECT TRUE FROM Rope.Equal[each.first.name, entry.name, FALSE] => lag.rest _ next; removeDuplDates AND each.first.stamp = thisStamp => lag.rest _ next; ENDCASE => lag _ each; each _ next; ENDLOOP; sfl _ sfl.rest; ENDLOOP; }; TryExtensions: PROC [sfl: SourceFileList] RETURNS [ROPE _ NIL, GMT _ BasicTime.nullGMT] = { line: ROPE _ UserProfile.Line["SourceFileExtensions", "mesa tioga df cm config"]; in: STREAM _ IO.RIS[line, NIL]; DO token: ROPE _ IO.GetTokenRope[in, IO.IDProc ! IO.EndOfStream => EXIT].token; currentList: SourceFileList _ NIL; IF Rope.Length[token] = 0 THEN EXIT; FOR each: SourceFileList _ sfl, each.rest WHILE each # NIL DO name: ROPE _ each.first.name; base, ext: ROPE _ NIL; [base, ext] _ SplitName[name]; IF Rope.Equal[ext, token, FALSE] THEN { name _ FS.FileInfo[ name: Rope.Cat[base, ".", token], wantedCreatedTime: each.first.created, remoteCheck: FALSE ! FS.Error => SELECT error.code FROM $unknownFile, $unknownCreatedTime => LOOP; ENDCASE ].fullFName; currentList _ CONS[each.first, currentList]; }; ENDLOOP; IF currentList # NIL THEN RETURN FindMostRecent[currentList]; ENDLOOP; }; Init: PROC = TRUSTED { Commander.Register [ "///Commands/OpenR", OpenCommand, "Opens viewers on Cedar release source files given the short names (.mesa extension is the default). If a short name has multiple long names associated with it, the alternatives are listed, and no viewer is opened for that name."]; Commander.Register [ "///Commands/FindR", FindCommand, "Finds Cedar release source file names given the short names (.mesa extension is the default)"]; Commander.Register [ "///Commands/FindRBin", FindCommand, "Finds Cedar release binary file names given the short names.", $Bin]; }; Init[]; END. nOpenRCommandsImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) July 1, 1985 9:20:03 pm PDT Useful types [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] Handle = REF [in, out, err: STREAM, commandLine,command: ROPE, propertyList: List.AList] No file found as explicitly given, we might need to try some alternatives. At least one match, so open the most recent [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] Handle = REF [in, out, err: STREAM, commandLine,command: ROPE, propertyList: List.AList] make a long name into a short one assumes a valid long name, of course the file in each is more recent or the same date each is more recent OR (same date AND lexically greater name) This routine removes entries with duplicate names an (if removeDuplDates = TRUE) also removes entries with duplicate dates. Κ Ο˜codešœ™Kšœ Οmœ7™BK™/—K˜šΟk ˜ Kšœ žœžœ˜'Kšœžœ˜*Kšœ žœ!˜0Kšžœžœ3˜;Kšžœžœ+žœžœ˜@Kšœžœ˜KšœžœEžœ˜bKšœ žœ˜Kšœ žœ ˜Kšœ žœ˜Kšœ žœK˜[Kšœžœ˜&Kšœžœ ˜K˜—šœžœž˜ KšžœžœžœT˜xKšžœ ˜Kšœž˜K˜—šœ ™ K˜Kšœžœžœžœ˜/šœžœžœ˜Kšœžœžœ˜N—K˜Kšžœžœ žœ˜Kšœžœ˜Kšœ žœ˜#Kšžœžœžœ˜Kšžœžœžœžœ˜šœžœ˜*Kšœ0˜0K˜——šœ&˜&š œžœ žœžœžœžœ™:Kšœ žœžœžœ™X—Kšœžœžœ ˜Kš œ žœžœžœžœ˜.šœ žœ˜šΟnœžœžœžœ˜"šœžœ žœ)˜?šœžœ ˜šžœ˜šžœ˜Kšžœ,˜.K˜—šžœ˜Kšžœ.˜0K˜——Kšœ˜Kšžœžœ˜ K˜—K˜—Kšœžœ˜#Kšœžœ˜"Kšžœ ˜Kšœ!˜!šžœ ž˜šžœ˜Kšžœ)˜+Kšœ˜K˜—šžœ˜Kšžœ&˜(Kšœ žœ˜ šžœž˜Kšœ7˜7—K˜——Kšžœ ˜K˜—Kšœžœ˜Kšœžœžœ˜Kšœžœ˜ Kšœžœžœžœ˜5Kšžœžœžœ˜"Kšœ˜šžœžœž˜šœžœ˜K™JKšœ žœ˜Kšœ˜šžœž˜ šžœ˜Kšœ+˜+Kšœ"˜"K˜ K˜—šžœ˜Kšœ.˜.Kšœ#˜#Kšœ ˜ K˜——šžœžœžœ˜KšžœK˜MKšœ˜Kšžœ˜K˜—K˜—šžœ˜ K™+Kšœ#˜#K˜ K˜——K˜—šž˜˜ Kšœžœ6žœ˜@Kšœžœžœ˜K˜—Kšžœ˜—K˜K˜—šœ&˜&š œžœ žœžœžœžœ™:Kšœ žœžœžœ™X—Kšœžœžœ ˜Kš œ žœžœžœžœ˜.Kšœžœ"˜.šœ žœ˜Kšœžœ˜Kšœžœžœžœ˜5Kšžœžœžœ˜"Kšžœžœžœ˜:Kš œžœžœžœ žœ ˜Ašžœžœžœ˜KšžœL˜NKšžœ˜Kšœ˜—Kšžœ!˜#šžœžœž˜šžœ˜Kšœ˜Kšœ˜Kšœ˜—K˜Kšžœ˜—K˜—šž˜˜ šœžœ6žœ˜@Kšžœžœ˜—K˜—Kšžœ˜—K˜K˜—šŸ œžœ žœžœžœ žœžœžœžœžœ˜zKšœžœ˜Kšœ žœ˜#Kšœžœ˜Kšœžœ˜*Kšœ"žœ˜&Kšœžœ˜Kšœžœ˜Kšœ žœ#˜3Kšœžœ˜-Kšœžœ˜Kšžœ žœžœ˜Kšžœ žœžœ˜$Kšžœ žœžœ0˜EKšœ9˜9šžœ žœž˜Kšœ*˜*K˜Kšœ˜K˜šžœ˜šžœ˜Kšœ žœ˜+Kšžœžœžœ˜$Kšœ"˜"šžœž˜Kšœ žœ˜Kšœ˜Kšœ žœ˜Kšœžœ˜KšœC˜CKšœ ˜ Kšžœ'žœžœžœ˜Jšžœžœžœ˜-šœ˜KšœžœC˜I—Kšžœžœžœ žœ˜3K˜ K˜—Kšžœ˜—K˜—šžœ˜šžœž˜Kšœ˜Kšœ žœ˜Kšœ˜Kšœžœ˜KšœC˜CKšœžœC˜MKšžœžœžœ žœ˜3K˜ Kšž˜—K˜——Kšžœ˜—Kšœ(˜(Kšžœ˜K˜K˜—š Ÿ œžœžœžœžœ˜,Kšœ!™!Kšœ$™$Kšœžœ˜Kšœžœ˜š žœžœž œžœ ž˜%Kšœžœ˜šžœž˜ Kšœžœ˜K˜Kšžœ˜ —Kšžœ˜—Kšžœ ˜&K˜K˜—šŸ œžœžœžœ žœžœžœžœ˜NKšœžœ˜Kšœžœ˜Kšœžœ˜šžœž˜šžœž˜!K˜5KšœNžœ˜VKšœžœ˜Kšžœ˜—Kšžœ˜—Kšžœžœ˜K˜K˜—š Ÿœžœžœžœžœžœ˜Tšžœžœžœ˜Kšœ˜Kšœ˜šžœ,žœžœž˜BKšœ žœ˜#Kšœžœ.˜9šžœ žœ˜Kšœ0™0Kšœ žœ˜!šžœ žœžœ žœ˜EKšœžœ žœ™=Kšœ˜Kšœ˜K˜—K˜—Kšžœ˜—K˜—K˜K˜—šŸœžœ(žœ˜GKšœKžœ,™{šžœžœž˜K˜#K˜&K˜ K˜šžœžœž˜K˜!šžœžœž˜Kšœ(žœ˜BKšœžœ1˜DKšžœ˜—K˜ Kšžœ˜—K˜Kšžœ˜—K˜K˜—š Ÿ œžœžœžœžœžœ˜[KšœžœG˜QKš œžœžœžœžœ˜šž˜Kš œžœžœžœ žœΟr œžœ˜LKšœžœ˜"Kšžœžœžœ˜$šžœ'žœžœž˜=Kšœžœ˜Kšœ žœžœ˜Kšœ˜šžœžœžœ˜'šœžœ ˜Kšœ!˜!Kšœ&˜&Kšœ ž˜šœžœ ˜ šžœ ž˜Kšœ%žœ˜*Kšž˜——Kšœ ˜ —Kšœžœ˜,K˜—Kšžœ˜—Kšžœžœžœžœ˜=Kšžœ˜—Kšœ˜K˜—šŸœžœžœ˜šœ˜K˜!K˜θ—šœ˜K˜!K˜`—šœ˜K˜$K˜?K˜—K˜K˜—Kšœ˜K˜K˜šžœ˜K˜K˜——…—!Θ2