-- file SakuraDriver.Mesa
-- last modified by Satterthwaite, January 13, 1981 9:29 AM
-- last edit by Russ Atkinson, 9-Jul-81 14:50:32
-- last edited by Suzuki, 7-Mar-82 21:36:56
DIRECTORY
Convert: TYPE USING [MapValue, Value],
ConvertUnsafe: TYPE USING [ToRope],
IOStream: TYPE USING [Handle, Close, CreateFileStream, SetLength],
PPLeaves: TYPE USING [ISEIndex, HTIndex, LTIndex],
-- PPP1 USING [OpenTest, CloseTest],
PPRopeFile: TYPE USING [Create],
Rope: TYPE USING [Concat, Equal, Flatten, Index, Map, Ref, Size, Substr, Text],
SafeStorage: TYPE USING [ReclaimCollectibleObjects, SetCollectionInterval],
SakuraCommon,
SakuraOps: TYPE USING [ParseStream, SetLog],
SakuraRewrite: TYPE USING [PutChoiceDecl, Rewrite],
SakuraTree: TYPE USING [Handle, Link],
SakuraTreeOps: TYPE USING [Initialize, Finalize],
SakuraUtil: TYPE USING [PrettyPrint],
TTY: TYPE USING [Create, Destroy, GetLine, Handle, PutChar, PutCR];
SakuraDriver: MONITOR
IMPORTS Convert, ConvertUnsafe, IOStream, SakuraOps,
SakuraRewrite, SakuraTreeOps, SakuraUtil, PPRopeFile, Rope, SafeStorage, TTY
EXPORTS SakuraCommon =
BEGIN OPEN Tree: SakuraTree, SakuraTreeOps, PPLeaves, TTY;
-- main loop
CR: CHARACTER = 15C;
Unimplemented: SIGNAL = CODE;
tty: PUBLIC Handle ← Create["Sakura"];
CharAction: PROC [c: CHARACTER] RETURNS [BOOLEAN] = {
PutChar[tty, c]; RETURN [FALSE]};
Char1: PROC [c: CHARACTER] = {PutChar[tty, c]};
PutRope: PROC [r: Rope.Ref, newLine: BOOLEAN ← FALSE] = {
[] ← Rope.Map[base: r, action: CharAction];
IF newLine THEN PutChar[tty, CR];
};
GetFileName: PROC [prompt,suffix,last: Rope.Ref] RETURNS [Rope.Text] = {
line: STRING ← [80];
pos: LONG INTEGER ← 0;
name: Rope.Ref ← NIL;
PutRope[prompt];
GetLine[tty, line];
IF line.length=0 THEN RETURN[NIL];
name ← ConvertUnsafe.ToRope[line];
IF name.Equal["$"] THEN
name ← last.Substr[0, last.Index[0, "."]];
pos ← name.Index[0, "."];
IF pos = name.Size[] THEN {
name ← name.Concat[suffix]};
RETURN [name.Flatten[]];
};
GetInfo: PROC [t: Tree.Link] RETURNS [info: LONG INTEGER] = {
DO WITH t SELECT FROM
hti: HTIndex => info ← hti.index;
lti: LTIndex => info ← lti.index;
x: Tree.Handle =>
{info ← x.info;
IF info = 0 THEN
FOR i: NAT IN [1..x.sonLimit) WHILE info = 0 DO
info ← GetInfo[x[i]]
ENDLOOP};
ENDCASE => info ← 0;
EXIT
ENDLOOP};
GetAttrs: PROC [t: Tree.Link] RETURNS [a1: BOOLEAN, a2: BOOLEAN, a3: BOOLEAN] = {
WITH t SELECT FROM
x: Tree.Handle => RETURN [x.attr[1], x.attr[2], x.attr[3]];
ENDCASE => a1 ← a2 ← a3 ← FALSE};
SetExtension: PROC [name: STRING, ext: STRING] = {
IF name = NIL OR ext = NIL OR name.length = 0 OR ext.length = 0 THEN RETURN;
FOR i: NAT IN [0..name.length) DO
IF name[i] = '. THEN RETURN;
ENDLOOP;
FOR i: NAT IN [0..ext.length) DO
name[name.length] ← ext[i];
name.length ← name.length + 1;
ENDLOOP;
};
TreeComp: PROC [out: IOStream.Handle, t1,t2: Tree.Link] RETURNS [BOOLEAN] = {
oops: LONG INTEGER ← 0;
IF t1 = t2 THEN RETURN [TRUE];
WITH t1 SELECT FROM
hti1: HTIndex => {
WITH t2 SELECT FROM
hti2: HTIndex => IF Rope.Equal[hti1.name, hti2.name] THEN RETURN [TRUE];
ise: ISEIndex => IF Rope.Equal[hti1.name, ise] THEN RETURN [TRUE];
ENDCASE;
oops ← hti1.index};
lti1: LTIndex => {
WITH t2 SELECT FROM
lti2: LTIndex => IF Rope.Equal[lti1.literal, lti2.literal] THEN RETURN [TRUE];
ENDCASE;
oops ← lti1.index};
x1: Tree.Handle => {
WITH t2 SELECT FROM
x2: Tree.Handle => {
same: BOOLEAN ← x1.name = x2.name AND
x1.sonLimit = x2.sonLimit AND x1.attr = x2.attr;
FOR i: NAT IN [1..x1.sonLimit) WHILE same DO
same ← TreeComp[out, x1[i], x2[i]];
ENDLOOP;
IF same THEN RETURN [TRUE]};
ENDCASE;
oops ← GetInfo[t1]};
ise1: ISEIndex => {
WITH t2 SELECT FROM
hti2: HTIndex => IF Rope.Equal[ise1, hti2.name] THEN RETURN [TRUE];
ise2: ISEIndex => IF Rope.Equal[ise1, ise2] THEN RETURN [TRUE];
ENDCASE;
PutRope["Atomic difference, no index"];
PutCR[tty]};
ENDCASE => ERROR;
PutRope["Difference found near source index "];
Convert.MapValue[Char1, [signed[oops]]];
PutCR[tty];
RETURN [FALSE];
};
croaker: PROC = {[] ← SafeStorage.ReclaimCollectibleObjects[]};
oldTree: Tree.Link ← NIL;
newTree: Tree.Link ← NIL;
Main: PUBLIC ENTRY PROC = {
DO -- just keep processing the files
in, out: IOStream.Handle ← NIL;
source, name, tree, check: Rope.Ref ← NIL;
oldTree ← newTree ← NIL;
PutCR[tty];
name ← GetFileName["Input file: ", ".sak", NIL ! ANY => EXIT];
IF name=NIL THEN EXIT;
in ← IOStream.CreateFileStream[name, read
! ANY => {PutRope["Can't open '"];
PutRope[LOOPHOLE[name]];
PutChar[tty, '']; PutCR[tty]; LOOP}];
tree ← GetFileName["Output file: ", ".mesa", name ! ANY => LOOP];
out ← IOStream.CreateFileStream[tree, write];
IOStream.SetLength[out, 0];
source ← PPRopeFile.Create[in, 4096, 4, TRUE].rope;
-- PPP1.OpenTest[];
oldTree ← SakuraOps.ParseStream[source, out, FALSE];
-- PPP1.CloseTest[];
SakuraTreeOps.Initialize[];
oldTree ← SakuraRewrite.Rewrite[oldTree];
oldTree ← SakuraRewrite.PutChoiceDecl[oldTree];
SakuraOps.SetLog[out];
SakuraUtil.PrettyPrint[oldTree];
SakuraOps.SetLog[NIL];
SakuraTreeOps.Finalize[];
IOStream.Close[in];
IOStream.Close[out];
ENDLOOP;
TTY.Destroy[tty]};
[] ← SafeStorage.SetCollectionInterval[1000000];
END.