<> <> <> <> <> DIRECTORY Basics USING [BYTE, CARD, Comparison, HighHalf, LongNumber, LowHalf, NonNegative], Convert USING [IntFromRope], IO USING [PutBlock, PutChar, STREAM], IPSkeleton USING [GetSkeleton], IPMaster, IPReal USING [Rational, RationalFromReal], Real USING [FScale, NumberType, RealToPair, RoundLI], Rope USING [ActionType, Concat, Fetch, Length, Map, MaxLen, ROPE, Substr], SymTab USING [Create, Fetch, Ref, Store]; IPMasterImpl: CEDAR PROGRAM IMPORTS Basics, Convert, IPReal, IO, Real, Rope, SymTab, IPSkeleton EXPORTS IPMaster ~ BEGIN OPEN IPMaster; BYTE: TYPE ~ Basics.BYTE; CARD: TYPE ~ Basics.CARD; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; Error: PUBLIC ERROR [error: ErrorDesc] ~ CODE; Bug: PROC [x: ROPE] ~ { ERROR Error[[code: $bug, explanation: x]] }; InvalidIdentifier: PROC [x: ROPE] ~ { ERROR Error[[code: $invalidIdentifier, explanation: x]] }; InvalidString: PROC [x: ROPE] ~ { ERROR Error[[code: $invalidString, explanation: x]] }; InvalidName: PROC [x: ROPE] ~ { ERROR Error[[code: $invalidName, explanation: x]] }; InvalidVersion: PROC [x: ROPE] ~ { ERROR Error[[code: $invalidVersion, explanation: x]] }; EvFromOp: TYPE ~ REF READONLY EvFromOpArray; EvFromOpArray: TYPE ~ PACKED ARRAY Op OF EncodingValue; encodingValueFromOp: EvFromOp ~ NEW[EvFromOpArray = [ nil: nil, get: get, makeveclu: makeveclu, makevec: makevec, shape: shape, getprop: getprop, getp: getp, mergeprop: mergeprop, fget: fget, fset: fset, makesimpleco: makesimpleco, findoperator: findoperator, do: do, dosave: dosave, dosaveall: dosaveall, dosavesimplebody: dosavesimplebody, pop: pop, copy: copy, dup: dup, roll: roll, exch: exch, mark: mark, unmark: unmark, unmark0: unmark0, count: count, nop: nop, error: error, if: if, ifelse: ifelse, ifcopy: ifcopy, eq: eq, gt: gt, ge: ge, and: and, or: or, not: not, type: type, add: add, sub: sub, neg: neg, abs: abs, floor: floor, ceiling: ceiling, trunc: trunc, round: round, mul: mul, div: div, mod: mod, rem: rem, iget: iget, iset: iset, maket: maket, translate: translate, rotate: rotate, scale: scale, scale2: scale2, concat: concat, concatt: concatt, move: move, trans: trans, setxy: setxy, setxyrel: setxyrel, setxrel: setxrel, setyrel: setyrel, getcp: getcp, makepixelarray: makepixelarray, finddecompressor: finddecompressor, extractpixelarray: extractpixelarray, makegray: makegray, findcolor: findcolor, findcoloroperator: findcoloroperator, findcolormodeloperator: findcolormodeloperator, makesampledcolor: makesampledcolor, makesampledblack: makesampledblack, setgray: setgray, setsampledcolor: setsampledcolor, setsampledblack: setsampledblack, moveto: moveto, lineto: lineto, linetox: linetox, linetoy: linetoy, curveto: curveto, conicto: conicto, arcto: arcto, makeoutline: makeoutline, makeoutlineodd: makeoutlineodd, maskfill: maskfill, maskfillparity: maskfillparity, maskrectangle: maskrectangle, startunderline: startunderline, maskunderline: maskunderline, masktrapezoidx: masktrapezoidx, masktrapezoidy: masktrapezoidy, maskstroke: maskstroke, maskstrokeclosed: maskstrokeclosed, maskvector: maskvector, maskdashedstroke: maskdashedstroke, maskpixel: maskpixel, clipoutline: clipoutline, cliprectangle: cliprectangle, maskchar: maskchar, makefont: makefont, findfont: findfont, modifyfont: modifyfont, setfont: setfont, show: show, showandxrel: showandxrel, showandfixedxrel: showandfixedxrel, correctmask: correctmask, correctspace: correctspace, correct: correct, space: space, setcorrectmeasure: setcorrectmeasure, setcorrecttolerance: setcorrecttolerance, beginBody: beginBody, endBody: endBody, beginBlock: beginBlock, endBlock: endBlock, contentInstructions: contentInstructions ]]; OpFromEv: TYPE ~ REF READONLY OpFromEvArray; OpFromEvArray: TYPE ~ PACKED ARRAY EncodingValue OF Op; opFromEncodingValue: OpFromEv ~ InvertEvFromOp[encodingValueFromOp]; InvertEvFromOp: PROC [encodingValueFromOp: EvFromOp] RETURNS [OpFromEv] ~ { opFromEncodingValue: REF OpFromEvArray ~ NEW[OpFromEvArray _ ALL[nil]]; FOR op: Op IN Op DO opFromEncodingValue[encodingValueFromOp[op]] _ op ENDLOOP; RETURN[opFromEncodingValue]; }; EncodingValueFromOp: PUBLIC PROC [op: Op] RETURNS [EncodingValue] ~ { RETURN[encodingValueFromOp[op]]; }; OpFromEncodingValue: PUBLIC PROC [ev: EncodingValue] RETURNS [Op] ~ { RETURN[opFromEncodingValue[ev]]; }; GetOpFromEv: PUBLIC PROC RETURNS [OpFromEv] ~ { RETURN[opFromEncodingValue]; }; NonDefaultingRope: TYPE ~ ROPE _; RopeFromOpArray: TYPE ~ ARRAY Op OF NonDefaultingRope; ropeFromOp: REF RopeFromOpArray ~ NEW[RopeFromOpArray _ [nil: NIL, get: "GET", makeveclu: "MAKEVECLU", makevec: "MAKEVEC", shape: "SHAPE", getprop: "GETPROP", getp: "GETP", mergeprop: "MERGEPROP", fget: "FGET", fset: "FSET", makesimpleco: "MAKESIMPLECO", findoperator: "FINDOPERATOR", do: "DO", dosave: "DOSAVE", dosaveall: "DOSAVEALL", dosavesimplebody: "DOSAVESIMPLEBODY", pop: "POP", copy: "COPY", dup: "DUP", roll: "ROLL", exch: "EXCH", mark: "MARK", unmark: "UNMARK", unmark0: "UNMARK0", count: "COUNT", nop: "NOP", error: "ERROR", if: "IF", ifelse: "IFELSE", ifcopy: "IFCOPY", eq: "EQ", gt: "GT", ge: "GE", and: "AND", or: "OR", not: "NOT", type: "TYPE", add: "ADD", sub: "SUB", neg: "NEG", abs: "ABS", floor: "FLOOR", ceiling: "CEILING", trunc: "TRUNC", round: "ROUND", mul: "MUL", div: "DIV", mod: "MOD", rem: "REM", iget: "IGET", iset: "ISET", maket: "MAKET", translate: "TRANSLATE", rotate: "ROTATE", scale: "SCALE", scale2: "SCALE2", concat: "CONCAT", concatt: "CONCATT", move: "MOVE", trans: "TRANS", setxy: "SETXY", setxyrel: "SETXYREL", setxrel: "SETXREL", setyrel: "SETYREL", getcp: "GETCP", makepixelarray: "MAKEPIXELARRAY", finddecompressor: "FINDDECOMPRESSOR", extractpixelarray: "EXTRACTPIXELARRAY", makegray: "MAKEGRAY", setgray: "SETGRAY", findcolor: "FINDCOLOR", findcoloroperator: "FINDCOLOROPERATOR", findcolormodeloperator: "FINDCOLORMODELOPERATOR", makesampledcolor: "MAKESAMPLEDCOLOR", makesampledblack: "MAKESAMPLEDBLACK", setsampledcolor: "SETSAMPLEDCOLOR", setsampledblack: "SETSAMPLEDBLACK", moveto: "MOVETO", lineto: "LINETO", linetox: "LINETOX", linetoy: "LINETOY", curveto: "CURVETO", conicto: "CONICTO", arcto: "ARCTO", makeoutline: "MAKEOUTLINE", makeoutlineodd: "MAKEOUTLINEODD", maskfill: "MASKFILL", maskfillparity: "MASKFILLPARITY", maskrectangle: "MASKRECTANGLE", startunderline: "STARTUNDERLINE", maskunderline: "MASKUNDERLINE", masktrapezoidx: "MASKTRAPEZOIDX", masktrapezoidy: "MASKTRAPEZOIDY", maskstroke: "MASKSTROKE", maskstrokeclosed: "MASKSTROKECLOSED", maskvector: "MASKVECTOR", maskdashedstroke: "MASKDASHEDSTROKE", maskpixel: "MASKPIXEL", clipoutline: "CLIPOUTLINE", cliprectangle: "CLIPRECTANGLE", maskchar: "MASKCHAR", makefont: "MAKEFONT", findfont: "FINDFONT", modifyfont: "MODIFYFONT", setfont: "SETFONT", show: "SHOW", showandxrel: "SHOWANDXREL", showandfixedxrel: "SHOWANDFIXEDXREL", correctmask: "CORRECTMASK", correctspace: "CORRECTSPACE", space: "SPACE", setcorrectmeasure: "SETCORRECTMEASURE", setcorrecttolerance: "SETCORRECTTOLERANCE", correct: "CORRECT", beginBody: "{", endBody: "}", beginBlock: "BEGIN", endBlock: "END", contentInstructions: "CONTENTINSTRUCTIONS" ]]; opFromRope: SymTab.Ref ~ InvertRopeFromOp[ropeFromOp]; OpFromRopeVal: TYPE ~ REF OpFromRopeValRep; OpFromRopeValRep: TYPE ~ RECORD[op: Op]; InvertRopeFromOp: PROC [ropeFromOp: REF RopeFromOpArray] RETURNS [SymTab.Ref] ~ { opFromRope: SymTab.Ref ~ SymTab.Create[mod: ORD[Op.LAST], case: FALSE]; FOR op: Op IN Op DO key: ROPE ~ ropeFromOp[op]; val: OpFromRopeVal ~ NEW[OpFromRopeValRep _ [op: op]]; IF SymTab.Store[x: opFromRope, key: key, val: val] THEN NULL ELSE Bug["Duplicate name in opFromRope table."]; ENDLOOP; RETURN[opFromRope]; }; RopeFromOp: PUBLIC PROC [op: Op] RETURNS [ROPE] ~ { RETURN[ropeFromOp[op]]; }; OpFromRope: PUBLIC PROC [rope: ROPE] RETURNS [Op] ~ { found: BOOL; val: REF; [found, val] _ SymTab.Fetch[x: opFromRope, key: rope]; IF found THEN WITH val SELECT FROM val: OpFromRopeVal => RETURN[val.op]; ENDCASE => Bug["Bogus value in opFromRope table."]; RETURN[nil]; }; RopeFromImagerVarArray: TYPE ~ ARRAY ImagerVariable OF NonDefaultingRope; ropeFromImagerVar: REF RopeFromImagerVarArray ~ NEW[RopeFromImagerVarArray _ [ DCScpx: "DCScpx", DCScpy: "DCScpy", correctMX: "correctMX", correctMY: "correctMY", T: "T", priorityImportant: "priorityImportant", mediumXSize: "mediumXSize", mediumYSize: "mediumYSize", fieldXMin: "fieldXMin", fieldYMin: "fieldYMin", fieldXMax: "fieldXMax", fieldYMax: "fieldYMax", font: "font", color: "color", noImage: "noImage", strokeWidth: "strokeWidth", strokeEnd: "strokeEnd", underlineStart: "underlineStart", amplifySpace: "amplifySpace", correctPass: "correctPass", correctShrink: "correctShrink", correctTX: "correctTX", correctTY: "correctTY", strokeJoint: "strokeJoint", clipper: "clipper" ]]; RopeFromImagerVariable: PUBLIC PROC [var: ImagerVariable] RETURNS [ROPE] ~ { RETURN[ropeFromImagerVar[var]]; }; MapParts: PUBLIC PROC [base: ROPE, start: INT _ 0, len: INT _ MaxLen, delimiter: CHAR, action: PartActionType] RETURNS [BOOL] ~ { next, pos: INT _ start; -- next = next char index, pos = start of part mapPartsAction: Rope.ActionType ~ { index: INT ~ next; next _ next+1; IF c=delimiter THEN { quit _ action[base: base, start: pos, len: index-pos]; pos _ next }; }; IF Rope.Map[base: base, start: start, len: len, action: mapPartsAction] THEN RETURN[TRUE]; RETURN[action[base: base, start: pos, len: next-pos]]; -- don't forget the last one! }; ValidateIdentifier: PUBLIC PROC [rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { state: {first, rest} _ first; identifierChar: Rope.ActionType ~ { SELECT state FROM first => SELECT c FROM IN['a..'z], IN['A..'Z] => state _ rest; ENDCASE => RETURN[quit: TRUE]; -- illegal first char rest => SELECT c FROM IN['a..'z], IN['A..'Z], IN['0..'9], '- => NULL; ENDCASE => RETURN[quit: TRUE]; -- illegal char ENDCASE => Bug["Undefined state in ValidateIdentifier."]; }; IF Rope.Map[base: rope, start: start, len: len, action: identifierChar] THEN SELECT state FROM first => InvalidIdentifier["Identifier begins with an illegal character."]; rest => InvalidIdentifier["Identifier contains an illegal character."]; ENDCASE => Bug["Undefined state in ValidateIdentifier."]; IF state=first THEN InvalidIdentifier["Identifier is empty."]; }; ValidateName: PUBLIC PROC [rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { parts: INT _ 0; namePart: PartActionType ~ { parts _ parts+1; ValidateIdentifier[base, start, len] }; [] _ MapParts[base: rope, start: start, len: len, delimiter: '/, action: namePart]; IF parts=0 THEN InvalidName["Name is empty."]; }; ValidateString: PUBLIC PROC [rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { state: {run, escape, escape2, extended, extended2} _ run; index: INT _ start; stringChar: Rope.ActionType ~ { SELECT state FROM run => IF c='\377 THEN state _ escape; escape => IF c='\377 THEN state _ escape2 ELSE state _ run; escape2 => IF c='\000 THEN state _ extended ELSE quit _ TRUE; extended => IF c='\377 THEN state _ escape ELSE state _ extended2; extended2 => IF c='\377 THEN quit _ TRUE ELSE state _ extended; ENDCASE => Bug["Undefined state in ValidateString."]; index _ index+1; }; IF Rope.Map[base: rope, start: start, len: len, action: stringChar] THEN InvalidString["String contains an invalid escape sequence."]; IF state=run OR state=extended THEN NULL ELSE InvalidString["String ends in the middle of an escape sequence."]; }; ValidateNumber: PROC [rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { chars: INT _ 0; numberChar: Rope.ActionType ~ { chars _ chars+1; RETURN[quit: NOT (c IN['0..'9])] }; IF Rope.Map[base: rope, start: start, len: len, action: numberChar] THEN InvalidVersion["Version number contains an illegal character."]; IF chars=0 THEN InvalidVersion["Version number part is empty."]; }; ValidateVersion: PUBLIC PROC [rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { parts: NAT _ 0; versionPart: PartActionType ~ { parts _ parts+1; ValidateNumber[base, start, len] }; [] _ MapParts[base: rope, start: start, len: len, delimiter: '., action: versionPart]; SELECT parts FROM 0 => InvalidVersion["Version number is empty."]; 1 => InvalidVersion["Version number has no dot."]; 2 => NULL; ENDCASE => InvalidVersion["Version number has too many parts."]; }; VersionFromRope: PUBLIC PROC [rope: ROPE, start: INT _ 0, len: INT _ MaxLen] RETURNS [version: Version] ~ { parts: NAT _ 0; versionPart: PartActionType ~ { val: INT ~ Convert.IntFromRope[Rope.Substr[base, start, len]]; IF val NOT IN CARDINAL THEN InvalidVersion["Version number part is too big."]; SELECT parts FROM 0 => version.major _ val; 1 => version.minor _ val; ENDCASE => Bug["ValidateVersion failed."]; parts _ parts+1; }; ValidateVersion[rope, start, len]; [] _ MapParts[base: rope, start: start, len: len, delimiter: '., action: versionPart]; IF parts#2 THEN Bug["ValidateVersion failed."]; }; CompareVersion: PUBLIC PROC [a, b: Version] RETURNS [Basics.Comparison] ~ { SELECT a.major FROM RETURN[less]; >b.major => RETURN[greater]; ENDCASE => SELECT a.minor FROM RETURN[less]; >b.minor => RETURN[greater]; ENDCASE => RETURN[equal]; }; PutShortNumber: PUBLIC PROC [stream: STREAM, n: ShortNumber] ~ { x: [0..77777B] ~ n-ShortNumber.FIRST; IO.PutChar[stream, VAL[x/400B]]; IO.PutChar[stream, VAL[x MOD 400B]]; }; PutShortOp: PUBLIC PROC [stream: STREAM, op: ShortEncodingValue] ~ { x: [0..37B] ~ ORD[op]; IO.PutChar[stream, VAL[200B+x]]; }; PutLongOp: PUBLIC PROC [stream: STREAM, op: EncodingValue] ~ { x: [0..17777B] ~ ORD[op]; IO.PutChar[stream, VAL[240B+x/400B]]; IO.PutChar[stream, VAL[x MOD 400B]]; }; PutShortSequence: PUBLIC PROC [ stream: STREAM, seq: SequenceType, len: ShortSequenceLength] ~ { x: [0..37B] ~ ORD[seq]; IO.PutChar[stream, VAL[300B+x]]; IO.PutChar[stream, VAL[len]]; }; PutLongSequence: PUBLIC PROC [ stream: STREAM, seq: SequenceType, len: LongSequenceLength] ~ { x: [0..37B] ~ ORD[seq]; lenH: [0..377B] ~ Basics.HighHalf[len]; -- bounds check lenL: CARDINAL ~ Basics.LowHalf[len]; IO.PutChar[stream, VAL[340B+x]]; IO.PutChar[stream, VAL[lenH]]; IO.PutChar[stream, VAL[lenL/400B]]; IO.PutChar[stream, VAL[lenL MOD 400B]]; }; <<>> BytesInInt: PUBLIC PROC [val: INT] RETURNS [ByteCount] ~ { x: CARD ~ IF val<0 THEN -(val+1) ELSE val; SELECT x FROM <00000080H => RETURN[1]; <00008000H => RETURN[2]; <00800000H => RETURN[3]; ENDCASE => RETURN[4]; }; PutIntBytes: PUBLIC PROC [stream: STREAM, val: INT, len: ByteCount] ~ { bytes: Basics.LongNumber ~ [li[val]]; IF len>3 THEN IO.PutChar[stream, VAL[bytes.hh]]; IF len>2 THEN IO.PutChar[stream, VAL[bytes.hl]]; IF len>1 THEN IO.PutChar[stream, VAL[bytes.lh]]; IF len>0 THEN IO.PutChar[stream, VAL[bytes.ll]]; }; PutByte: PUBLIC PROC [stream: STREAM, byte: BYTE] ~ { IO.PutChar[stream, VAL[byte]]; }; PutOp: PUBLIC PROC [stream: STREAM, op: Op] ~ { ev: EncodingValue ~ encodingValueFromOp[op]; IF ev IN ShortEncodingValue THEN PutShortOp[stream, ev] ELSE PutLongOp[stream, ev]; }; PutSequence: PUBLIC PROC [stream: STREAM, seq: SequenceType, len: INT] ~ { IF len IN ShortSequenceLength THEN PutShortSequence[stream, seq, len] ELSE PutLongSequence[stream, seq, len]; }; PutInt: PUBLIC PROC [stream: STREAM, n: INT] ~ { IF n IN ShortNumber THEN PutShortNumber[stream, n] ELSE { len: ByteCount ~ BytesInInt[n]; PutShortSequence[stream, sequenceInteger, len]; PutIntBytes[stream: stream, val: n, len: len]; }; }; PutRational: PUBLIC PROC [stream: STREAM, n, d: INT] ~ { len: ByteCount ~ MAX[BytesInInt[n], BytesInInt[d]]; PutShortSequence[stream, sequenceRational, len+len]; PutIntBytes[stream: stream, val: n, len: len]; PutIntBytes[stream: stream, val: d, len: len]; }; tryDecimal: BOOL _ FALSE; tryRational: BOOL _ TRUE; decimalPrecision: NAT _ 6; maxRelativeError: REAL _ 0.00001; PutReal: PUBLIC PROC [stream: STREAM, val: REAL] ~ { <> r: REAL _ val; n: INT _ 0; d: INT _ 1; IF ABS[r]>INT.LAST THEN { tail: NAT _ 0; -- number of trailing zero bytes WHILE ABS[r]>INT.LAST DO r _ r/256; tail _ tail+1 ENDLOOP; PutSequence[stream, sequenceInteger, 4+tail]; PutIntBytes[stream: stream, val: Real.RoundLI[r], len: 4]; THROUGH [0..tail) DO IO.PutChar[stream, VAL[0]] ENDLOOP; RETURN; }; IF (n _ Real.RoundLI[r])=r THEN { PutInt[stream, n]; RETURN }; IF tryDecimal THEN { type: Real.NumberType; exp10: INTEGER; [type: type, fr: n, exp10: exp10] _ Real.RealToPair[r: r, precision: decimalPrecision]; IF type=$normal AND exp10 IN[-9..0) THEN { e: NAT _ -exp10; WHILE (n MOD 10)=0 AND e>0 DO n _ n/10; e _ e-1 ENDLOOP; THROUGH [0..e) DO d _ d*10 ENDLOOP; PutRational[stream, n, d]; RETURN; }; }; IF tryRational THEN { rat: IPReal.Rational _ IPReal.RationalFromReal[r]; IF rat.denominator # 0 AND ABS[REAL[rat.numerator]/REAL[rat.denominator] - r] <= maxRelativeError * ABS[r] THEN { IF rat.denominator = 1 THEN PutInt[stream, rat.numerator] ELSE PutRational[stream, rat.numerator, rat.denominator]; RETURN; }; }; THROUGH [0..30) DO r _ r*2; d _ d*2; IF (n _ Real.RoundLI[r])=r THEN EXIT; REPEAT FINISHED => { d _ INT.LAST; n _ Real.RoundLI[d*val] }; ENDLOOP; PutRational[stream, n, d]; }; PutSequenceRope: PUBLIC PROC [stream: STREAM, seq: SequenceType, rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { count: INT _ 0; charAction: Rope.ActionType ~ { IO.PutChar[stream, c]; count _ count+1 }; size: INT ~ Rope.Length[rope]; length: INT ~ MIN[MAX[0, len], Basics.NonNegative[size-Basics.NonNegative[start]]]; PutSequence[stream, seq, length]; [] _ Rope.Map[base: rope, start: start, len: length, action: charAction]; IF count#length THEN ERROR Error[[code: $bug, explanation: "Bug in PutSequenceRope."]]; }; PutSequenceText: PUBLIC PROC [stream: STREAM, seq: SequenceType, text: REF READONLY TEXT, start: NAT _ 0, len: NAT _ MaxTextLen] ~ { length: INT ~ MIN[len, NAT[text.length-start]]; PutSequence[stream, seq, length]; IO.PutBlock[self: stream, block: text, startIndex: start, count: length]; }; PutIdentifier: PUBLIC PROC [stream: STREAM, rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { ValidateIdentifier[rope, start, len]; PutSequenceRope[stream, sequenceIdentifier, rope, start, len]; }; PutString: PUBLIC PROC [stream: STREAM, rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { ValidateString[rope, start, len]; PutSequenceRope[stream, sequenceString, rope, start, len]; }; PutName: PUBLIC PROC [stream: STREAM, rope: ROPE, start: INT _ 0, len: INT _ MaxLen] ~ { count: INT _ 0; namePart: PartActionType ~ { PutIdentifier[stream, base, start, len]; count _ count+1 }; [] _ MapParts[base: rope, start: start, len: len, delimiter: '/, action: namePart]; PutInt[stream, count]; PutOp[stream, makevec]; }; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <> <> <> <> <> <<};>> <<>> GetToken: PUBLIC PROC [encoding: ROPE, start: INT] RETURNS [token: Token, next: INT] ~ { token _ []; next _ start; { GetByte: PROC RETURNS [BYTE] ~ INLINE { i: INT ~ next; next _ i+1; RETURN[ORD[CHAR[Rope.Fetch[encoding, i]]]]; }; b0: BYTE ~ GetByte[]; SELECT b0 FROM <200B => { token.num _ ShortNumber.FIRST+(b0*400B+GetByte[]); token.type _ num}; <240B => { token.op _ VAL[b0 MOD 40B]; token.type _ op}; <300B => { token.op _ VAL[(b0 MOD 40B)*400B+GetByte[]]; token.type _ op}; <340B => { token.seq _ VAL[b0 MOD 40B]; token.len _ GetByte[]; token.type _ seq}; ENDCASE => { long: Basics.LongNumber _ [li[0]]; long.hl _ GetByte[]; long.lh _ GetByte[]; long.ll _ GetByte[]; token.seq _ VAL[b0 MOD 40B]; token.len _ long.li; token.type _ seq}; }; }; SkipToEndOfBody: PUBLIC PROC [encoding: ROPE, start: INT] RETURNS [next: INT] ~ { next _ start; DO token: Token; [token, next] _ GetToken[encoding, next]; next _ next+token.len; SELECT token.op FROM beginBody => next _ SkipToEndOfBody[encoding, next]; endBody => EXIT; ENDCASE; ENDLOOP; }; GetSequenceRope: PUBLIC PROC [encoding: ROPE, start, len: INT] RETURNS [rope: ROPE, next: INT] ~ { rope _ Rope.Substr[encoding, start, len]; next _ start+len; DO peekToken: Token; peekStart: INT; [peekToken, peekStart] _ GetToken[encoding, next]; IF peekToken.seq=sequenceContinued THEN { rope _ Rope.Concat[rope, Rope.Substr[encoding, peekStart, peekToken.len]]; next _ peekStart+peekToken.len; } ELSE EXIT; ENDLOOP; }; GetSkeleton: PUBLIC PROC [master: ROPE, start: INT] RETURNS [IPMaster.SkeletonRecord] ~ { RETURN [IPSkeleton.GetSkeleton[master, start].skeleton^]}; IntFromLong: PROC [long: Basics.LongNumber] RETURNS [INT] ~ INLINE { RETURN [long.li] }; IntFromSequenceData: PUBLIC PROC [text: REF READONLY TEXT, start: NAT _ 0, len: NAT _ NAT.LAST] RETURNS [INT] ~ { b: ARRAY [0..4) OF BYTE _ ALL[0]; j: NAT _ 4; len _ MIN[len, NAT[text.length-start]]; FOR i: NAT DECREASING IN[start..start+len) DO b[j _ j-1] _ ORD[text[i]]; <> ENDLOOP; IF b[j] >= 200B THEN {WHILE j > 0 DO b[j _ j-1] _ 377B ENDLOOP}; RETURN [IntFromLong[[bytes[hh: b[0], hl: b[1], lh: b[2], ll: b[3]]]]]; }; <<>> RealFromSequenceData: PUBLIC PROC [text: REF READONLY TEXT, start: NAT _ 0, len: NAT _ NAT.LAST] RETURNS [val: REAL _ 0] ~ { len _ MIN[len, NAT[text.length-start]]; IF ORD[text[start]]<200B THEN { FOR i: NAT IN[start..start+len) DO val _ Real.FScale[val, 8]+ORD[text[i]] ENDLOOP; } ELSE { FOR i: NAT IN[start..start+len) DO val _ Real.FScale[val, 8]+(377B-ORD[text[i]]) ENDLOOP; val _ -1-val; }; }; END.