12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367 |
- {
- 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
- uses
- constexp;
- 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}
- function min(a,b : qword) : qword;{$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}
- function max(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
- { These functions are intenionally put here and not in the constexp unit.
- Since Tconstexprint may be automatically converted to int, which causes
- loss of data and since there are already min and max functions for ints in
- this unit, we put min and max for Tconstexprint as well. This way we avoid
- potential bugs, caused by code unintentionally calling the int versions of
- min/max on Tconstexprint, because of only including cutils and forgetting
- the constexp unit in the uses clause. }
- function min(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
- function max(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
- {# Return value @var(i) aligned on @var(a) boundary }
- function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
- function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
- function align(i,a:qword):qword;{$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;
- {# Return @var(w) with the bit order reversed }
- function reverse_word(w: word): word;
- {# Return @var(l) with the bit order reversed }
- function reverse_longword(l: longword): longword;
- function next_prime(l: longint): longint;
- function used_align(varalign,minalign,maxalign:longint):longint;
- function isbetteralignedthan(new, org, limit: cardinal): boolean;
- 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);
- procedure ReplaceCase(var s:ansistring;const s1,s2:ansistring);
- 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 rpos(const needle: char; const haystack: shortstring): longint; overload;
- function rpos(const needle: shortstring; const haystack: shortstring): longint; overload;
- function trimspace(const s:string):string;
- function trimspace(const s:AnsiString):AnsiString;
- function space (b : longint): string;
- { returns the position of the first char of the set cs in s, if there is none, then it returns 0 }
- function PosCharset(const cs : TCharSet;const s : ansistring) : integer;
- function PadSpace(const s:string;len:longint):string;
- function PadSpace(const s:AnsiString;len:longint):AnsiString;
- function GetToken(var s:string;endchar:char):string;
- function GetToken(var s:ansistring;endchar:char):ansistring;
- 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 ispowerof2(const value : Tconstexprint;out power : longint) : boolean;
- {# Returns true if abs(value) is a power of 2, the actual
- exponent value is returned in power.
- }
- function isabspowerof2(const value : Tconstexprint; out power : longint) : boolean;
- { # Returns the power of 2 >= value }
- function nextpowerof2(value : qword; out power: longint) : qword;
- function backspace_quote(const s:string;const qchars:Tcharset):string;
- function octal_quote(const s:string;const qchars:Tcharset):string;
- {# 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 : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
- function stringdup(const s : ansistring) : 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;
- function strpnew(const s : ansistring) : pchar;
- {# makes the character @var(c) lowercase, with spanish, french and german
- character set
- }
- function lowercase(c : char) : char;
- { allocate a new pchar with the contents of a}
- function ansistring2pchar(const a: ansistring) : 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;
- function LengthUleb128(a: qword) : byte;
- function LengthSleb128(a: int64) : byte;
- function EncodeUleb128(a: qword;out buf;len: byte) : byte;
- function EncodeSleb128(a: int64;out buf;len: byte) : byte;
- { hide Sysutils.ExecuteProcess in units using this one after SysUtils}
- const
- ExecuteProcess = 'Do not use' deprecated 'Use cfileutil.RequotedExecuteProcess instead, ExecuteProcess cannot deal with single quotes as used by Unix command lines';
- 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 min(const a,b : Tconstexprint) : Tconstexprint;{$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 : qword) : qword;
- {
- 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 max(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
- {
- return the maximum of a and b
- }
- begin
- if a>=b then
- max:=a
- else
- max:=b;
- end;
- function max(const a,b : Tconstexprint) : Tconstexprint;{$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;
- begin
- { oldalignment must be power of two.
- Negating two's complement number keeps its tail '100...000' and complements all bits above.
- "x and -x" extracts this tail of 'x'.
- Said tail of "oldalignment or offset" is the desired answer. }
- result:=oldalignment or longint(offset); { high part of offset won't matter as long as alignment is 32-bit }
- result:=result and -result;
- 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 reverse_word(w: word): word;
- type
- TWordRec = packed record
- hi, lo: Byte;
- end;
- begin
- TWordRec(reverse_word).hi := reverse_byte(TWordRec(w).lo);
- TWordRec(reverse_word).lo := reverse_byte(TWordRec(w).hi);
- end;
- function reverse_longword(l: longword): longword;
- type
- TLongWordRec = packed record
- b: array[0..3] of Byte;
- end;
- begin
- TLongWordRec(reverse_longword).b[0] := reverse_byte(TLongWordRec(l).b[3]);
- TLongWordRec(reverse_longword).b[1] := reverse_byte(TLongWordRec(l).b[2]);
- TLongWordRec(reverse_longword).b[2] := reverse_byte(TLongWordRec(l).b[1]);
- TLongWordRec(reverse_longword).b[3] := reverse_byte(TLongWordRec(l).b[0]);
- end;
- function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
- {
- return value <i> aligned <a> boundary. <a> must be power of two.
- }
- begin
- { One-line formula for i >= 0 is
- >>> (i + a - 1) and not (a - 1),
- and for i < 0 is
- >>> i and not (a - 1). }
- if a>0 then
- a:=a-1; { 'a' is decremented beforehand, this also allows a=0 as a synonym for a=1. }
- if i>=0 then
- i:=i+a;
- result:=i and not a;
- end;
- function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
- {
- return value <i> aligned <a> boundary. <a> must be power of two.
- }
- begin
- { Copy of 'longint' version. }
- if a>0 then
- a:=a-1;
- if i>=0 then
- i:=i+a;
- result:=i and not a;
- end;
- function align(i,a:qword):qword;{$ifdef USEINLINE}inline;{$endif}
- {
- return value <i> aligned <a> boundary. <a> must be power of two.
- }
- begin
- { No i < 0 case here. }
- if a>0 then
- a:=a-1;
- result:=(i+a) and not a;
- 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 next_prime(l: longint): longint;
- var
- check, checkbound: longint;
- ok: boolean;
- begin
- result:=l or 1;
- while l<high(longint) do
- begin
- ok:=true;
- checkbound:=trunc(sqrt(l));
- check:=3;
- while check<checkbound do
- begin
- if (l mod check) = 0 then
- begin
- ok:=false;
- break;
- end;
- inc(check,2);
- end;
- if ok then
- exit;
- inc(l);
- end;
- end;
- function used_align(varalign,minalign,maxalign:longint):longint;
- 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;
- procedure ReplaceCase(var s: ansistring; const s1, s2: ansistring);
- 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,n : sizeint;
- begin
- Result:=s;
- n:=length(s);
- i:=0;
- while i<n do
- if PChar(Pointer(s))[i] in ['a'..'z'] then
- begin
- UniqueString(Result);
- repeat
- PChar(Pointer(Result))[i]:=uppertbl[PChar(Pointer(s))[i]];
- inc(i);
- until i=n;
- exit;
- end
- else
- inc(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,n : sizeint;
- begin
- Result:=s;
- n:=length(s);
- i:=0;
- while i<n do
- if PChar(Pointer(s))[i] in ['A'..'Z'] then
- begin
- UniqueString(Result);
- repeat
- PChar(Pointer(Result))[i]:=lowertbl[PChar(Pointer(s))[i]];
- inc(i);
- until i=n;
- exit;
- end
- else
- inc(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 rpos(const needle: char; const haystack: shortstring): longint;
- begin
- result:=length(haystack);
- while (result>0) do
- begin
- if haystack[result]=needle then
- exit;
- dec(result);
- end;
- end;
- function rpos(const needle: shortstring; const haystack: shortstring): longint;
- begin
- result:=0;
- if (length(needle)=0) or
- (length(needle)>length(haystack)) then
- exit;
- result:=length(haystack)-length(needle)+1;
- repeat
- if (haystack[result]=needle[1]) and
- (CompareByte(haystack[result],needle[1],length(needle))=0) then
- exit;
- dec(result);
- until result=0;
- 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 trimspace(const s:AnsiString):AnsiString;
- {
- 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 PadSpace(const s:AnsiString;len:longint):AnsiString;
- {
- 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 GetToken(var s:ansistring;endchar:char):ansistring;
- 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
- }
- begin
- if (value <= 0) or (value and (value - 1) <> 0) then
- exit(false);
- power:=BsfQWord(value);
- result:=true;
- end;
- function ispowerof2(const value: Tconstexprint; out power: longint): boolean;
- begin
- if value.signed or
- (value.uvalue<=high(int64)) then
- result:=ispowerof2(value.svalue,power)
- else if not value.signed and
- (value.svalue=low(int64)) then
- begin
- result:=true;
- power:=63;
- end
- else
- result:=false;
- end;
- function isabspowerof2(const value : Tconstexprint;out power : longint) : boolean;
- begin
- if ispowerof2(value,power) then
- result:=true
- else if value.signed and (value.svalue<0) and (value.svalue<>low(int64)) and ispowerof2(-value.svalue,power) then
- result:=true
- else
- result:=false;
- end;
- function nextpowerof2(value : qword; out power: longint) : qword;
- begin
- power:=-1;
- result:=0;
- if (value=0) or (value>qword($8000000000000000)) then
- exit;
- power:=BsrQWord(value);
- result:=qword(1) shl power;
- if (value and (value-1))<>0 then
- begin
- inc(power);
- 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 DePascalQuote(var s: ansistring): Boolean;
- var
- destPos, sourcePos, len: Integer;
- t: string;
- ch: Char;
- begin
- t:='';
- 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 ansistring2pchar(const a: ansistring) : pchar;
- var
- len: ptrint;
- begin
- len:=length(a);
- getmem(result,len+1);
- if (len<>0) then
- move(a[1],result[0],len);
- result[len]:=#0;
- 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;
- function strpnew(const s: ansistring): pchar;
- var
- p : pchar;
- begin
- getmem(p,length(s)+1);
- move(s[1],p^,length(s)+1);
- 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 : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
- begin
- getmem(result,length(s)+1);
- result^:=s;
- end;
- function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
- begin
- getmem(result,length(s)+1);
- result^:=s;
- end;
- function PosCharset(const cs : TCharSet;const s : ansistring) : integer;
- var
- i : integer;
- begin
- result:=0;
- for i:=1 to length(s) do
- if s[i] in cs then
- begin
- result:=i;
- exit;
- end;
- end;
- function CompareStr(const S1, S2: string): Integer;
- var
- count, count1, count2: integer;
- begin
- Count1 := Length(S1);
- Count2 := Length(S2);
- if Count1>Count2 then
- Count:=Count2
- else
- Count:=Count1;
- result := CompareByte(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
- cmp : SizeInt;
- begin
- cmp:=CompareByte(p1^,p2^,min(length1,length2));
- if cmp=0 then
- cmp:=length1-length2;
- result:=ord(cmp>0)-ord(cmp<0);
- 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;
- procedure defaulterror(i:longint);
- begin
- writeln('Internal error ',i);
- runerror(255);
- end;
- function LengthUleb128(a: qword) : byte;
- begin
- result:=0;
- repeat
- inc(result);
- a := a shr 7;
- until a=0;
- end;
- function LengthSleb128(a: int64) : byte;
- begin
- { 'a xor SarInt64(a,63)' has upper bits 0...01 where '0's symbolize sign bits of 'a' and 1 symbolizes its most significant non-sign bit.
- 'shl 1' ensures storing the sign bit. }
- result:=LengthUleb128(qword(a xor SarInt64(a,63)) shl 1);
- end;
- function EncodeUleb128(a: qword;out buf;len : byte) : byte;
- var
- b: byte;
- pbuf : pbyte;
- begin
- result:=0;
- pbuf:=@buf;
- repeat
- b := a and $7f;
- a := a shr 7;
- if a<>0 then
- b := b or $80;
- pbuf^:=b;
- inc(pbuf);
- inc(result);
- until (a=0) and (result>=len);
- end;
- function EncodeSleb128(a: int64;out buf;len : byte) : byte;
- var
- b: byte;
- more: boolean;
- pbuf : pbyte;
- begin
- result:=0;
- pbuf:=@buf;
- repeat
- b := a and $7f;
- a := SarInt64(a, 7);
- inc(result);
- more:=(result<len) or (a<>-(b shr 6));
- pbuf^:=b or byte(more) shl 7;
- inc(pbuf);
- until not more;
- end;
- initialization
- internalerrorproc:=@defaulterror;
- initupperlower;
- end.
|