EnterString:
PUBLIC
PROC [s: SubString]
RETURNS [hti: HTIndex]~{
hvi: HVIndex~HashValue[s];
desc: SubString←[base~@ssb.string, offset~, length~];
charsPerWord: CARDINAL~Basics.charsPerWord;
offset, length, nw: CARDINAL;
ssi: Alloc.Index;
FOR hti ← hashVec[hvi], ht[hti].link
UNTIL hti = htNull
DO
desc ← SubStringForHash[hti];
IF ConvertUnsafe.EqualSubStrings[s, desc] THEN RETURN [hti];
ENDLOOP;
offset ← ssb.string.length; length ← s.length + 1;
nw ← (offset + length+ (charsPerWord-1) - ssb.string.maxlength)/charsPerWord;
IF nw # 0
THEN {
IF (ssi ← table.Words[ssType, nw]) # ssw THEN ERROR;
ssw ← ssw + nw;
ssb.string ← [
text~,
length~ssb.string.length, maxlength~ssb.string.maxlength+nw*charsPerWord]};
ConvertUnsafe.AppendRope[@ssb.string, Rope.FromChar[LOOPHOLE[s.length, CHAR]]];
ConvertUnsafe.AppendSubString[@ssb.string, s];
hti ← AllocateHash[];
ht[hti].link ← hashVec[hvi];
hashVec[hvi] ← hti;
RETURN};