home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
LANGUAGS
/
PASCAL
/
STRINGS.LBR
/
STRINGS.IZC
/
STRINGS.INC
Wrap
Text File
|
2000-06-30
|
9KB
|
288 lines
(* As long as an efficient method of determining string length *)
(* is available (supplied by the PASCALP scanfor intrinsic), *)
(* strings delimited by an end marker, as here, appear to be *)
(* more efficient, and more easily manipulated, than strings *)
(* defined as a record with a length field. by C.B. Falconer *)
(* Added stoi/itos 85/11/18. Added stringfill 85/11/25. *)
(* Renamed stringfill to fillstring (name conflict) 87/02/12 *)
(* 1---------------1 *)
PROCEDURE readstring(VAR f : text; VAR s : string)
(* At exit, eoln(f) is true, and no readln(f) has been called *);
(* The input string is terminated by eoln (usually cr). *)
VAR
i : xxstrindex;
BEGIN (* readstring *)
i := 1;
WHILE NOT eoln(f) DO
IF i < xmaxstring THEN BEGIN
read(f, s[i]); i := succ(i); END
ELSE get(f);
s[i] := eos;
END; (* readstring *)
(* 1---------------1 *)
PROCEDURE readlnstring(VAR f : text; VAR s : string)
(* differs from readstring in that at exit readln has been called *);
BEGIN (* readlnstring *)
readstring(f, s); readln(f);
END; (* readlnstring *)
(* 1---------------1 *)
FUNCTION length(VAR s : string) : xstrindex;
(* better implemented as a macro. *)
BEGIN (* length *)
length := pred(scanfor(eos, s, xmaxstring));
(* rangerror for invalid string, with no eos mark *)
END; (* length *)
(* 1---------------1 *)
PROCEDURE writestring(VAR f : text; VAR s : string);
(* better implemented as a macro. Uses the (nonstandard) *)
(* fact that write(f, s : 0) is a null op in PascalP. *)
(* On other systems guard with "IF s > 0 THEN ..." *)
BEGIN (* writestring *)
write(f, s : length(s));
END; (* writestring *)
(* 1---------------1 *)
PROCEDURE wrtfldstring(VAR f : text; VAR s : string; field : integer)
(* Analog to the normal Pascal write(f, x : field). Rt. justifies *);
VAR
l : integer;
BEGIN (* wrtfldstring *)
l := field - length(s);
IF l > 0 THEN BEGIN
write(f, ' ' : l); writestring(f, s); END
ELSE IF l < 0 THEN write(f, s : field)
ELSE writestring(f, s);
END; (* wrtfldstring *)
(* 1---------------1 *)
PROCEDURE concat(s1, s2 : string; VAR sdest : string)
(* Arguments may be the same string, correctly handled *);
VAR
i, j, k : integer;
BEGIN (* concat *)
sdest := s1; k := 1; i := length(s1); j := i + length(s2);
IF j > maxstring THEN j := maxstring;
FOR i := succ(i) TO j DO BEGIN
sdest[i] := s2[k]; k := succ(k); END;
sdest[succ(j)] := eos;
END; (* concat *)
(* 1---------------1 *)
PROCEDURE stringdeblank(VAR s : string)
(* remove trailing blanks, if any *);
VAR
i : integer;
BEGIN (* stringdeblank *)
i := length(s);
WHILE i > 0 DO
IF s[i] <> ' ' THEN i := 0 (* force exit *)
ELSE BEGIN
s[i] := eos; i := pred(i); END;
END; (* stringdeblank *)
(* 1---------------1 *)
PROCEDURE stringextend(VAR s : string; ch : char; always : boolean)
(* always false prevents extension if the terminal *)
(* char is ch, or if the string is null (length=0) *);
VAR
l : integer;
BEGIN (* stringextend *)
l := length(s);
IF l = 0 THEN BEGIN
IF always THEN BEGIN
s[1] := ch; s[2] := eos; END;
END
ELSE IF l < maxstring THEN
IF (s[l] <> ch) OR always THEN BEGIN
s[succ(l)] := ch; s[l + 2] := eos; END;
END; (* stringextend *)
(* 1---------------1 *)
PROCEDURE substring(si : string; index : strindex; len : integer;
VAR sdest : string)
(* if index outside of si, then return the null string *)
(* if index + len > length of si, then truncate len *);
VAR
i, j : integer;
BEGIN (* substring *)
IF (index > length(si)) OR (* check anomalies *)
(len <= 0) OR (index <= 0) THEN sdest[1] := eos
ELSE BEGIN
j := index; i := 0;
REPEAT
i := succ(i); sdest[i] := si[j]; j := succ(j);
UNTIL (sdest[i] = eos) OR (i >= len) OR (j > maxstring);
IF i <= maxstring THEN sdest[succ(i)] := eos; END;
END; (* substring *)
(* 1---------------1 *)
PROCEDURE stringclean(VAR s : string)
(* This standardizes the portion beyond the eos marker. *);
(* Thus straight lexical comparisons can be made. *)
(* Because strings are meaningless beyond their length, *)
(* this does not affect any other string operations. *)
(* Comparisons depend on the fact that eos is zero, so *)
(* that a string vs string+suffix compares correctly. *)
(* This should be called after any string has been mod- *)
(* ified, and before any comparison is made. It need *)
(* not be called again unless the string is modified. *)
VAR
i : xxstrindex;
BEGIN (* stringclean *)
FOR i := succ(length(s)) TO xmaxstring DO s[i] := eos;
END; (* stringclean *)
(* 1---------------1 *)
PROCEDURE fillstring(VAR s : string; fillchar : char)
(* This fills the string out to maximum string length with *)
(* "fillchar". Can be used to create fixed rcd. lgh files. *);
VAR
i : xxstrindex;
BEGIN (* fillstring *)
FOR i := succ(length(s)) TO maxstring DO s[i] := fillchar;
s[xmaxstring] := eos;
END; (* fillstring *)
(* 1---------------1 *)
FUNCTION stringfind(VAR s, searchee : string; start : strindex)
: xstrindex
(* returns the index in searchee (from start up) where *)
(* the substring s may be found. Returns 0 if not found. *);
LABEL 10;
CONST
debug = false;
VAR
i, j, k : integer;
BEGIN (* stringfind *)
stringfind := 0; (* default not found *)
IF (length(searchee) >= start) THEN
IF length(s) = 0 THEN stringfind := start (* null string found *)
ELSE BEGIN (* both strings non-null *)
j := start;
10: i := scanfor(s[1], searchee[j], succ(length(searchee)) - j)
+ pred(j); (* returns index from start point *)
IF debug THEN writeln('i=', i : 1, ', j=', j : 1);
IF i >= j THEN BEGIN (* found 1st char, check rest *)
IF (pred(i) + length(s)) <= length(searchee) THEN BEGIN
(* room for the substring, continue *)
FOR k := 2 TO length(s) DO (* 1st already matched *)
IF s[k] <> searchee[i + pred(k)] THEN BEGIN
j := succ(i); GOTO 10; END; (* no match, try again *)
stringfind := i; END; (* matched all *)
END;
END
(* ELSE searching a null string, return 0 *);
END; (* stringfind *)
(* 1---------------1 *)
PROCEDURE stringupshift(VAR s : string);
CONST
upconvert = 32; (* ord('a') - ord('A') *)
VAR
i : xstrindex;
BEGIN (* stringupshift *)
FOR i := 1 TO length(s) DO
IF s[i] IN ['a'..'z'] THEN
s[i] := chr(ord(s[i]) - upconvert);
END; (* stringupshift *)
(* 1---------------1 *)
FUNCTION stoi(VAR s : string; start : strindex;
VAR value : integer) : xstrindex
(* returns 0 for no valid number, else index past number *);
(* cannot handle -maxint - 1. Allows "--123" = 123, etc. *)
VAR
i : integer;
BEGIN (* stoi *)
value := 0; i := start;
WHILE s[i] = ' ' DO i := succ(i);
IF s[i] = '-' THEN BEGIN
stoi := stoi(s, succ(i), value); value := - value; END
ELSE IF s[i] IN ['0'..'9'] THEN BEGIN
REPEAT (* may cause integer overflow *)
value := 10*value + ord(s[i]) - ord('0'); i := succ(i);
UNTIL NOT (s[i] IN ['0'..'9']);
stoi := i; END
ELSE stoi := 0; (* failure *)
END; (* stoi *)
(* 1---------------1 *)
PROCEDURE itos(i : integer; VAR s : string)
(* Creates a string with the left justified representation of i *);
(* fails for -maxint -1 *)
VAR
x : xstrindex;
(* 2---------------2 *)
PROCEDURE convert(i : integer); (* and reverse digits *)
VAR
ch : char;
BEGIN (* convert *)
ch := chr(i MOD 10 + ord('0'));
IF i > 9 THEN convert(i DIV 10);
s[x] := ch; x := succ(x);
END; (* convert *)
(* 2---------------2 *)
BEGIN (* itos *)
IF i < 0 THEN BEGIN
s[1] := '-'; x := 2; i := abs(i); END
ELSE x := 1;
convert(i); s[x] := eos;
END; (* itos *)
(* 1---------------1 *)
gⁿ