IMPLEMENTATION MODULE STstrings; (*DEE 2014-01-22//2015-11-25/2022-09-13*) FROM ST IMPORT divide, putc; FROM STchars IMPORT BACKSPACE, BLANK, ESCAPE, MINUS, NEWLINE, PLUS, TAB, character; FROM STutility IMPORT isdigit; (* addstr: put c in outset[j] if it fits, increment j *) PROCEDURE addstr(c: character; VAR outset: string; VAR j: INTEGER; maxset: INTEGER): BOOLEAN; BEGIN IF (j > maxset) THEN RETURN FALSE ELSE outset[j] := c; INC(j); RETURN TRUE END END addstr; (* ctoi: convert string at a[i] to integer, increment i *) PROCEDURE ctoi(VAR s: string; VAR i: INTEGER): INTEGER; VAR o, n, sign: INTEGER; BEGIN WHILE (s[i] = BLANK) OR (s[i] = TAB) DO INC(i) END; IF (s[i] = MINUS) THEN sign := -1 ELSE sign := 1 END; IF (s[i] = PLUS) OR (s[i] = MINUS) THEN INC(i) END; n := 0; o := ORD('0'); WHILE (isdigit(s[i])) DO n := (10 * n) + s[i] - o; INC(i) END; RETURN sign * n END ctoi; (* esc: map s[i] into escaped character, increment i *) (* Software Tools in Pascal, exercise 2-22. *) PROCEDURE esc (VAR s: string; VAR i: INTEGER): character; CONST CR = 13; LF = 10; FF = 12; VT = 11; VAR B, F, L, N, R, S, T, V: character; BEGIN IF (s[i] # ESCAPE) THEN RETURN s[i] ELSIF (s[i+1] = ENDSTR) THEN (*@ not special at end*) RETURN ESCAPE ELSE INC(i); B := ORD('b'); F := ORD('f'); L := ORD('l'); N := ORD('n'); R := ORD('r'); S := ORD('s'); T := ORD('t'); V := ORD('v'); IF (s[i] = N) THEN RETURN NEWLINE ELSIF (s[i] = T) THEN RETURN TAB ELSIF (s[i] = S) THEN RETURN BLANK ELSIF (s[i] = F) THEN RETURN FF ELSIF (s[i] = V) THEN RETURN VT ELSIF (s[i] = B) THEN RETURN BACKSPACE ELSIF (s[i] = R) THEN RETURN CR ELSIF (s[i] = L) THEN RETURN LF (* What about @000 syntax? See vis. *) ELSE RETURN s[i] END END END esc; (* equal: test two strings for equality *) PROCEDURE equal (VAR str1, str2: string): BOOLEAN; VAR i: INTEGER; BEGIN i := 1; WHILE (str1[i] = str2[i]) AND (str1[i] # ENDSTR) DO INC(i) END; RETURN (str1[i] = str2[i]) END equal; (* itoc: convert integer n to char string in s[i]... *) PROCEDURE itoc(n: INTEGER; VAR s: string; i: INTEGER): INTEGER; VAR b: INTEGER; BEGIN IF (n < 0) THEN s[i] := ORD('-'); RETURN itoc(-n, s, i+1) ELSE IF (n >= 10) THEN i := itoc(divide(n, 10), s, i) (* n DIV 10 *) END; b := ORD('0'); s[i] := (n MOD 10) + b; s[i+1] := ENDSTR; RETURN i + 1 END END itoc; (* index: find position of character c in string s *) PROCEDURE index (VAR s: string; c: character): INTEGER; VAR i : INTEGER; BEGIN i := 1; WHILE (s[i] # c) AND (s[i] # ENDSTR) DO INC(i) END; IF (s[i] = ENDSTR) THEN RETURN 0 ELSE RETURN i END END index; (* length: compute length of string *) PROCEDURE length(VAR s: string): INTEGER; VAR n: INTEGER; BEGIN n := 1; WHILE (s[n] # ENDSTR) DO INC(n) END; RETURN n - 1 END length; (* putdec: put decimal integer n in field width >= w *) PROCEDURE putdec (n, w: INTEGER); VAR i, nd: INTEGER; s: string; BEGIN nd := itoc(n, s, 1); FOR i := nd TO w DO putc(BLANK) END; FOR i := 1 TO nd-1 DO putc(s[i]) END END putdec; END STstrings.