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];
TiogaToISProc: Commander.CommandProc = {
[cmd: REF CommandObject] RETURNS [result: REF ← NIL, msg: ROPE ← NIL]
CommandObject = [
in, out, err: STREAM, commandLine, command: ROPE,
propertyList: List.AList, procData: CommandProcHandle]
destinationDirectory: Rope.ROPE ← NIL;
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.STREAM ← FS.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: BOOL ← FALSE;
format: ATOM ← TiogaAccess.Peek[r].format;
comment: BOOL ← TiogaAccess.Peek[r].comment;
secondaryTags: LIST OF ATOM ← NIL;
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 [
BOOL←
FALSE] ~ {
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];
};
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];