unit utility; { DPL 2004-03-22 } { Utilities, mainly aids to parsing } interface function equalsIgnoreCase(s1, s2: string): boolean; function startsWithIgnoreCase(s1, s2: string): boolean; function endsWith(s1, s2: string): boolean; function startsWithBracedWord (P: string): boolean; function GetNextWord (var s: string; Delim, Term: char): string; function NextWord (s: string; Delim, Term: char): string; function wordCount (s: string): integer; function plural (n: integer): string; function curtail (var s: string; c: char): integer; { Remove last character if it equals c and return its position; otherwise return 0 } function toString(n: integer): string; procedure trim(var s: string); function digit(c: char): integer; function match(source, pattern: string): boolean; function translate(source, pattern, target: string): string; procedure grep(var source, pattern, target: string); { See Implementation for what this currently does. } implementation uses strings; const blank = ' '; dummy = #0; function wordCount (s: string): integer; var i, n: integer; begin if length(s)=0 then begin wordCount:=0; exit; end; if s[1]=blank then n:=0 else n:=1; for i:=1 to length(s)-1 do if (s[i]=blank) and (s[i+1]<>blank) then inc(n); wordCount:=n; end; function GetNextWord (var s: string; Delim, Term: char): string; { A delimiter is a character that separates words, but forms no part of them. A terminator is a character that appears at the end of a word. } var n, start, last: integer; begin last:=length(s); n:=1; while (n<=last) and (s[n] = Delim) do inc(n); start:=n; while (n<=last) and not (s[n] in [Delim,Term]) do inc(n); if (n<=last) and (s[n] = Term) then inc(n); GetNextWord:=substr(s,start,n-start); while (n<=last) and (s[n] = Delim) do inc(n); predelete(s,n-1); end; function NextWord (s: string; Delim, Term: char): string; begin NextWord:=GetNextWord(s,Delim,Term); end; function plural (n: integer): string; begin if n=1 then plural:='' else plural:='s'; end; function curtail (var s: string; c: char): integer; var l: integer; begin l:=length(s); curtail:=0; if s[l]=c then begin shorten(s,l-1); curtail:=l; end; end; function toString(n: integer): string; var s: string; begin str(n,s); toString:=s; end; function digit(c: char): integer; begin digit:=ord(c)-ord('0'); end; function equalsIgnoreCase(s1, s2: string): boolean; begin toUpper(s1); toUpper(s2); equalsIgnoreCase:=s1=s2; end; function startsWithIgnoreCase(s1, s2: string): boolean; begin toUpper(s1); toUpper(s2); startsWithIgnoreCase:=startsWith(s1,s2); end; function startsWithBracedWord (P: string): boolean; var w: string; begin w := getNextWord(P,blank,dummy); startsWithBracedWord := (w[1]='{') and (w[length(w)]='}'); end; procedure trim(var s: string); var k: integer; begin k:=posnot(blank,s); if k>1 then predelete(s,k-1) else if k=0 then s:=''; end; function endsWith(s1, s2: string): boolean; var l1, l2: integer; begin l1:=length(s1); l2:=length(s2); if l19 then halt(9999); p1[index] := s1; p2[index] := s2; s := s2+1; inc(index) end; procedure matchnum; var allowsign, allowpoint, quit: boolean; s0: integer; begin allowsign := false; allowpoint := false; matching := false; s0 := s; if plength(source) then exit end; quit := false; while (not quit) and (s<=length(source)) do begin if source[s]='.' then if not allowpoint then quit := true else begin inc(s); allowpoint := false end; if (source[i]>='0') and (source[i]<='9') then begin inc(s); matching := true end else quit := true end; if matching then remember(s0,s-1) end; procedure matchmeta; begin if p=0) and (reg<=9) then for j:=p1[reg] to p2[reg] do product := product + source[j] else if target[t]='\' then product := product + '\' else product := product + '\' + target[t]; trigger := false end else if (target[t]='\') and (t