ISFromTioga.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
MKaplan, September 13, 1985 0:46:13 am PDT
DIRECTORY
Commander USING [CommandProc, Register],
CommandTool USING [ArgumentVector, Parse, Failed],
Rope USING [ROPE, Equal, Concat, Length, Fetch, Substr],
FileNames USING [ResolveRelativePath, IsAPattern, IsADirectory, ConvertToSlashFormat, CurrentWorkingDirectory],
TiogaAccess USING [Reader, FromFile, DoneWith, Get, Peek, GetExternalProp, GetNodeProps, EndOf, Look, Looks, TiogaChar, SkipToNextNode],
Process USING [CheckForAbort],
FS USING [ErrorDesc, Error, StreamOpen],
IO USING [STREAM, PutRope, PutChar, PutF, --int,-- char, rope, atom, Close--, Flush--],
Atom USING [PropList, DottedPair, GetPName, MakeAtom, GetPropFromList];
ISFromTioga: CEDAR PROGRAM
IMPORTS Commander, CommandTool, Rope, FileNames, TiogaAccess, Process, FS, IO, Atom
EXPORTS ExportsList
~ BEGIN
TiogaToISProc: Commander.CommandProc = {
[cmd: REF CommandObject] RETURNS [result: REFNIL, msg: ROPENIL]
CommandObject = [
in, out, err: STREAM, commandLine, command: ROPE,
propertyList: List.AList, procData: CommandProcHandle]
destinationDirectory: Rope.ROPENIL;
leftArrowExists: BOOL;
FSErrorMsg1: PROC [error: FS.ErrorDesc] RETURNS [Rope.ROPE] = {
SELECT error.group FROM
lock => RETURN[" -- locked!"];
ENDCASE =>
IF error.code = $unknownFile
THEN RETURN [" -- not found!"]
ELSE RETURN[Rope.Concat["\n -- FS.Error: ", error.explanation]];
};
HandleAFile: PROC [to, from: Rope.ROPE] = {
Process.CheckForAbort[];
cmd.out.PutF[" %g ← %g", [rope[to]], [rope[from]]];
{ENABLE
FS.Error =>
IF error.group # bug THEN {msg ← FSErrorMsg1[error]; GO TO skipIt};
s: IO.STREAMFS.StreamOpen[to, $create];
r: TiogaAccess.Reader ← TiogaAccess.FromFile[from];
d: INT --← 0--;
EmitNodes: PROC ~ {
DO
noLooks: TiogaAccess.Looks = ALL[FALSE];
looks: TiogaAccess.Looks ← noLooks;
started: BOOLFALSE;
format: ATOM ← TiogaAccess.Peek[r].format;
comment: BOOL ← TiogaAccess.Peek[r].comment;
secondaryTags: LIST OF ATOMNIL;
tag: Rope.ROPE ← TiogaAccess.GetExternalProp[$ISTag, Atom.GetPropFromList[TiogaAccess.GetNodeProps[r], $ISTag]];
EmitBindings: PROC [t: ATOM, propList: Atom.PropList] ~ {
FOR l: Atom.PropList ← propList, l.rest UNTIL l=NIL DO
binding: Atom.DottedPair ← l.first;
IF BindingTag[NARROW[binding.key]]=t THEN
IO.PutF[s, "%g%g=%g ",
IO.rope[IF t=$PROPERTIES THEN "PROPERTIES." ELSE ""], IO.atom[NARROW[binding.key]], IO.rope[TiogaAccess.GetExternalProp[NARROW[binding.key], binding.val]]];
ENDLOOP;
IF t=$PROPERTIES AND comment THEN
IO.PutF[s, "PROPERTIES.Comment=<TRUE> "];
};
BindingTag: PROC [b: ATOM] RETURNS [ATOM] ~ {
n: Rope.ROPE = Atom.GetPName[b];
i: INT ← 0;
l: INT = Rope.Length[n];
WHILE i<l DO
IF Rope.Fetch[n,i]='. THEN
RETURN[Atom.MakeAtom[Rope.Substr[base: n, len: i]]] ELSE
i ← i+1;
ENDLOOP;
RETURN[$PROPERTIES];
};
SetEmitted: PROC [tag: ATOM] ~ {
secondaryTags ← CONS[tag, secondaryTags];
};
WasEmitted: PROC [t: ATOM] RETURNS [BOOLFALSE] ~ {
l: LIST OF ATOM ← secondaryTags;
UNTIL l=NIL DO
IF l.first=t THEN RETURN[TRUE] ELSE l←l.rest;
ENDLOOP;
};
IF Rope.Equal[tag, "<Literal>"] THEN --Just copy node contents to IS file--
BEGIN
c: TiogaAccess.TiogaChar;
c.endOfNode ← FALSE;
UNTIL c.endOfNode DO
c ← TiogaAccess.Get[r];
IO.PutChar[s, c.char];
ENDLOOP;
d ← c.deltaLevel;
END ELSE {
IO.PutF[s, "{"];
IF tag=NIL THEN tag ← "PARA"; --This node was originated in Tioga. Make it logical--
IF NOT Rope.Equal[tag, "<Set>"] THEN BEGIN --Set nodes have no primary (or other) tags. They are just collections of their contents--
contents: REF;
IO.PutF[s, "%g$ ", IO.rope[tag]];
IF (contents ← Atom.GetPropFromList[TiogaAccess.GetNodeProps[r], $ISContents])#NIL THEN
IO.PutF[s, "%g ", IO.rope[TiogaAccess.GetExternalProp[$ISContents, contents]]];
END;
IF format#NIL THEN IO.PutF[s, "STYLE$ STYLE.FORMAT=<%g> ", IO.atom[format]];
FOR l: Atom.PropList ← TiogaAccess.GetNodeProps[r], l.rest UNTIL l=NIL DO
IF l.first.key#$ISTag --AND l.first.key#$ISContents-- THEN BEGIN
n: ATOM = BindingTag[NARROW[l.first.key]];
IF NOT WasEmitted[n] THEN BEGIN
IF NOT Rope.Equal[Atom.GetPName[n], tag] THEN
IO.PutF[s, "%g$ ", IO.atom[n]];
SetEmitted[n];
EmitBindings[n,l];
END;
END;
ENDLOOP;
IF NOT WasEmitted[$PROPERTIES] AND comment THEN
IO.PutRope[s, "PROPERTIES$ PROPERTIES.Comment=<TRUE> "];
IO.PutChar[s, '\n];
IF Rope.Equal[tag, "PARA"] THEN BEGIN
DO
c: TiogaAccess.TiogaChar ← TiogaAccess.Get[r];
IF looks#c.looks THEN {
looks ← c.looks;
IF looks#noLooks THEN {
IF started THEN IO.PutRope[s, ">}\n"] ELSE started ← TRUE;
IO.PutRope[s, "{CHARS$ LOOKS$ "];
FOR l: TiogaAccess.Look IN [FIRST[TiogaAccess.Look]..LAST[TiogaAccess.Look]] DO
IF looks[l] THEN IO.PutF[s, "LOOKS.%g=TRUE ", IO.char[l]];
ENDLOOP;
IO.PutChar[s, '<]
}
ELSE {
IF started THEN IO.PutRope[s, ">}\n"] ELSE started ← TRUE;
IO.PutRope[s, "{CHARS$ <"]
}
}
ELSE IF NOT started THEN {
IO.PutRope[s, "{CHARS$ <"];
started ← TRUE
};
IO.PutChar[s, c.char];
IF c.char='> THEN IO.PutChar[s, c.char];
IF c.endOfNode THEN {
d ← c.deltaLevel;
EXIT
};
ENDLOOP;
IO.PutRope[s, ">}"];
END ELSE
IF Rope.Equal[tag, "CHARS"] THEN BEGIN
IO.PutRope[s, "<"];
BEGIN
c: TiogaAccess.TiogaChar;
c.endOfNode ← FALSE;
UNTIL c.endOfNode DO
c ← TiogaAccess.Get[r];
IO.PutChar[s, c.char];
ENDLOOP;
d ← c.deltaLevel;
END;
IO.PutRope[s, ">"];
END
ELSE
d ← TiogaAccess.SkipToNextNode[r]; --No text in unknown nodes--
WHILE d<1 DO {
d ← d+1;
IO.PutChar[s, '}];
}
ENDLOOP;
IO.PutChar[s, '\n];
IF TiogaAccess.EndOf[r] THEN EXIT;
};
ENDLOOP;
};
IO.PutRope[s," {DOCUMENT$\n"];
EmitNodes[];
IO.PutRope[s, "}\n"];
IO.Close[s];
TiogaAccess.DoneWith[r];
EXITS
skipIt => {};
};
cmd.out.PutRope["\n"];
};
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd
! CommandTool.Failed => {msg ← errorMsg; GO TO Die}];
nArgs: NAT ← argv.argc;
{
Process switches
i: NAT ← 1;
length: INT;
Bump: PROC [scratch: NAT] = {
FOR j: NAT IN (scratch..nArgs) DO
argv[j - 1] ← argv[j];
ENDLOOP;
nArgs ← nArgs - 1;
};
WHILE i < nArgs DO
length ← argv[i].Length[];
SELECT TRUE FROM
length = 0 => Bump[i];
argv[i].Fetch[0] = '- => {
FOR j: INT IN [1..length) DO
SELECT argv[i].Fetch[j] FROM
no switches...
ENDCASE;
ENDLOOP;
Bump[i];
};
ENDCASE => i ← i + 1;
ENDLOOP;
}; -- end of switch processing
First find out whether there is a ← anywhere. If there is, it must be the second arg.
leftArrowExists ← nArgs >= 3 AND Rope.Equal[argv[2], "←"];
FOR i: NAT IN [1..nArgs) DO
argv[i] ← FileNames.ConvertToSlashFormat[FileNames.ResolveRelativePath[argv[i]]];
ENDLOOP;
IF leftArrowExists
THEN {
IF FileNames.IsADirectory[argv[1]]
THEN destinationDirectory ← argv[1]
ELSE {
IF nArgs # 4 OR FileNames.IsAPattern[argv[1]] OR FileNames.IsAPattern[argv[3]]
THEN RETURN[$Failure, "Bad syntax for copying a file"];
HandleAFile[from: argv[3], to: argv[1]];
RETURN[IF msg # NIL THEN $Failure ELSE NIL, msg];
};
}
ELSE destinationDirectory ←
FileNames.ConvertToSlashFormat[FileNames.CurrentWorkingDirectory[]];
EXITS
Die => result ← $Failure;
};
Commander.Register[
"ISFromTioga", TiogaToISProc, "ISFromTioga newFile ← oldFile", $ISFromTioga];
END.