IPMiscImpl:
CEDAR
PROGRAM
IMPORTS FileIO, IO, IPEncoding, Rope, RopeIO, RopeReader
EXPORTS IPMisc
= BEGIN OPEN IPEncoding;
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Rational: TYPE = IPBasic.Rational;
BodyOp:
PROC[token: Token]
RETURNS[
BOOL] = {
RETURN[
SELECT token.op
FROM
makesimpleco, makeco, makecompiledimage, dosavesimplebody, dobody, dosavebody, dosaveallbody, if, ifelse, ifcopy, loop, correct => TRUE, ENDCASE => FALSE];
};
InhibitNewLine:
PROC[token: Token]
RETURNS[
BOOL] = {
SELECT token.op
FROM
scale, scale2, rotate, translate, makevec, makeveclu => RETURN[TRUE];
makesimpleco, makeco, makecompiledimage, dosavesimplebody, dobody, dosavebody, dosaveallbody, if, ifelse, ifcopy, loop, correct => RETURN[TRUE];
ENDCASE => RETURN[FALSE];
};
ToWritten:
PUBLIC
PROC[from:
ROPE, to:
ROPE, tick:
PROC ←
NIL] = {
reader: Reader = OpenReader[from];
writer: Writer = OpenWriter[to, "Written"];
writer.stream.PutRope["-- "];
writer.stream.PutRope[from];
writer.stream.PutRope[" -> "];
writer.stream.PutRope[to];
writer.stream.PutRope[" -- \n"];
WriteWritten[reader, writer, tick];
CloseReader[reader];
CloseWriter[writer];
};
WriteWritten:
PROC[reader: Reader, writer: Writer, tick:
PROC] = {
token: Token ← nullToken;
prevToken: Token ← nullToken;
nest: INT ← 0;
page: INT ← 0;
FOR index:
INT ← reader.GetStartingIndex[], token.next
DO
token ← reader.GetToken[index];
IF token.type=eof THEN EXIT;
IF (token.op=iget
OR token.op=iset)
AND prevToken.type=number
THEN {
writer.stream.PutRope["--"];
writer.stream.PutRope[
SELECT prevToken.number
FROM
0 => "DCScpx", 1 => "DCScpy", 2 => "correctMX", 3 => "correctMY",
4 => "T", 5 => "priorityImportant", 6 => "mediumXSize", 7 => "mediumYSize",
8 => "fieldXMin", 9 => "fieldYMin", 10 => "fieldXMax", 11 => "fieldYMax",
12 => "showVec", 13 => "color", 14 => "noImage", 15 => "strokeWidth",
16 => "strokeEnd", 17 => "underlineStart", 18 => "amplifySpace",
19 => "correctPass", 20 => "correctShrink", 21 => "correctTX", 22 => "correctTY",
ENDCASE => "???"];
writer.stream.PutRope["-- "];
};
[] ← EncodeToken[reader, writer, token];
SELECT token.op
FROM
beginBody => {
IF nest=0
THEN {
IF tick#NIL THEN tick[];
IF page=0 THEN writer.stream.PutRope["-- Preamble -- "]
ELSE writer.stream.Put[IO.rope["-- Page "], IO.int[page], IO.rope[" -- "]];
};
nest ← nest+1;
};
endBody => {
nest ← nest-1;
IF nest=0 THEN page ← page+1;
};
ENDCASE;
IF token.type=op
AND
NOT InhibitNewLine[token]
THEN {
writer.stream.PutChar['\n];
THROUGH [0..nest) DO writer.stream.PutRope[" "] ENDLOOP;
};
IF token.type=rational
THEN {
r: Rational = reader.GetRational[token];
n: REAL = r.num; d: REAL = r.den;
writer.stream.PutRope["--("];
IF d#0 THEN writer.stream.Put[IO.real[n/d]]
ELSE writer.stream.PutRope["???"];
writer.stream.PutRope[")-- "];
};
prevToken ← token;
ENDLOOP;
};
ToEncoded:
PUBLIC
PROC[from:
ROPE, to:
ROPE, tick:
PROC ←
NIL] = {
reader: Reader = OpenReader[from];
writer: Writer = OpenWriter[to, "Xerox"];
WriteEncoded[reader, writer, tick];
CloseReader[reader];
CloseWriter[writer];
};
WriteEncoded:
PROC[reader: Reader, writer: Writer, tick:
PROC ←
NIL] = {
index: INT ← reader.GetStartingIndex[];
DO token: Token = reader.GetToken[index];
SELECT token.type
FROM
op =>
SELECT token.op
FROM
beginBlock, endBlock => index ← EncodeToken[reader, writer, token];
beginBody => { index ← EncodeBody[reader, writer, token];
IF tick#NIL THEN tick[] };
ENDCASE => ERROR;
comment, insertFile => index ← EncodeToken[reader, writer, token];
eof => EXIT;
ENDCASE => ERROR;
ENDLOOP;
};
ReaderForWritten:
PROC[file:
ROPE]
RETURNS[Reader] = {
rope: ROPE = RopeIO.FromFile[file];
rr: RopeReader.Ref = RopeReader.Create[];
RopeReader.SetPosition[rr, rope, 0];
RETURN[CreateReader["Written", rr]];
};
ReaderForRope:
PROC[rope:
ROPE]
RETURNS[Reader] = {
rr: RopeReader.Ref = RopeReader.Create[];
RopeReader.SetPosition[rr, rope, 0];
RETURN[CreateReader["Written", rr]];
};
RopeToMaster:
PUBLIC
PROC[rope:
ROPE, masterName:
ROPE] = {
reader: Reader = ReaderForRope[rope];
writer: Writer = OpenWriter[masterName, "Xerox"];
WriteEncoded[reader, writer];
CloseReader[reader];
CloseWriter[writer];
};
EncodeToken:
PROC[reader: Reader, writer: Writer, token: Token]
RETURNS[
INT] = {
SELECT token.type
FROM
op => writer.PutOp[token.op];
number => writer.PutInt[token.number];
int => { i: INT = reader.GetInt[token]; writer.PutInt[i] };
rational => { r: Rational = reader.GetRational[token]; writer.PutRational[r] };
real => { r: REAL = reader.GetReal[token]; writer.PutReal[r] };
identifier, string, comment, insertFile, largeVec => {
rope: ROPE = reader.GetRope[token]; writer.PutRope[token.type, rope] };
ENDCASE => ERROR;
RETURN[token.next];
};
SkipToken:
PROC[reader: Reader, token: Token]
RETURNS[
INT] = {
IF token.type=eof THEN ERROR
ELSE RETURN[token.next];
};
EncodeBody:
PROC[reader: Reader, writer: Writer, begin: Token]
RETURNS[
INT] = {
index: INT ← begin.next;
IF begin.op#beginBody THEN ERROR;
writer.PutOp[beginBody];
DO token: Token = reader.GetToken[index];
SELECT token.op
FROM
beginBody => index ← EncodeBodyAndOp[reader, writer, token];
endBody => { index ← token.next; EXIT };
beginVec => index ← EncodeVec[reader, writer, token];
endVec => ERROR;
ENDCASE =>
IF BodyOp[token]
THEN index ← EncodeOpAndBody[reader, writer, token]
ELSE index ← EncodeToken[reader, writer, token];
ENDLOOP;
writer.PutOp[endBody];
RETURN[index];
};
EncodeVec:
PROC[reader: Reader, writer: Writer, begin: Token]
RETURNS[
INT] = {
index: INT ← begin.next;
k: INT ← 0; -- number of elements
IF begin.op#beginVec THEN ERROR;
DO token: Token = reader.GetToken[index];
SELECT token.op
FROM
beginBody => index ← EncodeBodyAndOp[reader, writer, token];
endBody => ERROR;
beginVec => index ← EncodeVec[reader, writer, token];
comma => { index ← token.next; k ← k+1 };
endVec => { index ← token.next; EXIT };
ENDCASE =>
IF BodyOp[token]
THEN index ← EncodeOpAndBody[reader, writer, token]
ELSE index ← EncodeToken[reader, writer, token];
IF k=0 AND token.type#comment THEN k ← 1;
ENDLOOP;
writer.PutInt[k];
writer.PutOp[makevec];
RETURN[index];
};
EncodeBodyAndOp:
PROC[reader: Reader, writer: Writer, begin: Token]
RETURNS[
INT] = {
after: INT = SkipBody[reader, begin];
token: Token = reader.GetToken[after];
IF BodyOp[token]
THEN {
writer.PutOp[token.op];
IF EncodeBody[reader, writer, begin]#after THEN ERROR;
RETURN[token.next];
}
ELSE ERROR;
};
EncodeOpAndBody:
PROC[reader: Reader, writer: Writer, begin: Token]
RETURNS[
INT] = {
IF BodyOp[begin]
THEN {
token: Token = reader.GetToken[begin.next];
writer.PutOp[begin.op];
RETURN[EncodeBody[reader, writer, token]];
}
ELSE ERROR;
};
SkipBody:
PROC[reader: Reader, begin: Token]
RETURNS[
INT] = {
index: INT ← begin.next;
IF begin.op#beginBody THEN ERROR;
DO token: Token = reader.GetToken[index];
IF token.type=eof THEN ERROR;
SELECT token.op
FROM
beginBody => index ← SkipBody[reader, token];
endBody => RETURN[token.next];
beginVec => index ← SkipVec[reader, token];
comma => ERROR;
endVec => ERROR;
ENDCASE => index ← SkipToken[reader, token];
ENDLOOP;
};
SkipVec:
PROC[reader: Reader, begin: Token]
RETURNS[
INT] = {
index: INT ← begin.next;
IF begin.op#beginVec THEN ERROR;
DO token: Token = reader.GetToken[index];
IF token.type=eof THEN ERROR;
SELECT token.op
FROM
beginBody => index ← SkipBody[reader, token];
endBody => ERROR;
beginVec => index ← SkipVec[reader, token];
endVec => RETURN[token.next];
ENDCASE => index ← SkipToken[reader, token];
ENDLOOP;
};
ReplaceExtension:
PROC[name, newExtension:
ROPE]
RETURNS[
ROPE] = {
length: INT = name.Length[];
lastDot: INT ← length;
FOR i:
INT
DECREASING
IN[0..length)
DO
IF name.Fetch[i]='. THEN { lastDot ← i; EXIT };
REPEAT FINISHED => ERROR;
ENDLOOP;
RETURN[name.Replace[start: lastDot+1, with: newExtension]];
};
ToDecimal:
PROC[fromName:
ROPE] = {
toName: ROPE = ReplaceExtension[fromName, "Decimal"];
in: STREAM = FileIO.Open[fromName];
out: STREAM = FileIO.Open[toName, overwrite];
UNTIL in.EndOf[]
DO
c: CHAR = in.GetChar[];
out.Put[IO.int[LOOPHOLE[c, CARDINAL]], IO.char[' ]];
ENDLOOP;
in.Close[]; out.Close[];
};
ToOctal:
PROC[fromName:
ROPE] = {
toName: ROPE = ReplaceExtension[fromName, "Octal"];
in: STREAM = FileIO.Open[fromName];
out: STREAM = FileIO.Open[toName, overwrite];
UNTIL in.EndOf[]
DO
c: CHAR = in.GetChar[];
out.PutF["%03b ", IO.int[LOOPHOLE[c, CARDINAL]]];
ENDLOOP;
in.Close[]; out.Close[];
};
END.