IMPLEMENTATION MODULE Strings; (* The descriptor's header holds the logical length; Assign/Concat update it (m2setlen), so Length reflects content, not capacity. *) PROCEDURE m2setlen(VAR s : ARRAY OF CHAR; n : INTEGER); EXTERNAL; PROCEDURE Length(VAR s : ARRAY OF CHAR) : INTEGER; BEGIN RETURN LEN(s) END Length; PROCEDURE Assign(VAR src, dst : ARRAY OF CHAR); VAR i, n, cap : INTEGER; BEGIN n := LEN(src); cap := LEN(dst); IF n > cap THEN n := cap END; i := 0; WHILE i < n DO dst[i] := src[i]; i := i + 1 END; m2setlen(dst, n) END Assign; PROCEDURE Copy(VAR src, dst : ARRAY OF CHAR); BEGIN Assign(src, dst) END Copy; PROCEDURE Concat(VAR s1, s2 : ARRAY OF CHAR; VAR dst : ARRAY OF CHAR); VAR i, n1, n2, cap : INTEGER; BEGIN n1 := LEN(s1); n2 := LEN(s2); cap := LEN(dst); IF n1 + n2 > cap THEN n1 := cap - n2; IF n1 < 0 THEN n1 := 0 END END; i := 0; WHILE i < n1 DO dst[i] := s1[i]; i := i + 1 END; i := 0; WHILE i < n2 DO dst[n1 + i] := s2[i]; i := i + 1 END; m2setlen(dst, n1 + n2) END Concat; PROCEDURE Compare(VAR s1, s2 : ARRAY OF CHAR) : INTEGER; VAR i, n1, n2, n : INTEGER; BEGIN n1 := LEN(s1); n2 := LEN(s2); n := n1; IF n2 < n THEN n := n2 END; i := 0; WHILE i < n DO IF s1[i] < s2[i] THEN RETURN -1 ELSIF s1[i] > s2[i] THEN RETURN 1 END; i := i + 1 END; IF n1 < n2 THEN RETURN -1 ELSIF n1 > n2 THEN RETURN 1 END; RETURN 0 END Compare; END Strings.