1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420 |
- {
- Copyright (c) 1998-2002 by Florian Klaempfl
- This unit implements some support functions
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- {# This unit contains some generic support functions which are used
- in the different parts of the compiler.
- }
- unit cutils;
- {$i fpcdefs.inc}
- interface
- type
- Tcharset=set of char;
- var
- internalerrorproc : procedure(i:longint);
- {# Returns the minimal value between @var(a) and @var(b) }
- function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
- function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
- {# Returns the maximum value between @var(a) and @var(b) }
- function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
- function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
- {# Return value @var(i) aligned on @var(a) boundary }
- function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
- { if you have an address aligned using "oldalignment" and add an
- offset of (a multiple of) offset to it, this function calculates
- the new minimally guaranteed alignment
- }
- function newalignment(oldalignment: longint; offset: int64): longint;
- {# Return @var(b) with the bit order reversed }
- function reverse_byte(b: byte): byte;
- function used_align(varalign,minalign,maxalign:shortint):shortint;
- function isbetteralignedthan(new, org, limit: cardinal): boolean;
- function size_2_align(len : longint) : shortint;
- function packedbitsloadsize(bitlen: int64) : int64;
- procedure Replace(var s:string;s1:string;const s2:string);
- procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
- procedure ReplaceCase(var s:string;const s1,s2:string);
- Function MatchPattern(const pattern,what:string):boolean;
- function upper(const c : char) : char;
- function upper(const s : string) : string;
- function upper(const s : ansistring) : ansistring;
- function lower(const c : char) : char;
- function lower(const s : string) : string;
- function lower(const s : ansistring) : ansistring;
- function trimbspace(const s:string):string;
- function trimspace(const s:string):string;
- function space (b : longint): string;
- function PadSpace(const s:string;len:longint):string;
- function GetToken(var s:string;endchar:char):string;
- procedure uppervar(var s : string);
- function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
- function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
- function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
- function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
- function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
- function DStr(l:longint):string;
- {# Returns true if the string s is a number }
- function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
- {# Returns true if value is a power of 2, the actual
- exponent value is returned in power.
- }
- function ispowerof2(value : int64;out power : longint) : boolean;
- function nextpowerof2(value : int64; out power: longint) : int64;
- function backspace_quote(const s:string;const qchars:Tcharset):string;
- function octal_quote(const s:string;const qchars:Tcharset):string;
- function maybequoted(const s:string):string;
- function maybequoted(const s:ansistring):ansistring;
- {# If the string is quoted, in accordance with pascal, it is
- dequoted and returned in s, and the function returns true.
- If it is not quoted, or if the quoting is bad, s is not touched,
- and false is returned.
- }
- function DePascalQuote(var s: ansistring): Boolean;
- function CompareStr(const S1, S2: string): Integer;
- function CompareText(S1, S2: string): integer;
- { releases the string p and assignes nil to p }
- { if p=nil then freemem isn't called }
- procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
- { allocates mem for a copy of s, copies s to this mem and returns }
- { a pointer to this mem }
- function stringdup(const s : string) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
- {# Allocates memory for the string @var(s) and copies s as zero
- terminated string to that allocated memory and returns a pointer
- to that mem
- }
- function strpnew(const s : string) : pchar;
- {# makes the character @var(c) lowercase, with spanish, french and german
- character set
- }
- function lowercase(c : char) : char;
- { makes zero terminated string to a pascal string }
- { the data in p is modified and p is returned }
- function pchar2pshortstring(p : pchar) : pshortstring;
- { inverse of pchar2pshortstring }
- function pshortstring2pchar(p : pshortstring) : pchar;
- { Ansistring (pchar+length) support }
- procedure ansistringdispose(var p : pchar;length : longint);
- function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
- function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
- {Lzw encode/decode to compress strings -> save memory.}
- function minilzw_encode(const s:string):string;
- function minilzw_decode(const s:string):string;
- Function nextafter(x,y:double):double;
- {$ifdef ver2_0}
- { RTL routines not available yet in 2.0.x }
- function SwapEndian(const AValue: SmallInt): SmallInt;
- function SwapEndian(const AValue: Word): Word;
- function SwapEndian(const AValue: LongInt): LongInt;
- function SwapEndian(const AValue: DWord): DWord;
- function SwapEndian(const AValue: Int64): Int64;
- function SwapEndian(const AValue: QWord): QWord;
- {$endif ver2_0}
- implementation
- uses
- SysUtils;
- var
- uppertbl,
- lowertbl : array[char] of char;
- function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
- {
- return the minimal of a and b
- }
- begin
- if a<=b then
- min:=a
- else
- min:=b;
- end;
- function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
- {
- return the minimal of a and b
- }
- begin
- if a<=b then
- min:=a
- else
- min:=b;
- end;
- function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
- {
- return the maximum of a and b
- }
- begin
- if a>=b then
- max:=a
- else
- max:=b;
- end;
- function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
- {
- return the maximum of a and b
- }
- begin
- if a>=b then
- max:=a
- else
- max:=b;
- end;
- function newalignment(oldalignment: longint; offset: int64): longint;
- var
- localoffset: longint;
- begin
- localoffset:=longint(offset);
- while (localoffset mod oldalignment)<>0 do
- oldalignment:=oldalignment div 2;
- newalignment:=oldalignment;
- end;
- function reverse_byte(b: byte): byte;
- const
- reverse_nible:array[0..15] of 0..15 =
- (%0000,%1000,%0100,%1100,%0010,%1010,%0110,%1110,
- %0001,%1001,%0101,%1101,%0011,%1011,%0111,%1111);
- begin
- reverse_byte:=(reverse_nible[b and $f] shl 4) or reverse_nible[b shr 4];
- end;
- function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
- {
- return value <i> aligned <a> boundary
- }
- begin
- { for 0 and 1 no aligning is needed }
- if a<=1 then
- result:=i
- else
- begin
- if i<0 then
- result:=((i-a+1) div a) * a
- else
- result:=((i+a-1) div a) * a;
- end;
- end;
- function size_2_align(len : longint) : shortint;
- begin
- if len>16 then
- size_2_align:=32
- else if len>8 then
- size_2_align:=16
- else if len>4 then
- size_2_align:=8
- else if len>2 then
- size_2_align:=4
- else if len>1 then
- size_2_align:=2
- else
- size_2_align:=1;
- end;
- function packedbitsloadsize(bitlen: int64) : int64;
- begin
- case bitlen of
- 1,2,4,8:
- result := 1;
- { 10 bits can never be split over 3 bytes via 1-8-1, because it }
- { always starts at a multiple of 10 bits. Same for the others. }
- 3,5,6,7,9,10,12,16:
- result := 2;
- {$ifdef cpu64bitalu}
- { performance penalty for unaligned 8 byte access is much }
- { higher than for unaligned 4 byte access, at least on ppc, }
- { so use 4 bytes even in some cases where a value could }
- { always loaded using a single 8 byte load (e.g. in case of }
- { 28 bit values) }
- 11,13,14,15,17..32:
- result := 4;
- else
- result := 8;
- {$else cpu64bitalu}
- else
- result := 4;
- {$endif cpu64bitalu}
- end;
- end;
- function isbetteralignedthan(new, org, limit: cardinal): boolean;
- var
- cnt: cardinal;
- begin
- cnt:=2;
- while (cnt <= limit) do
- begin
- if (org and (cnt-1)) > (new and (cnt-1)) then
- begin
- result:=true;
- exit;
- end
- else if (org and (cnt-1)) < (new and (cnt-1)) then
- begin
- result:=false;
- exit;
- end;
- cnt:=cnt*2;
- end;
- result:=false;
- end;
- function used_align(varalign,minalign,maxalign:shortint):shortint;
- begin
- { varalign : minimum alignment required for the variable
- minalign : Minimum alignment of this structure, 0 = undefined
- maxalign : Maximum alignment of this structure, 0 = undefined }
- if (minalign>0) and
- (varalign<minalign) then
- used_align:=minalign
- else
- begin
- if (maxalign>0) and
- (varalign>maxalign) then
- used_align:=maxalign
- else
- used_align:=varalign;
- end;
- end;
- procedure Replace(var s:string;s1:string;const s2:string);
- var
- last,
- i : longint;
- begin
- s1:=upper(s1);
- last:=0;
- repeat
- i:=pos(s1,upper(s));
- if i=last then
- i:=0;
- if (i>0) then
- begin
- Delete(s,i,length(s1));
- Insert(s2,s,i);
- last:=i;
- end;
- until (i=0);
- end;
- procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
- var
- last,
- i : longint;
- begin
- s1:=upper(s1);
- last:=0;
- repeat
- i:=pos(s1,upper(s));
- if i=last then
- i:=0;
- if (i>0) then
- begin
- Delete(s,i,length(s1));
- Insert(s2,s,i);
- last:=i;
- end;
- until (i=0);
- end;
- procedure ReplaceCase(var s:string;const s1,s2:string);
- var
- last,
- i : longint;
- begin
- last:=0;
- repeat
- i:=pos(s1,s);
- if i=last then
- i:=0;
- if (i>0) then
- begin
- Delete(s,i,length(s1));
- Insert(s2,s,i);
- last:=i;
- end;
- until (i=0);
- end;
- Function MatchPattern(const pattern,what:string):boolean;
- var
- found : boolean;
- i1,i2 : longint;
- begin
- i1:=0;
- i2:=0;
- if pattern='' then
- begin
- result:=(what='');
- exit;
- end;
- found:=true;
- repeat
- inc(i1);
- if (i1>length(pattern)) then
- break;
- inc(i2);
- if (i2>length(what)) then
- break;
- case pattern[i1] of
- '?' :
- found:=true;
- '*' :
- begin
- found:=true;
- if (i1=length(pattern)) then
- i2:=length(what)
- else
- if (i1<length(pattern)) and (pattern[i1+1]<>what[i2]) then
- begin
- if i2<length(what) then
- dec(i1)
- end
- else
- if i2>1 then
- dec(i2);
- end;
- else
- found:=(pattern[i1]=what[i2]) or (what[i2]='?');
- end;
- until not found;
- if found then
- begin
- found:=(i2>=length(what)) and
- (
- (i1>length(pattern)) or
- ((i1=length(pattern)) and
- (pattern[i1]='*'))
- );
- end;
- result:=found;
- end;
- function upper(const c : char) : char;
- {
- return uppercase of c
- }
- begin
- upper:=uppertbl[c];
- end;
- function upper(const s : string) : string;
- {
- return uppercased string of s
- }
- var
- i : longint;
- begin
- for i:=1 to length(s) do
- upper[i]:=uppertbl[s[i]];
- upper[0]:=s[0];
- end;
- function upper(const s : ansistring) : ansistring;
- {
- return uppercased string of s
- }
- var
- i : longint;
- begin
- setlength(upper,length(s));
- for i:=1 to length(s) do
- upper[i]:=uppertbl[s[i]];
- end;
- function lower(const c : char) : char;
- {
- return lowercase of c
- }
- begin
- lower:=lowertbl[c];
- end;
- function lower(const s : string) : string;
- {
- return lowercased string of s
- }
- var
- i : longint;
- begin
- for i:=1 to length(s) do
- lower[i]:=lowertbl[s[i]];
- lower[0]:=s[0];
- end;
- function lower(const s : ansistring) : ansistring;
- {
- return lowercased string of s
- }
- var
- i : longint;
- begin
- setlength(lower,length(s));
- for i:=1 to length(s) do
- lower[i]:=lowertbl[s[i]];
- end;
- procedure uppervar(var s : string);
- {
- uppercase string s
- }
- var
- i : longint;
- begin
- for i:=1 to length(s) do
- s[i]:=uppertbl[s[i]];
- end;
- procedure initupperlower;
- var
- c : char;
- begin
- for c:=#0 to #255 do
- begin
- lowertbl[c]:=c;
- uppertbl[c]:=c;
- case c of
- 'A'..'Z' :
- lowertbl[c]:=char(byte(c)+32);
- 'a'..'z' :
- uppertbl[c]:=char(byte(c)-32);
- end;
- end;
- end;
- function DStr(l:longint):string;
- var
- TmpStr : string[32];
- i : longint;
- begin
- Str(l,TmpStr);
- i:=Length(TmpStr);
- while (i>3) do
- begin
- dec(i,3);
- if TmpStr[i]<>'-' then
- insert('.',TmpStr,i+1);
- end;
- DStr:=TmpStr;
- end;
- function trimbspace(const s:string):string;
- {
- return s with all leading spaces and tabs removed
- }
- var
- i,j : longint;
- begin
- j:=1;
- i:=length(s);
- while (j<i) and (s[j] in [#9,' ']) do
- inc(j);
- trimbspace:=Copy(s,j,i-j+1);
- end;
- function trimspace(const s:string):string;
- {
- return s with all leading and ending spaces and tabs removed
- }
- var
- i,j : longint;
- begin
- i:=length(s);
- while (i>0) and (s[i] in [#9,' ']) do
- dec(i);
- j:=1;
- while (j<i) and (s[j] in [#9,' ']) do
- inc(j);
- trimspace:=Copy(s,j,i-j+1);
- end;
- function space (b : longint): string;
- var
- s: string;
- begin
- space[0] := chr(b);
- s[0] := chr(b);
- FillChar (S[1],b,' ');
- space:=s;
- end;
- function PadSpace(const s:string;len:longint):string;
- {
- return s with spaces add to the end
- }
- begin
- if length(s)<len then
- PadSpace:=s+Space(len-length(s))
- else
- PadSpace:=s;
- end;
- function GetToken(var s:string;endchar:char):string;
- var
- i : longint;
- quote : char;
- begin
- GetToken:='';
- s:=TrimSpace(s);
- if (length(s)>0) and
- (s[1] in ['''','"']) then
- begin
- quote:=s[1];
- i:=1;
- while (i<length(s)) do
- begin
- inc(i);
- if s[i]=quote then
- begin
- { Remove double quote }
- if (i<length(s)) and
- (s[i+1]=quote) then
- begin
- Delete(s,i,1);
- inc(i);
- end
- else
- begin
- GetToken:=Copy(s,2,i-2);
- Delete(s,1,i);
- exit;
- end;
- end;
- end;
- GetToken:=s;
- s:='';
- end
- else
- begin
- i:=pos(EndChar,s);
- if i=0 then
- begin
- GetToken:=s;
- s:='';
- exit;
- end
- else
- begin
- GetToken:=Copy(s,1,i-1);
- Delete(s,1,i);
- exit;
- end;
- end;
- end;
- function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
- begin
- str(e,result);
- end;
- function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
- {
- return string of value i
- }
- begin
- str(i,result);
- end;
- function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
- {
- return string of value i
- }
- begin
- str(i,result);
- end;
- function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
- {
- return string of value i
- }
- begin
- str(i,result);
- end;
- function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
- {
- return string of value i, but always include a + when i>=0
- }
- begin
- str(i,result);
- if i>=0 then
- result:='+'+result;
- end;
- function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
- {
- is string a correct number ?
- }
- var
- w : integer;
- l : longint;
- begin
- val(s,l,w);
- // remove warning
- l:=l;
- is_number:=(w=0);
- end;
- function ispowerof2(value : int64;out power : longint) : boolean;
- {
- return if value is a power of 2. And if correct return the power
- }
- var
- hl : int64;
- i : longint;
- begin
- if value and (value - 1) <> 0 then
- begin
- ispowerof2 := false;
- exit
- end;
- hl:=1;
- ispowerof2:=true;
- for i:=0 to 63 do
- begin
- if hl=value then
- begin
- power:=i;
- exit;
- end;
- hl:=hl shl 1;
- end;
- ispowerof2:=false;
- end;
- function nextpowerof2(value : int64; out power: longint) : int64;
- {
- returns the power of 2 >= value
- }
- var
- i : longint;
- begin
- result := 0;
- power := -1;
- if ((value <= 0) or
- (value >= $4000000000000000)) then
- exit;
- result := 1;
- for i:=0 to 63 do
- begin
- if result>=value then
- begin
- power := i;
- exit;
- end;
- result:=result shl 1;
- end;
- end;
- function backspace_quote(const s:string;const qchars:Tcharset):string;
- var i:byte;
- begin
- backspace_quote:='';
- for i:=1 to length(s) do
- begin
- if (s[i]=#10) and (#10 in qchars) then
- backspace_quote:=backspace_quote+'\n'
- else if (s[i]=#13) and (#13 in qchars) then
- backspace_quote:=backspace_quote+'\r'
- else
- begin
- if s[i] in qchars then
- backspace_quote:=backspace_quote+'\';
- backspace_quote:=backspace_quote+s[i];
- end;
- end;
- end;
- function octal_quote(const s:string;const qchars:Tcharset):string;
- var i:byte;
- begin
- octal_quote:='';
- for i:=1 to length(s) do
- begin
- if s[i] in qchars then
- begin
- if ord(s[i])<64 then
- octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
- else
- octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
- end
- else
- octal_quote:=octal_quote+s[i];
- end;
- end;
- function maybequoted(const s:ansistring):ansistring;
- const
- {$IFDEF MSWINDOWS}
- FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
- '{', '}', '''', '`', '~'];
- {$ELSE}
- FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
- '{', '}', '''', ':', '\', '`', '~'];
- {$ENDIF}
- var
- s1 : ansistring;
- i : integer;
- quoted : boolean;
- begin
- quoted:=false;
- s1:='"';
- for i:=1 to length(s) do
- begin
- case s[i] of
- '"' :
- begin
- quoted:=true;
- s1:=s1+'\"';
- end;
- ' ',
- #128..#255 :
- begin
- quoted:=true;
- s1:=s1+s[i];
- end;
- else begin
- if s[i] in FORBIDDEN_CHARS then
- quoted:=True;
- s1:=s1+s[i];
- end;
- end;
- end;
- if quoted then
- maybequoted:=s1+'"'
- else
- maybequoted:=s;
- end;
- function maybequoted(const s:string):string;
- const
- {$IFDEF MSWINDOWS}
- FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
- '{', '}', '''', '`', '~'];
- {$ELSE}
- FORBIDDEN_CHARS = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
- '{', '}', '''', ':', '\', '`', '~'];
- {$ENDIF}
- var
- s1 : string;
- i : integer;
- quoted : boolean;
- begin
- quoted:=false;
- s1:='"';
- for i:=1 to length(s) do
- begin
- case s[i] of
- '"' :
- begin
- quoted:=true;
- s1:=s1+'\"';
- end;
- ' ',
- #128..#255 :
- begin
- quoted:=true;
- s1:=s1+s[i];
- end;
- else begin
- if s[i] in FORBIDDEN_CHARS then
- quoted:=True;
- s1:=s1+s[i];
- end;
- end;
- end;
- if quoted then
- maybequoted:=s1+'"'
- else
- maybequoted:=s;
- end;
- function DePascalQuote(var s: ansistring): Boolean;
- var
- destPos, sourcePos, len: Integer;
- t: string;
- ch: Char;
- begin
- DePascalQuote:= false;
- len:= length(s);
- if (len >= 1) and (s[1] = '''') then
- begin
- {Remove quotes, exchange '' against ' }
- destPos := 0;
- sourcepos:=1;
- while (sourcepos<len) do
- begin
- inc(sourcePos);
- ch := s[sourcePos];
- if ch = '''' then
- begin
- inc(sourcePos);
- if (sourcePos <= len) and (s[sourcePos] = '''') then
- {Add the quote as part of string}
- else
- begin
- SetLength(t, destPos);
- s:= t;
- Exit(true);
- end;
- end;
- inc(destPos);
- t[destPos] := ch;
- end;
- end;
- end;
- function pchar2pshortstring(p : pchar) : pshortstring;
- var
- w,i : longint;
- begin
- w:=strlen(p);
- for i:=w-1 downto 0 do
- p[i+1]:=p[i];
- p[0]:=chr(w);
- pchar2pshortstring:=pshortstring(p);
- end;
- function pshortstring2pchar(p : pshortstring) : pchar;
- var
- w,i : longint;
- begin
- w:=length(p^);
- for i:=1 to w do
- p^[i-1]:=p^[i];
- p^[w]:=#0;
- pshortstring2pchar:=pchar(p);
- end;
- function lowercase(c : char) : char;
- begin
- case c of
- #65..#90 : c := chr(ord (c) + 32);
- #154 : c:=#129; { german }
- #142 : c:=#132; { german }
- #153 : c:=#148; { german }
- #144 : c:=#130; { french }
- #128 : c:=#135; { french }
- #143 : c:=#134; { swedish/norge (?) }
- #165 : c:=#164; { spanish }
- #228 : c:=#229; { greek }
- #226 : c:=#231; { greek }
- #232 : c:=#227; { greek }
- end;
- lowercase := c;
- end;
- function strpnew(const s : string) : pchar;
- var
- p : pchar;
- begin
- getmem(p,length(s)+1);
- move(s[1],p^,length(s));
- p[length(s)]:=#0;
- result:=p;
- end;
- procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
- begin
- if assigned(p) then
- begin
- freemem(p);
- p:=nil;
- end;
- end;
- function stringdup(const s : string) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
- begin
- getmem(result,length(s)+1);
- result^:=s;
- end;
- function CompareStr(const S1, S2: string): Integer;
- var
- count, count1, count2: integer;
- begin
- result := 0;
- Count1 := Length(S1);
- Count2 := Length(S2);
- if Count1>Count2 then
- Count:=Count2
- else
- Count:=Count1;
- result := CompareChar(S1[1],S2[1], Count);
- if result=0 then
- result:=Count1-Count2;
- end;
- function CompareText(S1, S2: string): integer;
- begin
- UpperVar(S1);
- UpperVar(S2);
- Result:=CompareStr(S1,S2);
- end;
- {*****************************************************************************
- Ansistring (PChar+Length)
- *****************************************************************************}
- procedure ansistringdispose(var p : pchar;length : longint);
- begin
- if assigned(p) then
- begin
- freemem(p);
- p:=nil;
- end;
- end;
- { enable ansistring comparison }
- { 0 means equal }
- { 1 means p1 > p2 }
- { -1 means p1 < p2 }
- function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
- var
- i,j : longint;
- begin
- compareansistrings:=0;
- j:=min(length1,length2);
- i:=0;
- while (i<j) do
- begin
- if p1[i]>p2[i] then
- begin
- compareansistrings:=1;
- exit;
- end
- else
- if p1[i]<p2[i] then
- begin
- compareansistrings:=-1;
- exit;
- end;
- inc(i);
- end;
- if length1>length2 then
- compareansistrings:=1
- else
- if length1<length2 then
- compareansistrings:=-1;
- end;
- function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
- var
- p : pchar;
- begin
- getmem(p,length1+length2+1);
- move(p1[0],p[0],length1);
- move(p2[0],p[length1],length2+1);
- concatansistrings:=p;
- end;
- {*****************************************************************************
- Ultra basic KISS Lzw (de)compressor
- *****************************************************************************}
- {This is an extremely basic implementation of the Lzw algorithm. It
- compresses 7-bit ASCII strings into 8-bit compressed strings.
- The Lzw dictionary is preinitialized with 0..127, therefore this
- part of the dictionary does not need to be stored in the arrays.
- The Lzw code size is allways 8 bit, so we do not need complex code
- that can write partial bytes.}
- function minilzw_encode(const s:string):string;
- var t,u,i:byte;
- c:char;
- data:array[128..255] of char;
- previous:array[128..255] of byte;
- lzwptr:byte;
- next_avail:set of 0..255;
- label l1;
- begin
- minilzw_encode:='';
- fillchar(data,sizeof(data),#0);
- fillchar(previous,sizeof(previous),#0);
- if s<>'' then
- begin
- lzwptr:=127;
- t:=byte(s[1]);
- i:=2;
- u:=128;
- next_avail:=[];
- while i<=length(s) do
- begin
- c:=s[i];
- if not(t in next_avail) or (u>lzwptr) then goto l1;
- while (previous[u]<>t) or (data[u]<>c) do
- begin
- inc(u);
- if u>lzwptr then goto l1;
- end;
- t:=u;
- inc(i);
- continue;
- l1:
- {It's a pity that we still need those awfull tricks
- with this modern compiler. Without this performance
- of the entire procedure drops about 3 times.}
- inc(minilzw_encode[0]);
- minilzw_encode[length(minilzw_encode)]:=char(t);
- if lzwptr=255 then
- begin
- lzwptr:=127;
- next_avail:=[];
- end
- else
- begin
- inc(lzwptr);
- data[lzwptr]:=c;
- previous[lzwptr]:=t;
- include(next_avail,t);
- end;
- t:=byte(c);
- u:=128;
- inc(i);
- end;
- inc(minilzw_encode[0]);
- minilzw_encode[length(minilzw_encode)]:=char(t);
- end;
- end;
- function minilzw_decode(const s:string):string;
- var oldc,newc,c:char;
- i,j:byte;
- data:array[128..255] of char;
- previous:array[128..255] of byte;
- lzwptr:byte;
- t:string;
- begin
- minilzw_decode:='';
- fillchar(data,sizeof(data),#0);
- fillchar(previous,sizeof(previous),#0);
- if s<>'' then
- begin
- lzwptr:=127;
- oldc:=s[1];
- c:=oldc;
- i:=2;
- minilzw_decode:=oldc;
- while i<=length(s) do
- begin
- newc:=s[i];
- if byte(newc)>lzwptr then
- begin
- t:=c;
- c:=oldc;
- end
- else
- begin
- c:=newc;
- t:='';
- end;
- while c>=#128 do
- begin
- inc(t[0]);
- t[length(t)]:=data[byte(c)];
- byte(c):=previous[byte(c)];
- end;
- inc(minilzw_decode[0]);
- minilzw_decode[length(minilzw_decode)]:=c;
- for j:=length(t) downto 1 do
- begin
- inc(minilzw_decode[0]);
- minilzw_decode[length(minilzw_decode)]:=t[j];
- end;
- if lzwptr=255 then
- lzwptr:=127
- else
- begin
- inc(lzwptr);
- previous[lzwptr]:=byte(oldc);
- data[lzwptr]:=c;
- end;
- oldc:=newc;
- inc(i);
- end;
- end;
- end;
- procedure defaulterror(i:longint);
- begin
- writeln('Internal error ',i);
- runerror(255);
- end;
- Function Nextafter(x,y:double):double;
- // Returns the double precision number closest to x in
- // the direction toward y.
- // Initial direct translation by Soeren Haastrup from
- // www.netlib.org/fdlibm/s_nextafter.c according to
- // ====================================================
- // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- // Developed at SunSoft, a Sun Microsystems, Inc. business.
- // Permission to use, copy, modify, and distribute this
- // software is freely granted, provided that this notice
- // is preserved.
- // ====================================================
- // and with all signaling policies preserved as is.
- type
- {$if defined(ENDIAN_LITTLE) and not defined(FPC_DOUBLE_HILO_SWAPPED)}
- twoword=record
- lo,hi:longword; // Little Endian split of a double.
- end;
- {$else}
- twoword=record
- hi,lo:longword; // Big Endian split of a double.
- end;
- {$endif}
- var
- hx,hy,ix,iy:longint;
- lx,ly:longword;
- Begin
- hx:=twoword(x).hi; // high and low words of x and y
- lx:=twoword(x).lo;
- hy:=twoword(y).hi;
- ly:=twoword(y).lo;
- ix:=hx and $7fffffff; // absolute values
- iy:=hy and $7fffffff;
- // Case x=NAN or y=NAN
- if ( (ix>=$7ff00000) and ((longword(ix-$7ff00000) or lx) <> 0) )
- or ( (iy>=$7ff00000) and ((longword(iy-$7ff00000) OR ly) <> 0) )
- then exit(x+y);
- // Case x=y
- if x=y then exit(x); // (implies Nextafter(0,-0) is 0 and not -0...)
- // Case x=0
- if (longword(ix) or lx)=0
- then begin
- twoword(x).hi:=hy and $80000000; // return +-minimalSubnormal
- twoword(x).lo:=1;
- y:=x*x; // set underflow flag (ignored in FPC as default)
- if y=x
- then exit(y)
- else exit(x);
- end;
- // all other cases
- if hx>=0 // x>0
- then begin
- if (hx>hy) or ( (hx=hy) and (lx>ly) ) // x>y , return x-ulp
- then begin
- if (lx=0) then hx:=hx-1;
- lx:=lx-1;
- end
- else begin // x<y, return x+ulp
- lx:=lx+1;
- if lx=0 then hx:=hx+1;
- end
- end
- else begin // x<0
- if (hy>=0) or (hx>=hy) or ( (hx=hy) and (lx>ly)) // x<y, return x-ulp
- then begin
- if (lx=0) then hx:=hx-1;
- lx:=lx-1;
- end
- else begin // x>y , return x+ulp
- lx:=lx+1;
- if lx=0 then hx:=hx+1;
- end
- end;
- // finally check if overflow or underflow just happend
- hy:=hx and $7ff00000;
- if (hy>= $7ff00000) then exit(x+x); // overflow and signal
- if (hy<$0010000) // underflow
- then begin
- y:=x*x; // raise underflow flag
- if y<>x
- then begin
- twoword(y).hi:=hx;
- twoword(y).lo:=lx;
- exit(y);
- end
- end;
- twoword(x).hi:=hx;
- twoword(x).lo:=lx;
- nextafter:=x;
- end;
- {$ifdef ver2_0}
- function SwapEndian(const AValue: SmallInt): SmallInt;
- begin
- { the extra Word type cast is necessary because the "AValue shr 8" }
- { is turned into "longint(AValue) shr 8", so if AValue < 0 then }
- { the sign bits from the upper 16 bits are shifted in rather than }
- { zeroes. }
- Result := SmallInt((Word(AValue) shr 8) or (Word(AValue) shl 8));
- end;
- function SwapEndian(const AValue: Word): Word;
- begin
- Result := (AValue shr 8) or (AValue shl 8);
- end;
- function SwapEndian(const AValue: LongInt): LongInt;
- begin
- Result := (AValue shl 24)
- or ((AValue and $0000FF00) shl 8)
- or ((AValue and $00FF0000) shr 8)
- or (AValue shr 24);
- end;
- function SwapEndian(const AValue: DWord): DWord;
- begin
- Result := (AValue shl 24)
- or ((AValue and $0000FF00) shl 8)
- or ((AValue and $00FF0000) shr 8)
- or (AValue shr 24);
- end;
- function SwapEndian(const AValue: Int64): Int64;
- begin
- Result := (AValue shl 56)
- or ((AValue and $000000000000FF00) shl 40)
- or ((AValue and $0000000000FF0000) shl 24)
- or ((AValue and $00000000FF000000) shl 8)
- or ((AValue and $000000FF00000000) shr 8)
- or ((AValue and $0000FF0000000000) shr 24)
- or ((AValue and $00FF000000000000) shr 40)
- or (AValue shr 56);
- end;
- function SwapEndian(const AValue: QWord): QWord;
- begin
- Result := (AValue shl 56)
- or ((AValue and $000000000000FF00) shl 40)
- or ((AValue and $0000000000FF0000) shl 24)
- or ((AValue and $00000000FF000000) shl 8)
- or ((AValue and $000000FF00000000) shr 8)
- or ((AValue and $0000FF0000000000) shr 24)
- or ((AValue and $00FF000000000000) shr 40)
- or (AValue shr 56);
- end;
- {$endif ver2_0}
- initialization
- internalerrorproc:=@defaulterror;
- initupperlower;
- end.
|