IPScanImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Eric Nickell, November 22, 1988 4:10:08 am PST
Bob Coleman, April 23, 1990 4:45:45 pm PDT
DIRECTORY
IPScan,
FS USING [Error, FileInfo],
IPMaster,
Rope USING [Find, Run, Size, Substr],
RopeFile USING [Create];
IPScanImpl: CEDAR PROGRAM
IMPORTS FS, IPMaster, Rope, RopeFile
EXPORTS IPScan
~ BEGIN
OPEN IPScan;
stackMax: NAT ~ 1000;
OpAction: TYPE ~ RECORD [pop: NAT ← stackMax, push, requireStackEmpty: BOOLFALSE];
opAction: ARRAY Op OF OpAction ~ [
abs: [pop: 1, push: TRUE],
add: [pop: 2, push: TRUE],
alternatemetrics: [],
and: [pop: 2, push: TRUE],
arcto: [pop: 5, push: TRUE],
beginBlock: [pop: 0, requireStackEmpty: TRUE],
beginBody: [pop: 0, requireStackEmpty: TRUE],
ceiling: [pop: 1, push: TRUE],
clipoutline: [pop: 1],
cliprectangle: [pop: 4],
concat: [pop: 2, push: TRUE],
concatt: [pop: 1],
conicto: [pop: 6, push: TRUE],
contentInstructions: [pop: 0, requireStackEmpty: TRUE],
copy: [],
correct: [pop: 0, requireStackEmpty: TRUE],
correctmask: [pop: 0],
correctspace: [pop: 2],
count: [pop: 0, push: TRUE],
curveto: [pop: 7, push: TRUE],
div: [pop: 2, push: TRUE],
do: [],
dosave: [],
dosaveall: [],
dosavesimplebody: [pop: 0, requireStackEmpty: TRUE],
dup: [pop: 0, push: TRUE],
endBlock: [pop: 0],
endBody: [pop: 0],
eq: [pop: 2, push: TRUE],
error: [pop: 2],
exch: [],
extractpixelarray: [pop: 2, push: TRUE],
fget: [pop: 1, push: TRUE],
findcolor: [pop: 1, push: TRUE],
findcolormodeloperator: [pop: 1, push: TRUE],
findcoloroperator: [pop: 1, push: TRUE],
finddecompressor: [pop: 1, push: TRUE],
findfont: [pop: 1, push: TRUE],
findoperator: [pop: 1, push: TRUE],
floor: [pop: 1, push: TRUE],
fset: [pop: 2],
ge: [pop: 2, push: TRUE],
get: [pop: 2, push: TRUE],
getcp: [],
getp: [pop: 2, push: TRUE],
getprop: [],
gt: [pop: 2, push: TRUE],
if: [pop: 1, requireStackEmpty: TRUE],
ifcopy: [],
ifelse: [pop: 1, requireStackEmpty: TRUE],
iget: [pop: 1, push: TRUE],
iset: [pop: 2],
lineto: [pop: 3, push: TRUE],
linetox: [pop: 2, push: TRUE],
linetoy: [pop: 2, push: TRUE],
makefont: [pop: 1, push: TRUE],
makegray: [pop: 1, push: TRUE],
makeoutline: [pop: 1, push: TRUE], --Special case!
makeoutlineodd: [pop: 1, push: TRUE], --Special case!
makepixelarray: [pop: 7, push: TRUE],
makesampledblack: [pop: 3, push: TRUE],
makesampledcolor: [pop: 3, push: TRUE],
makesimpleco: [pop: 0],
maket: [pop: 6, push: TRUE],
makevec: [pop: 1, push: TRUE], --Special case!
makeveclu: [],
mark: [],
maskchar: [pop: 1], --Actually [2, 1], but the push is the fd already on the stack
maskdashedstroke: [pop: 4],
maskfill: [pop: 1],
maskfillparity: [pop: 1],  --??
maskpixel: [pop: 1],
maskrectangle: [pop: 4],
maskstroke: [pop: 1],
maskstrokeclosed: [pop: 1],
masktrapezoidx: [pop: 6],
masktrapezoidy: [pop: 6],
maskunderline: [pop: 2],
maskvector: [pop: 4],
mergeprop: [pop: 2, push: TRUE],
mod: [pop: 2, push: TRUE],
modifyfont: [pop: 2, push: TRUE],
move: [pop: 0],
moveto: [pop: 2, push: TRUE],
mul: [pop: 2, push: TRUE],
neg: [pop: 1, push: TRUE],
nil: [],
nop: [pop: 0],
not: [pop: 1, push: TRUE],
or: [pop: 2, push: TRUE],
pop: [pop: 1],
rem: [pop: 2, push: TRUE],
roll: [],
rotate: [pop: 1, push: TRUE],
round: [pop: 1, push: TRUE],
scale: [pop: 1, push: TRUE],
scale2: [pop: 2, push: TRUE],
setcorrectmeasure: [pop: 2],
setcorrecttolerance: [pop: 2],
setfont: [pop: 1],
setgray: [pop: 1],
setsampledblack: [pop: 3],
setsampledcolor: [pop: 3],
setxrel: [pop: 1],
setxy: [pop: 2],
setxyrel: [pop: 2],
setyrel: [pop: 1],
shape: [],
show: [pop: 1],
showandfixedxrel: [pop: 2],
showandxrel: [pop: 1],
showbackward: [pop: 1],  --??
space: [pop: 1],
startunderline: [pop: 0],
sub: [pop: 2, push: TRUE],
trans: [pop: 0],
translate: [pop: 2, push: TRUE],
trunc: [pop: 1, push: TRUE],
type: [pop: 1, push: TRUE],
unmark: [],
unmark0: [pop: 1]
];
allSeqs: PUBLIC LIST OF Seq ~ LIST [sequenceString, sequenceInteger, sequenceInsertMaster, sequenceRational, sequenceIdentifier, sequenceComment, sequenceContinued, sequenceLargeVector, sequencePackedPixelVector, sequenceCompressedPixelVector, sequenceInsertFile, sequenceAdaptivePixelVector, sequenceCCITT4PixelVector];
allOps: PUBLIC LIST OF Op ~ LIST [
nil,
BASE primitives
get, makeveclu, makevec, shape, getprop, getp, mergeprop, fget, fset,
makesimpleco, do, dosave, dosaveall, dosavesimplebody, findoperator,
pop, copy, dup, roll, exch, mark, unmark, unmark0, count, nop, error,
if, ifelse, ifcopy, eq, gt, ge, and, or, not, type,
add, sub, neg, abs, floor, ceiling, trunc, round, mul, div, mod, rem,
IMAGE primitives
iget, iset, maket, translate, rotate, scale, scale2, concat,
concatt, move, trans, setxy, setxyrel, setxrel, setyrel, getcp,
makepixelarray, extractpixelarray, finddecompressor,
makegray, findcolor, findcoloroperator, findcolormodeloperator,
makesampledcolor, makesampledblack, setgray, setsampledcolor, setsampledblack,
moveto, lineto, linetox, linetoy, curveto, conicto, arcto,
makeoutline, makeoutlineodd, maskfill, maskfillparity, maskrectangle,
startunderline, maskunderline, masktrapezoidx, masktrapezoidy,
maskstroke, maskstrokeclosed, maskvector, maskdashedstroke, maskpixel,
clipoutline, cliprectangle,
maskchar, makefont, findfont, modifyfont, alternatemetrics, setfont,
show, showbackward, showandxrel, showandfixedxrel,
correctmask, correctspace, space, setcorrectmeasure, setcorrecttolerance, correct,
Symbols
beginBody, endBody, beginBlock, endBlock, contentInstructions
];
maxHeaderLength: INT ← 200;
IPRopeFromName: PUBLIC PROC [xeroxName: ROPE] RETURNS [header, ip: ROPE] ~ {
prefix: ROPE ~ "Interpress/Xerox/";
inFullFName: ROPE ~ FS.FileInfo[xeroxName].fullFName;
inRope: ROPE ~ RopeFile.Create[name: inFullFName, raw: TRUE];
headerLength: INT ~ Rope.Find[Rope.Substr[inRope, 0, maxHeaderLength], " "];
IF headerLength<0 OR Rope.Run[s1: inRope, s2: prefix] # Rope.Size[prefix]
THEN FS.Error[error: [group: user, code: $NotIP, explanation: "Not an interpress master."]]
ELSE RETURN [
header: Rope.Substr[inRope, 0, headerLength],
ip: Rope.Substr[inRope, headerLength+1]
];
};
ScanRope: PUBLIC PROC [ip: ROPE, ops: LIST OF Op ← NIL, seqs: LIST OF Seq ← NIL, nums: BOOLFALSE, action: ScanProc] ~ {
stopIndex: INT ~ ip.Size[];
earlyQuit: BOOLFALSE;
index: INT ← 0;
seqIndex, tokenIndex: INTINT.LAST;
num: INTEGER ← stackMax;
seq: Seq ← nil;
token: IPMaster.Token ← [];
stk: ARRAY [0..stackMax) OF INT; --For interpress stack objects, starting pos to build object
stkSize: NAT ← 0;
Establish the arrays we'll use to determine whether or not to
do: RECORD [ops: ARRAY Op OF BOOL, seqs: ARRAY Seq OF BOOL, nums: BOOL] ← [ALL[FALSE], ALL[FALSE], nums];
FOR each: LIST OF Op ← ops, each.rest UNTIL each=NIL DO
do.ops[each.first] ← TRUE;
ENDLOOP;
FOR each: LIST OF Seq ← seqs, each.rest UNTIL each=NIL DO
do.seqs[each.first] ← TRUE;
ENDLOOP;
Main Loop:
WHILE index < stopIndex DO
tokenIndex ← index;
[token, index] ← IPMaster.GetToken[encoding: ip, start: index];
IF seq#nil THEN {
IF token.seq=sequenceContinued
THEN {
index ← index + token.len;
LOOP;
}
ELSE {
IF do.seqs[seq] THEN earlyQuit ← action[min: seqIndex, max: tokenIndex, seq: seq];
IF earlyQuit THEN EXIT;
seq ← nil;
};
};
stk[stkSize] ← tokenIndex; --This is above the top of the stack
SELECT token.type FROM
op => {
op: IPMaster.Op ~ IPMaster.OpFromEncodingValue[token.op];
pop: NAT ~ opAction[op].pop + (SELECT op FROM
makeoutline, makeoutlineodd, makevec => num,
ENDCASE => 0
);
punt: BOOL ← stkSize < pop OR (opAction[op].requireStackEmpty AND stkSize > pop);
min: INT ~ IF punt THEN tokenIndex ELSE stk[stkSize ← stkSize-pop];
IF do.ops[op] THEN earlyQuit ← action[min: min, max: index, op: op, punt: punt];
IF earlyQuit THEN EXIT;
IF punt THEN stkSize ← 0;
SELECT TRUE FROM
punt => stkSize ← 0;
opAction[op].push => stkSize ← stkSize+1; --N.B. no push on punts
ENDCASE;
};
num => {
num ← token.num;
stkSize ← stkSize+1;
IF do.nums THEN earlyQuit ← action[min: tokenIndex, max: index, num: num];
IF earlyQuit THEN EXIT;
};
seq => {
punt: BOOLFALSE;
index ← index + token.len;
seqIndex ← tokenIndex;
SELECT seq ← token.seq FROM
sequenceAdaptivePixelVector, sequenceCCITT4PixelVector, sequenceCompressedPixelVector, sequenceIdentifier, sequenceInteger, sequenceLargeVector, sequencePackedPixelVector, sequenceRational, sequenceString => stkSize ← stkSize+1; --Push
sequenceInsertFile, sequenceInsertMaster => {
punt ← TRUE;
stkSize ← 0;
};
sequenceComment => NULL;  --Ignore
nil, sequenceContinued => ERROR;
ENDCASE => ERROR;
};
ENDCASE => ERROR;
ENDLOOP;
};
END.