VersionMapCommandsImpl.mesa
Russ Atkinson, December 12, 1983 3:49 pm
Paul Rovner, December 12, 1983 11:32 am
DIRECTORY
AMModel USING [MostRecentNamedContext, RootContext, Section, Source],
AMModelBridge USING [FrameFromContext],
AMViewerOps USING [ReportProc, SourceFromTV],
AMTypes USING [TV],
BasicTime USING [FromPupTime],
BcdDefs USING [NullVersion, VersionStamp],
Commander USING [CommandProc, Handle, Register],
FileViewerOps USING [OpenSource],
IO USING [EndOfStream, GetTokenRope, IDProc, Put, PutRope, RIS, STREAM, time],
List USING [Assoc],
ProcessProps USING [GetPropList],
Rope USING [Concat, Fetch, Flatten, Index, Match, ROPE, Run, Size, Substr],
VersionMap
USING
[Length, Map, MapList, Range, RangeList, RangeToEntry, ShortNameToRanges],
VersionMapDefaults USING [GetMapList],
WorldVM USING [LocalWorld, World];
VersionMapCommandsImpl:
CEDAR
MONITOR
IMPORTS
AMModel, AMModelBridge, AMViewerOps, BasicTime, Commander, FileViewerOps, List, IO, ProcessProps, Rope, VersionMap, VersionMapDefaults, WorldVM
SHARES VersionMap
= BEGIN OPEN AMViewerOps, FileViewerOps;
Useful types
Section: TYPE = AMModel.Section;
Source: TYPE = AMModel.Source;
SourceFileList: TYPE = LIST OF SourceFileEntry;
SourceFileEntry: TYPE = RECORD[map: VersionMap.Map, name: ROPE, stamp: VersionStamp];
Map: TYPE = VersionMap.Map;
MapList: TYPE = VersionMap.MapList;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
TV: TYPE = AMTypes.TV;
VersionStamp:
TYPE = BcdDefs.VersionStamp;
NullVersion: VersionStamp = BcdDefs.NullVersion;
World: TYPE = WorldVM.World;
FileVersion: PROC
[name: ROPE, desiredVersion: VersionStamp ← NullVersion]
RETURNS [version: VersionStamp ← NullVersion] = {
returns NullVersion if any errors occur (like missing file)
proc: FS.InfoProc = {
PROC[fullFName, attachedTo: ROPE, created: BasicTime.GMT, bytes: INT, keep: CARDINAL]
RETURNS [continue: BOOL];
IF bytes > 0 THEN version ← [0, 0, BasicTime.ToPupTime[created]];
continue ← version # desiredVersion;
};
FS.EnumerateForInfo[name, proc ! FS.Error => CONTINUE];
};
FindSource:
PROC
[short: ROPE, mapList: MapList ← NIL, firstOnly: BOOL ← FALSE]
RETURNS [SourceFileList ← NIL] = TRUSTED {
size: INT ← short.Size[];
match: BOOL ← short.Index[0, "*"] # size;
hasDot: BOOL ← short.Index[0, "."] # size;
rangeList: VersionMap.RangeList ← NIL;
head,tail: SourceFileList ← NIL;
shortShort: ROPE ← NIL;
IF size = 0 THEN RETURN;
IF match
THEN {
shortShort ← Rope.Flatten[short, 0, short.Index[0, "*"]];
IF shortShort.Size[] = 0 THEN RETURN;
}
ELSE {
IF
NOT hasDot
THEN {
short ← short.Concat[".mesa"];
size ← short.Size[];
};
};
IF mapList = NIL THEN mapList ← VersionMapDefaults.GetMapList[$Source];
rangeList ← VersionMap.ShortNameToRanges[mapList, short];
WHILE rangeList #
NIL
DO
range: VersionMap.Range ← rangeList.first;
map: Map = range.map;
rangeList ← rangeList.rest;
IF
NOT match
THEN {
WHILE range.len # 0
DO
new: SourceFileList;
fullName: ROPE;
stamp: VersionStamp;
[fullName, stamp, range] ← VersionMap.RangeToEntry[range];
new ← LIST[[map: range.map, name: fullName, stamp: stamp]];
IF tail = NIL THEN head ← new ELSE tail.rest ← new;
tail ← new;
ENDLOOP;
}
ELSE {
entries: CARDINAL = VersionMap.Length[map];
shortShortLen: INT = Rope.Size[shortShort];
IF range.first >= entries THEN LOOP;
range.len ← entries - range.first;
WHILE range.len # 0
DO
fullName: ROPE;
stamp: VersionStamp;
thisShort: ROPE;
[fullName, stamp, 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, stamp: stamp]];
IF tail = NIL THEN head ← new ELSE tail.rest ← new;
tail ← new;
};
ENDLOOP;
};
ENDLOOP;
RETURN [head];
};
OpenViewerFromEntry: PROC [entry: SourceFileEntry] = TRUSTED {
full: ROPE ← entry.name;
short: ROPE ← ShortName[full];
stamp: VersionStamp ← FileVersion[short, entry.stamp];
readOnly: BOOL ← TRUE;
IF stamp # NullVersion THEN {
file may be on local disk, so let's try it
IF stamp = entry.stamp THEN {
hooray, we can use the local file
full ← short;
readOnly ← FALSE};
};
OpenSource[full, 0, 0, GetOutStream[]];
};
ShortName:
PROC [r:
ROPE]
RETURNS [
ROPE] = {
make a long name into a short one
assumes a valid long name, of course
first: INT ← 0;
last: INT ← r.Size[];
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]]
};
OpenCommand: Commander.CommandProc =
TRUSTED {
[cmd: Handle]
=> [in, out, err: STREAM, commandLine,command: ROPE, propertyList: List.AList]
st: IO.STREAM ← cmd.out;
dir: ROPE ← NIL;
each:
PROC [r:
ROPE] =
TRUSTED {
inStream: IO.STREAM ← IO.RIS[r];
DO
sfl: SourceFileList ← NIL;
r ← IO.GetTokenRope[inStream, IO.IDProc ! IO.EndOfStream => EXIT].token;
IF r.Size[] = 0 THEN RETURN;
sfl ← RemoveDuplicates[FindSource[r, NIL, FALSE]];
IF sfl =
NIL
THEN {
st.PutRope["Sorry, '"];
st.PutRope[r];
st.PutRope["' is not in the current Cedar release.\n"];
LOOP};
IF sfl.rest #
NIL
THEN {
st.PutRope["Sorry, multiple versions for '"];
st.PutRope[r];
st.PutRope["':"];
WHILE sfl #
NIL
DO
st.PutRope["\n "];
st.PutRope[sfl.first.name];
st.PutRope["\n "];
st.Put[IO.time[BasicTime.FromPupTime[sfl.first.stamp.time]]];
sfl ← sfl.rest;
ENDLOOP;
st.PutRope["\n"];
LOOP};
OpenSource[sfl.first.name, 0, 0, GetOutStream[]]; -- OpenViewerFromEntry[sfl.first];
st.PutRope["\n"];
ENDLOOP;
};
each[cmd.commandLine];
};
OpenGlobalCommand: Commander.CommandProc =
TRUSTED {
[cmd: Handle]
=> [in, out, err: STREAM, commandLine,command: ROPE, propertyList: List.AList]
st: IO.STREAM ← cmd.out;
dir: ROPE ← NIL;
each:
PROC [r:
ROPE] =
TRUSTED {
inStream: IO.STREAM ← IO.RIS[r];
gf: TV ← NIL;
DO
fileName: ROPE ← NIL;
r ← IO.GetTokenRope[inStream, IO.IDProc ! IO.EndOfStream => EXIT].token;
IF r.Size[] = 0 THEN RETURN;
gf ← AMModelBridge.FrameFromContext
[AMModel.MostRecentNamedContext
[name: r, context: AMModel.RootContext[WorldVM.LocalWorld[]]]];
IF gf =
NIL
THEN {
st.PutRope[r];
st.PutRope[" can not be found.\n"];
LOOP;
};
fileName ← SourceFromTV[gf, ClarkKent].name;
IF fileName #
NIL
THEN {
OpenSource[fileName, 0, 0, GetOutStream[]];
st.PutRope["\n"];
};
ENDLOOP;
};
each[cmd.commandLine];
};
GetOutStream:
PROC
RETURNS[s:
IO.
STREAM ←
NIL] =
TRUSTED {
WITH List.Assoc[$CommanderHandle, ProcessProps.GetPropList[]]
SELECT
FROM
cmd: Commander.Handle => s ← cmd.out;
ENDCASE;
};
ClarkKent: AMViewerOps.ReportProc =
TRUSTED {
[msg: ROPE, severity: Severity]
=> [in, out, err: STREAM, commandLine,command: ROPE, propertyList: List.AList]
WITH List.Assoc[$CommanderHandle, ProcessProps.GetPropList[]]
SELECT
FROM
cmd: Commander.Handle => {
st: IO.STREAM ← cmd.out;
st.PutRope[msg];
};
ENDCASE;
};
RemoveDuplicates:
PROC [sfl: SourceFileList]
RETURNS [new: SourceFileList ←
NIL] = {
IF sfl #
NIL
THEN {
entry: SourceFileEntry ← sfl.first;
thisStamp: VersionStamp ← entry.stamp;
each: SourceFileList ← sfl.rest ← RemoveDuplicates[sfl.rest];
lag: SourceFileList ← new ← sfl;
WHILE each #
NIL
DO
next: SourceFileList ← each.rest;
IF each.first.stamp = thisStamp
THEN lag.rest ← next
ELSE lag ← each;
each ← next;
ENDLOOP;
};
};
FindCommand: Commander.CommandProc =
TRUSTED {
[cmd: Handle]
=> [in, out, err: STREAM, commandLine,command: ROPE, propertyList: List.AList]
st: IO.STREAM ← cmd.out;
each:
PROC [r:
ROPE] =
TRUSTED {
inStream: IO.STREAM ← IO.RIS[r];
DO
sfl: SourceFileList ← NIL;
r ← IO.GetTokenRope[inStream, IO.IDProc ! IO.EndOfStream => EXIT].token;
IF r.Size[] = 0 THEN RETURN;
sfl ← RemoveDuplicates[FindSource[r, NIL, FALSE]];
IF sfl =
NIL
THEN {
st.PutRope["Sorry, '"];
st.PutRope[r];
st.PutRope["' is not in the current Cedar release.\n"];
LOOP};
st.PutRope[r];
st.PutRope[" =>\n"];
sfl ← FindSource[r, NIL, FALSE];
IF sfl =
NIL
THEN {
st.PutRope["Sorry, '"];
st.PutRope[r];
st.PutRope["' is not in the current Cedar release.\n"];
LOOP};
WHILE sfl #
NIL
DO
st.PutRope[" "];
st.PutRope[sfl.first.name];
st.PutRope["\n "];
st.Put[IO.time[BasicTime.FromPupTime[sfl.first.stamp.time]]];
st.PutRope["\n"];
sfl ← sfl.rest;
ENDLOOP;
ENDLOOP;
};
each[cmd.commandLine];
};
Init:
PROC =
TRUSTED {
Commander.Register [
"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. No spelling correction is performed."];
Commander.Register [
"openG", OpenGlobalCommand,
"Opens source for named global frame."];
Commander.Register [
"findr", FindCommand,
"Finds Cedar release source file names given the short names (.mesa extension is the default). No spelling correction is performed."];
};
Init[];