DIRECTORY Ascii, ByteBlt, Inline, String; StringImpl: PROGRAM IMPORTS ByteBlt, Inline, String EXPORTS String = PUBLIC BEGIN OPEN String; StringBoundsFault: SIGNAL [s: LONG STRING] RETURNS [ns: LONG STRING] = CODE; AppendChar: PROCEDURE [s: LONG STRING, c: CHARACTER] = BEGIN IF s = NIL THEN RETURN; UNTIL s.length < s.maxlength DO temp: LONG STRING _ SIGNAL StringBoundsFault[s]; IF temp = NIL THEN RETURN; s _ temp; ENDLOOP; s[s.length] _ c; s.length _ s.length + 1; RETURN END; AppendString: PROCEDURE [to: LONG STRING, from: LONG STRING] = BEGIN n: CARDINAL; IF to = NIL OR from = NIL THEN RETURN; WHILE from.length + to.length > to.maxlength DO temp: LONG STRING _ SIGNAL StringBoundsFault[to]; IF temp = NIL THEN EXIT; -- just fill in as much as fits to _ temp; ENDLOOP; n _ MIN[from.length, LOOPHOLE[to.maxlength - to.length, CARDINAL]]; IF to.length MOD 2 = 0 THEN Inline.LongCOPY[ from: @from.text, to: to + SIZE[StringBody[to.length]], nwords: SIZE[StringBody[n]]-SIZE[StringBody[0]]] ELSE [] _ ByteBlt.ByteBlt[ from: [ blockPointer: LOOPHOLE[@from.text], startIndex: 0, stopIndexPlusOne: n], to: [ blockPointer: LOOPHOLE[@to.text], startIndex: to.length, stopIndexPlusOne: to.length + n]]; to.length _ to.length + n; RETURN END; Equal: PROCEDURE [s1, s2: LONG STRING] RETURNS [BOOLEAN] = BEGIN i: CARDINAL; IF s1 = NIL AND s2 = NIL THEN RETURN[TRUE]; IF s1 = NIL OR s2 = NIL OR s1.length # s2.length THEN RETURN[FALSE]; FOR i IN [0..s1.length) DO IF s1[i] # s2[i] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] END; Equivalent: PROCEDURE [s1, s2: LONG STRING] RETURNS [BOOLEAN] = BEGIN OPEN Inline; i: CARDINAL; casebit: WORD = 40B; IF s1 = NIL AND s2 = NIL THEN RETURN[TRUE]; IF s1 = NIL OR s2 = NIL OR s1.length # s2.length THEN RETURN[FALSE]; FOR i IN [0..s1.length) DO IF BITOR[s1[i], casebit] # BITOR[s2[i], casebit] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE] END; AppendSubString: PROCEDURE [to: LONG STRING, from: SubString] = BEGIN i, j, n: CARDINAL; s: LONG STRING; IF to = NIL OR (s _ from.base) = NIL THEN RETURN; WHILE from.length + to.length > to.maxlength DO temp: LONG STRING _ SIGNAL StringBoundsFault[to]; IF temp = NIL THEN EXIT; -- just fill in as much as fits to _ temp; ENDLOOP; i _ to.length; j _ from.offset; n _ MIN[from.length, LOOPHOLE[to.maxlength - to.length, CARDINAL]]; WHILE n > 0 DO to[i] _ s[j]; i _ i + 1; j _ j + 1; n _ n - 1; ENDLOOP; to.length _ i; RETURN END; EqualSubString: PROCEDURE [s1, s2: SubString] RETURNS [BOOLEAN] = BEGIN i1, i2, n: CARDINAL; b1, b2: LONG STRING; IF s1.length # s2.length THEN RETURN[FALSE]; b1 _ s1.base; i1 _ s1.offset; b2 _ s2.base; i2 _ s2.offset; FOR n _ s1.length, n - 1 WHILE n > 0 DO IF b1[i1] # b2[i2] THEN RETURN[FALSE]; i1 _ i1 + 1; i2 _ i2 + 1; ENDLOOP; RETURN[TRUE] END; EquivalentSubString: PROCEDURE [s1, s2: SubString] RETURNS [BOOLEAN] = BEGIN OPEN Inline; casebit: WORD = 40B; i1, i2, n: CARDINAL; b1, b2: LONG STRING; IF s1.length # s2.length THEN RETURN[FALSE]; b1 _ s1.base; i1 _ s1.offset; b2 _ s2.base; i2 _ s2.offset; FOR n _ s1.length, n - 1 WHILE n > 0 DO IF BITOR[b1[i1], casebit] # BITOR[b2[i2], casebit] THEN RETURN[FALSE]; i1 _ i1 + 1; i2 _ i2 + 1; ENDLOOP; RETURN[TRUE] END; Copy: PROCEDURE [to, from: LONG STRING] = { n: CARDINAL; IF to = NIL OR from = NIL THEN RETURN; WHILE from.length > to.maxlength DO temp: LONG STRING _ SIGNAL StringBoundsFault[to]; IF temp = NIL THEN EXIT; -- just fill in as much as fits to _ temp; ENDLOOP; n _ MIN[from.length, to.maxlength]; Inline.LongCOPY[ from: @from.text, to: @to.text, nwords: SIZE[StringBody[n]]-SIZE[StringBody[0]]]; to.length _ n; RETURN}; DeleteSubString: PROCEDURE [s: SubString] = BEGIN b: LONG STRING = s.base; i: CARDINAL _ s.offset; j: CARDINAL _ i + s.length; WHILE j < b.length DO b[i] _ b[j]; i _ i + 1; j _ j + 1; ENDLOOP; b.length _ i; RETURN END; AppendCharAndGrow: PROCEDURE [ to: LONG POINTER TO LONG STRING, c: CHARACTER, z: UNCOUNTED ZONE] = BEGIN extra: CARDINAL _ 6; temp: LONG STRING _ to^; IF temp = NIL OR temp.length = temp.maxlength THEN { temp _ CopyToNewString[temp, z, extra]; FreeString[z, to^]; to^ _ temp; }; temp[temp.length] _ c; temp.length _ temp.length + 1; END; AppendExtensionIfNeeded: PROCEDURE [ to: LONG POINTER TO LONG STRING, extension: LONG STRING, z: UNCOUNTED ZONE] RETURNS [done: BOOLEAN] = BEGIN i, nCharsToAdd: CARDINAL; temp: LONG STRING _ to^; done _ FALSE; IF EmptyString[temp] THEN RETURN[FALSE]; FOR i DECREASING IN [1..temp.length) DO SELECT temp[i] FROM '., Ascii.SP, Ascii.TAB => temp.length _ temp.length - 1; ENDCASE => EXIT; ENDLOOP; FOR i DECREASING IN [0..temp.length) DO IF temp[i] = '. THEN RETURN[FALSE]; ENDLOOP; nCharsToAdd _ extension.length + (IF extension[0] # '. THEN 1 ELSE 0); IF temp.length + nCharsToAdd > temp.maxlength THEN { temp _ CopyToNewString[temp, z, nCharsToAdd]; FreeString[z, to^]; to^ _ temp; }; IF extension[0] # '. THEN AppendChar[temp, '.]; AppendString[temp, extension]; done _ TRUE; END; AppendStringAndGrow: PROCEDURE [ to: LONG POINTER TO LONG STRING, from: LONG STRING, z: UNCOUNTED ZONE, extra: CARDINAL _ 0] = BEGIN temp: LONG STRING _ to^; IF temp = NIL OR temp.length + from.length >= temp.maxlength THEN { temp _ CopyToNewString[temp, z, from.length + extra]; FreeString[z, to^]; to^ _ temp; }; AppendString[to: temp, from: from]; END; Replace: PROCEDURE [ to: LONG POINTER TO LONG STRING, from: LONG STRING, z: UNCOUNTED ZONE] = BEGIN IF to = NIL THEN RETURN[]; IF to^ # NIL THEN {FreeString[z, to^]; to^ _ NIL}; IF from # NIL THEN to^ _ CopyToNewString[from, z]; RETURN END; CopyToNewString: PROCEDURE [ s: LONG STRING, z: UNCOUNTED ZONE, longer: CARDINAL _ 0] RETURNS [newS: LONG STRING] = BEGIN l: CARDINAL = (IF s = NIL THEN 0 ELSE s.length); IF s = NIL AND longer = 0 THEN RETURN[NIL]; newS _ MakeString[z, l + longer]; Inline.LongCOPY[ from: @s.text, to: @newS.text, nwords: SIZE[StringBody[l]]-SIZE[StringBody[0]]]; newS.length _ l; END; ExpandString: PROCEDURE [ s: LONG POINTER TO LONG STRING, longer: CARDINAL, z: UNCOUNTED ZONE] = BEGIN newS: LONG STRING _ CopyToNewString[ s^, z, longer + (IF s^ = NIL THEN 0 ELSE s.maxlength - s.length)]; FreeString[z, s^]; s^ _ newS; END; Overflow: SIGNAL = CODE; InvalidNumber: SIGNAL = CODE; NUL: CHARACTER = 0C; Space: CHARACTER = ' ; UpperCase: PROCEDURE [c: CHARACTER] RETURNS [CHARACTER] = BEGIN IF c IN ['a..'z] THEN c _ c + ('A - 'a); RETURN[c] END; LowerCase: PROCEDURE [c: CHARACTER] RETURNS [CHARACTER] = BEGIN IF c IN ['A..'Z] THEN c _ c + ('a - 'A); RETURN[c] END; Compare: PROCEDURE [s1, s2: LONG STRING, ignoreCase: BOOLEAN _ TRUE] RETURNS [INTEGER] = BEGIN i: CARDINAL; l1: CARDINAL = s1.length; l2: CARDINAL = s2.length; c1, c2: CHARACTER; FOR i IN [0..MIN[l1, l2]) DO c1 _ s1[i]; c2 _ s2[i]; IF ignoreCase THEN BEGIN c1 _ UpperCase[c1]; c2 _ UpperCase[c2]; END; SELECT c1 FROM < c2 => RETURN[-1]; > c2 => RETURN[1]; ENDCASE; ENDLOOP; RETURN[SELECT l1 FROM < l2 => -1, > l2 => 1, ENDCASE => 0] END; StringToDecimal: PROCEDURE [s: LONG STRING] RETURNS [INTEGER] = { RETURN[StringToNumber[s, 10]]}; StringToOctal: PROCEDURE [s: LONG STRING] RETURNS [CARDINAL] = { RETURN[StringToNumber[s, 8]]}; StringToNumber: PROCEDURE [s: LONG STRING, radix: CARDINAL] RETURNS [v: UNSPECIFIED] = BEGIN OPEN Inline; char: CHARACTER; cp: CARDINAL _ 0; v8, v10: CARDINAL _ 0; neg: BOOLEAN _ FALSE; getchar: PROCEDURE = BEGIN char _ IF cp >= s.length THEN NUL ELSE s[cp]; cp _ cp + 1; END; getchar[]; WHILE char <= Space DO IF char = NUL THEN SIGNAL InvalidNumber; getchar[]; ENDLOOP; IF char = '- THEN BEGIN neg _ TRUE; getchar[] END; WHILE char IN ['0..'9] DO v10 _ v10*10 + (char - '0); v8 _ v8*8 + (char - '0); getchar[]; ENDLOOP; BEGIN SELECT LOOPHOLE[BITAND[char, 137B], CHARACTER] FROM NUL => GOTO noexponent; 'B => BEGIN v _ v8; radix _ 8; END; 'D => BEGIN v _ v10; radix _ 10; END; ENDCASE => GOTO noexponent; getchar[]; v10 _ 0; WHILE char IN ['0..'9] DO v10 _ v10*10 + char - '0; getchar[]; ENDLOOP; THROUGH [1..v10] DO v _ v*radix ENDLOOP; EXITS noexponent => v _ IF radix = 8 THEN v8 ELSE v10; END; IF char # NUL THEN SIGNAL InvalidNumber; IF neg THEN RETURN[-v]; END; AppendNumber: PROCEDURE [s: LONG STRING, n: CARDINAL, radix: CARDINAL] = BEGIN ps: POINTER TO LONG STRING = @s; xn: PROCEDURE [n: CARDINAL] = BEGIN r: CARDINAL; [n, r] _ Inline.DIVMOD[n, radix]; IF n # 0 THEN xn[n]; IF r > 9 THEN r _ r + 'A - '0 - 10; AppendChar[s, r + '0]; END; xn[n ! StringBoundsFault => RESUME[ps^ _ StringBoundsFault[s]]]; END; AppendDecimal: PROCEDURE [s: LONG STRING, n: INTEGER] = BEGIN IF n < 0 THEN BEGIN ps: POINTER TO LONG STRING = @s; IF n = LAST[INTEGER] THEN BEGIN AppendString[s, "-32768"L]; RETURN END; AppendChar[s, '- ! StringBoundsFault => RESUME[ps^ _ StringBoundsFault[s]]]; n _ -n END; AppendNumber[s, n, 10]; END; AppendOctal: PROCEDURE [s: LONG STRING, n: UNSPECIFIED] = BEGIN AppendNumber[s, n, 8]; AppendChar[s, 'B]; END; AppendLongDecimal: PROCEDURE [s: LONG STRING, n: LONG INTEGER] = BEGIN IF n < 0 THEN BEGIN ps: POINTER TO LONG STRING = @s; IF n = LAST[LONG INTEGER] THEN BEGIN AppendString[s, "-2147483648"L]; RETURN END; AppendChar[s, '- ! StringBoundsFault => RESUME[ps^ _ StringBoundsFault[s]]]; n _ -n END; AppendLongNumber[s, n, 10]; END; AppendLongNumber: PROCEDURE [ s: LONG STRING, n: LONG UNSPECIFIED, radix: CARDINAL] = BEGIN ps: POINTER TO LONG STRING = @s; xn: PROCEDURE [n: LONG CARDINAL] = BEGIN lr: LONG CARDINAL; r: CARDINAL; [n, lr] _ Inline.UDDivMod[n, radix]; IF n # 0 THEN xn[n]; IF (r _ Inline.LowHalf[lr]) > 9 THEN r _ r + 'A - '0 - 10; AppendChar[s, r + '0]; END; xn[n ! StringBoundsFault => RESUME[ps^ _ StringBoundsFault[s]]]; END; StringToLongNumber: PROCEDURE [s: LONG STRING, radix: CARDINAL] RETURNS [v: LONG CARDINAL] = BEGIN OPEN Inline; char: CHARACTER; cp: CARDINAL _ 0; exp: CARDINAL; v8, v10: LONG INTEGER _ 0; neg: BOOLEAN _ FALSE; getchar: PROCEDURE = BEGIN char _ IF cp >= s.length THEN NUL ELSE s[cp]; cp _ cp + 1; END; getchar[]; WHILE char <= Space DO IF char = NUL THEN SIGNAL InvalidNumber; getchar[]; ENDLOOP; IF char = '- THEN BEGIN neg _ TRUE; getchar[] END; WHILE char IN ['0..'9] DO v10 _ v10*10 + CARDINAL[char - '0]; v8 _ v8*8 + CARDINAL[char - '0]; getchar[]; ENDLOOP; BEGIN SELECT LOOPHOLE[BITAND[char, 137B], CHARACTER] FROM NUL => GOTO noexponent; 'B => BEGIN v _ v8; radix _ 8; END; 'D => BEGIN v _ v10; radix _ 10; END; ENDCASE => GOTO noexponent; getchar[]; exp _ 0; WHILE char IN ['0..'9] DO exp _ exp*10 + char - '0; getchar[]; ENDLOOP; THROUGH [1..exp] DO v _ v*radix ENDLOOP; EXITS noexponent => v _ IF radix = 8 THEN v8 ELSE v10; END; IF char # NUL THEN SIGNAL InvalidNumber; IF neg THEN RETURN[-v]; END; END.... ¬StringImpl.mesa Copyright (C) 1984, Xerox Corporation. All rights reserved. Michael Plass, September 7, 1984 5:14:51 pm PDT Merge of Pilot StringsImplA and StringsImplB, with Heap references removed. IF Heap.OwnerChecking[z] THEN SetOwner[temp, GetGF[Runtime.GetCaller[]]] IF Heap.OwnerChecking[z] THEN SetOwner[temp, GetGF[Runtime.GetCaller[]]] IF Heap.OwnerChecking[z] THEN SetOwner[temp, GetGF[Runtime.GetCaller[]]] IF Heap.OwnerChecking[z] THEN SetOwner[to^, GetGF[Runtime.GetCaller[]]]; IF Heap.OwnerChecking[z] THEN LOOPHOLE[(newS - 1), LONG POINTER]^ _ GetGF[Runtime.GetCaller[]]; IF Heap.OwnerChecking[z] THEN LOOPHOLE[(newS - 1), LONG POINTER]^ _ GetGF[Runtime.GetCaller[]]; GetGF: PRIVATE PROCEDURE [p: PROGRAM] RETURNS [POINTER] = INLINE { RETURN[Inline.LowHalf[LOOPHOLE[p]]]}; SetOwner: PRIVATE PROCEDURE [ node: LONG STRING, owner: UNSPECIFIED] = INLINE { IF node#NIL THEN LOOPHOLE[node - 1, LONG POINTER]^ _ owner}; Êm˜Jšœ™J™Jš˜Jšœœ˜ Jš œœœœœœ˜&šœ(˜/Jšœœœœ˜2Jš œœœœÏc˜8J˜ Jšœ˜—Jšœœœœ˜Cšœ œ˜˜J˜Jšœ œ˜%Jšœœœ˜0——šœ˜˜Jšœœ˜$J˜J˜—˜Jšœœ ˜"J˜J˜"——J˜Jš˜Jšœ˜J˜—š žœ œ œœœœ˜:Jš˜Jšœœ˜ Jšœœœœœœœ˜+Jšœœœœœœœœ˜DJšœœœœœœœœ˜HJšœœ˜ Jšœ˜J˜—šž œ œ œœ˜+Jšœœ˜Jšœœ˜Jšœœ˜ Jšœ œ˜Jšœœœœœœœ˜+Jšœœœœœœœœ˜Dšœœ˜Jš œœœœœœ˜DJšœ˜—Jšœœ˜ Jšœ˜J˜—šžœ œœœ˜?Jš˜Jšœ œ˜Jšœœœ˜Jš œœœœœœ˜1šœ(˜/Jšœœœœ˜2Jš œœœœŸ˜8J˜ Jšœ˜—J˜J˜Jšœœœœ˜CJšœœ0œ˜FJ˜Jš˜Jšœ˜J˜—šžœ œ˜-Jšœœ˜Jš˜Jšœ œ˜Jšœœœ˜Jšœœœœ˜,J˜ J˜J˜ J˜šœœ˜'Jš œœœœœ˜I—Jšœœ˜ Jšœ˜J˜—šžœ œ˜2Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ œ˜Jšœœœ˜Jšœœœœ˜,J˜ J˜J˜ J˜šœœ˜'Jš œœœœœœ˜FJ˜ J˜ Jšœ˜—Jšœœ˜ Jšœ˜J˜—šžœ œ œœ˜+Jšœœ˜ Jš œœœœœœ˜&šœ˜#Jšœœœœ˜2Jš œœœœŸ˜8J˜ Jšœ˜—Jšœœ˜#˜J˜J˜ Jšœœœ˜1—J˜Jšœ˜J˜—šžœ œ˜+Jš˜Jšœœœ ˜Jšœœ ˜Jšœœ˜Jšœœ$œ˜AJ˜ Jš˜Jšœ˜J˜—šžœ œ˜Jšœœœœœœ œ œœ˜DJš˜Jšœœ˜Jšœœœ˜šœœœœ˜4J˜'J˜J˜ Jšœœ+™HJšœ˜—J˜J˜Jšœ˜J˜—šžœ œ˜$Jšœœœœœœ œœ œœ˜KJšœœ˜Jš˜Jšœœ˜Jšœœœ˜Jšœœ˜ Jšœœœœ˜(šœ œœ˜'šœ ˜Jšœ œœ"˜9Jšœœ˜—Jšœ˜—šœ œœ˜'Jšœœœœ˜#Jšœ˜—Jšœ"œœœ˜Fšœ,œ˜5J˜-J˜J˜ Jšœœ+™HJšœ˜—Jšœœ˜/J˜Jšœœ˜ Jšœ˜J˜—šžœ œ˜ Jšœœœœœœœœ œœ˜FJšœœ˜Jš˜Jšœœœ˜šœœœ-œ˜CJ˜5J˜J˜ Jšœœ+™HJšœ˜—J˜#Jšœ˜J˜—šžœ œ˜Jšœœœœœœœœ œœ˜HJš˜Jšœœœœ˜Jšœœœœ˜2Jšœœœ ˜2Jšœœ+™HJš˜Jšœ˜J˜—šžœ œ˜Jš œœœ œœ œ˜8Jšœœœ˜Jš˜Jš œœœœœœ ˜0Jš œœœ œœœ˜+J˜!˜J˜J˜Jšœœœ˜1—J˜šœ™Jšœ œœ ™A—Jšœ˜J˜—šž œ œ˜šœœœœœœ œ œœ˜FJš˜—šœœœ˜$Jš œœœœœ˜B—J˜J˜ šœ™Jšœ œœ ™A—Jšœ˜J˜—šžœœ œœœœœ™BJšœœ™%J™—šžœœ œ™Jš œœœ œœ™1Jš œœœœ œœ ™Jšœ˜—Jšœœœœ˜:Jšœ˜J˜—š žœ œœœœœ˜AJšœ˜J˜—š ž œ œœœœœ˜@Jšœ˜J˜—š žœ œœœ œ˜;Jšœ œ˜Jšœœ˜Jšœ œ˜Jšœœ˜Jšœ œ˜Jšœœœ˜J˜šœ œ˜Jš œœœœœœ˜EJ˜—J˜ šœ˜Jš œœœœœ˜<—Jš œ œœœ œ˜2šœœ ˜Jšœ@œ˜H—Jš˜š œœœ œ˜3Jšœœ ˜Jšœœœ˜#Jšœœœ˜%Jšœœ ˜—J˜ J˜Jšœœ œ&œ˜GJšœ œ œ˜(Jšœœ œœ˜6Jšœ˜Jšœœœœ˜(Jšœœœ˜Jšœ˜J˜—š ž œ œœœœ œ˜HJš˜Jš œœœœœ˜ J˜šœ œœ˜Jš˜Jšœœ˜ Jšœœ ˜!Jšœœ˜Jšœœ˜#J˜Jšœ˜J˜—Jšœœ˜@Jšœ˜J˜—š ž œ œœœœ˜7Jš˜šœ˜ Jš˜Jš œœœœœ˜ Jšœœœœœœœ˜GJšœ(œ˜LJ˜Jšœ˜—J˜Jšœ˜J˜—š ž œ œœœ œ˜9Jšœ+œ˜4J˜—š žœ œœœœœ˜@Jš˜šœ˜ Jš˜Jš œœœœœ˜ š œœœœ˜Jšœ"œœ˜2—Jšœ(œ˜LJ˜Jšœ˜—J˜Jšœ˜J˜—šžœ œ˜Jš œœœœ œ œ˜7Jš˜Jš œœœœœ˜ šœ œœœ˜"Jš˜Jšœœœ˜Jšœœ˜ J˜$Jšœœ˜Jšœœ˜:J˜Jšœ˜—Jšœœ˜@Jšœ˜J˜—š žœ œœœ œ˜?Jšœœœ˜Jšœœ˜Jšœ œ˜Jšœœ˜Jšœœ˜Jšœ œœ˜Jšœœœ˜J˜šœ œ˜Jš œœœœœœ˜EJ˜—J˜ šœ˜Jš œœœœœ˜<—Jš œ œœœ œ˜2šœœ ˜Jšœœ ˜#Jšœ œ ˜ J˜ Jšœ˜—Jš˜š œœœ œ˜3Jšœœ ˜Jšœœœ˜#Jšœœœ˜%Jšœœ ˜—J˜ J˜Jšœœ œ&œ˜GJšœ œ œ˜(Jšœœ œœ˜6Jšœ˜Jšœœœœ˜(Jšœœœ˜Jšœ˜J˜—Jšœ˜J˜——…—) A¹